Two-issue release. Both reports by @oaabahussain.
Highlights
Hash attestation for plan injection (closes #150)
After v2.36.1 wrapped task_plan.md content in BEGIN/END delimiters, the model still parsed the bytes. v2.37.0 adds an opt-in second layer.
- New slash command
/plan-attestand helperscripts/attest-plan.sh(and.ps1). - Computes a SHA-256 of
task_plan.mdand stores it at.planning/<active-plan>/.attestation(parallel-plan mode) or./.plan-attestation(legacy mode). UserPromptSubmitandPreToolUsehooks recompute the hash on every fire and emit[planning-with-files] [PLAN TAMPERED — injection blocked]instead of plan content on mismatch.- When attestation is set, the injected context carries a
Plan-SHA256:line so the model can log the attested hash. - Opt-in: absence of an attestation file keeps the v2.36.x behavior.
Parity-locked version bumper (closes #151)
The "missed one variant" regression hit four consecutive releases (v2.34.1, v2.36.0, v2.36.2, v2.36.3).
- New
scripts/bump-version.pyatomically bumps the parity set in one shot: 14 SKILL.md variants +plugin.json+marketplace.json+CITATION.cff. - New
tests/test_skill_md_version_parity.pyfails the build the moment any parity-locked file diverges from the canonical version. .continue,.gemini,.pi,.kirostay on their own schemes; the bumper lists them at the end of every run so the omission stays visible.
Other changes
tests/test_canonical_script_sync.py: removed leftover duplicate test class; SHARED_SCRIPTS extended to ten entries.scripts/sync-ide-folders.py: SCRIPTS manifest coversattest-plan.{sh,ps1}.- Canonical SKILL.md Security Boundary section documents the two layers of defense.
- New
tests/test_plan_attestation.py: six tests covering legacy and parallel-plan attest,--show,--clear, tamper detection, missing-plan handling.
Thanks
- @oaabahussain for two well-scoped P1 reports that both turned a class of risk into something that fails the build instead of shipping silently.
Verification
python -m pytest tests/ -q
# 78 passed, 2 pre-existing Windows exec-bit failures (unrelated)