- Backlog::BoardResolver with injected config read/write; Cards does no filesystem I/O
- board_id honored only for planka: trackers; id hit validated against returned board
name; 404/mismatch/cache failure degrades to name lookup and rewrites the cache
- comment-preserving Config.set mirrors os-status's writer (Config.merge not used)
- FakePlankaClient boards.get 404 support; 14 new tests; suite 90 runs / 0 failures
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CLeMz48rvG3s9XpAsDxeho
Rename plugins/os-orchestration -> plugins/os-context. SessionStart hook is
now a composer: globs prompts/session-start/*.md in filename order, emits one
additionalContext block, byte-identical for the existing orchestration rules
(tested), line budgets enforced (warn 120 / refuse 240). ORCHESTRATION.md ->
prompts/session-start/10-orchestration.md. New prompt files from the
2026-07-09 audit: 20-kickoff-conventions, 30-standing-safety,
40-decision-memos (total injection 102/120 lines). os-status audit-skill and
state-path references updated (old ~/.local/state path symlinked;
OS_ORCH_AUDIT_LEDGER name kept for compatibility).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CLeMz48rvG3s9XpAsDxeho
Adds card-move over planka-api Cards#move; ownership rules enforced in
lib (never Next, never hitl, never out of Done, Done only for
afk-ready). afk-ready cards now skip Review per user decision; semi
still stops at Review. Skills updated to "working a card means moving
it". Suite 68 runs/153 assertions.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QBAYNm4AmczQaEHfXwai5a
User-invoked QOL commands plugin; domain boundary vs hook-injection
plugins recorded in ADR-028. First resident /os-shortcuts:wrap encodes
the session-close ritual (commit per repo conventions, doc sweep,
handoff) from the 2026-07-09 workflow audit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QBAYNm4AmczQaEHfXwai5a
Config parsed/wrote YAML while os-status owns the file as key=value
lines, so config-write output was invisible to the tracker-configured
check. Now reads key=value (legacy 'key: value' lines still accepted)
and merge emits key=value.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EUyiRB4vHaRkhYKUdoMW2P
os-status (#21): fix skill orchestrates remediation of failing checks via a
new hooks/checks.py --json runner; remediation pointers on every Check; new
project-graph-present and config-version-current checks; version= stamping
in .cc-os/config; banner names /os-status:fix as the single entry point.
Suite 64 tests (was 36).
os-backlog (#14): route skill (inspect + config-write subcommands,
lib/backlog/tracker.rb + inspector.rb); destination choice and live-history
migration are named human gates; Config.merge preserves other keys. Suite
54 runs / 110 assertions (was 35). Rollout (onboard cc-os, then one more
project) still pending, so #14 stays open.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EUyiRB4vHaRkhYKUdoMW2P
Cards#snapshot again emits all 19 Types::Card fields (camelCase) plus
labels — 8df0cb7 had narrowed it to 8 keys, dropping listChangedAt and
silently breaking board-audit's stale-Doing check. A regression test
now pins the complete key set (35 runs green). implementation-status
records the 0.2.0 typed-returns migration and the live end-to-end
verification against the real Planka board (run on ovh-vps 2026-07-10).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BS59Nkb7fvJMFB9dZiwZ7H
0.2.0 returns Planka::Types value objects instead of parsed-JSON
hashes. Replace all hash access with typed accessors, rebuild
Cards#snapshot output as explicit string-keyed hashes (JSON output
stays byte-compatible, so skill/agent contracts are unchanged), and
rewrite test fakes on real Planka::Types records. 34 runs green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014GjXD4ZDsucFZXNgVVrnZB
Two agent definitions. card-triage batch-labels raw Backlog cards with
one priority (P0-P3) and one autonomy (hitl/semi/afk-ready) label —
label changes only, ambiguity defaults to hitl. board-audit reports the
four drift classes (stale Doing, WIP over cap, Waiting unblocked, aging
Review) and writes at most one comment per drifting card. Both
definitions state the column-ownership constraints: never move cards
past Review, never pull Next, never touch Done.
Supporting read/write primitives: Cards#attach_label + Cards#comment,
exposed as card-label / card-comment subcommands alongside the existing
read-only snapshot JSON. Fake-client unit tests, no live API.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XknQRvihHDpYE47RTmUR4N
/os-backlog:capture resolves repo -> board via the pure resolver, runs
board-ensure transparently when the board is missing, and creates the
card at Backlog only. /os-backlog:list is strictly pull-based — board
state is never injected unasked. Both skills state the column-ownership
rules (create at Backlog only, move Doing -> Review at most, never pull
Next, never move Review -> Done, never self-assign hitl cards) and fail
soft when the gem/Planka is unavailable.
New Backlog::Cards lib class + card-add / cards / snapshot subcommands;
fake-client unit tests, no live API. Manual live verification is still
pending: the planka-api gem is not installed in this environment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XknQRvihHDpYE47RTmUR4N
Pure repo -> board decision function (Backlog::Resolver) plus the
`resolve` os-backlog subcommand: given repo path, .cc-os/config contents,
and a board-name inventory (all passed in — no filesystem or network
access in the resolver itself), returns exactly one of "use <board>" /
"activate <archived board>" / "stop-and-discuss". An explicit config
board takes precedence; otherwise the board name is derived from the
repo/client dir basename with project inferred from ~/dev vs ~/clients.
Unmapped paths, and configured-but-unmatched boards, both resolve to
stop-and-discuss rather than silently falling back. Pure Ruby unit tests,
no network.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XknQRvihHDpYE47RTmUR4N
Idempotent board-ensure over the installed planka-api gem: uniform lists
(Backlog/Next/Doing/Waiting/Review/Done), uniform label set (P0-P3, hitl,
semi, afk-ready) with per-label color-candidate fallback since Planka's
color whitelist isn't documented, the archived--<name> rename convention
(activate/archive primitives; ensure never archives automatically), and
the bot-created-project visibility fix (shared-type project + explicit
project-manager add + null ownerProjectManagerId). Unit tests stub the
client layer entirely — no live API calls.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XknQRvihHDpYE47RTmUR4N
Reads the `tracker` key from .cc-os/config, validating the
planka:<board> | forgejo:<owner>/<repo> | github:<owner>/<repo> |
repo:<path> grammar. Present+valid is silent, malformed is a one-line
warn (never a crash), and absent-in-a-git-project is a daily-snoozed
nudge pointing at the os-backlog routing skill.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XknQRvihHDpYE47RTmUR4N
Deterministic layer: audit/bin/audit-stats (Ruby) composes the existing
extract fact-sheets across all production transcripts since the last
run, writes per-run stats/flags/sheets to
~/.local/state/os-orchestration/audit/, and appends the metrics.tsv
trend ledger (seeded with the 2026-07-10 run: 23 sessions).
Judgment layer: new /os-orchestration:audit-sessions skill — sonnet
auditor fan-out over precomputed flagged regions only, tiered
synthesis with run-over-run trend verdicts, stops before any wording
edit. Nudge: os-status check orchestration-audit-due warns when the
ledger is >=14 days stale (missing ledger = machine not opted in).
Planka recurrence entry deferred: gem offsets are +1y/+6m/+3m/+1m by
design; +2w blocked on parked gem versioning decisions.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XknQRvihHDpYE47RTmUR4N
Sync was push-only via SessionEnd (vault_sync.py/memsearch_sync.py); a second
machine's copies could go stale. session_start.py now runs a fast-forward-only,
10s-timeout git pull for both repos before the staleness check — silent on
success, quiet one-line stderr note on failure, never blocking session start.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mb3V8NNzAuns7vgX9A2jU
The reserve twin E3P-retry-storm targets gen-logs' other planted incident
(2026-07-02 auth-token-expiry 401 storm) and was authored before axis B
existed; the single concept table would have failed a compliant model.
Fixed pre-reserve-measurement without reading reserve files (incident chain
comes from gen-logs). Run-set scoring byte-identical; self-test 34/34 incl.
keying proof both directions.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New global plugin with one SessionStart hook running all checks in-process
(hooks/checks.py, check(ctx) -> CheckResult, single registry). Three states:
ok (silent), note (near-zero-token line, never suppressed), warn (one
aggregated banner, once-per-day snooze + permanent suppress in gitignored
per-project .cc-os/). Initial checks: subagent-model-env-override (catches
the WS1 Cluster 1 incident deterministically), adr-system-present (verbatim
port of os-adr's hook, legacy .os-adr/suppress honored), vault-hub-note-present.
os-adr's own SessionStart hook moved here atomically (its hooks.json now
empty; session_start.py stays as wording source of record). Built via
OpenSpec change add-os-status-plugin; 36 model-free tests; smoke-tested
2026-07-06 incl. env-override canary.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Grid (36 reps + 2 canaries, all counted): negatives 18/18 both tiers, zero
over-triggering; positives 1/18 on delegate-at-all, but transcript
verification splits those FAILs into superior direct strategies (scripted
bulk edit, surgical greps - the audit's own justified-non-delegation shape)
vs genuine misses (haiku whole-file ingestion, per-file grind). Conditional
rules validated where engaged: 14/14 spawns explicit-model, self-report
downgrade flag worked. E2P/E3P criterion redesign pre-registered with
independently-anchored thresholds; reserve untouched. Analysis in vault:
os-orchestration-eval-baseline-grid-results.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Harness: 6 run-set + 6 frozen-reserve paired scenarios from the WS1 verified
misses, Node relaystation fixture (deterministic sandbox-time logs), headless
runner with CLAUDE_CODE_SUBAGENT_MODEL stub for E1P, deterministic-first
checker driving audit/bin/extract (extended with per-segment read targets),
narrow frozen haiku-judge fallback for E1 language axes, model-free self-test
21/21 incl. shipped-instruction-compliant conformance transcripts.
Wording v2: the E1 canary (counted) proved resolvedModel is not model-visible
in the launch result, so the launch-stub-comparison rule was unactionable;
replaced with subagent model self-report on sonnet/opus spawns (subagents know
their exact model ID - verified live). Scenarios/checker/rubric untouched.
Deterministic env-override detection routed to WS3 (plan updated).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Applies the Eval B when->then lesson to the three verified WS1 clusters:
explicit model: before every Agent call (cluster 2, cost exposure now that
CLAUDE_CODE_SUBAGENT_MODEL is removed), verify resolved model after launch
(cluster 1 policy gap), don't re-cover own ground before delegating
(cluster 3). Delegation thresholds unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add session-audit findings (10 stratified sessions, verified synthesis)
and E1-E4 eval-scenario backlog: docs/orchestration-audit/
- Add Phase 1 fact-sheet extractor: plugins/os-orchestration/audit/bin/extract
- Post-audit correction: Cluster 1 (all 23 spawns downgraded to haiku) was
NOT a Fable-5 harness bug — root cause was CLAUDE_CODE_SUBAGENT_MODEL=haiku
in ~/.claude/settings.json env block, set by an earlier session as a cost
measure. Removed 2026-07-06. Policy gap (no verify-resolvedModel rule)
stands regardless; E1 remains valid.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
First full run of the Eval C discrimination harness (3-level ambiguity ladder,
6-scenario run-set, 3 reps/cell, both sonnet+haiku): 36 headless reps, 12/12
cells PASS at ≥2/3 majority. Haiku 18/18 reps, sonnet 17/18 (P1-L1 rep 1: final
message citing only 0005, not governing 0002 — a boundary artifact, not a
behavioral miss). Zero over-trigger ADR creation on any negative at any level;
all positive passes via governing-ADR citation (16 reps) or judge fallback (1).
Two harness defects fixed before running the grid: (1) bin/run pipefail bug that
aborted remaining reps after first FAIL (changed checker invocation to || true);
(2) positive axis-b previously required ADR creation only, contradicting the
README's design statement that "consulting and/or recording is correct" — run-set
positives sit in already-decided territory, so find→cite→comply is the correct
behavior. Implemented three-branch axis-b check: created (new ADR file),
cited-governing (final message cites the governing Accepted ADR), or judge
fallback. Added two self-test guards to verify the compliance path.
Scenario metadata updated to document the corrected axis-b checker behavior
(cited-governing as a valid pass branch). TSV reasons column now records the
pass path via `B-via:` field for positives.
Verdict: Eval B wording generalizes to a new fixture, new language, new domain,
and decreasing cue explicitness. Grid ceiling not found; next signal is
production (rollout + IRL session audits). Run-set baseline locked; wording
tuning moves measurement to reserve-set.
Eval B wording reached 8/8 (sonnet) / 7/8 (haiku) on its run-set
after five iterations; subsequent W3 stability testing confirmed
intermittent flicker but acceptable performance. As Eval B is now
contaminated by iteration, we need a held-out measurement set to
assess generalization to new projects and cues.
Eval C measures whether learned behavior generalizes across
decreasing cue explicitness (explicit → moderate → conceptual
framing) and, critically, whether the model correctly avoids
false positives (over-triggering) when no Accepted ADR is in play.
Six paired scenarios (positive/negative at each level) run against
a job-execution domain fixture; a frozen reserve-set (notifications
domain) becomes the measurement set if anyone tunes wording against
the run-set.
New: `plugins/os-adr/eval-c/` — bin/ (run/check/self-test/sandbox
scripts), fixture/ (taskq async job queue, 6 ADRs, trigger-phrased
CLAUDE.md), scenarios/ (6 run-set), scenarios-reserve/ (6 reserve-
set), README.md (measurement discipline + design), judge-rubric.md.
Model-free self-test passing. First real grid run is a pending
decision.
Five-iteration /autoresearch wording experiment against the Eval B baseline
(haiku 0/8, sonnet 5/8). Checker/fixtures/scenarios/rubric frozen; wording
surfaces: hook PRESENT_NOTE, find/create SKILL.mds, fixture CLAUDE.md
(declared a surface upfront — it is the real-project adoption template).
- Hook note + skill descriptions: when->then trigger-conditioned phrasing
(H1 confirmed, both tiers)
- find skill: explicit-unconditional reversal->supersede offer where find's
output is on screen (fixed sonnet W3)
- Mechanical lower-tier trigger: before first edit to any existing file,
run find on those paths; additions count (fixed haiku R1/R4)
- New eval-b/fixture/project/CLAUDE.md carrying the same rules
Final grid: sonnet 8/8, haiku 7/8 (W3 axis-b judge flicker). Open: channel
ablation (hook vs CLAUDE.md) not run; R4-nograph now passes both tiers.
Hypothesis->result map: vault note os-adr-eval-b-wording-experiment-hypotheses.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Remove explicit name: frontmatter from os-adr and os-doc-hygiene SKILL.mds
so slash commands register namespaced (/os-adr:find, not bare /find)
- Add bin/refresh-plugins to refresh stale local plugin caches
- CLAUDE.md: cache-refresh procedure, naming-convention pointer, mandate
reading the vault autoresearch-eval howto before the next eval
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Eval A grid ran clean across all scenarios/tiers. Eval B grid (1 rep/cell)
shows a real gap: haiku never unprompted-consults the ADR system in any
scenario, while sonnet passes 5/8 (misses W3 write-trigger and R1 direct-
conflict retrieval). Updates CLAUDE.md component status and the eval-b
README so the next session picks up from here instead of re-running blind.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Rename skills to bare verbs (hygiene-check -> check, hygiene-clean -> clean),
matching the os-vault/os-orchestration pattern. Remove the commands/hygiene.md
dispatcher in favor of two new skills, status and sweep, so all four actions
are invoked directly as /os-doc-hygiene:<skill> instead of through a custom
subcommand parser that no other plugin in the marketplace uses.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Moves the doc-hygiene plugin from the standalone cc-plugins repo into
cc-os as plugins/os-doc-hygiene/, following the same pattern as
os-vault and os-orchestration. Also commits the previously-unstaged
ADR-019 (global os-orchestration plugin supersedes per-project
orchestration text), which documents the prior migration but never
made it into a commit.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Renamed orchestration -> os-orchestration per naming convention, kept the
plugin's permissive delegation rule as the canonical global default, and
dropped cc-os's stricter local override so this repo behaves like every
other project (ADR-019).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The plugin directory, symlink, and settings.json were already renamed to
os-vault, but the local-plugins marketplace manifest still declared the old
memory/./memory entry, so skills/slash-commands silently stopped registering
while hooks (wired by absolute path) kept working. Re-registered the plugin
under its new name via the marketplace manifest + claude plugin install/
uninstall, and documented the fix and standing rename procedure (ADR-018,
CLAUDE.md) so this doesn't recur.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Closes #1–#6 (Forgejo jared/cc-os).
- Reconcile vault-conventions.md to a single authoritative frontmatter schema (#1)
- Add memory-template plugin skill: template-design + new-type-creation (#2)
- Add howto/convention/reference note templates, each dogfooded (#3–#5)
- Patch 4 proof-of-concept notes to the settled schema (#6)
Note: vault note files (templates, patched notes, vault-conventions.md) live in the separate ~/Documents/SecondBrain repo and are committed by its own SessionEnd hook; this commit covers only the cc-os-tracked files (skill + docs).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Assessment now reasons about ignorable content by category (fetched
deps, build output, caches, tooling/AI-assistant dirs, lockfiles, bulk
data, binaries) so it generalizes across stacks. Onboarding switches to
the config.yaml model qwen25-coder-7b-16k: inference is GPU-bound at
~65 tok/s, so the speed lever is fewer chunks per doc via a larger
context window (GRAPHIFY_OLLAMA_NUM_CTX does not propagate through the
OpenAI-compatible path; context must come from the modelfile). Extends
ADR-017.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Onboarding ran a bare `graphify extract`, but graphify does not honor
.gitignore — it needs its own .graphifyignore. Without one, onboarding
viking-warrior-training-log walked node_modules/ (5,858 files) and
routed its non-code files through the Ollama doc pass; the run was
killed after ~1 hour with no graph.json.
Onboarding is now assessment-first: survey the repo, generate a
per-project .graphifyignore (the ignore set varies by stack), confirm
with the user, then extract. Records the gotcha and decision in ADR-017.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Step 5b (Obsidian vault -> VPS git sync) is now fully done: the vault is a
private Forgejo repo (SecondBrain) and vault_sync.py auto-commits+pushes it on
SessionEnd, mirroring memsearch_sync.py. Step 2e pilot done (llf-schema project
graph onboarded). Step 2d closed (live vault graph is the baseline). Docs and
implementation status updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Delete the four ported bash hooks from plugins/memory/hooks (now live only in git history; runtime uses the Python ports)
- Update tests/README to reflect removal; test harness drives Python hooks via python-wrappers adapters (preserved)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Move memory plugin source from ~/.claude/plugins/memory (untracked) into cc-os/plugins/memory under git
- Port four bash hooks to Python deep-module architecture (config.py, hook_io.py, session_state.py + thin entry points)
- Split memsearch auto-commit+push into dedicated memsearch_sync.py SessionEnd hook (relocation of ADR-015, behavior preserved)
- Cutover via symlink + settings.json rewrite; fresh-session test verified all hooks fire
- Add ADR-016; update CLAUDE.md, build plan, and fix stale bash-hook/source-path references
- Sync three new-capability delta specs into openspec/specs; archive change as 2026-06-12-memory-plugin-source-and-port
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>