Accountability principle (ADR-0050) + archived AI council (ADR-0051) #2

Merged
amethyst merged 14 commits from docs/accountability-council into main 2026-10-11 04:56:15 +00:00
Owner

Carries the old pr60 branch (accountability principle + AI review council) onto the Forgejo main. The principle stays. The council is archived, because the services it was built on went away with the GitHub account.

Consensus impact

  • breaking
  • adjacent
  • none

Could this behave differently on two honest nodes given the same inputs? No. This PR changes docs only (no Rust).

Specification and decision record

  • I identified the applicable docs/specification/ section. (None applies: process and philosophy docs only.)
  • If no specification existed, this PR adds it before implementation. (N/A)
  • I added an ADR for a significant interpretation or deviation. ADR-0050 (accountability by construction) and ADR-0051 (council, superseded).
  • I implemented the complete specified structure, or documented each tracked exception.
  • I described any ambiguity or deviation explicitly below (ADR renumbering).

Checks

No Rust is changed, so the cargo checks don't apply. These doc checks were run locally, since the server has no CI:

  • python3 scripts/site.py check: pass
  • python3 scripts/check-doc-links.py: pass
  • python3 scripts/check-spec-citations.py: pass
  • python3 scripts/version.py check: pass

Notes

What lands

  • docs/PHILOSOPHY.md: project philosophy, including the accountability principle in its refined form (f85a699).
  • docs/adr/0050-accountability-by-construction.md: ADR-0050. Unchanged from pr60.
  • docs/adr/0051-ai-council-first-class.md: the council ADR. Renumbered from 0049 and marked Superseded.
  • docs/architecture/ai-council/*: the council design docs (registry, status model, degraded operation, provenance, costs, incidents), kept as the record. The README has an archive note.

What was archived vs removed, and why

Item Outcome Reason
PHILOSOPHY.md, ADR-0050 kept, unchanged The principle doesn't depend on any platform.
Council ADR (0049 → 0051) kept, marked superseded It records the decision. The council (CodeRabbit, Devin, Greptile, the GitHub review relay) ran on GitHub and was removed with the account. Review is now defined in CONTRIBUTING.md#review-process.
docs/architecture/ai-council/ kept as an archive Same reason. It's history, not a live process.
.github/workflows/ai-council.yml removed The server runs no CI, and main already removed every other workflow.
scripts/ai-council/health.py, liveness.py removed Both read GitHub PR activity through the GitHub API, which no longer exists for this repo.

ADR renumbering

pr59 (M6 BFT consensus) and pr60 both created an ADR-0049. pr59's ADR-0049 (BFT locking protocol, 3f2b7e5) was written first, on 2026-10-09. pr60's council ADR (d5ca451) came on 2026-10-10. So the BFT ADR keeps 0049 and the council ADR becomes 0051. 0050 is already taken by Accountability by Construction. The ADR header records the old number.

Review history (from the original PR #60 on GitHub)

  • 395f42e: zizmor fixes on the council workflow (permissions: contents: read, persist-credentials: false). Turn-2 failure policy in degraded-operation.md corrected to match review-relay.yml. Site rebuilt.
  • 24a6893 (round 2): registry turn-2 failure_policy aligned with the relay. health.py FULL now requires every member AVAILABLE, a lead that is UNAVAILABLE gives STOPPED, and the timestamp is relabeled as report generation time. The validator requires all mandatory roles. Fixed a health.sh → health.py reference and the override label name (consensus-override). Clarified the costs/incident procedure.
  • ff02012: the turn-4 live verifier is advisory (required: false), so it was removed from the validator's required roles.
  • c573e10 (round 3): policy and code aligned (a turn-1 UNAVAILABLE is policy, not enforced by code). liveness.py actually loads the registry and surfaces API errors. Provenance uses the registry at the reviewed commit.
  • f85a699: adopted Claude's refinement of the accountability principle in PHILOSOPHY.md and ADR-0050: covers "misbehavior" (broader than equivocation), works "from the messages alone", and "cost always exceeds the gain".

Several of these fixes (zizmor, the validator, health.py, liveness.py) touched files that this merge removes. They're listed here so the record stays complete.

Merge

8f52976 merges main (the Forgejo migration, PR #1) into the pr60 branch. site/index.html was resolved by regenerating it on the merged tree (scripts/site.py build).

Prompts

Operator prompt, verbatim, for the session that produced this PR and its sibling. Redactions are marked inline.

  Resume ONX PR work in /root/The-Open-Network-X. Self-hosted Forgejo only:
  https://git.on-x.live/amethyst/the-open-network-x (origin). NO GitHub, ever.
  Zero CI on the server. Commit locally freely; push and open PRs only as
  part of this task (already authorized). Send a Telegram done report at the
  end (memory rule).

  ## State
  - PR #1 (migration/kill-actions) is MERGED into main (dbd4c1a). Run
    `git fetch origin` first. Local `main` is stale; fast-forward it.
  - Two local branches resolve the old pr59/pr60 branches. They are NOT
    pushed and have NO PRs yet:
    1. m6/bft-consensus = origin/pr59 + merge of main (091c61a, site/index.html
       regenerated) + WIP commit 082677e that ADDS TESTS NOT YET COMPILED/RUN.
    2. docs/accountability-council = origin/pr60 + merge of main (8f52976).
       User chose "keep principles, archive council": council ADR renumbered
       0049 -> 0051 and marked superseded, ai-council.yml workflow and
       scripts/ai-council/{health,liveness}.py deleted, PHILOSOPHY.md and
       ADR-0050 unchanged. Doc checks pass. Ready to push and PR.
  - Both may still be checked out in old worktrees under
    /tmp/claude-0/.../scratchpad/wt-m6 and wt-council. If those dirs are gone,
    run `git worktree prune` and re-add the worktrees from the branches.
  - Rust: system rustc is 1.85.1 (too old). Use the pinned toolchain:
    export PATH=$HOME/.cargo/bin:$PATH  (rustup 1.98.1 installed).
    Machine has 3 GB RAM: build with -j3. A prior `cargo test --no-run` was
    interrupted mid-build. Reuse CARGO_TARGET_DIR=/root/The-Open-Network-X/target.

  ## Tests in 082677e (verify they compile; fix test code only)
  onx-consensus/tests/engine_integration.rs:
  - forged_qc_round_does_not_unlock: regression for the critical fix
    2b87615, expected to PASS.
  - observed_pol_for_other_block_unlocks: #[ignore]. FINDING: the POL unlock
    path is unreachable. A validator locked on A rejects B's proposal, and the
    engine only counts votes for the current proposal, so pol[B] is never
    written. Split locks (Byzantine selective PreCommit delivery) stall the
    height forever (liveness). Expected to FAIL with --ignored.
  onxd/src/consensus_driver.rs tests:
  - commit_vote_without_header_sig_is_rejected: regression, should PASS.
  - stale_buffered_vote_does_not_poison_valid_vote: #[ignore]. FINDING: the
    pending buffer survives the view change. A stale round-0 vote hits the
    `?` in receive_vote's retry loop, so a valid vote returns Err, its
    triggered broadcast is lost, and the rest of the buffer is dropped.
  - forged_future_round_votes_are_not_buffered: #[ignore]. FINDING: the engine
    returns InvalidRound before verifying the signature, and the driver
    buffers future-round votes with no bound (memory DoS from any peer).

  ## Steps
  1. In the m6 worktree: cargo fmt --all; clippy -p onx-consensus -p onxd
     --all-targets -D warnings; cargo test -p onx-consensus -p onxd; then
     `-- --ignored` to confirm the 3 findings FAIL as described. If a finding
     test passes, the finding is wrong: delete the test and drop the claim.
     Also run python3 scripts/site.py check, check-doc-links.py,
     check-spec-citations.py, version.py check. Reword the WIP commit with
     the real results.
  2. Do NOT fix the consensus findings (design before code, user decides).
     Report them in the PR body, scored with the CONTRIBUTING point system
     (critical = NO-GO; high 30, medium 10). The POL stall is a chain halt,
     so critical by docs/claude-review-prompt.md.
  3. Push both branches and open 2 PRs to main via the Forgejo API.
     Auth: the user's password in [redacted: credential file path]. Use it
     ONLY via a temp GIT_ASKPASS script (git) and a temp `curl -K` config
     file (API) in the scratchpad, and delete both right after. Never put it
     in a URL, config or log.
     PR bodies must carry the evidence from the original PRs:
     - pr59: review rounds 0ddbe44 (sign QC fields), 69f1ae1 (re-audit:
       header-sig ordering, buffering, locked leader), 2b87615 (critical:
       local POL unlock, reject sig-less commits, keep buffer on timeout),
       probes 2 and 4 regression tests; the 13 M6 commits appear TWICE in
       history (rebase duplicate, net diff fine); known gap from 0ddbe44:
       set_head is never called, so the prev_hash check is dead; STF dry-run
       is a TODO; the new test results.
     - pr60: rounds 395f42e, 24a6893, ff02012, c573e10, f85a699; ADR
       renumbering rationale (pr59's ADR-0049 was written first,
       2026-10-09 vs 2026-10-10); what was archived vs removed and why.
     End each PR body with: 🤖 Generated with [Claude Code](https://claude.com/claude-code)
  4. Note in the final report: my migration commit e3d3bd9 is authored as
     "quickerup" (global git identity). This conflicts with MIGRATION's "one
     human identity, one bot identity" rule. Ask the user which identity
     this repo should use.

Review relay

N/A. The GitHub review relay was removed in the Forgejo migration. Review follows CONTRIBUTING.md#review-process.

🤖 Generated with Claude Code

Carries the old `pr60` branch (accountability principle + AI review council) onto the Forgejo `main`. The principle stays. The council is archived, because the services it was built on went away with the GitHub account. ## Consensus impact - [ ] breaking - [ ] adjacent - [x] none Could this behave differently on two honest nodes given the same inputs? No. This PR changes docs only (no Rust). ## Specification and decision record - [x] I identified the applicable `docs/specification/` section. (None applies: process and philosophy docs only.) - [ ] If no specification existed, this PR adds it before implementation. (N/A) - [x] I added an ADR for a significant interpretation or deviation. ADR-0050 (accountability by construction) and ADR-0051 (council, superseded). - [x] I implemented the complete specified structure, or documented each tracked exception. - [x] I described any ambiguity or deviation explicitly below (ADR renumbering). ## Checks No Rust is changed, so the cargo checks don't apply. These doc checks were run locally, since the server has no CI: - [x] `python3 scripts/site.py check`: pass - [x] `python3 scripts/check-doc-links.py`: pass - [x] `python3 scripts/check-spec-citations.py`: pass - [x] `python3 scripts/version.py check`: pass ## Notes ### What lands - `docs/PHILOSOPHY.md`: project philosophy, including the accountability principle in its refined form (f85a699). - `docs/adr/0050-accountability-by-construction.md`: ADR-0050. Unchanged from pr60. - `docs/adr/0051-ai-council-first-class.md`: the council ADR. Renumbered from 0049 and marked **Superseded**. - `docs/architecture/ai-council/*`: the council design docs (registry, status model, degraded operation, provenance, costs, incidents), kept as the record. The README has an archive note. ### What was archived vs removed, and why | Item | Outcome | Reason | |---|---|---| | PHILOSOPHY.md, ADR-0050 | **kept, unchanged** | The principle doesn't depend on any platform. | | Council ADR (0049 → 0051) | **kept, marked superseded** | It records the decision. The council (CodeRabbit, Devin, Greptile, the GitHub review relay) ran on GitHub and was removed with the account. Review is now defined in `CONTRIBUTING.md#review-process`. | | `docs/architecture/ai-council/` | **kept as an archive** | Same reason. It's history, not a live process. | | `.github/workflows/ai-council.yml` | **removed** | The server runs no CI, and main already removed every other workflow. | | `scripts/ai-council/health.py`, `liveness.py` | **removed** | Both read GitHub PR activity through the GitHub API, which no longer exists for this repo. | ### ADR renumbering pr59 (M6 BFT consensus) and pr60 both created an `ADR-0049`. pr59's ADR-0049 (BFT locking protocol, 3f2b7e5) was **written first, on 2026-10-09**. pr60's council ADR (d5ca451) came on **2026-10-10**. So the BFT ADR keeps 0049 and the council ADR becomes 0051. 0050 is already taken by Accountability by Construction. The ADR header records the old number. ### Review history (from the original PR #60 on GitHub) - **395f42e**: zizmor fixes on the council workflow (`permissions: contents: read`, `persist-credentials: false`). Turn-2 failure policy in `degraded-operation.md` corrected to match `review-relay.yml`. Site rebuilt. - **24a6893** (round 2): registry turn-2 `failure_policy` aligned with the relay. `health.py` FULL now requires every member AVAILABLE, a lead that is UNAVAILABLE gives STOPPED, and the timestamp is relabeled as report generation time. The validator requires all mandatory roles. Fixed a `health.sh` → `health.py` reference and the override label name (`consensus-override`). Clarified the costs/incident procedure. - **ff02012**: the turn-4 live verifier is advisory (`required: false`), so it was removed from the validator's required roles. - **c573e10** (round 3): policy and code aligned (a turn-1 UNAVAILABLE is policy, not enforced by code). `liveness.py` actually loads the registry and surfaces API errors. Provenance uses the registry at the reviewed commit. - **f85a699**: adopted Claude's refinement of the accountability principle in PHILOSOPHY.md and ADR-0050: covers "misbehavior" (broader than equivocation), works "from the messages alone", and "cost always exceeds the gain". Several of these fixes (zizmor, the validator, `health.py`, `liveness.py`) touched files that this merge removes. They're listed here so the record stays complete. ### Merge 8f52976 merges `main` (the Forgejo migration, PR #1) into the pr60 branch. `site/index.html` was resolved by regenerating it on the merged tree (`scripts/site.py build`). ## Prompts Operator prompt, verbatim, for the session that produced this PR and its sibling. Redactions are marked inline. ```text Resume ONX PR work in /root/The-Open-Network-X. Self-hosted Forgejo only: https://git.on-x.live/amethyst/the-open-network-x (origin). NO GitHub, ever. Zero CI on the server. Commit locally freely; push and open PRs only as part of this task (already authorized). Send a Telegram done report at the end (memory rule). ## State - PR #1 (migration/kill-actions) is MERGED into main (dbd4c1a). Run `git fetch origin` first. Local `main` is stale; fast-forward it. - Two local branches resolve the old pr59/pr60 branches. They are NOT pushed and have NO PRs yet: 1. m6/bft-consensus = origin/pr59 + merge of main (091c61a, site/index.html regenerated) + WIP commit 082677e that ADDS TESTS NOT YET COMPILED/RUN. 2. docs/accountability-council = origin/pr60 + merge of main (8f52976). User chose "keep principles, archive council": council ADR renumbered 0049 -> 0051 and marked superseded, ai-council.yml workflow and scripts/ai-council/{health,liveness}.py deleted, PHILOSOPHY.md and ADR-0050 unchanged. Doc checks pass. Ready to push and PR. - Both may still be checked out in old worktrees under /tmp/claude-0/.../scratchpad/wt-m6 and wt-council. If those dirs are gone, run `git worktree prune` and re-add the worktrees from the branches. - Rust: system rustc is 1.85.1 (too old). Use the pinned toolchain: export PATH=$HOME/.cargo/bin:$PATH (rustup 1.98.1 installed). Machine has 3 GB RAM: build with -j3. A prior `cargo test --no-run` was interrupted mid-build. Reuse CARGO_TARGET_DIR=/root/The-Open-Network-X/target. ## Tests in 082677e (verify they compile; fix test code only) onx-consensus/tests/engine_integration.rs: - forged_qc_round_does_not_unlock: regression for the critical fix 2b87615, expected to PASS. - observed_pol_for_other_block_unlocks: #[ignore]. FINDING: the POL unlock path is unreachable. A validator locked on A rejects B's proposal, and the engine only counts votes for the current proposal, so pol[B] is never written. Split locks (Byzantine selective PreCommit delivery) stall the height forever (liveness). Expected to FAIL with --ignored. onxd/src/consensus_driver.rs tests: - commit_vote_without_header_sig_is_rejected: regression, should PASS. - stale_buffered_vote_does_not_poison_valid_vote: #[ignore]. FINDING: the pending buffer survives the view change. A stale round-0 vote hits the `?` in receive_vote's retry loop, so a valid vote returns Err, its triggered broadcast is lost, and the rest of the buffer is dropped. - forged_future_round_votes_are_not_buffered: #[ignore]. FINDING: the engine returns InvalidRound before verifying the signature, and the driver buffers future-round votes with no bound (memory DoS from any peer). ## Steps 1. In the m6 worktree: cargo fmt --all; clippy -p onx-consensus -p onxd --all-targets -D warnings; cargo test -p onx-consensus -p onxd; then `-- --ignored` to confirm the 3 findings FAIL as described. If a finding test passes, the finding is wrong: delete the test and drop the claim. Also run python3 scripts/site.py check, check-doc-links.py, check-spec-citations.py, version.py check. Reword the WIP commit with the real results. 2. Do NOT fix the consensus findings (design before code, user decides). Report them in the PR body, scored with the CONTRIBUTING point system (critical = NO-GO; high 30, medium 10). The POL stall is a chain halt, so critical by docs/claude-review-prompt.md. 3. Push both branches and open 2 PRs to main via the Forgejo API. Auth: the user's password in [redacted: credential file path]. Use it ONLY via a temp GIT_ASKPASS script (git) and a temp `curl -K` config file (API) in the scratchpad, and delete both right after. Never put it in a URL, config or log. PR bodies must carry the evidence from the original PRs: - pr59: review rounds 0ddbe44 (sign QC fields), 69f1ae1 (re-audit: header-sig ordering, buffering, locked leader), 2b87615 (critical: local POL unlock, reject sig-less commits, keep buffer on timeout), probes 2 and 4 regression tests; the 13 M6 commits appear TWICE in history (rebase duplicate, net diff fine); known gap from 0ddbe44: set_head is never called, so the prev_hash check is dead; STF dry-run is a TODO; the new test results. - pr60: rounds 395f42e, 24a6893, ff02012, c573e10, f85a699; ADR renumbering rationale (pr59's ADR-0049 was written first, 2026-10-09 vs 2026-10-10); what was archived vs removed and why. End each PR body with: 🤖 Generated with [Claude Code](https://claude.com/claude-code) 4. Note in the final report: my migration commit e3d3bd9 is authored as "quickerup" (global git identity). This conflicts with MIGRATION's "one human identity, one bot identity" rule. Ask the user which identity this repo should use. ``` ## Review relay N/A. The GitHub review relay was removed in the Forgejo migration. Review follows `CONTRIBUTING.md#review-process`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- ADR-0049: documents the decision and the evolution from single AI
  developer through deliberative council to formal architectural component
- docs/architecture/ai-council/registry.yaml: canonical membership registry
  with roles, capabilities, status, and failure policies for all 8 participants
- docs/architecture/ai-council/status-model.md: AVAILABLE/DEGRADED/UNAVAILABLE/
  DISABLED/NOT_CONFIGURED with the UNAVAILABLE != REMOVED invariant
- docs/architecture/ai-council/degraded-operation.md: per-role policy for
  when absence blocks vs warns, and Amethyst's override
- docs/architecture/ai-council/provenance.md: format for reconstructing
  what the council did on any PR
- scripts/ai-council/health.py: human-readable and JSON health reports
- .github/workflows/ai-council.yml: CI validation of registry schema
Documents the research behind the council formalization decision:
- BIP-1 and EIP-1 primary sources on proposal/author/editor/consensus roles
- Structural analogy table (functional, not identity)
- What is novel: AI-mediated roles in a blockchain-style review structure
- Honest evolution history (grown, not designed)
- Why-now reasoning grounded in observable system properties
- Explicit 'what we are claiming' statement with bounded analogy
The consensus gate is a commitment device by design. It constrains
even the founder from merging on feeling or impatience. A review
system its creator can casually bypass is a suggestion box, not a
review system.
- .github/workflows/ai-council.yml: add permissions: contents read and
  persist-credentials: false (zizmor artipacked/excessive-permissions)
- docs/architecture/ai-council/degraded-operation.md: correct turn-2
  failure policy to match review-relay.yml (turn-3 gated on turn-2 success)
- site/index.html: rebuild via scripts/site.py build
The github-advanced-security Copilot agent hit monthly quota exhaustion,
failing AI code scanning on PR #60. The council continued normally —
Claude, CodeRabbit, Devin, Greptile all unimpaired. This is the first
recorded instance of a review tool going UNAVAILABLE in production,
validating the degraded operation policy: absence was visible, correctly
diagnosed, and did not cascade.
Per merge requirement: document current usage for each council participant
before PR #60 merges. Includes known data (Gokoo 2.8B tokens, Greptile
unlimited ~11-12 days, Copilot quota exhausted) and explicit gaps for
Claude, CodeRabbit, Devin, and Copilot reset date.
Exact usage tracking proved impractical. New approach: record known costs,
document UNAVAILABLE events in incidents.md when they happen. Adds watch
items for Greptile unlimited expiry (~Oct 21-22) and Claude billing limits.
- registry.yaml:143: fix turn-2 failure_policy to match review-relay.yml
  (turn 3 blocked on turn-2 failure, relay must be re-run)
- health.py: FULL now requires all members AVAILABLE (not just required);
  lead UNAVAILABLE gives STOPPED; timestamp relabeled as report generation
  time, not status verification time; JSON uses report_generated_at
- ai-council.yml: validator now requires all mandatory roles
  (lead, auditor, second_opinion, moderator, verifier), not just auditor
- ADR-0049: fix health.sh -> health.py reference
- provenance.md, degraded-operation.md: fix override label name to
  consensus-override (was review-consensus-override)
- costs.md: clarify incident->registry status update procedure; remove
  ungrounded 'two-member floor' reference to degraded-operation.md
- incidents.md: clarify Copilot is not a registry participant; UNAVAILABLE
  label is descriptive
Turn-4 verification is explicitly advisory (required: false in registry).
Remove it from REQUIRED_ROLES in the CI validator.
- registry.yaml, degraded-operation.md: clarify turn-1 UNAVAILABLE is
  policy (should block) not code enforcement (tally needs 2 GOs, no
  turn-1 requirement) — docs now match reality
- liveness.py: actually load REGISTRY and compare observed vs expected;
  surface API errors instead of swallowing them
- provenance.md: expected participants from registry at reviewed commit,
  not merge commit
Design principle: protocol messages structured so equivocation is
cryptographically provable by any observer. Makes dishonesty irrational
(certain detection) not just difficult. Detection and punishment are
separate; this covers detection.
Codifies the principles that have emerged from building ONX:
accountability by construction, spec-first, adversarial review,
the gate binds its creator, evidence over assertion, honesty about
unknowns, better through understanding. Includes Amethyst's direct
statement on equivocation accountability verbatim.
Broader than equivocation ('misbehavior'), explicit self-containment
('from the messages alone'), names the mechanism ('cost always exceeds
the gain'). Updated in PHILOSOPHY.md and ADR-0050.
- Resolve site/index.html by regenerating it on the merged tree.
- Renumber the council ADR 0049 -> 0051: ADR-0049 is the BFT locking
  protocol from the M6 branch, written first (2026-10-09 vs 2026-10-10).
- Mark ADR-0051 superseded by the Forgejo migration: the council (CodeRabbit,
  Devin, Greptile, the GitHub review relay) was removed with the account.
  Its docs stay as the record; README carries an archive note.
- Remove .github/workflows/ai-council.yml (no CI on the server) and
  scripts/ai-council/{health,liveness}.py (they read GitHub PR activity).
- PHILOSOPHY.md and ADR-0050 (Accountability by Construction) unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
amethyst deleted branch docs/accountability-council 2026-10-11 04:56:15 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amethyst/the-open-network-x!2
No description provided.