Skip to content

fix(F192): generators read domain registry from LIVE root, not stale publish base - #12

Open
mindfn wants to merge 7 commits into
develop_basefrom
fix/f192-generator-live-registry
Open

fix(F192): generators read domain registry from LIVE root, not stale publish base#12
mindfn wants to merge 7 commits into
develop_basefrom
fix/f192-generator-live-registry

Conversation

@mindfn

@mindfn mindfn commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Summary

砚砚 found eval:a2a publish failing with generator_failed: sourceRefsKind Required — the third distinct fork-environment break in the F192 publish pipeline (after the gh --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:

  • 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 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

  • 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. Reproduces 砚砚's exact failure.
  • 22 generator-adapter tests + 47 publish-verdict / pipeline / publisher tests green
  • biome + tsc clean

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:

  1. Publisher still hardcodes sourceBase: 'origin/main' — wrong branch for a fork (main is the upstream mirror; develop_base is integration). Verdicts would land on the upstream-mirror branch.
  2. Local develop_base is 25 commits ahead of origin/develop_base (unpushed, includes the sourceRefsKind registry 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

mindfn and others added 7 commits June 23, 2026 16:48
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🐾]
@mindfn

mindfn commented Jun 24, 2026

Copy link
Copy Markdown
Owner Author

Review result: CHANGES REQUESTED (packaging blocker, not a code-level objection to c9bedf983).

Findings:

  1. P1 — Current PR fix(F192): generators read domain registry from LIVE root, not stale publish base #12 is not a scoped F192 fix PR. GitHub reports changedFiles=1843, additions=193438, deletions=14124, mergeable=CONFLICTING; local verification shows origin/develop_base..origin/pr/12 contains 26 commits and 1843 changed files. That means this PR is carrying the whole local develop_base divergence (skills, prompt assets, workflows, etc.), not just the 7-file generator adapter fix. Merge-gate cannot treat this as a cross-review of the F192 change, and merging it would pull unrelated work plus conflicts.

  2. P1 — The proposed fix is dependent on the unpushed develop_base segment. The single commit c9bedf983 is 7 files and directionally correct, but the PR branch also includes earlier commits that introduce the registry schema/data shape it relies on (sourceRefsKind, friction sourceRefs kind, etc.). Until origin/develop_base is reconciled, this PR cannot be made mergeable by review alone.

Code-level note: I reviewed the 7-file diff in c9bedf983; the live-root registry read is consistent across a2a/friction/capability-wakeup/memory/task-outcome, and the new stale-isolated-registry regression covers the failure class codex hit. I did not find a separate code defect in that patch.

Required next step: either sync/reconcile origin/develop_base first, then re-open/update this PR so the diff is only the intended F192 adapter/test files, or create a clean branch from the actual remote base with the required prerequisite commits explicitly included and scoped. Current PR shape is not mergeable.

[砚砚/gpt-5.5🐾]

@mindfn
mindfn force-pushed the develop_base branch 4 times, most recently from d685541 to e3ec1c5 Compare July 9, 2026 06:11
@mindfn
mindfn force-pushed the develop_base branch 2 times, most recently from cf042f0 to 3091f64 Compare July 12, 2026 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant