12 KiB
12 KiB
os-backlog — component detail
Leaf file of ../implementation-status.md. Read on demand.
Global os-backlog plugin — cc-os/plugins/os-backlog/ (git-tracked, 2026-07-10);
symlinked into ~/.claude/plugins/os-backlog; PRD Forgejo issue #9, slices #10–#17.
Decision records: ADR-0023 (own plugin, not an os-vault extension), ADR-0025 (standard Ruby
plugin structure), ADR-0029 (column ownership — subject removed by ADR-0042), ADR-0042
(2026-07-16, supersedes ADR-0033): Planka retired; git issues are the single tracker for
state and specs (OpenSpec change retire-planka-git-issues-only).
Component inventory (post-ADR-0042, v0.3.0)
- Purpose: the AI's process-management surface over git issues — deterministic tracker
routing (
forgejo:<owner>/<repo>|github:<owner>/<repo>|repo:<path>;planka:rejected fail-soft citing ADR-0042), mid-session capture as labeled issues, pull-only listing, cross-project filing via the global project index. - State model: open/closed + labels. Ten canonical labels: priority
P0–P3; autonomyhitl/semi/afk-ready(semi ships toreviewlabel and stays open; afk-ready closes after verification); statenext(human-only — AI never applies/removes),waiting(+ blocker comment),review. Nodoing/donelabels: in-progress = assignment/branch activity, done = closed. Recurring-convention issues (e.g.jared/ops#1biweekly audit) are commented per occurrence and never closed by the AI. - Lib (Ruby):
tracker.rb(grammar validation +issues_destination::git_issues/:repo_files/:unrouted),issues.rb(2026-07-16 — capture/list dispatch:teafor forgejo,ghfor github,NNN-<slug>.mdfrontmatter files forrepo:; injected runner, no state labels reachable throughcreate),inspector.rb(issue-shape classification),config.rb,resolver.rb(reduced to tracker-presence decision),project_index.rb,wakeup.rb. - CLI:
bin/os-backlog—resolve,inspect,config-write,projects,issue-create(--title/--body/--priority),issues(grouped next/waiting/review/other). Fail-soft one-liners throughout. - Skills:
/os-backlog:capture(issue-create; never state labels, nevernext),/os-backlog:list(pull-only),/os-backlog:route(destination proposal + idempotent ten-label ensure via tea/gh). SessionStart note rewritten 2026-07-16 (~444 tokens, down from ~687 measured): capture / routing / cross-project / human-only-next/ working-state / autonomy / recurring rules. - Tests: 88 runs / 203 assertions (2026-07-16) with fake CLI runners; no live API.
Companion os-status
tracker-configuredcheck validates the reduced grammar and rejectsplanka:with the ADR-0042 advisory.
Build and verification history
- AFK slices shipped (2026-07-10): #10 plugin scaffold +
board-ensure(uniform lists/labels incl. newsemiautonomy label), #11trackerkey in.cc-os/config+ os-status check, #12 pure routing resolver CLI, #13 capture/list skills + card CLI, #15card-triage+board-auditnamed agents. Live verification same day: planka-api gem 0.1.0 installed locally (rake install, rbenv 4.0.2; publish/versioning parked behind gem issue 13);snapshot,board-ensure(created the missingsemilabel on the cc-os board),card-add+card-labelall succeeded against production Planka with bot credentials sourced from ovh-vps (~/services/planka/bot-credentials.env) in a subshell. Follow-up captured as ahitlBacklog card: get planka_bot into credvault (no import path — rotate vs. add import capability is a human decision). - planka-api 0.2.0 typed-returns migration (2026-07-10, commit
8df0cb7): 0.2.0 returnsPlanka::Typesvalue objects instead of parsed-JSON hashes.board_ensurer.rbandcards.rbrewritten on typed accessors;Cards#snapshotbuilds explicit string-keyed hashes fromBoardDetail#lists/#cards/#labels/#card_labels. Test fakes rebuilt to return realPlanka::Typesrecords. JSON output stays byte-compatible, so skill/agent contracts are unchanged. Follow-up fix (issue #18, same day): the migration had silently dropped one field from the per-card snapshot hash; restored the full 19-key camelCase card key set pluslabels, with a regression test pinning the key set includinglistChangedAt. - Live verification 0.2.0 (2026-07-10, issue #20): local machine had no
PLANKA_*env/credvault entry, so the plugin tree was rsynced toovh-vps:/tmp/os-backlog-verifyand exercised there with bot credentials sourced in a subshell (contents never read or printed). Results: tests 35 runs/0 failures on ovh-vps;board-ensure cc-osidempotent (twice(existing), nothing created); card-add/card-label/card-comment/snapshot all correct with the full 20-key set; test card deleted viaPlanka::Client#cards.delete(the CLI has no delete subcommand) and confirmed gone; verification tree removed. No regressions vs. pre-0.2.0. - Slice 7 (2026-07-13, issue #16): SessionStart injection note shipped
(
hooks/session_start.py+hooks/hooks.json, os-adr-style plugin-local hook): WHEN→THEN rules for capture / routing / promotion / column ownership / autonomy labels, ADR-0029 semantics (the issue body's "afk-ready → Review" was wrong — caught in Codex review), rules only, zero board state, ~447 tokens./to-issues(global skill,~/.agents/skills/to-issues/) gained a destination-tracker step reading the.cc-os/configtracker key; theplanka:/unset default publishes slices as git issues on the repo remote + one Planka pointer card (spec/state boundary preserved — human gate decided 2026-07-13).Backlog::Tracker.issues_destination+ 6 routing tests. - Board-id cache (2026-07-13, issue #22):
Backlog::BoardResolverwith injected config read/write lambdas;board_id=cached in.cc-os/configbesidetracker=(name stays source of truth; id honored only forplanka:trackers and validated against the returned board name; 404/mismatch/any cache failure degrades to name lookup and rewrites the cache; write failures never fail the command). Comment-preservingConfig.setmirrors os-status's writer. 14 new tests; suite 90 runs / 198 assertions / 0 failures. - Slice 8 (2026-07-13, issue #17): Operations board created in the Dev project (board
1818308120145822783) with uniform lists/labels; recurring card "Biweekly orchestration IRL audit (recurring)" (card1818310715438531668, P2 + semi, first progress comment1818310889929966683; recurrence contract: comment + move back to Backlog, never Done). Tracker-routing convention canonized as ADR-0033 (Planka = state / git issues = specs, tracker key grammar, pointer + promotion rules; cites route/to-issues/session-start rather than restating). os-context audit rubric gained category 8tracker-routing(capture/route/promote compliance only). Bug found live and fixed: label color fallback only rescuedPlanka::ValidationError, but Planka rejects unknown colors as HTTP 400Planka::BadRequestError— fallback now rescues both (regression test; suite 91 runs / 0 failures). os-status/os-status:fixstep d reworded: invoke/os-backlog:routedirectly, never pre-ask "forgejo or planka?" (boundary rule uses both — surfaced by the servers-repo onboarding, cf. issue #26). - Issue-shape classification (2026-07-13, issue #26):
inspectnow fetches lightweight remote-issue metadata (tea--output jsonwith string-index/joined-labels normalization; gh--json; fail-soft → nil) and emits an always-presentissue_shapekey (sequential-chain/flat-adhoc/mixed/ null). Classification is a pureInspector.classify_issue_shape(label allowlist with whole-token matching; cross-refs must hit the fetched set with dependency language within 40 chars; <3 issues or no metadata → null). Route SKILL.md step 2 rewritten as three branches with split as the default for spec-shaped issue sets (still exactly one tracker key — division of labor, not two destinations); step 3 got a never-re-trigger exception; boundary rule now cites ADR-0033 instead of restating it. 12 new tests incl. a CLI-contract test; suite 103 runs / 212 assertions / 0 failures. - Cross-project filing (2026-07-13, issue #27, ADR-0034):
Backlog::ProjectIndex— derived global index at~/.cc-os/projects.json(atomic temp+rename writes, corrupt/ missing → empty,CC_OS_HOMEoverride), upserted fail-soft by config-write (canonical path = realpath of the directory the config was written into — NOT the git toplevel, so umbrella subprojects index as themselves; corrected 2026-07-13 review), queried via newprojects [filter]CLI subcommand (filter matches name, tracker, or path). Discoverer template + tea/gh/card-add mechanics inskills/route/references/cross-project-filing.md; one CROSS-PROJECT rule line added to the SessionStart note. 9 new tests; suite 112 runs / 233 assertions / 0 failures. Live smoke: cc-os row present in the real index. - Wakeup design spike (2026-07-13, issue #28, ADR-0035/0036): poll + tmux direction
chosen at the human gate.
Backlog::Wakeup+bin/wakeup-pollthin pilot (dry-run default,--spawnto createcc-<project>-issue<N>tmux sessions and persist~/.cc-os/wakeup-state.json; opt-inwakeup=truein.cc-os/config; afk-ready → act, semi → triage-only, else notify-only into pull-only~/.cc-os/wakeup-summary.md). No cron installed; 6 tests; suite 128 runs / 0 failures. Follow-up recorded: single designated poller machine (state stays per-host); cadence/cron mechanism and aconfig-writewakeup key deferred until a first project opts in. - Review corrections (2026-07-13, cards #1818330518584820864 / #1818330528525321347):
post-ship review (Codex + verification pass) of the triage hook and project index:
Config#planka_board(tracker=planka:<board>now counts everywhere, incl. the Resolver, not just the explicitboardkey); triage hook board resolution moved to pureTriageCheck.board_name_forhonoring the umbrella rule (session cwd's.cc-os/configoverrides the git root's; hook previously read only the root config); index keying fixed per above; hook timeout 8→15s;CC_OS_DEBUG=1surfaces swallowed hook errors on stderr. Known residual (captured as a Backlog card): board lookup is name-only across ALL Planka projects — duplicate board names in different projects can resolve to the wrong board. Suite 138 runs / 295 assertions / 0 failures. - Planka retirement rework (2026-07-16, ADR-0042, OpenSpec change
retire-planka-git-issues-only): after a week live, all real work flowed through git issues while boards held only the plugin's own build cards — Planka retired. Deleted:board_ensurer/board_resolver/board_spec/cards/triage_check(+ triage hook), both agents, planka-api gem wiring,FakePlankaClient, nine card/board CLI subcommands. Added:issues.rb+issue-create/issuesCLI (live-verified; fixed tea fieldassignees—assigneeis not a valid tea list field). Skills + SessionStart note +/to-issues+ os-status fix skill rewritten to the single-tracker model. Migration: all 9 boards snapshotted (JSON + comments) + Postgres dump on ovh-vps; snapshot archived in new privatejared/opsForgejo repo (canonical labels; recurring audit issuejared/ops#1); cc-os non-Done cards → issues jared/cc-os#61–70 (3 skipped: pointer to closed #25, duplicate of open #8, obsoleted board-lookup card); ovh-prod + ruby-gems strays → jared/ops#2–3;plankaboard's 18 cards obsolete (gem build history, covered by snapshot);tracker=rewritten in all 6 indexed projects (noplanka:values remain). Suite 88 runs / 203 assertions; os-status 80 tests. - Human gates closed (2026-07-16): philly per-card pass done — 4 repo cards →
jared/llf-schema#7–10, 18 client cards → jared/ops#4–21, guardrails pin closed (vault
note is the record). Decommission done same day: bot creds deleted, Planka
containers/cron/service dir removed from ovh-vps (snapshot + pg dump + service configs
kept at
~/planka-final-snapshot-2026-07-16/), github.com/jaredswanson/planka archived read-only with an ADR-0042 README banner. - Outstanding: #14 residual (onboard one more project — operational hitl); wakeup rollout (first opt-in project + poller machine + cadence); jared/cc-os#74 — fold ADR-0025 compliance into os-backlog (bin/wakeup-poll second entry point, README gem deps), filed by the standards audit.