docs(beta-delivery-ux): R1 stage kickoff — npm release mechanics (A6), name frozen against the live registry - #1336
Merged
Conversation
added 11 commits
August 8, 2026 11:39
…six #1284 parks (re-dispatch rev) Records the operator's 2026-08-08 batch: Park-1 schema = flat Candidate A + description field; Park-2 format = JSON (F-B' shell-sourced rejection recorded with the WHY); Park-3 economy review = whole line on executor tier, aif cap 1 iteration, external cold fidelity mandatory; Park-4 CC detection = CLAUDE_CODE_SESSION_ID env-presence capability check; Park-5 conditional park did not fire (live runtime-profiles probe, no substring collision); Park-6 ship the full functional set (create-worktree.sh + worktree-node-modules.sh + link-coordination.sh) under the same $1j gate, fresh-consumer smoke AC added. Unblocks the S2 re-dispatch (A4 presets + A5 status + A9 parts 2-3).
…ry-ux-pipeline-ac40e1
…GUOUS + host-verify contract Run 2 (aif task 92bf0019) returned FIDELITY STOP with KICKOFF-AMBIGUOUS (PR #1300). The kickoff's §7a never states how the aif runtime acquires the key VALUE: #1 stores only the env-var NAME in the profile, #4(ii) writes the value to ~/.config/getff/glm.env, and #3 requires the validation ping to run through the created profile. Verified against source: aif resolves the key from its own runtime process.env by that name (aif-handoff packages/runtime/src/resolution.ts:217-219, :247), and that env comes from the compose env-file (docker-compose.yml:15,59,94) — so glm.env is a dead end as written and #3 is unreachable without dereferencing the value, which #1 forbids. §7b closes it by binding the OUTCOME (value reachable in the aif runtime process env under the §7a #1 name, verified before the ping, honest objective-3 MISS on failure) while leaving the wiring mechanism to the worker as a §7 technical fork. It is marked as a dispatcher-authored completion, not an operator decision — the operator can override it. §7c carries run 2's settled corrections: PUT /projects/:id with a full body (aifHttp.ts:96) instead of the invented PATCH /project, no GET /projects/:id (:90), both defaults halves, ping through the profile, 10-skills.sh untouched. §4.1 adds the missing host-verify contract — the stage ships a shell helper, an install-time gate and a tests/install-sh suite, i.e. exactly the container-vs-host surface destination-environment-verification.md §1 exists for; the umbrella had no contract on any of its six kickoffs (exit 2). Prior-art: skipped — dispatch-input documentation only, no new capability; resolves an ambiguity in an existing stage kickoff against in-repo source citations.
… path, bind run-3 blockers §7d.0 retracts the §1 + §7a #1 instruction to re-read `~/code/aif-handoff/packages/api/src/routes/runtimeProfiles.ts` at stage entry. That path is host-only: the agent container mounts `$PROJECTS_DIR` (= `$PROJECTS_HOST_ROOT/projects`), so the repo root holding `packages/api/` sits one level above the mount. The instruction was unexecutable and run 3 guessed instead of parking — same class as state.md §2 decision 14. Replacement is an oracle the container can actually reach: the live aif API. §7d.1 pins two probes (required-field discovery + route-existence discovery) with the dispatcher's own 2026-08-09 outputs recorded for reproduction, not for trust. Run-3 blockers bound as corrections: §7d.2 `runtimeId`+`providerId` required in the create body; §7d.3 the ping route is `POST /runtime-profiles/validate` (the guessed `/<id>/v1/messages` → 404); §7d.4 §7b #1 still undelivered (the helper verifies reachability but never establishes it); §7d.5 companion install is prose in a field `engine.sh:18` early-returns past; §7d.6 (MAJOR) the suite mocks the non-existent endpoint and a body-blind 201, so §4.1 passed over §7d.2/§7d.3 — the stub becomes fail-closed with a paired-negative that fails on the run-3 helper, and `it.fails()`-as-delivery is banned. Adds T-BDU-D: unreachable instructed source → probe, else PARK; never substitute a plausible shape. Prior-art: skipped — kickoff prose revision only, no new capability; markdown is exempt from the capability-commit LOC triggers per CLAUDE.md.
…ry-ux-pipeline-ac40e1 # Conflicts: # .claude/orchestrator-prompts/beta-delivery-ux/kickoff-s4.md
…, and the container trap under it Own cold-QA of #1319 caught two defects in §7d.1. (1) It invented `$AIF`; the helper actually resolves `AIF_URL="${RUNTIME_BRIDGE_AIF_URL:-http://localhost:3009}"` (scripts/getff-glm-onebutton.sh:94), so the probe block now uses that name. (2) The more load-bearing half: that shipped default is unreachable from the agent container. Measured 2026-08-09 from aif-handoff-agent-1 — `http://localhost:3009/runtime-profiles` → curl exit 7 (000), `http://api:3009/runtime-profiles` → 200. `RUNTIME_BRIDGE_AIF_URL` is unset in the container, so an in-container run of the run-3 helper could not have reached aif at all, which is consistent with the suite mocking every call (§7d.6). §7d.1 now instructs the export for probing, explicitly forbids changing the shipped consumer default, and §4 item 1 must quote the base URL alongside any live end-to-end transcript. Prior-art: skipped — kickoff prose correction only, no new capability; markdown is exempt from the capability-commit LOC triggers per CLAUDE.md.
…r; the ping is two halves §7d.3 as first written told the worker to route §7a #3's «one real minimal model call» through `POST /runtime-profiles/validate` and left a falsifier for the case where that endpoint is only a reachability check. The dispatcher fired that falsifier itself rather than shipping the trap: - for `transport: "api"`, `validateClaudeConnection` returns ok after checking only that `apiKey` and `baseUrl` are non-empty — no network call (aif-handoff packages/runtime/src/adapters/claude/index.ts:468-479). Live 2026-08-09: `/validate` against the Qwen3.8-Max-Preview profile returned ok:true sub-second. - `POST /runtime-profiles/models` is not a substitute — it returned a static Claude catalogue (Sonnet 4.6, Opus 4.6) for a Qwen profile, so it is not querying the provider. So §7a #3 and §7c #3 cannot both be satisfied by one aif REST call. §7d.3 now binds both halves — `/validate` for the route proof, plus one 1-token-scale completion against the `baseUrl` READ BACK from that response (not a hardcoded `$GLM_BASE_URL`, which was run 2's W-3 defect). Provenance is stated as dispatcher-authored and operator-overridable, matching §7b. §7d.4 gains an exact, value-free verifier for §7b #3: `hasApiKey` is `Boolean(resolved.apiKey)` and `resolved.apiKey` is `normalizeString(env[envVarName])` off the aif runtime's own process.env (packages/runtime/src/resolution.ts:426, :217-219), so `hasApiKey:true` in the §7d.3(1) response IS proof that §7b #1's outcome was achieved — without dereferencing the key, without argv exposure. Prior-art: skipped — kickoff prose correction only, no new capability; markdown is exempt from the capability-commit LOC triggers per CLAUDE.md.
#1318 landed a §7d on the same file while this branch was in flight, so the block authored here is renumbered §7d → §7e and rebuilt on top of #1318 rather than over it. #1318's content is kept intact. Two corrections to §7d, both evidence-backed: §7e.0 — §7d step 1 orders `git merge feature/beta-delivery-ux-92bf00`, which is run 2 (task 92bf0019, 2026-08-08T01:04Z). Run 3 (task e65989fa, commit 53fce45, 14:51Z) is newer and already carries every §7c correction. Measured: getff-glm-onebutton.sh is 212 lines on 92bf00, still holding `PATCH "$AIF_URL/project"` (:135) and the vendor-direct ping (:171), versus 361 lines at 53fce45 with the profile-routed path in place. Basing on 92bf00 re-does ~150 accepted lines and re-opens two closed defects. §7e.3 — §7d.1 states `POST /runtime-profiles/validate` «exercises the route the flow just built» and is «exactly what §7a #3 / §7c #3 ask for». For `transport: "api"` it makes no network call at all — it checks only that apiKey and baseUrl are non-empty (aif-handoff packages/runtime/src/adapters/claude/index.ts:468-479); live, `/validate` against the Qwen3.8-Max-Preview profile returned ok:true sub-second, and /runtime-profiles/models returned a static Claude catalogue for that same Qwen profile. The ping is therefore split in two: /validate for the route proof, plus one 1-token-scale completion against the baseUrl read back from that response. Carried over unchanged in substance: §7e.1 (host-path retraction + the container base-URL trap — localhost:3009 → 000, api:3009 → 200), §7e.2 (runtimeId/providerId required), §7e.4 (§7b #1 undelivered; hasApiKey as its exact value-free verifier), §7e.5 (companion install in a dead field), §7e.6 (fail-closed mock, it.fails-as-delivery banned). §6 gains T-BDU-D and T-BDU-E. Prior-art: skipped — kickoff prose revision only, no new capability; markdown is exempt from the capability-commit LOC triggers per CLAUDE.md.
…ry-ux-pipeline-ac40e1 # Conflicts: # .claude/orchestrator-prompts/beta-delivery-ux/kickoff-s4.md
…ry-ux-pipeline-ac40e1
R1 is the last unstarted stage of the umbrella (S1-S5 all merged). This is its dispatch input, scoped from the spec (§4 A6 `:278-284`, §11 F-C' `:467-468`) and the binding input `launch-preannounce-track/s6-u10-handoff.md`. Three things the kickoff decides, because a worker cannot: 1. Dispatchability (§0.1) — R1 IS aif-dispatchable. `private: true` STAYS on `packages/core/package.json` for the whole stage; npm refuses to publish a private package, so the publish guard is mechanical rather than a reminder (attention-is-not-a-mechanism §1). Verified `npm pack --dry-run` works on a private package, so the tarball loop runs with the guard armed. 2. Name architecture (§0.2) — probed the live registry, not the spec's prose: unscoped `getff` ALREADY EXISTS at 0.0.1, published 2026-06-23 by the maintainer as a reservation stub. So the registry-side freeze is done, 0.0.1 is spent as a version, and `@getff` SCOPE ownership stays unproven (a 404 on `@getff/core` proves the package is free, not the scope) — that is an entry probe with a STOP attached. 3. Scope boundary (§0.3) — R1 does NOT execute the `@rules-as-tests/*` rename. Measured blast radius 33 tracked files / 55 occurrences; umbrella §3 puts the rename in U9 (post-announce), and the acceptance gate is name-independent because `npm i <tarball>` installs by path. Also recorded: two gates of the binding input's §0 are SUPERSEDED by the 2026-07-23 amendment (U9 no longer the rename window; the private-drop ordering), and the honest gap R1 does not close — U10's `npx getff init` gate needs a package with `bin: getff`, which does not exist in this repo and which A6 does not ask R1 to build. Host-verification contract declared (no opt-out): the new tarball cell plus the existing pnpm start cell, which is the file-copy fallback the §4 rollback doctrine requires to keep working. `scripts/host-verify.sh --list` parses both, exit 0. Prior-art: skipped — dispatch-input authoring only; a markdown kickoff adds no capability, no dependency, and no code module (CLAUDE.md doc-file carve-out).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds
.claude/orchestrator-prompts/beta-delivery-ux/kickoff-r1.md— the dispatch input for R1, the last unstarted stage of the umbrella (S1 #1173, S2 #1327, S3 #1272, S4 #1323, S5 #1285 are all merged). Scoped from the spec's own lines, not from recall:docs/superpowers/specs/2026-07-23-beta-program-design.md:278(A6) and:467(fork F-C′), plus the binding input.claude/orchestrator-prompts/launch-preannounce-track/s6-u10-handoff.md:1.369 lines, under the 600-line markdown gate.
The three calls a worker cannot make, made here
1. Dispatchability (§0.1) — R1 is aif-dispatchable, and the publish guard is mechanical.
packages/core/package.jsonkeeps"private": truefor the entire stage; npm refuses to publish a private package, so «the worker will not publish» stops being a reminder. Verified this does not block the work:npm pack --dry-runrun frompackages/core/on the currentprivate:truemanifest producedrules-as-tests-core-0.1.0.tgz(707 files / 1.2 MB packed / 4.8 MB unpacked), so the whole tarball-validation loop runs with the guard armed.2. Name architecture (§0.2) — probed the registry instead of trusting the spec's prose.
npm view getffreturns an existing0.0.1, maintainerartyhoo <yhooi2011@gmail.com>, created2026-06-23T07:50:39Z, description «getff.ai — name reserved. Real release coming soon.» So: the unscoped name is already ours (U11's «имена заморожены ДО публикации» is satisfied registry-side),0.0.1is a spent version, and@getffscope ownership is still unproven — a 404 on@getff/coreproves the package is free, not the scope. That last one is an entry probe with a STOP attached (§11), not an assumption.3. Scope boundary (§0.3) — R1 does NOT execute the
@rules-as-tests/*→@getff/*rename. Measured:git grep -l "@rules-as-tests/core"→ 33 tracked files / 55 occurrences (18.md, 8.ts, 7.json). The umbrella kickoff.claude/orchestrator-prompts/beta-delivery-ux/kickoff.md:57puts the rename in U9 (post-announce), and the stage's acceptance gate is name-independent becausenpm i <tarball>installs by path. So R1 ships a name-freeze record, not a rename commit.Two corrections to the binding input, and one gap left open
The
s6-u10-handoff.md§0 dependency graph predates the 2026-07-23 spec amendment. §0.4 of the kickoff records both supersessions rather than letting a worker rediscover them: U9 is no longer the rename window (.claude/orchestrator-prompts/getff-to-prod-meta-launch/kickoff.md:66— «post-announce; no longer gates U10»;:98gates U10 on this stage), and the «dropprivate:truein the same commit as the name-freeze» ordering is replaced by keeping it true throughout, which satisfies that instruction's own invariant more strongly. Everything else in that handoff — §2 audit, §2 allowlist + its CAVEAT, §3, §4 rollback doctrine, §5 — stays binding.Gap R1 does not close, stated rather than papered over (§0.5): U10's gate is
npx getff init, and no package withbin: getffexists in this repo —packages/coreships six bins, allrules-as-tests-*. A6 does not ask R1 to build a CLI package, so the kickoff requires the freeze record to name wherebin: getffwill live and to flag it as still blocking U10, and puts building it out of scope (§7).Host-verification contract
Declared, not opted out — a tarball's file list, bin runnability, and
npm pack's symlink handling all differ by machine, which is the container≠host surfacedestination-environment-verification.md:21exists for.bash scripts/host-verify.sh .claude/orchestrator-prompts/beta-delivery-ux/kickoff-r1.md --list→ parses both commands, EXIT=0. The second command is the existingpnpm-monorepo-cell.sh: it is the file-copy fallback path the §4 rollback doctrine requires to keep working, so afilesallowlist that breaks it is a regression however green the new cell is.§1.7 Forward-check applied
.claude/rules/kickoff-staging-placement.md:28— «author the kickoff → merge it tostaging→ only then … initiate an aif dispatch». This is why R1 is a PR before it is a dispatch; nothing is dispatched until this merges..claude/rules/destination-environment-verification.md:21+:32— the contract is declared, not opted out, andscripts/host-verify.sh:44was actually run against the file (exit 0, two commands listed) rather than the block being assumed well-formed. §4 of that rule names#optout-as-reflex; a stage with an executable deliverable and an opt-out is a review-time reject..claude/rules/attention-is-not-a-mechanism.md:29— §0.1 replaces «the worker will remember not to publish» withprivate: true, a deterministic refusal by npm. The kickoff says so in those terms..claude/rules/source-before-shape.md:29(scope surface) — the stage was scoped by reading and quotingdocs/superpowers/specs/2026-07-23-beta-program-design.md:278and:467and the binding handoff, not from session recall; §0.2's registry facts arenpm viewoutput, and §0.3's blast radius is agit grepcount..claude/rules/ai-laziness-traps.md:186(§3 kickoff-author obligations) — §8 cites the rule, enumerates 8 distinct canonical T-numbers (T2, T3, T10, T12, T14, T19, T20, T21), and adds two domain traps, exceeding the «≥1» floor.CLAUDE.md) — markdown only, so the*.mdcarve-out applies; the commit carries the escape-hatch trailer with a rationale over the 20-char floor.§1.7 Backward-check applied
Class of this change = stage-kickoff dispatch inputs under
.claude/orchestrator-prompts/beta-delivery-ux/. Surfaces enumerated from the class — most of them not in this diff — each verdicted:.claude/orchestrator-prompts/beta-delivery-ux/kickoff-s5.md:1— SWEPT-CLEAN, and used as the shape precedent (§-numbering, park-don't-guess block, PR-body gate section). Its §5 already reserves «npm release mechanics … → R1», so the new file claims no scope a sibling holds.kickoff-s1/s2/s3.mdlikewise untouched and non-overlapping..claude/orchestrator-prompts/beta-delivery-ux/kickoff-s4.md:1— SWEPT-CLEAN. R1 touchespackages/corepackaging; S4 ownsscripts/getff-glm-onebutton.sh+setup.d/**. No file is claimed by both..claude/orchestrator-prompts/beta-delivery-ux/kickoff.md:47(umbrella row R1) — SWEPT-CLEAN: the new file implements that row's gate verbatim («npm packtarball installs + runs in the matrix cell; publish itself NOT executed») and does not rewrite the umbrella. Separately GAP-FOUND, not fixed here (pre-existing, and the umbrella kickoff is a different owner):bash scripts/host-verify.sh beta-delivery-uxresolves to that file and exits 2 — no contract block. Same finding docs(beta-delivery-ux): S4 kickoff §7f — run-4 dispatch facts (run 3 harvested, 995e9c dead-end) #1324 recorded; bundling the fix would break one-concern-per-PR..claude/rules/destination-environment-verification.md:119— SWEPT-CLEAN and load-bearing to note: the gate + runner reach*/kickoff.mdonly, sokickoff-r1.mdis outside their automatic scope. That is why §6.1 names the explicit-path invocation instead of the<umbrella>form, and why the contract was run by hand at authoring..gitignore:43— SWEPT-CLEAN, verified:!.claude/orchestrator-prompts/beta-delivery-ux/kickoff-r*.mdalready negates the ignore, so the file is tracked and will be visible onstagingto/pipelineand aif. Without that line the whole PR would be a no-op for dispatch consumers.packages/core/principles/12-ai-laziness-traps.test.ts:1— SWEPT-CLEAN: it asserts the §-citation + T-enumeration on kickoffs; the new file satisfies both rather than needing an exemption..claude/hooks/check-kickoff-traps.sh:71— SWEPT-CLEAN: its case pattern is*/kickoff.md, so it did not fire on this write. Noted so the green edit is not misread as a passed gate — the T-floor here is met by authoring, not by the hook.tests/consumer-matrix/pnpm-monorepo-cell.sh:1+.github/workflows/audit-self.yml:1604— SWEPT-CLEAN: unmodified. The kickoff names them as the sibling shape and as theci-success needs:precedent the new cell must follow, and §10 puts both in the executing stage's own backward-sweep list.5cfe83e2— SWEPT-CLEAN as artefacts: R1 shares no file with them, so this PR neither strands nor supersedes anything. Pre-dispatch probe re-run on the merged branch (SLUG=beta-delivery-ux .claude/skills/dispatcher/helpers/probe-inflight.sh) →VERDICT: DONE-UNHARVESTED, with zero signals on R1 itself: no branch, no PR, no container worktree.Fidelity verdict
FIDELITY: skipped — dispatch-input kickoff (docs-only; this PR ships no aif-produced substrate, so it carries no Provenance section, same reading as #1319/#1324). Every load-bearing claim in the file is backed by a command run at authoring rather than carried over from the binding input: the 707-file over-ship and the private-package
npm packbehaviour fromnpm pack --dry-run, the name facts fromnpm view getff, the 33-file blast radius fromgit grep -l, the contract's well-formedness fromscripts/host-verify.sh --list(exit 0). Where the binding input's own numbers were stale (549 files, 2026-07-11) the kickoff says so and instructs the worker to re-measure.Authoring provenance
Authored in-session 2026-08-09 from
HANDOFF-2026-08-09-r2.md, whose §3 assigned exactly the two decisions resolved in §0.1 and §6.1. The handoff's §1 («a live worker is redoing merged work») was re-probed first and is stale — task5cfe83e2reacheddoneat 08:26Z and bases on49eaafe804, which already contains #1323, so it is a superset rather than the feared revert; its disposition is unchanged by this PR.