Skip to content

docs(beta-delivery-ux): R1 stage kickoff — npm release mechanics (A6), name frozen against the live registry - #1336

Merged
artyhoo merged 11 commits into
stagingfrom
claude/beta-delivery-ux-pipeline-ac40e1
Aug 9, 2026
Merged

docs(beta-delivery-ux): R1 stage kickoff — npm release mechanics (A6), name frozen against the live registry#1336
artyhoo merged 11 commits into
stagingfrom
claude/beta-delivery-ux-pipeline-ac40e1

Conversation

@artyhoo

@artyhoo artyhoo commented Aug 9, 2026

Copy link
Copy Markdown
Owner

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.json keeps "private": true for 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-run run from packages/core/ on the current private:true manifest produced rules-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 getff returns an existing 0.0.1, maintainer artyhoo <yhooi2011@gmail.com>, created 2026-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.1 is a spent version, and @getff scope ownership is still unproven — a 404 on @getff/core proves 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:57 puts the rename in U9 (post-announce), and the stage's acceptance gate is name-independent because npm 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»; :98 gates U10 on this stage), and the «drop private:true in 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 with bin: getff exists in this repopackages/core ships six bins, all rules-as-tests-*. A6 does not ask R1 to build a CLI package, so the kickoff requires the freeze record to name where bin: getff will 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 surface destination-environment-verification.md:21 exists 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 existing pnpm-monorepo-cell.sh: it is the file-copy fallback path the §4 rollback doctrine requires to keep working, so a files allowlist 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 to stagingonly 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, and scripts/host-verify.sh:44 was 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» with private: 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 quoting docs/superpowers/specs/2026-07-23-beta-program-design.md:278 and :467 and the binding handoff, not from session recall; §0.2's registry facts are npm view output, and §0.3's blast radius is a git grep count.
  • .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.
  • Capability-commit gate (CLAUDE.md) — markdown only, so the *.md carve-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:1SWEPT-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.md likewise untouched and non-overlapping.
  • .claude/orchestrator-prompts/beta-delivery-ux/kickoff-s4.md:1SWEPT-CLEAN. R1 touches packages/core packaging; S4 owns scripts/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 pack tarball 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-ux resolves 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:119SWEPT-CLEAN and load-bearing to note: the gate + runner reach */kickoff.md only, so kickoff-r1.md is 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:43SWEPT-CLEAN, verified: !.claude/orchestrator-prompts/beta-delivery-ux/kickoff-r*.md already negates the ignore, so the file is tracked and will be visible on staging to /pipeline and aif. Without that line the whole PR would be a no-op for dispatch consumers.
  • packages/core/principles/12-ai-laziness-traps.test.ts:1SWEPT-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:71SWEPT-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:1604SWEPT-CLEAN: unmodified. The kickoff names them as the sibling shape and as the ci-success needs: precedent the new cell must follow, and §10 puts both in the executing stage's own backward-sweep list.
  • Open PRs feat(beta-delivery-ux): S4 — GLM one-button + aif guided install (A2) [FIDELITY STOP — rework needed] #1300 / feat(beta-delivery-ux): S4 run 3 — GLM one-button per kickoff §7b/§7c (A2) [FIDELITY STOP — base for run 4] #1322 (S4 runs 2-3, both DIRTY) and the unharvested aif task 5cfe83e2SWEPT-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 pack behaviour from npm pack --dry-run, the name facts from npm view getff, the 33-file blast radius from git grep -l, the contract's well-formedness from scripts/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 — task 5cfe83e2 reached done at 08:26Z and bases on 49eaafe804, which already contains #1323, so it is a superset rather than the feared revert; its disposition is unchanged by this PR.

Test 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).
…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
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).
@artyhoo
artyhoo merged commit e49f56e into staging Aug 9, 2026
42 checks passed
@artyhoo
artyhoo deleted the claude/beta-delivery-ux-pipeline-ac40e1 branch August 9, 2026 10:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant