diff --git a/.gitignore b/.gitignore index 2db615c..277b31a 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ graphify-out/ # Python bytecode __pycache__/ +.pytest_cache/ # autoresearch skill run logs (eval iterations) /autoresearch/ diff --git a/plugins/cc-architect/scripts/plugin_config/operations/base.rb b/plugins/cc-architect/scripts/plugin_config/operations/base.rb index a7a5dd5..f6eee36 100644 --- a/plugins/cc-architect/scripts/plugin_config/operations/base.rb +++ b/plugins/cc-architect/scripts/plugin_config/operations/base.rb @@ -20,7 +20,23 @@ module PluginConfig private def plugin_key - "#{plugin}@#{marketplace}" + "#{plugin}@#{resolved_marketplace}" + end + + # The marketplace id this plugin is actually installed under, per + # installed_plugins.json, falling back to the --marketplace param when + # no installed entry exists yet (e.g. before first install). Needed + # because cc-os's os-* plugins install under a `local-plugins` + # marketplace (symlink into ~/.claude/plugins) rather than whatever + # marketplace id the caller assumes (e.g. the repo's own `cc-os`), + # which otherwise produces false "not installed" results. + def resolved_marketplace + data = read_json(installed_plugins_path) + if data && data['plugins'] + match = data['plugins'].keys.find { |k| k.start_with?("#{plugin}@") } + return match.split('@', 2).last if match + end + marketplace end def read_json(path) diff --git a/plugins/os-backlog/CLAUDE.md b/plugins/os-backlog/CLAUDE.md index d542cc8..22cf945 100644 --- a/plugins/os-backlog/CLAUDE.md +++ b/plugins/os-backlog/CLAUDE.md @@ -12,3 +12,20 @@ see NOTE below. NOTE (2026-07-16): a major rework retiring Planka in favor of git-issues-only (ADR-0042, OpenSpec change retire-planka-git-issues-only) is in flight on main; this index intentionally avoids enumerating internals that rework replaces. + +## ADR-0025 exemption + +`bin/wakeup-poll` is a second `bin/` entry point alongside the `bin/os-backlog` +dispatcher — a deviation from [ADR-0025](../../docs/adr/0025-standard-ruby-structure-for-cc-os-plugins-lib-single-dispatcher-bin-fail-soft-installed-gem-only-dependencies.md)'s +single-dispatcher rule. This is **grandfathered**, following the same +exemption mechanism os-adr recorded for its own ADR-0025 deviation (see +`plugins/os-adr/CLAUDE.md`): the split is backed by +[ADR-0034](../../docs/adr/0034-cross-project-filing-file-dont-fix-with-a-derived-global-project-index.md) +(global project index), +[ADR-0035](../../docs/adr/0035-issue-triggered-project-ai-wakeup-via-polling-not-webhooks.md) +(issue-triggered wakeup via polling), and +[ADR-0036](../../docs/adr/0036-tmux-session-convention-for-ai-run-sessions-cc-project-purpose.md) +(tmux session convention) — "Pilot only" per the script's header comment, +not an oversight. Don't +fold `wakeup-poll` into the dispatcher as a drive-by; revisit if/when those +ADRs graduate past pilot. diff --git a/plugins/os-backlog/lib/backlog/config.rb b/plugins/os-backlog/lib/backlog/config.rb index a2fc4a9..a95a0c7 100644 --- a/plugins/os-backlog/lib/backlog/config.rb +++ b/plugins/os-backlog/lib/backlog/config.rb @@ -25,11 +25,6 @@ module Backlog end end - # @return [String, nil] the explicit board name override, if configured - def board - @data["board"] - end - # @return [String, nil] the tracker key (e.g. "forgejo:owner/repo"), if configured def tracker @data["tracker"] @@ -42,7 +37,6 @@ module Backlog @data["board_id"] end - def configured? = !board.nil? def tracker_configured? = !tracker.nil? # @return [Hash] a copy of the parsed config data diff --git a/plugins/os-backlog/tests/config_test.rb b/plugins/os-backlog/tests/config_test.rb index 2b84056..459f6cd 100644 --- a/plugins/os-backlog/tests/config_test.rb +++ b/plugins/os-backlog/tests/config_test.rb @@ -1,37 +1,21 @@ require_relative "test_helper" class ConfigTest < Minitest::Test - def test_nil_contents_is_unconfigured + def test_nil_contents_has_no_tracker config = Backlog::Config.new(nil) - refute config.configured? - assert_nil config.board + refute config.tracker_configured? + assert_nil config.tracker end - def test_blank_contents_is_unconfigured - config = Backlog::Config.new(" \n") - refute config.configured? - end - - def test_reads_board_key - config = Backlog::Config.new("board=llf-schema\n") - assert config.configured? - assert_equal "llf-schema", config.board - end - - def test_reads_legacy_yaml_style_board_key - config = Backlog::Config.new("---\nboard: llf-schema\n") - assert config.configured? - assert_equal "llf-schema", config.board + def test_reads_legacy_yaml_style_key + config = Backlog::Config.new("---\ntracker: forgejo:jared/cc-os\n") + assert config.tracker_configured? + assert_equal "forgejo:jared/cc-os", config.tracker end def test_lines_without_separator_are_ignored config = Backlog::Config.new("# comment\njunk line\n") - refute config.configured? - end - - def test_contents_without_board_key_is_unconfigured - config = Backlog::Config.new("other=value\n") - refute config.configured? + assert_empty config.to_h end def test_reads_tracker_key @@ -41,7 +25,7 @@ class ConfigTest < Minitest::Test end def test_tracker_unconfigured_when_absent - config = Backlog::Config.new("board=llf-schema\n") + config = Backlog::Config.new("other=value\n") refute config.tracker_configured? end @@ -52,11 +36,11 @@ class ConfigTest < Minitest::Test def test_merge_preserves_other_keys existing = "board=llf-schema\nother=kept\n" - updated_contents = Backlog::Config.merge(existing, "tracker", "planka:llf-schema") + updated_contents = Backlog::Config.merge(existing, "tracker", "forgejo:jared/cc-os") updated = Backlog::Config.new(updated_contents) - assert_equal "llf-schema", updated.board - assert_equal "planka:llf-schema", updated.tracker + assert_equal "llf-schema", updated.to_h["board"] + assert_equal "forgejo:jared/cc-os", updated.tracker assert_equal "kept", updated.to_h["other"] end @@ -82,7 +66,7 @@ class ConfigTest < Minitest::Test def test_merge_normalizes_existing_spaced_lines_on_rewrite existing = "version = 1\nhub = my-hub\n" - updated_contents = Backlog::Config.merge(existing, "tracker", "planka:board") + updated_contents = Backlog::Config.merge(existing, "tracker", "forgejo:jared/demo") updated_contents.each_line do |line| next if line.strip.empty? @@ -91,26 +75,26 @@ class ConfigTest < Minitest::Test updated = Backlog::Config.new(updated_contents) assert_equal "1", updated.to_h["version"] assert_equal "my-hub", updated.to_h["hub"] - assert_equal "planka:board", updated.tracker + assert_equal "forgejo:jared/demo", updated.tracker end def test_board_id_reader - config = Backlog::Config.new("tracker=planka:board\nboard_id=42\n") + config = Backlog::Config.new("tracker=forgejo:jared/demo\nboard_id=42\n") assert_equal "42", config.board_id assert_nil Backlog::Config.new(nil).board_id end def test_set_preserves_comments_and_blank_lines - existing = "# managed by cc-os\ntracker=planka:board\n\n# stamped by os-status\nversion=3\n" + existing = "# managed by cc-os\ntracker=forgejo:jared/demo\n\n# stamped by os-status\nversion=3\n" updated = Backlog::Config.set(existing, "board_id", "42") - assert_equal "# managed by cc-os\ntracker=planka:board\n\n# stamped by os-status\nversion=3\nboard_id=42\n", + assert_equal "# managed by cc-os\ntracker=forgejo:jared/demo\n\n# stamped by os-status\nversion=3\nboard_id=42\n", updated end def test_set_replaces_existing_key_in_place - existing = "# top comment\nboard_id=old\ntracker=planka:board\n" + existing = "# top comment\nboard_id=old\ntracker=forgejo:jared/demo\n" updated = Backlog::Config.set(existing, "board_id", "new") - assert_equal "# top comment\nboard_id=new\ntracker=planka:board\n", updated + assert_equal "# top comment\nboard_id=new\ntracker=forgejo:jared/demo\n", updated end def test_set_normalizes_spaced_key_value_lines_only diff --git a/plugins/os-context/skills/audit-sessions/references/rubric.md b/plugins/os-context/skills/audit-sessions/references/rubric.md index 6780ce6..6ad556a 100644 --- a/plugins/os-context/skills/audit-sessions/references/rubric.md +++ b/plugins/os-context/skills/audit-sessions/references/rubric.md @@ -32,11 +32,13 @@ severity, and category. especially after a design/decision settles. 8. **tracker-routing** — mid-session follow-up work (a concrete task, bug, or deferred item not done this session) left as a TODO comment or chat mention instead of captured - to the tracked board; durable spec text routed to a Planka card description (or task - state routed to git issues) against the Planka-state/git-issues-spec boundary - (ADR-0033, `.cc-os/config` tracker key); or a Planka card visibly accreting spec-like - decisions in comments with no promotion flag raised to the user — silent promotion - counts too. Convention compliance only, not whether the routing choice was wise. + as an issue on the repo's configured tracker (`.cc-os/config` tracker key, + `os-backlog:capture`); an AI-authored issue carrying state labels or the human-curated + `next` label it shouldn't (ADR-0042 — git issues are the single tracker, `next` is + human-only, the AI never adds or removes it short of an explicit direct request); or an + issue visibly accreting scope/decisions in comments with no promotion flag raised to the + user — silent promotion counts too. Convention compliance only, not whether the routing + choice was wise. ## Per-session report format (return exactly this) diff --git a/plugins/os-vault/eval/README.md b/plugins/os-vault/eval/README.md index b23216d..a47812c 100644 --- a/plugins/os-vault/eval/README.md +++ b/plugins/os-vault/eval/README.md @@ -1,6 +1,8 @@ # os-vault write-behavior eval — unprompted vault-write discrimination (held-out) -_Last updated: 2026-07-06 — harness built (WS2); baseline grid NOT yet run._ +_Last updated: 2026-07-07 — harness built (WS2), baseline grid run, and the +wording loop complete and shipped; run-set and reserve are now contaminated for +future wording tuning (see `eval/results/`)._ Measures whether the model **unprompted** (a) writes evergreen cross-project knowledge to the SecondBrain vault when it surfaces during normal work, and (b) writes it with diff --git a/plugins/os-vault/hooks/config.py b/plugins/os-vault/hooks/config.py index 11e96ec..1b9f5ee 100644 --- a/plugins/os-vault/hooks/config.py +++ b/plugins/os-vault/hooks/config.py @@ -21,7 +21,7 @@ except Exception: # pragma: no cover - yaml is provided via graphify CONFIG_PATH = os.path.expanduser("~/.claude/plugins/os-vault/config.yaml") DEFAULT_VAULT_PATH = "~/Documents/SecondBrain" -DEFAULT_GRAPHIFY_OUTPUT_DIR = "~/Documents/SecondBrain/.graphify" +DEFAULT_GRAPHIFY_OUTPUT_DIR = "~/Documents/SecondBrain/graphify-out" DEFAULT_MODEL = "qwen25-coder-7b-16k" DEFAULT_STALE_DAYS = 7 DEFAULT_MEMSEARCH_DIR = "~/.memsearch"