Skip to content

feat(beta-delivery-ux): S2 PARTIAL — T11 ship create-worktree.sh under env+ (stage stays open, 6 forks parked) - #1284

Merged
artyhoo merged 1 commit into
stagingfrom
feature/beta-delivery-ux-fd1d75
Aug 7, 2026
Merged

feat(beta-delivery-ux): S2 PARTIAL — T11 ship create-worktree.sh under env+ (stage stays open, 6 forks parked)#1284
artyhoo merged 1 commit into
stagingfrom
feature/beta-delivery-ux-fd1d75

Conversation

@artyhoo

@artyhoo artyhoo commented Aug 7, 2026

Copy link
Copy Markdown
Owner

beta-delivery-ux S2 — PARTIAL: T11 only (A9 part 1). Ships scripts/create-worktree.sh into consumer repos under the env+ profile (setup.d/10-skills.sh §1j, profile-gated env|factory|WITH_AIF_SUITE, copy_safe verbatim — no script rewrite, §4 REUSE). This PR does NOT close stage S2: A4 (presets), A5 (/pipeline status), A9 parts 2-3 (getff work + CC-detection) are parked on six maintainer forks — see Parked questions. The stage re-dispatches after the forks are answered.

Provenance: aif task fd1d75e1 (re-dispatch of the empty-done 2b84effa), harvested via host push after a pre-publish rebase onto current staging (single commit bb89f69a5e3a3e83d031, content identical — rebase only).

Cold fidelity audit (external seat, 2026-08-07): branch clean and honest, verdict REVISE at stage level (1 of 3 deliverables) → harvested per the audit's explicit «safe as partial» ruling with its two conditions applied: (1) this partial marking; (2) the parks surfaced to the maintainer below (the worker's register lived only in a gitignored container file + task record — the task closed done instead of manualReviewRequired, so without this PR body the parks were invisible to the queue).

Parked questions

Six forks from the worker's park register (beta-delivery-ux S2 — Parked forks register, task fd1d75e1), each with full Option-format in the register; condensed here as the durable record:

  • Park-1 — preset data SCHEMA (load-bearing; gates T4-T9): flat schema (A) vs structured (B). The schema is consumed across three seams (parse-override-flags.sh parser / SKILL §2.5 Step 5 predicates / marker emit) — guessed in isolation it breaks the other two.
  • Park-2 — preset data FORMAT: the pipeline references/ dir is all-markdown today; a data format would be the first non-md entry. Spec §11 F-B′ lists three options + a binding criterion.
  • Park-3 — economy preset reviewer-tier semantics: spec calls it «cheap reviewer» — cost/depth tradeoff is a maintainer value call.
  • Park-4 — CC harness detection for getff work: A9 must defer to CC-native worktree UX on CC; dual-implementation-discipline.md §4 forbids brand-name matching, so the capability-check signal is a genuine fork.
  • Park-5 — marker value economy vs aif (CONDITIONAL): fires only if a live runtime-profile probe shows a name collision; deferred to the marker-emit task (bridge was unreachable in the task context).
  • Park-6 — ship create-worktree.sh alone vs with soft-dep siblings (surfaced by the worker's own T15 backward-sweep, post-commit): T11 shipped alone in this PR; the sibling set is the fork.

Known minor (audit): the shipped setup.d/10-skills.sh §1j comment references the gitignored register path — unresolvable for staging readers; superseded by this PR body as the durable park record.

Fidelity verdict

FIDELITY: GO
Basis: .claude/orchestrator-prompts/beta-delivery-ux/kickoff-s2.md
Round: 1
Audited-SHA: 3a3e83d
GO is scoped to the T11 partial this PR actually ships (the stage-level verdict was REVISE — recorded above, stage stays open). Evidence: profile-gated §1j block setup.d/10-skills.sh:291 (branch numbering; gate env|factory|WITH_AIF_SUITE matches the F7-split precedent at setup.d/10-skills.sh:95); zero prior create-worktree refs in setup.d/ (audit grep); bash -n syntax-clean; LAYERS.md:10 monotonic-depth claim honoured. Audited-SHA note: the audit ran on bb89f69a5e; 3a3e83d031 is the same single commit rebased onto current staging with an identical diff (verified content-equal at rebase time).

…r env+ profile (A9 part 1)

Wiring-only slice of A9 part 1 (kickoff §4 binding — REUSE, do not rebuild).
Extends setup.d/10-skills.sh with §1j: gates create-worktree.sh shipping on
PROFILE=env|factory OR legacy WITH_AIF_SUITE, mirroring the F7-split pattern
at line 95. The script itself is unchanged — copied verbatim via copy_safe
to $PROJECT_ROOT/scripts/create-worktree.sh.

Closes the S1 inventory gap (kickoff §1 + LAYERS.md:10): create-worktree.sh
exists in the framework tree but shipped to NO profile before this commit
(verified — zero `create-worktree` references in setup.d/ prior to §1j).
This is the FIRST env-specific payload surface — the divergence between
--profile env and --profile core begins here.

Within-bounds fork resolved (kickoff §8 — YOURS to resolve): extend
10-skills.sh vs introduce a new layer file. Picked extend — minimal
footprint, matches the file's existing role as "shipped-to-consumer .claude/
+ scripts/ artefacts" (§1 skills + §1b-§1i hooks + this §1j workspace
script). The §1j naming parallels §1/§1b-§1i.

Smoke GREEN:
- bash -n setup.d/10-skills.sh — clean syntax
- PROFILE=core dry-run — does NOT ship create-worktree.sh (byte-identical
  invariant preserved per LAYERS.md:10)
- PROFILE=env dry-run — DOES ship: "[dry-run] would: ship
  scripts/create-worktree.sh (env+ profile payload)"

The full A9 (T11 + T12 + T13) waits on T12 resolution — `getff work <name>`
has a within-bounds sub-fork (bin/ does not exist; entrypoint shape) plus a
CC-detection park (Park-4) gating the CC-deferral branch. T11 ships
independently of those — no reason to hold the create-worktree.sh wiring
while T12 design is settled.

Parks (Park-1 through Park-5) documented locally in
.ai-factory/plans/beta-delivery-ux-parked-forks.md (gitignored —
.ai-factory/plans/* is per-consumer scaffolding per .gitignore:60). The
park register carries T1 pre-flight evidence + candidate statements;
maintainer picks A/B/C per park; executor resumes from the pick.

Prior-art: F7-split pattern at setup.d/10-skills.sh:95 (the established PROFILE-conditional shipping mechanism; this commit is the same pattern, extended from `factory`-only to `env|factory` for the env+ monotonic-depth surface — setup.d/LAYERS.md:10).
@artyhoo
artyhoo enabled auto-merge (squash) August 7, 2026 23:01
@artyhoo
artyhoo merged commit 1812a8c into staging Aug 7, 2026
44 of 45 checks passed
@artyhoo
artyhoo deleted the feature/beta-delivery-ux-fd1d75 branch August 7, 2026 23:12
artyhoo added a commit that referenced this pull request Aug 8, 2026
…six #1284 parks (re-dispatch rev) (#1295)

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).

Co-authored-by: Test <test@example.com>
artyhoo added a commit that referenced this pull request Aug 8, 2026
…kickoff rev 2 clobbered by #1285 squash-rebuild (#1298)

* fix(setup): restore §1j create-worktree env+ shipping clobbered by #1285 squash-rebuild

PR #1285 (ab280e1) was squash-rebuilt from a stale base and silently
reverted PR #1284 (1812a8c): the §1j block shipping
scripts/create-worktree.sh under env|factory profiles. Re-applies the
original 36-line insertion onto the current file; #1285's A8 three-arm
split is untouched.

Prior-art: skipped — restoration of already-merged reviewed content, no new capability

* docs(orchestrator): restore pnpm-flake kickoff rev 2 clobbered by #1285 squash-rebuild

Byte-exact restore of the rev-2 kickoff (PR #1283, 025aac0 — 3 rounds
of Phase -1 cold review, GO) that PR #1285's stale-base squash-rebuild
reverted to rev 1. The umbrella is closed; this repairs the historical
record its done.md cites.

Prior-art: skipped — restoration of already-merged reviewed content, no new capability

---------

Co-authored-by: Test <test@example.com>
artyhoo added a commit that referenced this pull request Aug 8, 2026
…es to outdated base blobs (#1285 class) (#1307)

* feat(hooks): pr-stale-revert check pair + tests

Deterministic PR-time gate for the stale-base squash-rebuild clobber class
(incident PR #1285, repaired by #1298): a PR that sets a tracked file to a blob
BYTE-IDENTICAL to an OLDER ancestor version of that file on the base branch is
silently discarding merged work. Nobody reproduces an old blob by hand by
accident, so the signature is mechanical and needs no judgment.

Every existing channel misses the class by construction: GitHub's "require
branches to be up to date" is POSITIONAL (the branch WAS up to date — the stale
content arrived as the PR's own change), no CI test covered the reverted content
(a merge queue shares that blindness), and the 21 reverted lines sat inside a
2498-insertion diff, i.e. bare attention.

- pr-stale-revert.ts: pure decision logic (git injected via StaleRevertGit) plus
  the PR-GLOBAL escape token `STALE-REVERT: intended — <rationale >=20 chars>`
  for deliberate restorations like #1298. The real provider is parameterised by
  cwd so tests and the calibration harness exercise the shipped code path.
- pr-stale-revert-bin.ts: CI glue reading PR_BODY / BASE_REF / BASE_SHA /
  HEAD_SHA. Fails CLOSED on its own misconfiguration — an unset env var, an
  unresolvable SHA, or an unresolvable merge-base all produce an EMPTY file set
  that is indistinguishable from "clean", so they error instead of passing.
- Tests: 38 arms, including two paired-negative arms over the real #1285
  archaeology and an end-to-end run of the shipped provider and the bin against
  a throwaway fixture repository reproducing the incident shape.

Declared v1 non-goals (rule §8 + SSOT #241 carry the revisit triggers): renames
are not followed, deletions are not flagged, and a stale file the PR ALSO edits
yields a novel blob and is undetectable by whole-file equality — in #1285 itself
setup.d/10-skills.sh would not flag; only the untouched kickoff.md does.

Calibration over the 150 staging squash commits back from 004864d: exactly 2
flags, both true positives (ab280e1 = #1285, 4fe20cc = #1298), zero false
positives.

Prior-art: prior-art-evaluations.md#241 (BUILD — no upstream detects PR-sets-file-to-outdated-base-blob; 9-phrasing WebSearch + DeepWiki git/danger-js + native-gates check all miss; see entry).

* ci(workflows): stale-revert-in-pr-diff gate on staging PRs

Wires packages/core/hooks/checks/pr-stale-revert-bin.ts as a PR-time job on
base=staging PRs, mirroring pr-body-fidelity.yml (same pinned action SHAs, node
22, npm ci --prefix packages/core, job id == job name so the operator registers
the string GitHub actually reports).

Two load-bearing details:

- The checkout sets BOTH `fetch-depth: 0` AND `ref: head.sha`. Without the
  explicit ref a `pull_request` checkout lands on the synthetic
  `refs/pull/N/merge` commit, where git has ALREADY merged the newer base
  content over the stale file — the signal is erased and the gate fails OPEN in
  exactly the scenario it exists for. Same trap documented at audit-self.yml's
  pr-commit-trailers job.
- Unfiltered events (the pr-body-prior-art.yml model): a `paths:` filter would
  un-fail-close exactly the docs/config PRs where this class hides. `edited` is
  included so adding the STALE-REVERT token re-runs the check.

The gate is ADVISORY until the operator registers `stale-revert-in-pr-diff` as a
required check in the staging branch-protection set; CI cannot verify that
registration (GITHUB_TOKEN cannot read branches/*/protection — the KNOWN
LIMITATION recorded in workflow-integrity.yml). Deterministic git plumbing, no
LLM. Verified with actionlint and zizmor (no findings).

Prior-art: skipped — CI wiring only for the detector shipped in the preceding commit; no new capability, no new dependency, no new module.

* docs(rules): git-conflict-merge-forward §8 stale-base rebuild hazard

Adds §8 for the sibling failure of the merge-forward class: the branch is NOT
behind — its CONTENT is. A squash-rebuilt PR (fresh fork + older tree committed
over it) silently reverts every file the base moved in between, which is how
#1285 discarded #1283 and #1284 before #1298 repaired it.

The section records the incident, the mechanical signature (head blob
byte-identical to an OLDER ancestor version on the base branch), the shipped
PR-time gate and its escape token, and both v1 non-goals with revisit triggers:
(a) renames/deletions, and (b) the edited-stale-file false negative — a stale
file the PR also edits yields a novel blob and is invisible to whole-file
equality, with setup.d/10-skills.sh in #1285 as the worked example.

Also reconciles the header's Class-B claim: «a CI principle test is structurally
unreachable» scopes the merge-forward PROCEDURE (a command choice, invisible to
repo CI); §8's hazard is PR-diff content lineage, which IS mechanically visible
at PR time and now has its own CI channel. The Authoritative-for enumeration
gains §8.

§1.7: forward — the new channel is a deterministic gate, not «a reviewer will read the diff», per attention-is-not-a-mechanism.md:15, and it fires at the earliest channel where the signature exists at all (a PR diff), with zero LLM per no-paid-llm-in-ci.md; the Class-B ceiling claim it qualifies is at .claude/rules/git-conflict-merge-forward.md:5, and the Authoritative-for enumeration was extended in the same edit per doc-authority-hierarchy.md §2-§3. Backward — sibling surfaces in the «agent-facing git/push gotchas» class are §2's trailer-gate range fix, the CLAUDE.md Harness-gates bullet, and the harvest/egress pre-publish rebase carve-out in §3: §8 extends the file's scope from «un-conflicting a branch» to «the branch looks fine and is silently stale», contradicting none of them; no other rule claims authority over PR-diff content lineage.

Prior-art: skipped — rule prose amendment documenting a gate shipped two commits earlier; no new capability, no dependency, no module.

---------

Co-authored-by: Test <test@example.com>
artyhoo added a commit that referenced this pull request Aug 8, 2026
… (aif) + self-gen docs sweep (tab) (#1309)

* docs(beta-ai-docs-agnosticism): meta-launch kickoff — stage gates, DECOMPOSE routing, autonomous gate shut

Generated by `/pipeline beta-ai-docs-agnosticism`. Plan-currency CURRENT at 6f11473;
all three umbrella §0 dispatch gates resolved mechanically (A-S3 #1272 + A-S1 #1173 merged;
the three inflight-check signals are two merged umbrella-B branches and this session's own
worktree). Live anchor spot-check re-confirms C3's negative-existence claim: principle 21
walks agents/*.md only, so no probe enumerates .claude/skills today.

Routing: umbrella DECOMPOSE/Mode-B; S1 PAIR -> S2 || S3 PAIR x2 (Mode-B worktrees) -> S4 SOLO.
Autonomous aif dispatch is gated shut — the bridge answers (/runtime-profiles 200) but the
Lever-1 container probe returns AGENT_MAX_REVIEW_ITERATIONS=UNSET, which per /pipeline §5
#autonomous-dispatch-without-park is UNVERIFIED, not passing. Maintainer-paste tabs until set.

state.md stays gitignored per the /pipeline §10 lifecycle split.

* docs(beta-ai-docs-agnosticism): S2 + S3 stage kickoffs — skills probe (aif) + self-gen docs sweep (tab)

Stage 2 fan-out dispatch inputs, authored per the meta-launch launch-table (PR #1293).

S2 (kickoff-s2.md, branch beta-c-s2-skills-probe) — C3 skills agnosticism probe.
Dispatch channel: autonomous aif-handoff — Lever-1 verified live 2026-08-08
(docker exec aif-handoff-agent-1 -> AGENT_MAX_REVIEW_ITERATIONS=1, set via
docker-compose.override.yml, operator GO). Carries the verbatim Lever-2
park-don't-guess block (dispatch-gate grep target), a host-verify contract
(run green on host: 2/2), single ownership of night-mode/SKILL.md, and the
dynamic-enumeration falsifier (T-BADC-S2-A).

S3 (kickoff-s3.md, branch beta-c-s3-selfgen-docs) — C5 self-generating docs sweep.
Dispatch channel: maintainer-paste tab (operator decision 2026-08-08 — fork-heavy
D7 ownership judgments; aif precedent on design-heavy stages: #1300 FIDELITY STOP,
#1284 PARTIAL). Corrects the umbrella premise with evidence: the zcode-doctrine §3
hand-sync already landed via #1156 (2026-07-25, post-spec), so the first patch
proposal is the D7 generated-section CONVERSION of the doctrine's status columns
(00-rule-index.md precedent), not a content re-sync. host-verify run green on
host: 3/3. T10 inventory-before-migration is the binding order.

Both kickoffs declare the S2||S3 file-ownership split (night-mode + probes vs
doc migrations + auditor) against #shared-workdir-parallel.

---------

Co-authored-by: Test <test@example.com>
artyhoo added a commit that referenced this pull request Aug 8, 2026
…GUOUS + host-verify contract (#1310)

* docs(beta-delivery-ux): S2 kickoff §8a — operator resolutions of the 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).

* docs(beta-delivery-ux): S4 kickoff §7b/§7c — close run-2 KICKOFF-AMBIGUOUS + 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.

---------

Co-authored-by: Test <test@example.com>
artyhoo added a commit that referenced this pull request Aug 8, 2026
… read (api stamps the task row) (#1313)

* docs(beta-ai-docs-agnosticism): meta-launch kickoff — stage gates, DECOMPOSE routing, autonomous gate shut

Generated by `/pipeline beta-ai-docs-agnosticism`. Plan-currency CURRENT at 6f11473;
all three umbrella §0 dispatch gates resolved mechanically (A-S3 #1272 + A-S1 #1173 merged;
the three inflight-check signals are two merged umbrella-B branches and this session's own
worktree). Live anchor spot-check re-confirms C3's negative-existence claim: principle 21
walks agents/*.md only, so no probe enumerates .claude/skills today.

Routing: umbrella DECOMPOSE/Mode-B; S1 PAIR -> S2 || S3 PAIR x2 (Mode-B worktrees) -> S4 SOLO.
Autonomous aif dispatch is gated shut — the bridge answers (/runtime-profiles 200) but the
Lever-1 container probe returns AGENT_MAX_REVIEW_ITERATIONS=UNSET, which per /pipeline §5
#autonomous-dispatch-without-park is UNVERIFIED, not passing. Maintainer-paste tabs until set.

state.md stays gitignored per the /pipeline §10 lifecycle split.

* docs(beta-ai-docs-agnosticism): S2 + S3 stage kickoffs — skills probe (aif) + self-gen docs sweep (tab)

Stage 2 fan-out dispatch inputs, authored per the meta-launch launch-table (PR #1293).

S2 (kickoff-s2.md, branch beta-c-s2-skills-probe) — C3 skills agnosticism probe.
Dispatch channel: autonomous aif-handoff — Lever-1 verified live 2026-08-08
(docker exec aif-handoff-agent-1 -> AGENT_MAX_REVIEW_ITERATIONS=1, set via
docker-compose.override.yml, operator GO). Carries the verbatim Lever-2
park-don't-guess block (dispatch-gate grep target), a host-verify contract
(run green on host: 2/2), single ownership of night-mode/SKILL.md, and the
dynamic-enumeration falsifier (T-BADC-S2-A).

S3 (kickoff-s3.md, branch beta-c-s3-selfgen-docs) — C5 self-generating docs sweep.
Dispatch channel: maintainer-paste tab (operator decision 2026-08-08 — fork-heavy
D7 ownership judgments; aif precedent on design-heavy stages: #1300 FIDELITY STOP,
#1284 PARTIAL). Corrects the umbrella premise with evidence: the zcode-doctrine §3
hand-sync already landed via #1156 (2026-07-25, post-spec), so the first patch
proposal is the D7 generated-section CONVERSION of the doctrine's status columns
(00-rule-index.md precedent), not a content re-sync. host-verify run green on
host: 3/3. T10 inventory-before-migration is the binding order.

Both kickoffs declare the S2||S3 file-ownership split (night-mode + probes vs
doc migrations + auditor) against #shared-workdir-parallel.

* docs(beta-ai-docs-agnosticism): Lever-1 = 4, set where it is actually read (api stamps the row)

Operator decision: raise the review-iteration ceiling to 4 — a cheap executor seat
should keep fixing its own review findings rather than parking them on a human.

Corrects a real defect in the prior wiring, measured not assumed. autoReviewHandler.ts:125
reads `refreshedTask.maxReviewIterations ?? env.AGENT_MAX_REVIEW_ITERATIONS` — the TASK ROW
wins — and api/schemas.ts:79 stamps that row at creation from the *api* container's env.
So the previous agent-only setting was INERT for every API-created task: `GET /tasks`
showed the 5 most recent rows all carrying mri=3 while the agent container reported 1.
Same failure class as the COORDINATOR_MAX_CONCURRENT_TASKS incident already documented in
docker-compose.override.yml ("the line above NEVER took effect").

Now set on BOTH services; verified api=4, agent=4, GET /settings maxReviewIterations=4.

Scope honesty recorded in both kickoffs: this is a GLOBAL ceiling, not GLM-only. Nothing
pins a task to the GLM seat without a `<!-- bridge-profile: -->` marker
(runtime-bridge/src/kickoff.ts:30 -> AifHandoffBackend.ts:221), and Tier-2 kickoffs omit
that marker by rule — verified absent in all three umbrella kickoffs by running the
extractor's own regex; resolvedDefaultTaskRuntimeProfileId is null. The tier-vs-pinning
tension is surfaced as an open maintainer fork, not decided here.

meta-launch §4c flipped GATED SHUT -> OPEN accordingly (both legs verified).

---------

Co-authored-by: Test <test@example.com>
artyhoo added a commit that referenced this pull request Aug 8, 2026
… path, bind run-3 blockers (#1319)

* docs(beta-delivery-ux): S2 kickoff §8a — operator resolutions of the 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).

* docs(beta-delivery-ux): S4 kickoff §7b/§7c — close run-2 KICKOFF-AMBIGUOUS + 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.

* docs(beta-delivery-ux): S4 kickoff §7d — retract the unreachable host 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.

* docs(beta-delivery-ux): S4 kickoff §7d.1 — name the real base-URL var, 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.

* docs(beta-delivery-ux): S4 kickoff §7d.3/§7d.4 — fire my own falsifier; 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.

---------

Co-authored-by: Test <test@example.com>
artyhoo added a commit that referenced this pull request Aug 9, 2026
…, name frozen against the live registry (#1336)

* docs(beta-delivery-ux): S2 kickoff §8a — operator resolutions of the 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).

* docs(beta-delivery-ux): S4 kickoff §7b/§7c — close run-2 KICKOFF-AMBIGUOUS + 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.

* docs(beta-delivery-ux): S4 kickoff §7d — retract the unreachable host 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.

* docs(beta-delivery-ux): S4 kickoff §7d.1 — name the real base-URL var, 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.

* docs(beta-delivery-ux): S4 kickoff §7d.3/§7d.4 — fire my own falsifier; 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.

* docs(beta-delivery-ux): R1 stage kickoff — npm release mechanics (A6)

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).

---------

Co-authored-by: Test <test@example.com>
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