Skip to content

Claude/resume repos migration 9 o2 u1#30

Merged
hyperpolymath merged 3 commits into
mainfrom
claude/resume-repos-migration-9O2U1
Apr 19, 2026
Merged

Claude/resume repos migration 9 o2 u1#30
hyperpolymath merged 3 commits into
mainfrom
claude/resume-repos-migration-9O2U1

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

Changes

RSR Quality Checklist

Required

  • Tests pass (just test or equivalent)
  • Code is formatted (just fmt or equivalent)
  • Linter is clean (no new warnings or errors)
  • No banned language patterns (no TypeScript, no npm/bun, no Go/Python)
  • No unsafe blocks without // SAFETY: comments
  • No banned functions (believe_me, unsafeCoerce, Obj.magic, Admitted, sorry)
  • SPDX license headers present on all new/modified source files
  • No secrets, credentials, or .env files included

As Applicable

  • .machine_readable/STATE.a2ml updated (if project state changed)
  • .machine_readable/ECOSYSTEM.a2ml updated (if integrations changed)
  • .machine_readable/META.a2ml updated (if architectural decisions changed)
  • Documentation updated for user-facing changes
  • TOPOLOGY.md updated (if architecture changed)
  • CHANGELOG or release notes updated
  • New dependencies reviewed for license compatibility (PMPL-1.0-or-later / MPL-2.0)
  • ABI/FFI changes validated (src/abi/ and ffi/zig/ consistent)

Testing

Screenshots

claude and others added 3 commits April 19, 2026 22:37
…bilities (Tasks #33 + #34)

Closes P0 backlog items #33 and #34 in docs/handover/COORD-MCP-TODO.md.
Version bumped to 0.7.0 (cartridge.json + cartridge.ncl + boj_cartridge_version).

Task #33 — client_kind extension + free-form variant label
- ClientKind enum: added openai (4) + mistral (5) in Zig FFI and Idris
  ABI (SafeLocalCoord.idr); KIND_COUNT bumped 4 → 6 for reject-ring.
- Peer struct gains `variant: [32]u8 + variant_len` (alphanumeric +
  `.`/`-`/`_` only). New FFI:
    coord_set_variant(token, variant)
    coord_read_peer_variant(peer_idx, out, cap)
- Adapter `coord_register` accepts optional `variant` and `capabilities`
  blocks — invalid values roll back the register so the caller sees a
  clean 400. `coord_list_peers` output now includes a `variant` field.
- Durable log: peer_variant_set = 15 (new event type), with
  logPeerVariantSet + decodePeerVariantSet and replay-dispatch wiring
  so slot reuse after crash reconstructs variant correctly.

Task #34 — capability advertisement for cold-start routing
- Per-peer storage: class_csv (≤128B), tier (0=unset, 1..5), and
  prover_strengths CSV (≤256B). CSV alphabets restricted to
  [A-Za-z0-9._-+/,] so later JSON rendering stays injection-safe.
- New FFI:
    coord_set_capabilities(token, class, tier, provers)
    coord_read_peer_class / _tier / _provers
- Adapter tools (cartridge.ncl + cartridge.json):
    coord_set_variant        — post-register update
    coord_set_capabilities   — post-register update
    coord_get_peer_capabilities
      — returns {peer_id, kind, variant, tier, class[], prover_strengths[]}
        using the server-rebuilt canonical peer_id rather than echoing
        client input.
- Durable log: peer_capabilities_set = 16 with matching encode + decode
  + replay-dispatch.

Tests
- Extended `default role derives from client_kind` to cover openai /
  mistral → apprentice.
- New `set and read peer variant (Task #33)` — round-trip, rejection of
  invalid chars, slot-reuse clears variant.
- New `set and read peer capabilities (Task #34)` — round-trip, tier
  out-of-range rejection retains prior value, bad CSV char (`"`)
  rejected.

Notes
- Build + e2e verification deferred: Zig is not on PATH in this
  environment. Pattern for every new code path mirrors established
  idioms in the same file (@memcpy slices, std.io.fixedBufferStream,
  std.mem.splitScalar, std.mem.writeInt with `buf[p_off..][0..2]`).
- cartridge.json was hand-synchronised; note the pre-existing drift
  from cartridge.ncl (extra tools from Tasks #13..#15, #32, #35 live
  in .json only). Regenerating from Nickel would currently delete
  them; kept surgical until Nickel toolchain is available.
- D3 in TODO says `just cartridge-install` in 007-lang is gated on
  these tasks shipping — that unblock now applies.

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

https://claude.ai/code/session_01DobLJY3jgoso4M3z7xcZi8
From P1 in docs/handover/COORD-MCP-TODO.md. Single read-only tool that
returns a coord-wide snapshot so operators can monitor health without
walking every existing export individually.

Version → 0.8.0 (cartridge.json + cartridge.ncl + boj_cartridge_version).

FFI additions (all require a valid session token, -1 on bad token):
  coord_count_quarantine         — active quarantine entries
  coord_count_claims             — active task claims
  coord_count_track              — track-record ring fill
  coord_count_rejects_recent(k)  — rejects in the 10-min window for kind k
  coord_kind_in_cooldown(k)      — 1 if kind k is in reject-cooldown

Adapter:
  coord_health {token} → {
    peers:      { active, max, by_kind, by_role },
    quarantine: { pending, max },
    claims:     { active, max },
    track:      { entries, max },
    rejects:    { window_ms, cooldown_ms, recent_by_kind, in_cooldown: [...] }
  }
  Validates caller token via coord_count_rejects_recent(kind=0); first -1
  short-circuits to 401. Per-peer breakdown walks the 16 slots directly
  using the existing coord_read_peer_kind / _role exports.

Tests:
  `coord_health counts basics` — bad token → -1, valid token with one
  active claim reflects count, unseen kind has zero rejects, out-of-range
  kind returns -2.

Non-goals for this pass:
  - No historical / time-series data (spill to VeriSimDB is a separate
    P1 item).
  - No rate-limiting on the poll — loopback only, all callers are trusted
    session peers.

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

https://claude.ai/code/session_01DobLJY3jgoso4M3z7xcZi8
Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
@hyperpolymath hyperpolymath merged commit 408bf7f into main Apr 19, 2026
10 of 18 checks passed
@hyperpolymath hyperpolymath deleted the claude/resume-repos-migration-9O2U1 branch April 19, 2026 22:56
hyperpolymath added a commit that referenced this pull request Jun 8, 2026
…ards#91 / #100)

Refreshes docs/integration/hcg-tier2-rollout-runbook.md from v0.1
(draft, 2026-05-20, pre Phase-D) to v0.2 reflecting the current
state of the single-lane channel rooted at standards#91:

- §1.1 Phase D deliverables: tick D-1..D-3 + D-4 bootstrap with
  http-capability-gateway PR refs (#12 / #14 / #22 / #26 / #30) and
  the boj-server D-1 load-profile (#168) that joint-closed standards#99
  on 2026-06-01. The one remaining open item is the owner-driven
  perf-rebaseline workflow dispatch + `_status: scaffold-placeholder
  -> active` flip; called out explicitly rather than left as a stale
  unchecked checkbox.

- §1.4 BoJ-side prereqs: tick the three loopback-bind layers
  (#130 / #131 / #132), the Phase C TrustPolicy clause (#106), the
  NetworkPolicy (#173), and the SSE-route policy coverage (#165).
  The Trustfile `tier_2_gateway.status: PENDING` line stays
  intentionally unchecked - it's the §6.4 last-action target.

- §1.5 Gateway-side prereqs: tick the new
  `container/gateway-deploy.k9.ncl` from http-capability-gateway#38
  (2026-06-03), record what stays PLACEHOLDER until cerro-torre
  signing runs, and expand the smoke-test entry with the concrete
  allow/deny sequence boj-server#165 deferred.

- Header banner: replace the stale "Phase D has merged the scaffold
  only" Phase-D-dependency note with a current-state summary,
  bump version 0.1 -> 0.2, date 2026-05-20 -> 2026-06-08.

- CHANGELOG.md: Documentation entry under [Unreleased] summarising
  the refresh.

No code, infrastructure, or runtime behaviour changes. The runbook
is the operator-facing source of truth for what's gating the next
Phase E owner action; the drift it had was making "what's still
open" harder to read at a glance.

Refs hyperpolymath/standards#91
Refs hyperpolymath/standards#100

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request Jun 9, 2026
)

## Summary

Lands `config/gateway-policy-boj.yaml` — the **live** Verb Governance
Spec
the HCG tier-2 gateway loads via `POLICY_PATH` in staging (§2.1) and
production (§3.1) per the rollout runbook. The Phase A worked example
(`config/gateway-policy-boj-example.yaml`) is retained as the
documentation
artefact; the live file is now the operational one. Closes the
example→live
promotion item on the Phase E §1.5 checklist.

Single-lane HCG tier-2 channel (`standards#91`). Phase A (#96), B (#97),
C (#98), D (#99) are joint-closed; Phase E (`standards#100`) is the
active
phase, with multiple artefacts gating closure (§6.4 Trustfile flip is
the
last). This PR lands one tractable artefact; staging soak (§2),
production
traffic split (§3) and the §6.4 flip remain owner-driven.

## What this PR lands

- **`config/gateway-policy-boj.yaml`** — live policy file.
Content-identical
to `gateway-policy-boj-example.yaml` at promotion time. Header rewritten
  to reflect its live-file role (operational artefact, not pedagogical),
with `DEFAULT-DENY INVARIANT` reframed from "Phase A check" to
"permanent
invariant — must hold for every future gateway release". DSL v1
conformance
preserved; all 28 routes (`global_verbs: [GET, POST]`; per-route
`verbs`,
  `exposure`, `name`, `narrative`; `stealth_profile` on internal routes;
top-level `stealth: { enabled: true, status_code: 404 }`) carried
forward
  unchanged.
- **Runbook §1.5** — flips the trailing "still to be promoted from this
example before §3.1" note (on the existing `[x]` example-in-place line)
  to a discrete `[x]` item recording the live file's existence and the
divergence policy ("future BoJ-surface evolution lands in the live file;
  the example remains as the worked-example artefact").
- **Runbook §2.1 step 2** — switches staging `POLICY_PATH` from the
example
to the live file so staging exercises the same artefact that production
  will. Production §3.1 (which inherits §2.1's environment with the
  traffic-shift mechanism overlaid) needs no change.
- **Runbook header** — version 0.2 → 0.3; status line updated to
acknowledge
  the live-policy promotion.

## What this PR deliberately does NOT do

- **Close `standards#100`.** Per runbook §6.5 the joint-close happens
after
  the §6.4 Trustfile flip (`tier_2_gateway.status: PENDING → DEPLOYED`),
which itself follows the §3.3 100% production-soak window. Using `Refs`
  not `Closes` to match the established Phase E pattern (PRs #38, and
Phase D PRs #14, #22, #26, #30 — all `Refs`'d their phase issue and the
  owner joint-closed the issue once the final artefact landed). This
  deliberately diverges from the dispatch brief's literal "Closes
  hyperpolymath/standards#<phase-issue-number>" line in favour of the
canonical runbook §6.5 close-out discipline that the brief itself points
  to as the source of truth ("using the canonical sources"). The owner
  remains the sole closer of `standards#100`.
- **Touch the HCG deploy spec.** `container/gateway-deploy.k9.ncl` in
`hyperpolymath/http-capability-gateway` (PR #38) reads `POLICY_PATH` at
deploy time from the env, so the live-file cut-over is a runbook +
config
artefact change on the BoJ side, not a deploy-spec change on the gateway
  side. No companion PR on the gateway repo.
- **Diverge the live file from the example.** At promotion the two files
are content-identical. Future divergence is intentional and the live
file
  is authoritative; the example may be intentionally simpler.
- **Trigger any deploy.** No traffic shift, no staging cut-over, no §6.4
  flip happens at merge time. This is a static artefact landing.
- **Update the deploy spec's `POLICY_PATH` default.** The deploy spec
carries env-var declarations; the live-file path is operator-supplied at
  deploy time.

## Verification

- [x] DSL v1 conformance: `dsl_version: "1"`; `governance.global_verbs`
is
      `[GET, POST]`; every route has a non-empty `verbs`; `exposure ∈
      {public, authenticated, internal}`; `stealth.enabled` boolean,
      `stealth.status_code: 404` in 100..599.
- [x] All 28 example routes preserved unchanged in the live file (route
      count, `name`s, paths, verbs, exposures, narratives).
- [x] SPDX header `MPL-2.0` matches repo convention (config/, docs/).
- [x] Runbook §1.5 and §2.1 cross-references to
`gateway-policy-boj.yaml`
      and `gateway-policy-boj-example.yaml` resolve.
- [ ] Manual: `mix gateway.validate config/gateway-policy-boj.yaml`
      (gateway-side; can be run by the operator before §2.1 stand-up —
      see runbook §1.5 last open item, smoke-test).

## Channel position

```
standards#91 (parent, open)
├── #96 Phase A — closed (boj-server: contract + policy-authoring + example; gateway: -)
├── #97 Phase B — closed (gateway#10: mTLS primary path)
├── #98 Phase C — closed (gateway#11: strip; boj-server#106: TrustPolicy clause)
├── #99 Phase D — closed (boj-server#168 on 2026-06-01; gateway#12/#14/#22/#26/#30)
└── #100 Phase E — IN PROGRESS
     ├── E5 runbook draft — boj-server#128 (landed; rehearsal pending)
     ├── E1 loopback prereqs — boj-server#130/#131/#132/#165/#173 (landed)
     ├── E1 deploy spec — http-capability-gateway#38 (landed)
     ├── E1 live policy promotion — THIS PR (in review)
     ├── E1 .ctp signing — owner follow-up
     ├── E2 staging cut-over — owner follow-up
     ├── E3 telemetry verification — owner follow-up
     ├── E4 production rollout — owner follow-up
     └── §6.4 Trustfile flip + §6.5 joint-close — owner-only
```

Refs hyperpolymath/standards#91
Refs hyperpolymath/standards#100

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---
_Generated by [Claude
Code](https://claude.ai/code/session_012FiVM8R8FWBgBsUGpnXTZM)_

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request Jun 12, 2026
#210)

## Summary

Lands `scripts/hcg-policy-smoke.sh` — a checked-in smoke that exercises
the HCG tier-2 live Verb Governance Spec
(`config/gateway-policy-boj.yaml`) from outside the gateway. Replaces
the manual probe sequence the rollout runbook §1.5 last open item
formerly described as "out of band — operator pre-check".

Single-lane HCG tier-2 channel (`standards#91`). Phase A (#96), B (#97),
C (#98), D (#99) are joint-closed; Phase E (`standards#100`) is the
active phase. This PR lands one tractable artefact (§1.5 operator
pre-check now checked-in and reproducible); staging soak (§2),
production traffic split (§3), and the §6.4 Trustfile flip remain
owner-driven.

## What this PR lands

- **`scripts/hcg-policy-smoke.sh`** — POSIX-conformant bash + curl, no
  jq/yq dependency.
  - **Deny mode (default)**: sends one no-trust-header probe to every
    non-public route in the live policy (25 routes spanning the 19
    authenticated and 6 internal+stealth entries) and asserts a 4xx
    response. The 4xx assertion covers both bare 403 and stealth-profile
    codes regardless of the gateway's `:stealth_profiles` runtime
    config. Plus a default-deny verb canary (DELETE /cartridges, PUT
    /health, PATCH /cartridges) confirming `global_verbs: [GET, POST]`
    enforces the ADR-0004 verb-governance invariant for un-listed verbs.
    Gateway-internal — BoJ does **not** have to be reachable.
  - **`--with-backend` mode**: additionally probes the allow path with
    `X-Trust-Level: authenticated` (and `internal` for internal+stealth
    routes), asserting the response is NOT a gateway-origin 4xx (2xx /
    3xx / 5xx all pass — BoJ's own status is fine; only a gateway deny
    is a failure). Requires BoJ reachable at the gateway's `BACKEND_URL`
    and the script to run from a trusted-proxy IP so the trust header is
    not stripped by the gateway's `strip_untrusted_headers` plug.
  - Exits 0 on all-PASS, 1 on any FAIL (with per-probe summary), 64 on
    usage error.

- **Runbook §1.5** — last unchecked operator pre-check item flips from
  a free-form "stand the gateway up ... exercise one allow + one deny
  per route" sequence (which was deferred to boj-server#165's test plan
  and documented as out-of-band) to a single
  `scripts/hcg-policy-smoke.sh` invocation. The PASS/FAIL summary
  attaches to the cut-over ticket; a single FAIL is a stop-the-rollout
  condition with the three failure modes named (policy not enforcing,
  BoJ unreachable, non-trusted-proxy caller stripping the header).

- **Runbook header** — version 0.3 → 0.4; date 2026-06-09 → 2026-06-10;
  status line acknowledges the smoke script landing alongside the
  existing live policy promotion.

- **Runbook Appendix B** — new cross-reference entry for
  `scripts/hcg-policy-smoke.sh`.

## What this PR deliberately does NOT do

- **Close `standards#100`.** Per runbook §6.5 the joint-close happens
  after the §6.4 Trustfile flip (`tier_2_gateway.status: PENDING →
  DEPLOYED`), which itself follows the §3.3 100% production-soak
  window. Using `Refs` to match the Phase E PR convention established
  by #208 / #38 / #168 and documented in §6.5 ("Do not self-close
  standards#100; joint-close is owner-only per the single-lane channel
  discipline"). The owner remains the sole closer of `standards#100`.
- **Touch HCG.** This is a BoJ-side artefact: the script lives in
  `scripts/`, reads `config/gateway-policy-boj.yaml`, and probes the
  gateway over HTTP. No companion PR on the gateway repo required.
- **Run during CI deployment.** The script is checked in but only the
  operator's explicit invocation against a live gateway URL exercises
  it. CI does not stand up a gateway to run it (would require an
  external service); the script is intentionally operator-driven, with
  the PASS/FAIL summary attached to the cut-over ticket as the
  evidence-of-pre-check artefact.
- **Diverge the policy from the script's route matrix.** The script's
  route matrix mirrors the 25-route live policy. When the policy file
  evolves (new BoJ surface routes wired in), the script must be updated
  in lock-step — that is a benefit not a cost (the script doubles as a
  policy-completeness checklist), but it must be observed.

## Verification

- [x] `bash -n scripts/hcg-policy-smoke.sh` — syntax check passes.
- [x] `scripts/hcg-policy-smoke.sh` (no args) — exits 64 (usage error).
- [x] `scripts/hcg-policy-smoke.sh --help` — exits 64 with full help.
- [x] Against a synthetic always-403 mock on :18443 — `PASS=28 FAIL=0`,
      exits 0 (deny-only mode covers all 25 policy routes + 3 verb
      canaries).
- [x] Against a closed port (no gateway up) — every probe FAILs with
      `got=000 expected=deny`; exits 1 with the FAIL line summary.
- [x] SPDX header `MPL-2.0` matches repo convention (scripts/, docs/).
- [x] Runbook cross-references resolve (`§1.5`, Appendix B, sibling
      docs).

## Channel position

```
standards#91 (parent, open)
├── #96 Phase A — closed (boj-server: contract + policy-authoring + example; gateway: -)
├── #97 Phase B — closed (gateway#10: mTLS primary path)
├── #98 Phase C — closed (gateway#11: strip; boj-server#106: TrustPolicy clause)
├── #99 Phase D — closed (boj-server#168 on 2026-06-01; gateway#12/#14/#22/#26/#30)
└── #100 Phase E — IN PROGRESS
     ├── E5 runbook draft — boj-server#128 (landed; rehearsal pending)
     ├── E1 loopback prereqs — boj-server#130/#131/#132/#165/#173 (landed)
     ├── E1 deploy spec — http-capability-gateway#38 (landed)
     ├── E1 live policy promotion — boj-server#208 (landed)
     ├── §1.5 operator pre-check smoke — THIS PR (in review)
     ├── E1 .ctp signing — owner follow-up
     ├── E2 staging cut-over — owner follow-up
     ├── E3 telemetry verification — owner follow-up
     ├── E4 production rollout — owner follow-up
     └── §6.4 Trustfile flip + §6.5 joint-close — owner-only
```

Refs hyperpolymath/standards#91
Refs hyperpolymath/standards#100

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---
_Generated by [Claude
Code](https://claude.ai/code/session_01SE4pkWg8SEKsSWK9geD5r9)_

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request Jun 16, 2026
## Summary

Phase E §3 traffic-shift sign-off has four success criteria (rollout
runbook §3.1). The runbook §4 names the signals that gate sign-off at
the human level — p99 latency, throughput, circuit-breaker state, 5xx
rate, policy reload counter, trust-level decision distribution, plus
three BoJ-side signals — but stops short of giving the on-call a query
they can paste. This PR adds
`docs/integration/gateway-observability-spec.md` to fill that gap.

For every runbook §4.1 + §4.2 signal, the spec wires:

1. The **telemetry event** emitted by the gateway (audit document §5 /
§1.6).
2. The **Prometheus metric** the `telemetry_metrics_prometheus_core`
reporter exports for that event, anchored to the canonical declaration
in `http-capability-gateway/lib/http_capability_gateway/application.ex`
`telemetry_metrics/0` (lines 259–296).
3. A **PromQL query template** the operator pastes verbatim into a
dashboard panel or alert rule.
4. An **alert threshold** anchored to a canonical source — the rollback
runbook §5.1 trigger value, the perf contract tolerance ratio, or the
load-profile §2 SLO budget. Absolute-µs values that depend on Phase D-4
baseline collection are left as `${BASELINE_*}` placeholders with the
lookup site (`bench/baseline.json` after `_status` flips to `active`)
named — not invented numbers.

§5 closes the loop with a table mapping every runbook §5.1 rollback
trigger to the PromQL alert rule in this spec, plus three follow-up gaps
surfaced honestly:

- **Circuit-breaker state** — no dedicated telemetry event today; the
503 spike + log inspection is the interim signal. Spec flags
`[:http_capability_gateway, :circuit_breaker, :state_change]` as a
post-Phase-E gateway follow-up.
- **Policy reload counter** — logged via `Logger.info`, not telemetry.
Treat as log-based until the event is added.
- **VeriSimDB write failures** — cast-only (audit §4), no metric surface
today. Phase E §1.3 already lists VeriSimDB integration as an `!OWNER:`
confirmation; the metric-side consequence is recorded here.

Edits the rollout runbook §4 lead-in and Appendix B cross-reference list
to point at the spec, so an operator landing in §4 can find the queries
without grep. No changes to the §4 signal list itself or to any
§1/§3/§5/§6 procedure — the runbook stays normative; the spec is its
declarative half.

## What this PR does NOT do

- Does not invent absolute percentile budgets (those live in
`bench/baseline.json` after D-4).
- Does not commit a dashboard URL (the `!OWNER:` rows in runbook §4.3
stand).
- Does not pre-empt the §6.4 Trustfile flip (`tier_2_gateway.status`
stays `PENDING`).
- Per single-lane HCG channel discipline (pattern set in
http-capability-gateway PRs #14, #22, #26, #30, #38 and boj-server PRs
#168, #173, #224): joint-close is owner-only. This PR **refs but does
not close** `standards#100`.

## Test plan

- [ ] Review `docs/integration/gateway-observability-spec.md` end-to-end
— verify the cited line numbers in
`http-capability-gateway/lib/http_capability_gateway/application.ex`
(259–296) and `lib/http_capability_gateway/gateway.ex` (228–232, 411)
match the current gateway main (commit `46116cf` at PR open time).
- [ ] Verify the metric naming convention
(`http_capability_gateway_<event>_<measurement>_<suffix>` with `_total`
on counters and `_bucket`/`_count`/`_sum` on distributions) matches
`TelemetryMetricsPrometheus.Core.scrape()` output against a locally
running gateway. If the naming convention diverges from this spec, the
spec is wrong — open a fix-up PR.
- [ ] Verify the rollout runbook §4 back-link renders correctly in
GitHub's markdown viewer.
- [ ] Verify no Hypatia / governance / spdx gates fire on the new file
(matches the existing `gateway-load-profile.md` MPL-2.0 + SPDX header
shape).

Refs hyperpolymath/standards#91
Refs hyperpolymath/standards#100

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---
_Generated by [Claude
Code](https://claude.ai/code/session_01MkuwduQrd7anDHzGNZhvGj)_

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request Jun 19, 2026
The HCG live policy header records a manual re-verification stamp
("Re-verified 2026-05-28 against `BojRest.Router`") confirming that
every wired BoJ HTTP route is covered by a Verb Governance Spec rule.
The ADR's largest declared risk is "policy lagging the surface" — a
new wired route landing without a matching policy rule would default-
deny in production (an outage on a route that should be live),
silently exposing the §1.5 manual-check failure-mode this stamp is
meant to gate.

This script makes the same check machine-checkable:

  - Extract `(verb, path-template)` tuples from
    `elixir/lib/boj_rest/router.ex` (Plug.Router `get "/..."` /
    `post "/..."` lines).
  - Extract `(verb, path-pattern, ...)` tuples from
    `config/gateway-policy-boj.yaml` (the live policy promoted in
    Phase E §1.5).
  - For each wired route, concretise its `:name`-style placeholders
    with a known probe segment and assert at least one policy rule
    matches (literal equality for non-regex paths; ERE `grep -E`
    against the concrete URL for `^...` regex paths).
  - Exit 0 on no drift, 1 on drift, 64 on bad usage.

Sits alongside `scripts/hcg-policy-smoke.sh`: the smoke script runs
*against a live gateway* to confirm the policy enforces as declared
(deny/allow paths, stealth-status canaries); this script runs *against
the source files* to confirm the policy still covers the wired
surface. Together they bracket the two halves of the §1.5 pre-
rollout verification — surface→policy coverage (this) and policy→
gateway enforcement (smoke).

Hardens the §1.5 pre-rollout posture without changing any policy
content, runbook procedure, or gateway code. The runbook can adopt
this script as the §1.5 surface-drift check in a follow-up PR; this
PR lands the artefact only.

Per single-lane HCG channel discipline (pattern set in
http-capability-gateway PRs #14, #22, #26, #30, #38 and boj-server
PRs #168, #173, #224, #226): joint-close is owner-only. This commit
refs but does not close standards#100.

Refs hyperpolymath/standards#91
Refs hyperpolymath/standards#100

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request Jun 19, 2026
## Summary

Adds `scripts/hcg-surface-drift-check.sh`: a static, source-only audit
that asserts every wired `BojRest.Router` route is covered by at least
one rule in the HCG live Verb Governance Spec
(`config/gateway-policy-boj.yaml`).

The ADR's largest declared risk is **"policy lagging the surface"** —
a wired route landing without a matching policy rule would default-deny
in production (an outage on a route that should be live). The live
policy header carries a manual re-verification stamp
(`Re-verified 2026-05-28 against BojRest.Router`) which is the only
check today that catches this; the §1.5 prerequisite checklist relies
on the same manual procedure. This script makes the check
machine-checkable without changing any policy content, runbook
procedure, or gateway code.

### What the script does

1. Extracts `(verb, path-template)` tuples from
   `elixir/lib/boj_rest/router.ex` (Plug.Router `get "/…"` / `post "/…"`
   etc.).
2. Extracts `(verb, path-pattern)` tuples from
   `config/gateway-policy-boj.yaml`.
3. For each wired route, concretises `:name`-style placeholders with a
   known probe segment and asserts at least one policy rule matches
   (literal equality for non-regex paths; ERE `grep -E` match against
   the concrete URL for `^…` regex paths).
4. Exit 0 on no drift, 1 on drift detected, 64 on bad usage.

### Bracket-style relationship with `hcg-policy-smoke.sh`

- **Smoke script** (`hcg-policy-smoke.sh`) — runs against a *live
  gateway* to confirm the policy enforces as declared (deny/allow
  paths, stealth-status canaries, default-deny no-match canary).
- **Drift check** (this PR) — runs against the *source files* to
  confirm the policy still covers the wired surface.

Together they cover both halves of the §1.5 pre-rollout verification:
surface→policy coverage (drift) and policy→gateway enforcement (smoke).

### What this PR does NOT do

- Does **not** modify the rollout runbook §1.5. Adoption as the §1.5
  surface-drift check is a separate, owner-driven PR; this PR lands
  the artefact only so the runbook update is a one-line wiring change.
- Does **not** wire the script into CI. Boj-server's CI discipline
  (`docs/wikis/CI-and-Required-Checks.adoc` / `.claude/CLAUDE.md`)
  requires path-filtered required checks to use the "always-trigger +
  changes job" pattern; a CI wiring PR should follow that pattern.
  Out of scope here.
- Does **not** modify any policy file. Today's surface and today's
  policy are in agreement (the 2026-05-28 re-verification still holds;
  the script run on this commit's working tree returns OK on the seven
  wired routes: `/.well-known/boj-node-pubkey`, `/health`, `/menu`,
  `/cartridges`, `/cartridge/:name`, `/cartridge/:name/invoke`,
  `/cartridge/:name/sse`).
- Does **not** pre-empt the §6.4 Trustfile flip
  (`tier_2_gateway.status` stays `PENDING`).
- Per single-lane HCG channel discipline (pattern set in
  `http-capability-gateway` PRs #14, #22, #26, #30, #38 and `boj-server`
  PRs #168, #173, #224, #226): joint-close is owner-only. **This PR
  refs but does not close `standards#100`.**

### Channel state note

This session could not read `hyperpolymath/standards#91` / `#100` (the
session's repository scope is restricted to `http-capability-gateway`
and `boj-server`), so the brief's instructed status comment on
`standards#91` could not be posted. State was reconstructed from the
canonical sources in this repo (ADR-0004, the integration plan, the
audit, the rollout runbook, the live policy, and the merged-PR
commit history) plus the current `main` of both in-scope repos. The
analysis: Phase A/B/C/D are closed (artefacts merged, runbook §1.2 and
the Phase-D status note in the runbook header confirm); Phase E
(`standards#100`) is the only open phase; all remaining §1 checklist
items are owner-driven (`!OWNER:` placeholders, D-4 rebaseline
workflow_dispatch, cerro-torre `.ctp` signing, the §6.4 Trustfile flip).
This PR advances Phase E §1.5 ("Gateway-side prerequisites") by
converting one manual sub-check into an executable artefact, without
crossing into any owner-input territory.

## Test plan

- [ ] Run the script on this branch's working tree: `bash
  scripts/hcg-surface-drift-check.sh` — expect exit 0, "OK: every wired
  router route is covered by at least one policy rule." with the
  wired-count = 7 and the policy-count matching the rule total in
  `config/gateway-policy-boj.yaml`.
- [ ] Run `bash scripts/hcg-surface-drift-check.sh -v` — expect the
  same exit 0 plus a `Matched:` block listing each of the seven wired
  routes against its policy rule (literal `/health` → literal rule;
  `/cartridge/:name/invoke` → `^/cartridge/[A-Za-z0-9_.-]+/invoke$`
  regex; etc.).
- [ ] Synthetic drift test: temporarily add a wired route to the
  router (e.g. `get "/__drift_test__" do …`) without a policy rule;
  re-run and expect exit 1 with the route listed under `DRIFT:`.
  Revert before merge.
- [ ] Confirm `shellcheck scripts/hcg-surface-drift-check.sh` is clean
  (matches `scripts/hcg-policy-smoke.sh`'s shellcheck posture).
- [ ] Confirm SPDX header + Owner copyright match the canonical estate
  format (matches `scripts/hcg-policy-smoke.sh`'s header shape).
- [ ] Verify no Hypatia / governance / spdx gates fire on the new
  script file.

Refs hyperpolymath/standards#91
Refs hyperpolymath/standards#100

🤖 Generated with [Claude Code](https://claude.com/claude-code)


---
_Generated by [Claude
Code](https://claude.ai/code/session_01JuztZ5kyDr3AqGtUsBipDL)_

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request Jun 20, 2026
…229)

## Summary

Wires `scripts/hcg-surface-drift-check.sh` (landed in boj-server#228,
merged 2026-06-19) into GitHub Actions, so the surface⊆policy invariant
the ADR calls its largest declared risk is re-proven on every PR rather
than relying on the manual re-verification stamp in
`config/gateway-policy-boj.yaml`'s header.

PR #228 explicitly flagged this CI wiring as the follow-up step — "a CI
wiring PR should follow [the always-trigger + changes-job] pattern. Out
of scope here." This is that follow-up; the script, the router, and the
policy are unchanged.

## What lands

A single new file: `.github/workflows/hcg-surface-drift.yml`. The
workflow follows the boj-server "always-trigger + changes-job" pattern
documented in `docs/wikis/CI-and-Required-Checks.adoc` and
`.claude/CLAUDE.md` §"CI / Required Status Checks":

- **No `on.*.paths`** — the check is always created. A path-filtered
required workflow that never fires is the failure mode that stranded
#213/#215 until #216 fixed it; this gate is built to never re-introduce
it, regardless of whether it later joins `required_status_checks`.
- **Lightweight `changes` job** recomputes relevance via `git diff
origin/<base>...HEAD` against the four paths this gate cares about —
router (`elixir/lib/boj_rest/router.ex`), live policy
(`config/gateway-policy-boj.yaml`), the drift script
(`scripts/hcg-surface-drift-check.sh`), and the workflow file itself.
Fail-safe to `run=true` on any diff failure.
- **Heavy `check` job** is `needs: changes` + `if:
needs.changes.outputs.run == 'true'`. A skipped `if:` reports SUCCESS to
any future required-context list, so unrelated PRs never pay for it and
can never be blocked by it.
- **Pinned action**, **timeout-minutes**, **concurrency group**,
**`permissions: contents: read`**, **SPDX header** — matches the
canonical pattern in `.github/workflows/abi-drift.yml`.

The `check` job invokes the script with `bash
scripts/hcg-surface-drift-check.sh -v` (matching the test plan in #228)
so it works regardless of the script's file mode — #228 committed the
script as 0644.

## What this PR does NOT do

- **Does NOT** modify the runbook §1.5 ("Gateway-side prerequisites").
Adoption of the CI gate into the §1.5 checklist is a one-line
owner-driven runbook update — the PR #228 deliberate boundary stays in
place.
- **Does NOT** add the new check to `.github/settings.yml`'s
`required_status_checks` list (currently `hypatia-scan` + `codeql`).
Promotion to required is a settings change for the owner to make once
the gate has run green on a few PRs.
- **Does NOT** modify the live policy, the example policy, the router,
the script, or any other Phase E artefact. The change is wholly within
`.github/workflows/`.
- **Does NOT** pre-empt the §6.4 Trustfile flip (`tier_2_gateway.status`
stays `PENDING`), the staging soak (§3.3), or cerro-torre `.ctp` signing
— all of which remain owner-driven per the channel doctrine reaffirmed
in #207 / #224.
- Per the single-lane HCG channel discipline (pattern set in
`http-capability-gateway` PRs #14, #22, #26, #30, #38 and `boj-server`
PRs #168, #173, #224, #226, #228): joint-close is owner-only. **This PR
refs but does not close `standards#100`.**

## Channel state note

This session could not read `hyperpolymath/standards#91` / `#100` (the
session's MCP repo scope is restricted to `http-capability-gateway` and
`boj-server`), so the brief's instructed status comment on
`standards#91` could not be posted. State was reconstructed from the
canonical sources in this repo (ADR-0004, the integration plan, the
audit, the rollout runbook, the live policy,
`docs/wikis/CI-and-Required-Checks.adoc`) plus the merged-PR history of
both in-scope repos. Analysis: Phase A/B/C/D closed; Phase E
(`standards#100`) is the only open phase; #228 (2026-06-19) is the most
recent advance and explicitly named this CI wiring as the next step.

## Test plan

- [ ] **Required**: the `changes` job runs and emits `run=true` (because
`.github/workflows/hcg-surface-drift.yml` matches the path regex), so
the `check` job is gated through, not skipped, on this PR.
- [ ] **Required**: the `check` job runs `bash
scripts/hcg-surface-drift-check.sh -v` and exits 0 with the OK message —
current `main` (64a70c5) has 7 wired routes, 28 policy rules, no drift;
locally re-verified on this branch.
- [ ] **Synthetic skip**: on a follow-up PR that touches none of the
four watched paths, `changes.outputs.run` is `false` and `check` reports
`skipped` (which counts as success for any required-context list).
- [ ] **Synthetic drift**: a temporary PR adding `get "/__drift_test__"`
to `elixir/lib/boj_rest/router.ex` without a matching policy rule fires
`run=true`, `check` exits 1 with the route listed under `DRIFT:`, and
the PR is blocked from merge if/when this gate is promoted to required.
- [ ] No `actionlint` / Hypatia / SPDX gate fires on the new workflow
file.

Refs hyperpolymath/standards#91
Refs hyperpolymath/standards#100

🤖 Generated with [Claude Code](https://claude.com/claude-code)


---
_Generated by [Claude
Code](https://claude.ai/code/session_019cKmxx6AkNjzhXT6ZoxGfx)_

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

Adds `scripts/hcg-spec-coverage-check.sh`: a static, source-only audit
that asserts every HTTP route declared in
`docs/specification/openapi.yaml` is covered by at least one rule in the
HCG live Verb Governance Spec (`config/gateway-policy-boj.yaml`).

Companion / complement to PR #228's `hcg-surface-drift-check.sh`. The
two scripts bracket the contract §8 declared-surface invariant from both
directions:

| Script | Invariant | Catches |
|---|---|---|
| `hcg-surface-drift-check.sh` (#228) | wired (router.ex) ⊆ policy |
policy lag behind wiring |
| `hcg-spec-coverage-check.sh` (this PR) | declared (openapi.yaml) ⊆
policy | policy lag behind the spec |

Contract §8 (`docs/integration/http-capability-gateway-boj-contract.md`)
is explicit: "the Verb Governance Spec governs the **declared** surface
(openapi.yaml), not only the currently-wired subset.
Declared-but-unimplemented routes are still classified in the policy so
that when the gnosis handler grows them they are governed from day one
rather than silently exposed." The live policy header carries the
cross-check statement (*"Surface source:
docs/specification/openapi.yaml, cross-checked against
elixir/lib/boj_rest/router.ex"*); PR #228 made the router half
machine-checkable, this PR makes the openapi half machine-checkable.
Together they make the entire §1.5 re-verification stamp executable.

Without this check the risk is concrete: someone adds a new path to
`openapi.yaml` without a corresponding policy rule. The surface-drift
check does not catch it (the route is not yet wired in `router.ex`). The
day the route is wired, the surface-drift gate fires — but by then the
operator has to either (a) ship the wiring with a default-deny in
production for a route that should be live or (b) hold the wiring PR
until the policy catches up. Catching the gap at spec-edit time avoids
both, with no procedural cost above running the existing CI gate.

### What the script does

1. Extracts `(verb, path-template)` tuples from the `paths:` section of
`docs/specification/openapi.yaml` — path entries at exactly 2-space
indent, HTTP operations (get/post/put/delete/patch/head/options) at
exactly 4-space indent under each path. Other keys at 4-space indent
(parameters/summary/description/tags/...) are metadata, not operations,
and are skipped.
2. Extracts `(verb, path-pattern)` tuples from
`config/gateway-policy-boj.yaml` using the identical extraction block
that `hcg-surface-drift-check.sh` uses, so the two scripts cannot drift
in how they read the policy.
3. For each declared route, concretises `{name}`-style placeholders with
a known probe segment (`probe`, shared with the smoke + surface-drift
scripts so a future regex tightening fails all three in lock-step) and
asserts at least one policy rule covers it: literal equality for
non-regex paths; ERE `grep -E` match against the concrete URL for `^…`
regex paths. The declared verb must be in the policy rule's verb list.
4. Exit `0` on no gap, `1` on gap detected, `64` on bad usage.

### What this PR does NOT do

- Does **not** modify the rollout runbook §1.5 or the contract §8.
Adoption as the §1.5 declared-surface check is a separate, owner-driven
PR; this PR lands the artefact only so the runbook update is a one-line
wiring change. Matches the §228-then-runbook split.
- Does **not** wire the script into CI. Boj-server's CI discipline
(`docs/wikis/CI-and-Required-Checks.adoc` / `.claude/CLAUDE.md`)
requires path-filtered required checks to use the "always-trigger +
changes job" pattern; a CI wiring PR should follow that pattern,
matching the #228#229 split. Out of scope here.
- Does **not** modify the openapi.yaml or the policy. On this branch the
script reports OK against today's surface — every one of the 26 `(verb,
path)` pairs declared in openapi.yaml has a matching rule among the 28
`(verb, path)` rules in the live policy. The 2-rule surplus is the
policy's coverage of routes the openapi.yaml does not declare (notably
`/.well-known/boj-node-pubkey`, which the router wires but the spec does
not yet enumerate); the script intentionally does not penalise that
direction — see the script's `Limitations` header.
- Does **not** pre-empt the §6.4 Trustfile flip (`tier_2_gateway.status`
stays `PENDING`).
- Per single-lane HCG channel discipline (pattern set in
`http-capability-gateway` PRs #10, #11, #12, #14, #22, #26, #30, #38 and
`boj-server` PRs #78, #90, #106, #168, #173, #207, #208, #210, #215,
#222, #224, #226, #228, #229): joint-close is owner-only. **This PR refs
but does not close `standards#100`.**

### Channel state note

This session could not read `hyperpolymath/standards#91` / `#100` (the
session's repository scope is restricted to `http-capability-gateway`
and `boj-server`), so the brief's instructed status comment on
`standards#91` could not be posted. State was reconstructed from the
canonical sources in this repo (ADR-0004, the integration plan, the
audit, the rollout runbook, the live policy, the openapi spec, and the
merged-PR commit history) plus the current `main` of both in-scope
repos. The analysis: Phase A/B/C/D are closed (artefacts merged, runbook
§1.2 and the Phase-D status note in the runbook header confirm); Phase E
(`standards#100`) is the only open phase; all remaining §1 checklist
items are owner-driven (`!OWNER:` placeholders, D-4 rebaseline
`workflow_dispatch`, cerro-torre `.ctp` signing, the §6.4 Trustfile
flip). This PR advances Phase E §1.5 ("Gateway-side prerequisites") by
converting one half of the declared-surface invariant into an executable
artefact, mirroring exactly the script-first split of #228.

## Test plan

- [ ] Run the script on this branch's working tree: `bash
scripts/hcg-spec-coverage-check.sh` — expect exit `0`, "OK: every
openapi-declared route is covered by at least one policy rule." with
`Declared (openapi) routes: 26` and `Policy (verb,path) rules: 28`.
- [ ] Run `bash scripts/hcg-spec-coverage-check.sh -v` — expect the same
exit `0` plus a `Matched:` block listing each of the 26 declared routes
against its policy rule (literal `/health` → literal rule;
`/cartridge/{name}/invoke` → `^/cartridge/[A-Za-z0-9_.-]+/invoke$`
regex; `/grpc/{service}/{method}` → two-segment regex; `/umoja/peers`
matches both `GET` and `POST` rules; etc.).
- [ ] Synthetic gap test: build a temporary openapi.yaml containing a
single declared path with no policy rule and run `OPENAPI_FILE=... bash
scripts/hcg-spec-coverage-check.sh` — expect exit `1` with the route
listed under `GAP:`. (Verified locally on this branch.)
- [ ] Confirm `shellcheck scripts/hcg-spec-coverage-check.sh` produces
only the same `SC1001` info note that
`scripts/hcg-surface-drift-check.sh` produces today (the `\^` escape
inside a `case` pattern is intentional and matches the sibling script's
posture exactly).
- [ ] Confirm SPDX header + Owner copyright match the canonical estate
format (matches `scripts/hcg-surface-drift-check.sh`'s header shape).
- [ ] Verify `scripts/check-shebang-first.sh` is still green with the
new file present.
- [ ] Verify no Hypatia / governance / spdx gates fire on the new script
file.

Refs hyperpolymath/standards#91
Refs hyperpolymath/standards#100

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---
_Generated by [Claude
Code](https://claude.ai/code/session_013VLPKSTEMFnPYQdx6rD91b)_

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

2 participants