Skip to content

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

Description

@aarontrowbridge

Important

Problem — The approved Armonia knowledge-system design's flagship is the Campaign Inspector: a home-dashboard digest widget plus a Work Column drill-down rendering live campaign state. Its data path does not exist: the service serves problems, runs, warrants, vault files — but no campaign/ledger route, and the widget allowlist would reject any fetch a digest widget attempted. The ground truth is the personal vault's session ledgers (sessions/session-<date>-<slug>.md), written by live agents in a stable nine-section grammar (§1 objective/directives, §2 verdict table, §3 active work, §4 blocked, §5 next queue, §6 checkout topology, §7 gotchas, §8 loop log, §9 compaction) — but that grammar is only machine-readable today by whatever reads the raw file.
Approach — Two read-only service routes over the personal vault's sessions directory, plus the allowlist entries: GET /amicode/campaigns (list: slug, date, campaign name, status, one-line objective — frontmatter + first section scan, newest first) and GET /amicode/campaign?slug=… (one ledger parsed into structured sections: the §2 verdict-table rows, §3 active work, §4 blocked, §5 next queue as structured text, the §8 loop log as a bounded tail window, and §9's compaction state). The parser is a mechanical projection of the stable section grammar — splitting on the ## N. headers and parsing §2's markdown table — no agent authoring, no LLM. Known grammar corruption must be handled: some ledgers have loop-log rows appended after the §9 header (append-at-EOF straddle, verified in the wild) — the parser must treat §8's table as extending to EOF in that case. Multi-machine honesty: the data is as fresh as the vault sync (≤15 min off-machine); the route returns the ledger's own timestamp fields so the UI can show staleness.
Scope — in: the two routes + a ledger-section parser module + allowlist entries + tests (fixture ledgers incl. a straddled §9, missing sections, empty vault) · out: any UI rendering (the digest widget and Campaign tab are subsequent slices), any ledger writing, the vault-query verb, the OBSIDIAN/free-vault surfaces.

Acceptance Criteria

  • GET /amicode/campaigns returns the parsed list of session ledgers (slug, date, campaign, status, objective line), newest first, from the personal vault's sessions/ directory
  • GET /amicode/campaign?slug=… returns the ledger's structured sections: verdict-table rows, active work, blocked, next queue, loop-log tail window (bounded), compaction-log state
  • The parser handles the §9-straddle corruption (loop rows after the §9 header) — verified against a real straddled ledger fixture
  • Missing sections, an empty sessions dir, and malformed frontmatter degrade gracefully (empty arrays / omitted fields, never a 500)
  • Both routes are added to the widget-fetch allowlist (a widget may fetch them); the allowlist's exact-match/no-bare-prefix property is preserved and tested

Testing Decisions

Extend the service route test suite (mirror the problems/run-status route tests' pattern); parser tests use trimmed REAL ledger fixtures (a clean one + the straddled one) checked into the test tree, plus synthetic edge cases.

Prior Art

The problems/run-status routes (the service's existing read-only route pattern); the stack-state splice module (the frontmatter-parsing and node-builtin-only constraints — the parser should follow the same dependency discipline as its sibling module); the session-ledger grammar (stable across all 24 ledgers on disk).

Notes

Slice zero-and-a-half of the approved Armonia knowledge-system design (plans/2026-08-30-armonia-knowledge-system.md): "the ledger route + widget-allowlist plumbing — no campaign route exists in the service or FETCH_ROUTES today; named as its own slice." The digest widget and Campaign tab consume this route in their own subsequent slices. Staleness honesty (≤15-min off-machine) comes from the design's streaming-honesty line. Part of the skill-health campaign (session-20260830-skill-health).

Metadata

Metadata

Assignees

No one assigned

    Labels

    afkImplementable without human interaction

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions