Skip to content

docs: enroll Agent Zero + Archon in living-docs tracking, mark superseded docs - #2449

Merged
POWERFULMOVES merged 4 commits into
mainfrom
docs/enroll-az-archon-living-docs
Aug 7, 2026
Merged

POWERFULMOVES merged 4 commits into
mainfrom
docs/enroll-az-archon-living-docs

Conversation

@POWERFULMOVES

@POWERFULMOVES POWERFULMOVES commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Root cause

Neither integration had any entry in pmoves/configs/living_docs_registry.yaml. make docs-reconcile-check was structurally blind to their docs drifting from their code — so the drift mechanism worked fine; these two were simply never enrolled.

That single gap produced everything below, including the live Prometheus outage fixed separately in #2448.

Commit 1 — enrollment (mechanical)

Enrolls the four docs that are actually canonical:

Doc Budget Why
AGENT_ZERO_API.md 30d live-state, probed from /openapi.json
services/agent-zero/README.md 60d env vars, build, make targets
ARCHON_MINT_CONTRACT_REVIEW.md 60d authoritative mint-pipeline state
SERVICE_HEALTH_ENDPOINTS.md 90d the doc that would have caught #2448

Severity P2 is deliberate. Freshness is measured from last-commit date (docs_reconcile.py:174-185), and two are already outside budget (81d, 155d). Enrolling at P1 would fail CI on merge for pre-existing staleness this PR didn't cause. Promote to P1 after a refresh pass.

Verified: docs_reconcile.py --check exits 1 both with and without this change — pre-existing P1s (.claude/BOOTSTRAP.md 102d, AGNOTE4482_SITREP.md 10d, dashboard 163 commits behind). The entire delta is two honest P2 warnings. CI status unchanged. Registry parses; 24 tracked entries; no missing paths; renderable: intact.

Commit 2 — supersede banners (judgment)

Bannered, not deleted. These have real inbound references — .claude/CLAUDE.md, four TAC docs, INTEGRATIONS_OVERVIEW.md, SERVICE_DOCS_MATRIX.md, and pmoves/scripts/update_service_logs.py (a script reads UPDATE_NOTES). Deletion would break all of them.

Agent Zero — documents an API that was never implemented:

Documented Reality (services/agent-zero/main.py)
GET /mcp/health GET /healthz
GET /mcp/agents does not exist
POST /mcp/subordinate/create does not exist
POST /mcp/execute {task, context, priority} {cmd, arguments}
agent.zero.* / agent.task.* agentzero.task.v1, agentzero.memory.update

Not merely stale prose — agent-zero-orchestration.md ships copy-pasteable curl and nats sub commands that 404 or never fire, and .claude/CLAUDE.md listed it as the MCP API reference.

Archon — describes the pre-0.6.0 Python/Supabase service (169d–234d old). 0.6.0 (#2217) is TypeScript/Bun, single port 3090, /api/health, Postgres via DATABASE_URL. Host ports 3737/8091 are compat aliases onto container 3090, not separate services.

Three broken references fixed in .claude/CLAUDE.md:

  • Tier-2 pointed at PMOVES-Agent-Zero/.claude/CLAUDE.mdthat submodule has no .claude/ directory at all, so any agent following the documented load order got a failed read and silently continued with no submodule context
  • "Additional References" listed the fictional orchestration doc as the MCP API reference
  • A context-loop note used the wrong path for ARCHON_INTEGRATION.md

Each banner names its canonical replacement, so readers are redirected rather than just warned off.

Deliberately not included

.claude/commands/agents/{execute,subordinate,task-status}.md — three user-invocable slash commands built entirely on the same nonexistent endpoints. Every curl in them 404s.

execute and task-status can be rewritten against the real async model (POST /tasksGET /jobs/{context_id}). subordinate cannot — subordinate-agent creation has no implementation to point at. Deleting it removes a documented intent; leaving it is a trap. That's an operator call, so it's held back rather than guessed at.

Related: #2448 (Archon blackbox probe — live outage from the same root cause).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Added prominent notices identifying outdated Agent Zero and Archon guidance.
    • Updated documentation to reference canonical API, architecture, integration, and service resources.
    • Clarified current Archon 0.6.0 endpoints, architecture, and backend details.
    • Documented verified Agent Zero endpoints and messaging subjects while preserving historical material.
    • Added registry entries to track documentation freshness and review severity.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

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

Next review available in: 11 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

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

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

How do review limits work?

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

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

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 21d39fb1-6efc-4691-ac75-d4dff1428a44

📥 Commits

Reviewing files that changed from the base of the PR and between c0c4a58 and 7b5d948.

📒 Files selected for processing (1)
  • pmoves/scripts/update_service_logs.py
📝 Walkthrough

Walkthrough

Updated Agent Zero and Archon documentation with supersession notices, canonical references, current API and architecture details, and freshness tracking in the living-document registry.

Changes

Documentation canonicalization

Layer / File(s) Summary
Agent Zero canonical guidance
.claude/CLAUDE.md, .claude/context/agent-zero-orchestration.md, pmoves/docs/TAC/TAC_AGENT_ZERO.md
Agent Zero references now identify obsolete API, endpoint, request, and NATS subject details and link canonical documentation.
Archon architecture notices
.claude/CLAUDE.md, pmoves/docs/integrations/ARCHON_INTEGRATION.md, pmoves/docs/services/archon/*
Archon documents now identify superseded pre-0.6.0 architecture and record the current TypeScript/Bun server, API, port, and database details.
Living documentation registry
pmoves/configs/living_docs_registry.yaml
Added freshness and P2 warning entries for Agent Zero, Archon handoff, and cross-service health documentation.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested labels: docs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the changes well but omits the required Testing, Required Checks, and Review Coordination sections. Add the required Testing, Required Checks, and Review Coordination sections, and document executed commands, check results, and review coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the enrollment and supersession-banner changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/enroll-az-archon-living-docs

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

❤️ Share

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

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c0c4a58cb6

ℹ️ About Codex in GitHub

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

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

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

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

Comment thread .claude/CLAUDE.md
- `PMOVES-Archon/.claude/CLAUDE.md` — agent service architecture
- `PMOVES-BoTZ/.claude/CLAUDE.md` — skills marketplace framework (legacy/archived per 2026-04-19)
- `PMOVES-Agent-Zero/.claude/CLAUDE.md` — orchestration patterns
- Agent Zero — the submodule has **no** `.claude/CLAUDE.md` (verified 2026-08-06). Use `pmoves/services/agent-zero/README.md` for the service, and `pmoves/docs/operations/AGENT_ZERO_API.md` for the live API surface.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Correct the promoted Agent Zero API reference

When an operator follows this newly promoted live-API reference, its copyable /mcp/execute examples send {"name": ...} even though MCPExecuteRequest in pmoves/services/agent-zero/main.py requires cmd, so both examples receive a 422 response. The document also redirects readers to .claude/context/mcp-api.md as the canonical specification, although that file still documents the same nonexistent /mcp/health, /mcp/agents, and /mcp/subordinate/create surface being retired here; refresh this target and retire the conflicting reference before making it the recommended API source.

Useful? React with 👍 / 👎.

Comment on lines +134 to +137
- path: pmoves/docs/handoffs/ARCHON_MINT_CONTRACT_REVIEW.md
freshness_days: 60
severity: P2
description: "Archon mint-contract current state — archon.mint.* implementation + registration gaps; authoritative over the mint-agent command doc"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Refresh the Archon mint review before declaring it authoritative

When contributors use this entry as the authoritative current state, the referenced document incorrectly says the mint schemas and topics.json mappings are still owed and that the mint subjects are absent from nats-subjects.md; at this commit, all five topic mappings, their schemas, and the subject catalog entries already exist. It also leaves appendix checks labeled as unregistered, so this designation sends implementation work toward gaps that have already been resolved.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pmoves/docs/services/archon/UPDATE_NOTES.md`:
- Around line 1-11: Update update_service_logs.py::render_markdown to preserve
the Archon supersession warning before the generated “# archon — Update Notes”
section when rendering the legacy pre-0.6.0 Archon runbook. Reuse the existing
warning content or emit it through the legacy service template so regeneration
does not overwrite the prefix.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5955efab-f618-4234-916a-cbb32209aa50

📥 Commits

Reviewing files that changed from the base of the PR and between c7ff017 and c0c4a58.

📒 Files selected for processing (8)
  • .claude/CLAUDE.md
  • .claude/context/agent-zero-orchestration.md
  • pmoves/configs/living_docs_registry.yaml
  • pmoves/docs/TAC/TAC_AGENT_ZERO.md
  • pmoves/docs/integrations/ARCHON_INTEGRATION.md
  • pmoves/docs/services/archon/HEADLESS_RUNBOOK.md
  • pmoves/docs/services/archon/README.md
  • pmoves/docs/services/archon/UPDATE_NOTES.md

Comment thread pmoves/docs/services/archon/UPDATE_NOTES.md
POWERFULMOVES and others added 2 commits August 7, 2026 11:41
…s tracking

Neither integration had ANY entry in living_docs_registry.yaml, so
`make docs-reconcile-check` was structurally blind to their docs drifting away
from their code. That is the root cause behind a cluster of defects found in a
read-only audit of both integrations:

  - .claude/context/agent-zero-orchestration.md (165d) and
    pmoves/docs/TAC/TAC_AGENT_ZERO.md (106d) document an /mcp/* API and an
    agent.zero.* / agent.task.* NATS family that were NEVER implemented —
    including copy-pasteable curl and `nats sub` commands that cannot work.
    Real endpoints are /healthz, /mcp/commands, /mcp/execute ({cmd, arguments});
    real subjects are agentzero.task.v1 and agentzero.memory.update.

  - Four Archon docs (169d-234d) still describe the pre-0.6.0 Python/Supabase
    split-port architecture. Archon 0.6.0 (#2217) is TypeScript/Bun on a single
    port, 3090, with /api/health.

  - Prometheus probed a dead Archon port AND path, reporting it permanently
    DOWN (fixed separately in #2448).

Enrolls the four docs that are actually canonical:

  AGENT_ZERO_API.md              live-state, probed from /openapi.json
  services/agent-zero/README.md  env vars, build, make targets
  ARCHON_MINT_CONTRACT_REVIEW.md authoritative mint-pipeline current state
  SERVICE_HEALTH_ENDPOINTS.md    the doc that would have caught #2448

Severity P2 (warn, never gate) is deliberate, not timidity. Freshness is
measured from last-commit date (docs_reconcile.py:174-185), and two of these are
already outside budget — AGENT_ZERO_API.md at 81d, SERVICE_HEALTH_ENDPOINTS.md
at 155d. Enrolling them at P1 would fail CI on merge for pre-existing staleness
this PR did not cause. Promote to P1 after a refresh pass brings them inside
budget.

Verified: `docs_reconcile.py --check` exits 1 both WITH and WITHOUT this change
(pre-existing P1 findings: .claude/BOOTSTRAP.md 102d, AGNOTE4482_SITREP.md 10d,
dashboard 163 commits behind HEAD). The entire delta from this commit is the two
P2 warnings above — CI status is unchanged. Registry parses, 24 tracked entries,
no missing paths, `renderable:` section intact.

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

Companion to the registry-enrollment commit. Six docs describe systems that no
longer exist — or in two cases, never existed. They are BANNERED, not deleted,
because they have real inbound references that deletion would break:
.claude/CLAUDE.md, four TAC docs, INTEGRATIONS_OVERVIEW.md, SERVICE_DOCS_MATRIX.md,
and pmoves/scripts/update_service_logs.py (a script reads UPDATE_NOTES).

Agent Zero — documents an API that was never implemented:
  .claude/context/agent-zero-orchestration.md (165d)
  pmoves/docs/TAC/TAC_AGENT_ZERO.md           (106d)

Both describe /mcp/health, /mcp/agents, /mcp/subordinate/create, a
POST /mcp/execute {task, context, priority} body, and an agent.zero.* /
agent.task.* NATS family. Verified against pmoves/services/agent-zero/main.py:
none exist. Real endpoints are /healthz, /config/environment, /metrics,
/mcp/commands, POST /mcp/execute {cmd, arguments}, /tasks, /jobs/{context_id},
/sessions, /memory CRUD, /events/publish. Real subjects are agentzero.task.v1
and agentzero.memory.update (controller.py:144).

This is not merely stale prose: the orchestration doc ships copy-pasteable curl
and `nats sub` commands that 404 or never fire.

Archon — describes the pre-0.6.0 Python/Supabase service:
  pmoves/docs/integrations/ARCHON_INTEGRATION.md   (169d)
  pmoves/docs/services/archon/UPDATE_NOTES.md      (184d)
  pmoves/docs/services/archon/README.md            (234d)
  pmoves/docs/services/archon/HEADLESS_RUNBOOK.md  (234d)

Archon 0.6.0 (#2217) is TypeScript/Bun on a single port 3090 with /api/health,
Postgres via DATABASE_URL. The docs still claim Supabase storage, /healthz on
:8091, an MCP server on :8051, PydanticAI on :8052, and a separate UI on :3737.
Host ports 3737/8091 are compat aliases onto container 3090, not services.

Also fixes three broken references in .claude/CLAUDE.md:
  - Tier-2 pointed at PMOVES-Agent-Zero/.claude/CLAUDE.md, which does not exist
    (no .claude/ directory in that submodule at all). Any agent following the
    documented load order got a failed read and silently proceeded with no
    submodule context.
  - "Additional References" listed agent-zero-orchestration.md as THE MCP API
    reference — the fictional one above.
  - A context-loop note pointed at pmoves/docs/ARCHON_INTEGRATION.md; the real
    path is pmoves/docs/integrations/ARCHON_INTEGRATION.md, and it is superseded.

Each banner names the canonical replacement so the reader is redirected, not
just warned off.

Not included, pending an operator decision: .claude/commands/agents/{execute,
subordinate,task-status}.md are three user-invocable slash commands built
entirely on the same nonexistent endpoints. execute and task-status can be
rewritten against /tasks + /jobs/{context_id}; subordinate cannot — subordinate
creation has no implementation to point at.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@POWERFULMOVES
POWERFULMOVES force-pushed the docs/enroll-az-archon-living-docs branch from c0c4a58 to 97917a0 Compare August 7, 2026 15:42
@github-actions github-actions Bot added docs Documentation config pmoves/config(s)/ changes labels Aug 7, 2026
POWERFULMOVES and others added 2 commits August 7, 2026 18:11
…ading

CodeRabbit (Major): the SUPERSEDED banner #2449 adds to archon/UPDATE_NOTES.md
would be wiped by update_service_logs.py on rerun. extract_manual_prefix()
preserves any hand-authored content above the '# <name> — Update Notes' H1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@POWERFULMOVES
POWERFULMOVES merged commit 3c4bbb1 into main Aug 7, 2026
18 of 19 checks passed
@POWERFULMOVES
POWERFULMOVES deleted the docs/enroll-az-archon-living-docs branch August 7, 2026 22:12
POWERFULMOVES added a commit that referenced this pull request Aug 14, 2026
…back citations

The first pass keyed on `http://<service>:<port>/path`. Then I counted the
actual citation forms in the scanned tree:

    localhost / 127.0.0.1 / host.docker.internal  1574
    service-name                                   158

So the class read like it covered documented endpoints while covering 9% of
them. That is the same defect the ratchet exists to catch, committed by the
thing catching it — a gate advertising coverage it does not have. Worse than a
missing check, because a green run reads as an answer.

Loopback host:port is now resolved to a service through the compose port map.
Two details that took a pass to get right:

  * Ports are written `${AGENT_ZERO_BIND:-127.0.0.1}:${AGENT_ZERO_PORT:-8080}:8080`.
    Without substituting `${VAR:-default}` the host field is not a digit and
    every port silently drops — the first parse mapped 18 ports and resolved
    none of 8080/8086/8091/8104. It now maps 118.
  * A port published by more than one service (11434 by two ollamas, 9096 by
    three jellyfins, 80/443 by nginx and traefik) is DROPPED, not guessed —
    21 such ports. Guessing attaches one service's route table to another's
    citations and invents ghosts.

Findings 11 -> 58, all hand-verified. It now catches the endpoints #2449
bannered by hand: /mcp/health x10, /mcp/agents x6, /mcp/subordinate/create x3.

Verified against all three Agent Zeros, because "the doc is wrong" is only
worth asserting if the API really is absent everywhere it could live:

  * PMOVES supervisor (pmoves/services/agent-zero) serves /mcp/commands and
    /mcp/execute, nothing else under /mcp.
  * PMOVES-Agent-Zero fork (v1.14) serves MCP at /t-{token}/sse + messages.
  * Upstream agent0ai/agent-zero v2.9 — latest — is identical: /t-{token}/sse,
    /t-{token}/http, /t-{token}/messages/.

No Agent Zero, at any version, ever served /mcp/health, /mcp/agents,
/mcp/tools/list or /mcp/subordinate/create.

Also surfaced, unrelated to Agent Zero: the voice-lane docs describe a
flute-gateway API that is not there. It declares /v1/voice/*; the docs cite
/v1/sessions (x4), /v1/voices, /v1/voice/health, /v1/voice/capabilities and
/v1/pipeline/status. And presign serves /presign/{get,post,put}, never /presign.

Baseline +58 -0. 47 tests pass. Gate still exits 1 on a planted loopback ghost.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
POWERFULMOVES added a commit that referenced this pull request Aug 14, 2026
…ot served

Four record defects in one session shared a shape no existing gate could see:
a doc stating something about the system that was confidently wrong, in a file
that was recently edited. `docs_reconcile.py` measures freshness. Freshness is
not accuracy — a doc updated yesterday with a fictional API passes it.

The anchor ratchet already had the right mechanism (does the named thing
resolve?) and the wrong coverage. Probed empirically against the four defects
before writing anything: it caught 0 of 4, while correctly catching both
control shapes. So this extends coverage, it does not add a second gate.

GHOST_ENDPOINT: a doc cites `http://<service>:<port>/<path>`, the service's
routes are readable, and it declares no such route.

Soundness — the part that decides whether this class is worth having:

  * Services that relocate routes at include/mount time (APIRouter(prefix=),
    include_router(prefix=), .mount()) are excluded outright. Their extracted
    route set would be wrong for every route, and false positives get baselined
    until the class means nothing.
  * Namespace rule: a path is only flagged if the service already declares a
    route in the same top-level namespace. agent-zero pulls /a2a/v1/* from a
    router defined outside its service dir — those routes are real and
    unreadable here, so absence must not imply ghost. It declares /mcp/*, so it
    has standing to be wrong about /mcp/tools/list, and none about /a2a/v1/*.

11 findings on main, all verified by hand, across 9 docs. Two things they show:

  * #2449 bannered six docs carrying the fictional Agent Zero `/mcp/*` API.
    Nine more docs cite it. A manual pass finds what it looks at; a gate finds
    what is there.
  * github-runner-ctl's documented `curl .../queue/POWERFULMOVES/PMOVES.AI`
    cannot work — `{repository}` matches one path segment, so it 404s. Nobody
    was going to notice that by reading.

Baselined, not fixed: this PR is the gate. Burning down the 11 is doc surgery
across 9 files and belongs on its own. The count only goes down.

Also triggers CI on pmoves/services/**/*.py — route drift runs both ways, and
the person renaming a route is rarely the person who wrote the runbook.

Verified: gate exits 1 on a planted fictional endpoint and 0 once removed;
43 tests pass, 8 new and pinned to the two properties that matter — it must
fire on a fictional route and stay silent where it has no standing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
POWERFULMOVES added a commit that referenced this pull request Aug 14, 2026
…back citations

The first pass keyed on `http://<service>:<port>/path`. Then I counted the
actual citation forms in the scanned tree:

    localhost / 127.0.0.1 / host.docker.internal  1574
    service-name                                   158

So the class read like it covered documented endpoints while covering 9% of
them. That is the same defect the ratchet exists to catch, committed by the
thing catching it — a gate advertising coverage it does not have. Worse than a
missing check, because a green run reads as an answer.

Loopback host:port is now resolved to a service through the compose port map.
Two details that took a pass to get right:

  * Ports are written `${AGENT_ZERO_BIND:-127.0.0.1}:${AGENT_ZERO_PORT:-8080}:8080`.
    Without substituting `${VAR:-default}` the host field is not a digit and
    every port silently drops — the first parse mapped 18 ports and resolved
    none of 8080/8086/8091/8104. It now maps 118.
  * A port published by more than one service (11434 by two ollamas, 9096 by
    three jellyfins, 80/443 by nginx and traefik) is DROPPED, not guessed —
    21 such ports. Guessing attaches one service's route table to another's
    citations and invents ghosts.

Findings 11 -> 58, all hand-verified. It now catches the endpoints #2449
bannered by hand: /mcp/health x10, /mcp/agents x6, /mcp/subordinate/create x3.

Verified against all three Agent Zeros, because "the doc is wrong" is only
worth asserting if the API really is absent everywhere it could live:

  * PMOVES supervisor (pmoves/services/agent-zero) serves /mcp/commands and
    /mcp/execute, nothing else under /mcp.
  * PMOVES-Agent-Zero fork (v1.14) serves MCP at /t-{token}/sse + messages.
  * Upstream agent0ai/agent-zero v2.9 — latest — is identical: /t-{token}/sse,
    /t-{token}/http, /t-{token}/messages/.

No Agent Zero, at any version, ever served /mcp/health, /mcp/agents,
/mcp/tools/list or /mcp/subordinate/create.

Also surfaced, unrelated to Agent Zero: the voice-lane docs describe a
flute-gateway API that is not there. It declares /v1/voice/*; the docs cite
/v1/sessions (x4), /v1/voices, /v1/voice/health, /v1/voice/capabilities and
/v1/pipeline/status. And presign serves /presign/{get,post,put}, never /presign.

Baseline +58 -0. 47 tests pass. Gate still exits 1 on a planted loopback ghost.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
POWERFULMOVES added a commit that referenced this pull request Aug 14, 2026
…ot served (#2541)

* feat(anchors): GHOST_ENDPOINT — catch documented HTTP APIs that are not served

Four record defects in one session shared a shape no existing gate could see:
a doc stating something about the system that was confidently wrong, in a file
that was recently edited. `docs_reconcile.py` measures freshness. Freshness is
not accuracy — a doc updated yesterday with a fictional API passes it.

The anchor ratchet already had the right mechanism (does the named thing
resolve?) and the wrong coverage. Probed empirically against the four defects
before writing anything: it caught 0 of 4, while correctly catching both
control shapes. So this extends coverage, it does not add a second gate.

GHOST_ENDPOINT: a doc cites `http://<service>:<port>/<path>`, the service's
routes are readable, and it declares no such route.

Soundness — the part that decides whether this class is worth having:

  * Services that relocate routes at include/mount time (APIRouter(prefix=),
    include_router(prefix=), .mount()) are excluded outright. Their extracted
    route set would be wrong for every route, and false positives get baselined
    until the class means nothing.
  * Namespace rule: a path is only flagged if the service already declares a
    route in the same top-level namespace. agent-zero pulls /a2a/v1/* from a
    router defined outside its service dir — those routes are real and
    unreadable here, so absence must not imply ghost. It declares /mcp/*, so it
    has standing to be wrong about /mcp/tools/list, and none about /a2a/v1/*.

11 findings on main, all verified by hand, across 9 docs. Two things they show:

  * #2449 bannered six docs carrying the fictional Agent Zero `/mcp/*` API.
    Nine more docs cite it. A manual pass finds what it looks at; a gate finds
    what is there.
  * github-runner-ctl's documented `curl .../queue/POWERFULMOVES/PMOVES.AI`
    cannot work — `{repository}` matches one path segment, so it 404s. Nobody
    was going to notice that by reading.

Baselined, not fixed: this PR is the gate. Burning down the 11 is doc surgery
across 9 files and belongs on its own. The count only goes down.

Also triggers CI on pmoves/services/**/*.py — route drift runs both ways, and
the person renaming a route is rarely the person who wrote the runbook.

Verified: gate exits 1 on a planted fictional endpoint and 0 once removed;
43 tests pass, 8 new and pinned to the two properties that matter — it must
fire on a fictional route and stay silent where it has no standing.

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

* fix(anchors): GHOST_ENDPOINT covered 9% of the surface — resolve loopback citations

The first pass keyed on `http://<service>:<port>/path`. Then I counted the
actual citation forms in the scanned tree:

    localhost / 127.0.0.1 / host.docker.internal  1574
    service-name                                   158

So the class read like it covered documented endpoints while covering 9% of
them. That is the same defect the ratchet exists to catch, committed by the
thing catching it — a gate advertising coverage it does not have. Worse than a
missing check, because a green run reads as an answer.

Loopback host:port is now resolved to a service through the compose port map.
Two details that took a pass to get right:

  * Ports are written `${AGENT_ZERO_BIND:-127.0.0.1}:${AGENT_ZERO_PORT:-8080}:8080`.
    Without substituting `${VAR:-default}` the host field is not a digit and
    every port silently drops — the first parse mapped 18 ports and resolved
    none of 8080/8086/8091/8104. It now maps 118.
  * A port published by more than one service (11434 by two ollamas, 9096 by
    three jellyfins, 80/443 by nginx and traefik) is DROPPED, not guessed —
    21 such ports. Guessing attaches one service's route table to another's
    citations and invents ghosts.

Findings 11 -> 58, all hand-verified. It now catches the endpoints #2449
bannered by hand: /mcp/health x10, /mcp/agents x6, /mcp/subordinate/create x3.

Verified against all three Agent Zeros, because "the doc is wrong" is only
worth asserting if the API really is absent everywhere it could live:

  * PMOVES supervisor (pmoves/services/agent-zero) serves /mcp/commands and
    /mcp/execute, nothing else under /mcp.
  * PMOVES-Agent-Zero fork (v1.14) serves MCP at /t-{token}/sse + messages.
  * Upstream agent0ai/agent-zero v2.9 — latest — is identical: /t-{token}/sse,
    /t-{token}/http, /t-{token}/messages/.

No Agent Zero, at any version, ever served /mcp/health, /mcp/agents,
/mcp/tools/list or /mcp/subordinate/create.

Also surfaced, unrelated to Agent Zero: the voice-lane docs describe a
flute-gateway API that is not there. It declares /v1/voice/*; the docs cite
/v1/sessions (x4), /v1/voices, /v1/voice/health, /v1/voice/capabilities and
/v1/pipeline/status. And presign serves /presign/{get,post,put}, never /presign.

Baseline +58 -0. 47 tests pass. Gate still exits 1 on a planted loopback ghost.

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

* fix(anchors): the port map imported yaml — in a step documented stdlib-only

CI caught this on the PR that introduced it, which is the system working.

`host_port_map()` imported yaml behind `try/except ImportError: return {}`. The
ratchet step is documented "stdlib only, no network" and has no pyyaml, so in CI
the map came back empty, every loopback finding vanished, and all 47 of them
tripped STALE_BASELINE against a baseline recorded on a machine that had yaml.

The import was not the bug. The SILENT degradation was: findings that depend on
an optional dependency, failing open, are not findings. That is the same defect
class this ratchet exists to catch, so it is fixed rather than papered over by
pip-installing yaml into the step.

Replaced with a direct parser and proved equivalence: 97 ports, IDENTICAL map to
the yaml parse, key-for-key. Two forms had to be handled, and both were found by
that comparison rather than by reading:

  * Inline flow sequence — `ports: ["${FLUTE_BIND:-127.0.0.1}:8055:8055", ...]`,
    used by flute-gateway, traefik and ~20 others. Missing it dropped 9 ports.
  * Trailing comment on the service key — `voice-sampler:  # media-sourced ...`.
    An endswith(":") test keeps the PREVIOUS service name, so voice-sampler's
    ports were filed under voice-relay.

Both failed in the UNDER-collecting direction, which is the dangerous one: a
port published by two services looks like it belongs to one, and the ambiguity
guard that exists to stop exactly that never fires. 80 and 443 briefly resolved
to nginx alone instead of being dropped as nginx-or-traefik.

Three tests pin it: the tool imports no third-party module, the service-key
regex tolerates a trailing comment while still rejecting list items and nested
keys, and the map covers block, inline and trailing-comment forms. 50 pass.

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

* fix(anchors): `<param>` in a URL made the gate flag correct documentation

Found by an agent applying doc fixes against this gate — it hit three flags on
`/jobs/`, a route that is real.

`<` was not in ENDPOINT_CITE_RE's path charclass. That did not skip the
citation, it TRUNCATED it: `http://localhost:8080/jobs/<context_id>` captured as
`/jobs/`, which then failed the matcher for the declared `/jobs/{context_id}`
and reported a ghost. The placeholder skip below could never fire, because it
only sees characters the capture kept.

`<param>` is a normal doc convention. So the gate was flagging accurate
documentation and would have pushed authors to "fix" docs that were right —
worse than missing, because a false positive spends someone's trust.

The first fix was also wrong and is worth recording: adding `<>` to the class
let the existing skip fire, which silently dropped THREE REAL GHOSTS
(`/mcp/task/<task_id>` in execute.md, mcp-query.md, task-status.md). Trading a
false-positive class for a false-negative class is not a fix.

Correct behaviour: `<param>` is treated as a wildcard, exactly like `{param}`.
It contains no slash, so it matches the `[^/]+` that a declared `{param}`
compiles to. Both directions stay honest:

    /jobs/<context_id>   -> matches real /jobs/{context_id}   -> silent
    /jobs/{context_id}   -> matches real /jobs/{context_id}   -> silent
    /mcp/task/<task_id>  -> matches no declared /mcp route     -> FLAGGED
    /mcp/health          -> matches no declared /mcp route     -> FLAGGED
    /mcp/commands        -> real                               -> silent

`$` is still skipped — shell interpolation can expand to anything, so there is
no claim to check.

Baseline: the same three ghosts are re-keyed from the truncated
`agent-zero/mcp/task/` to the accurate `agent-zero/mcp/task/<task_id>`. Total
findings unchanged at 504; no ghost gained or lost, three are now named
correctly. 52 tests pass, 2 new pinning both directions.

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

* feat(anchors): strict mode for services whose route set is provably complete

Prompted by the operator asking what happened to botz-gateway. Two findings
against it (/tools, /execute, in ARCHON_INTEGRATION.md:70-71) were surfaced by
the first cut of GHOST_ENDPOINT and then silenced by the namespace rule. That
was wrong, and the reason is worth stating.

The namespace rule exists to protect services whose routes we CANNOT SEE:
agent-zero pulls /a2a/v1/* from a router defined outside its service directory,
so "not in my extracted set" does not mean "not served". Fair.

But it was applied to every service, including ones with nothing unseen.
botz-gateway declares 16 routes -- /healthz, /metrics and /v1/* -- and contains
no include_router and no mount anywhere. Its route set is COMPLETE. A doc citing
botz-gateway:8054/tools is plainly wrong, and the rule stayed silent purely
because the service "owns no /tools namespace". A conservative rule applied
where it has no purpose is not conservative, it is blind.

Strict mode: a service with no include_router and no mount skips the namespace
rule entirely. 51 of 54 services with readable routes qualify.

Findings 0 -> 28 new, every one verified by hand against the declared routes:

  botz-gateway/health        real: /healthz
  extract-worker/health      real: /healthz
  ffmpeg-whisper/health      real: /healthz
  render-webhook/webhook/render  real: /comfy/webhook
  media-audio/.well-known/agent.json, /a2a/v1/tasks   declared nowhere

The /health vs /healthz cluster is the useful one: four services documented with
a probe path that 404s. That is an operational trap, not a typo -- a monitoring
check written from those docs reports the service down while it is healthy, or
worse, is quietly never wired up.

agent-zero and flute-gateway correctly stay OUT of strict mode; both include
routers, so the namespace rule still guards them.

Baselined, not fixed. 54 tests pass, 2 new pinning that botz-gateway is strict
and agent-zero is not.

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

---------

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

config pmoves/config(s)/ changes docs Documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant