Skip to content

Set up conductor.json#9

Merged
bokelley merged 1 commit into
mainfrom
conductor-json-3f01
Sep 20, 2025
Merged

Set up conductor.json#9
bokelley merged 1 commit into
mainfrom
conductor-json-3f01

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

This PR is autogenerated by Conductor.

Conductor lets you run coding agents in parallel. This PR adds scripts for setting up or running fresh copies of your software inside Conductor.

See https://docs.conductor.build/tips/migration-conductor-json for more info.

@bokelley bokelley merged commit 719b047 into main Sep 20, 2025
1 check passed
tescoboy pushed a commit to tescoboy/adcp-client that referenced this pull request Apr 14, 2026
Addresses review feedback:
- Removed standalone Implementation Traps section
- Folded accepted traps (adcontextprotocol#1-adcontextprotocol#6) into existing Common Mistakes table
- Dropped traps adcontextprotocol#7 (Accept header), adcontextprotocol#8 (Zod bug), adcontextprotocol#9 (pin version) per reviewer guidance
bokelley added a commit that referenced this pull request May 3, 2026
… adopters

Recipe #9 grows a "make construction errors observable" subsection — eager
registration at boot is the cleanest path, but lazy shapes (autoscale replicas
avoiding JWKS-storm, multi-tenant SaaS with mutable tenant tables, serverless
warm-start) are legitimate. The bug isn't lazy init per se; it's letting
construction throws fall into the host framework's default 500-HTML error
handler where MCP clients (correctly) report `discovery_failed`. Adopters who
defer should catch at the registration site and surface through their error
pipeline.

Recipe #16 fixes two pieces of overclaim flagged in expert review: (a) the
HTTP 500 HTML body is rendered by the host framework's default error handler,
not by the SDK; (b) closes with a generalization callout — the collision-check
error always names the framework-handler equivalent, so when the next
promotion-induced collision lands, follow the message.

`TenantRegistry.register` JSDoc tracks the same reframe so IDE hover stays in
sync with the migration recipe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bokelley added a commit that referenced this pull request May 3, 2026
…romoted tools (#1448)

* fix(server): migration hint on customTools collision with framework-promoted tools

`createAdcpServer` collision-check error now points at the platform handler that
supersedes a colliding `customTools` entry (e.g. `BrandRightsPlatform.updateRights`
for `customTools["update_rights"]`, promoted to a framework-registered first-class
tool in 6.7.0). The previous "rename or remove the handler" advice was misleading
for adopters carrying a pre-6.7 customTool registration across the version
boundary — the throw fires inside the request handler in lazy tenant-build setups
and surfaces as HTTP 500 HTML on every MCP probe, looking like a client-side
discovery regression (cf. adcp-client#1438 root cause analysis).

`docs/migration-6.6-to-6.7.md` adds recipe #16 with the audit recipe
(`grep -rn 'customTools.*update_rights'`) and the platform-handler swap, and the
breaking-changes preamble lists the collision alongside #10 and #11. The existing
"`update_rights` first-class tool" bullet cross-references the new recipe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(server): boot-vs-lazy register guidance for createTenantRegistry adopters

Recipe #9 grows a "make construction errors observable" subsection — eager
registration at boot is the cleanest path, but lazy shapes (autoscale replicas
avoiding JWKS-storm, multi-tenant SaaS with mutable tenant tables, serverless
warm-start) are legitimate. The bug isn't lazy init per se; it's letting
construction throws fall into the host framework's default 500-HTML error
handler where MCP clients (correctly) report `discovery_failed`. Adopters who
defer should catch at the registration site and surface through their error
pipeline.

Recipe #16 fixes two pieces of overclaim flagged in expert review: (a) the
HTTP 500 HTML body is rendered by the host framework's default error handler,
not by the SDK; (b) closes with a generalization callout — the collision-check
error always names the framework-handler equivalent, so when the next
promotion-induced collision lands, follow the message.

`TenantRegistry.register` JSDoc tracks the same reframe so IDE hover stays in
sync with the migration recipe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bokelley added a commit that referenced this pull request May 17, 2026
…1825)

signRequest / signWebhook / signResponse now refuse keys whose adcp_use
doesn't match the helper, with the same error codes the verifier raises
at step 8 (request_signature_key_purpose_invalid,
webhook_signature_key_purpose_invalid, response_signature_key_purpose_invalid).
Surfaces operator misconfiguration at signing time rather than at the
verifier, where the message is far from its cause.

- assertKeyPurpose centralizes the gate; called from all three sync
  entry points before any crypto runs.
- Storyboard negative-vector builder (#9 cross-purpose rejection)
  switched to prepareRequestSignature + manual produceSignature so it
  can keep signing with wrong-purpose keys to exercise the verifier's
  step-8 check. The KMS-shaped prepare/finalize split is the natural
  bypass for test-vector authors.
- request-signing-provider test fixed to use webhook-signing adcp_use
  for the signWebhookAsync sync/async equivalence check (was reusing a
  request-signing vector key, masked by the missing gate).
- New ResponseSignatureError + ResponseSignatureErrorCode in errors.ts;
  re-exported from client and server barrels parallel to the existing
  RequestSignatureError / WebhookSignatureError shapes.

Closes #1825.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bokelley added a commit that referenced this pull request May 17, 2026
)

* feat(signing): add signResponse for RFC 9421 §2.2.9 response signing (#1822)

Rounds out the signing surface with the missing direction: server→buyer
signed responses. signRequest / signWebhook / signResponse now share the
same prepare/finalize shape and SigningProvider async path.

- buildResponseSignatureBase resolves @status from the response and binds
  @authority (and optionally @target-uri / @method) to the originating
  request carried on ResponseLike.request.
- Default covered components: [@status, @authority], plus content-type +
  content-digest automatically when the response has a body — same shape
  as request signing. Extra components opt-in via additionalComponents.
- Tag: adcp/response-signing/v1. AdcpUse extended with 'response-signing'
  so signer-side JWKs can declare the binding now; verifier surface is a
  separate follow-up.
- @status is rejected in request-signing canonicalization with a clear
  error so misuse doesn't fall through to silent "component missing".

Closes #1822

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(signing): address review on #1823 — absolute URL contract + interop examples + AdcpUse widening note

- ResponseLike.request.url: document absolute-URL requirement and show
  Express / Lambda / Workers reconstruction. canonicalAuthority and
  canonicalTargetUri parse via new URL() and throw on relative paths;
  Express's req.url / req.originalUrl are path-only.
- signResponse: add Express / Fetch / Node http.ServerResponse adapter
  snippets so adopters know how to spread Record<string, string> headers
  into immutable Headers / setHeader loops.
- Changeset: note that AdcpUse widening with 'response-signing' is
  additive at runtime but requires exhaustive switch+never narrowers to
  add a case arm.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(signing): adcp_use purpose-binding gate on signer side (closes #1825)

signRequest / signWebhook / signResponse now refuse keys whose adcp_use
doesn't match the helper, with the same error codes the verifier raises
at step 8 (request_signature_key_purpose_invalid,
webhook_signature_key_purpose_invalid, response_signature_key_purpose_invalid).
Surfaces operator misconfiguration at signing time rather than at the
verifier, where the message is far from its cause.

- assertKeyPurpose centralizes the gate; called from all three sync
  entry points before any crypto runs.
- Storyboard negative-vector builder (#9 cross-purpose rejection)
  switched to prepareRequestSignature + manual produceSignature so it
  can keep signing with wrong-purpose keys to exercise the verifier's
  step-8 check. The KMS-shaped prepare/finalize split is the natural
  bypass for test-vector authors.
- request-signing-provider test fixed to use webhook-signing adcp_use
  for the signWebhookAsync sync/async equivalence check (was reusing a
  request-signing vector key, masked by the missing gate).
- New ResponseSignatureError + ResponseSignatureErrorCode in errors.ts;
  re-exported from client and server barrels parallel to the existing
  RequestSignatureError / WebhookSignatureError shapes.

Closes #1825.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(signing): expert review fixes on #1823 — @target-uri default, asymmetry callout, fixture test

Protocol + security + code-reviewer ran in parallel; convergent
actionable findings synthesized below. All deferred / follow-up items
are tracked as separate issues.

- RESPONSE_MANDATORY_COMPONENTS now includes @target-uri by default
  (was [@status, @authority]). Multi-tenant sellers can no longer emit
  signatures interchangeable across endpoints on the same authority,
  per RFC 9421 §B.2.5 examples. Wire-contract decision locked before
  any adopter ships.

- coverContentDigest JSDoc + changeset now call out the deliberate
  asymmetry vs signRequest: response defaults opt-out (always cover
  when body present), request defaults opt-in. An unbound response
  body is the most common cross-purpose footgun for response signing.

- Wire-format fixture test pins the signature base byte-by-byte against
  an independently constructed expected value, so an internal refactor
  to buildResponseSignatureBase that breaks wire-compat is caught (the
  round-trip tests alone are partially circular and would not catch it).

- assertKeyPurpose switch gets an exhaustive default arm using
  `_exhaustive: never` so a future AdcpUse widening trips tsc rather
  than silently falling through. Direct fix for the regression vector
  this PR itself just exercised.

- prepareRequestSignature / prepareResponseSignature / prepareWebhookSignature
  JSDoc explicitly states the no-gate semantics so adopters composing
  prepare* + own-signer know they need to call assertKeyPurpose themselves.
  Storyboard builder bypass is the documented use case.

- ResponseLike.request.url JSDoc warns about Host / X-Forwarded-* trust
  under proxy termination. Express's req.get('host') + req.protocol are
  attacker-controllable absent trust proxy + Host allowlist.

- RESPONSE_SIGNING_TAG JSDoc + changeset mark the v1 wire format as
  provisional until #1826 (verifyResponseSignature) lands and is
  exercised cross-SDK. The v1 suffix gives a clean v2 break path.

- additionalComponents test split into "@method adds" and
  "@target-uri is idempotent in defaults" cases so the dedup logic is
  exercised explicitly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(signing): bypass signer-side adcp_use gate for negative-vector webhook test

webhook-verifier-error-codes.test.js authors a wire payload signed with a
request-signing key to verify the verifier's step-8 cross-purpose
rejection (webhook_mode_mismatch). The new signer-side gate refuses such
keys before any payload is produced, masking what the test actually
exercises.

- signerKeyFor() now preserves adcp_use from the fixture (was stripped on
  reconstruction, breaking even valid webhook-signing tests).
- The cross-purpose case at the top of the file routes through a new
  signWebhookBypassingPurposeGate() helper that composes
  prepareWebhookSignature + node:crypto + finalizeRequestSignature —
  same pattern the storyboard request-signing builder uses for AdCP
  negative vector 009.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bokelley added a commit that referenced this pull request May 18, 2026
… 100% coverage

Two updates after the spec evolution beyond the previous refresh:

1. New lesson #9 covers the `canonical-projection-ref` object shape
   (commit 1c19b3d075) and the architectural commitment to "no new
   canonicals" — broadcast / DOOH / native / generative all resolved
   via sibling refinement fields (asset_source, slots_override,
   applies_to_channels) rather than format_kind multiplication. The
   12-branch discriminated union stays at 12 branches even as the
   protocol grows new media types.

2. Coverage section updated: 41/57 → 50/50 at 3.1 GA (commit
   84a43fa932 closed every catalog annotation gap). Card scaffolding
   (7 entries) correctly split into a separate ui-element-formats.json
   since cards aren't ad formats. Migration table and catalog source-
   of-truth section reflect the new numbers and the file split.

Adds a "Why no new canonicals matters" subsection making explicit
that `format_kind` expresses creative asset shape; delivery medium /
channels / measurement live in product-level fields. A buyer doing
format-kind switching pre-filters by channel; format_kind is "what
shape creative does this product accept," never "where does it run."

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bokelley added a commit that referenced this pull request May 18, 2026
)

* docs(development): draft 8.0 design proposal for AdCP 3.1 support

Standalone design proposal for how the SDK should expose AdCP 3.1
(canonical formats, version envelope, expanded capabilities) without
forcing adopters to think about v1 vs v2 shapes.

The proposal lays out: auto-negotiation per agent via supported_versions;
a single dual-shape Product type that always carries format_ids and
populates format_options when projectable; bidirectional v1<->v2
projection with a structured Diagnostic surface (FORMAT_PROJECTION_FAILED,
FORMAT_DECLARATION_DIVERGENT, CUSTOM_FORMAT_FETCH_FAILED) that's never
logger-only per the spec's resolution-order amendment; a centralized
fetchFormatSchema utility implementing the normative custom-format fetch
contract; versioned codegen under src/lib/types/v3.0/ and v3.1/.

Migration path: 7.x defensive fixes (PR #1807 already shipped); 8.0
ships canonical-formats enablement; 8.x hardens; 9.0 removes v1 paths
when AdCP 4.0 lands.

Explicit non-goals and open questions documented for reviewer feedback.
Draft for review only — no code changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(development): flip 8.0 design to V2-only mental model

Brian's review feedback on the draft: canonical formats aren't "new
functionality" — they're the V2 way of thinking about creatives, and
better. The "dual-shape Product exposed on the public type" framing was
the engineer's compromise; the right product position is to flip every
SDK consumer to V2 in 8.0 and make the SDK responsible for translating
v1 sellers to look V2-shaped.

Changes:

- Reframe "The question" as "The position" — 8.0 commits to V2 as the
  mental model, not as an additive surface.
- Add a "What V2 actually changes for the buyer's mental model" section
  capturing Brian's insight: V1 conflated "what does this publisher's
  inventory accept?" with "what can this creative agent build?" V2
  separates them — format_options lives on Product (tied to inventory),
  creative.supported_formats lives on creative-agent capabilities.
- Goal #1 changes from "zero forced migration" to "V2 is the mental
  model." Goal #2 changes from "one Product type carrying both
  representations" to "the SDK teaches V2 by hiding v1." Goal #3 drops
  the "opt-in for new functionality" framing entirely.
- "Dual-shape Product" architecture section becomes "V2-shaped Product,
  transparent v1 normalization." Product no longer carries top-level
  format_ids; legitimate ops needs (tracing the v1 named format) read
  format_options[i].v1_format_ref.
- Migration table updated: 8.0 is "the major that flips you to V2";
  adopter action is a search-and-replace from format_ids[] to
  format_options[]. 9.0 becomes mostly an internal retirement, not a
  second mental-model migration.
- Open question #3 (read-time vs lazy projection) resolved to read-time
  — lazy projection is incompatible with V2-only public types.
- New non-goal: "We don't expose v1 vocabulary on the public type."
  Explicit about why dual-shape is the wrong compromise.

The wire-level facts didn't change; the SDK's product position did.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(development): refresh 8.0 design with prototype findings

Lessons from the v1↔v2 projection prototype at PR #1815 land as a
new top-of-doc section, plus three subsections updated inline:

1. New "Lessons from the prototype" section captures the 8
   architectural refinements:
   - Catalog source-of-truth is 4-tier (AAO base + community mirror
     + adagents.json#/formats + per-placement format_options[]).
     The doc had treated it as 1-tier ("fetch from
     list_creative_formats").
   - Multi-size lossy advisory is a new diagnostic class emitted
     alongside the v1 emit, not instead of. Structural invariant
     relaxed.
   - Symmetric "not yet" buckets: v1_translatable: false (v2 side)
     and catalog_lacks_canonical_annotation (v1 side).
   - canonical_formats_only semantically overloaded.
   - Quantified coverage: 41/57 (72%) clean v1→v2; 5/5 single-size
     +7-emit multi-size v2→v1.
   - Registry reverse-lookup dormant at 3.1 GA (registry shrank to
     7 pure-structural fallbacks).
   - AAO convergence pattern resolved per-publisher format-id sprawl.
   - format_kind orthogonal to dimensional identity; affects
     codegen and adopter mental model.

2. Projection-layer section rewritten:
   - Documents the 4-tier catalog model with merge order (most-
     specific-wins).
   - Full resolution order for both v1→v2 and v2→v1 directions.
   - Diagnostic union expanded to include all 7 codes (3 spec, 4
     SDK-local) with prose for each.

3. V2-shaped Product table updated:
   - Single-size vs multi-size vs responsive vs canonical_formats_only
     vs v1_translatable: false outbound behavior all spelled out.
   - Multi-size fan-out documented as the productized path.

4. Migration path gains a "Coverage adopters can expect at 8.0 GA"
   subsection citing the prototype's coverage report.

Doc shape preserved (option C of the three options I offered):
Lessons section + sharpen affected subsections inline; no wholesale
rewrite of unaffected sections.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(development): refresh 8.0 design with canonical-projection-ref + 100% coverage

Two updates after the spec evolution beyond the previous refresh:

1. New lesson #9 covers the `canonical-projection-ref` object shape
   (commit 1c19b3d075) and the architectural commitment to "no new
   canonicals" — broadcast / DOOH / native / generative all resolved
   via sibling refinement fields (asset_source, slots_override,
   applies_to_channels) rather than format_kind multiplication. The
   12-branch discriminated union stays at 12 branches even as the
   protocol grows new media types.

2. Coverage section updated: 41/57 → 50/50 at 3.1 GA (commit
   84a43fa932 closed every catalog annotation gap). Card scaffolding
   (7 entries) correctly split into a separate ui-element-formats.json
   since cards aren't ad formats. Migration table and catalog source-
   of-truth section reflect the new numbers and the file split.

Adds a "Why no new canonicals matters" subsection making explicit
that `format_kind` expresses creative asset shape; delivery medium /
channels / measurement live in product-level fields. A buyer doing
format-kind switching pre-filters by channel; format_kind is "what
shape creative does this product accept," never "where does it run."

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(changeset): add empty changeset for docs-only PR #1809

The Changeset Check CI gate requires every PR to declare an empty or
non-empty changeset. This PR adds only a design proposal under
`docs/development/`; per CLAUDE.md docs don't need a release bump,
but the CI doesn't distinguish docs-only diffs.

Empty changeset is the spec-approved way to satisfy the gate without
triggering a version bump.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
andybevan-scope3 added a commit that referenced this pull request Jul 13, 2026
…guard

- #5: writeDiffFile degrades to a placeholder (not a hard fail) on an oversized
  diff / HTTP 406, so large PRs still get a human-flagged review.
- #6: coverage.md largest-file rule reconciled to the base-SHA checkout — read
  changes from the diff files, cite head line numbers from the diff's + side.
- #8: install-hooks.js no longer clobbers a foreign pre-commit hook (warns +
  prints how to chain the delegator instead).
- #9: WG-constitution fetch gets --max-filesize + a fail-open warning; the
  prompt/findings GITHUB_OUTPUT heredocs use randomized sentinels (was fixed,
  a predictable-sentinel injection risk).
- #10: reviewer prompt no longer claims the delta diff is intersected/trivial-
  filtered (the API compare diff is not); wording now matches reality.
- CI dist guard: .secretariat/ai-review/scripts/check-dist.sh + a workflow that
  rebuilds each node action and fails if committed dist/ is stale — the real
  backstop for the bypassable pre-commit hook.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
andybevan-scope3 added a commit that referenced this pull request Jul 13, 2026
…tion (#2354)

* feat(aao-secretariat): fork Scope3 review action tree (setup/reviewer/arbiter/review) into .github/aao-secretariat

Node/TS GitHub Action set forked from Scope3's Argus review action and adapted
for AdCP: validated findings-json contract, arbiter decides via a constrained
submit_decision enum, auth via the AAO Secretariat App, pull_request_target
head-read handling, and the WG constitution fetched from adcp@main at review time.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(aao-secretariat): add repo-root AAO-SECRETARIAT.md; fence action tree from published package

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(aao-secretariat): cut ai-review.yml over to the forked TS action; retire bash reviewer

Supersedes the bash Argus reviewer (incl. #2338's inline WG-constitution/App-identity
edits, now carried by the TS reviewer composite + orchestrator). Keeps
pull_request_target base-SHA checkout + head fetch + workflow-mod gate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(aao-secretariat): drop write-capable gh grant from reviewer allowlist

With CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=0 the installation token is in the Bash env;
the `gh api repos/*/issues/*` grant allowed a POST, so fork-PR prompt-injection
could exfiltrate the token via an issue comment. The reviewer posts inline comments
through the MCP tool, not Bash gh, so the grant is unnecessary. Removed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(aao-secretariat): add empty changeset (no-release; dev-tooling only)

Root-level files (AAO-SECRETARIAT.md, .prettierignore) map to the @adcp/sdk root
package (workspaces includes "."), so `changeset status` requires an entry. This
PR ships no library change, so an empty (no-release) changeset satisfies the gate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(aao-secretariat): source setup's diff from the GitHub API; drop pull_request_target head fetch

CodeQL flagged actions/untrusted-checkout (critical) on the `git fetch <head>`
step: fetching PR-head code in a privileged pull_request_target workflow. setup
now derives changed files (pulls.listFiles), the delta (compareCommits), and the
diff patches (diff media type) from the GitHub API — matching the pattern in
adcontextprotocol/adcp and this repo's prior reviewer — so the head is never
fetched, checked out, or executed. Removed the fetch step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(aao-secretariat): drop redundant mergeable reassignment in setup

github-code-quality flagged the initial `let mergeable = true` as always
overwritten. The catch re-assigned the same default; removing it makes the
initial value the transient-failure default, resolving the finding.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor(secretariat): move review action tree to .secretariat/ai-review

Relocates the forked review action tree from .github/aao-secretariat/ to a
root-level, dot-prefixed .secretariat/ai-review/ (Option C: the Secretariat's
ai-review desk). The dot prefix marks it as repo infrastructure (like .github)
and keeps it out of glob-based tooling; root placement matches the actions-repo
layout and simplifies the rebuild hook. Rewires uses:/paths-ignore/mod-gate/
codeql/prettierignore refs. Identity (AAO-SECRETARIAT bot, labels, AAO-SECRETARIAT.md,
input names) is unchanged — the desk vs argus naming call is still pending.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(secretariat): rewire workflow/codeql/prettierignore to .secretariat/ai-review

The tree-move commit missed these three reference files (staging error), leaving
the workflow uses:/paths-ignore/mod-gate pointing at the removed
.github/aao-secretariat path. Point them at .secretariat/ai-review.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(secretariat): add pre-commit dist-rebuild hook (self-contained; wired via install-hooks.js)

Keeps the setup/arbiter committed dist/ in sync with source: when a staged change
touches a node action's src/build-config, rebuild that action and re-stage its
dist/. Logic lives in .secretariat/ai-review/scripts/precommit.sh so it travels
with the tree (Phase-2 extraction); install-hooks.js installs a thin delegating
pre-commit that calls it. No husky, no core.hooksPath change — existing
commit-msg/pre-push hooks are untouched. Fast no-op for commits that don't touch
the tree.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(secretariat): fail closed on unreliable PR surface; drop write-capable gh grant

Review deep-dive fixes:
- #1/#2: computePrSurfaceFiles now returns {files, reliable}. reliable=false on a
  pulls.listFiles error OR the 3000-file cap; setup fails closed (throws) rather
  than clearing the high-risk/gated gates on an incomplete surface — a transient
  API blip or huge PR can no longer let a security-critical PR auto-approve.
- #3: removed the write-capable `gh api repos/*/contents/*` grant from the reviewer
  allowlist (gh api can't be method-restricted, and with ENV_SCRUB=0 the token is
  in the Bash env → prompt-injection exfil path). The agent now reads changes via
  the diff files + gh pr diff. Also removed # comment lines from inside claude_args
  (that block is passed verbatim to the CLI as args).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(secretariat): deep-review follow-ups (#5,#6,#8,#9,#10) + CI dist guard

- #5: writeDiffFile degrades to a placeholder (not a hard fail) on an oversized
  diff / HTTP 406, so large PRs still get a human-flagged review.
- #6: coverage.md largest-file rule reconciled to the base-SHA checkout — read
  changes from the diff files, cite head line numbers from the diff's + side.
- #8: install-hooks.js no longer clobbers a foreign pre-commit hook (warns +
  prints how to chain the delegator instead).
- #9: WG-constitution fetch gets --max-filesize + a fail-open warning; the
  prompt/findings GITHUB_OUTPUT heredocs use randomized sentinels (was fixed,
  a predictable-sentinel injection risk).
- #10: reviewer prompt no longer claims the delta diff is intersected/trivial-
  filtered (the API compare diff is not); wording now matches reality.
- CI dist guard: .secretariat/ai-review/scripts/check-dist.sh + a workflow that
  rebuilds each node action and fails if committed dist/ is stale — the real
  backstop for the bypassable pre-commit hook.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(ci): set least-privilege permissions on the secretariat dist-check workflow

CodeQL flagged the new workflow for not restricting GITHUB_TOKEN. The job only
checks out, builds, and diffs — add a top-level `permissions: contents: read`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* style(secretariat): prettier-format install-hooks.js

The #8 edit introduced a formatting drift that failed the format:check lane.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <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