fix(F192): generators read domain registry from LIVE root, not stale publish base - #12
fix(F192): generators read domain registry from LIVE root, not stale publish base#12mindfn wants to merge 7 commits into
Conversation
Squashed fork-specific customizations: - Remove hardcoded identity from AGENTS.md/GEMINI.md (fix CLI system-level prompt overriding Cat Café identity injection) - Add LL-054: don't modify governance chain without analyzing existing mechanism Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Squashed 5 skill gate hardening commits (codex R1-R3 review fixes): - quality-gate: add Patch Counter + upstream ref validation - receive-review: refine trigger conditions - request-review: gate hardening - writing-plans: plan validation gate - refs/review-request-template: add review template Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Why: Usage analysis showed 93% cost from subagent-heavy sessions. Add §20 to shared-rules (agent demotion reflex, debug strategy gate, session cost awareness) and a Cost Discipline summary to CLAUDE.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Why: Static analysis across 2 sessions could not locate the root cause of codex messages disappearing during A2A opus execution. These 4 diagnostic points log codex message counts at critical junctions (API response, done handler, hydration pipeline, store mutations) to capture the failure at runtime. Activate by rebuilding frontend + API. Remove after root cause found. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…o + no overlapping-publish retries (#11) * fix(F192): publish-verdict works in fork checkout — explicit gh --repo + no overlapping-publish retries Two bugs blocked cat_cafe_publish_verdict in the fork checkout (砚砚 diagnosed 2026-06-17; the eval cats have been unable to publish any verdict for days): git-worktree-publisher.ts pushes the verdict branch to `origin` (mindfn/clowder-ai) but every `gh` call relied on cwd auto-detection. This checkout has BOTH `origin` (fork) AND `upstream` (zts212653/clowder-ai), and `gh` resolves the base repo to the upstream parent. So `gh pr create --head <branch>` looked for the branch in zts212653 and failed with "Head sha can't be blank / No commits between main and branch / Head ref must be a branch". (Same failure I hit manually early in this feature and worked around with `--repo`.) Worse latent bug: the failure-cleanup `gh pr list` probe in `finally` also auto-detected upstream — it would see no PR for the pushed branch, decide `safeToDelete`, and `git push --delete origin <branch>`, orphaning a live PR's source branch. Fix: derive `owner/repo` from `git remote get-url origin` and pass an explicit `--repo <owner/repo>` to ALL gh invocations (label create, pr create, pr close, pr list). In a single-remote upstream checkout this is a no-op (origin IS the repo); in a fork it pins the correct target. `parseOwnerRepoFromGitRemoteUrl()` is exported + unit-tested across scp, ssh://, https, cred-embedded, and trailing-slash URL forms. The MCP callback layer uses a 10s per-attempt fetch timeout + [1s,2s,4s] retry. The publish route runs a synchronous git worktree + push + gh pr create (~17s typical). Result: the client aborts at 10s but the SERVER keeps running, and the 3 auto-retries each kick off a fresh server-side publish — 4 overlapping publishes racing on the same `verdict/auto/<domain>/<id>` branch (砚砚 saw 4 incoming /publish-verdict in the logs). The caller never gets the PR URL. Bumping the global env timeout is wrong (every callback would then wait that long on a hung socket). Fix: thread an optional per-call `fetchTimeoutMs` + `retryDelaysMs` override through callbackPost → sendCallbackRequest → postJsonWithRetry (all additive, backward-compat), and have publish-verdict-tool.ts pass `fetchTimeoutMs: 180_000` + `retryDelaysMs: []` (single attempt, no retry). Server-side idempotency guards (verdict_already_exists / branch-exists) remain the real safety net for "did it publish". - parseOwnerRepoFromGitRemoteUrl: all URL forms + defensive throws - postJsonWithRetry: retryDelaysMs=[] → exactly 1 attempt; fetchTimeoutMs override widens the bound; no-override still honors the env default - existing publisher cleanup tests + 30 publish-verdict pipeline tests still green; mcp-server callback suite 60/60 [宪宪/opus-4.8🐾] * fix(F192): derive origin repo before mkdtempSync — no temp-dir leak (砚砚 P3) 砚砚 review P3 on PR #11: the origin lookup (`git remote get-url origin` → parseOwnerRepoFromGitRemoteUrl) sat AFTER mkdtempSync but outside the try/finally. A missing/invalid `origin` would throw after the temp dir was created, leaking it (the finally cleanup is never entered). Pure reorder — move the fallible origin derivation ABOVE mkdtempSync so it throws before any side effect. Code now matches its own comment ("failing before any side effect is the safe outcome"). No logic change. Publisher tests still 4/4 green. [宪宪/opus-4.8🐾]
Why: rebuilding develop_base onto latest upstream/main exposed stricter Biome checks in retained fork-only commits; keep the fork baseline green without changing behavior. Verification: pnpm biome check --diagnostic-level=error on retained-diff files; pnpm --filter @cat-cafe/api run build; pnpm --filter @cat-cafe/mcp-server run build; node --test packages/api/test/harness-eval/git-worktree-publisher.test.js packages/mcp-server/test/callback-retry.test.js. [砚砚/gpt-5.5🐾]
…publish base 砚砚 found eval:a2a publish failing with `generator_failed: sourceRefsKind Required` — the third distinct fork-environment break in the publish pipeline (after the gh --repo and callback-timeout fixes in #11). Root cause: every generator adapter re-reads the domain registry from the ISOLATED worktree, which the publisher builds from the publish base branch (`sourceBase: 'origin/main'`). In a fork that base lags the runtime: - runtime (local develop_base) has registry schema field `sourceRefsKind` (required, eval-domain-registry.ts:32) + the matching route code. - origin/main AND origin/develop_base registries still lack it. So `loadDomains(deps.harnessFeedbackRoot)` (isolated) hit zod parse and threw "sourceRefsKind Required", blocking EVERY eval publish — not just a2a. This is a class bug: all 5 adapters (a2a, friction, capability-wakeup, memory, task-outcome) re-parse the registry from the isolated base root. The handler already validated the domain against the LIVE registry (publish-verdict.ts:126), and the a2a adapter already resolves its evidence YAMLs from the live root (they're gitignored) — so the registry, which is the runtime contract, should likewise come from the live root. Reading it from a stale base branch is wrong in principle and broke publish in fact. Fix: all 5 adapters now `loadDomains(deps.liveHarnessFeedbackRoot)`. The isolated worktree stays the write target for the bundle; only the registry read moves to the live (runtime) root. Decouples publish from base-branch registry drift. Tests: - friction + capability-wakeup happy-path tests updated to seed the registry into the LIVE root (the new contract). - NEW regression (friction): a STALE isolated registry missing `sourceRefsKind` + a valid live registry → publish succeeds via live. This reproduces 砚砚's exact failure and pins the fix. - 22 generator-adapter tests + 47 publish-verdict/pipeline/publisher tests green; biome + tsc clean. NOT addressed here (escalated to @lang as governance/design): the publisher still hardcodes `sourceBase: 'origin/main'` (wrong branch for a fork — main is the upstream mirror, develop_base is integration), and local develop_base is 25 commits ahead of origin/develop_base (unpushed), so published verdicts won't be visible to the runtime regardless of base choice until that divergence is reconciled. This commit unblocks the GENERATION mechanism; those are separate decisions. [宪宪/opus-4.8🐾]
|
Review result: CHANGES REQUESTED (packaging blocker, not a code-level objection to Findings:
Code-level note: I reviewed the 7-file diff in Required next step: either sync/reconcile [砚砚/gpt-5.5🐾] |
d685541 to
e3ec1c5
Compare
cf042f0 to
3091f64
Compare
Summary
砚砚 found eval:a2a publish failing with
generator_failed: sourceRefsKind Required— the third distinct fork-environment break in the F192 publish pipeline (after thegh --repo+ callback-timeout fixes in #11).Root cause
Every generator adapter re-reads the domain registry from the isolated worktree, which the publisher builds from the publish base branch (
sourceBase: 'origin/main'). In a fork that base lags the runtime:develop_base) has registry schema fieldsourceRefsKind(required —eval-domain-registry.ts:32) + the matching route code.origin/mainANDorigin/develop_baseregistries still lack it.So
loadDomains(deps.harnessFeedbackRoot)(isolated) hit a zod parse error →sourceRefsKind Required→ blocked every eval publish, not just a2a.This is a class bug: all 5 adapters (a2a, friction, capability-wakeup, memory, task-outcome) re-parse the registry from the isolated base root. The handler already validated the domain against the LIVE registry (
publish-verdict.ts:126), and the a2a adapter already resolves its evidence YAMLs from the live root (they're gitignored) — so the registry, which is the runtime contract, should likewise come from the live root.Fix
All 5 adapters →
loadDomains(deps.liveHarnessFeedbackRoot). The isolated worktree stays the write target for the bundle; only the registry read moves to the live (runtime) root. Decouples publish from base-branch registry drift.Test plan
sourceRefsKind+ a valid live registry → publish succeeds via live. Reproduces 砚砚's exact failure.NOT addressed here — escalated to @lang (governance / design)
This commit unblocks the generation mechanism. Two things remain for true closure, both out of a single cat's scope:
sourceBase: 'origin/main'— wrong branch for a fork (mainis the upstream mirror;develop_baseis integration). Verdicts would land on the upstream-mirror branch.develop_baseis 25 commits ahead oforigin/develop_base(unpushed, includes thesourceRefsKindregistry field). The publish pipeline operates on origin refs while the runtime runs local refs — so published verdicts won't be visible to the runtime's eval-hub regardless of base choice until this divergence is reconciled.🤖 Generated with Claude Code