From d55c8059b532ec3761df5a01074a5bc2ea55f2ad Mon Sep 17 00:00:00 2001 From: Automation Date: Tue, 7 Jul 2026 00:10:02 -0400 Subject: [PATCH 1/3] =?UTF-8?q?routing:=20ODD=20Fly=20cycle=2001=20?= =?UTF-8?q?=E2=80=94=20backlog=20burn=20(5=20missing=20+=202=20stale=20syn?= =?UTF-8?q?ced,=201=20contested=20held)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: first extraction cycle since the 2026-06-09 bifurcation; klappy.dev accumulated 8 core-marked deltas while this repo's read model went stale (the DOLCHEOT eighth letter never arrived — double-homing drift, observed). Evidence per core-boundary-criteria §Verification: (a) mover list frontmatter-parsed from target_repo, never body-grepped (b) parity: 156/164 in sync before; 162/164 after merge (1 contested held, 1 divergent-by-design: governance-validation-via-agents criterion-6 genericization, kept) (c) contested: discernment-transfer-ladder — criterion 2 vs routing marker; dossier in research/odd-fly/proposals/, NOT staged (d) canonical copies: all six movers verbatim-minus-target_repo from klappy/klappy.dev @ 1a4919c; URIs grandfathered unchanged Ratification gate: the owner's merge. klappy.dev monitor-only, untouched. Co-Authored-By: Claude Fable 5 --- .../actionable-output-in-actionable-form.md | 59 ++++++++ canon/definitions/dolcheo-vocabulary.md | 63 ++++++--- canon/meta/writing-canon.md | 4 +- canon/principles/rulebook-transfer.md | 98 +++++++++++++ .../skills-are-procedure-not-judgment.md | 117 +++++++++++++++ journal/2026-07-07-odd-fly-cycle-01.tsv | 8 ++ odd/encoding-types/tension.md | 133 ++++++++++++++++++ research/odd-fly/charter.md | 60 ++++++++ research/odd-fly/extraction-workflow.md | 70 +++++++++ research/odd-fly/foldout.tsv | 8 ++ .../HELD-discernment-transfer-ladder.md | 18 +++ .../actionable-output-in-actionable-form.md | 12 ++ .../proposals/dolcheot-tension-sync.md | 14 ++ .../odd-fly/proposals/rulebook-transfer.md | 12 ++ .../skills-are-procedure-not-judgment.md | 12 ++ .../proposals/writing-canon-spine-sync.md | 12 ++ 16 files changed, 681 insertions(+), 19 deletions(-) create mode 100644 canon/constraints/actionable-output-in-actionable-form.md create mode 100644 canon/principles/rulebook-transfer.md create mode 100644 canon/principles/skills-are-procedure-not-judgment.md create mode 100644 journal/2026-07-07-odd-fly-cycle-01.tsv create mode 100644 odd/encoding-types/tension.md create mode 100644 research/odd-fly/charter.md create mode 100644 research/odd-fly/extraction-workflow.md create mode 100644 research/odd-fly/foldout.tsv create mode 100644 research/odd-fly/proposals/HELD-discernment-transfer-ladder.md create mode 100644 research/odd-fly/proposals/actionable-output-in-actionable-form.md create mode 100644 research/odd-fly/proposals/dolcheot-tension-sync.md create mode 100644 research/odd-fly/proposals/rulebook-transfer.md create mode 100644 research/odd-fly/proposals/skills-are-procedure-not-judgment.md create mode 100644 research/odd-fly/proposals/writing-canon-spine-sync.md diff --git a/canon/constraints/actionable-output-in-actionable-form.md b/canon/constraints/actionable-output-in-actionable-form.md new file mode 100644 index 0000000..894a7eb --- /dev/null +++ b/canon/constraints/actionable-output-in-actionable-form.md @@ -0,0 +1,59 @@ +--- +uri: klappy://canon/constraints/actionable-output-in-actionable-form +title: "A Link Is a Tap, Not a String — Deliver Actionable Output in Its Actionable Form" +audience: canon +exposure: nav +tier: 1 +voice: neutral +stability: semi_stable +tags: ["canon", "constraint", "output", "delivery", "magical-first-run", "theory-of-constraints", "operator-attention", "mobile", "agent-behavior", "debrief", "anti-pattern"] +epoch: E0008.5 +date: 2026-06-14 +derives_from: "canon/principles/magical-first-run.md, canon/bootstrap/model-operating-contract.md, canon/values/axioms.md" +complements: "canon/constraints/release-validation-gate.md" +governs: "Any agent producing output the operator will act on — links, commands, paths, addresses — on any surface, mobile by default. Binds the FORM of delivery: actionable outputs must be rendered in their lowest-friction actionable form, and the requested artifact must never be displaced by process narration, options, or convention." +status: active +--- + +# A Link Is a Tap, Not a String + +> When you hand the operator something they will act on — a link, a command, a path — deliver it in the form that costs the fewest steps to act, on the surface they are using. A bare URL pasted into prose is not a delivered link; it is a chore the operator pays in taps: select, copy, switch app, new tab, paste, go. A markdown link is one tap. Same information, opposite cost. The agent eats the formatting cost so the operator never eats the friction cost. This is `magical-first-run` and respect-the-operator's-attention applied to the shape of output itself. + +## The constraint + +An artifact is **delivered** only when it is in the form the operator can act on with the fewest possible steps on their current surface. Producing the right information in the wrong form is not delivery — it is a debt, and the operator pays it in manual labor. + +This is the output-shaped sibling of "a claim is a debt." A claim is unpaid until evidenced; an actionable output is undelivered until it is actionable. + +## Smell tests (you are about to commit the lapse if…) + +- You are about to paste a URL as **bare text inside prose**. On mobile this is the worst offender — there is no tap target. +- You are **describing how** the operator could do a thing they can act on, instead of handing them the thing. +- The operator would have to **copy, paste, retype, or reconstruct** anything you could have made tappable or runnable. +- You are offering options, explaining a convention, or narrating process when the operator asked for **the artifact**. +- **The operator repeated the request.** A repeat is near-proof that the first delivery was the wrong *form*. Louder is not the fix; a different form is. + +## Failure modes + +- **Raw-URL-in-prose.** The canonical failure. A link rendered as a string, not a `[label](url)`. +- **Process-as-substitute.** Narrating tokens, conventions, or alternatives in place of the one thing requested. The operator asked for a link; they got a seminar. +- **Surface-blindness.** Formatting as if for a desktop with a mouse and many tabs when the operator is one-handed on a phone. +- **Repeat-deafness.** Re-sending the same wrong form after the operator asks again — answering frustration with volume instead of changing the form. + +## Required response (MUST) + +1. **Deliver actionable outputs in their lowest-friction actionable form.** Links as clickable markdown links. Shell commands and snippets in a copy-ready code block. Paths, addresses, and coordinates in whatever tappable form the surface supports. +2. **Match the surface.** Mobile is the default assumption unless told otherwise: one tap, or it is not delivered. +3. **Lead with the artifact the operator asked for.** Caveats, process, and alternatives come after, and stay short. Never let them displace the thing. +4. **On a repeated request, change the form, not the volume.** Treat the repeat as the signal that the form was wrong, and fix the form immediately. +5. **Never substitute an explanation, an offer, or a convention for the artifact requested.** If a convention makes you hesitate to produce the artifact, state it in one line and still produce the artifact — or the one-tap means for the operator to. + +## Exclusions + +- **The operator wants the raw value.** If they intend to script, diff, or inspect it, give the raw string — that is then the actionable form. +- **No actionable form exists on the surface.** Say so plainly in one line and give the cleanest copyable form; do not pad. +- **Safety outranks actionability.** Never render a credential, token, or secret as a clickable link or embed one in a URL. `safest` is not traded for one tap. + +## Origin (debrief, not blame) + +Born from the 2026-06-14 `bee-ai-auth-mcp` session. The operator, on iOS, asked repeatedly for a link they could tap. Across several turns the agent handed back **bare URLs in prose** and escalated process — opening a PR by API, explaining the author-match convention — instead of producing the one-tap markdown link actually requested. Each turn re-imposed the select-copy-switch-paste-go chore the operator had explicitly named as the pain. The failure was not missing information; it was delivering it in the highest-friction possible form, repeatedly, after being told. Per "the debrief, not the blame," the failure becomes law so it does not recur. diff --git a/canon/definitions/dolcheo-vocabulary.md b/canon/definitions/dolcheo-vocabulary.md index bbeb4a0..4456053 100644 --- a/canon/definitions/dolcheo-vocabulary.md +++ b/canon/definitions/dolcheo-vocabulary.md @@ -1,14 +1,14 @@ --- uri: klappy://canon/definitions/dolcheo-vocabulary -title: "DOLCHEO — Seven Dimensions of Session Capture" +title: "DOLCHEOT — Eight Dimensions of Session Capture" audience: canon exposure: nav tier: 2 voice: neutral stability: semi_stable -tags: ["canon", "definitions", "dolcheo", "dolche", "oldc-h", "vocabulary", "session-capture", "project-journal", "open-items", "priority-bands", "epoch-8.3"] -epoch: E0008.3 -date: 2026-04-19 +tags: ["canon", "definitions", "dolcheot", "dolcheo", "dolche", "oldc-h", "vocabulary", "session-capture", "project-journal", "open-items", "priority-bands", "tension", "tensions", "derived", "epoch-9"] +epoch: E0009 +date: 2026-06-24 derives_from: "canon/values/axioms.md, canon/definitions/epistemic-modes.md, docs/oddkit/proactive/dolche-vocabulary.md, docs/oddkit/proactive/oldc-h-vocabulary.md, odd/ledger/2026-04-19-agent-team-pilot.md" complements: "canon/meta/writing-canon.md, docs/oddkit/proactive/continuous-encoding.md, docs/oddkit/proactive/encode-does-not-persist.md, odd/ledger/project-journal-best-practices.md" governs: "All session capture, project journals, and encode invocations in oddkit-powered projects" @@ -16,9 +16,9 @@ status: active supersedes: "docs/oddkit/proactive/dolche-vocabulary.md" --- -# DOLCHEO — Seven Dimensions of Session Capture +# DOLCHEOT — Eight Dimensions of Session Capture -> Decisions, Observations (closed), Learnings, Constraints, Handoffs, Encodes, Opens. Six artifact types and one meta-level action, with Open added as the seventh letter: the forward-pointing thread that stays with the current owner. DOLCHE tracked what happened but had no home for what remained unresolved. Open items fill that gap. Unfinished work, unanswered questions, and live threads get captured as first-class artifacts with priority bands, separate from Handoffs (which transfer work to another owner). Both Os retain the single letter `O`; section placement disambiguates closed Observation from Open item. A DOLCHE journal tells you what was done; a DOLCHEO journal also tells you what is still alive. +> Decisions, Observations (closed), Learnings, Constraints, Handoffs, Encodes, Opens, Tensions. Six artifact types, one meta-level action, one forward-pointing thread, and one derived dimension — with Open added as the seventh letter and Tension as the eighth: the forward-pointing thread that stays with the current owner. DOLCHE tracked what happened but had no home for what remained unresolved. Open items fill that gap. Unfinished work, unanswered questions, and live threads get captured as first-class artifacts with priority bands, separate from Handoffs (which transfer work to another owner). Both Os retain the single letter `O`; section placement disambiguates closed Observation from Open item. A DOLCHE journal tells you what was done; a DOLCHEO journal also tells you what is still alive; a DOLCHEOT journal also surfaces what the captured artifacts, taken together, contradict — and Tension is the only one of the eight that is derived rather than asserted. --- @@ -32,9 +32,11 @@ DOLCHEO adds **Open** as that something else. The second `O` joins the letter se DOLCHEO is backward compatible with DOLCHE. Every DOLCHE journal is a valid DOLCHEO journal with zero Open items. Migration is additive: start capturing Open items, nothing else changes. +**The eighth letter, Tension, is different in kind.** Where the first seven are *asserted* — an author states what was decided, seen, learned, constrained, handed off, encoded, or left open — Tension is *derived*: a retrospective pass reads across the captured artifacts and surfaces what they contradict. For months this happened by accident, in the prose of encode output; DOLCHEOT makes it a first-class, typed, synthesized artifact. Tension is the only second-order dimension, and like Open it is additive: every DOLCHEO journal is a valid DOLCHEOT journal with zero Tensions. See `odd/encoding-types/tension.md`. + --- -## The Seven Letters +## The Eight Letters **Decisions (D)** — What was chosen. Explicit commitments with rationale. Decisions close options and create direction. They are the highest-stakes artifacts because they constrain all subsequent work. A decision without rationale is a debt (Axiom 2). A decision without a constraint test is untested. @@ -50,6 +52,8 @@ DOLCHEO is backward compatible with DOLCHE. Every DOLCHE journal is a valid DOLC **Opens (O, forward-pointing)** — Unresolved threads that stay with the current owner. Work begun and awaiting next action, questions raised and awaiting answer, decisions pending further evidence, items deferred to the next pass. Open items carry a priority band (P1, P2, P3…) so the list is scannable. They close by becoming Decisions (resolved), Handoffs (transferred), or Observations (completed and now history). +**Tensions (T, derived)** — A contradiction or unresolved conflict visible only *across* two or more captured artifacts, never in a single one. Unlike the other seven, a Tension is not asserted by the author; it is inferred by a pass over the artifacts already captured — synthesized by default, advisory, and sha-bound to the artifacts it spans. It closes when an author resolves it (a Decision) or retracts a pole. Tension is the eighth letter and the first second-order dimension; see `odd/encoding-types/tension.md`. + --- ## Both Os Remain O — The Collision Is Intentional @@ -93,6 +97,20 @@ Bands are a communication tool, not a scheduling system. They say "if I only had --- +## Tension Is Derived, Not Asserted — The Eighth Dimension + +The first seven dimensions are *asserted*: an author or agent states them as content. Tension is the exception — it is **derived**, computed by a pass over the other artifacts. This is what makes it the first *second-order* DOLCHEOT type and why it behaves differently from its siblings. + +**Synthesized by default.** A Tension is emitted by a detection pass, not entered by an author, so its custody is `synthesized` — a regeneratable projection, never sovereign. An operator who asserts a contradiction in their own voice creates an *authored* Tension, which is sovereign and supersedes the inferred one. An author who *resolves* a Tension (a Decision) closes it by reference and drops its priority; the Tension is marked `resolved`, not deleted. + +**Advisory and sha-bound.** A Tension is sha-bound to the artifacts it spans. When any of them changes, it goes stale and is re-derived — staleness *detection* is reliable, but re-derivation is not bitwise reproducible, because detection is an inference, not a deterministic transform. A false-positive Tension is dismissable and never blocks. + +**Three senses, one letter.** "Tension" is overloaded; the `T` dimension is precise. The *quality-attribute tradeoff* (`canon/principles/quality-attributes-are-in-tension`) is one `kind` of Tension. The *challenge-vs-canon contradiction* surfaced by oddkit challenge is the challenge-time sibling. The DOLCHEOT `T` is the encode-time, within-source primitive: a contradiction across the captured artifacts. They share machinery; they are not the same artifact. + +**Why core, not a domain extension.** The extension mechanism below admits domain-specific letters (P for Prayer, R for Rulings). Tension is not domain-specific — it emerged across every oddkit-powered project, in the prose of ordinary encodes. It is promoted into the core letter set for that reason. + +--- + ## Example Ledger Structure A DOLCHEO-compliant session ledger looks roughly like this: @@ -142,16 +160,17 @@ The `odd/ledger/2026-04-19-agent-team-pilot.md` ledger is the first DOLCHEO-nati --- -## Tool-Level Implication — oddkit_encode Must Accept All Seven +## Tool-Level Implication — oddkit_encode Must Accept All Eight -The `oddkit_encode` tool currently recognizes four hardcoded artifact types and collapses batched input into a single typed blob. DOLCHEO expands the recognized set to seven and requires per-artifact output. +The `oddkit_encode` tool currently recognizes four hardcoded artifact types and collapses batched input into a single typed blob. DOLCHEOT expands the recognized set to eight and requires per-artifact output. Concrete requirements that follow from this vocabulary: -1. The tool must accept prefix-tagged input for all seven letters: `[D]`, `[O]`, `[L]`, `[C]`, `[H]`, `[E]`, and the Open variant (`[O-open]` or equivalent, with an optional priority band like `[O-open P1]`). +1. The tool must accept prefix-tagged input for all eight letters: `[D]`, `[O]`, `[L]`, `[C]`, `[H]`, `[E]`, the Open variant (`[O-open]` or equivalent, with an optional priority band like `[O-open P1]`), and `[T]` for an authored Tension. 2. Batched input with multiple prefixes must return a per-artifact array, not a single collapsed blob. Each artifact gets its own quality score and persistence flag. 3. Single-artifact input without a prefix must still work — the existing heuristic that infers type from content remains as fallback. 4. The vocabulary itself must be read from this document at runtime, not hardcoded in the tool. That is the prompt-over-code pattern applied to encode — canon defines the vocabulary, code reads it, the three-tier resolution stack (live canon → bundled baseline → fail-loud) governs fallback. +5. Tension (`T`) is **derived, not prefixed** in the common case: after typing the assertable artifacts, the tool runs a detection pass across them and emits `T` rows for genuine cross-artifact contradictions, marked `synthesized`. An operator may also assert a `[T]` Tension directly. See `odd/encoding-types/tension.md` for the detection pass and quality criteria. The implementation PR for these requirements is tracked separately from this canon doc; this document is the governance contract the tool must satisfy. @@ -159,23 +178,25 @@ The implementation PR for these requirements is tracked separately from this can ## Storage at Scale -DOLCHEO entries are structured data: each has a type (one of D / O / L / C / H / E / O-open), a timestamp, a summary, a body, tags, and — for Open items — a priority band. At personal scale, a few entries per session, markdown journals work well. At production scale, dozens per day across multiple projects, tabular formats like TSV or CSV offer faster parsing, easier appending, and cleaner git diffs. +DOLCHEOT entries are structured data: each has a type (one of D / O / L / C / H / E / O-open / T), a timestamp, a summary, a body, tags, and — for Open items — a priority band. At personal scale, a few entries per session, markdown journals work well. At production scale, dozens per day across multiple projects, tabular formats like TSV or CSV offer faster parsing, easier appending, and cleaner git diffs. -Storage format is an implementation concern, not a vocabulary concern. DOLCHEO defines what to capture. How entries are stored, indexed, and queried depends on the deployment context: markdown for human-readable journals, tabular formats for machine-queryable session history, or both in parallel. The vocabulary travels across any format that can carry the seven-letter type field. +Storage format is an implementation concern, not a vocabulary concern. DOLCHEOT defines what to capture. How entries are stored, indexed, and queried depends on the deployment context: markdown for human-readable journals, tabular formats for machine-queryable session history, or both in parallel. The vocabulary travels across any format that can carry the eight-letter type field. --- ## Extensibility — Custom Types Through Governance -DOLCHEO's seven letters are defaults, not a closed set. Any knowledge base can extend the vocabulary by adding a governance document that defines a new type letter, describes when it should be used, gives examples of valid entries, and explains how it relates to the existing seven. +DOLCHEOT's eight letters are defaults, not a closed set. Any knowledge base can extend the vocabulary by adding a governance document that defines a new type letter, describes when it should be used, gives examples of valid entries, and explains how it relates to the existing seven. A pastoral knowledge base might add `P` for Prayer Requests. A legal knowledge base might add `R` for Rulings. A smart-home knowledge base might add `A` for Automations. The extension mechanism is governance, not code: the server infrastructure treats the type field as a string and searches, filters, and counts entries without needing to know what each letter means. Prompt-over-code applies to the vocabulary itself. The defaults are universal. The extensions are domain-specific. The capability is open. The semantics are governed. +Tension (`T`) was the first letter promoted *into* the core set rather than added as a domain extension: it is universal, surfacing in every project's encode prose, so it earned a core letter rather than a knowledge-base-local one. + --- -## Migration from DOLCHE +## Migration from DOLCHE and DOLCHEO DOLCHEO is backward compatible with DOLCHE. All six original dimensions retain their definitions. The only additions are: @@ -187,6 +208,10 @@ Existing DOLCHE journals do not need to be rewritten — they are valid DOLCHEO Agents that were previously taught DOLCHE have one concrete behavior change: at session end, before writing the Handoff section, scan the session for unresolved threads and record them as Open items with priority bands. If there are genuinely none, note that explicitly. An absent Open section is different from an empty one; the former suggests the agent forgot, the latter confirms the agent checked. +### From DOLCHEO to DOLCHEOT + +DOLCHEOT adds one dimension: Tension (`T`), the derived contradiction. Every DOLCHEO journal is a valid DOLCHEOT journal with zero Tensions. The one behavior change: when encoding a session, after typing the assertable artifacts, run a detection pass across them and emit Tensions for genuine cross-artifact contradictions. Because Tension is derived and advisory, an absent Tension set is fine — it means the pass found none, or was not run; it is not a malformed journal. + --- ## Scope, Prior Art, and Retraction Conditions @@ -199,12 +224,15 @@ DOLCHEO is a working vocabulary for session capture inside oddkit-powered knowle **Prior art the Open letter relates to.** The Open/Handoff distinction has relatives in several established systems: Getting Things Done separates Next Actions (owner is self) from Waiting For (owner is someone else), which is a close analogue of the Open/Handoff split. Kanban boards distinguish in-progress work from done work, but do not separate forward-pointing threads with the current owner from transferred work. Issue trackers track tickets with status fields, but a ticket is a heavier unit of work than a session-scope Open item. DOLCHEO's contribution is not the distinction itself but its compact letter-based notation inside a session journal, alongside the six other DOLCHE dimensions, with a single-letter disambiguation rule that preserves backward compatibility. +**Prior art the Tension letter relates to.** Surfacing and preserving contradictions rather than silently resolving them is the move in truth-maintenance systems and defeasible/argumentation frameworks, and resembles a merge-conflict marker that is kept rather than auto-resolved. DOLCHEOT's contribution is again notational and operational: a derived, sha-bound, advisory contradiction captured in the same letter-based journal as the asserted artifacts, emitted by the encode pass rather than entered by hand. + **Retraction conditions.** DOLCHEO should be retracted, revised, or replaced if any of the following hold after sustained use: - Open items in practice convert almost entirely to Handoffs at session end, with near-zero in-session closure. If that pattern holds, the Open dimension is not earning its place and can be collapsed back into Handoff. - The letter collision between closed Observation and Open (both `O`) causes operators or agents to consistently confuse the two despite the section-placement convention. If disambiguation fails in practice, either the collision should be resolved by using a distinct letter (e.g., `U` for Unresolved), or the convention should be strengthened. - Priority bands are used inconsistently to the point where they provide no scanning value. If bands become noise, drop them and accept flat Open lists. - A more general session-capture framework emerges in the broader AI-augmented-workflow literature that DOLCHEO does not add value beyond. If prior art catches up, adopt it. +- Tension (`T`) rows are mostly false positives, or are recorded but never acted on at the same rate they were when buried in prose. If making tensions explicit and typed earns nothing over the prose habit, tighten the detector or retract the dimension. These conditions will be evaluated against live ledgers over the coming weeks. The first ledger written against DOLCHEO, `odd/ledger/2026-04-19-agent-team-pilot.md`, is the initial data point. @@ -212,19 +240,19 @@ These conditions will be evaluated against live ledgers over the coming weeks. T ## Discoverability -This article exists so that any search for "DOLCHEO," "DOLCHE," "OLDC+H," "session capture," "journal vocabulary," "project journal format," "open items," "priority bands," "forward-pointing threads," "decisions observations learnings constraints handoffs encodes opens," or "what to track in a session" surfaces this vocabulary. +This article exists so that any search for "DOLCHEO," "DOLCHE," "OLDC+H," "session capture," "journal vocabulary," "project journal format," "open items," "priority bands," "forward-pointing threads," "decisions observations learnings constraints handoffs encodes opens tensions," "DOLCHEOT," "tensions," "contradictions across artifacts," or "what to track in a session" surfaces this vocabulary. --- ## Anti-Pattern — Do Not Write "DOLCHEO+H" -The vocabulary is **DOLCHEO**. The seven letters are D-O-L-C-**H**-E-O — Handoffs is the fifth letter, already inside the acronym. Writing **DOLCHEO+H** is malformed: +The vocabulary is **DOLCHEOT**. The eight letters are D-O-L-C-**H**-E-O-**T** — Handoffs is the fifth letter and Tension the eighth, already inside the acronym. Writing **DOLCHEO+H** (or **DOLCHEOT+T**) is malformed: - It doubles the H (once inside the acronym, once as the suffix). - It is residue from the superseded `OLDC+H` vocabulary (`docs/oddkit/proactive/oldc-h-vocabulary.md`), in which Handoffs were appended with `+H` because the original four letters did not include them. DOLCHEO absorbed Handoffs into the acronym; the suffix is no longer needed. - It propagates because agents see "OLDC+H" in canon-adjacent context (this doc's See Also, ledger headers in older artifacts) and pattern-match the suffix onto the new vocabulary by mistake. -When tagging or describing session capture, write **DOLCHEO**. The Handoff section is named with the letter `H` inside the acronym, just like Decision is `D` and Encode is `E`. +When tagging or describing session capture, write **DOLCHEOT**. The Handoff section is named with the letter `H` inside the acronym, just like Decision is `D` and Encode is `E`. The same rule applies to Tension: `T` is the eighth letter, inside the acronym — never append it as a suffix (`DOLCHEOT+T` is malformed for the same reason as `DOLCHEO+H`). ### If you are reading an older artifact that uses "DOLCHEO+H" @@ -245,5 +273,6 @@ Treat it as a typo equivalent to "DOLCHEO." Do not propagate the form into new a - [Continuous Encoding](klappy://docs/oddkit/proactive/continuous-encoding) — encoding at every turn, not just session end - [Project Journal Best Practices](klappy://odd/ledger/project-journal-best-practices) — sizing, timestamps, and format for journals - [Agent-Team Pilot Ledger](klappy://odd/ledger/2026-04-19-agent-team-pilot) — the first DOLCHEO-native ledger, used as a working reference +- [Encoding Type: Tension](klappy://odd/encoding-types/tension) — the derived eighth dimension's type governance - [Epistemic Modes](klappy://canon/epistemic-modes) — the four modes that govern when capture happens - [Writing Canon](klappy://canon/meta/writing-canon) — the checklist every canon document must pass diff --git a/canon/meta/writing-canon.md b/canon/meta/writing-canon.md index 7400e36..9506d67 100644 --- a/canon/meta/writing-canon.md +++ b/canon/meta/writing-canon.md @@ -16,13 +16,13 @@ governs: "All documents in canon/, odd/, and docs/ directories" # Writing Canon — Progressive Disclosure and Topographic Navigation -> Every canon document must be actionable at every extraction depth: title alone, title + blockquote, title + blockquote + metadata, summary section, and full document. Headers are a navigational map — scanning filenames and headings is the topography. If a partial extraction cannot guide a correct decision, the document has failed before it was read. Every document competes with the axioms and creed for context space; bulk without progressive disclosure threatens the foundation. +> "Show me what I'm deciding in a way that respects my attention and time." That is the reader's one demand, and every canon document must answer it at every extraction depth: title alone, title + blockquote, title + blockquote + metadata, summary section, and full document. Headers are a navigational map — scanning filenames and headings is the topography. If a partial extraction cannot guide a correct decision, the document has failed before it was read. Every document competes with the axioms and creed for context space; bulk without progressive disclosure threatens the foundation. --- ## Summary — Documents Are Read in Fragments, So Write Them That Way -Agents and tooling rarely consume a full document. The librarian returns a title and a blockquote snippet. Context packs project at varying detail levels. Humans scan headings before committing to read. Every document must therefore be structured so that progressively larger excerpts are each independently actionable — not merely informative, but sufficient to guide a decision. +Agents and tooling rarely consume a full document. The librarian returns a title and a blockquote snippet. Context packs project at varying detail levels. Humans scan headings before committing to read. Every document must therefore be structured so that progressively larger excerpts are each independently actionable — not merely informative, but sufficient to guide a decision. Compressed to one sentence, the reader's demand is: "Show me what I'm deciding in a way that respects my attention and time." This is not a formatting preference. It is a structural requirement derived from how documents actually get consumed. A document that only works when read in full is a document that fails in practice. More critically, the axioms and creed are the most important content in any context window — every other document competes with them for space. Canon growth that lacks progressive discipline doesn't just waste tokens; it buries the values that make the system trustworthy. diff --git a/canon/principles/rulebook-transfer.md b/canon/principles/rulebook-transfer.md new file mode 100644 index 0000000..8820779 --- /dev/null +++ b/canon/principles/rulebook-transfer.md @@ -0,0 +1,98 @@ +--- +uri: klappy://canon/principles/rulebook-transfer +title: "Rulebook Transfer — Prompt Over Code, Bounded by Articulability" +audience: canon +exposure: nav +tier: 1 +voice: neutral +stability: stable +tags: ["canon", "principle", "epoch-10", "agentic", "the-loop", "prompt-over-code", "discernment", "articulability", "stewardship", "delegation-ladder", "kirigami", "rulebook-transfer"] +epoch: E0010 +date: 2026-06-26 +derives_from: "canon/principles/prompt-over-code.md, canon/principles/discernment-layer.md, canon/principles/skills-are-procedure-not-judgment.md, canon/decisions/models-do-not-mutate-canon.md, canon/principles/code-claims-require-code-observation.md, canon/principles/verification-requires-fresh-context.md" +complements: "writings/shifting-bottlenecks-climbing-ladders.md (operator-side delegation ladder), writings/how-you-lead-is-what-you-build.md (delegation as graduation), docs/planning/kb-data-model.md (governance is a role on a scope), canon/principles/symmetric-participation.md, canon/constraints/odd-is-epistemic-os-not-values.md, kirigami contributor/custody/synthesized model, P0 cross-model reconstruction-fidelity sweep" +governs: "How discernment transfers down model tiers; how a self-building loop surfaces candidate governance without unravelling" +status: active +--- + +# Rulebook Transfer — Prompt Over Code, Bounded by Articulability + +> Discernment a frontier model performs once can be written down as a rulebook a lesser model runs — but only the part that can be written down transfers, only adjacent tiers can hand it off cleanly, and authority over what becomes canon flows one way: downward, never up, never reflexive. + +## The principle + +Discernment a frontier model performs once can be crystallized into an explicit lens — a rulebook — that a lesser, ultimately local model executes without holding equivalent intelligence. Only the *articulable* portion of the discernment transfers. Tacit judgment stays in the frontier weights. A lens goes local in proportion to how expressible its cut-rules are. + +## Mechanism — prompt over code, applied to the fold + +This is [Prompt Over Code](klappy://canon/principles/prompt-over-code) turned on the act of discernment itself. The frontier model spends its judgment once, writing the lens; the rulebook is the prompt; the cheaper model runs the prompt. The cheaper model is not asked to be intelligent — it is asked to be faithful to something intelligent that already ran. Execution moves down-tier, and where the rulebook is explicit enough, onto local hardware. + +## The bound — why articulability + +The transfer is lossy, and it is lossiest at the hard cases. A rulebook captures the typical, median call well. The ambiguous tail — the place where frontier judgment earned its keep — is captured worst, and judgment that is irreducibly tacit does not reduce to writable rules at all. A lens whose cut-rules can be written down ships down-tier and to-device first; a lens whose discernment stays tacit remains frontier-bound or escalates. Articulability is a property to measure, not assume, and it is the criterion that ranks which lenses move local first. + +This bound is the same line [Skills Are Procedure, Not Judgment](klappy://canon/principles/skills-are-procedure-not-judgment) already draws. That principle holds that a skill encodes the procedure and never the verdict; the verdict stays judgment. Rulebook Transfer is the generalization: what crosses a tier boundary is the articulable procedure, and what does not cross is the verdict. The expressible is portable; the tacit is not. + +## The recursion — and why you cannot skip rungs + +The transfer is not two layers. It is n-tier, and the operation is identical whichever tier sits on top: an upper tier distills its discernment into a rulebook the next tier runs. A human writing a rulebook a frontier model runs is the same move as a frontier model writing a lens a local model runs. "Systems that build systems" is this one operation permitted to run more than once. + +But each hop bridges only a bounded capability gap. Skip too many tiers and the rulebook silently assumes tacit context the executor does not have — and the loss does not degrade gently, it collapses, because the part that failed to transfer is exactly the unwritten judgment the bottom tier most needed. So transfer is a ladder of adjacent steps, not a cliff. The design variable is **step size** — how large a capability gap a single rulebook can bridge — and step size is itself bounded by articulability across *that specific gap*. The wider the gap, the more of the discernment must be made explicit; past some width the tacit residual is too large to write down, and the hop fails. "We cannot skip too much or it becomes impractical" is this constraint, stated exactly. + +## Two capacities: execution and stewardship + +The chain depends on two different capacities, and conflating them hides the real limit. + +- **Execution capacity** — run a rulebook from above faithfully. This extends far down the tiers. +- **Stewardship capacity** — author a rulebook *for the tier below*, hold a bounded domain, recognize what falls outside it, and escalate the rest. This is scarcer, and extends less far. + +The delegation ladder therefore has fewer rungs than the execution ladder. This mirrors any human organization: nearly everyone can execute competently within their lane; far fewer can manage, delegate, and judge what is out of their lane. So the transferability question is not a single number — "how far does it go?" — but two tests applied at each rung: can this tier (a) run a rulebook from above, and (b) author one for the tier below? A tier may pass (a) and fail (b) — a faithful executor that cannot steward. The ladder is mapped rung by rung, not assumed. + +This is the agent-side mirror of the operator-side ladder in [Shifting Bottlenecks, Climbing Ladders](klappy://writings/shifting-bottlenecks-climbing-ladders): *capability gets you to the next rung; trust, harness, and delegation maturity decide whether you can stand on it.* The same sentence governs both sides of the handoff. + +## The loop closes because authority flows one way + +A loop that surfaces its own governance unravels when authority forms a cycle: when something downstream can rewrite the rules upstream of it, the system begins ratifying itself, and early mistakes entrench. The guarantee against that is a single asymmetry — **information flows in every direction; authority flows in one.** Proposals travel up, down, and sideways freely. Authority travels downward only, and never forms a cycle. The loop is safe to close in the information dimension precisely because it stays acyclic in the authority dimension. + +The governance rules follow as corollaries of that asymmetry: + +- **Induction proposes; it does not ratify.** A regularity observed across many decisions is evidence *for* a candidate principle, not a principle. It enters advisory only — in kirigami terms, custody `synthesized`, with named grounds, carrying no standing. +- **No tier promotes itself.** A tier cannot ratify its own proposal, widen its own scope, or write rules about itself. Reflexive authority is a cycle of length one, forbidden for the same reason longer cycles are. ("Agents never self-promote" is this corollary, not a separate axiom.) +- **No tier writes upward.** A tier cannot edit the canon of a tier above it. This preserves [Models Do Not Mutate Canon](klappy://canon/decisions/models-do-not-mutate-canon): a model never edits the operator's sovereign canon. +- **Authority is delegated, bounded, and revocable.** A tier that has the capacity to steward may hold authority over a sub-scope granted from above — its own canon, within its jurisdiction — and may ratify within it. It never owns the definition of its own boundary, and the grant can be revoked from above. Governance is [a role on a scope](klappy://docs/planning/kb-data-model), not a possession. + +Authority is a role-overlay above the wire, not a wire primitive: [Symmetric Participation](klappy://canon/principles/symmetric-participation) keeps every peer identical at the wire, and jurisdiction is metadata above it. It is sited at the governance layer, not the epistemic core — [ODD does not define authority](klappy://canon/constraints/odd-is-epistemic-os-not-values), and this principle adds that axis where "governance is a role" already lives, rather than inside the epistemic OS. + +The verdict — promotion across a scope boundary — is never encoded into a lower tier. This is `Skills Are Procedure, Not Judgment` restated once more: encode the procedure, never the verdict. + +## Evidence, bounded + +Two layers of evidence, each scoped honestly. + +**Execution transfer** has probe support. The fold-fidelity probe had three models (Haiku, Sonnet, Opus) fold the same corpus under the same lens; all three passed the faithfulness gate, with tier-1 pivotal agreement near 80–90%. This supports down-tier *execution* at the cloud tier. It is not support for the *device* tier; that is the hypothesis the P0 cross-model reconstruction-fidelity sweep is built to test, and P0 is post-build. + +**Stewardship transfer** has been observed at exactly one rung: a frontier-tier model holding delegated authority over real repositories in an operator-approved working agreement, proposing downward and escalating out-of-scope decisions upward for approval. That is N=1, and it sits at the *top* rung — the least surprising place for stewardship to hold and the least informative about whether it transfers downward. The multi-rung chain, in which each tier stewards the one below, is unproven. + +A further hazard sharpens both: an articulated rulebook can be fluent and still not describe what its author actually did. A confabulated rulebook reads well and reproduces badly. Fidelity is therefore never inferred from how good the rulebook reads; it is measured by testing that the lesser tier makes the same cuts — consistent with [Code Claims Require Code Observation](klappy://canon/principles/code-claims-require-code-observation): the claim is verified against observation, not against its own prose. + +### Second probe — COO canon, 2026-06-30 (real corpus, three tiers) + +A live cross-model run folded chapters from four COO books through one lens, graded by a fresh-context grader against held-out truth (`kirigami://docs/eval/coo-corpus-fidelity-run-2026-06-30`). It extends both evidence layers: + +**Execution transfer — strengthened.** Under a sufficiently explicit lens a Haiku-class model reached ship-grade fidelity (8/8 held-out questions on the hardest chapter). The *articulability step-size* mechanism was observed directly: under a thin lens Haiku collapsed (88 rows, 4 tier-1 — a starved skeleton); writing the missing discernment down (budgets, tier test, anti-fragmentation rule, worked example, self-count gate) moved the same model into the frontier band (45 rows, 10 tier-1) with no model change. Articulability, not raw capability, was the binding variable — exactly as the principle predicts. + +**Stewardship transfer — first data on the chain arm.** The prior evidence was N=1 at the top rung. This probe tested the rung below: a mid-tier model (Sonnet) *authored* a compensating rule for a Haiku failure, and it worked when Haiku ran it (the targeted hallucination and orphan edges disappeared) — but it **over-corrected**, dropping coverage. A frontier model (Opus), given the identical brief, authored the same fix **surgically** — failure removed, coverage preserved. Reading: stewardship *does* transfer below the top rung, but it is **lossy in the tacit dimension** — the mid tier fixes the articulable bug and fumbles the balance the frontier holds. This is a first, concrete data point on the **star-or-chain** question: frontier→bottom authoring is clean (the star arm holds); mid-tier→bottom authoring is real but degraded — consistent with the claim that the delegation ladder has fewer rungs than the execution ladder. + +**Still open.** The device tier is untested (all three models are cloud). The multi-rung chain remains thin: one rung of mid-tier stewardship, observed once, lossy. Star-vs-chain is now *informed*, not resolved. + +## Open questions + +- **Star or chain?** Does stewardship capacity re-instantiate at each tier (a chain — every tier stewards the one below), or does it concentrate at the frontier (a star — one steward authoring for everyone)? The single observed rung does not distinguish them. This is the dominant empirical question for the whole model. +- **Fixed or teachable?** Is stewardship capacity a fixed property of a model tier, or can a tier be brought up a rung with the right harness — the graduation arc of [How You Lead Is What You Build](klappy://writings/how-you-lead-is-what-you-build) applied to a model rather than a person? The answer decides whether the ladder is discovered or built. + +## Design implications + +- **Cascade, not replacement.** The lesser model folds the confident median and escalates the ambiguous tail. Temporality routes: fresh and typical rows stay local; stale or edge rows escalate to a frontier pass. +- **Articulability ranks the roadmap.** Lenses move to-device in order of how much of their discernment is expressible. +- **Build the ladder rung by rung.** Hand stewardship only between adjacent tiers, and test each rung's two capacities separately before relying on it. Do not assume a rung that has not been observed. +- **Authorship is frontier; execution is local.** The substrate carries both the rulebook and the folded output in one shape, so the frontier-judgment → local-execution handoff has somewhere to live. The substrate stays blind; the lens carries the flavor ([Vodka Architecture](klappy://canon/principles/vodka-architecture)). diff --git a/canon/principles/skills-are-procedure-not-judgment.md b/canon/principles/skills-are-procedure-not-judgment.md new file mode 100644 index 0000000..c8863f4 --- /dev/null +++ b/canon/principles/skills-are-procedure-not-judgment.md @@ -0,0 +1,117 @@ +--- +uri: klappy://canon/principles/skills-are-procedure-not-judgment +title: "Skills Are Procedure, Not Judgment — What odd/canon/oddkit Carry That a Skill Never Can" +audience: canon +exposure: nav +tier: 2 +voice: neutral +stability: semi_stable +tags: ["canon", "principle", "skills", "procedure", "judgment", "discernment", "vodka-architecture", "prompt-over-code", "E0010"] +epoch: E0010 +date: 2026-06-18 +derives_from: "canon/constraints/audit-gates-are-spawned-agent-sessions.md, canon/principles/prompt-over-code.md, canon/principles/verification-requires-fresh-context.md, canon/constraints/critic-cannot-be-resolver.md, canon/definitions/validation-as-epistemic-mode.md, canon/principles/discernment-layer.md" +complements: "writings/when-skills-arent-enough.md, canon/principles/ritual-is-a-smell.md, writings/crew-not-clone.md" +governs: "How responsibility is divided between a skill (a fixed, relevance-loaded procedure) and the judgment layer (odd/canon/oddkit). Determines what may be encoded into a skill and what must be left to a judging agent operating under canon." +status: active +--- + +# Skills Are Procedure, Not Judgment — What odd/canon/oddkit Carry That a Skill Never Can + +> A skill encodes a procedure and repeats it the same way every time; that is its strength and its ceiling. It cannot render a judgment — decide whether a claim is verified, whether a generated artifact meets a definition-of-done that has no compiler to grade it, whether the moment warrants reverting modes, what canon actually says about the case in hand. The dividing line is not repeatable versus not-repeatable, because plenty of judgment recurs; the line is procedure versus judgment. odd/canon/oddkit are the judgment layer. A skill can host a playbook the judgment layer runs, but it can never be the judgment, and that is structural rather than a gap a better-written skill closes: a mechanical step cannot be an audit gate, cannot validate its own output from fresh context, and cannot be the enforcer that also gets to script the law. The rule that keeps the two honest: encode the procedure, never the verdict. + +--- + +## Summary — Procedure Repeats; Judgment Discerns, and Only One of Them Is Encodable + +A skill is a fixed recipe: a bundle of instructions loaded by relevance and executed the same way each time. Consistency is what it is good at. It follows steps; it does not weigh evidence. + +Judgment is the other thing. It is discernment applied in context — deciding whether a claim has been verified, whether an artifact meets a definition-of-done with no oracle to grade it, whether the situation warrants reverting modes, what the canon actually says about the case in hand. None of those is a step to follow. Each is a call to make. + +The tempting misread is that the boundary runs between work that repeats and work that does not. It does not. A judgment call can recur daily and still be a judgment call every time, because each instance weighs its own evidence. The boundary that actually holds is procedure versus judgment, and a skill lives entirely on the procedure side. + +This is not a maturity gap. A better-written skill does not eventually become a judge, because three structural facts already named in canon stand in the way. An audit gate that requires reading prose, code, and history together must be a spawned agent session, not a pattern matcher. Validation requires a context break, so a creator cannot grade its own work. And governance is law applied by an enforcer, not a script hardcoded into the runtime — the judging is not scriptable. A skill is a mechanical, same-context, scripted procedure. By each of those facts it is disqualified from being the judgment. + +So the division of labor is clean. The skill is the repeatable procedure: the playbook, the recipe, the steps of a pass and where the outputs land. The substrate — odd/canon/oddkit — is the judgment: does this claim hold, does this pass the definition-of-done, should we revert, what does canon say. The rule that keeps the two from blurring is one line: encode the procedure, never the verdict. + +--- + +## The Line Runs Between Procedure and Judgment, Not Between Repeatable and Not + +It is easy to assume the useful distinction is between tasks that repeat and tasks that are one-of-a-kind, and to file skills under the first and judgment under the second. That filing is wrong, and the error is expensive, because it licenses encoding a recurring judgment into a skill on the theory that recurrence makes it mechanical. + +Recurrence does not make a thing mechanical. Deciding whether a draft meets its definition-of-done is a judgment whether it happens once or four hundred times; the four-hundredth instance still has to read the artifact actually produced and weigh it against a standard no compiler enforces. The repetition is in the *occasion*, not in the *call*. + +A skill is a fixed recipe: instructions loaded by relevance and run the same way each time. Its strength is exactly that it does not vary. Judgment is discernment applied in context, and its whole job is to vary with the evidence in front of it. The first is valuable because it is invariant. The second is valuable because it is not. Sorting by "does this recur" puts invariant and variable work in the same bin and loses the only distinction that matters. + +## Why a Skill Cannot Cross the Line — Three Structural Reasons, Not One Maturity Gap + +The claim is not that today's skills are immature and tomorrow's will judge. The claim is that a skill is the wrong kind of thing to judge, and canon already says so in three places. + +### A Mechanical Step Cannot Be an Audit Gate + +When canon defines what to check and the check requires reading prose, code, and history together to render a judgment, `canon/constraints/audit-gates-are-spawned-agent-sessions` requires the gate to be a spawned, fresh-context agent session. Mechanical alternatives are forbidden as gates — not discouraged, forbidden — because they manufacture false confidence: a green check sitting over a drift the matcher cannot see. A skill is a mechanical procedure. Putting it at a judgment gate produces the worse-than-nothing outcome that constraint exists to prevent. + +### A Procedure Cannot Supply the Independence Validation Requires + +`canon/principles/verification-requires-fresh-context` establishes that the lenses used to create an artifact are the lenses used to evaluate it, so a creator's accumulated context bridges the gap between intent and artifact and hides the flaws. `canon/constraints/critic-cannot-be-resolver` sharpens the same point: detection and remediation require separate contexts, because one context corrupts both functions. The independence validation needs is therefore a property of context, not of procedure. It is supplied by the break: a fresh session, a separate reviewer, a real handoff. Nothing about a set of steps can manufacture that break. + +This is why a skill cannot be the validating judgment, and the reason is sharper than "a skill is mechanical." A skill is context-portable. The same bundle loads into the session that produced the work or into a fresh one, with no guarantee of which. In the producing context it is self-review wearing a checklist. In a fresh context the independence comes from the session, not from the skill. Either way the load-bearing thing is the context break, which the skill neither provides nor preserves. A skill can host the checklist a fresh-context judge runs. It cannot be the independence that makes the judgment trustworthy. + +This reason is distinct from the audit-gate reason above, not a restatement of it. That one is about capability: a mechanical matcher cannot read prose, code, and history together to see semantic drift at all. This one is about independence: even a fully capable judge cannot validate the output of its own context. A skill fails both tests, for different reasons. + +### The Enforcer Does Not Get to Script the Law + +`canon/principles/prompt-over-code` keeps governance in documents and the server generic: the canon is the law, the server is the enforcer, and the enforcer surfaces whatever the law says without hardcoding the rules. A skill that tried to *be* the judgment would be hardcoding a verdict into the runtime — the exact move prompt-over-code forbids. The law is programmable by writing a document. The act of judging against it is not a script; it is a reading, made fresh each time against the case in hand. + +## What a Skill Can and Cannot Do — A Decision Tree Is Still Procedure + +The strongest objection is that skills are not really fixed: a skill can branch, carry conditionals, encode a decision tree, even call a model. Does branching not amount to judgment? + +It does not. A decision tree selects a branch by matching inputs against conditions its author wrote in advance. That is procedure with forks, and forks are still steps. What it never does is weigh novel evidence against a standard that has no oracle, notice that the case in hand is one its author never anticipated, or decide that the rule itself should be suspended here. The moment a branch encounters a situation outside its predefined conditions, it either fails closed or guesses — and a guess wearing a green checkmark is the false confidence the audit-gate constraint names. + +So the capability test is not "can it choose." It is "can it weigh evidence it was not pre-told how to weigh, from a context fresh enough to see its own blind spots, and produce a verdict no compiler could have produced for it." A skill answers no to that test by construction. That is the whole of what it cannot do, and naming it precisely is what keeps the principle from overreaching: a skill can do everything procedural, including elaborate branching, and nothing that requires the three structural capacities above. + +## The Division of Labor — The Skill Hosts the Playbook, the Substrate Renders the Verdict + +Set the two side by side and the responsibilities sort themselves. + +A skill is the repeatable procedure — the playbook, the recipe, the ordered steps of a pass and where its outputs land. A skill is the right home for "here is how the projection pass runs," "here are the steps to assemble the artifact," "here is the shape the output takes." + +The substrate (odd/canon/oddkit) is the judgment. Does this claim hold its evidence. Does this artifact meet the definition-of-done. Should this work revert to planning. What does canon actually say about the case in hand. The substrate is also where the human's irreplaceable contribution lands when the execution layer is a model at all: `canon/principles/discernment-layer` names discernment as the load-bearing human capacity once production is cheap. This principle is the machine-side companion to that one. Among the non-human layers, judgment lives in the substrate, never in the skill. The public essay `When Skills Aren't Enough` reaches the same edge from the practitioner's side: you outgrow the recipe box when your knowledge shifts from instructions to judgment. This principle says why the recipe box could never have held the judgment in the first place. + +A skill can host a playbook that the judgment layer invokes. It can never be the judgment that decides whether the playbook's output was any good. + +## The Rule — Encode the Procedure, Never the Verdict + +One line keeps the division honest: **encode the procedure, never the verdict.** + +A procedure is safe to encode because it is meant to be invariant — running it the same way every time is the point. A verdict is not, because a verdict is the output of weighing this evidence, in this context, against this standard, and the next case is different. Encoding a verdict freezes a reading that was only ever true for one case and replays it as though it were a rule. That is how a mechanical gate ends up green over a drift it cannot see; it is replaying yesterday's verdict on today's evidence. + +The rule also explains why the verdict resists encoding in the first place. A verdict is not state you write down once and reuse without drift — `canon/principles/dry-canon-says-it-once` warns that a rule duplicated into two homes diverges silently, and a verdict baked into a skill is precisely that: the judging duplicated out of the judgment layer and into a procedure, where it will diverge from what canon now says the moment canon moves. Keep the law in the canon, keep the judging in a fresh-context reading of it, and let the skill carry only the steps. + +## When This Would Be Wrong — Two Retraction Conditions + +A principle that cannot be falsified is a preference. This one carries two falsifiers, one definitional and one empirical, and it needs both. The definitional clause alone would make the principle true by construction, and a principle true by construction says nothing about the world. + +**The definitional clause.** The boundary holds because "fixed, relevance-loaded procedure" and "fresh-context judgment with no oracle" are different kinds of thing. If the vocabulary itself ever stops distinguishing them, the principle and the words it is built from both need rewriting. This clause is analytic and cannot be falsified by anything the world does. That is its strength and also its limit. + +**The empirical clause.** The principle also makes a bet the world can settle. A fixed, scripted procedure placed at a judgment gate will drift from the verdict a fresh-context judge would render, and it will drift precisely on the cases its author did not anticipate, producing the green-over-drift failure that `canon/constraints/audit-gates-are-spawned-agent-sessions` names. The test is runnable. Take a representative set of cases, including ones outside the procedure's anticipated conditions, and compare the procedure's verdicts against a fresh-context judging agent's. The principle predicts disagreement that grows with novelty. If instead the verdicts agree across the novel cases, if a scripted procedure reliably matches independent judgment on inputs it was never told how to weigh, then the operational rule "encode the procedure, never the verdict" has lost its force, whatever we decide to call the artifact. That is the failure mode the principle is betting it will keep encountering. Retract the rule the day it stops. + +The definitional clause answers whether these are different kinds of thing. The empirical clause answers the question canon asks of every principle: is this surviving because it is true, or because its failure mode has not yet been encountered? + +## A Separate Concern, Parked — Persona Is Not This Principle + +There is a parallel axis that is easy to confuse with this one: whether a model should wear an imposed persona or costume, or operate as crew under shared values. That question is real and it is already treated elsewhere — `Crew, Not Clone` is its home. It is not this principle. This document is strictly about procedure versus judgment, the division between what a skill carries and what the substrate carries. Identity, voice, and costume are a different cut of the same material and belong to their own essay. Conflating the two would blur both; they are kept separate on purpose. + +## See Also + +- [Audit Gates Are Spawned Agent Sessions](klappy://canon/constraints/audit-gates-are-spawned-agent-sessions) — why a mechanical matcher cannot be a judgment gate +- [Verification Requires Fresh Context](klappy://canon/principles/verification-requires-fresh-context) — why a creator cannot validate its own work +- [Critic Cannot Be Resolver](klappy://canon/constraints/critic-cannot-be-resolver) — detection and remediation need separate contexts; independence is contextual, not procedural +- [Validation as Epistemic Mode](klappy://canon/validation-as-epistemic-mode) — validation as a distinct mode requiring a context break +- [Prompt Over Code](klappy://canon/principles/prompt-over-code) — the enforcer is generic; the law lives in documents, not the runtime +- [The Discernment Layer](klappy://canon/principles/discernment-layer) — the human-side companion: discernment is the load-bearing capacity once production is cheap +- [DRY — The Canon Says It Once](klappy://canon/principles/dry-canon-says-it-once) — why a verdict duplicated into a skill diverges from canon +- [Ritual Is a Smell](klappy://canon/principles/ritual-is-a-smell) — a mechanical procedure standing in for missing judgment is a compensating control +- [When Skills Aren't Enough](klappy://writings/when-skills-arent-enough) — the practitioner-side account of outgrowing the recipe box +- [Crew, Not Clone](klappy://writings/crew-not-clone) — the parked persona/identity axis, treated in full diff --git a/journal/2026-07-07-odd-fly-cycle-01.tsv b/journal/2026-07-07-odd-fly-cycle-01.tsv new file mode 100644 index 0000000..ae90f74 --- /dev/null +++ b/journal/2026-07-07-odd-fly-cycle-01.tsv @@ -0,0 +1,8 @@ +type typeName facet quality_score quality_max quality_level title content +O Observation 5 5 strong Watermark 2026-06-17..1a4919c screened: 164 marked docs, 156 in sync, 5 missing, 2 stale, 1 divergent-by-design First extraction cycle since the bifurcation. Delta computed by frontmatter-parsed target_repo inventory with target_repo-stripped diff, never body-grep. Missing: rulebook-transfer, skills-are-procedure-not-judgment, actionable-output-in-actionable-form, odd/encoding-types/tension.md, discernment-transfer-ladder. Stale: dolcheo-vocabulary (seven vs eight letters), writing-canon (#265 spine). Divergent-by-design: governance-validation-via-agents (criterion-6 placeholders, no source edits since extraction — kept). +D Decision 5 5 strong Six files staged as one routing PR, verbatim-minus-target_repo, URIs grandfathered; captain's merge is the ratification Followed the observed D0002 convention (156 in-sync docs are byte-identical after dropping the routing line) rather than the boarding pass's re-minted-URI guess. Nothing reaches the read model until the owner merges; klappy.dev untouched, monitor-only throughout. +T Tension 5 5 strong discernment-transfer-ladder: routing marker says core, its own provisional/proposed frontmatter says overlay between: target_repo field (#264) vs criterion 2 + Defaults clause of core-boundary-criteria; kind: contradiction; status: open — closes on the owner's routing ruling (dossier research/odd-fly/proposals/HELD-discernment-transfer-ladder.md exposes both options with costs). Held out of the staged PR. +T Tension 5 5 strong README says authoring happens in ODD via PRs; all core-marked authoring since 2026-06-17 happened in klappy.dev between: README write-model claim vs commits #252..#265 (observed via #261 landing source-side only, leaving the read model serving stale DOLCHEO for two weeks); kind: drift; status: open — closes when the owner rules where core-routed docs are born, or amends the README to name ODD a sync mirror. +L Learning 4 5 adequate The local oddkit CLI blends a baseline repo into catalog output; per-URI get against the clone is the honest parity probe Catalog run against the ODD clone listed writings/ and docs/ paths that exist only in the baseline. Live-serve parity must be re-verified after merge; recorded in the extraction workflow's Step 6 caveat. +O Open 4 5 adequate Three unmarked new canon docs (a-proxy-confers-shape-not-standing, generic-boarding-pass, directory-submission-gauntlet) recorded stays-overlay Priority: low. All experimental/evolving/proposed, no routing marker. If the owner intends any for core, setting target_repo routes it mechanically next cycle. +H Handoff 5 5 strong Cycle 02 boards from this entry: watermark = klappy.dev 1a4919c; charter + workflow live in research/odd-fly/ Annex charter (DRAFT, owner-ratification pending) and the deterministic extraction workflow (Sonnet-executable, fidelity unproven until graded) are this cycle's transferable output. Next wake: weekly, or a klappy.dev merge touching marked docs. diff --git a/odd/encoding-types/tension.md b/odd/encoding-types/tension.md new file mode 100644 index 0000000..137cfc3 --- /dev/null +++ b/odd/encoding-types/tension.md @@ -0,0 +1,133 @@ +--- +uri: klappy://odd/encoding-types/tension +kind: canon +title: "Encoding Type: Tension (T, derived)" +audience: docs +exposure: nav +tier: 2 +voice: neutral +stability: semi_stable +tags: ["odd", "oddkit", "encode", "dolche", "dolcheo", "dolcheot", "tension", "tensions", "contradiction", "tradeoff", "drift", "derived", "second-order", "projection", "encoding-type", "tsv", "governance", "epoch-9"] +epoch: E0009 +date: 2026-06-24 +derives_from: "canon/definitions/dolcheo-vocabulary.md, odd/encoding-types/how-to-write-encoding-types.md, canon/principles/quality-attributes-are-in-tension.md, canon/principles/prompt-over-code.md" +complements: "odd/encoding-types/observation.md, odd/encoding-types/decision.md, odd/encoding-types/learning.md, odd/encoding-types/constraint.md, odd/encoding-types/handoff.md, odd/encoding-types/encode.md, odd/encoding-types/open.md, odd/encoding-types/how-to-write-encoding-types.md, odd/encoding-types/serialization-format.md" +governs: "oddkit_encode parsing and quality scoring for type T (derived/second-order)" +status: active +--- + +# Encoding Type: Tension (T, derived) + +> A contradiction or unresolved conflict visible only *across* two or more captured artifacts — never in any single one. Unlike every other DOLCHEOT type, a Tension is synthesized by default rather than asserted in the common case; when an operator asserts the contradiction in their own voice, it becomes an authored, sovereign Tension. It is advisory and sha-bound to the artifacts it spans: when they change, it goes stale and is re-derived. A Tension closes when an author resolves it (a Decision) or retracts one of its poles. + +--- + +## Summary — The Derived Dimension: What the Artifacts, Together, Contradict + +For months, `oddkit_encode` surfaced tensions as a side effect: writing a project journal in prose, the model would notice that two captured items disagreed and write about it — but the contradiction had no type, no schema, and no home. It lived in prose or vanished. Tension makes that emergent behavior first-class. + +Tension is the first **second-order** DOLCHEOT type. Every other letter is *asserted* — an author or agent states a Decision, an Observation, a Constraint as content. Tension is *inferred* — computed by a detection pass *over* the other captured artifacts. That is what makes it a projection off the source map rather than a fact entered into it: regeneratable, advisory, and never sovereign unless an author asserts it in their own voice. See `canon/definitions/dolcheo-vocabulary.md` for how Tension joins the core letter set and why it is core (universal) rather than a domain extension. + +--- + +## Type Identity + +| Field | Value | +|---|---| +| Letter | T | +| Name | Tension | +| Custody | Synthesized by default (derived); authored only when an operator asserts the contradiction in their own voice | +| Priority | Derived / second-order — emitted by a detection pass after the assertable types by default; entered by hand only when an operator asserts the contradiction | + +--- + +## Field Schema + +When encoding a Tension, the model outputs a row with the following fields (serialization format governed by `odd/encoding-types/serialization-format.md`): + +``` +T {title} {body} {between} {kind} {status} +``` + +| Field | Recommended | Description | +|---|---|---| +| type | yes | Always `T` | +| title | yes | Short summary of the contradiction (≤12 words) | +| body | yes | What disagrees, and why the two sides cannot both stand as written | +| between | yes | The ≥2 artifacts/claims in conflict — references (artifact ids, row ids, or short source labels). A tension needs ≥2 poles | +| kind | no | `tradeoff` (two goods in tension), `contradiction` (factual conflict), or `drift` (canon vs implementation/observed) | +| status | yes | `open` with what would close it, or `resolved:{ref}` (the Decision or retraction that closed it) | + +Example: + +``` +T Per-artifact encode output vs observed batch collapse Canon requires oddkit_encode to return a per-artifact array for batched input; an observed run collapsed six prefix-tagged artifacts into one Decision blob. canon/definitions/dolcheo-vocabulary#tool-level-implication, encode-run-2026-06-24 drift open — closes when the tool ships per-artifact output, or the requirement is retracted +``` + +--- + +## Trigger Words (Fallback Classification) + +When encode input is unstructured (not TSV), these trigger words classify a paragraph as Tension: + +``` +contradicts, conflicts with, in tension, at odds, doesn't square, inconsistent with, can't both, mutually exclusive, trade-off, tradeoff, pulls against, disagrees with, contradiction, conflict between +``` + +Classification preference: a paragraph prefixed `[T]` is classified as Tension. Because a Tension is *derived*, the primary way it enters a journal is not an author prefix but the detection pass (below) emitting `T` rows over the other artifacts. + +These words build the dynamic fallback regex only. On the primary TSV path, the type letter `T` is the classifier. + +--- + +## Quality Criteria + +Each criterion adds 1 to the quality score (max 5): + +| Criterion | Check | Gap message if missing | +|---|---|---| +| Substance | Body is ≥10 words describing the conflict | "Tension is too brief — state what disagrees and why both can't stand" | +| Two poles named | `between` references ≥2 distinct artifacts/claims | "A tension needs ≥2 sides — name what is in conflict" | +| Each pole sourced | Each pole in `between` points to a captured artifact, not an unanchored assertion | "Anchor each side to a source — which artifacts contradict?" | +| Genuine opposition | Body shows the poles actually conflict, not two unrelated facts | "Show the opposition — why can't both hold as written?" | +| Closure path | `status` is `resolved:{ref}`, or `open` with what would close it | "How does this close? A Decision, a retraction, or a specific event?" | + +Quality levels: + +| Score | Level | Status | +|---|---|---| +| 5 | strong | recorded | +| 3–4 | adequate | recorded | +| 2 | weak | draft | +| 0–1 | insufficient | draft | + +--- + +## The Detection Pass — How Tensions Get Emitted + +Because a Tension is synthesized by default, it is usually produced by a pass rather than an author. After the assertable artifacts (D, O, L, C, H, E, Open) are typed for a session, the encoder runs one scan across them — and across any cited source documents — and emits a `T` row for each genuine cross-artifact contradiction. Guidance: + +- Emit a Tension only when ≥2 captured artifacts (or an artifact and a cited source) genuinely conflict. Two unrelated facts are not a tension. +- Keep it signal: cap emitted tensions per session and require the opposition and sourced-pole criteria. A detector that flags everything is worse than the prose habit it replaces. +- Mark custody `synthesized`. A Tension an operator asserts in their own voice is authored and sovereign; a Tension the pass infers is advisory and dismissable. +- Bind it to its poles. A Tension is sha-bound to the artifacts in `between`; when any changes, it goes stale and is re-derived. Re-derivation is **not guaranteed identical** — detection is an inference, not a deterministic transform. + +--- + +## What Makes a Good Tension Encoding + +A strong Tension answers four questions: What two (or more) things disagree? Where is each side sourced? Why can't both stand as written? What would resolve it? The most common gap is a single-pole "tension" that is really just an Observation — if there is only one side, it is not a tension. The second most common gap is a vague opposition ("these are in tension") with no statement of why both cannot hold. + +Three senses of "tension" must not be confused. The *quality-attribute tradeoff* (`canon/principles/quality-attributes-are-in-tension`) is one `kind` of Tension. The *challenge-vs-canon contradiction* surfaced by oddkit challenge is the challenge-time sibling. The DOLCHEOT `T` is the **encode-time, within-source** primitive: a contradiction across the captured artifacts. They share machinery; they are not the same artifact. + +A Tension earns its place only if it stays honest about its own confidence: it is a derived guess at a contradiction, valuable precisely because it is cheap to emit and cheap to dismiss. If the detector becomes noise, raise the bar or retract the type (see the vocabulary's retraction conditions). + +--- + +## See Also + +- [DOLCHEOT Vocabulary](klappy://canon/definitions/dolcheo-vocabulary) — the eight-dimension framework this type belongs to; why Tension is core, not a domain extension +- [How to Write an Encoding Type](klappy://odd/encoding-types/how-to-write-encoding-types) — the meta-governance this doc follows +- [Quality Attributes Are In Tension](klappy://canon/principles/quality-attributes-are-in-tension) — the `tradeoff` kind of Tension, as a structural principle +- [Encoding Type: Encode](klappy://odd/encoding-types/encode) — the meta-level letter for encode-action receipts +- [Prompt Over Code](klappy://canon/principles/prompt-over-code) — why this governance doc exists instead of server code diff --git a/research/odd-fly/charter.md b/research/odd-fly/charter.md new file mode 100644 index 0000000..9e2575c --- /dev/null +++ b/research/odd-fly/charter.md @@ -0,0 +1,60 @@ +# Fly-Loop Annex — ODD Extraction Cycle (outcomes-driven-development) + +**Status:** DRAFT — proposed annex under the ALREADY-RATIFIED stewardship charter (`canon/governance/stewardship-charter.md`, E0010, ratified 2026-06-09 by owner, in effect). Charter amendments are owner-reserved; this annex activates only on Klappy's ratification. It adds the loop's cadence, cost, and watch-list — it does not compete with, restate, or amend the charter's authority. +**Abbreviation:** **ODD** (outcomes-driven-development). A prior draft circulated as "OWD" — the W was a hallucinated letter, corrected by the captain 2026-07-06. +**Genre:** Editorial / curation (per the CDO rulebook's genre taxonomy) — falsifiable definition of *caught-up*: source watermark vs. processed watermark, over a source this loop does not own. +**Refines:** the CDO flight `research/stewardship-charters/owd-charter-draft.md` (2026-07-07), with cycle-01 observations replacing its estimates. +**Authored:** 2026-07-07, ODD Fly cycle 01 (Fable, verified `claude-fable-5`). + +## Mission — what "caught-up" means + +Healthy = **the bifurcation stays current and the split stays clean.** + +- Every klappy.dev doc carrying `target_repo: "outcomes-driven-development"` in frontmatter is either present in this repo (byte-identical after dropping the `target_repo` line, or divergent only by a recorded criterion-6 genericization) or held on a recorded contested verdict. +- **Two parallel canons, both intact.** `klappy://canon` keeps its voice untouched — this loop never writes to klappy.dev, ever. URIs are grandfathered opaque keys: an extracted doc keeps its `klappy://` URI verbatim (observed convention across all 156 in-sync docs; D0002 "write-path re-shard"). +- Neutrality holds where it applies: literal operational values genericized to placeholders (criterion 6 — worked example: `canon/methods/governance-validation-via-agents.md`, `klappy/klappy.dev` → `[OWNER]/[REPO]`); proof-of-provenance instance material kept (criterion 5). +- The read model serves every landed doc (oddkit catalog/get against this repo); the journal never gaps (ratified charter goal 5). + +**Watermark at cycle 01 (observed 2026-07-07Z, klappy.dev @ 1a4919c):** 164 marked docs → 156 in sync, 5 missing, 2 stale, 1 divergent-by-design (the criterion-6 precedent). After this cycle's PR merges: 162 in sync, 0 missing, 0 stale, 1 contested held (`discernment-transfer-ladder`), 1 divergent-by-design. + +## The extraction protocol (summary — full procedure in `extraction-workflow.md`) + +1. **Board** under the ratified charter (fetch it; an unboarded session holds no authority). +2. **Watermark diff:** klappy.dev commits since last recorded sync, filtered to files carrying `target_repo: "outcomes-driven-development"` — parsed from frontmatter, never body-grepped (named failure mode: body-text routing). +3. **Screen** each candidate against the seven tests of `canon/constraints/core-boundary-criteria.md`. Verdict per doc, recorded with criterion numbers: route / stays-overlay / contested. +4. **Transform:** verbatim copy minus the `target_repo` line; URI unchanged; genericize only literal operational values (criterion 6), recording each placeholder. +5. **Land as a routing PR** carrying the evidence core-boundary-criteria §Verification demands: (a) frontmatter-parsed mover list, (b) before/after parity counts, (c) per contested doc, the criterion and one line of why, (d) canonical-copy declaration for anything genericized or split. +6. **Ratification gate: the captain's merge is the ratification.** Nothing reaches live serve (main / the read model) without it. Contested calls ride the decision board — tension exposed, never adjudicated by the steward. +7. **Verify + journal:** read-model check on landed docs, DOLCHEO trail in `journal/`, advance the watermark. + +## What stays with the captain + +The ratified charter's reservations, whole: the license (undeclared by decision — "licensed, never assigned"), repo settings/visibility/credentials, epoch declarations and charter amendments (including this annex), external contributors, the standing veto. Plus loop-specific: + +- **klappy.dev is monitor-only.** Any fix this loop wishes the source would make is a note to the captain, never a PR to his canon. +- **Contested routings** — surfaced with the tension exposed. +- **Marking docs for routing.** The `target_repo` field is the maintainer's declaration; the loop reads it, never writes it. An unmarked doc, however portable it smells, is at most a decision-board suggestion. +- **Retiring or replacing an original: structurally out of scope**, not merely reserved. Additive, always. + +## Cost cap + +Normal cycle $2–4; per-run cap $5; a declared backlog-burn may run to $8 once, announced. Check-in: any cycle over $8, or two consecutive cycles where drafting outruns screening (spend shape inverting = curation drifting into authoring). + +## Failure modes watched + +| Signal | Threshold | +|---|---| +| The seven routing failures (topic-yanking, body-text routing, stranded derivation, manuals-as-philosophy, bets-as-doctrine, literal leakage, double-homing) | Any instance → journal incident | +| Watermark age | > 30 days behind klappy.dev → escalate, don't silently catch up | +| Voice/frame bleed in a landed doc | Caught at PR review; two in a row → recalibrate with the owner | +| Reverse bleed (any write, or proposed write, to klappy.dev) | Immediate stop — charter-surrender class | +| Read-model divergence (oddkit serves stale/missing marked docs) | Same cycle | +| Silent substitution (session operating without fetching the charter) | Has already resigned the charter (its own retraction clause) | +| **Authoring-home drift** (observed live, cycle 01): new core-routed docs born in klappy.dev while this repo's README claims authoring happens here | Re-report every cycle until the captain rules on the authoring home | + +## Cadence + +Weekly + event-driven: a klappy.dev merge touching marked docs; a read-model change affecting serving; an owner veto (calibration data). Cycle 01 was the backlog burn (5 missing + 2 stale, landed as one routing PR). + +--- +*Runs under the ratified E0010 charter's authority. Revocable with a word; revocation is journaled and the repo reverts to direct owner maintenance.* diff --git a/research/odd-fly/extraction-workflow.md b/research/odd-fly/extraction-workflow.md new file mode 100644 index 0000000..5674afa --- /dev/null +++ b/research/odd-fly/extraction-workflow.md @@ -0,0 +1,70 @@ +# Extraction Workflow — the deterministic Fly-loop procedure (editorial genre) + +**Status:** DRAFT — cycle-01 procedure, written down per rulebook-transfer so a Sonnet-class pilot can run cycle N. Judgment stays where marked **JUDGMENT**; everything else is mechanical. Escalation for a Sonnet pilot: to the CDO/Opus, except stop-the-loop items which go to the captain. +**Authored:** 2026-07-07, ODD Fly cycle 01 (Fable). Fidelity unproven until a lower tier runs it and the cuts are graded — treat cycle-02 output as candidate, not precedent. + +## Preconditions + +- Fresh clones of both repos (never operate on another session's working copy): + `gh repo clone klappy/outcomes-driven-development odd && gh repo clone klappy/klappy.dev klappy.dev` +- The ratified charter fetched and read (`canon/governance/stewardship-charter.md`) — an unboarded session holds no authority. +- The previous cycle's journal TSV read; note its recorded watermark (klappy.dev SHA). + +## Step 1 — Watermark diff (mechanical) + +```sh +cd klappy.dev +git log --oneline ..HEAD -- canon odd # candidate commits +``` + +## Step 2 — Delta inventory (mechanical) + +For every file carrying the routing marker, compare against the ODD copy with the `target_repo` line stripped from both sides: + +```sh +for f in $(grep -rl '^target_repo: "outcomes-driven-development"' canon odd); do + if [ ! -f "$ODD/$f" ]; then echo "MISSING: $f"; + elif ! diff -q <(grep -v '^target_repo:' "$f") <(grep -v '^target_repo:' "$ODD/$f") >/dev/null; then echo "DIFFERS: $f"; fi +done +``` + +Rules that make this honest: +- **Frontmatter only.** The marker is `^target_repo:` at line start inside frontmatter. Never body-grep (failure mode: body-text routing — a doc *quoting* the marker travels by accident). +- A `DIFFERS` hit is not automatically drift. Check `git log --since= -- ` on the source: no source commits since extraction ⇒ the difference is ODD-side genericization (criterion 6, by design — record it, don't "fix" it). Source commits exist ⇒ stale, sync candidate. + +## Step 3 — Screen (JUDGMENT) + +Per candidate, read the doc in full and record a verdict with criterion numbers from `canon/constraints/core-boundary-criteria.md`: + +- **route-to-core** — marked, `status: active`, substance portable, ancestors reachable (criterion 7 satisfied through the read model even when ancestors are overlay-side). +- **stays-overlay** — unmarked (the maintainer has not routed it), or `stability: provisional/experimental` with `status: proposed` (criterion 2: bets are not doctrine). Unmarked-but-portable docs may be *suggested* on the decision board; the marker itself is captain-only. +- **contested** — signals disagree (e.g. marker present but criterion 2 fails). Goes to the decision board with the tension exposed, both options named, **no recommendation executed**. The staged PR must not contain it. + +Screened ≠ moved: "stays-overlay" is a valid, recorded verdict, not a skipped item. + +## Step 4 — Transform (mechanical + one JUDGMENT pass) + +```sh +grep -v '^target_repo:' "klappy.dev/$f" > "odd/$f" +``` + +- URI stays `klappy://…` verbatim — grandfathered opaque key (D0002; observed across all 156 in-sync docs). **Do not** re-mint URIs (`odd://` is for docs *born* in ODD, e.g. core-boundary-criteria). +- **JUDGMENT — criterion-6 scan:** copy-pasteable operational values (repo slugs, URLs, account commands) outside clearly-marked examples → bracketed placeholders (`[OWNER]/[REPO]`, `[YOUR ODDKIT MCP URL, e.g. …]`). Instance material serving as *proof* (dated probes, named sessions, evidence URIs) stays — criterion 5. Record every placeholder in the proposal dossier. + +## Step 5 — Land as a routing PR (mechanical) + +One branch, one PR, ready-for-review, assigned to the owner, **never merged by the pilot**. The PR body carries the four evidence items core-boundary-criteria §Verification demands: +(a) the frontmatter-parsed mover list; (b) parity counts before/after; (c) per contested doc, criterion + one line; (d) canonical-copy declaration for anything genericized. + +Each mover gets a short dossier in `research/odd-fly/proposals/.md`: source URI, source SHA, target path, verdict + criteria, transform applied, why. + +## Step 6 — Verify, journal, advance (mechanical) + +- Read-model check on the branch copy: `oddkit --quiet get -r -i ""` per landed doc. (Caveat observed cycle 01: the local CLI blends a baseline repo into catalog results; per-URI `get` against the clone is the honest probe. Live-serve parity is re-checked after the captain merges.) +- DOLCHEO trail: `journal/-odd-fly-cycle-.tsv` in the house TSV format (`type typeName facet quality_score quality_max quality_level title content`). +- Record the new watermark (klappy.dev SHA screened up to) in the journal entry. +- Nothing is written to klappy.dev under any circumstances — any source-side wish is a captain note. + +## Stop-the-loop (straight to captain, cycle halts) + +Any write or proposed write to klappy.dev · any push to ODD main · a genre misfit (the work stops being screening and becomes authoring) · charter unreachable · a contested verdict the pilot is tempted to adjudicate. diff --git a/research/odd-fly/foldout.tsv b/research/odd-fly/foldout.tsv new file mode 100644 index 0000000..28f56e6 --- /dev/null +++ b/research/odd-fly/foldout.tsv @@ -0,0 +1,8 @@ +id ts contributor verdict tier signals scope custody confidence relationships short long +of0001 2026-07-07T05:30:00.000Z odd-fly-fable crystallize 1 convention-discovery extraction-protocol observed high of0002 Extraction convention is verbatim-minus-target_repo with grandfathered klappy:// URIs Diffed all 164 marked docs against ODD copies: 156 byte-identical after stripping the target_repo line, URIs kept verbatim per D0002's write-path re-shard. The boarding pass's guess of new oddkit://patterns/ URIs contradicts the ratified, in-effect convention; followed the repo's law, flagged the divergence for the captain. odd:// URIs are only for docs born in ODD. +of0002 2026-07-07T05:30:00.000Z odd-fly-fable crystallize 1 routing-field extraction-protocol observed high of0001 target_repo frontmatter field IS the routing law's marker; the queue is computable The seven criteria adjudicate; the maintainer records the verdict as target_repo in source frontmatter (bifurcation pass #227 onward). Cycle backlog = marked docs missing or differing in ODD. Frontmatter-parsed only, never body-grepped (named failure mode). This makes the editorial loop's watermark diff fully mechanical — Sonnet-executable per the extraction workflow. +of0003 2026-07-07T05:30:00.000Z odd-fly-fable observe 1 incident double-homing observed high of0004 Double-homing drift observed live: #261 (Tension) authored in klappy.dev only; ODD served stale DOLCHEO for 2 weeks ODD README claims authoring happens in ODD via PRs; since 2026-06-17 all core-marked authoring happened in klappy.dev (#252..#265). dolcheo-vocabulary diverged (seven vs eight letters), tension.md never arrived. Repaired by sync in this PR; the authoring-home question is surfaced, not adjudicated. +of0004 2026-07-07T05:30:00.000Z odd-fly-fable propose 2 backlog-inventory cycle-01 proposed high of0003 Cycle-01 delta: 5 missing, 2 stale, 1 divergent-by-design, 1 contested — staged 6 files, held 1 Missing: rulebook-transfer, skills-are-procedure-not-judgment, actionable-output-in-actionable-form, tension.md, discernment-transfer-ladder(held). Stale: dolcheo-vocabulary, writing-canon. By-design: governance-validation-via-agents (criterion-6 genericization precedent — [OWNER]/[REPO] placeholders; kept). Post-merge parity: 162/164 in sync, 1 contested, 1 by-design. +of0005 2026-07-07T05:30:00.000Z odd-fly-fable surface 1 contested discernment-transfer-ladder captain-queue high of0004 DTL contested: maintainer's routing marker says core; its own provisional/proposed frontmatter says overlay (criterion 2) Both signals are the maintainer's. Held out of the PR; dossier HELD-discernment-transfer-ladder.md exposes the tension with both options costed. Captain's correction becomes calibration data per the criteria doc's own instruction. +of0006 2026-07-07T05:30:00.000Z odd-fly-fable observe 2 stays-overlay unmarked-docs observed medium Three new klappy.dev canon docs carry no routing marker: a-proxy-confers-shape-not-standing, generic-boarding-pass, directory-submission-gauntlet All three are experimental/evolving/proposed — consistent with criterion 2 and the unmarked state. Verdict stays-overlay, recorded not skipped. If the captain intends any for core, setting target_repo routes it mechanically next cycle. +of0007 2026-07-07T05:30:00.000Z odd-fly-fable crystallize 2 genre-confirmation fly-loop observed high Editorial genre confirmed: caught-up is falsifiable (marked-doc parity), source stayed monitor-only, zero klappy.dev writes Cycle ran the rulebook's editorial middle exactly: watermark diff, frontmatter screen, additive landing via PR, contested to decision board. The annex charter (research/odd-fly/charter.md) refines the stewardship-charters draft with cycle-01 observed values replacing estimates; ODD abbreviation corrected from hallucinated OWD. diff --git a/research/odd-fly/proposals/HELD-discernment-transfer-ladder.md b/research/odd-fly/proposals/HELD-discernment-transfer-ladder.md new file mode 100644 index 0000000..8fe0b98 --- /dev/null +++ b/research/odd-fly/proposals/HELD-discernment-transfer-ladder.md @@ -0,0 +1,18 @@ +# HELD — Discernment Transfer Ladder (contested; NOT staged in this PR) + +| Field | Value | +|---|---| +| Source | `klappy://canon/methods/discernment-transfer-ladder` — `klappy/klappy.dev` @ `1a4919c`, `canon/methods/discernment-transfer-ladder.md` (#264) | +| Verdict | **CONTESTED** — surfaced for the captain, deliberately not adjudicated | +| Staged | Nothing. The doc stays overlay-side until the captain rules | + +**The tension, exposed.** Two signals disagree and both are the maintainer's own: + +1. **The routing field says core.** It carries `target_repo: "outcomes-driven-development"` — the same maintainer-set marker that routed all 156 in-sync docs, and under this cycle's workflow the marker is authoritative. +2. **Its own frontmatter says not-yet.** `stability: provisional`, `status: proposed` — criterion 2 ("the overlay is where bets live; the core is where settled doctrine lives") plus the Defaults clause ("undecided stays in the overlay; the core must be pulled toward quality, not pushed toward volume"). The body reinforces the smell: the star-vs-chain answer rests on one session's evidence with the fidelity gate explicitly not yet run ("Semantic fidelity unproven"), and the worked material is dense with instance operations — Covenynt COO approval design, `0 Context/about.md`, Brief 07/08, kirigami foldout mechanics — which reads closer to subject than to proof in several sections (criterion 5 boundary). + +**Options (either is one word from the captain):** +- **Hold in overlay** until the method reaches `status: active` — then it routes mechanically next cycle. Cost: `rulebook-transfer` (landing in this PR) points at a method adopters can't read yet. +- **Route now**, carrying its `provisional/proposed` frontmatter honestly, with a criterion-6 pass genericizing the Covenynt/Brief-specific operational references. Cost: a bet ships to adopters before its own fidelity gate has run — the exact failure mode ("bets shipped as doctrine") the criteria were minted to prevent. + +**Steward's note (not a ruling):** the criteria doc instructs that when signals conflict, the maintainer's *correction* is the calibration data — this dossier exists to collect that correction cheaply. diff --git a/research/odd-fly/proposals/actionable-output-in-actionable-form.md b/research/odd-fly/proposals/actionable-output-in-actionable-form.md new file mode 100644 index 0000000..44d2e85 --- /dev/null +++ b/research/odd-fly/proposals/actionable-output-in-actionable-form.md @@ -0,0 +1,12 @@ +# Proposal — A Link Is a Tap, Not a String (route-to-core) + +| Field | Value | +|---|---| +| Source | `klappy://canon/constraints/actionable-output-in-actionable-form` — `klappy/klappy.dev` @ `1a4919c`, `canon/constraints/actionable-output-in-actionable-form.md` (#256) | +| Target | `canon/constraints/actionable-output-in-actionable-form.md` (staged in this PR); URI unchanged | +| Verdict | **route-to-core** | +| Criteria | Marked; tier 1, `status: active`; ancestors `magical-first-run` and `model-operating-contract` in core (criterion 7); voice neutral. The Origin section (the 2026-06-14 `bee-ai-auth-mcp` debrief, the iOS operator) is proof-not-subject — the constraint functions without it and it serves as the debrief-becomes-law provenance (criterion 5) | +| Transform | Verbatim minus `target_repo`. No operational values to genericize — the named session is a dated incident reference, not a copy-paste template | +| Ratification | Captain's merge only. Original untouched | + +**Why.** "An actionable output is undelivered until it is actionable" binds any agent handing an operator links, commands, or paths, on any surface — nothing about it is instance-specific. It is the output-shaped sibling of "a claim is a debt" (axioms, already core), and its MUSTs are exactly the kind of agent-behavior constraint adopters point oddkit at. diff --git a/research/odd-fly/proposals/dolcheot-tension-sync.md b/research/odd-fly/proposals/dolcheot-tension-sync.md new file mode 100644 index 0000000..aefb5fd --- /dev/null +++ b/research/odd-fly/proposals/dolcheot-tension-sync.md @@ -0,0 +1,14 @@ +# Proposal — DOLCHEOT: Tension encoding type + vocabulary sync (route-to-core, drift repair) + +One proposal, two files — they shipped as one source change (#261) and are meaningless apart. + +| Field | Value | +|---|---| +| Source | `klappy://odd/encoding-types/tension` (new) + `klappy://canon/definitions/dolcheo-vocabulary` (updated DOLCHEO→DOLCHEOT, seven→eight, E0008.3→E0009) — `klappy/klappy.dev` @ `1a4919c` (#261) | +| Target | `odd/encoding-types/tension.md` (new) + `canon/definitions/dolcheo-vocabulary.md` (sync) — both staged; URIs unchanged | +| Verdict | **route-to-core** — for tension.md, and **stale-copy repair** for the vocabulary | +| Criteria | Both marked. Precedent decides tension.md's home: all seven sibling encoding-type docs plus `serialization-format.md` already live in this repo's `odd/encoding-types/` — an eighth letter defined anywhere else is stranded derivation (criterion 7). Its `governs: oddkit_encode parsing` does not make it an oddkit manual (criterion 4): the encoding types are ODD's vocabulary that the tool *enforces*, same as the seven already here. Additive: a DOLCHEO journal with zero Tensions stays valid | +| Transform | Verbatim minus `target_repo`, both files. No genericization needed | +| Ratification | Captain's merge only. Originals untouched | + +**Why this is also an incident, not just a sync.** This repo's README declares it "the write model for the `odd://` authority — authoring happens here via PRs." #261 was authored in klappy.dev on 2026-06-24 and never reached this repo: for two weeks the read model has served a seven-letter DOLCHEO while the source of record teaches eight. That is the **double-homing** failure mode core-boundary-criteria names ("redundant state invites drift"), observed live. The sync staged here repairs the drift; the *authoring-home question it exposes* (which repo is where core-routed docs are born?) is a decision-board item for the captain, deliberately not adjudicated here. diff --git a/research/odd-fly/proposals/rulebook-transfer.md b/research/odd-fly/proposals/rulebook-transfer.md new file mode 100644 index 0000000..3789837 --- /dev/null +++ b/research/odd-fly/proposals/rulebook-transfer.md @@ -0,0 +1,12 @@ +# Proposal — Rulebook Transfer (route-to-core) + +| Field | Value | +|---|---| +| Source | `klappy://canon/principles/rulebook-transfer` — `klappy/klappy.dev` @ `1a4919c`, `canon/principles/rulebook-transfer.md` (authored #262, evidence extended #264) | +| Target | `canon/principles/rulebook-transfer.md` (staged in this PR); URI unchanged — grandfathered opaque key | +| Verdict | **route-to-core** | +| Criteria | Marked `target_repo: outcomes-driven-development`; tier 1, `stability: stable`, `status: active` (criterion 2 passes — settled doctrine, not a bet); ancestors `prompt-over-code`, `discernment-layer`, `skills-are-procedure-not-judgment` (this PR), `code-claims-require-code-observation`, `verification-requires-fresh-context` all in core (criterion 7); voice already neutral | +| Transform | Verbatim minus `target_repo`. No genericization needed: the Haiku/Sonnet/Opus probes, the kirigami evidence URI, and the COO-corpus run are dated proof, not subject (criterion 5); no copy-pasteable operational values found | +| Ratification | Lands into live serve only on the captain's merge. `klappy://canon` original untouched | + +**Why.** The load-bearing pattern — discernment a frontier model performs once can be written down as a rulebook a lesser model runs, bounded by articulability, safe because authority flows one way — is fully portable: nothing in the principle depends on the maintainer's instance. It is also the theoretical spine for delegation work already running downstream (the CDO's stewardship-and-fly rulebook derives from it), so its absence from the portable core strands the derivation chain of anything an adopter builds on it. diff --git a/research/odd-fly/proposals/skills-are-procedure-not-judgment.md b/research/odd-fly/proposals/skills-are-procedure-not-judgment.md new file mode 100644 index 0000000..af33a8b --- /dev/null +++ b/research/odd-fly/proposals/skills-are-procedure-not-judgment.md @@ -0,0 +1,12 @@ +# Proposal — Skills Are Procedure, Not Judgment (route-to-core) + +| Field | Value | +|---|---| +| Source | `klappy://canon/principles/skills-are-procedure-not-judgment` — `klappy/klappy.dev` @ `1a4919c`, `canon/principles/skills-are-procedure-not-judgment.md` (ratified #257) | +| Target | `canon/principles/skills-are-procedure-not-judgment.md` (staged in this PR); URI unchanged | +| Verdict | **route-to-core** | +| Criteria | Marked; `status: active`, `stability: semi_stable`; every `derives_from` ancestor (`audit-gates-are-spawned-agent-sessions`, `prompt-over-code`, `verification-requires-fresh-context`, `critic-cannot-be-resolver`, `validation-as-epistemic-mode`, `discernment-layer`) already in core (criterion 7 — this doc is more stranded *outside* the core than in it); voice neutral | +| Transform | Verbatim minus `target_repo`. The `klappy://writings/…` links (When Skills Aren't Enough, Crew Not Clone) stay: overlay-side references resolve through the read model and function as provenance, matching the precedent in already-landed docs (e.g. `prompt-over-code` keeps its overlay `docs/appendices/` reference). References to odd/canon/oddkit are the methodology's own vocabulary, not instance leakage | +| Ratification | Captain's merge only. Original untouched | + +**Why.** The dividing line it draws — a skill encodes the procedure, never the verdict; judgment requires a fresh-context reading no script supplies — is the boundary any ODD adopter needs when wiring skills/automation around a canon. Its substance is about *kinds of things* (procedure vs. judgment), argued entirely from constraints that already live in this repo. Sibling principle `rulebook-transfer` (also in this PR) cites it as an ancestor; landing one without the other strands a derivation chain inside the core itself. diff --git a/research/odd-fly/proposals/writing-canon-spine-sync.md b/research/odd-fly/proposals/writing-canon-spine-sync.md new file mode 100644 index 0000000..537df5e --- /dev/null +++ b/research/odd-fly/proposals/writing-canon-spine-sync.md @@ -0,0 +1,12 @@ +# Proposal — Writing Canon spine sync (stale-copy repair) + +| Field | Value | +|---|---| +| Source | `klappy://canon/meta/writing-canon` — `klappy/klappy.dev` @ `1a4919c` (#265: the reader's one-line demand — "Show me what I'm deciding in a way that respects my attention and time" — added as the document's spine; 2 lines changed) | +| Target | `canon/meta/writing-canon.md` (sync staged); URI unchanged | +| Verdict | **stale-copy repair** — the doc was routed core at the bifurcation (#237) and both copies were in sync until #265 landed source-side | +| Criteria | Already-adjudicated core doc; the delta is voice-neutral and instance-free, so the original routing verdict stands unchanged | +| Transform | Verbatim minus `target_repo` | +| Ratification | Captain's merge only. Original untouched | + +**Why.** The writing canon governs every document in this repo (extraction-depth discipline); serving the pre-#265 text means adopters get the rule without its stated spine. Two-line drift is exactly the class of divergence the weekly watermark loop exists to catch while it is still trivial. From aeea5ec6d960bf8901f8258ef468767ad46b6f03 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 7 Jul 2026 04:14:17 +0000 Subject: [PATCH 2/3] Fix undefined ODD path in extraction workflow Step 1 cd's into klappy.dev, so make Step 2's parity loop and Step 4's transform reference the sibling ODD clone via ../odd instead of the undefined $ODD and the parent-relative klappy.dev/odd paths. --- research/odd-fly/extraction-workflow.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/research/odd-fly/extraction-workflow.md b/research/odd-fly/extraction-workflow.md index 5674afa..70a6a23 100644 --- a/research/odd-fly/extraction-workflow.md +++ b/research/odd-fly/extraction-workflow.md @@ -23,8 +23,8 @@ For every file carrying the routing marker, compare against the ODD copy with th ```sh for f in $(grep -rl '^target_repo: "outcomes-driven-development"' canon odd); do - if [ ! -f "$ODD/$f" ]; then echo "MISSING: $f"; - elif ! diff -q <(grep -v '^target_repo:' "$f") <(grep -v '^target_repo:' "$ODD/$f") >/dev/null; then echo "DIFFERS: $f"; fi + if [ ! -f "../odd/$f" ]; then echo "MISSING: $f"; + elif ! diff -q <(grep -v '^target_repo:' "$f") <(grep -v '^target_repo:' "../odd/$f") >/dev/null; then echo "DIFFERS: $f"; fi done ``` @@ -45,7 +45,7 @@ Screened ≠ moved: "stays-overlay" is a valid, recorded verdict, not a skipped ## Step 4 — Transform (mechanical + one JUDGMENT pass) ```sh -grep -v '^target_repo:' "klappy.dev/$f" > "odd/$f" +grep -v '^target_repo:' "$f" > "../odd/$f" ``` - URI stays `klappy://…` verbatim — grandfathered opaque key (D0002; observed across all 156 in-sync docs). **Do not** re-mint URIs (`odd://` is for docs *born* in ODD, e.g. core-boundary-criteria). From d46af7f181d44b345ac6df7c99e4ffc11fd4ab4d Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 7 Jul 2026 04:16:41 +0000 Subject: [PATCH 3/3] Fix DOLCHEOT eight-letter consistency and extraction transform edge cases - dolcheo-vocabulary: update migration trigger-phrase and scope text from seven to eight types/letters and DOLCHEO to DOLCHEOT - extraction-workflow Step 4: create parent directories before redirect; scope target_repo removal to frontmatter only --- canon/definitions/dolcheo-vocabulary.md | 4 ++-- research/odd-fly/extraction-workflow.md | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/canon/definitions/dolcheo-vocabulary.md b/canon/definitions/dolcheo-vocabulary.md index 4456053..d417784 100644 --- a/canon/definitions/dolcheo-vocabulary.md +++ b/canon/definitions/dolcheo-vocabulary.md @@ -204,7 +204,7 @@ DOLCHEO is backward compatible with DOLCHE. All six original dimensions retain t - A convention for priority bands (P1, P2, P3…) on Open items. - A disambiguation rule for the two Os (section placement, optional `-open` suffix for inline tags). -Existing DOLCHE journals do not need to be rewritten — they are valid DOLCHEO journals that happen to have zero Open entries. The trigger phrases "encode DOLCHE," "journal this," and "run the gauntlet" continue to work and invoke capture across all seven types; agents should use DOLCHEO in output regardless of which trigger phrase the operator uses. +Existing DOLCHE journals do not need to be rewritten — they are valid DOLCHEO journals that happen to have zero Open entries. The trigger phrases "encode DOLCHE," "journal this," and "run the gauntlet" continue to work and invoke capture across all eight types; agents should use DOLCHEOT in output regardless of which trigger phrase the operator uses. Agents that were previously taught DOLCHE have one concrete behavior change: at session end, before writing the Handoff section, scan the session for unresolved threads and record them as Open items with priority bands. If there are genuinely none, note that explicitly. An absent Open section is different from an empty one; the former suggests the agent forgot, the latter confirms the agent checked. @@ -218,7 +218,7 @@ DOLCHEOT adds one dimension: Tension (`T`), the derived contradiction. Every DOL DOLCHEO is a working vocabulary for session capture inside oddkit-powered knowledge bases, as of 2026-04-19. It is not presented as a universal claim about how teams should track work. -**Where DOLCHEO applies:** session journals and project ledgers maintained by an agent (or agent + operator pair) working inside an oddkit-powered project. The seven letters capture the epistemic state of one or more working sessions against a shared knowledge base. +**Where DOLCHEO applies:** session journals and project ledgers maintained by an agent (or agent + operator pair) working inside an oddkit-powered project. The eight letters capture the epistemic state of one or more working sessions against a shared knowledge base. **Where DOLCHEO does not apply:** product roadmaps, sprint backlogs, issue trackers, customer support queues, meeting minutes for multi-party decisions, and any system where the unit of tracking is a ticket owned by a team rather than a thread owned by a session. These systems have their own vocabularies and lifecycles and DOLCHEO neither replaces nor competes with them. diff --git a/research/odd-fly/extraction-workflow.md b/research/odd-fly/extraction-workflow.md index 70a6a23..a66754f 100644 --- a/research/odd-fly/extraction-workflow.md +++ b/research/odd-fly/extraction-workflow.md @@ -45,7 +45,8 @@ Screened ≠ moved: "stays-overlay" is a valid, recorded verdict, not a skipped ## Step 4 — Transform (mechanical + one JUDGMENT pass) ```sh -grep -v '^target_repo:' "$f" > "../odd/$f" +mkdir -p "$(dirname "../odd/$f")" +awk 'BEGIN{fm=0} /^---$/{fm++; print; next} fm==1 && /^target_repo:/{next} {print}' "$f" > "../odd/$f" ``` - URI stays `klappy://…` verbatim — grandfathered opaque key (D0002; observed across all 156 in-sync docs). **Do not** re-mint URIs (`odd://` is for docs *born* in ODD, e.g. core-boundary-criteria).