step.6.txt -- b3ubot U3.9a: first `execution`-kind DAG instance authored + round-tripped -- proving b3ubot's OWN planned extension to the substrate (design.md §2.13's "execution" workflow kind) actually fits the "deliberately permissive about kinds" grammar in practice, not just on paper. Registered as a PERMANENT 7th regression corpus, not a one-off manual check. Step: 6 -- promote UoW **U3.9a** (end_to_end.md §5, split from U3.9 at step.5's closure) to execution depth: hand- author one small, honestly-illustrative `execution`- kind `.dag` instance, get it to canonical form via `cctdag`, and make it a PERMANENT regression corpus -- so every future `dag/tests/run_tests.sh` run keeps proving b3ubot's own kind vocabulary still fits the substrate, not just this one time. Parent: end_to_end.md §5 U3.9a ("First b3ubot-kind instance (`execution`) authored + round-tripped against U3.9's now-proven substrate... real NEW authoring work, not verification of what already exists") + design.md §2.13 (the workflow DAG substrate -- the `execution` kind's own definition: "one per EXECUTING entry... nodes = tasks (context assembly, provider runs, tool calls, oracle gates, human gates); edges = dependencies; kv attrs carry engine state (status, run ids, timestamps)"). UoW: U3.9a -- "First execution instance". Depends on U3.9 (done, step.5, edbe4ed -- the substrate + regression suite proven green). No P1/P2 dependency (same self- contained-within-dag/ framing as U3.9 itself). Date: 2026-07-18 (SKELETON -- not executed. Execute on explicit request.) Origin: User directive 2026-07-18: "proceed with U3.9a." ## (0) Status SKELETON. Nothing built. Ground truth below comes from direct inspection of the grammar, a real committed instance, the OO API's entity definitions, and the SQL schema -- not assumption. ## (1) Ground truth probed at drafting EXISTS (the grammar, `dagModel.sgr`, read in full): a `dag` instance is `(dag { dagElement })`, where `dagElement` may be `kind`/`description`/`project`/ `project_name`/`root_node`/`version` (all OPTIONAL -- `{ }` iteration), a `keyValuePair` (`identifier '=' attrValue`), a `nodesBlock`, or an `edgesBlock`. A `node` is `(node { kind | description | path | artifact_refs | keyValuePair })`; an `edge` is `(edge { kind | description | keyValuePair })`. Nothing in the grammar enumerates valid `kind` VALUES -- kind is a bare `identifier` wherever it appears. EXISTS (a real committed instance, `dag/dagCommands/tests/ sample.dag`, read in full): `(dag d1Hierarchy (kind hierarchy) (description "...") (project bet3) ... (nodes (node bet3 (kind project) ...) ...) (edges (edge e_bet3_bot bet3 bet3_bot (kind consists_of) ...) ...))`. Confirms the textual shape directly, not just the grammar's abstract rules. EXISTS (the SQL schema, `dag/sql/dagModel.sql`, read in full): "Kind values: TEXT without CHECK constraint (Q-1003.C-E)" -- the dag/node/edge `kind` columns are plain TEXT, no enum, no foreign-key-style restriction to a known list. This is the CONCRETE form of design.md's "deliberately permissive about kinds" claim -- confirmed at the schema level, not just asserted in the design doc. EXISTS (the OO API entities, `dagModelPy/dag_model/entities.py`, a field-by-field mirror of `dagModelCpp/include/ dagModel.h`): `Dag(name, kind, description, project, project_name, root_node, version, attributes, nodes, edges)`; `Node(name, kind, description, path, artifact_refs, attributes)`; `Edge(name, source_name, target_name, kind, description, attributes)`; `KeyValue(key, value, value_kind)`. `project`/ `project_name`/`root_node` are Dag-level fields with no equivalent meaning for an `execution`-kind instance (they describe a codebase's structure) -- honestly OMITTED rather than force-filled with placeholder values. EXISTS (the canonical-form workflow, `dag/instances/README.md`, read in full): "prefer round-tripping through cctdag" when authoring/editing an instance -- `cctdag load --db /tmp/x.db` then `cctdag unload --db /tmp/x.db` -- since `cctdag unload`'s own output IS canonical form (2-space indent, insertion-order, no trailing whitespace) by construction. The committed file is the UNLOAD output, not the hand-typed draft. EXISTS (how a new corpus becomes permanently regression-tested, confirmed by reading all 3 test scripts): `regression/ lib/corpora.sh`'s `corpora_list()` function is the SINGLE source of truth -- `test_matrix.sh`, `test_npass.sh`, AND `test_quirks.sh` all `. corpora.sh` and iterate `while IFS='=' read -r label path; do ...; done < <(corpora_list)` (or equivalent). Adding ONE line to `corpora_list()` extends all three regression legs with zero further plumbing -- confirmed by reading each consumer, not assumed from one. EXISTS (a live inventory doc to extend, not create fresh): `dag/instances/README.md`'s own "## Inventory" table already tracks each committed instance file (currently just `d1Hierarchy.dag`) -- matches this project's own "live inventory docs" discipline (extend the existing table, don't invent a parallel doc). FOUND (an honest grounding choice for the instance's CONTENT): b3ubot already has ONE real thing that looks like an "execution" -- step.4's `app.cli.ask` flow: `propose_ask` (context assembly + a provider call) -> a human gate (`--yes` or the interactive confirm) -> `apply_ask` (the tool call). Modeling the hand-authored instance on THIS real flow (rather than an invented scenario) keeps it honestly grounded -- 4 of design.md's 5 named task kinds (context assembly, provider runs, human gates, tool calls) are covered for real; `oracle_gate` is the 5th and is DELIBERATELY OMITTED -- no oracle tier exists in b3ubot's code yet (P2, the ledger engine's T0/T1 machinery), and inventing one here would misrepresent what's actually built. ## (2) What U3.9a delivers 2.1 **`dag/instances/execution_example.dag`** (new, committed): one `execution`-kind instance, 4 nodes (`context_assembly`, `provider_run`, `human_gate`, `tool_call` -- named + `kind`- tagged to match, `path` pointing at the REAL b3ubot source location each models: `app/cli.py:propose_ask`, `app/pal/ adapter.py:Adapter.run`, `app/cli.py:main`, `app/tools.py: write_file`) and 3 `precedes`-kind edges forming the linear chain context_assembly -> provider_run -> human_gate -> tool_call. A few illustrative kv attrs (`status`, `provider`, `approved`) demonstrate the "kv attrs carry engine state" shape -- clearly described in the instance's OWN top-level `description` field as a HAND-AUTHORED illustration, not a captured real orchestrator run (none exists yet, P3's job). Hand-drafted, then round-tripped through `cctdag load`/`unload` to reach canonical form -- the committed file IS the unload output (Q-6-A). 2.2 **Register it as the 7th regression corpus**: one new line in `regression/lib/corpora.sh`'s `corpora_list()` -- `exec_example=$DAG_ROOT/instances/execution_example.dag`. From this commit on, EVERY `dag/tests/run_tests.sh` run proves the `execution` kind byte-identically round-trips across all 4 languages, permanently -- not a one-time manual check that could silently bit-rot. 2.3 **Extend `dag/instances/README.md`'s inventory table** with the new instance (the live-inventory-doc discipline) -- name, DAG kind (`execution`), edge kind (`precedes`), step (`step.6`), status (`landed`), plus a short "## execution_example scope" section (mirroring the existing "## d1 scope" section's shape) explaining what it models and why `oracle_gate` is absent. 2.4 **No dedicated standalone smoke script** (Q-6-B): `d1Hierarchy. dag`'s own `tests/test_d1_smoke.sh` predates the regression suite's existence (step.1003.F vs .H) and duplicates exactly what `test_matrix.sh`/`test_npass.sh`/`test_quirks.sh` now do generically for ANY registered corpus. Adding a bespoke smoke script for `execution_example.dag` would be pure duplication of what 2.2 already achieves -- not built. 2.5 **Full cascade re-verified green** with the new corpus in place: `bash dag/tests/run_tests.sh`, same discipline as step.5's own closing gate, now covering 7 corpora instead of 6. 2.6 **Closure**: end_to_end.md §11 U3.9a -> done; design.md untouched (this step proves an EXISTING design claim true, adds no new design); memory. Retro pair via step_gdiff. EXPLICITLY OUT OF SCOPE: - Any orchestrator code (`app/` untouched) -- U3.9a proves the SUBSTRATE accommodates the kind; P3's U3.1+ builds the real, programmatic compiler that produces instances like this one from a live run -> P3 - The `verification` kind (the gate graph of a VERIFYING pass) -- named in design.md alongside `execution` but not this step's ask -> later, if ever named - The `dependencies`/`todo` project-scope kinds -- conceptually close cousins of the ALREADY-PROVEN bootstrap kinds (Dependencies/TODO), lower priority than `execution` was -> later - An `oracle_gate` node -- no oracle tier exists in b3ubot's code yet; inventing one would misrepresent what's built (1's finding) -> P2/P3 - A dedicated smoke script for the new instance (2.4's own reasoning) -> never ## (3) Verification gates G1 THE INSTANCE IS VALID + LOADS: `cctdag load execution_example.dag --db ` succeeds; `cctdag list` shows the expected 4 nodes / 3 edges / kv counts. G2 CANONICAL FORM, VERIFIED NOT ASSUMED: `cctdag unload` on the freshly-loaded DB reproduces the COMMITTED file byte-for-byte (the same "load -> unload -> diff vs source" check every other corpus in this repo already passes). G3 4-WAY BYTE IDENTITY: the matrix leg of a full regression run shows `exec_example` at `4-way` (cctdag/Py/JS/Rust all OK, byte-identical to each other) -- zero SKIPs, matching every toolchain already proven present in step.5. G4 2-PASS ROUND-TRIP: the npass leg shows `exec_example` PASS -- pass1 counts == pass2 counts, snap1 byte-identical to snap2. G5 QUIRK LANDSCAPE: the quirks leg shows `exec_example` at the SAME E1=PRESENT/E2=ABSENT/E3=PRESENT baseline every other corpus already sits at -- no new SCB walker quirk surfaces on this new (small, hand-authored) corpus shape. G6 FULL CASCADE STILL GREEN: `bash dag/tests/run_tests.sh` shows "10 subproject PASS, 0 subproject FAIL, 0 SKIP" (unchanged subproject count -- this step adds a CORPUS, not a subproject) with the regression leg's own corpus count now 7, not 6. G7 SCOPE CONFINED TO dag/: no edit to `app/`, `adapters/`, `tests/`, or `design.md`'s own content. G8 Hygiene: b3ubot porcelain clean after each commit; retro via step_gdiff. ## (4) LOCKs C-6-A b3ubot porcelain clean after each commit. C-6-B SCOPE CONFINED TO dag/ (+ this step's own end_to_end.md closure, C-6-D): no orchestrator code, no `app/` change. C-6-C THE INSTANCE IS HONESTLY LABELED: `execution_example.dag`'s own `description` field states plainly that it is a hand- authored illustration modeling step.4's real `ask` flow, NOT a captured orchestrator run -- no field anywhere implies P3's orchestrator already exists or produced this file. C-6-D RE-PLANNING RECORDED IN THE SAME COMMIT: end_to_end.md's U3.9a row flips to `done` in the SAME commit as the retro that closes it (§12's own rule, already followed at step.5). C-6-E standing locks inherited: B-3 (no disclosure/no push), B-6 (deterministic T0/T1-class verification only, no AI-review tier). ## (5) Open questions Q-6-A Canonical-form production: hand-draft a rough version, then round-trip through `cctdag load`/`unload` and commit the UNLOAD output (LEAN -- `dag/instances/README.md`'s own documented practice for exactly this situation; guarantees byte-for-byte canonical form by construction rather than by careful hand-formatting) vs hand-format the committed file directly and hope it matches canonical form (fragile, no reason to risk it when the tool-verified path costs nothing extra). LEAN: round-trip through cctdag. Q-6-B Dedicated smoke script: NONE (LEAN -- see 2.4's reasoning; the general regression suite already covers everything a bespoke script would, and `d1Hierarchy.dag`'s own dedicated script predates that suite's existence, it isn't the CURRENT pattern to imitate) vs adding `dag/instances/tests/test_exec_example_smoke.sh` matching `d1Hierarchy`'s precedent for consistency. LEAN: none; registering in `corpora_list()` (2.2) is the current, non- duplicative way to get the same coverage. Q-6-C Node/edge kind vocabulary: `context_assembly` / `provider_run` / `human_gate` / `tool_call` (node kinds, LEAN -- lifted directly from design.md §2.13's own named task list, no invention) + `precedes` (edge kind, LEAN -- clearest available reading for "source must complete before target starts," and distinct from the bootstrap kinds' `consists_of`/`isomorphic_to`/etc. so a reader can tell at a glance this is a b3ubot-native kind, not a bootstrap one) vs inventing a different vocabulary. LEAN: as named, directly traceable to design.md's own words. ## (6) Acceptance - [x] `dag/instances/execution_example.dag` authored, round- tripped to canonical form (byte-identical on first attempt, diff-verified), committed (2.1, G1, G2). - [x] `regression/lib/corpora.sh` extended with the 7th corpus (2.2). - [x] `dag/instances/README.md` inventory + scope section updated (2.3); a stale bet3/bot/dag self-reference in the file's own header fixed while directly touching it. - [x] G3-G5: matrix/npass/quirks all show `exec_example` PASS (4-way, 1/4/3 counts matching exactly, baseline quirks), zero SKIP, verified by reading the regression report directly. - [x] G6: full cascade re-run, "10 subproject PASS, 0 FAIL, 0 SKIP," 7 corpora in the regression leg. - [x] G7 confirmed via git status: no edit outside `dag/`. - [x] Closure: end_to_end §11 U3.9a -> done + memory; retro pair via step_gdiff (2.6, G8). ## (7) Hash backfill SKELETON commit (this file + ledger row U3.9a -> active): fce666e BUILD commit (instance authored + registered + green): 289fd50 RETRO commit (retro pair + ledger done): (HEAD) End of skeleton.