Skip to content

Merge Orchestration · BatonEmitter (bag-of-actions mesh actuation backend) - #500

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/peaceful-pascal-IRlgq
Jun 14, 2026
Merged

hyperpolymath merged 1 commit into
mainfrom
claude/peaceful-pascal-IRlgq

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

BatonEmitter — actuate armed merges on the bag-of-actions mesh

Item #2 of what you picked: the real bag-of-actions integration. Since the repo still isn't in this session's MCP scope (your grant applies to a new session; the add_repo tool isn't available here), I read its real API by public git clone and built the integration hypatia-side — which is where it belongs anyway.

What the real API turned out to be

Bag.Mesh.submit_planned(spec, budget) takes %{check_id, command, required_cap, mutating?, risk?}; the planner routes to the cheapest capable node and gates mutating: true work on a verifier — which is the independent re-verification. So a merge needs no custom Ephapax action: it's just a command (gh pr merge …) carrying required_cap: "secret-access" — the capability only mesh-github-runner holds in the estate nodes.scm (the token-bearer). The brain's node lacks it, so the Baton can't run on the brain and migrates to the runner: the token-free-brain invariant expressed as capability routing. No bag-of-actions changes needed.

Hypatia.MergeOrchestration.BatonEmitter

  • to_spec/2 (pure) → the submit_planned spec, carrying lease_id + route + rationale as the trust/residue link.
  • emit/2 → submits one Baton per armed Loop entry (gate {:armed, lease}); deferred/flagged entries are skipped. The Bag.Mesh call is late-bound (apply/3) and injectable, so this stays compile-decoupled from bag-of-actions and the logic tests run without it.

This is the alternative actuation backend to merge-decisions.jsonl from the #498 design doc — now real, not just sketched.

Testing (actual, not looks-right)

74 ExUnit, 0 failures (was 71), mix-format-clean, scanner-clean:

74 tests, 0 failures

The +3 BatonEmitter tests: the spec shape (check_id, gh pr merge command, required_cap: "secret-access", mutating: true, attestation), the method→gh-flag + aggressive-pool→:high-risk mapping, and that emit submits only armed entries (via an injected submit).

Scope / what's left on BoA

  • Not auto-armed — core-tier lib/, your review.
  • The integration is complete on the hypatia side. The only remaining BoA step needs the repo in a session's MCP scope: wire emit into the live Loop as the actuation backend (alongside write_manifest) and register hypatia as a mesh node — no new emitter logic.

LEDGER v0.10.0 records the real-API findings + this build.


Generated by Claude Code

…e bag-of-actions mesh

The alternative actuation backend to merge-decisions.jsonl, built against
bag-of-actions' REAL API (read by public clone; the repo is not in this
session's MCP scope so this is hypatia-side only).

  * Bag.Mesh.submit_planned(spec, budget) takes %{check_id, command, required_cap,
    mutating?, risk?}; the planner routes to the cheapest capable node and GATES
    mutating:true work on a verifier -- that is the independent re-verification.
  * A merge is just command=[gh, pr, merge, N, --repo, R, --<method>] carrying
    required_cap="secret-access" -- the capability ONLY mesh-github-runner holds
    in the estate nodes.scm (the token-bearer). The brain's node lacks it, so the
    Baton cannot run on the brain and migrates to the runner: the token-free-brain
    invariant expressed as capability routing. No bag-of-actions changes needed.

  * Hypatia.MergeOrchestration.BatonEmitter.to_spec/2 (pure) -> the submit_planned
    spec, carrying lease_id + route + rationale as the trust/residue link;
    emit/2 submits one Baton per ARMED Loop entry. The Bag.Mesh call is late-bound
    (apply/3) + injectable, so this stays compile-decoupled from bag-of-actions and
    the logic tests run without it.

74 ExUnit (was 71): +3 BatonEmitter (spec shape + gh-flag/risk mapping + emit
filters to armed only). 0 failures, mix-format-clean, scanner-clean. LEDGER
v0.10.0. Companion to the design doc in #498.
@github-actions

Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 42 issues detected

Severity Count
🔴 Critical 0
🟠 High 0
🟡 Medium 42
View findings
[
  {
    "reason": "Repository has 5 non-main remote branch(es). Policy: single main branch only.",
    "type": "GS007",
    "file": ".",
    "action": "delete_remote_branches",
    "rule_module": "git_state",
    "severity": "medium"
  },
  {
    "reason": "Code scanning (Hypatia): hypatia/structural_drift/SD022 -- Hypatia structural_drift: SD022 -- 11 day(s) old",
    "type": "CSA001",
    "file": "src/ui/gossamer/README.adoc",
    "action": "review",
    "rule_module": "code_scanning_alerts",
    "severity": "medium"
  },
  {
    "reason": "Code scanning (Hypatia): hypatia/structural_drift/SD022 -- Hypatia structural_drift: SD022 -- 11 day(s) old",
    "type": "CSA001",
    "file": "scripts/ci-tools/Cargo.toml",
    "action": "review",
    "rule_module": "code_scanning_alerts",
    "severity": "medium"
  },
  {
    "reason": "Code scanning (Hypatia): hypatia/structural_drift/SD022 -- Hypatia structural_drift: SD022 -- 11 day(s) old",
    "type": "CSA001",
    "file": "scripts/bench-tools/Cargo.toml",
    "action": "review",
    "rule_module": "code_scanning_alerts",
    "severity": "medium"
  },
  {
    "reason": "Code scanning (Hypatia): hypatia/structural_drift/SD022 -- Hypatia structural_drift: SD022 -- 11 day(s) old",
    "type": "CSA001",
    "file": "ffi/zig/README.adoc",
    "action": "review",
    "rule_module": "code_scanning_alerts",
    "severity": "medium"
  },
  {
    "reason": "Code scanning (Hypatia): hypatia/structural_drift/SD022 -- Hypatia structural_drift: SD022 -- 11 day(s) old",
    "type": "CSA001",
    "file": "docs/reports/audit/audit-2026-04-15-post.md",
    "action": "review",
    "rule_module": "code_scanning_alerts",
    "severity": "medium"
  },
  {
    "reason": "Code scanning (Hypatia): hypatia/structural_drift/SD022 -- Hypatia structural_drift: SD022 -- 11 day(s) old",
    "type": "CSA001",
    "file": "docs/integration/github-registry.adoc",
    "action": "review",
    "rule_module": "code_scanning_alerts",
    "severity": "medium"
  },
  {
    "reason": "Code scanning (Hypatia): hypatia/structural_drift/SD022 -- Hypatia structural_drift: SD022 -- 11 day(s) old",
    "type": "CSA001",
    "file": "docs/integration/github-registry.adoc",
    "action": "review",
    "rule_module": "code_scanning_alerts",
    "severity": "medium"
  },
  {
    "reason": "Code scanning (Hypatia): hypatia/structural_drift/SD022 -- Hypatia structural_drift: SD022 -- 11 day(s) old",
    "type": "CSA001",
    "file": "docs/integration/a2ml-k9.md",
    "action": "review",
    "rule_module": "code_scanning_alerts",
    "severity": "medium"
  },
  {
    "reason": "Code scanning (Hypatia): hypatia/structural_drift/SD022 -- Hypatia structural_drift: SD022 -- 11 day(s) old",
    "type": "CSA001",
    "file": "docs/architecture/system-integration.md",
    "action": "review",
    "rule_module": "code_scanning_alerts",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath
hyperpolymath merged commit c170865 into main Jun 14, 2026
36 checks passed
@hyperpolymath
hyperpolymath deleted the claude/peaceful-pascal-IRlgq branch June 14, 2026 14:49
hyperpolymath added a commit that referenced this pull request Jun 14, 2026
…:baton|:both) (#501)

Finishes the live bag-of-actions wiring for the merge-orchestration
runtime (the BoA follow-on tracked in
`.machine_readable/merge-orchestration/LEDGER.a2ml`).

## What
- `Loop.run/1` gains `:actuation` — `:manifest` (default) | `:baton` |
`:both`. `:baton` submits one Baton per **armed** entry via
`BatonEmitter.emit/2`, late-bound to `Bag.Mesh.submit_planned(spec,
budget)` so a `:manifest`-only run never references `Bag.*`
(compile-decoupled; no new dep).
- Threaded through `Scheduler.cycle` and `mix hypatia.merge_orchestrate
--actuation`.
- **Two interop fixes in the as-merged `BatonEmitter` (#500)**, verified
against bag-of-actions' real source — each would otherwise make every
merge Baton fail:
- `required_cap "secret-access"` → `"secret_access"` (the Zig bridge /
`Bag.Planner` tag; a hyphenated tag is unprovable → routes to no node).
- `to_spec` now carries a `:verifier`, so a mutating merge passes the
planner's mutation gate instead of `{:rejected,
:mutation_requires_verifier}`.

## Token-free brain
The brain only emits/reads. `required_cap "secret_access"` is held
**only** by the `mesh-github-runner` node in bag-of-actions' estate, so
every merge Baton migrates off the brain to the runner — the
token-free-brain invariant as capability routing.

## Tests
- `+4` `Loop`/`Scheduler` `:actuation` tests; `baton_emitter_test`
updated.
- `mix test test/merge_orchestration/` → **81 tests, 0 failures**.
- Full suite: the ~14 failures are pre-existing and unrelated
(workflow-audit count drift, missing `:proof_model_retrain_count`
metric, watcher `:already_started` isolation) — identical with this
branch reverted.

Cross-repo counterpart: hyperpolymath/bag-of-actions
`claude/peaceful-pascal-IRlgq` (brain node + end-to-end test).
`BatonEmitter.to_spec` output matches that PR's routed spec
byte-for-byte.

Core-tier → **draft for owner review** (not auto-armed).

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

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request Sep 15, 2026
…gex (#790)

## What this does

Phase 1c of the hypatia campaign, and the first arm of the owner's **"2
then 1"**
sequencing ruling — finish arming the scanner at source before spending
fleet PRs.

Three changes, all zero-PR: hypatia is resolved by `git ls-remote …
HEAD` at
runtime by `hypatia-scan-reusable.yml`, so these reach every consumer on
its next
scan. **Severities were chosen by measurement, not by taste.**

### 1. The secret-history coverage rule

A deduplicated local census (579 raw roots → **573 distinct repos**
after deduping
on `git rev-parse --git-common-dir`) found **409 hypatia consumers, 398
secret-scanner callers, and 11 repos with no secret-history gate at
all**.

Rather than reimplement history scanning in Elixir alongside the
existing pinned,
checksum-verified gitleaks rail, this asserts the gate exists **and can
actually
see history**:

| Rule | Severity | Condition |
|---|---|---|
| `missing_secret_history_scan` | `:medium` | No rail call, no direct
scanner. Fires on the 11. |
| `secret_scan_without_history` | `:low` | A scanner exists but is
`--no-git` only (`:add_history_pass`) or fed by a checkout without
`fetch-depth: 0` (`:set_fetch_depth_zero`). |

`:medium` keeps it visible at the default threshold while staying
**below the
reusable's blocking high/critical refusal** — the 11 repos get a visible
finding,
and none gets a permanently-red required check with no PR to review.

It deliberately does **not** assert `secrets: inherit`. The rail's own
header still
requires it, but lines 44-49 record that #500 replaced the gitleaks
action with a
pinned binary and that the guidance *"became wrong when the binary
replaced it —
but it was left in place."* Probing for it would false-positive
fleet-wide.

### 2. GS008 — shallow-clone instrument health

A history rule that sees no history is a **fake gate by construction**,
so the
coverage rule needs a companion reporting on the scan *environment*.
GS008 fires
when `.git/shallow` exists, marking every history-dependent finding in
that report
as vacuous rather than as a pass.

> ⚠️ **The anchor is load-bearing and counter-intuitive.** `file:` must
**not** be
> `.git/shallow`, however naturally that reads. `.git/` is in
`@universal_excludes`
> (`scanner_suppression.ex`), so a finding anchored there is **silently
deleted by
> the path filter between the rule module and the CLI output**.
Measured: with that
> anchor the rule was a **complete no-op** on a real `git clone --depth
1` while
> passing a full-clone test perfectly. The exclusion exists to avoid
scanning files
> *inside* `.git/`; it also eats findings *about* it. Anchored at `.`
(matching
> GS005/GS007) and pinned by a dedicated regression test.

`:medium` not `:high` because the condition is controlled by **one
shared line in
`standards`** — at `:high`, a single regression there would redden every
consumer
simultaneously. It is a filesystem probe rather than
`git rev-parse --is-shallow-repository` because an unguarded
`System.cmd` raises
`ErlangError :enoent` — the exact defect that got
`secret_scanner_verification.ex`
deleted.

### 3. Restore the discarded `flawed_regex` findings

Pre-existing defect, found while reading. `flawed_regexes` was computed
at the top
of `audit/3` and summed into `flawed_regex_count:`, but **was never
added to the
`findings:` chain** — so the rule ran on every scan in the estate,
reported a count
nothing consumes, and discarded every finding it produced. `cli.ex`'s
own
normalizer comment names `flawed_regex` as a source it handles, so the
omission was
accidental, not a deliberate mute. Gate-safe: the rule emits `:low`.

## Verification

- **Four-arm planted-positive control on GS008** — repo as-is (silent) ·
real
`git clone --depth 1` (**fires**) · `git fetch --unshallow` (silent
again) · and
**arm 4 against the escript being replaced**, where none of the new
findings appear.
- **All five new-or-restored emitters were EXECUTED**, not merely
compiled. `test/`
is path-suppressed under `@training_corpus_paths`, so a fixture placed
there would
have faked every arm; planted fixtures live outside it and ran at
`--severity info`
  (`info` is rank 5 — `--severity low` would have hidden them).
- **Real-estate validation**: 10 of the 11 predicted gap repos emit
exactly one
`missing_secret_history_scan`. The 11th (`me-dialect`) was **explained,
not waved
away** — a concurrent writer added a pinned trufflehog after the census
ran, and
direct invocation confirms the rule correctly returns
`secret_scan_without_history`
/ `:set_fetch_depth_zero` instead. 8 of 8 rail-calling control repos
stay silent.
- **No new fleet noise**: the whole `secret_scan_without_history` class
is invisible
  at the default severity threshold.
- `mix test` — **1585 tests, 2 failures**: the same two pre-existing
`ResearchExtensionsTest` `re001_missing_harden_runner` failures present
on `main`
  without these changes. **Zero regressions.**
- Escript soundness gate **14/14, rc=0**. `mix format --check-formatted`
clean.
  Compiles clean under `--warnings-as-errors`.

## Known limit, stated rather than worked around

No soundness-manifest entries were added for the new rules. An *absence*
finding
names no file, and the manifest matcher requires a real fixture file —
contorting
the anchor to satisfy the gate would be worse than documenting the
limit.
`missing_secret_history_scan` does execute inside the soundness scan and
is
message-checked by the placeholder assertion.

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

https://claude.ai/code/session_011YTttTxnPc1V2sATvzBDN7

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