scar-cli 0.22.0__tar.gz → 0.24.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scar_cli-0.24.0/.release-please-manifest.json +3 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0005-history-rewrite-orphans-commit-evidence.landmine.md +5 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0006-yaml-pattern-anchor-over-escaping.landmine.md +2 -1
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0008-rich-output-nontty-must-bypass-rich.landmine.md +2 -2
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0011-lint-compile-check-lets-redos-anchors-hang-hotpath.landmine.md +2 -2
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0017-codex-pretool-context-can-replay-apply-patch.landmine.md +0 -1
- scar_cli-0.22.0/.scars/candidates/one-directional-health-check-leaves-flattering-direction-unwatched.md → scar_cli-0.24.0/.scars/0020-one-directional-health-check-leaves-flattering-direction-unwatched.landmine.md +6 -2
- scar_cli-0.22.0/.scars/candidates/posttool-fix-in-hooks-does-not-reach-codex-or-cascade.md → scar_cli-0.24.0/.scars/0021-posttool-fix-in-hooks-does-not-reach-codex-or-cascade.landmine.md +5 -3
- scar_cli-0.22.0/.scars/candidates/codex-hook-delivery-needs-user-file-and-trust.md → scar_cli-0.24.0/.scars/0022-codex-hook-delivery-needs-user-file-and-trust.landmine.md +4 -3
- scar_cli-0.24.0/.scars/candidates/host-detection-must-not-read-the-process-home.md +40 -0
- scar_cli-0.24.0/.scars/candidates/one-plugin-hook-manifest-two-hosts-two-root-variables.md +30 -0
- scar_cli-0.24.0/.scars/candidates/path-anchor-breadth-drives-the-review-due-threshold.md +37 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/AGENTS.md +5 -2
- {scar_cli-0.22.0 → scar_cli-0.24.0}/CHANGELOG.md +24 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/PKG-INFO +8 -12
- {scar_cli-0.22.0 → scar_cli-0.24.0}/README.md +7 -11
- {scar_cli-0.22.0 → scar_cli-0.24.0}/SCAR-FORMAT.md +1 -1
- {scar_cli-0.22.0 → scar_cli-0.24.0}/SPEC.md +6 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/plugin/plugin.json +1 -1
- {scar_cli-0.22.0 → scar_cli-0.24.0}/pyproject.toml +1 -1
- {scar_cli-0.22.0 → scar_cli-0.24.0}/release-please-config.json +1 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/cli.py +241 -63
- scar_cli-0.24.0/src/scar/firing_log.py +71 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/hooks.py +8 -10
- scar_cli-0.24.0/src/scar/hosts.py +221 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/installer.py +79 -10
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/lint.py +6 -2
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_cli.py +127 -1
- scar_cli-0.24.0/tests/test_firing_log.py +113 -0
- scar_cli-0.24.0/tests/test_hosts.py +404 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_installer.py +408 -22
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_lint.py +26 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_plugin.py +11 -23
- {scar_cli-0.22.0 → scar_cli-0.24.0}/uv.lock +1 -1
- {scar_cli-0.22.0 → scar_cli-0.24.0}/website/docs/agents.md +33 -6
- {scar_cli-0.22.0 → scar_cli-0.24.0}/website/static/llms.txt +1 -1
- scar_cli-0.22.0/.release-please-manifest.json +0 -3
- scar_cli-0.22.0/plugin/hooks/hooks.json +0 -43
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.claude-plugin/marketplace.json +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.github/workflows/ci.yml +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.github/workflows/docs.yml +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.github/workflows/pr-validation.yml +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.github/workflows/release.yml +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.gitignore +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.pre-commit-config.yaml +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.pre-commit-hooks.yaml +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0001-git-grep-ere-pitfalls.landmine.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0002-agent-direct-hook-install.deadend.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0003-installer-binds-to-active-venv-scar.landmine.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0004-promote-roundtrip-drops-expires-evidence.landmine.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0007-release-please-config-change-skips-open-pr.landmine.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0009-anchor-survival-harness-measures-symbol-not-path-anchors.deadend.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0010-git-returncode-128-vs-empty-tracked-set.landmine.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0012-firing-log-readers-need-blanket-guards.landmine.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0013-docusaurus-future-v4-requires-faster-dep.landmine.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0014-inject-flag-dest-collides-with-subcommand-dispatch.landmine.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0015-zero-checkruns-means-approval-gate-not-workflow-bug.deadend.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0016-hook-ownership-must-be-kind-scoped.landmine.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0018-cli-subparsers-register-through-_add-wrapper.landmine.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0019-token-in-scar-body-cannot-prove-hook-delivery.deadend.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/README.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/candidates/cascade-block-exit-collides-with-argparse.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/template.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/CONTRIBUTING.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/IDEA.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/LICENSE +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/ROADMAP.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/STRESS-TEST.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/action.yml +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/codecov.yml +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/anchor-survival/PROTOCOL.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/anchor-survival/RESULTS.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/anchor-survival/long_replay.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/anchor-survival/replay.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/anchor-survival/replay_shipped.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/anchor-survival/test_replay_shipped.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/auto-authorship/FINDINGS.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/auto-authorship/PROTOCOL.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/fence-honor/.gitignore +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/fence-honor/PROTOCOL.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/fence-honor/RESULTS.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/fence-honor/fixture/.scars/0001-vendor-retry-window.fence.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/fence-honor/fixture/.scars/0002-evicting-session-store.deadend.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/fence-honor/fixture/.scars/0003-export-column-order.landmine.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/fence-honor/fixture/README.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/fence-honor/fixture/payments/retry.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/fence-honor/fixture/reports/export.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/fence-honor/fixture/services/sessions.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/fence-honor/grade.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/harvest/PROTOCOL.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/experiments/harvest/harvest.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/hook/scar-hooks.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/plugin/hooks/run.sh +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/plugin/skills/scar-authoring/SKILL.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/plugin/skills/scar-authoring/assets/template.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/__init__.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/agent.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/cascade.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/codex.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/draftcheck.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/evidence.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/gc.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/harvest.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/match.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/mcp.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/model.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/orphan.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/output.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/reanchor.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/renames.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/render.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/review.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/skills/scar-authoring/SKILL.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/skills/scar-authoring/assets/template.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/store.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/src/scar/symbols.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/conftest.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_action_yml.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_anchor_kind.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_block_capability.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_cascade.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_codex.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_context_size.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_docs.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_draftcheck.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_evidence.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_gc.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_git_hook.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_harvest.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_hooks.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_json_contract.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_lifecycle.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_match.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_mcp.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_model.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_orphan.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_output.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_precommit_hooks.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_reanchor.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_renames.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_render.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_review.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_skill.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_store.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_symbols.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/tests/test_verdict_observability.py +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/website/.gitignore +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/website/docs/concepts.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/website/docs/index.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/website/docs/methodology.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/website/docs/quickstart.md +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/website/docusaurus.config.ts +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/website/package-lock.json +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/website/package.json +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/website/scripts/sync-changelog.mjs +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/website/sidebars.ts +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/website/src/css/custom.css +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/website/static/img/favicon.svg +0 -0
- {scar_cli-0.22.0 → scar_cli-0.24.0}/website/tsconfig.json +0 -0
{scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0005-history-rewrite-orphans-commit-evidence.landmine.md
RENAMED
|
@@ -8,8 +8,13 @@ created: 2026-06-11
|
|
|
8
8
|
authors: ["claude-code", "Kibukx"]
|
|
9
9
|
anchors:
|
|
10
10
|
- path: .scars/
|
|
11
|
+
- command: "git push.*--force"
|
|
12
|
+
- command: "git rebase"
|
|
13
|
+
- command: "git filter-repo|git filter-branch"
|
|
14
|
+
- command: "git commit.*--amend"
|
|
11
15
|
violation: "commit: [0-9a-f]{7,40}"
|
|
12
16
|
evidence:
|
|
17
|
+
- note: "2026-09-05 anchors: path .scars/ KEPT on purpose. The violation tripwire commit: [0-9a-f]{7,40} only evaluates on files an anchor matched, so dropping it to cut firings would silently disarm the scar. Command anchors added instead, so the history-rewrite half fires on the act rather than on any scar edit"
|
|
13
18
|
- note: v0.1.0 public release (2026-06-11): fresh-start force-push orphaned 3 commit SHAs cited by scars 0001 and 0002; SHAs still resolve on GitHub by URL but fail in any fresh clone, and GitHub may GC them eventually
|
|
14
19
|
expires:
|
|
15
20
|
condition: "evidence schema gains a resolvable form (full URL or archived diff) or lint warns on bare SHAs at promotion"
|
{scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0006-yaml-pattern-anchor-over-escaping.landmine.md
RENAMED
|
@@ -9,8 +9,9 @@ authors: ["claude-code", "kibukx"]
|
|
|
9
9
|
anchors:
|
|
10
10
|
- path: src/scar/orphan.py
|
|
11
11
|
- path: src/scar/match.py
|
|
12
|
-
-
|
|
12
|
+
- pattern: "\n\s*-\s*pattern:"
|
|
13
13
|
evidence:
|
|
14
|
+
- note: "2026-09-05 anchors: path .scars/ replaced by a pattern matching a scar frontmatter pattern: entry. The directory anchor fired on every scar edit, while the hazard only exists when a pattern anchor is being authored"
|
|
14
15
|
- pr: 40
|
|
15
16
|
- note: scar 1 grep pattern matched only its own body, never experiments/anchor-survival/RESULTS.md
|
|
16
17
|
expires:
|
{scar_cli-0.22.0 → scar_cli-0.24.0}/.scars/0008-rich-output-nontty-must-bypass-rich.landmine.md
RENAMED
|
@@ -7,10 +7,10 @@ confidence: 0.9
|
|
|
7
7
|
created: 2026-06-30
|
|
8
8
|
authors: ["claude-code", "kibukx"]
|
|
9
9
|
anchors:
|
|
10
|
-
- path: src/scar/cli.py
|
|
11
10
|
- path: src/scar/output.py
|
|
12
|
-
- pattern: "
|
|
11
|
+
- pattern: "def plain\(\):"
|
|
13
12
|
evidence:
|
|
13
|
+
- note: "2026-09-05 anchors: path src/scar/cli.py dropped, it is 3000+ lines and the tty gate is 17 of them. The 18 output.render( call sites only invoke the already-safe dispatcher, so that pattern is replaced by def plain():, which marks the 14 non-tty contract closures this scar actually protects"
|
|
14
14
|
- issue: 78
|
|
15
15
|
- note: 187-test suite asserts plain substrings like '0001-bad.deadend.md' and long anchor paths on main([...]) under capsys
|
|
16
16
|
expires:
|
|
@@ -7,11 +7,11 @@ confidence: 0.9
|
|
|
7
7
|
created: 2026-06-30
|
|
8
8
|
authors: ["claude-code", "Kibukx"]
|
|
9
9
|
anchors:
|
|
10
|
-
- path: src/scar/lint.py
|
|
11
|
-
- path: src/scar/match.py
|
|
12
10
|
- pattern: "rx\.search\("
|
|
13
11
|
- pattern: "MAX_ANCHOR_SCAN"
|
|
12
|
+
- pattern: "_is_redos_prone"
|
|
14
13
|
evidence:
|
|
14
|
+
- note: "2026-09-05 anchors: both whole-file path anchors dropped, lint.py and match.py serve many concerns beyond ReDoS. _is_redos_prone added so the GATE itself stays anchored, since the body says the gate is the defense and the 64 KiB cap is not"
|
|
15
15
|
- issue: 88
|
|
16
16
|
expires:
|
|
17
17
|
condition: "lint gains full regex-safety analysis OR the matcher runs on a hardened regex engine with a hard timeout"
|
|
@@ -8,7 +8,6 @@ created: 2026-08-28
|
|
|
8
8
|
authors: ["codex", "Kibukx"]
|
|
9
9
|
anchors:
|
|
10
10
|
- path: src/scar/codex.py
|
|
11
|
-
- path: plugin/hooks/hooks.json
|
|
12
11
|
evidence:
|
|
13
12
|
- issue: 243
|
|
14
13
|
- note: live codex-cli 0.147.0 A/B emitted two tool_use_ids for one identical apply_patch after the first PreToolUse context injection
|
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
---
|
|
2
|
-
id:
|
|
2
|
+
id: 20
|
|
3
3
|
type: landmine
|
|
4
4
|
title: A health check that watches one direction of pipeline failure leaves the flattering direction unwatched
|
|
5
5
|
severity: high
|
|
6
6
|
confidence: 0.9
|
|
7
7
|
created: 2026-08-30
|
|
8
8
|
authors: ["claude-code"]
|
|
9
|
+
promoted_by: Kibukx
|
|
10
|
+
promoted_by_source: git-config
|
|
9
11
|
anchors:
|
|
10
12
|
- path: src/scar/cli.py
|
|
11
13
|
- path: src/scar/hooks.py
|
|
14
|
+
- path: src/scar/codex.py
|
|
15
|
+
- path: src/scar/cascade.py
|
|
12
16
|
- pattern: "instrument_disconnected|posttool_silent|verdict_observed"
|
|
13
17
|
evidence:
|
|
14
18
|
- issue: 277
|
|
15
19
|
- issue: 237
|
|
16
20
|
expires:
|
|
17
21
|
condition: "the pipeline stops having two independently-installable halves"
|
|
18
|
-
status:
|
|
22
|
+
status: active
|
|
19
23
|
---
|
|
20
24
|
|
|
21
25
|
The precheck and posttool hooks install separately and fail separately. #237
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
---
|
|
2
|
-
id:
|
|
2
|
+
id: 21
|
|
3
3
|
type: landmine
|
|
4
4
|
title: A posttool change in hooks.py does not reach codex.py or cascade.py, which carry their own copy of the same logic
|
|
5
5
|
severity: high
|
|
6
6
|
confidence: 0.8
|
|
7
7
|
created: 2026-09-02
|
|
8
8
|
authors: ["claude-code"]
|
|
9
|
+
promoted_by: Kibukx
|
|
10
|
+
promoted_by_source: git-config
|
|
9
11
|
anchors:
|
|
10
12
|
- path: src/scar/hooks.py
|
|
11
13
|
- path: src/scar/codex.py
|
|
12
14
|
- path: src/scar/cascade.py
|
|
13
|
-
violation: "if not violations:"
|
|
14
15
|
evidence:
|
|
15
16
|
- issue: 277
|
|
16
17
|
- issue: 293
|
|
@@ -18,7 +19,8 @@ evidence:
|
|
|
18
19
|
expires:
|
|
19
20
|
condition: "the three posttool paths share one implementation, or the adapters delegate to hooks.posttool"
|
|
20
21
|
review_after: 2026-12-01
|
|
21
|
-
|
|
22
|
+
violation: "if not violations:"
|
|
23
|
+
status: active
|
|
22
24
|
---
|
|
23
25
|
|
|
24
26
|
The posttool verdict logic exists three times: `hooks.posttool` for Claude
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
---
|
|
2
|
-
id:
|
|
2
|
+
id: 22
|
|
3
3
|
type: landmine
|
|
4
4
|
title: Codex plugin hooks are not materialized, and untrusted Codex hooks are skipped silently
|
|
5
5
|
severity: high
|
|
6
6
|
confidence: 0.9
|
|
7
7
|
created: 2026-08-28
|
|
8
8
|
authors: ["claude-code"]
|
|
9
|
+
promoted_by: Kibukx
|
|
10
|
+
promoted_by_source: git-config
|
|
9
11
|
anchors:
|
|
10
|
-
- path: plugin/hooks/hooks.json
|
|
11
12
|
- path: src/scar/codex.py
|
|
12
13
|
- pattern: "hooks/hooks\.json|CODEX_HOME|codex-(pretool|posttool|session-notice)"
|
|
13
14
|
evidence:
|
|
@@ -17,7 +18,7 @@ evidence:
|
|
|
17
18
|
expires:
|
|
18
19
|
condition: "Codex materializes a plugin's hooks/hooks.json into the installed cache AND surfaces an error for untrusted hooks"
|
|
19
20
|
review_after: 2027-02-28
|
|
20
|
-
status:
|
|
21
|
+
status: active
|
|
21
22
|
---
|
|
22
23
|
|
|
23
24
|
Shipping a Codex hook through a plugin's `hooks/hooks.json` does not deliver it,
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 0
|
|
3
|
+
type: deadend
|
|
4
|
+
title: Host detection must take home from installer.CLAUDE_DIR, never Path.home() — a bare call passes locally and fails every other machine
|
|
5
|
+
severity: high
|
|
6
|
+
confidence: 0.9
|
|
7
|
+
created: 2026-09-07
|
|
8
|
+
authors: ["claude-code"]
|
|
9
|
+
anchors:
|
|
10
|
+
- pattern: "detect_hosts\("
|
|
11
|
+
- symbol: src/scar/cli.py::_detect
|
|
12
|
+
evidence:
|
|
13
|
+
- issue: 318
|
|
14
|
+
- note: "2026-09-07, during the multi-host skill install work: the skill-install refusal resolved home with Path.home(). Under HOME=empty the suite went 1031 passed / 2 FAILED, both PRE-EXISTING tests, printing 'claude not detected on this machine, nothing written'. Fixed by reusing _detect(). Branch SHAs deliberately omitted: scar #5 fired on the amend that wrote this, and squash-merge would orphan them."
|
|
15
|
+
expires:
|
|
16
|
+
condition: "detect_hosts takes home from one injected seam no caller can bypass"
|
|
17
|
+
review_after: 2027-03-08
|
|
18
|
+
status: candidate
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
`Path.home()` in a detection path looks obviously right and is a trap. Tests
|
|
22
|
+
patch `installer.CLAUDE_DIR`, not the environment, and `_detect()` derives
|
|
23
|
+
home from `installer.CLAUDE_DIR.parent`. A bare call reads the author's real
|
|
24
|
+
home, finds their real `~/.claude`, and passes. On any machine without one,
|
|
25
|
+
every CI runner included, detection returns nothing and the caller refuses.
|
|
26
|
+
|
|
27
|
+
The failure is invisible where it is introduced: the suite was fully green on
|
|
28
|
+
the authoring machine, and the tests that finally failed were pre-existing
|
|
29
|
+
ones nobody had touched. Use `_detect(kind)`, or `installer.CLAUDE_DIR.parent`
|
|
30
|
+
exactly as `_detect` does. Never add a second answer to where home is.
|
|
31
|
+
|
|
32
|
+
Two anchors on purpose. `cli.py` is 143 KiB and its first `detect_hosts(` sits
|
|
33
|
+
at byte ~123,000, past the 64 KiB `MAX_ANCHOR_SCAN` bound, so the pattern is
|
|
34
|
+
blind to the very file the defect landed in. The `symbol:` anchor covers it,
|
|
35
|
+
at the cost of needing `scar-cli[symbols]`. Lint reports neither gap: the
|
|
36
|
+
pattern matches `hosts.py`, so the scar reads live while blind where it counts.
|
|
37
|
+
|
|
38
|
+
Not armed. The obvious tripwire is `Path\.home\(\)`, but `cli.py` carries that
|
|
39
|
+
string in a warning comment and `installer.py` uses it correctly for module
|
|
40
|
+
constants, so it would fire on prose and on correct code.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 0
|
|
3
|
+
type: landmine
|
|
4
|
+
title: A plugin hook manifest is read by every host that installs the plugin, and hosts expand different root variables
|
|
5
|
+
severity: high
|
|
6
|
+
confidence: 0.9
|
|
7
|
+
created: 2026-09-03
|
|
8
|
+
authors: ["claude-code"]
|
|
9
|
+
anchors:
|
|
10
|
+
- path: plugin/
|
|
11
|
+
- path: src/scar/installer.py
|
|
12
|
+
- pattern: "PLUGIN_ROOT"
|
|
13
|
+
evidence:
|
|
14
|
+
- issue: 303
|
|
15
|
+
- issue: 244
|
|
16
|
+
expires:
|
|
17
|
+
condition: "the plugin format gains per-host scoping for hook files"
|
|
18
|
+
review_after: 2026-12-01
|
|
19
|
+
status: candidate
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
Claude Code merges plugin.json hooks with hooks/hooks.json and defines only
|
|
23
|
+
CLAUDE_PLUGIN_ROOT. Codex reads the same file and defines both PLUGIN_ROOT
|
|
24
|
+
and CLAUDE_PLUGIN_ROOT. A hooks/hooks.json written for Codex with
|
|
25
|
+
${PLUGIN_ROOT} therefore ran on every Claude session start and Bash call as
|
|
26
|
+
"/hooks/run.sh": No such file or directory, on every machine with the plugin
|
|
27
|
+
(#244 introduced it, #303 removed it). There is no way to mark a plugin
|
|
28
|
+
hook file as one host's only. Ship one manifest per plugin, on
|
|
29
|
+
${CLAUDE_PLUGIN_ROOT}, and deliver host-specific hooks through
|
|
30
|
+
`scar hook install --runtime <host>`, whose files live outside the plugin.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 0
|
|
3
|
+
type: landmine
|
|
4
|
+
title: A whole-file or whole-directory path anchor makes the review-due threshold report anchor breadth, not code hazard
|
|
5
|
+
severity: medium
|
|
6
|
+
confidence: 0.8
|
|
7
|
+
created: 2026-09-04
|
|
8
|
+
authors: ["claude-code"]
|
|
9
|
+
anchors:
|
|
10
|
+
- path: SCAR-FORMAT.md
|
|
11
|
+
- pattern: "review_after_firings"
|
|
12
|
+
evidence:
|
|
13
|
+
- issue: 312
|
|
14
|
+
- note: "triage of all five over-threshold scars in this repo on 2026-09-04: four were over-anchored, one was a real code fix"
|
|
15
|
+
expires:
|
|
16
|
+
condition: "lint reports what share of a scar's firings touched the hazard, so the review-due warning can distinguish breadth from recurrence"
|
|
17
|
+
review_after: 2027-03-04
|
|
18
|
+
status: candidate
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
`scar lint` warns past `review_after_firings` that either the guarded code
|
|
22
|
+
merits the fix or the scar merits revision. Read literally that sends you to
|
|
23
|
+
the code first. It is usually the anchor.
|
|
24
|
+
|
|
25
|
+
A `path:` anchor is a repo-relative PREFIX, so it fires on every edit beneath
|
|
26
|
+
it. Scar #8 guards a 17-line tty branch inside a 52-line module but anchored
|
|
27
|
+
the whole 3,090-line `src/scar/cli.py`; roughly nine of every ten of its 47
|
|
28
|
+
firings touched nothing related. Scar #5 guards against history rewrites and
|
|
29
|
+
anchored all of `.scars/`, so it fired on 22 routine promotions and zero
|
|
30
|
+
force-pushes, which is zero of its actual trigger events.
|
|
31
|
+
|
|
32
|
+
A firing count therefore measures anchor breadth first and hazard recurrence
|
|
33
|
+
second, and the two are not separable from the log. Before reading a
|
|
34
|
+
review-due warning as evidence that code needs fixing, check what share of the
|
|
35
|
+
firings touched the hazard at all. Then narrow the anchor to the smallest file
|
|
36
|
+
holding the branching, or switch to a `command:` anchor when the trigger is an
|
|
37
|
+
action rather than a file (#312 is the one case here that really was the code).
|
|
@@ -26,8 +26,11 @@ The full authoring contract — qualification criteria, the candidates-only writ
|
|
|
26
26
|
path, mandatory YAML frontmatter, and the regex over-escaping trap — is packaged
|
|
27
27
|
as the `scar-authoring` skill.
|
|
28
28
|
|
|
29
|
-
- **Claude Code
|
|
30
|
-
|
|
29
|
+
- **Claude Code, Codex, Cursor, opencode, Windsurf:** `scar skill install`
|
|
30
|
+
detects which of those hosts are on the machine and writes the skill to each
|
|
31
|
+
one's native skills directory. On Claude Code the plugin is the recommended
|
|
32
|
+
route and carries the same skill. The per-host destination table is in
|
|
33
|
+
[website/docs/agents.md](website/docs/agents.md).
|
|
31
34
|
- **MCP agents (Cursor/Windsurf/opencode):** the `scar_draft` tool enforces the
|
|
32
35
|
candidates-only path and lints before writing; its description carries the
|
|
33
36
|
digest.
|
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.24.0](https://github.com/Daily-Nerd/Scar/compare/v0.23.0...v0.24.0) (2026-09-08)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **firing-log:** one shared validated reader for the firing log ([#313](https://github.com/Daily-Nerd/Scar/issues/313)) ([d316922](https://github.com/Daily-Nerd/Scar/commit/d31692205715e63380b8ac104643de4ceac0338d))
|
|
9
|
+
* **skill:** install the authoring skill to every detected host ([#320](https://github.com/Daily-Nerd/Scar/issues/320)) ([1d9c985](https://github.com/Daily-Nerd/Scar/commit/1d9c985e3e5815ba67d222defa86d549886c7e94))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* **promote:** record whether a promotion happened at a terminal ([#315](https://github.com/Daily-Nerd/Scar/issues/315)) ([f28e8eb](https://github.com/Daily-Nerd/Scar/commit/f28e8eb90a5fb3161aa40565dbfb218d1b9b4160)), closes [#308](https://github.com/Daily-Nerd/Scar/issues/308)
|
|
15
|
+
|
|
16
|
+
## [0.23.0](https://github.com/Daily-Nerd/Scar/compare/v0.22.0...v0.23.0) (2026-09-03)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### ⚠ BREAKING CHANGES
|
|
20
|
+
|
|
21
|
+
* **install:** with no --runtime, no terminal, and more than one detected host, scar hook install and scar skill install write nothing and print the commands to run instead of installing Claude Code by default.
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
|
|
25
|
+
* **install:** detect installed hosts and the channel that already serves each ([#304](https://github.com/Daily-Nerd/Scar/issues/304)) ([180cf6f](https://github.com/Daily-Nerd/Scar/commit/180cf6f53ab671e6fb9ce6636fe718aabead1c7c))
|
|
26
|
+
|
|
3
27
|
## [0.22.0](https://github.com/Daily-Nerd/Scar/compare/v0.21.0...v0.22.0) (2026-09-03)
|
|
4
28
|
|
|
5
29
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: scar-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.24.0
|
|
4
4
|
Summary: SCAR — version control for negative knowledge (deadends, fences, landmines)
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -75,20 +75,16 @@ cp .scars/template.md .scars/candidates/redis-sessions.md
|
|
|
75
75
|
$EDITOR .scars/candidates/redis-sessions.md
|
|
76
76
|
scar lint # validate format
|
|
77
77
|
scar promote redis-sessions.md # human review gate: candidate -> active
|
|
78
|
-
scar hook install #
|
|
79
|
-
scar skill install #
|
|
80
|
-
scar hook
|
|
78
|
+
scar hook install # detects installed hosts, asks which to wire (--all, --runtime X)
|
|
79
|
+
scar skill install # same detection for the scar-authoring skill
|
|
80
|
+
scar hook status # every host with the channel that serves it (settings, plugin, none)
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
Claude Code
|
|
84
|
-
scar-authoring skill together; the two commands above are the manual fallback.
|
|
85
|
-
Re-run `scar skill install` after upgrading — the installed skill is a static copy.
|
|
83
|
+
`scar skill install` writes the scar-authoring skill to a native path for Claude Code, Codex, Cursor, opencode, or Windsurf. Claude Code is the one confirmed to load it, and the rest are written per vendor documentation but unverified: see the [per-host table](https://daily-nerd.github.io/Scar/agents#where-scar-skill-install-writes) for which is which.
|
|
86
84
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
scars before `Bash` and `apply_patch` calls and report post-patch `violation:`
|
|
90
|
-
tripwires without blocking or rewriting the action. Plugin updates that change
|
|
91
|
-
the hook definitions require trust review again.
|
|
85
|
+
Claude Code users: the marketplace **plugin** ships the hooks and the scar-authoring skill together. `scar hook install` and `scar skill install` see the plugin and skip Claude unless you pass `--runtime claude --force`. Re-run `scar skill install` after upgrading a manual install; the installed skill is a static copy.
|
|
86
|
+
|
|
87
|
+
Codex users: run `scar hook install --runtime codex`, then open `/hooks` in Codex to review and trust the entries. The hooks push matching scars before `Bash` and `apply_patch` calls and report post-patch `violation:` tripwires without blocking. The plugin no longer carries Codex hook definitions; the installer is the one path.
|
|
92
88
|
|
|
93
89
|
Full walkthrough, lifecycle commands, and agent wiring (Claude Code plugin,
|
|
94
90
|
Codex native hooks, Windsurf/Cascade hooks, MCP server, `scar draft-check`):
|
|
@@ -60,20 +60,16 @@ cp .scars/template.md .scars/candidates/redis-sessions.md
|
|
|
60
60
|
$EDITOR .scars/candidates/redis-sessions.md
|
|
61
61
|
scar lint # validate format
|
|
62
62
|
scar promote redis-sessions.md # human review gate: candidate -> active
|
|
63
|
-
scar hook install #
|
|
64
|
-
scar skill install #
|
|
65
|
-
scar hook
|
|
63
|
+
scar hook install # detects installed hosts, asks which to wire (--all, --runtime X)
|
|
64
|
+
scar skill install # same detection for the scar-authoring skill
|
|
65
|
+
scar hook status # every host with the channel that serves it (settings, plugin, none)
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
Claude Code
|
|
69
|
-
scar-authoring skill together; the two commands above are the manual fallback.
|
|
70
|
-
Re-run `scar skill install` after upgrading — the installed skill is a static copy.
|
|
68
|
+
`scar skill install` writes the scar-authoring skill to a native path for Claude Code, Codex, Cursor, opencode, or Windsurf. Claude Code is the one confirmed to load it, and the rest are written per vendor documentation but unverified: see the [per-host table](https://daily-nerd.github.io/Scar/agents#where-scar-skill-install-writes) for which is which.
|
|
71
69
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
scars before `Bash` and `apply_patch` calls and report post-patch `violation:`
|
|
75
|
-
tripwires without blocking or rewriting the action. Plugin updates that change
|
|
76
|
-
the hook definitions require trust review again.
|
|
70
|
+
Claude Code users: the marketplace **plugin** ships the hooks and the scar-authoring skill together. `scar hook install` and `scar skill install` see the plugin and skip Claude unless you pass `--runtime claude --force`. Re-run `scar skill install` after upgrading a manual install; the installed skill is a static copy.
|
|
71
|
+
|
|
72
|
+
Codex users: run `scar hook install --runtime codex`, then open `/hooks` in Codex to review and trust the entries. The hooks push matching scars before `Bash` and `apply_patch` calls and report post-patch `violation:` tripwires without blocking. The plugin no longer carries Codex hook definitions; the installer is the one path.
|
|
77
73
|
|
|
78
74
|
Full walkthrough, lifecycle commands, and agent wiring (Claude Code plugin,
|
|
79
75
|
Codex native hooks, Windsurf/Cascade hooks, MCP server, `scar draft-check`):
|
|
@@ -43,7 +43,7 @@ is deliberate: consumers in hook hot-paths parse with zero dependencies.
|
|
|
43
43
|
| `created` | yes | ISO date | |
|
|
44
44
|
| `authors` | yes | inline list | who drafted it: agents as `"claude-code"` etc. The reviewer is no longer appended here |
|
|
45
45
|
| `promoted_by` | active scars | string | the human who promoted it. Written only by `scar promote`, which overwrites anything a candidate carried. Empty on scars promoted before the field existed, and never inferred from `authors` |
|
|
46
|
-
| `promoted_by_source` | optional | `explicit` \| `git-config` |
|
|
46
|
+
| `promoted_by_source` | optional | `explicit` \| `git-config-interactive` \| `git-config` | how strongly `promoted_by` is evidenced. `explicit` = a name was typed with `--reviewer`. `git-config-interactive` = no name typed, but `promote` ran at a terminal, so a person was there. `git-config` = no name typed and no terminal recorded, which is the unattended shape `lint` warns on. Written only alongside `promoted_by`, never on its own. Absent on scars promoted before the field existed, and plain `git-config` on scars promoted before interactivity was recorded, so neither absence proves an agent did it |
|
|
47
47
|
| `anchors` | yes, ≥1 | list of `- path:`, `- pattern:`, `- symbol:`, and/or `- command:` | §4 |
|
|
48
48
|
| `evidence` | recommended | list of `- commit:`/`- pr:`/`- issue:`/`- incident:`/`- note:`/`- url:` | absent ⇒ challengeable on sight; `issue:`/`url:` are durable forms that survive squash-merge |
|
|
49
49
|
| `expires.condition` | recommended | quoted string | what change obsoletes this scar |
|
|
@@ -464,3 +464,9 @@ just as well as edit rows do.
|
|
|
464
464
|
command output, and asserts the nullable semantics of §9.2. A guarantee no
|
|
465
465
|
test enforces is an untestable assertion, and untestable assertions are the
|
|
466
466
|
ones that reach `main` wrong.
|
|
467
|
+
|
|
468
|
+
### 9.10 Install detection
|
|
469
|
+
|
|
470
|
+
`scar hook install` and `scar skill install` without `--runtime` detect hosts (claude, codex, windsurf, cursor, opencode) by config directory or binary on PATH, and resolve for each the channel that already serves it: `settings` (Scar's own entries in the host's hook file), `plugin` (the scar marketplace plugin installed and not disabled), or `none`. windsurf is repo-scoped: its hooks file is written into the working repo, so the binary on PATH counts only when that repo is inside a git repository. On a terminal, one question per present, wirable, unserved host, default no. Without a terminal, exactly one such host is installed; zero or several means the commands are printed and nothing is written. Zero detected hosts says so, rather than naming the plugin. `--all` wires every such host. `--runtime claude` on a Claude Code already served by the plugin refuses unless `--force`. `--all` and `--force` apply to `install` only, and `--force` applies to `--runtime claude` only. A missing or unreadable plugin registry never counts as `plugin`.
|
|
471
|
+
|
|
472
|
+
Two rules differ for the skill kind. windsurf is not repo-scoped there: its global skills live under home (`~/.codeium/windsurf/skills`), so the binary on PATH counts on its own, with no git-repo guard. And `scar skill install --runtime <host>` refuses, exit 1, when detection does not find that host on the machine, rather than creating a skill directory nothing reads. Every destination resolves through the same home the detection pass used, and the Codex destination honours `$CODEX_HOME`, so a reported success always names a directory the detected host actually reads.
|