2026-07-13 13:18:23 +00:00
|
|
|
|
# os-backlog — component detail
|
|
|
|
|
|
|
|
|
|
|
|
_Leaf file of [../implementation-status.md](../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 (state pointer: Planka
|
|
|
|
|
|
card `1816234194716592051`), slices #10–#17. Decision records: ADR-0023 (own plugin, not an
|
|
|
|
|
|
os-vault extension), ADR-0025 (standard Ruby plugin structure), ADR-0029 (card-move +
|
|
|
|
|
|
column ownership).
|
|
|
|
|
|
|
|
|
|
|
|
## Component inventory
|
|
|
|
|
|
|
|
|
|
|
|
- Purpose: the AI's process-management surface over Planka — deterministic tracker routing
|
|
|
|
|
|
(Planka = task state by default; git issues = implementation specs only), mid-session
|
|
|
|
|
|
capture, pull-only listing, board lifecycle, and the three-value autonomy convention
|
|
|
|
|
|
(`hitl`/`semi`/`afk-ready`; amended per ADR-0029: afk-ready ships straight to Done, semi
|
|
|
|
|
|
stops at Review).
|
|
|
|
|
|
- Lib (Ruby, os-adr `lib/`+`bin/` pattern, installed planka-api gem only — no source
|
|
|
|
|
|
coupling): `board_spec.rb` (uniform lists/labels contract), `board_ensurer.rb`
|
|
|
|
|
|
(idempotent create/repair; Planka 2.1.1 `type` fields, shared-project + owner-manager
|
|
|
|
|
|
visibility fix, label color candidates with fallback; `archived--` rename convention),
|
|
|
|
|
|
`config.rb` (`.cc-os/config` parser), `resolver.rb` (pure repo→board decision:
|
|
|
|
|
|
`use`/`activate`/`stop-and-discuss`; no network), `cards.rb` (add-at-Backlog, snapshot,
|
|
|
|
|
|
attach_label, comment, move with ownership rules), `tracker.rb` + `inspector.rb`
|
|
|
|
|
|
(2026-07-12, issue #14 — tracker-format validation/remote classification + in-repo
|
|
|
|
|
|
issue-file discovery; `Config.merge` preserves other keys).
|
|
|
|
|
|
- CLI: `bin/os-backlog` — `board-ensure`, `activate`, `archive`, `resolve`, `card-add`,
|
|
|
|
|
|
`cards`, `snapshot`, `card-label`, `card-comment`, `card-move` (2026-07-12, ADR-0029),
|
|
|
|
|
|
`inspect`, `config-write`; every path fails soft (one-line error, exit 1) when the
|
|
|
|
|
|
gem/Planka is unavailable.
|
|
|
|
|
|
- Skills: `/os-backlog:capture`, `/os-backlog:list` (pull-only per notification policy v2),
|
|
|
|
|
|
`/os-backlog:route` (2026-07-12, issue #14 — tracker onboarding conversation; destination
|
|
|
|
|
|
choice + live-history migration are named human gates) — carry the column-ownership rules
|
|
|
|
|
|
(AI creates at Backlog, Doing→Review at most, never Next, never self-assigns `hitl`;
|
|
|
|
|
|
"working a card means moving it" contract added 2026-07-12).
|
|
|
|
|
|
- Agents: `agents/card-triage.md` (priority + autonomy labels only; ambiguity → `hitl`),
|
|
|
|
|
|
`agents/board-audit.md` (four drift classes; writes at most comments).
|
|
|
|
|
|
- Tests: `tests/` — 68 runs/153 assertions as of 2026-07-12 (35 → 54 → 58 → 68 across the
|
|
|
|
|
|
slices) against an in-memory `FakePlankaClient`; no live API. Companion os-status check
|
|
|
|
|
|
`tracker-configured` (issue #11) validates the `tracker` key grammar and nudges
|
|
|
|
|
|
unconfigured git projects (daily-snoozed).
|
|
|
|
|
|
|
|
|
|
|
|
## Build and verification history
|
|
|
|
|
|
|
|
|
|
|
|
- **AFK slices shipped (2026-07-10):** #10 plugin scaffold + `board-ensure` (uniform
|
|
|
|
|
|
lists/labels incl. new `semi` autonomy label), #11 `tracker` key in `.cc-os/config` +
|
|
|
|
|
|
os-status check, #12 pure routing resolver CLI, #13 capture/list skills + card CLI, #15
|
|
|
|
|
|
`card-triage` + `board-audit` named 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 missing `semi` label on the cc-os
|
|
|
|
|
|
board), `card-add` + `card-label` all succeeded against production Planka with bot
|
|
|
|
|
|
credentials sourced from ovh-vps (`~/services/planka/bot-credentials.env`) in a subshell.
|
|
|
|
|
|
Follow-up captured as a `hitl` Backlog 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 returns
|
|
|
|
|
|
`Planka::Types` value objects instead of parsed-JSON hashes. `board_ensurer.rb` and
|
|
|
|
|
|
`cards.rb` rewritten on typed accessors; `Cards#snapshot` builds explicit string-keyed
|
|
|
|
|
|
hashes from `BoardDetail#lists`/`#cards`/`#labels`/`#card_labels`. Test fakes rebuilt to
|
|
|
|
|
|
return real `Planka::Types` records. 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 plus `labels`, with a regression test pinning the key set including
|
|
|
|
|
|
`listChangedAt`.
|
|
|
|
|
|
- **Live verification 0.2.0 (2026-07-10, issue #20):** local machine had no `PLANKA_*`
|
|
|
|
|
|
env/credvault entry, so the plugin tree was rsynced to `ovh-vps:/tmp/os-backlog-verify`
|
|
|
|
|
|
and 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-os` idempotent
|
|
|
|
|
|
(twice `(existing)`, nothing created); card-add/card-label/card-comment/snapshot all
|
|
|
|
|
|
correct with the full 20-key set; test card deleted via `Planka::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/config` tracker key; the `planka:`/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::BoardResolver` with injected config
|
|
|
|
|
|
read/write lambdas; `board_id=` cached in `.cc-os/config` beside `tracker=` (name stays
|
|
|
|
|
|
source of truth; id honored only for `planka:` 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-preserving `Config.set`
|
|
|
|
|
|
mirrors os-status's writer. 14 new tests; suite 90 runs / 198 assertions / 0 failures.
|
2026-07-13 14:00:36 +00:00
|
|
|
|
- **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)" (card `1818310715438531668`, P2 + semi, first progress comment
|
|
|
|
|
|
`1818310889929966683`; 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 8 `tracker-routing`
|
|
|
|
|
|
(capture/route/promote compliance only). Bug found live and fixed: label color fallback
|
|
|
|
|
|
only rescued `Planka::ValidationError`, but Planka rejects unknown colors as HTTP 400
|
|
|
|
|
|
`Planka::BadRequestError` — fallback now rescues both (regression test; suite 91 runs /
|
|
|
|
|
|
0 failures). os-status `/os-status:fix` step d reworded: invoke `/os-backlog:route`
|
|
|
|
|
|
directly, never pre-ask "forgejo or planka?" (boundary rule uses both — surfaced by the
|
|
|
|
|
|
servers-repo onboarding, cf. issue #26).
|
2026-07-13 14:32:58 +00:00
|
|
|
|
- **Issue-shape classification (2026-07-13, issue #26):** `inspect` now fetches lightweight
|
|
|
|
|
|
remote-issue metadata (tea `--output json` with string-index/joined-labels normalization;
|
|
|
|
|
|
gh `--json`; fail-soft → nil) and emits an always-present `issue_shape` key
|
|
|
|
|
|
(`sequential-chain` / `flat-adhoc` / `mixed` / null). Classification is a pure
|
|
|
|
|
|
`Inspector.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.
|
2026-07-13 14:48:19 +00:00
|
|
|
|
- **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_HOME` override), upserted fail-soft by config-write (canonical
|
|
|
|
|
|
path via `git rev-parse --show-toplevel`), queried via new `projects [filter]` CLI
|
|
|
|
|
|
subcommand. Discoverer template + tea/gh/card-add mechanics in
|
|
|
|
|
|
`skills/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.
|
2026-07-13 15:02:44 +00:00
|
|
|
|
- **Wakeup design spike (2026-07-13, issue #28, ADR-0035/0036):** poll + tmux direction
|
|
|
|
|
|
chosen at the human gate. `Backlog::Wakeup` + `bin/wakeup-poll` thin pilot (dry-run
|
|
|
|
|
|
default, `--spawn` to create `cc-<project>-issue<N>` tmux sessions and persist
|
|
|
|
|
|
`~/.cc-os/wakeup-state.json`; opt-in `wakeup=true` in `.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 a
|
|
|
|
|
|
`config-write` wakeup key deferred until a first project opts in.
|
|
|
|
|
|
- **Outstanding:** #14 residual (onboard one more project — operational hitl); wakeup
|
|
|
|
|
|
rollout (first opt-in project + poller machine + cadence).
|