Skip to content

feat(beta-delivery-ux): S4 — GLM one-button + aif companion install, with the three false greens fixed - #1323

Merged
artyhoo merged 8 commits into
stagingfrom
harvest/s4-995e9c
Aug 9, 2026
Merged

feat(beta-delivery-ux): S4 — GLM one-button + aif companion install, with the three false greens fixed#1323
artyhoo merged 8 commits into
stagingfrom
harvest/s4-995e9c

Conversation

@artyhoo

@artyhoo artyhoo commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Ships S4 (GLM one-button + aif companion guided install, spec A2 + A1) and fixes the three false greens that made the shipped flow unable to complete a single live run.

What the review found

Run 4's suite reported 25/25 green. Firing the helper's own create body at the live aif returned HTTP 400. Three independent false greens, each verified on 2026-08-09 rather than reasoned about:

  1. Create body omitted runtimeId + providerId. createRuntimeProfileSchema requires both (no .optional(), no .nullable()). POST /runtime-profiles with the helper's exact body → 400 ZodError, path: ["runtimeId"] and path: ["providerId"]. With curl -sf, step A always returned non-zero, so every run fell through to guided-manual — an objective-3 MISS by the kickoff's own §4 item 5. Fourth consecutive round carrying this defect (scripts/getff-glm-onebutton.sh:102).

  2. transport was unset, which voided step C. Omitting it resolves the profile to SDK, and for SDK transport validateClaudeConnection returns ok unconditionally. Measured against a non-persisted inline profile via POST /runtime-profiles/validate:

    body result
    no transport {"ok":true,"transport":"sdk","hasApiKey":false} ← passes with no key at all
    transport:"api" {"ok":false,"transport":"api","hasApiKey":false,"message":"Missing API key (expected env var: …)"} ← real gate

    One missing field separated a ping that cannot fail from a ping that gates.

  3. Step C read the verdict from the exit code. /runtime-profiles/validate answers HTTP 200 even when validation fails — the verdict lives in .ok. Measured: HTTP 200 {"ok":false,"message":"Missing API key …"}, and curl -sf exits 0 on it. Step C now parses .ok.

Honesty corrections

Comments claimed the validate call performs «profile resolution + key lookup + model call in one shot» and «returns auth-error» if the key is unreachable. It does neither — for transport: "api" it checks only that apiKey and baseUrl are non-empty (aif-handoff packages/runtime/src/adapters/claude/index.ts:468). POST /runtime-profiles/models is not a substitute either: it returned a static Claude catalogue (Sonnet 4.6 / Opus 4.6) for a Qwen profile, so it does not query the provider.

§7a #3's real model call is now an explicit §7 PARK, not a claimed delivery — with both options and the binding each one breaks recorded in the source: calling the vendor from the helper puts the key in curl's argv (forbidden by §2 constraint 1 / §7b #4, run-2 watch-list W-2), and no aif endpoint performs a completion through a stored profile.

§7b #1 is stated honestly rather than claimed closed. The helper prints wiring instructions; it does not wire. What changed is that an un-applied instruction is now a hard MISS at step C instead of a green run — detection, not wiring, and the comment says exactly that.

Suite made fail-closed (25 → 33 checks)

The stub had two defects that hid all of the above:

  • the /validate arm was dead code*"/runtime-profiles"* matched first, so step C was tested against the create response. shellcheck -S warning flags this class automatically (SC2221/SC2222) and fires on the original file; it simply is not pointed at tests/install-sh/** today.
  • the create arm answered success regardless of body, hiding defect 1.

Now: ordered arms, an explicit endpoint allowlist (each entry dated by live probe), a body rule mirroring the live 400, and paired negatives N1/N1b/N2/N2b/N3 that fail on run 3's invented ping path and run 4's create body.

Gates shown to discriminate, not merely to pass — each fix reverted in turn:

reverted fix suite
remove transport PASS=32 FAIL=1
remove runtimeId/providerId PASS=30 FAIL=3
drop the .ok parse PASS=30 FAIL=3
restored control PASS=33 FAIL=0

Held CLEAN — delivered by run 4, not redone here

§7c #1 PUT /projects/:id with a full body + GET /projects read-back; §7c #3 no direct vendor ping; §7d.2 clone URL repointed to the lee-to upstream; and the companion consent surface, which run 3 had left as prose in a field setup.d/engine.sh:18 early-returns past — now a real [y/N] prompt (setup.d/aif-handoff-guided-install.sh:55) with consent/decline paths and env-level degradation as a designed success, wired at install.sh:1139. refresh-covers-full-delivery 6/6 PASS, so no refresh drift.

Host-verify

bash tests/install-sh/glm-onebutton.test.sh   → PASS=33 FAIL=0
bash tests/install-sh/refresh-covers-full-delivery.test.sh → PASS=6 FAIL=0
shellcheck -x -S warning (helper + suite)     → clean

Run on the host, per destination-environment-verification.md §1 — the worker's own green was the thing under suspicion.

§1.7 Forward-check applied

Complies with attention-is-not-a-mechanism.md §1: every fix here is a gate that fails, not a warning someone must read — the three reverted-fix runs above are the evidence it discriminates, and it.fails()-as-delivery is not used anywhere (tests/install-sh/glm-onebutton.test.sh:33). Complies with no-paid-llm-in-ci.md (deterministic bash + curl, zero API-billed calls). Complies with destination-environment-verification.md §1 — the declared host-verify command was run on this host, and its own blind spot is what the fail-closed stub closes. Complies with language-discipline.md §1 (machinery in English). Key-handling invariant (§2 constraint 1 / §7b #4) re-verified: the value never enters the profile, argv, or any log line, asserted at tests/install-sh/glm-onebutton.test.sh:283.

§1.7 Backward-check applied

Class of this change = shell helpers that talk to the aif REST API, plus their stub-based suites. Enumerated beyond this diff: setup.d/bridge-guided.sh:11SWEPT-CLEAN, it only probes /health and never POSTs a profile, so the required-field and 200-with-ok:false hazards do not reach it; tests/install-sh/bridge-guided.test.sh:1SWEPT-CLEAN, its stub has a single arm with no shadowing pair (shellcheck -S warning reports no SC2221/SC2222); packages/runtime-bridge/src/cli/aifHttp.ts:71SWEPT-CLEAN for the ordering hazard (typed client, not a case stub) and already carries the null-budget refusal there. GAP-FOUND (surfaced, not fixed here — separate concern): .github/workflows/audit-self.yml:479 runs tests/install-sh/glm-onebutton.test.sh as a test, but no shard runs shellcheck over tests/install-sh/**, which is why SC2221/SC2222 never fired on run 4's dead stub arm; pointing shellcheck at that directory is a one-line workflow change and belongs in its own PR.

Fidelity verdict

FIDELITY: skipped — no cold fidelity auditor was run in this session, so a GO would be unearned; this is a dispatcher-side repair of a round-4 STOP, self-reviewed against live probes against the running aif, with every claim carrying a command output or an in-repo file:line and the three reverted-fix runs standing as the non-vacuity evidence for the new gates. A cold audit before merge is still the stronger path and is not blocked by anything here.

Test added 8 commits August 8, 2026 00:55
…-install helper + entry verification

S4 (spec §4 A2 + A1) — the GLM executor tier connects with ONE human-entered key, and the
factory profile UPGRADES the aif-handoff companion row from S1's detect+instruct declaration
to a consented guided INSTALL.

Three artefacts:
- scripts/getff-glm-onebutton.sh — the one-button automation (detect | explain | provision).
  Executor of the flow = the consumer's in-session AI agent reading an INSTALL-FOR-AI step
  (the aider pattern). detect probes /runtime-profiles for a Z.ai-shape profile; explain
  prints the one explanation block (z.ai Coding Plan, env-file path); provision runs REST
  create + per-mode defaults + validation ping (real model call per §7a #3).
  KEY-HANDLING INVARIANT (§4 item 2 — binding): the helper references ONLY the env-var NAME
  ANTHROPIC_AUTH_TOKEN; the value lives only in the untracked env file the human creates.
- setup.d/aif-handoff-guided-install.sh — the consented guided INSTALL for the factory profile.
  Sources bridge-guided.sh for bridge_diagnose (SSOT per dual-implementation-discipline.md §7);
  states: up (no-op, detect-first) | docker (consented git clone + docker compose up -d +
  30s health wait) | native (instruct start) | absent (env-level degrade). Decline → env-level
  degradation is a DESIGNED SUCCESS PATH (kickoff §6 T-BDU-B).
- docs/meta-factory/research-patches/2026-08-08-s4-glm-onebutton-entry-verification.md — the
  entry verification record. Bridge unreachable + schema inaccessible at build time (both
  explicit §7 park triggers); §7a resolutions implemented on operator authority (binding) with
  falsifiers UNRESOLVED at build time. engine.sh does NOT gate on @Profile: (comment-only
  convention — the helper is invoked from install.sh under PROFILE=factory).

Prior-art: skipped — bash helpers under scripts/ and setup.d/, not packages/; not a capability-commit per CLAUDE.md definition (no new package.json dependency, no new file ≥50 LOC under packages/core/<new-dir>/, no new file ≥80 LOC under packages/).
… gate + INSTALL-FOR-AI one-button step + tests

Four wiring changes completing S4's scope:
- setup.d/companions.manifest — aif-handoff row install_cmd upgraded from the S1 placeholder
  to the real pointer: setup.d/aif-handoff-guided-install.sh under --profile factory. The
  @Profile: factory marker (S1) is preserved; engine.sh contract unchanged (kind=external-service
  → print + return 0; actual handling routes through the helper invoked from install.sh).
- install.sh — factory gate added after the setup.d layer loop (after line 1115). Gating
  matches setup.d/10-skills.sh:95 exactly: PROFILE=factory OR WITH_AIF_SUITE set. The helper
  is invoked via `bash ... || true` (decline → env-level degrade is a designed-success path).
- INSTALL-FOR-AI.md — new "GLM executor one-button (factory profile ONLY)" subsection under
  the depth-profiles section. Documents the detect→explain→provision flow the consumer's
  in-session AI agent runs; carries the key-handling invariant sentence.
- tests/install-sh/glm-onebutton.test.sh — 20-assertion firing test covering: (a) detect
  cases (present|missing|bridge-unreachable), (b) explain output (env-file path + env-var name
  + cost line + parent dir), (c) provision cases (happy path, step-A failure, preflight
  env-file missing), (d) key-handling invariant grep (no echo/printf/log/_log/_warn references
  the env-var name; indirect expansion present in curl header). Snapshot baselines
  byte-identical (companions.manifest is not part of the installed-tree fingerprint).

Stage boundary respected: setup.d/10-skills.sh and .zcode/ are NOT touched (S5's sole-editor
scope for skill-set wiring). packages/runtime-bridge is NOT touched (S5 vendoring scope).

Prior-art: skipped — wiring edits + bash test; not a capability-commit per CLAUDE.md definition (no new package.json dependency, no new file ≥50 LOC under packages/core/<new-dir>/, no new file ≥80 LOC under packages/).
…PUT /projects/:id, profile-routed validate, key-reachability preflight

Round 3 rework of scripts/getff-glm-onebutton.sh — fixes the four §7c dispatcher
defects from run-2 plus the §7b key-reachability gap (resolved 2026-08-09):

- §7c #1: replace invented PATCH /project (singular, no id) with PUT /projects/:id
  using a full createProjectSchema body (jq-mutated from GET /projects response).
  Aligns with packages/runtime-bridge/src/cli/aifHttp.ts:96 which documents
  PUT /projects/:id as the only parallelEnabled write path.
- §7c #2: write BOTH Task+Review halves of per-mode defaults, with distinct
  preserve-vs-park branches for the Plan half based on defaultPlanRuntimeProfileId
  read from GET /projects. Conflating them silently overwrites a consumer's
  existing top-tier or silently writes a null.
- §7c #3: route the validation ping through POST $AIF_URL/runtime-profiles/validate
  with payload {profileId:$id} — proving key + model + route together via aif.
  Run-2 pinged the Z.ai vendor URL directly, bypassing the runtime the flow built.
- §7c (implicit): drop the invented x-api-key header attribution.
- §7b: print docker-compose env_file wiring instruction for the consumer/AI agent
  to apply (the aif runtime resolves ANTHROPIC_AUTH_TOKEN from its own process.env
  by NAME; a file at $GLM_ENV_FILE is invisible unless deployment loads it). Honor
  §7b #2 design-call: print, do NOT auto-patch deployment files.

Key-handling invariant (kickoff §4 item 2) holds: helper references ONLY the
env-var NAME ANTHROPIC_AUTH_TOKEN (line 31); value lives only in untracked env
file (line 29); post-source reachability check at line 249 uses ${!GLM_ENV_VAR:-}
indirection — never expands the value into a log/echo line. Pre-flight grep
returns empty (rc=1).

INSTALL-FOR-AI.md updated to reference the §7b key-reachability wiring the
helper prints. Tests updated with happy-path stubs for GET /projects, POST
/runtime-profiles, PUT /projects/:id, POST /runtime-profiles/validate, plus
regression guards for all four §7c defects. 25/25 PASS.

Hook: worker-container mirror at /tmp/fix-hook/pre-commit (per memory
project_handoff_root_owned_pre_commit_err path 3 — mktemp substitutes for
root-owned /tmp/pre-commit-err; substantive probes unchanged). markdownlint-cli2
+ prettier skipped (npm install blocked in container); maintainer-side pre-commit
+ CI on PR branch carries those gates.

Prior-art: skipped — refactor only, no new capability (round 3 repairs run-2's
existing payload per dispatcher §7c/§7d resolutions; no new dep, no new module).
…eam + drop park language (§7d.2)

Two changes per §7d.2 dispatcher resolution (host-verified 2026-08-09):

setup.d/aif-handoff-guided-install.sh:
- Default AIF_HANDOFF_REPO_URL → https://github.com/lee-to/aif-handoff.git
  (gh api confirmed 2026-08-09: sst-aif/aif-handoff returns 404;
   lee-to/aif-handoff returns 200). The sst-aif reference is retained only
   in the comment documenting the host-side verification rationale.
- Park language ("PARKED — repo URL unverified") dropped — the §7d.2
  resolution closes the run-1 park with host-verified evidence.
- # shellcheck source= directive restored to the canonical
  setup.d/bridge-guided.sh form (run-2 had drifted it).

docs/meta-factory/research-patches/2026-08-08-s4-glm-onebutton-entry-verification.md:
- Prepended scope slug (<!-- scope:s4-glm-onebutton-entry-verification -->)
  as the first line per principle 10's research-patch annotation requirement.
- Item 5 verdict updated from "PARKED — repo URL unverified" to
  "RESOLVED — default upstream is lee-to/aif-handoff" matching the
  §7d.2 host-verified resolution.

Hook: worker-container mirror at /tmp/fix-hook/pre-commit (per memory
project_handoff_root_owned_pre_commit_err path 3).

Prior-art: skipped — refactor only, no new capability.
…on.test.sh into audit-self shard A (§7d.3 #2)

Two cleanup/wire changes per §7d dispatcher resolutions:

setup.d/companions.manifest:
- Added MINOR-4 resolution comment above the aif-handoff row recording that
  kind=external-service rows have an informational-only `install` field —
  setup.d/engine.sh companion_step returns 0 for this kind without consulting
  it. Actual install routes via install.sh → setup.d/aif-handoff-guided-install.sh
  (mirrors the existing runtime-bridge row precedent). Closes the §7d.4 MINOR-4
  run-2 finding that the manifest carried placeholder install semantics.

.github/workflows/audit-self.yml:
- Added `bash tests/install-sh/glm-onebutton.test.sh` step to the shard A
  sequence (after the bridge-guided test). Closes §7d.3 #2 — the new test
  existed but was not wired into CI. Indentation 6/8 spaces matches adjacent
  entries per ci-tool-pinning §1 (no version-pinned tool install needed —
  bash is system-provided).

Hook: worker-container mirror at /tmp/fix-hook/pre-commit (per memory
project_handoff_root_owned_pre_commit_err path 3).

Prior-art: skipped — refactor only, no new capability.
…ngle live run — three false greens

Round-4 review found the shipped flow 400s on its first live call while its own suite reported
25/25 green. Three independent false greens, each verified against the live aif on 2026-08-09.

1. Create body omitted the two schema-REQUIRED fields. `createRuntimeProfileSchema` requires
   `runtimeId` and `providerId` (no .optional(), no .nullable()). Firing the helper's exact body:
     POST /runtime-profiles -d '{"name":…,"defaultModel":…,"apiKeyEnvVar":…,"baseUrl":…}'
       → HTTP 400 ZodError, path ["runtimeId"] and ["providerId"]
   With `curl -sf`, step A therefore always returned non-zero and the flow always fell back to
   guided-manual — an objective-3 MISS on every run, by the kickoff's own §4 item 5.

2. Transport was unset, which voided step C entirely. Omitting `transport` resolves the profile to
   SDK, and for SDK transport validateClaudeConnection returns ok unconditionally ("using session
   auth"). Measured against a non-persisted inline profile:
     no transport  → {"ok":true,  "transport":"sdk", "hasApiKey":false}   ← passes with NO key
     transport=api → {"ok":false, "transport":"api", "hasApiKey":false,
                      "message":"Missing API key (expected env var: …)"}  ← real gate
   One missing field was the difference between a ping that cannot fail and a ping that gates.

3. Step C read the verdict from the exit code, but /runtime-profiles/validate answers HTTP 200 even
   when validation fails — the verdict is in `.ok`. Measured: `HTTP 200 {"ok":false,"message":
   "Missing API key …"}` and `curl -sf` exits 0 on it. Step C now parses `.ok`.

Also corrected: comments claiming the validate call performs "profile resolution + key lookup +
model call" and that it "returns auth-error" — it does neither. §7a #3's real model call is now an
explicit §7 PARK with both options and the binding each one breaks (argv exposure of the key vs. no
aif endpoint that completes through a stored profile), instead of being reported as delivered.

§7b #1 is stated honestly rather than claimed closed: the helper prints wiring instructions and does
not wire. What changed is that an un-applied instruction is now a hard MISS at step C instead of a
green run — detection, not wiring, and the comment says so.

Test suite made fail-closed (25 → 33 checks). The stub had two defects that hid the above:
  - the /validate arm was DEAD CODE — `*"/runtime-profiles"*` matched first, so step C was tested
    against the CREATE response. shellcheck flags this automatically (SC2221/SC2222) and fires on
    the original file; it simply is not pointed at tests/install-sh/** today.
  - the create arm answered success regardless of body, hiding defect 1.
Now: ordered arms, an explicit endpoint allowlist (each entry dated by live probe), a body rule
mirroring the live 400, and paired negatives N1/N1b/N2/N2b/N3 that fail on run 3's invented ping
path and run 4's create body.

Gates shown to discriminate, not merely to pass — each fix reverted in turn:
  remove transport            → PASS=32 FAIL=1
  remove runtimeId/providerId → PASS=30 FAIL=3
  drop the .ok parse          → PASS=30 FAIL=3
  restored control            → PASS=33 FAIL=0
refresh-covers-full-delivery 6/6 PASS; shellcheck -S warning clean.

Prior-art: skipped — bug fix to an existing capability plus test hardening, no new capability.
@artyhoo
artyhoo merged commit 6ea6011 into staging Aug 9, 2026
47 of 48 checks passed
@artyhoo
artyhoo deleted the harvest/s4-995e9c branch August 9, 2026 07:40
artyhoo added a commit that referenced this pull request Aug 9, 2026
…cted, model proof measured (#1340)

The Round-4 fidelity audit emitted KICKOFF-AMBIGUOUS on §7e.3 and a DECISION-NEEDED fork
(weaken §7a #3's completion proof, or weaken §2 constraint 1's key-handling invariant). Both
options were unnecessary: the fork rested on §7f.2's claim that every aif-side completion route
is closed, and that claim came from a single probe.

Corrected here, each against a measurement rather than a re-reading:

- §7f.0 — «base on run 3» pointed at PR #1322, which is still OPEN and red. The S4 work is on
  `staging` as `6ea6011560` (PR #1323); `git merge-base --is-ancestor 6ea6011 49eaafe`
  → YES, so a staging-based run 4 satisfies §7e.0 with a superset, not a regression.
- §7f.1 — `…-995e9c` was labelled a dead end. The BRANCH is; its CONTENT was repaired
  dispatcher-side, pushed as `harvest/s4-995e9c` and merged as #1323, shard-A wiring included.
- §7f.2 — `POST /runtime-profiles/<id>/v1/messages` → 404 was measured and stands, but the
  conclusion drawn from it («the only reachable form of §7a #3») generalised one probe into a
  negative-existence claim, missing project invariant #3. `POST /chat/sessions` → 400: the route
  exists. `chat.ts:923-937` project-scope-validates `runtimeProfileId`; `chat.ts:1275` is the
  completion endpoint; §7e.4 already established the key is read off aif's own `process.env`, so
  aif makes the call and the helper never handles the value. Both constraints hold.

Proven end-to-end with one operator-approved billed call: `assistantMessage` returned,
`costUsd:0.117219`, `runtime.profileId:53eca24c-…`, and that profile's `lastUsageAt` moved
`09:15:11.263Z` → `09:51:42.017Z`. Cost is recorded as ~$0.12/run, not token-scale, because aif
injects project context — the suite must stub it and only host-verify may fire it live.

What is still unproven is stated as run 5's task rather than implied closed: the probe used an
already-created profile on a warm aif, not a cold install immediately after the helper's own
`POST /runtime-profiles`.

The file lands at exactly 600 lines. `.husky/pre-commit` carries no kickoff exemption (only
`md-line-gate.sh` does, and its glob is `kickoff.md`, which never matches `kickoff-s4.md`), so
the next correction to this file needs a split, not a trim.

Prior-art: skipped — documentation only; corrects three falsified facts in an existing kickoff
section and adds no capability, no dependency, and no new module.

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