Skip to content

feat: harden archive continuity closure#3051

Merged
Sinity merged 13 commits into
masterfrom
feature/query/z9gh-closure
Jul 17, 2026
Merged

feat: harden archive continuity closure#3051
Sinity merged 13 commits into
masterfrom
feature/query/z9gh-closure

Conversation

@Sinity

@Sinity Sinity commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary

Land the reviewed archive-read, repair, source-admission, and work-evidence improvements as one coherent continuity slice.

Problem

Archive read surfaces and raw-authority recovery had unbounded or inconsistent paths, while agent-work evidence lacked a provider-neutral substrate.

Solution

  • Carry one cancellable, bounded query transaction through API, HTTP, and MCP reads.
  • Repair raw-authority replay accounting, envelope propagation, and frontier claim serialization.
  • Make the scale proof fail closed on unsuccessful repair passes.
  • Add typed origin admission and provider-neutral work-claim/effect evidence primitives.

Verification

  • devtools verify --seed-testmon --skip-slow
  • Focused repair, MCP, scale-proof, and evidence tests recorded on the branch.

Remaining boundary

This code slice does not claim a live production continuity replay: the deployed daemon is on an older build and its archive reports unresolved raw-authority debt. That operational proof remains tracked separately.

Sinity and others added 13 commits July 17, 2026 20:03
Introduce stable actor, content-addressed execution-context, and explicit worker-profile references. Comparative judgments now consume the core identity values while preserving their stored string wire fields.

The focused identity route and repository quick gate pass.
Add typed public-origin admission declarations for Claude Code, ChatGPT, and reserved Grok exports. The registry validates lifecycle, fixture, coverage, provider-collision, and detector-tightness contracts against the current parser dispatch order.

Focused declaration/source tests and the repository quick gate pass.
Problem: automated assertion replay could read a candidate before an\noperator judgment and later overwrite the terminal result from another\nconnection. ArchiveStore also bypassed the shared SQLite connection profiles\nfor user-tier reads and writes.\n\nWhat changed: establish BEGIN IMMEDIATE before top-level assertion\npreserve/write and judgment decisions, retaining caller-owned commits and\nnested batch savepoints. Route user-tier ArchiveStore connections through the\ncanonical read/write factories and prove the interleaving, conflict, timeout,\nand rollback behavior against real SQLite connections.\n\nCo-Authored-By: Codex <noreply@openai.com>
Problem: source admission covered only pilot origins, leaving most public\nOrigin tokens outside the typed declaration and detector-parity contract.\n\nWhat changed: register each public Origin with executable parser and fixture\nevidence or explicit reserved/fallback semantics. The registry now reports a\nmissing public origin and validates detector precedence across the full\nexecutable set.\n\nCo-Authored-By: Codex <noreply@openai.com>
Problem: provider completeness maintained a separate nine-origin inventory,\nwhich could report green while omitting public Origins and their lifecycle.\n\nWhat changed: OriginSpec now owns completeness modes for every public Origin.\nThe report projects those modes, including explicit reserved and fallback\nstates, and the old hand-maintained inventory is removed.\n\nCo-Authored-By: Codex <noreply@openai.com>
Repair diagnostics now report the max payload envelope that governed
planning and postflight decisions, so persisted metrics and operator-visible
details agree for custom resource limits.

Strengthen recovery coverage to exercise census finalization through the
production restart path after all selected outcomes were recorded.

Co-Authored-By: Codex <noreply@openai.com>
Problem: Claude workflow evidence was treated as generic sidecars, leaving
run snapshots, journals, agent metadata, and adoption manifests outside
the declared source-admission path.

What changed: declare the artifact family on the Claude OriginSpec, classify
its paths through that declaration, parse fact-bearing sidecars during the
existing Claude assembly pass, and preserve coordinator Workflow invocations
as provider-evidenced events. Missing counterpart artifacts report coverage
gaps instead of becoming inferred links.

Compatibility/migration: reparse Claude sessions and re-inventory workflow
artifacts when the declared parser fingerprint changes.

Ref polylogue-2qx.2.

Co-Authored-By: Codex <noreply@openai.com>
Add a rebuildable work-evidence graph with typed topology nodes,
evidence-backed edges, and bidirectional repository traversal. Claims are
represented as distinct graph nodes and cannot stand in for observed effects
or evaluated satisfaction.

The index tier moves to v39. It is declared semantic-reparse only: rebuild
the derived index after source adapters materialize their admitted facts.

Ref polylogue-1vpm.6.1.

Co-Authored-By: Codex <noreply@openai.com>
Reserve the source-tier write transaction before checking a frontier preview claim, preventing concurrent applies from creating duplicate execution receipts.

Regression coverage proves governed memberships replay after an index reset, recovery rejects partial frontier postconditions, and readiness remains fail-closed behind durable authority blockers.

Co-Authored-By: Codex <noreply@openai.com>
Problem: terminal unit reads still let the API and HTTP adapters mint\nseparate execution identities, while ordinary action pages built follow-up\ndetail before their page selection.\n\nWhat changed: route terminal unit reads through QueryTransaction across API,\nHTTP, and MCP; preserve the HTTP reader timeout; and derive action follow-up\ndetail only for the selected ordinary-action page. The registered MCP route\nnow proves discovery plus advancing action continuation.\n\nRef polylogue-z9gh.9.1.\n\nCo-authored-by: Codex <noreply@openai.com>
Reject every unsuccessful receipt-bearing repair pass and refuse successful
receipts for incomplete generated or resource-deferred workloads. Complete the
necessary parser census before receipt-bearing replay, sample host admission
around generation, census, and replay, and stream corpus identity metadata.

Set the command defaults to the July topology: 10,163 authority components,
15,264 direct candidates, and 21,398 expanded memberships.

Ref polylogue-z9gh.

Co-Authored-By: Codex <noreply@openai.com>
Project only admitted coordinator and workflow artifact facts into the provider-neutral work graph. Preserve invocation, resume, call, attempt, structured-result, artifact, and unresolved identities without inferring membership from child-session topology.

Ref polylogue-2qx.2 and polylogue-1vpm.6.1.

Co-Authored-By: Codex <noreply@openai.com>
Attach direct git, GitHub, Beads, artifact, and verification observations as effect nodes. Reconciliation judgments retain claims and effects as distinct facts and reject non-claim sources.

Ref polylogue-1vpm.6.2.

Co-Authored-By: Codex <noreply@openai.com>
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@Sinity, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 16 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3eac8bc2-e977-43e8-a62b-326fcda1023c

📥 Commits

Reviewing files that changed from the base of the PR and between 5a97fd7 and 9ddbf6c.

📒 Files selected for processing (55)
  • devtools/command_catalog.py
  • devtools/raw_authority_scale_proof.py
  • docs/plans/topology-target.yaml
  • docs/topology-status.md
  • polylogue/api/archive.py
  • polylogue/archive/artifact_taxonomy/models.py
  • polylogue/archive/artifact_taxonomy/runtime.py
  • polylogue/archive/query/transaction.py
  • polylogue/archive/query/unit_results.py
  • polylogue/core/refs.py
  • polylogue/daemon/http.py
  • polylogue/insights/claude_workflow_evidence.py
  • polylogue/insights/judgment/types.py
  • polylogue/insights/work_evidence.py
  • polylogue/insights/work_reconciliation.py
  • polylogue/mcp/server_tools.py
  • polylogue/sources/assembly.py
  • polylogue/sources/assembly_claude_code.py
  • polylogue/sources/dispatch.py
  • polylogue/sources/origin_specs.py
  • polylogue/sources/parsers/claude/__init__.py
  • polylogue/sources/parsers/claude/code_parser.py
  • polylogue/sources/parsers/claude/orchestration.py
  • polylogue/sources/provider_completeness.py
  • polylogue/storage/query_models.py
  • polylogue/storage/raw_authority.py
  • polylogue/storage/repair.py
  • polylogue/storage/repository/__init__.py
  • polylogue/storage/repository/insight/work_evidence.py
  • polylogue/storage/sqlite/archive_tiers/archive.py
  • polylogue/storage/sqlite/archive_tiers/index.py
  • polylogue/storage/sqlite/archive_tiers/user_write.py
  • polylogue/storage/sqlite/lifecycle.py
  • polylogue/storage/sqlite/queries/__init__.py
  • polylogue/storage/sqlite/queries/work_evidence.py
  • polylogue/storage/sqlite/query_store.py
  • polylogue/storage/sqlite/query_store_work_evidence.py
  • polylogue/surfaces/payloads.py
  • tests/unit/archive/query/test_transaction.py
  • tests/unit/core/test_refs.py
  • tests/unit/devtools/test_raw_authority_scale_proof.py
  • tests/unit/insights/judgment/test_types.py
  • tests/unit/insights/test_claude_workflow_evidence.py
  • tests/unit/insights/test_work_evidence.py
  • tests/unit/insights/test_work_reconciliation.py
  • tests/unit/mcp/test_server_surfaces.py
  • tests/unit/sources/test_artifact_taxonomy.py
  • tests/unit/sources/test_assembly_claude_code_history.py
  • tests/unit/sources/test_origin_specs.py
  • tests/unit/sources/test_parsers_claude_code_artifacts.py
  • tests/unit/sources/test_provider_completeness.py
  • tests/unit/storage/test_archive_tiers_assertions.py
  • tests/unit/storage/test_duplicate_raw_identity_repair.py
  • tests/unit/storage/test_raw_authority_ledger.py
  • tests/unit/storage/test_repair.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/query/z9gh-closure

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Sinity
Sinity merged commit bce7336 into master Jul 17, 2026
2 checks passed
@Sinity
Sinity deleted the feature/query/z9gh-closure branch July 17, 2026 19:51

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9ddbf6ce4f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +87 to +90
return {
"session_index": session_index,
"history_paste_index": merged_history,
"orchestration_artifacts": tuple(artifacts),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep orchestration artifacts out of per-file worker payloads

When Claude ingestion uses multiple workers, this tuple contains every parsed workflow journal and snapshot, while pipeline/services/archive_ingest.py submits the entire walk.sidecar_data mapping separately for every source path. A source with many session files or a large journal therefore repeatedly pickles and transfers the full orchestration corpus to every worker task—even though enrich_session() never consumes these entries—causing ingest CPU and memory to grow roughly with artifact bytes × path count. Pass these facts through a once-per-source route rather than the per-session sidecar payload.

Useful? React with 👍 / 👎.

Comment on lines +30 to +32
direction: str = "both",
edge_kinds: tuple[str, ...] = (),
limit: int | None = 100,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Enforce a positive bound on work-evidence traversal

For a high-degree work node, callers can pass limit=None or a negative value through the new repository method; None omits the SQL LIMIT, while SQLite interprets LIMIT -1 as unlimited, and the query then fetchall()s every matching edge and neighbor. This defeats the bounded-read contract and can consume unbounded memory on a large graph, so reject or clamp these values to a positive maximum.

Useful? React with 👍 / 👎.

Comment thread polylogue/api/archive.py
"expression": expression,
"session_filters": dict(request.session_filters or {}),
},
page_size=max(1, limit),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Normalize the API page size before executing the query

When a Python API caller supplies limit <= 0, only the transaction request is coerced to page size 1; the separately constructed QueryUnitRequest still executes with the original non-positive limit. If matching rows exist, this produces an empty page whose next_offset does not advance, so the returned continuation repeatedly requests the same page forever. Clamp or reject the limit once before constructing both requests.

Useful? React with 👍 / 👎.

Sinity added a commit that referenced this pull request Jul 18, 2026
Land the first WebUI v2 vertical: a TypeScript + Preact + Vite workspace
building an archive-overview island served by a new daemon strangler
mount, reusing the existing bounded query-transaction/continuation
substrate rather than inventing a new pagination API.

Adapted from an externally generated implementation packet
(webui-01-workspace-scaffold-r01) authored against commit 536a53e;
verified independently against current master (13 commits of drift,
none touching the same surface except a query_units continuation
refactor in #3051 that this change composes with cleanly) before
integrating: applied the patch, rebuilt the webui/ workspace from
scratch, ran the full Vitest + focused Python route suite, and
regenerated topology/openapi projections rather than trusting the
packet's own claims.

- polylogue/daemon/webui.py: manifest-governed Vite asset bundle
  discovery, SHA-256 ETag/immutable caching, and semantic SSR for a
  bounded `messages where words >= 0 | sort by time desc` overview page.
- polylogue/daemon/http.py: publish GET /app and GET /app/assets/:asset
  under the existing shell bootstrap admission policy; teach
  /api/query-units to replay an opaque continuation token end-to-end.
- webui/: strict TS + Preact + Vite workspace (existing playwright-only
  webui/ dir gains real app source); committed, content-hashed
  `polylogue/daemon/static/dist` build output ships in the wheel/sdist.
- flake.nix postFixup asserts the packaged manifest exists (Nix build
  itself not exercised - `nix` unavailable in this environment).

No existing legacy shell route, module, or test was touched or removed.

Verification:
- cd webui && npm ci && npm run typecheck && npm test && npm run build
  -> 1 Vitest file/test passed; typecheck clean; build reproduces the
  exact committed dist bytes (`git diff --exit-code -- polylogue/daemon/static/dist`
  is clean)
- npm audit --audit-level=low -> 0 vulnerabilities
- devtools test tests/unit/daemon/test_route_contracts.py
  tests/unit/daemon/test_web_reader.py -k 'TestReaderQueryUnits or
  TestWebUIV2 or route_contract' -> 112 passed
- uv run ruff format --check / ruff check / mypy --follow-imports=skip
  on the touched daemon files -> clean
- devtools render topology-projection && devtools render
  topology-status && devtools render openapi -> regenerated
  (the packet's committed topology/openapi diffs were stale against
  current master and were dropped in favor of a fresh regenerate)
- devtools render all --check -> all surfaces sync OK

Not run: Nix build/eval, Playwright/browser E2E, full `devtools
verify --all`.

Ref polylogue-bby.11
Sinity added a commit that referenced this pull request Jul 18, 2026
…nuation

Land the WebUI v2 client-contracts vertical: devtools render webui-client
derives a committed, deterministic TypeScript client
(webui/src/api/generated.ts + runtime.ts) from docs/openapi/search.yaml,
covering bootstrapWebCredential, revokeWebCredential, searchSessions,
search() (ranked-search async iterator), queryUnits, query() (terminal
query-unit async iterator), readSessionView, and listAssertionClaims.
No runtime dependency was added; the client uses only platform fetch/
AbortSignal/URL APIs.

Adapted from an externally generated implementation packet
(webui-08-client-contracts-r01), independently authored against the
same base commit as webui-01/07. Reconciled by hand:

- devtools/command_catalog.py, devtools/generated_surfaces.py,
  docs/devtools.md: the packet's `render webui-client` registration
  collided with webui-07's already-committed `render webui-design-system`
  entry at the same insertion point - both now registered in sequence;
  docs/devtools.md is generated, so it was regenerated rather than
  hand-patched.
- webui/package.json: the packet's own `test:unit`/`test` scripts ran a
  completely different lane (raw `tsc` emit + Node's built-in test
  runner over `tests/unit/*.test.mjs`) than this branch's established
  `test` = `vitest run`. Kept `test` as the Vitest canonical command and
  renamed the packet's lane to `test:client-contracts`; added
  `generate:client`/`check:client` and folded everything into `check`.
- webui/tsconfig.client.json (new): the packet's own tsconfig.json used
  `rootDir: "src"` + `include: ["src/**/*.ts"]`, which cannot be the
  single merged webui/tsconfig.json (that file's `include` now also
  covers `tests/**` and `*.config.ts`, which sit outside `src/` and
  would violate a shared `rootDir`). Added a narrow tsconfig extending
  the base, scoped to `src/api/**/*.ts` with `noEmit: false`, so
  `test:client-contracts`'s `tsc -p tsconfig.client.json --outDir
  .cache/client-test` emits `api/generated.js`/`api/runtime.js` at the
  exact path the packet's own `.test.mjs` imports.
- webui/src/api/runtime.ts: the merged tsconfig's `noImplicitOverride`
  (present in webui-01's tsconfig, absent from this packet's own)
  surfaced a real strictness gap - `TransportError.cause` shadows
  `Error.prototype.cause` without an `override` modifier. Fixed at the
  declaration.

Found and fixed a genuine correctness gap in webui-01's already-merged
`/api/query-units` continuation handling (not merely applied 08's
version verbatim - the literal `projection != "default"` check in the
packet's own patch was ALSO stale, since production actually sets
`projection="terminal-unit-envelope"` for this route per #3051, landed
after both packets' shared snapshot; using the packet's check verbatim
would have 400'd every real continuation request):
- polylogue/archive/query/transaction.py: `QueryContinuation.decode()`
  did not catch `binascii.Error`/`UnicodeDecodeError` from malformed
  base64/UTF-8 continuation tokens, so a malformed token from a browser
  or attacker would raise an unhandled exception instead of a clean 400.
- polylogue/daemon/http.py `_handle_query_units`: tightened continuation
  validation to reject continuation+other-query-param combinations,
  verify operation/projection (corrected to the real production value)
  /stable_order/exact-argument-keys, and cross-check the continuation's
  `result_ref` against the one re-derivable from its own request -
  replacing webui-01's looser (but not incorrect) validation.
- Added the packet's three new route-level tests plus its parametrized
  malformed-continuation unit test for `QueryContinuation.decode()`.

Verified real correspondence to current source: docs/openapi/search.yaml
and webui/src/api/generated.ts both regenerate as exact byte-for-byte
matches of the packet's committed copies once the generator source
merge was in place, confirming the OpenAPI/client generation is
deterministic and the underlying Pydantic/route surface it reads did
not semantically drift. Referenced Beads polylogue-o21.1,
polylogue-t46.8.1, polylogue-z9gh.9.1, polylogue-4p1 all exist and match
their described scope.

Verification:
- devtools test tests/unit/archive/query/test_transaction.py
  tests/unit/devtools/test_command_catalog.py
  tests/unit/devtools/test_render_webui_client.py
  tests/unit/devtools/test_render_openapi.py
  tests/unit/devtools/test_generated_surfaces.py
  tests/unit/daemon/test_web_reader.py tests/unit/daemon/test_route_contracts.py
  -> 281 passed, 1 failed (TestReaderAssertionEndpoint::
  test_operational_web_payloads_redact_configured_archive_paths - a
  symlinked-archive_root sqlite-open failure reproduced identically on
  unmodified master before any of these three packets were applied;
  unrelated file, pre-existing/environment-specific, not introduced here)
- devtools render openapi / render webui-client (both --check) -> sync
  OK, zero drift after the generator-source merge
- cd webui && npm run typecheck -> clean after the override-modifier fix
- npm run test:client-contracts (tsc emit + `node --test`) -> 8/8 passed
- npm run check (generate:check + check:client + lint + typecheck +
  test + test:client-contracts + build + build:design-system) -> all
  green; production build still reproduces the exact committed
  polylogue/daemon/static/dist bytes
- npm audit --audit-level=low -> 0 vulnerabilities
- uv run ruff format / ruff check on touched Python -> clean (2 files
  needed reformatting under this repo's pinned ruff version; fixed,
  re-verified generators still byte-identical)
- uv run mypy --follow-imports=skip on touched Python -> 3
  pre-existing `no-any-return` findings, confirmed present identically
  before these edits (unrelated generic-TypeVar/str-return diagnostics)
- devtools render topology-projection / topology-status, then
  devtools render all --check -> all surfaces sync OK

Not run: Nix build/eval, full `devtools verify --all`, exact-lockfile
TypeScript 5.9.3 toolchain from the original packet's own environment
(this repo's committed npm lockfile already pins and uses 5.9.3, so
that gap does not apply here).

Ref polylogue-bby.11
Sinity added a commit that referenced this pull request Jul 18, 2026
#3066)

## Summary

Adds an executable corpus of query examples (106 positive, 18 negative)
that teaches the real query DSL through production-parser-gated data
instead of hand-authored strings, plus a shared result-semantics
vocabulary
(`exhaustive`/`top-k`/`sample`/`aggregate`/`bounded-context`/`recursive-page`)
bridged into the existing MCP declaration enum. This is the parser-gated
discovery slice of `polylogue-z9gh.3`.

## Problem

MCP/CLI/docs teaching surfaces shipped invalid query examples that fail
against the real production parser:

- `polylogue/mcp/server_prompts.py:509` (pre-patch): `actions where
session.repo:{repo}...since:{since} AND output:failed` →
`ExpressionCompileError: invalid query expression near column 27`
(missing `AND`, missing `session.` prefix on `since`).
- `polylogue/mcp/server_prompts.py:524` (pre-patch): `files where
{repo_clause}path:{path}` → `field 'repo' is not supported for file
predicates` (repo is a session predicate, not a file predicate).
- `docs/search.md:924` (pre-patch): raw FTS5-style `text:css {...}:
refactor` → unknown field `text` (the DSL never exposed `text` as a
session field).

Separately, no discovery surface distinguished exact totals (exhaustive)
from ranked (top-k), sampled, aggregate-bucket, bounded-context, or
recursive-page results, so a `limit` could be misread as totality.

## Solution

- `polylogue/archive/query/discovery.py` — new typed corpus module: 106
positive rows (expression, parser route, unit source, one-sentence
answer, semantics class, projected columns, cost class) + 18 negative
rows (exact `ExpressionCompileError` class/text/field + a parser-valid
correction).
- `polylogue/archive/query/transaction.py` — shared
`QueryResultSemanticsContract` coverage/total/continuation vocabulary
(six classes).
- `polylogue/archive/query/completions.py` —
`query_completions(kind="example"|"error")` now serve corpus-backed rows
instead of ad hoc strings.
- `polylogue/mcp/server_prompts.py`, `server_resources.py` — the four
query-bearing cookbook prompts and the query capability resource (now
v2) render from the corpus; the six generic semantics classes map onto
the existing `MCPResultSemantics` enum
(`exhaustive_page`/`top_k`/`sample`/`aggregate`/`bounded_context`/`recursive_graph`)
without introducing a second taxonomy.
- `polylogue/cli/click_app.py`, `devtools/render_query_discovery.py`,
`docs/search.md` — root CLI help and a new generated search-guide
section render from stable corpus keys.
- `tests/unit/archive/query/test_discovery.py` — anti-lying gate: every
positive row is parsed through the real production route
(`compile_expression` for session expressions,
`parse_unit_source_expression` for terminal/pipeline expressions — this
necessarily exercises the hand-written pipeline splitter); every
negative row pins the exact `ExpressionCompileError` and proves its
correction parses.

**No grammar change**: `polylogue/archive/query/expression.py` is
untouched by this PR (verified: `git diff --stat` against this file is
empty).

## Scope — satisfied vs. deferred (polylogue-z9gh.3)

Satisfied by this slice:
- Executable corpus (106 positive / 18 negative), all six semantics
classes, all ten unit sources represented.
- Production-parser anti-lying gate (no mock grammar).
- Shared result-semantics vocabulary declared and mapped into the
existing MCP enum.
- Rewiring of the highest-risk teaching routes: 4 MCP cookbook prompts,
central search-guide section, root CLI help examples,
`query_completions` example/error kinds, MCP query-capability resource.
- Three confirmed shipped-invalid examples fixed at their source.

Explicitly **not** done here (remains open on `polylogue-z9gh.3` /
`polylogue-z9gh.9.1` / `polylogue-t46.8.1`):
- Typed structured-plan lowering to one AST.
- OpenAPI/JSON schema generation for the discovery vocabulary.
- Live coverage/freshness/cardinality discovery, current-value
discovery.
- The full six-tool `explain` transaction.
- Migrating every remaining hand-authored docs/help example to corpus
keys (they are parser-gated, not all declaration-rendered).
- Making every live read adapter emit the exact/qualified totals and
continuations this vocabulary describes (`z9gh.9.1`'s executor
migration).

Spot-checking against a seeded demo archive also surfaced (but this PR
does not fix, since it's outside this corpus/discovery slice and touches
unrelated execution code): `near:id:<ref>` session-similarity queries
execute without error but do not perform real similarity ranking through
the generic `find`/`read` CLI route (falls back to a plain unfiltered
session list), and the declared `recursive-page` projection columns
(`parent_refs`/`child_refs`/`continuation`) are not materialized by that
same generic route for `lineage:id:` queries — both are pre-existing
execution-layer gaps unrelated to this patch (confirmed
`archive/query/expression.py`, `execution_control.py`, and
`unit_results.py` are untouched by this diff), consistent with this
corpus's own disclosed limitation that non-exhaustive/non-aggregate
semantics classes are parser-valid but not execution-verified here.

## Provenance note

This PR lands external-agent (GPT Pro) packaged output
(`mcp-04-discovery-corpus-r01.zip`) generated against snapshot commit
`536a53efac0cbe4a2473ad379e4db49ef3fce74d`, reviewed and reconciled
against 13 commits of subsequent master drift, then verified
independently in this repo (not merely re-run from the packet's own
claims).

## Verification

- `git apply --check` against the snapshot commit's parent tree was
clean except for two purely-generated files
(`docs/plans/topology-target.yaml`, `docs/topology-status.md`); applied
the rest and regenerated those two via `devtools render
topology-projection && devtools render topology-status` (repo convention
for new `polylogue/` modules).
- One real conflict found and reconciled: PR #3051 (merged after the
packet's snapshot) added
`test_agent_query_discovery_and_action_pages_share_one_registered_transaction`
in `tests/unit/mcp/test_server_surfaces.py` asserting the *old* nested
`grammar["terminal_sources"]` shape; this PR's capability-resource v2
moves that key to top-level `terminal_sources` (as this PR's own
`test_envelope_contracts.py` assertion already expects). Fixed the one
assertion; no declarations/registry files were touched
(`polylogue/mcp/declarations/**` and `registry.py` are untouched by this
diff).
- `devtools render all --check` — clean (no `out of sync`).
- `devtools test tests/unit/archive/query/test_discovery.py
tests/unit/archive/query/test_transaction.py
tests/unit/archive/test_query_metadata.py
tests/unit/cli/test_query_expression.py
tests/unit/cli/test_completions_contract.py
tests/unit/cli/test_query_discovery_help.py
tests/unit/devtools/test_generated_surfaces.py
tests/unit/devtools/test_query_teaching_surfaces.py
tests/unit/devtools/test_render_query_discovery.py
tests/unit/mcp/test_envelope_contracts.py
tests/unit/mcp/test_server_surfaces.py` → **798 passed, 1 skipped**.
- `ruff format --check` / `ruff check` / `git diff --check` over all
changed files — clean.
- `mypy` (strict, whole repo: `polylogue tests devtools`) — clean. Found
and fixed two real type errors the source packet's own verification
never caught (a loop-variable type collision from reusing `row` across
two differently-typed loops in `devtools/render_query_discovery.py` and
again in `tests/unit/archive/query/test_discovery.py`, plus an
unannotated polymorphic Pydantic-model dict needing an explicit
`type[SurfacePayloadModel]` annotation).
- `devtools verify --quick` (format + lint + mypy + `render all
--check`) — clean; this is what the pre-push hook runs and it now
passes.
- Spot-checked 11 corpus rows across all six semantics classes against a
`polylogue demo seed` archive using the real production execution paths
(`find ... then read`, `query_unit_rows`): exhaustive queries returned
exact totals (including real zero-match cases), the aggregate query
correctly bucketed real data (`role:assistant` messages by type:
`message=19`, `tool_use=14`), top-k returned a qualified/null total
under `mode: "search"`, and bounded-context correctly projected the
declared `messages(message_id,role,text)` columns.

Ref polylogue-z9gh.3

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sinity added a commit that referenced this pull request Jul 18, 2026
Problem: Claude Code's agent-acompact-* artifact family is overloaded.
The parser unconditionally classified every agent-acompact-* record as a
CONTINUATION of its main session, but ~39/187 observed files (9 at 0%
overlap) are actually Task-subagent self-compactions replaying only their
own fresh transcript. Composition then prepended the wrong (main-session)
transcript onto these subagent reads.

What changed:
- code_parser.py: add `_is_fresh_task_prompt_head`, a narrow structural
  predicate (root sidechain user record with explicit agentId/promptId,
  no parentUuid, not human-authored) that gives a conservative SIDECHAIN
  hint when the parser can only see one JSONL group in isolation.
- write.py: add the authoritative gate — a bounded multiset
  content-membership ratio (90% threshold) between the child's
  pre-summary prefix and the parent's composed transcript, computed once
  parent content is resolvable. Below threshold (or no fresh-head hint
  and a spawned-fresh parent) reclassifies to SIDECHAIN/spawned-fresh
  (branch_point_message_id explicitly NULL, never left dangling); at or
  above threshold, parent-content membership overrides even a
  conservative fresh-head hint back to CONTINUATION/prefix-sharing. Both
  ingest orders are handled: parent-known (`write_parsed_session_to_archive`)
  and child-before-parent (`_reextract_prefix_tail_db`, including the
  session_links natural-key PK-lane move when link_type changes).
- dispatch.py: fix a twin-path fallback_id divergence — the eager grouping
  path (`_claude_code_grouped_record_specs`) now assigns `fallback_id` to
  the first group like the streaming path
  (`_claude_code_stream_sessions`) already did, so composed_session_id
  and classification agree between both ingest routes.
- docs/design/session-lineage-model.md: correct the stale claim that all
  187 agent-acompact-* sessions are 100% main-session copies; ~148 are,
  ~39 are Task self-compactions below the 90% membership threshold.
- New fixture + regression tests for both cases (true main-session
  acompact -> parent=main; subagent self-compact -> sidechain, no
  inherited prefix), each parametrized over parent-first/child-first
  ingest order, plus a dispatch-path-parity test.

Verification:
- devtools test tests/unit/sources/test_compaction.py
  tests/unit/sources/test_claude_code_normalization_laws.py
  tests/unit/sources/test_dispatch_payloads.py -> 56 passed
- mypy --strict clean on the three changed modules
- ruff check + format --check clean
- Anti-vacuity: temporarily forced
  `_acompact_content_membership_ratio` to always return 1.0 (pre-patch
  unconditional-continuation behavior); both parametrized cases of
  test_subagent_self_compaction_stays_whole_and_never_composes_main_prefix
  failed as expected, confirming the test exercises the real gate;
  reverted after confirming.
- No schema/migration files touched (git diff --stat against
  storage/sqlite/migrations/ is empty) — pure logic fix.
- Checked for collision with #3051 (orchestration.py / Workflow tool
  events, already on master): its code_parser.py/dispatch.py changes are
  additive and touch an unrelated concept (explicit Workflow tool-call
  session events), no overlap with the acompact classification path.

Live re-ingest of the ~39 known-mismatched files driving the
mis-parented-subagent-acompact count to zero remains an operator step
(requires the live archive) and is not verified in this container.

Ref polylogue-4ts.3
Ref gh-2471

Co-Authored-By: Claude <noreply@anthropic.com>
Sinity added a commit that referenced this pull request Jul 18, 2026
…3069)

## Summary

`agent-acompact-*` is overloaded by Claude Code: a main-session
auto-compact
replays the whole parent transcript (genuine continuation), but a Task
subagent can self-compact under the same filename prefix (a fresh
sidechain
with no relation to the main session's content). The parser previously
classified every `agent-acompact-*` record as an unconditional
continuation
of its main session, so composed reads of subagent self-compactions
incorrectly prepended the wrong (main-session) transcript.

## Problem

Code-confirmed (gh#2471, bead `polylogue-4ts.3`): ~39/187 observed
`agent-acompact-*` files (9 at 0% overlap) are Task-subagent
self-compactions with less than 90% content overlap with their claimed
main session, yet were stored/composed as if they were verbatim
continuations of it.

## Solution

- `polylogue/sources/parsers/claude/code_parser.py`: add
  `_is_fresh_task_prompt_head`, a narrow structural predicate (root
  sidechain user record, explicit `agentId`/`promptId`, no `parentUuid`,
not human-authored) giving a conservative SIDECHAIN hint when the parser
  can only see one JSONL group in isolation.
- `polylogue/storage/sqlite/archive_tiers/write.py`: the authoritative
  gate — a bounded multiset content-membership ratio (90% threshold)
  between the child's pre-summary prefix and the parent's composed
transcript, computed once parent content is resolvable. Below threshold
  (or no fresh-head hint with an unresolvable/spawned-fresh parent)
  reclassifies to SIDECHAIN/`spawned-fresh` (`branch_point_message_id`
  explicitly NULL, never left dangling — respects the documented
  not-a-FK invariant). At or above threshold, parent-content membership
  overrides even a conservative fresh-head hint back to
  CONTINUATION/`prefix-sharing`. Both ingest orders are handled:
  parent-known (`write_parsed_session_to_archive`) and
  child-before-parent (`_reextract_prefix_tail_db`, including the
  `session_links` natural-key PK-lane move when `link_type` changes from
  continuation to sidechain or vice versa).
- `polylogue/sources/dispatch.py`: fix a twin-path `fallback_id`
  divergence flagged in the bead's own investigation notes — the eager
  grouping path (`_claude_code_grouped_record_specs`) now assigns
  `fallback_id` to the first group the same way the streaming path
  (`_claude_code_stream_sessions`) already did, so `composed_session_id`
  and classification agree between both ingest routes.
- `docs/design/session-lineage-model.md`: correct the stale claim that
all
187 `agent-acompact-*` sessions are 100% main-session copies; ~148 are,
  ~39 are Task self-compactions below the 90% membership threshold.
- New fixture
(`tests/fixtures/claude-code/normalization-lineage-subagent-acompact.jsonl`)
  and regression tests for both cases (true main-session acompact ->
  parent=main; subagent self-compact -> sidechain, no inherited prefix),
  each parametrized over parent-first/child-first ingest order, plus a
  dispatch-path-parity test.
- Companion fix (second commit): the demo/scenario corpus's own
  `agent-acompact-demo.jsonl` fixture reused a shared generic-workload
  session as its "parent" but authored unrelated content, relying on the
  old unconditional-continuation classifier. The new membership gate
  correctly rejected it (0% real overlap) and flipped it to SIDECHAIN,
  breaking the `devtools render demo-corpus-datasheet --check` generated
  surface (part of `render all --check`) — this is the exact
  misclassification shape the bead describes, just hiding in the demo
corpus's own fixtures. Gave the fixture a dedicated parent session with
  literally-replayed content (matching real Claude Code auto-compact
  behavior) and updated the `compaction_omits_failed_attempt` construct
  query and its anti-vacuity test to check both physical locations
  (child + parent), since genuine prefix-sharing dedup now stores the
  replayed failed-attempt row once under the parent rather than
  duplicating it under the child.

## Verification

- `devtools test tests/unit/sources/test_compaction.py
tests/unit/sources/test_claude_code_normalization_laws.py
tests/unit/sources/test_dispatch_payloads.py` -> 56 passed
- `devtools test tests/unit/sources tests/unit/demo tests/unit/scenarios
tests/unit/cli/test_demo_command.py` -> 1825 passed; 2 pre-existing
failures (`test_chatgpt_normalization_survivors.py`, ChatGPT
DOM-fallback fidelity) reproduced identically on clean `origin/master`,
unrelated to this change.
-
`tests/integration/test_demo_daemon_convergence.py::test_import_demo_converges_through_live_daemon_path`
reproduces identically on clean `origin/master` (live-daemon 20s
convergence timeout plus several unrelated missing constructs —
browser-capture, embeddings, gemini session-id suffix drift); confirmed
pre-existing.
- `devtools verify --quick` -> exit 0 (ruff format/check, mypy, `render
all`,
topology/layering/closure-matrix/manifests/ci-workflows/doc-commands/docs-coverage/test-infra-currency/test-clock-hygiene/pytest-timeout-overrides/degrade-loudly
all ok). `devtools render demo-corpus-datasheet --output -` reports
`Verifier result: ok`, 0 problems.
- `mypy` clean on the whole `polylogue/` package (1031 files) and on
every touched module individually.
- Anti-vacuity: temporarily forced `_acompact_content_membership_ratio`
to always return `1.0` (the pre-patch unconditional-continuation
behavior). Both parametrized cases (parent-first, child-first) of
`test_subagent_self_compaction_stays_whole_and_never_composes_main_prefix`
failed as expected (`'continuation' != 'sidechain'`), confirming the
test exercises the real gate. Reverted after confirming.
- Checked for collision with #3051 (`orchestration.py` / Workflow
tool-call session events, already on `master`): its
`code_parser.py`/`dispatch.py` changes are additive and touch an
unrelated concept (explicit `Workflow` tool invocations), no overlap
with the acompact classification path.
- No schema/migration files touched (`git diff --stat` against
`polylogue/storage/sqlite/migrations/` is empty) — pure logic fix,
consistent with the bead's "no schema change" framing.

## Follow-up / operator verification (cannot be run in this container —
no live archive)

After a live re-ingest against the real ~38GB archive (`polylogue ops
reset --index && polylogued run`, or targeted reprocess of the ~39
known-mismatched files), confirm the reclassification actually lands.
Pre/post-rebuild probe:

```sql
WITH acompact AS (
    SELECT
        s.session_id,
        s.branch_type,
        l.link_type,
        l.inheritance,
        l.branch_point_message_id
    FROM sessions AS s
    LEFT JOIN session_links AS l
      ON l.src_session_id = s.session_id
     AND l.method = 'parser-parent'
    WHERE s.origin = 'claude-code-session'
      AND (
          s.native_id LIKE 'agent-acompact-%'
          OR s.native_id LIKE '%:agent-acompact-%'
      )
)
SELECT
    COALESCE(branch_type, '<NULL>') AS branch_type,
    COALESCE(link_type, '<NO-LINK>') AS link_type,
    COALESCE(inheritance, '<NULL>') AS inheritance,
    COUNT(DISTINCT session_id) AS sessions
FROM acompact
GROUP BY 1, 2, 3
ORDER BY sessions DESC, 1, 2, 3;
```

Expected movement (not verified in this container): total acompact
session
count stays ~187; ~148 true main-session artifacts read
`continuation / continuation / prefix-sharing`; ~39 Task
self-compactions
move to `sidechain / sidechain / spawned-fresh`; the 9 zero-overlap
artifacts move branch/link topology from continuation to sidechain (they
may already have had `spawned-fresh` inheritance from the older
zero-contiguous-alignment path).

Post-rebuild integrity check (expect `0`):

```sql
WITH acompact AS (
    SELECT
        s.session_id,
        s.branch_type,
        l.link_type,
        l.inheritance,
        l.branch_point_message_id
    FROM sessions AS s
    LEFT JOIN session_links AS l
      ON l.src_session_id = s.session_id
     AND l.method = 'parser-parent'
    WHERE s.origin = 'claude-code-session'
      AND (
          s.native_id LIKE 'agent-acompact-%'
          OR s.native_id LIKE '%:agent-acompact-%'
      )
)
SELECT COUNT(*) AS malformed_sidechain_acompacts
FROM acompact
WHERE branch_type = 'sidechain'
  AND (
      link_type IS NULL
      OR link_type <> 'sidechain'
      OR inheritance IS NULL
      OR inheritance <> 'spawned-fresh'
      OR branch_point_message_id IS NOT NULL
  );
```

(Both queries verified against the current `session_links` schema in
this
container — the `method` column and the `'parser-parent'` literal it
filters on are confirmed present in
`polylogue/storage/sqlite/archive_tiers/index.py`
and written by `_write_session_link`; only the live-corpus row counts
are
unverified.)

Ref polylogue-4ts.3
Ref gh-2471

---

Generated from a review/verification pass over an externally-authored
patch (packet `lin-03-subagent-compaction-r01`); its own HANDOFF/TESTS
claims were independently re-verified against current code rather than
trusted, per the task's instructions. Not merged — left for coordinator
review.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sinity added a commit that referenced this pull request Jul 18, 2026
… hand ledger

Problem: docs/public-claims.yaml (schema external-claims-ledger/v2) was
a hand-maintained YAML file, a second durable claims store parallel to
the FINDING assertion substrate that PR #2791's canonical judgment
lifecycle already governs. polylogue-3tl.16 asks for public claims to
be a rendered projection over FINDING rows, judgment/supersession
state, and a shared evidence-integrity verdict instead.

Solution: polylogue/insights/measurement/public_claims.py computes one
PublicClaimProjection per stable claim key from
list_public_finding_inputs() (new adapter in
storage/finding_provenance.py) plus an injected
EvidenceIntegrityProvider.verdict_for() seam (polylogue-37t.14 is not
yet landed, so a missing verdict fails closed as unresolved, never
fresh/supported). Four presets (readme/launch/findings-page/
verified-export) filter the same computed rows -- status is computed
once, not per surface. devtools/public_claims.py + new
devtools/render_public_claims.py replace the old YAML-validator with a
render/check command; docs/public-claims.yaml becomes a generated
verified-export compatibility view. Seeds the three current
claim-vs-evidence headline findings plus the flight-recorder capability
statement via new PublicClaimDeclaration fields on the existing
additive polylogue.finding.v1 assertion payload (no user-tier schema
migration -- these are additive JSON fields on an already-JSON column).

Originated as external-agent packet ann-05-claims-view-r01 (GPT Pro
wave 2, snapshot 536a53e), unreviewed. Verified independently:

- Confirmed against live source (not the packet's claim) that no
  second durable claims table exists and no schema migration is
  required for the new FindingAssertion fields.
- git apply --check against current origin/master (12+ commits ahead
  of the packet's snapshot) failed on 3 of 29 files. Two
  (docs/plans/topology-target.yaml, docs/topology-status.md) are
  generated docs that drifted from unrelated intervening commits --
  regenerated via `devtools render topology-projection` +
  `render topology-status` rather than force-applying stale content.
  The third (user_write.py) conflicted on one import line added by
  PR #3051 (`feat: harden archive continuity closure`) landing after
  the packet's snapshot; reconciled by hand (7 of 8 hunks applied
  clean via git apply --reject, the import line added manually).
- Independently reproduced devtools verify public-claims --json (4
  claims, 9 artifacts, 3 monitored surfaces, 0 problems) and
  devtools verify layering (0 violations) -- both match the packet's
  own claimed output exactly.
- The packet flagged test_archive_tiers_api_archive_debt_reads_archive_consistency
  as a pre-existing "database source_debt is locked" failure unrelated
  to its patch. Reproduced this independently on the unrelated ann-01
  worktree (clean master plus an unrelated feature) to confirm it is
  a genuine baseline/environmental flake, not something this patch
  introduced.

Verification:
- devtools test tests/unit/insights/measurement/test_public_claims.py tests/unit/storage/test_public_claims_projection.py tests/unit/devtools/test_public_claims.py -> 31 passed
- devtools test tests/unit/scenarios/test_demo_archive_convergence.py tests/unit/storage/test_archive_tiers_assertions.py tests/unit/devtools/test_generated_surfaces.py tests/unit/devtools/test_release_readiness.py tests/unit/devtools/test_render_docs_surface.py tests/unit/devtools/test_project_motd.py tests/unit/daemon/test_standing_queries.py tests/unit/cli/test_import.py -> 84 passed
- devtools test (6 affected tests/unit/api/test_facade_contracts.py cases) -> 6 passed, 1 pre-existing unrelated flake classified above
- ruff format --check / ruff check on all 16 touched Python files -> clean
- mypy --strict on all 13 touched production/test modules -> Success, no issues
- devtools render all --check -> exit 0, no drift (includes regenerated topology projection/status)
- devtools verify public-claims --json -> ok, 0 problems
- devtools verify layering -> 0 violations
- devtools verify --quick -> exit_code 0

Ref polylogue-3tl.16

Co-Authored-By: Claude <noreply@anthropic.com>
Sinity added a commit that referenced this pull request Jul 18, 2026
… hand ledger (#3065)

## Summary

Implements polylogue-3tl.16: `docs/public-claims.yaml` stops being a
hand-maintained ledger and becomes a generated projection over
`AssertionKind.FINDING` rows, the canonical judgment/supersession
lifecycle (PR #2791), and a bounded evidence-integrity verdict seam for
the not-yet-landed `polylogue-37t.14` evaluator.

## Problem

`docs/public-claims.yaml` (schema `external-claims-ledger/v2`) was a
second durable claim store maintained by hand, parallel to the FINDING
assertion substrate. A claim's public status could drift from what the
judgment lifecycle actually supports, and README/launch/findings-page
copy had no single source of truth to render from.

## Solution

- `polylogue/insights/measurement/public_claims.py`:
`project_public_claims()`
  computes one `PublicClaimProjection` per stable claim key from
  `list_public_finding_inputs()` (new read adapter in
  `storage/finding_provenance.py`), the FINDING/judgment/supersession
  facts, and an injected `EvidenceIntegrityProvider.verdict_for()` seam.
  A missing verdict fails closed as `unresolved`, never
  fresh/supported. Four presets (`readme`, `launch`, `findings-page`,
  `verified-export`) only *filter* the one already-computed projection
  -- status is never recomputed per surface.
- `polylogue/storage/sqlite/archive_tiers/user_write.py`: additive
  `PublicClaimDeclaration` + `source_epoch`/`evaluation_ref`/`frame_ref`
  fields on the existing `polylogue.finding.v1` JSON payload. No
  user-tier schema migration -- these are new keys in an already-JSON
  column.
- `devtools/public_claims.py` (existing validator, rewritten) +
  new `devtools/render_public_claims.py`: render/check command,
  registered in `generated_surfaces.py`/`command_catalog.py`/
  `docs_surface.py`/`release_readiness.py`. `docs/public-claims.yaml`
  is now the generated `verified-export` compatibility view.
- Seeds the three current claim-vs-evidence headline findings plus the
  `category.local-evidence-system` capability statement via
  `polylogue/scenarios/corpus.py`.
- Distinct fail-closed states for
broken/circular/stale/frame-incomplete/
  private-held/unsupported evidence, verified by real negative tests
  (see Verification), not just read from the packet's own claims.

## Provenance and independent verification

Originated as external-agent packet `ann-05-claims-view-r01` (GPT Pro
wave 2, snapshot `536a53efac0cbe4a2473ad379e4db49ef3fce74d`,
unreviewed). Verified adversarially rather than trusting its `TESTS.md`:

- Confirmed against live source that no second durable claims table
  exists and no schema migration is needed for the new
  `FindingAssertion` fields.
- `git apply --check` against current `origin/master` (12+ commits
  ahead of the snapshot) failed on 3 of 29 files:
  - `docs/plans/topology-target.yaml` / `docs/topology-status.md` had
    drifted from unrelated intervening commits (both are generated) --
    regenerated with `devtools render topology-projection` +
    `render topology-status` instead of force-applying stale content.
  - `polylogue/storage/sqlite/archive_tiers/user_write.py` conflicted
    on one import line added by PR #3051, landed after the packet's
    snapshot. Reconciled by hand: 7 of 8 hunks applied clean via
    `git apply --reject`, the import added manually.
- Independently reran `devtools verify public-claims --json` (4
  claims, 9 artifacts, 3 monitored surfaces, 0 problems) and
  `devtools verify layering` (0 violations) -- both match the packet's
  own claimed output exactly, not just re-asserted from its prose.
- The packet flagged
`test_archive_tiers_api_archive_debt_reads_archive_consistency`
  ("database source_debt is locked") as a pre-existing baseline
  failure unrelated to its patch. Reproduced this independently on an
  unrelated worktree (clean master plus an unrelated annotations
  feature) to confirm it's a genuine environmental flake, not
  something introduced here.

## Verification

```
devtools test tests/unit/insights/measurement/test_public_claims.py \
  tests/unit/storage/test_public_claims_projection.py tests/unit/devtools/test_public_claims.py
-> 31 passed

devtools test tests/unit/scenarios/test_demo_archive_convergence.py \
  tests/unit/storage/test_archive_tiers_assertions.py tests/unit/devtools/test_generated_surfaces.py \
  tests/unit/devtools/test_release_readiness.py tests/unit/devtools/test_render_docs_surface.py \
  tests/unit/devtools/test_project_motd.py tests/unit/daemon/test_standing_queries.py tests/unit/cli/test_import.py
-> 84 passed

devtools test (6 affected tests/unit/api/test_facade_contracts.py cases)
-> 6 passed, 1 pre-existing unrelated flake (classified above, reproduced independent of this patch)

ruff format --check / ruff check (all 16 touched Python files) -> clean
mypy --strict (all 13 touched production/test modules) -> Success, no issues
devtools render all --check -> exit 0, no drift (includes regenerated topology docs)
devtools verify public-claims --json -> ok, 0 problems
devtools verify layering -> 0 violations
devtools verify --quick -> exit_code 0
```

Not run: the full non-quick `devtools verify` (testmon inner loop) and
the post-merge heavy CI `test` suite; per-PR CI intentionally skips it.

## Follow-ups intentionally deferred

- `polylogue-37t.14` (the shared evidence-integrity evaluator) is not
  yet landed. This PR defines the narrow consumer interface
  (`EvidenceIntegrityProvider.verdict_for`) it must implement; the
  three seeded findings currently render `unknown · unresolved`
  because no verdict/canonical judgment has been supplied yet -- this
  is the honest default, not a placeholder bug.
- Coverage is currently `README.md`, `docs/demos.md`,
  `docs/findings/claim-vs-evidence.md`; a future tracked launch-post
source should be registered against the `launch` preset when it exists.

Ref polylogue-3tl.16

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sinity added a commit that referenced this pull request Jul 18, 2026
…rtion preservation reads (#3101)

## Summary
Closes a latent residual in the assertion write-lock TOCTOU fix (#3051):
a caller-owned deferred transaction was never upgraded to hold the
SQLite write lock before the terminal-status preservation read.

## Problem
`#3051` fixed `upsert_assertion`'s TOCTOU race for the common case by
wrapping the preserve/read/write decision in `BEGIN IMMEDIATE` when the
connection is idle (`_immediate_user_write_transaction`). But its
fallback for an already-open transaction — `if conn.in_transaction:
yield; return` — never upgrades that transaction to hold the write lock.
A caller-owned deferred (plain `BEGIN`) transaction has not yet reserved
the SQLite writer slot, so the terminal-status preservation read taken
inside it can still race a concurrent operator judgment landing between
that read and this connection's eventual write — reintroducing the exact
silent-revert bug `polylogue-41ow` tracks, for any caller that reuses a
connection across a transaction it opened itself rather than a fresh
connection per call.

I audited every production caller of
`upsert_assertion`/`judge_assertion_candidate` (`annotations/write.py`,
`security/lifecycle.py`, `security/secret_scan.py`,
`scenarios/corpus.py`, `storage/repair.py`, `storage/raw_reconciler.py`,
and `user_write.py`'s own batch helpers): none currently reach these
functions with a caller-owned deferred transaction open, so this exact
gap is not yet exploitable in production — but it is latent, one
refactor away, the same character as the `vwia` writer-twin bug fixed
earlier in this hardening sweep (#3099).

## Solution
Closed it defensively. When the connection already has an open
transaction, open a `SAVEPOINT` and force a zero-row `UPDATE assertions
SET updated_at_ms = updated_at_ms WHERE 0` before yielding — this forces
SQLite to acquire the `RESERVED` lock immediately, before any
preserve/read decision runs, without committing or rolling back state
the caller owns. If the caller's transaction already holds the write
lock (the common in-repo case: a batch of
`upsert_mark`/`upsert_blackboard_note`/`upsert_saved_view`/`upsert_assertion`
calls sharing one `BEGIN IMMEDIATE` opened by the first call in the
batch), the forced write is a no-op. Also added the canonical
`busy_timeout` PRAGMA to the fresh-transaction branch.

Deliberately did **not** port the auto-commit-on-fresh-transaction
behavior from an available external delivery patch
(`feature/assertions/judgment-transaction`): tracing
`scenarios/corpus.py`'s intentional multi-call batch (five upserts
sharing one transaction, one final caller commit) confirmed that change
would silently split one atomic batch into five separate commits. Also
did not port that delivery's non-overlapping additive scope (evidence
previews, queue health, capture idempotency, canary script) — that's
feature delivery, tracked separately as `polylogue-2o3d`.

## Verification
- New regression:
`test_cross_connection_replay_inside_caller_owned_deferred_transaction_cannot_resurrect_operator_accept`
(`tests/unit/storage/test_archive_tiers_assertions.py`) — two real
SQLite connections; the detector opens a plain `BEGIN` (not `IMMEDIATE`)
before calling `upsert_assertion`, then a concurrent operator judgment
attempts to land between the detector's SELECT and its write.
- Anti-vacuity: reverted the source fix via `git stash`, keeping the new
test — it fails (operator resurrects the candidate within 0.15s); passes
after restoring the fix.
- `devtools test tests/unit/storage/test_archive_tiers_assertions.py
tests/unit/storage/test_archive_tiers_assertion_write_through.py
tests/unit/storage/test_comparative_judgment_assertions.py` → 61 passed
- `devtools test` across every other
`upsert_assertion`/`judge_assertion_candidate` write-path suite
(annotations, security, cli judge/note/candidates, mcp judgment tools,
storage user_audit/user_overlay/blackboard/public_claims,
scenarios/corpus demo seeding) → 128 passed, no batching regression.
- `devtools verify --quick` → exit 0.

Ref polylogue-41ow

Co-authored-by: Claude <noreply@anthropic.com>
Sinity added a commit that referenced this pull request Jul 21, 2026
## Summary

Closes the remaining conformance-law gaps in the OriginSpec admission
kernel
(`polylogue/sources/origin_specs.py`) against every clause of
`polylogue-2qx.1.1`'s acceptance criteria: a
public-origin/Provider-token leak
guard, a stream/parser binding parity check against dispatch, and a live
proof of the `lifecycle="reserved"` admission path.

## Problem

`polylogue-2qx.1.1` asked for the OriginSpec admission kernel (built on
the
`polylogue/declarations` DeclarationSpec kernel from `polylogue-o21.1`)
plus a
conformance law where missing parser, stream/parser conflict, ambiguous
detector order, absent fixture, undeclared coverage, leaked Provider
token,
and non-injective Provider-to-Origin collision each yield a
source-locatable
diagnostic.

Auditing the live repo found the kernel **already exists on master** —
`polylogue/sources/origin_specs.py` landed incrementally via unrelated
feature PRs (#3051, #3087, #3088, #3092, #3201, #3228: Claude Workflow
admission, Hermes ATOF/ATIF, the Grok parser, provider_completeness
migration) without ever citing this bead, so `bd`'s tracking never
reflected
it — the 2026-07-18 warroom sweep found no bead-tagged commits and reset
the
bead to open even though the code was there. It already covers all 11
`Origin` tokens, consumes the declarations kernel correctly, and is
wired
into `provider_completeness.py`, the artifact taxonomy, the live
watcher, and
Claude Code orchestration.

Auditing it clause-by-clause against the AC found three real gaps:

1. No diagnostic caught a public origin `public_name` colliding with a
raw
   `Provider`-wire token — the doctrine in
`docs/provider-origin-identity.md` ("no provider wording on public
origin
   surfaces") was enforced only indirectly (public_name must equal
   `origin.value`, and no current `Origin`/`Provider` pair happens to
collide), with no explicit guard or diagnostic for a future collision.
2. No check parity-verified declared `stream_parser_path` presence
against
`sources/dispatch.py:STREAM_RECORD_PROVIDERS` — a stream/parser binding
could silently drift from dispatch's actual streaming behavior with no
   diagnostic.
3. The module docstring still claimed a live "reserved origin" pilot,
but
Grok shipped a real parser (`polylogue-611`, #3201) after this bead was
written, so no `OriginSpec` is currently `lifecycle="reserved"` and that
   admission path had no live proof.

## Solution

- Added `_PROVIDER_TOKEN_VALUES` and a guard in
`OriginSpecRegistry.register()`
that rejects a declaration whose `public_name` collides with any
`Provider`
enum value, ordered before the existing public-name/origin equality
check
  so it is independently testable (a synthetic declaration can trip it
  without also tripping the equality check).
- Added `validate_stream_parser_parity()`, parity-checked against
  `sources/dispatch.py:STREAM_RECORD_PROVIDERS` the same way
`validate_dispatch_precedence()` already parity-checks detector
tightness
order. **Zero edits to `dispatch.py`** — only a new read-only import of
its
  existing `STREAM_RECORD_PROVIDERS` constant, respecting this slice's
ownership boundary with the concurrent `ingest_worker.py`/`decoders.py`
  lane.
- Updated the module docstring to honestly state Grok's promotion from
reserved to executable, and point at the new synthetic
reserved-lifecycle
test as the live proof of that admission path (since no real production
  `Origin` is currently reserved).
- Added five tests to `tests/unit/sources/test_origin_specs.py`:
undeclared-
  coverage rejection, provider-token-leak rejection, a synthetic
`lifecycle="reserved"` registration (built via `replace()` of the real
Grok
spec) proving the reserved admission contract requires no
parser/detector
tightness while still requiring coverage/fixture evidence, and positive
  plus negative stream/parser parity checks.

## Verification

- `devtools test tests/unit/sources/test_origin_specs.py` → 8 passed
- `devtools test tests/unit/sources/test_dispatch_ordering.py
tests/unit/sources/test_dispatch_payloads.py` → 21 passed
- `devtools test -k "provider_completeness or origin_specs or
dispatch_ordering"` → 26 passed
- `mypy --strict polylogue/sources/origin_specs.py
tests/unit/sources/test_origin_specs.py` → Success, no issues found
- `devtools verify --quick` → exit 0 (all 16 steps ok: format, lint,
mypy, render all, topology, layering, closure-matrix, schema roundtrip,
manifests, ci-workflows, doc-commands, docs-coverage,
test-infra-currency, test-clock-hygiene, pytest-timeout-overrides,
degrade-loudly)
- No new module/file added, so no topology projection regen was
required.

## AC matrix

| # | AC | Status |
| --- | --- | --- |
| 1 | `origin_specs.py` defines complete typed fields/lifecycle states,
consumes `polylogue/declarations` without adding source semantics to
that kernel | Satisfied (pre-existing on master; verified by reading
`polylogue/declarations/*` and confirming `origin_specs.py` only wraps
`DeclarationSpec`/`DeclarationRegistry`, adding no kernel-layer
semantics) |
| 2 | Claude Code / ChatGPT / reserved Grok pilots derive/validate
deterministic tightness, parser/assembly registration, public origin
values, coverage/completeness rows, fixtures, docs, reparse consequences
from one declaration each | Satisfied for Claude Code (executable,
tightness 60, stream+artifact-rule bindings) and ChatGPT (executable,
tightness 70). Grok itself is now executable (real parser shipped after
this bead was written, #3201) rather than reserved; the
reserved-lifecycle admission contract is proven live by this PR's new
synthetic test rather than by a real reserved origin, since every
current public `Origin` token is admitted as executable or
compatibility-only |
| 3 | `dispatch.py` uses derived registration/order or is parity-checked
by it; adding a synthetic executable origin requires one OriginSpec +
adapter + fixtures | Satisfied — `validate_dispatch_precedence()`
(pre-existing) plus this PR's new `validate_stream_parser_parity()`
parity-check `dispatch.py`'s
`RECORD_DETECTOR_PROVIDER_ORDER`/`STREAM_RECORD_PROVIDERS` without
restructuring dispatch.py |
| 4 | Missing parser / stream-parser conflict / ambiguous or cyclic
detector order / absent fixture / undeclared coverage / leaked Provider
token / non-injective collision each yield a source-locatable diagnostic
+ repair | Satisfied — missing parser, absent fixture, and non-injective
collision without policy were pre-existing `ValueError` raises (now also
covered by a dedicated undeclared-coverage test in this PR); ambiguous
detector order was pre-existing (`ambiguous_detector_tightness`); this
PR adds the previously-missing stream/parser-conflict diagnostic
(`stream_parser_parity_mismatch`) and leaked-Provider-token guard.
"Cyclic" detector order has no distinct failure mode beyond ambiguous
tightness, since tightness is a total order, not a graph |
| 5 | Provider stays in adapters, Origin is the public vocabulary,
Gemini/Drive-style collisions require an explicit collision policy |
Satisfied (pre-existing `collision_policy` field + registration guard,
exercised by `aistudio-drive`'s `Provider.GEMINI`/`Provider.DRIVE`
fiber) |
| 6 | Focused
declaration/dispatch/public-schema/completeness/fixture/mutation/render/quick
verification passes | Satisfied — see Verification section above |

`polylogue-2qx.1.2` (migrate every current origin onto OriginSpec,
delete
parallel inventories) is explicitly out of this slice's scope per the
bead's
own design text — it is largely already superseded in practice too (all
11
origins are already declared here and `provider_completeness.py` already
projects from `ORIGIN_SPECS`), but a formal audit of that bead's own AC
(exact-eleven-token enumeration, parallel-inventory deletion, dispatch
golden fixture) is left to whoever picks it up.

Ref polylogue-2qx.1.1

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
  * Prevented origin names from exposing internal provider terminology.
* Added validation to ensure origin evidence is complete before
registration.
  * Improved consistency checks for origins that support streaming data.
* **New Features**
* Added support for reserved-lifecycle origins used in fixtures,
including required supporting evidence without requiring parser
configuration.
* Added diagnostics for mismatches between streaming capabilities and
origin configuration.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude <noreply@anthropic.com>
Sinity added a commit that referenced this pull request Jul 21, 2026
…gue-2qx.1.2) (#3250)

## Summary

Audits and closes the remaining gap in polylogue-2qx.1.2 ("migrate every
current origin onto OriginSpec"). Most of this bead's scope was already
shipped to `master` untagged across
#3051/#3087/#3088/#3092/#3201/#3228/#3246
(closing `polylogue-2qx.1.1`'s notes confirm this). This PR verifies
that
prior work end-to-end, proves the parity checks actually catch
regressions
(not just pass today), and closes one concrete residual gap: a second,
un-declared provider-to-assembly-hook dispatch that Claude Code, Codex,
and
AI Studio/Drive depend on.

## Problem

`polylogue/sources/origin_specs.py` already declares all eleven `Origin`
tokens with lifecycle/detector-tightness/parser/fixture/coverage
bindings,
and `polylogue/sources/provider_completeness.py` already derives its
rows
from `ORIGIN_SPECS` (`PACKAGE_MODE_SPECS` is a tuple comprehension over
it,
parity-proven by
`test_provider_completeness_is_a_projection_of_every_origin_spec`).
Dispatch-order and stream-parser-binding parity are also already
mechanically checked (`validate_dispatch_precedence`,
`validate_stream_parser_parity`) against the real production values in
`sources/dispatch.py` (`RECORD_DETECTOR_PROVIDER_ORDER`,
`STREAM_RECORD_PROVIDERS`).

What was genuinely missing: the bead's design explicitly calls for
"Claude
Code and Codex specs [to] expose typed
assembly/orchestration/title/action
extension hooks (consumed later by 2qx.2, j2zz, ih67) — a typed field on
the spec, not another registry."
`polylogue.sources.assembly.get_assembly_spec()`
is exactly that second, un-declared provider dispatch
(`ProviderAssemblySpec` factory for
`Provider.CLAUDE_CODE`/`Provider.CODEX`/
`Provider.GEMINI`) — it existed in production but had no OriginSpec
declaration or parity check, so a caller had no way to discover the hook
from `origin_specs.py` and no test would catch it drifting from the real
registry.

Also: `docs/provider-origin-identity.md` documented
Provider/Origin/Source
doctrine but never pointed at `origin_specs.py` as the per-origin
admission
authority a reader should trust over any hand-maintained list.

## Solution

- `polylogue/sources/origin_specs.py`: added
`OriginSpec.assembly_spec_path`
  (`"module/path.py:ClassName"` or `None`) declaring which
`ProviderAssemblySpec` a given origin's provider wire binds. Populated
for
  the three origins with a real live hook: `claude-code-session` →
  `assembly_claude_code.py:ClaudeCodeAssemblySpec`, `codex-session` →
  `assembly_codex.py:CodexAssemblySpec`, `aistudio-drive` →
`assembly_gemini.py:GeminiAssemblySpec` (its `Provider.GEMINI` wire is
the
one `get_assembly_spec` keys on). Added
`validate_assembly_spec_parity()`,
  following the exact idiom of `validate_dispatch_precedence`/
`validate_stream_parser_parity`: it checks the declared field against
the
live `get_assembly_spec(provider)` return value rather than replacing
that
  registry with a second one in `origin_specs.py`.
- `tests/unit/sources/test_origin_specs.py`: two new tests — one
asserting
the three declared hook paths (and `None` for two origins without a live
hook), one asserting `validate_assembly_spec_parity(get_assembly_spec)
== ()`
plus the mutation shape (a resolver that always returns `None` makes
every
origin that declares a hook path report
`assembly_spec_parity_mismatch`).
- `docs/provider-origin-identity.md`: added an "Origin admission"
section
  naming `origin_specs.py` as the per-origin declaration authority and
  pointing at both live-production parity checks.
- No parallel hand-maintained inventory was deleted, because the audit
found
none left inside my ownership (`polylogue/sources/**`) — see the
residual
  below for the one still outstanding elsewhere.

### Residual found outside owned scope

`polylogue/cli/shell_completion_values.py:_ORIGIN_DESCRIPTIONS` is a
hand-maintained `dict[str, str]` of 8 of the 11 origin tokens (missing
`beads-issue`, `grok-export`, `unknown-export`) used for
shell-completion
help text, and it is **not** parity-checked against
`Origin`/`ORIGIN_SPECS`
the way `polylogue/agent_integration/spec.py:ORIGIN_MEANINGS` already is
(that one has a `RuntimeError` guard requiring exact `Origin`-enum order
match — already satisfies AC4, no action needed there). `cli/**` is out
of
this lane's ownership (per dispatch instructions, another lane owns it
concurrently); flagging as a follow-up rather than touching it here.

## Verification

- `devtools test tests/unit/sources/test_origin_specs.py
tests/unit/sources/test_provider_completeness.py` → **15 passed**
- `devtools test tests/unit/sources/ -k "origin_specs or
provider_completeness or dispatch or assembly"` → **144 passed**
- `devtools test tests/unit/sources/test_parsers_props.py` (protected
file) → **43 passed**
- `devtools verify --quick` → all 16 steps `ok`, `"exit_code": 0` (ruff
format/check, mypy --strict, render all,
topology/layering/closure-matrix, manifests, ci-workflows, doc-commands,
docs-coverage, test-infra-currency, test-clock-hygiene,
pytest-timeout-overrides, degrade-loudly)
- Anti-vacuity mutations, run manually then reverted (`git checkout
--`), each confirmed the *existing* production dependency actually fails
on the mutation before I added anything:
- Removing `_grok_spec()` from the registration loop →
`ORIGIN_SPEC_REGISTRY.diagnostics()` reports `missing_origin_spec` for
`grok-export`.
- Dropping Claude Code's `detector_tightness` below
`gemini_cli_session`'s (contradicting its real last-in-branch-order
position) →
`validate_dispatch_precedence(RECORD_DETECTOR_PROVIDER_ORDER)` reports
`dispatch_tightness_mismatch`.
- Deleting Codex's new `assembly_spec_path` declaration →
`validate_assembly_spec_parity(get_assembly_spec)` reports
`assembly_spec_parity_mismatch` for `codex-session` (this is the
mutation the new code in this PR is proven against).

## AC matrix (polylogue-2qx.1.2)

1. **Satisfied (pre-existing).** All eleven `Origin` tokens are declared
exactly once in `ORIGIN_SPECS`; `set(by_origin) == set(Origin)` is
asserted in
`test_origin_specs_cover_the_public_enum_and_admission_lifecycles`, and
`OriginSpecRegistry.diagnostics()` emits `missing_origin_spec` for any
omission (proven above).
2. **Satisfied (pre-existing + this PR).** Every executable origin
declares acquisition modes,
detector/parser/stream-parser/fixture/coverage/fidelity/reparse fields;
`claude-code-session` additionally declares 6 typed
`OriginArtifactRule`s for its
workflow/journal/transcript/sidecar/adopt-manifest/coordinator-stream
family. `grok-export` is `lifecycle="executable"` today (it shipped a
real parser via #3201/polylogue-611 after 2qx.1.1's pilot design assumed
it would stay reserved — documented at the top of `origin_specs.py`);
the `reserved` lifecycle contract itself is proven against a synthetic
variant since no current `Origin` is genuinely reserved.
`unknown-export` is `lifecycle="compatibility-only"` with explicit
fallback semantics; `beads-issue` is executable with `issue-jsonl`
acquisition and its own non-`accepted` completeness maturity caveat (no
harvested schema sample yet). This PR adds the Claude/Codex/AI-Studio
assembly hook declaration.
3. **Satisfied (pre-existing).**
`validate_dispatch_precedence`/`validate_stream_parser_parity`
parity-check tightness and stream-binding against
`sources/dispatch.py`'s real
`RECORD_DETECTOR_PROVIDER_ORDER`/`STREAM_RECORD_PROVIDERS`;
mutation-proven above (deleting/reordering a declaration fails).
4. **Satisfied (pre-existing) for `provider_completeness.py`; this PR
extends it to the assembly-hook axis.** `PACKAGE_MODE_SPECS` is a direct
tuple comprehension over `ORIGIN_SPECS`, parity-proven by
`test_provider_completeness_is_a_projection_of_every_origin_spec`.
`agent_integration/spec.py:ORIGIN_MEANINGS` is separately parity-guarded
against `Origin` at import time. **Deferred**:
`cli/shell_completion_values.py:_ORIGIN_DESCRIPTIONS` remains a stale,
un-parity-checked hand-maintained inventory — out of this lane's
ownership (`cli/**`), flagged as a residual above rather than a named
follow-up bead (small, mechanical, single-file fix for whichever lane
next touches CLI completions).
5. **Satisfied (pre-existing).** `aistudio-drive`'s
`provider_wires=(Provider.GEMINI, Provider.DRIVE)` with
`collision_policy` is registration-enforced
(`OriginSpecRegistry.register` raises `ValueError` if
`len(provider_wires) > 1` without a `collision_policy`, tested in
`test_origin_spec_rejects_missing_fixture_and_noninjective_collision_without_policy`);
`docs/provider-origin-identity.md` already documented the non-reversal
doctrine, and this PR adds the pointer from that doc to the enforcing
code.
6. **Misframed — recorded honestly rather than claimed satisfied.**
`polylogue-2qx.2` (Claude Code orchestration artifact admission) already
closed via PR #3088, and its own close reason states it shipped as a
`claude_workflow_materializer` convergence stage *without* the
OriginSpec migration this bead was meant to gate — the blocking edge was
explicitly force-closed as "over-blocking" because the merged
implementation disproves that ordering. So AC6 as written ("Claude/Codex
extension hooks are the only admission path used by 2qx.2...") cannot be
retroactively true for `2qx.2`. `j2zz` (Codex child-action lowering) and
`ih67` (Codex title enrichment) are still open; this PR's new
`assembly_spec_path`/`validate_assembly_spec_parity` gives them a real
typed admission point to consume going forward, but I did not modify
`assembly_codex.py`/`ih67`/`j2zz` scope — those remain their own beads'
work, not migrated by me here.

## Files touched

- `polylogue/sources/origin_specs.py`
- `tests/unit/sources/test_origin_specs.py`
- `docs/provider-origin-identity.md`

Ref polylogue-2qx.1.2

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Documentation**
- Added guidance on how origin metadata is declared, validated, and kept
aligned with runtime behavior.
- Documented checks for provider completeness and assembly-related
configuration.

- **Improvements**
- Added validation to detect mismatches between declared origin
capabilities and available assembly behavior.
- Added assembly configuration metadata for Claude Code, Codex, and AI
Studio origins.

- **Tests**
- Added coverage confirming assembly declarations and runtime parity
checks behave as expected.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude <noreply@anthropic.com>
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