Skip to content

Add read-only hosted qualification of the Rendering raw and provider knowledge routes (Refs #4822) - #4836

Merged
EHotwagner merged 3 commits into
mainfrom
routine/4822-rendering-routes
Oct 23, 2026
Merged

EHotwagner merged 3 commits into
mainfrom
routine/4822-rendering-routes

Conversation

@EHotwagner

@EHotwagner EHotwagner commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Source half of the next #4822 slice: the external Rendering raw and provider knowledge routes, typed and default, on the current published tuple. Route coverage: #4822 (comment). The delivery shape is the same as R3 (#4828) and R4 (#4832).

What this adds

  • tests/new-sdd-workspace/knowledge-rendering-routes-public.py: eight rows (provider/raw × app/game × typed/omitted) plus 10 pure causal controls, wired into new-sdd-workspace-selftest.yml. Helpers come from the accepted R3 adapter's sealed bytes (3269ebd7…).
  • .github/workflows/rendering-routes-public-acceptance.yml: dispatch-only, contents: read, public nuget.org, isolated HOME, no token in any child, 60-minute timeout. The job id rendering-routes-acceptance is unique.
  • A roadmap section in docs/roadmaps/tsdd-knowledge-wizard.md.

Rows (each step is asserted by the adapter)

Typed rows (provider and raw), common steps

  • All typed rows compose fs-gg-project-knowledge --lifecycle typed-sdd without --force, which adds exactly the two CI files with package bytes.
  • Each then makes the normal foreground initial commit. Canonical files, CI and the pin are tracked; the cache is not.
  • Each passes the maintained Qualify remaining public knowledge routes and retained FSharp compatibility migration #4723 probe, the ALL-shared export after private capture, and the ordinary pinned checker at 10,485,760 bytes and +1, with no residue.
  • Every product byte and mode is preserved except the declared knowledge paths, and the .gitignore keeps its original content as a prefix.

Provider typed (app, game)

  • fsgg-sdd scaffold --provider rendering with the immutable descriptor (Templates 24f3c307, SHA-256 pinned) records typed-sdd, the profile and producer 2.4.0.
  • It creates the store and guide but no knowledge CI.
  • On a copy with an owner-authored knowledge workflow, the overlay refuses (exit 73) and changes nothing.

Raw typed (app, game)

  • dotnet new fs-gg-ui --lifecycle typed-sdd from the original UI.Template 0.32.3 creates no .fsgg/, no .config/ and no knowledge.
  • The caller adds the overlay and a local manifest pinning only SDD 2.4.0.
  • The checker refuses before initialization without changing bytes.
  • knowledge initialize is explicit and idempotent. This proves standalone knowledge readiness, not a Typed SDD skeleton.

Omitted (provider and raw, app and game)

  • These rows record sdd: from the descriptor default for provider, and from the packed lifecycle default read from the archive for raw.
  • No store and no knowledge CI. The overlay without a typed lifecycle emits nothing.

Archives must match their pins:

  • SDD.Cli 2.4.0
  • UI.Template 0.32.3 747f33eb0242783f67b2462d8ca137b14f36bb4133bd0a3d4ca98ca8ad93dfe6
  • Workspace.Template 0.19.3
  • Coord.Cli 0.94.0

Checked locally

  • --source-controls 10/10.
  • A full local run of the operation at this source passed: 270 commands, all 8 rows, all process groups absent. Every non-zero exit is an intended refusal (27). This is development evidence only.
  • The timeout, paths-coherence, pipefail and job-uniqueness checks pass.

Head 0b9f0801 is rebased onto main 6e6fb9b9. It adds one commit answering the 429e03a7 review:

  • B1: every row now asserts the lane the template actually emitted. It reads the created product's lifecycle-scaffolding-pending.md heading: # Typed SDD lifecycle scaffolding pending or # Lifecycle scaffolding pending (sdd lane).
  • N1: the raw checker refusal before initialization must be for the missing guide.
  • N2: only the provider's own scaffold installs UI.Template, and the run asserts nothing preinstalled it.
  • N3: omitted rows also run the overlay with --lifecycle sdd.
  • N4: raw-game-typed repeats the owner-workflow collision refusal.
  • Controls 10/10. A local full run passed with 274 commands.

Head 47913274 adds one commit on top of the accepted 0b9f0801. It moves the omitted rows' --lifecycle sdd overlay call into overlay_argv(False, 'sdd'), with a control (critic nit). The push also gives change-completeness a fresh event: its rerun had kept the earlier body, which contained a closing keyword, now reworded. Controls pass 10/10 (the new assertions extend an existing control).

One local run hit a transient 180-second dotnet tool restore hang. The adapter's finite command budget refused it, and there is no retry by design. The immediate local rerun passed with 274 commands.

Observations for the reviewer

  • Provider-default rows keep .fsgg/knowledge-guide.md, which SDD initialization seeds for every lifecycle. The store and CI are absent.
  • Both raw and provider products carry lifecycle-scaffolding-pending.md. Raw typed rows are standalone knowledge-ready, not Typed SDD workspaces.
  • Atlas capture for these route facts is still owed. I'm deferring it until after hosted acceptance, so that unaccepted runtime claims aren't recorded as facts. fdev retains the gap.

Merge. The .github merge hold (Wizard publish) is ON. This PR will not be merged until fdev releases it. A workflow_dispatch workflow can only be dispatched once it is on the default branch, so the hosted run follows the merge.

Not done. No runtime acceptance is claimed. Still open on #4822 after this slice: the Wizard fable-game rows, which depend on #4811 / Wizard 0.22, and the Rendering Wizard default rows. #4822 stays open; this PR only references it (Refs).

🤖 Generated with Claude Code

@EHotwagner

Copy link
Copy Markdown
Contributor Author

Independent review: PR #4836 at 429e03a77539d5699624450e70b202bd1b430968

Verdict: REJECT (request changes). There is one blocking finding, and it has a small fix. Required CI was also still queued when I read it.

The reviewed candidate is the PR head 429e03a7, which is one commit on top of 8eb86bf6 (#4832). It changes 4 files: the adapter, the dispatch-only workflow, the selftest line and the roadmap section.

Blocking

B1. The raw rows never bind the created product's effective lifecycle, so the raw typed/omitted axis can pass vacuously.
tests/new-sdd-workspace/knowledge-rendering-routes-public.py L198-201 (raw branch of run_row) and L282-283.

For raw rows, the only evidence about lifecycle is raw_argv (the flag that was passed) and packedDefaults.lifecycle == 'sdd', which is a property of the template definition, not of the created row. Everything the raw branch checks is identical for typed-sdd and sdd:

  • no .fsgg/
  • no .config/
  • knowledge-state {false,false,false}

The later knowledge steps do not depend on the raw lifecycle at all. Suppose fs-gg-ui silently aliased --lifecycle typed-sdd to sdd, which tsdd-knowledge-receivers.md §Supported creation boundaries forbids. All four raw rows would still pass. The claim that "a raw typed-sdd flag does not itself create .fsgg/ or knowledge" (§Direct templates and composition; roadmap L1394) only means something if the product really was created in the typed lane.

§Candidate and installed acceptance also requires binding the effective lifecycle per creation. The roadmap's "These record sdd" (L1407) holds for provider rows, through provenance, but no raw row records anything.

The product does record its lifecycle. In my run the sentinel differed by lane:

  • typed-sdd: lifecycle-scaffolding-pending.md starts with # Typed SDD lifecycle scaffolding pending, and the post-action notice reads "Typed SDD guard notice".
  • sdd: it starts with # Lifecycle scaffolding pending (sdd lane), and the notice reads "ADR-0056 §Decision.2: the sdd-lane guard NOTICE".

Fix: in the raw branch, assert and record the sentinel's lane from the created bytes (typed vs sdd), and add a pure control that refuses the mismatched lane. The sentinel is not in the preservation allow-list, so it is already pinned through use.

Non-blocking

  • N1 (L230). The raw pre-initialization checker refusal accepts any non-zero exit. In my run it refused for the intended reason (Missing .fsgg/knowledge-guide.md; initialize knowledge ...), but the adapter does not assert that, so a crashing checker would also satisfy it. Asserting the message would make the step causal.
  • N2 (L279). FS.GG.UI.Template::0.32.3 is installed into the isolated HOME before the provider rows run. The provider's own dotnet new install <source> therefore runs against an already-registered package rather than a clean template cache. The single-registration and SHA checks still bind the identity, so this is not a correctness defect, but it differs from a first-time provider caller. Consider a note, or running the provider rows before the raw-only install.
  • N3 (L207, L343). Omitted rows apply the overlay with no --lifecycle, which hits the overlay's own none default. They do not pass the product's effective sdd. The contract says "Omission and other lifecycles emit nothing". Passing --lifecycle sdd in the omitted rows, or adding it as a second call, would match a caller composing for an ordinary sdd product. The template condition (lifecycle != "typed-sdd" excludes all files) makes the outcome predictable, so this is not blocking.
  • N4. The authored-workflow collision control runs only on provider-app-typed. That is enough to show the overlay refuses, but the raw route's collision is not exercised. This is fine given the Templates-level qualification.

What I verified

  • Head and tree. The PR head is 429e03a7 (via gh pr view). The worktree was clean before and after my run.
  • R3 seal. knowledge-retained-upgrade-public.py has sha256 3269ebd7…160f, which equals R3_SHA. The PR leaves it unchanged, and it was last changed by 65a71ad2 (Add read-only hosted qualification of the retained knowledge upgrade R3 (Refs #4822) #4828).
  • Rendering descriptor. providers/rendering.providers.yml at Templates 24f3c307 has sha256 ff49732a…7fc2, which equals DESCRIPTOR_SHA. It has a single source: FS.GG.UI.Template::0.32.3, a single templateId: fs-gg-ui, and lifecycle default sdd. It is identical on current Templates origin/main.
  • Public nuget.org bytes. I downloaded each package independently and hashed it. All match the pins:
    • UI.Template 0.32.3: 747f33eb…dfe6
    • SDD.Cli 2.4.0: 1df2e74f…921f
    • Workspace.Template 0.19.3: 9594ec20…72a2
    • Coord.Cli 0.94.0: e68a2134…c332
  • Packed definitions. In UI.Template 0.32.3 the lifecycle default is sdd and the profile default is app. In Workspace.Template 0.19.3, the fs-gg-project-knowledge overlay emits only the workflow and the checker, and only when lifecycle == typed-sdd. Its default is none.
  • Composition. The sequence matches the Templates contract:
    • Provider: the provider creates the tool manifest, store and guide but no CI. The caller overlay runs without --force and adds exactly the two CI files with package bytes. Then comes the foreground initial commit.
    • Raw: create, overlay, local SDD 2.4.0 pin, explicit knowledge initialize (idempotent), then commit. The roadmap correctly calls this "standalone knowledge readiness, not a Typed SDD skeleton".
  • --source-controls. 8/8 passed, with TMPDIR on disk.
  • Full --run. I ran it locally (dotnet 10.0.401, isolated HOME, on-disk TMPDIR, token variables unset). state: passed, 8/8 rows, 270 commands. In the report:
    • All five identities match.
    • Provider provenance shows typed-sdd/sdd with the requested profile and producer 2.4.0.
    • The collision returns exit 73 with "Overwrite" and leaves owner bytes unchanged.
    • Every typed row has probe findings=4 and history=2. The checker passes at exactly 10,485,760 and refuses at +1 with the budget diagnostic.
    • Preservation allows only the declared knowledge paths, .gitignore, the cache, and the raw-only .config/dotnet-tools.json.
    • Omitted rows end with store=false and ci=false. Provider omitted rows keep the guide.
  • Read-only and no token. These claims hold:
    • Every child receives only R.environment, which carries no GITHUB_TOKEN/GH_TOKEN/FSGG_PACKAGES_TOKEN and sets GIT_CONFIG_GLOBAL=/dev/null.
    • The workflow has contents: read only and persist-credentials: false on all three checkouts. It is dispatch-only and its only output is an artifact.
    • Its shape mirrors the accepted R3/R4 workflows.
  • Required CI. At my single read, all required checks were QUEUED. Final-candidate CI must still pass. Hosted-artifact acceptance remains fdev's after merge and dispatch, as the roadmap states.

A fix for B1 changes the head, and the new head needs a fresh exact-candidate decision.

-- fdev-critic

EHotwagner and others added 2 commits October 23, 2026 11:55
…knowledge routes (Refs #4822)

Eight rows on SDD.Cli 2.4.0 / FS.GG.UI.Template 0.32.3 / Workspace.Template 0.19.3: provider and raw
creation x app/game x explicit typed-sdd/omitted lifecycle. Typed rows compose the project-knowledge
overlay without --force (and refuse it over an owner-authored workflow); raw typed rows add the caller's
local SDD pin and explicit knowledge initialization. Each typed row passes the normal initial commit, the
maintained typed probe, the ALL-shared export and the 10 MiB checker boundary while preserving product
bytes; omitted rows stay sdd without knowledge or CI. A dispatch-only, contents:read workflow runs it on
public feeds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fusals (Refs #4822)

Address the #4836 review. B1: every row asserts the lane the template actually emitted, from the product's lifecycle-scaffolding-pending heading. N1: the raw pre-initialization checker refusal must be for the missing guide. N2: only the provider scaffold installs UI.Template. N3: omitted rows also run the overlay with --lifecycle sdd. N4: a raw typed row repeats the owner-workflow collision refusal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@EHotwagner
EHotwagner force-pushed the routine/4822-rendering-routes branch from 429e03a to 0b9f080 Compare October 23, 2026 09:55
@EHotwagner

Copy link
Copy Markdown
Contributor Author

Independent review: PR #4836 at 0b9f08016210b183a2d0b6541a4684defe4ddf8b

Verdict: ACCEPT. There are no blocking findings. Merge is still gated on required CI passing on this exact head, and the .github hold stays in place.

This review replaces my earlier REJECT at 429e03a7 (comment 6362136098) and covers the new head only.

Candidate correspondence

  • The PR head is 0b9f0801 (via gh pr view). It equals the local worktree HEAD, and the worktree is clean.
  • 4eba0595 is a rebase of 429e03a7 onto main 6e6fb9b9. git range-diff reports it as patch-identical (=).
  • Main's intervening commits (8eb86bf6..6e6fb9b9) touch only the Creator/release successor scripts and tests. They do not touch the adapter, the workflows, the roadmap, the R3 adapter or the console helper.
  • The sealed inputs are unchanged on this base:
    • R3 adapter: 3269ebd7…160f, which equals R3_SHA
    • console helper: afc9de40…4873

How the earlier findings were dispositioned (repair commit 0b9f0801)

  • B1, resolved. check_lane() (L114-119) reads the first line of the created product's lifecycle-scaffolding-pending.md. It checks that line against LANE_HEADINGS[typed] for all eight rows, before any overlay or caller step. The sentinel is outside the preservation allow-list, so it is also pinned through use. The control test_effective_lane_comes_from_the_created_product refuses a wrong heading in both directions and a missing file, so the control is causal. In my run, every typed row recorded # Typed SDD lifecycle scaffolding pending and every omitted row recorded # Lifecycle scaffolding pending (sdd lane). The raw lifecycle axis is now bound to observed bytes.
  • N1, resolved. check_pre_init_refusal requires a non-zero exit, the "Missing .fsgg/knowledge-guide.md" reason and unchanged bytes. Its control refuses a traceback, exit 0 and changed bytes. My run recorded {exitCode: 1, reason: missing-knowledge-guide} for both raw typed rows.
  • N2, resolved.
    • The up-front UI install is gone. The adapter asserts that no UI.Template registration exists before rows run.
    • It requires that ROWS[0] is a provider row.
    • It binds the registration and its hash only after that row, recorded as installedBy: provider-scaffold.
    • The command journal confirms the order: dotnet new install runs only for Workspace.Template (seq 4), and the scaffold comes next (seq 5).
  • N3, resolved. Omitted rows call the overlay both without --lifecycle and with --lifecycle sdd (seq 69/133/203/274 exit 0). The combined effect must be empty.
  • N4, resolved. raw-game-typed repeats the owner-workflow collision: exit 73, "Overwrite", bytes unchanged.
  • Docs. The roadmap now says the lane comes from the product's own heading, not from flags or packed defaults. That matches the code.

What I verified on this head

  • --source-controls: 10/10 passed, with TMPDIR on disk.

  • Full --run. I ran it from public nuget.org (dotnet 10.0.401, isolated HOME, token variables unset). state: passed, 8/8 rows, 274 commands. All five identities match their pins:

    • SDD.Cli 2.4.0: 1df2e74f…
    • Workspace.Template 0.19.3: 9594ec20…
    • UI.Template 0.32.3: 747f33eb…
    • restored SDD 2.4.0
    • Coord.Cli 0.94.0: e68a2134…

    I had already confirmed these against bytes downloaded independently from nuget.org.

  • The provider/raw composition, the 10,485,760 / +1 checker boundary, the preservation rules, and the read-only, no-token workflow posture are unchanged from my previous review and still hold.

Non-blocking

  • The --lifecycle sdd overlay call is written inline (L225) rather than through overlay_argv, so no argv control covers it. The run journal shows it executes, so this is cosmetic.

Gates outside this verdict

  • Required CI. At my single read on this head, most checks were QUEUED. 7 had succeeded. The CANCELLED entries appear to be superseded runs. Required CI must be green on 0b9f0801 before merge.
  • Hosted acceptance. This remains fdev's after merge, dispatch and independent review of the hosted artifact, as the roadmap states. A source merge establishes no runtime result.

Any change to the head needs a fresh exact-candidate decision.

-- fdev-critic

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

Copy link
Copy Markdown
Contributor Author

Independent review: PR #4836 at 47913274c8bb21b753780df8a6d8f4eab55aa907

Verdict: ACCEPT. There are no blocking findings. Before merge, routine-eligibility must pass on this exact head (see below), and the .github hold stays in place.

This review replaces my ACCEPT at 0b9f0801 (comment 6362307821) and covers this head only.

Candidate correspondence

  • The PR head is 47913274 (via gh pr view). It equals the local worktree HEAD, and the worktree is clean.
  • It is exactly one commit on top of 0b9f0801, which I accepted. The commit changes only knowledge-rendering-routes-public.py (+10/-3).

The new commit

  • overlay_argv(typed, lifecycle=None) now builds the omitted rows' --lifecycle sdd call (L101-105, L228). This answers my earlier nit.
    • The guard lifecycle in (None, 'sdd') and not (typed and lifecycle) refuses typed+sdd and non-typed+typed-sdd with overlay-lifecycle.
    • The control in test_argv_selects_route_profile_and_lifecycle_explicitly pins the exact sdd argv and the typed argv, and refuses both invalid combinations. It is causal.
  • The emitted argv is byte-identical to the previous inline call, so runtime behaviour is unchanged.
  • Small correction to the author's report. The new assertions extend an existing test, so --source-controls reports 10 tests here, not 11. All 10 pass, and nothing is missing.

What I verified on this head

  • --source-controls: 10/10 passed, with TMPDIR on disk.
  • Full --run. I ran it from public nuget.org (dotnet 10.0.401, isolated HOME, token variables unset). state: passed, 8/8 rows, 274 commands.
    • All five identities match their pins: SDD.Cli 2.4.0, Workspace.Template 0.19.3, UI.Template 0.32.3 (installedBy: provider-scaffold), restored SDD 2.4.0 and Coord.Cli 0.94.0.
    • Every row's lane, read from the created product's heading, matched: typed rows typed-sdd, omitted rows sdd.
    • Both owner-workflow collisions (provider-app-typed, raw-game-typed) exited 73 with no change.
    • The omitted rows' --lifecycle sdd overlay calls (seq 69/133/203/274) exited 0 with no effect.
  • Everything else I verified at 429e03a7 and 0b9f0801 still holds and is untouched by this commit: public nuget.org byte identities, descriptor and R3 seals, the composition sequence, the 10,485,760 / +1 boundary, preservation, and the read-only, no-token workflow.

Gates outside this verdict

  • Required CI. At my single read, 63 checks succeeded and change-completeness was SUCCESS. Two routine-eligibility runs had FAILED. The log of run 39939701377 shows fetched head 0b9f0801… differs from event head 47913274…: an event/fetch race between the PR-body edit and the push, not a defect in the candidate. Before merge, routine-eligibility must pass on 47913274, either through a fresh event or a rerun that fetches this head.
  • Hosted acceptance. This remains fdev's after merge, dispatch and independent review of the hosted artifact. A source merge establishes no runtime result.

Any further change to the head needs a fresh exact-candidate decision.

-- fdev-critic

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