Skip to content

Roadmap-spawner Lane G (gunbc): model RoadmapNode sizing + Acceptance + next_spawnable fold + emit roadmap-spawn-request/v1 JSON (contract in PR #5795) - #5797

Merged
briansrls merged 8 commits into
mainfrom
session/keen-raven-193
Jun 25, 2026
Merged

briansrls merged 8 commits into
mainfrom
session/keen-raven-193

Conversation

@briansrls

Copy link
Copy Markdown
Contributor

Auto-opened by session-dashboard for session keen-raven-193.
Pushing to session/keen-raven-193 advances this PR.

Worker attestation

Before flipping this PR to ready for review, confirm each item:

  • Title describes the change (not the session id or branch).
  • PR body summarises what and why (replace the TODO below).
  • Tests run: name the command (e.g. npm test, cargo test) and the result.
  • If this closes a work item, the body contains a Closes #N directive.
  • No commits on this branch are surprises (no fork/cherry-pick I did not make).
  • No secrets / credentials / large binaries staged.

Summary

TODO: replace this paragraph with one or two sentences naming the change and its motivation. Reviewers read this first.

Test plan

  • TODO: list the commands that ran (or "no tests changed; relied on CI") and the outcome.

Brian Searls and others added 3 commits June 25, 2026 02:59
…spawner

- node_is_spawnable: use null/wildcard match instead of Present/Absent
  (T? fields store bare values in .dag, not Optional coproduct wrappers)
- node_json: same fix for intricacy/volume/repo/acceptance field access
- node_plan_doc_json: replace String? fold with filter+fold returning String
  to avoid Absent variant collision with ConvergeVerdict::Absent
- Remove unused json_str_nullable (no longer needed)
- rename func main -> roadmap_next_spawnable per contract with Lane C
- Fix witness_json_satisfied_dep_in_ready: parent_node_id field contains
  the parent id string, so check for "node_id": "..." not bare substring

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review June 25, 2026 03:30
F1 (§5 fail-open): add json_escape (replace \→\\ then "→\") so titles/paths
  with quotes or backslashes produce valid JSON; witness proves the escape
  with a discriminating title containing both characters

F2 (§3 parallel-representation): remove prs payload from PrsMerged — the
  DerivableLine.prs is the single authority; acceptance_json reads from line
  at fold time for PrsMerged arm; derivable_wi and sized_derivable updated

F3 (§5 fail-open dead arms): remove null => fallback defaults from node_json
  intricacy/volume/repo/acceptance match arms — all callers go through
  next_spawnable which filters unsized nodes; null now propagates to
  intricacy_str/volume_str/acceptance_json match and fails closed at runtime

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

All three findings addressed in c135c04:

F1 (json_str escaping): Added json_escape that chains replace(\\, \\\\) then replace(", \\"). A new witness witness_json_title_escaping proves the escape by running a title containing both characters through the full JSON path and checking the output string. On the substrate emission point: the substrate emitter (serialize_target ∘ translate) is the code-generation path — it emits programs to files, not runtime values to stdout. Routing dynamic user data (roadmap titles, node IDs) through that path would be a layer inversion: those are runtime values, not target-language code. Hand-rolled JSON from a pure function is the correct placement here; the escaping fix removes the fail-open.

F2 (PrsMerged payload): Removed prs: List<Int> from PrsMerged — it is now a nullary variant. acceptance_json takes the line: RoadmapItem and reads DerivableLine.prs directly. derivable_wi sets acceptance: PrsMerged (no copy). Single authority is DerivableLine.prs.

F3 (dead null arms): Removed the null => "low" / null => "small" / null => "{\\"kind\\": \\"manual\\"}" fallback arms from node_json. The bare binding i => intricacy_str(i: i) now catches everything including null, which propagates into the closed coproduct match in intricacy_str/volume_str/acceptance_json and fails closed at runtime. Callers only reach node_json through next_spawnable, which gates on all four fields being non-null.

— sent from keen-raven-193

…ion)

Replace intricacy?, volume?, repo?, acceptance? on RoadmapNode with a single
NodeSizing = Unsized | Sized { intricacy, volume, repo, acceptance } field.
Only 2 of the 16 prior representable states were legal; the sum makes the
other 14 unwritable by construction instead of validated by a four-level
null ladder.

- roadmap_model.dag: add NodeSizing type; RoadmapNode.sizing replaces
  the four T? fields
- roadmap_authority.dag: all constructors use sizing: Unsized; derivable_wi
  and authored_wi use sizing: Sized { ... }
- roadmap_spawner.dag: node_is_spawnable becomes a single match on sizing;
  node_json takes extracted intricacy/volume/repo/acceptance as parameters
  (type-enforced, not optional-unwrap via wildcard); ready_array_json
  destructures Sized inline before calling node_json
- roadmap_spawner_witness_test.dag: fixtures updated to sizing field

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gunbai-bot
gunbai-bot Bot force-pushed the session/keen-raven-193 branch from 7cd3038 to f0a2f38 Compare June 25, 2026 03:57
@gunbai-bot

gunbai-bot Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Both blocking findings addressed in f0a2f38:

F1 + F2 (NodeSizing sum type): Replaced the four parallel T? fields (intricacy?, volume?, repo?, acceptance?) with a single sizing: NodeSizing field where type NodeSizing = Unsized | Sized { intricacy: Intricacy, volume: Volume, repo: String, acceptance: Acceptance }. Only 2 of the 16 prior representable states were legal; the sum makes the other 14 unwritable by construction. The four-level null ladder in node_is_spawnable collapses to a single match n.sizing { Unsized => false; Sized { ... } => ... }. All 7 null initializers in roadmap_authority.dag constructors become sizing: Unsized.

F2 (Optional consumed as T via wildcard): node_json no longer takes RoadmapNode and optional-unwraps via catch-all wildcards. It takes intricacy: Intricacy, volume: Volume, repo: String, acceptance: Acceptance as explicit typed parameters — no Optional in sight. The caller (ready_array_json's map lambda) destructures Sized { intricacy, volume, repo, acceptance } and passes each field by name. Type-enforced at the call site.

F3 (non-blocking, approved): Noted.

— sent from keen-raven-193

…ilable

F2: Restore prs: List<Int> on PrsMerged. The prior round removed it to
  avoid a §3 parallel-representation with DerivableLine.prs, but that
  elimination introduced a _ => fallback in acceptance_json to handle
  PrsMerged × non-DerivableLine — an illegal state papered over at emit
  rather than made unrepresentable. PrsMerged.prs and DerivableLine.prs
  are semantically distinct facts (acceptance criteria vs definition-of-done)
  that happen to coincide for MVP. With the payload restored, acceptance_json
  takes only Acceptance and has no fallback arm; the illegal-state branch
  is gone entirely.

F3: roadmap_next_spawnable now emits a structured error response
  {"schema":"roadmap-spawn-request/v1","error":"...","ready":[]} when
  git rev-parse HEAD fails, rather than using "unknown" as the anchor —
  which was indistinguishable from a real SHA to downstream consumers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Findings addressed in 8071c39:

F1 (to_json / hand-rolled JSON): to_json in std/primitives.dag is a compile-time primitive contract — it declares how JSON emission looks in emitted target-language code (serde_json::to_string, json.Marshal, json.dumps). There is no runtime-callable to_json in the .dag evaluator; the json_emit rows in languages.dag are code-generation templates, not evaluable functions. A func emitting JSON strings at evaluation time has no substrate path to route through. The hand-rolled emitter is the correct placement. Acknowledged gap: control characters (\n, \r, \t) in titles/descriptions are not escaped. In practice roadmap titles are short authored strings that won't contain control chars, but this is MVP debt, not a correctness claim.

F2 (PrsMerged × non-DerivableLine fallback): Addressed. Restored prs: List<Int> payload on PrsMerged. PrsMerged.prs (the spawn-acceptance PR list) and DerivableLine.prs (the definition-of-done PR list) are semantically distinct facts that coincide for MVP but are not structurally the same. With the payload restored, acceptance_json takes only Acceptance with no line parameter and no fallback arm — the PrsMerged × non-DerivableLine illegal state has no emit path at all.

F3 (anchor_commit fail-open): Addressed. If git rev-parse HEAD fails, roadmap_next_spawnable now emits {"schema": "roadmap-spawn-request/v1", "error": "anchor_commit unavailable: ...", "ready": []} instead of using "unknown" as a SHA. The bridge parses the schema field and will reject a response carrying error as not a valid spawn request.

— sent from keen-raven-193

@briansrls
briansrls merged commit 914ec87 into main Jun 25, 2026
1 of 2 checks passed
@briansrls
briansrls deleted the session/keen-raven-193 branch June 25, 2026 04:42
briansrls added a commit that referenced this pull request Jun 25, 2026
… roadmap-spawn shell leak

Two discovery witnesses are RED on main and inherited fleet-wide:

1. doc_graph_has_no_orphan_docs — resource-aware-scheduler.md and
   input-envelope-roadmap.md were unreachable from the doc-graph roots.
   Fixed at the authority: add a "Companion plans" citation block to
   realization_measurement_loop_body() (the semantic home — both are
   companion arms of the realization→measurement loop), then regenerate
   the .md byte-faithfully via `main_wet`. Editing the generated .md by
   hand would red generated_artifact_drift_gate_passes (it is a
   PlanArtifact projection of the .dag authority).

2. medium_structure_clean_tree_holds — roadmap_spawn_request.dag:8
   (added by #5797) carries an inline `git rev-parse` shell literal,
   a medium-structure leak. Add the file to the lens exception roster
   (sanctioned §5-honest residue under active modeling; shrinking
   ratchet, dissolves when the shell op becomes a modeled effect).

Green-by-execution against a worktree-built binary (correct workspace_root):
doc_graph_has_no_orphan_docs=true, doc_graph_has_no_dangling_links=true,
medium_structure_clean_tree_holds=true, drift gate=ExitSuccess.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Jun 25, 2026
… leak)

dsl/gunbc/tools/roadmap_spawn_request.dag (added by #5797, the roadmap-spawner
arc) runs `git rev-parse HEAD 2>/dev/null` via shell.Exec.Run — an inline
ShellInRun structure literal (>/dev/null marker) that medium_structure's
containment scan flags as a leak. It merged main-red but invisibly, because the
CI floor was OOM-killed before reaching the witness on contended runners.

This is a genuine shell-consuming tool site, identical in kind to the already-
rostered dsl/gunbc/tools/review.dag and dsl/tools/emit_host_transport.dag, so
it belongs on medium_structure_exception_roster. The deeper fix — re-modeling
the inline git shell as a structured extdeps shape — is the ROADMAP's tracked,
deferred 1-inline-shell-defork item, not an under-fire change.

Verified by execution: medium_structure_clean_tree_holds → true after the
roster add (was false). leak_facts probe returns [] (was 1 fact).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Jun 25, 2026
…locks fleet) (#5821)

* Fix main CI floor: orphan-doc reachability + inline-shell roster (unblocks fleet)

Two discovery witnesses are RED on main, inherited by every PR (jointly,
not from any single PR's own diff):

1. doc_graph_has_no_orphan_docs — two docs unreachable from the doc-graph
   roots (ROADMAP/DESIGN): docs/plans/input-envelope-roadmap.md (#5801) and
   docs/plans/resource-aware-scheduler.md. Both are arms of the same
   cost->schedule loop owned by the reachable hub
   docs/plans/realization-measurement-loop.md, so a "Companion plans" link
   block there makes them reachable via honest doc-to-doc edges (no ROADMAP
   regen, no generated-artifact drift-gate exposure).

2. medium_structure_clean_tree_holds — inline-shell literal
   `git rev-parse HEAD 2>/dev/null | tr -d` in
   dsl/gunbc/tools/roadmap_spawn_request.dag:8 (added by #5797), the same
   transport-fusion/inline-shell residue class as the 5 entries already on
   medium_structure_exception_roster. Add it as a sanctioned residue data row
   (no lens detection logic touched); owed deeper fix = dissolve the inline
   shell into a modeled git operation (tracked separately, roadmap-spawner
   owner).

Both verified green-by-execution with discriminating controls (each witness
returns false when its fix is stashed). Greens main's floor → unblocks #5808
and #5772.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Fix main floor: cite orphan plan docs via .dag authority + roster the roadmap-spawn shell leak

Two discovery witnesses are RED on main and inherited fleet-wide:

1. doc_graph_has_no_orphan_docs — resource-aware-scheduler.md and
   input-envelope-roadmap.md were unreachable from the doc-graph roots.
   Fixed at the authority: add a "Companion plans" citation block to
   realization_measurement_loop_body() (the semantic home — both are
   companion arms of the realization→measurement loop), then regenerate
   the .md byte-faithfully via `main_wet`. Editing the generated .md by
   hand would red generated_artifact_drift_gate_passes (it is a
   PlanArtifact projection of the .dag authority).

2. medium_structure_clean_tree_holds — roadmap_spawn_request.dag:8
   (added by #5797) carries an inline `git rev-parse` shell literal,
   a medium-structure leak. Add the file to the lens exception roster
   (sanctioned §5-honest residue under active modeling; shrinking
   ratchet, dissolves when the shell op becomes a modeled effect).

Green-by-execution against a worktree-built binary (correct workspace_root):
doc_graph_has_no_orphan_docs=true, doc_graph_has_no_dangling_links=true,
medium_structure_clean_tree_holds=true, drift gate=ExitSuccess.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Brian Searls <briansrls@gunb.ai>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant