Skip to content

feat(service): campaign routes — GET /amicode/campaigns + /amicode/campaign over the session ledgers (#658) - #662

Open
aarontrowbridge wants to merge 3 commits into
mainfrom
655-feat-campaign-routes
Open

feat(service): campaign routes — GET /amicode/campaigns + /amicode/campaign over the session ledgers (#658)#662
aarontrowbridge wants to merge 3 commits into
mainfrom
655-feat-campaign-routes

Conversation

@aarontrowbridge

Copy link
Copy Markdown
Member

Closes #658

What

The Campaign Inspector's data path (slice zero-and-a-half of the approved Armonia knowledge-system design): two read-only routes over the personal vault's session ledgers, plus the widget-fetch allowlist entries so a digest widget can consume them.

  • GET /amicode/campaigns — every sessions/session-*.md in the personal vault, newest first: slug, date, campaign, status, type, one-line objective. Empty/missing dir → empty list; malformed frontmatter degrades to null fields + filename date; never a 500.
  • GET /amicode/campaign?slug=… — one ledger parsed into structured sections: verdict-table rows, active work, blocked, next queue, a bounded loop-log tail (last 10 table rows / 40 lines), compaction state, sections found, file date (staleness honesty — ≤15-min off-machine per the sync cadence). Unknown slug → the service's not_found convention; the slug guard doubles as the session-*.md glob and bars traversal.
  • The parser is a mechanical projection of the stable nine-section grammar — no LLM, no agent authoring. Node-builtins only (the sibling splice rule). Handles the §9-straddle corruption verified in the wild: loop-log rows appended after the §9 header are recovered into §8's table, not lost to the compaction bucket.
  • Allowlist: both routes join FETCH_ROUTES; exact-match property preserved and tested (/amicode/campaign-x does not ride /amicode/campaign).

Acceptance criteria — evidence

  • List route returns parsed ledgers newest-first — fixture tests + live smoke: 26 real ledgers, date-sorted
  • Detail route returns structured sections — fixture tests + live smoke: the live skill-health ledger parses to 19 verdict rows, sections [1..9], bounded tail, honest not_found on unknown slug
  • §9-straddle corruption handled — a real straddled ledger (session-20260820-hrl-8dot-spin-mintime) is a checked-in fixture; no rows lost
  • Graceful degradation — empty dir, missing sections, frontmatter-less, malformed frontmatter (fixture-tested)
  • Allowlist entries + exact-match tests — 17/17 through the overlay's bun runner

Director gates (independently run)

Leftovers flagged

  • The digest widget and Campaign tab (the route's consumers) are the next slices
  • DEMOS.md frozen-but-spliced — separate slice, already queued
  • A brand-new ledger appeared mid-smoke (session-20260831-session-spawn-and-hub-resilience) — another live session on the fleet; the file_date staleness field exists precisely so the UI can show sync-cadence truth

Merge

Awaiting human review per campaign discipline. CI runs on this PR.

GET /amicode/campaigns and /amicode/campaign join FETCH_ROUTES so the
upcoming Campaign Inspector digest widget can fetch them. Exact-match
property preserved and tested: /amicode/campaign-x, /amicode/campaignx,
and /amicode/campaigns-extra still fail the prefix-ride check.
…on ledgers (#658)

The Campaign Inspector's data path: two read-only routes over the personal
vault's sessions/ dir plus the ledger-section parser that feeds them.

- campaign_ledger.ts — mechanical projection of the stable nine-section
  grammar: split on the '## N.' headers (the '## §N' variant and the
  out-of-order '## 10.' thread included), §2's verdict table parsed to rows
  (header kept, separator dropped), §3/§4/§5 as structured text, §8 bounded
  to the last 10 table rows (last 40 lines when non-table), §9 as compaction.
  The §9-straddle corruption (loop rows appended after §9's header, verified
  in the wild) is recovered: §8's table extends to EOF, no rows lost to the
  compaction bucket. node-builtins only, per the sibling rule; frontmatter
  parsed regex-lite like stack_state.ts's parseMarker.
- GET /amicode/campaigns — newest-first list (slug, date, campaign, status,
  type, one-line objective) from the personal vault via the vault family's
  mount resolution. Empty/missing dir → empty list; frontmatter-less or
  malformed ledgers degrade to null fields + the filename date; unreadable
  entries (directories-as-files included) are skipped. Never a 500.
- GET /amicode/campaign?slug=… — one ledger's structured sections
  (verdicts/active_work/blocked/next_queue/loop_log_tail/compaction/
  sections_found + file_date for staleness honesty). Unknown slug → the
  problems.ts not_found BODY convention; the slug guard doubles as the
  session-*.md glob and bars traversal. The vault-browser's fail-closed
  loopback law rides along (personal mounts pass by default).
- Fixtures: trimmed REAL ledgers — the clean strumento-twins one and the
  §9-straddled hrl-8dot one — plus synthetic edges (missing §4/§5, empty
  dir, frontmatter-less, malformed frontmatter, non-table §8).

AC map: list route + parser = AC1, detail route = AC2, straddle recovery =
AC3, degradation = AC4 (allowlist = separate ui commit).
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 935046d5-d88a-4896-b196-9f60065163e7


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.

…ts test (drift gate green)

The overlay is extractor-managed; the campaign-route slice's two overlay edits
(widget-allowlist FETCH_ROUTES + its exact-match test) needed their manifest
sha256 entries re-recorded. Precedent: #639's manifest hash updates. Local drift
gate: PASS (558 files).
@aarontrowbridge
aarontrowbridge marked this pull request as ready for review August 31, 2026 05:09
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.

service: campaign routes — GET /amicode/campaigns + /amicode/campaign (parsed ledger sections) + widget-allowlist entries

1 participant