simt-dev 0.6.2__tar.gz → 0.6.3__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.
Files changed (301) hide show
  1. {simt_dev-0.6.2 → simt_dev-0.6.3}/.gitignore +11 -0
  2. {simt_dev-0.6.2 → simt_dev-0.6.3}/CHANGELOG.md +48 -1
  3. {simt_dev-0.6.2 → simt_dev-0.6.3}/PKG-INFO +45 -16
  4. {simt_dev-0.6.2 → simt_dev-0.6.3}/README.md +44 -15
  5. {simt_dev-0.6.2 → simt_dev-0.6.3}/bin/simt.mjs +19 -6
  6. simt_dev-0.6.3/docs/decisions/ADR-100-a-staged-diff-is-the-last-gate-before-history-and-it-runs-inside-the-tool.md +94 -0
  7. simt_dev-0.6.3/docs/decisions/ADR-101-a-file-lease-belongs-to-one-session-and-the-pre-edit-hook-refuses-another.md +95 -0
  8. simt_dev-0.6.3/docs/decisions/ADR-102-the-two-queued-review-rows-are-closed-by-ruling.md +49 -0
  9. simt_dev-0.6.3/docs/decisions/ADR-103-co-projected-duplicates-merge-down.md +74 -0
  10. simt_dev-0.6.3/docs/decisions/ADR-104-the-pre-tool-use-policy-reads-the-command-the-way-a-shell-reads-it.md +76 -0
  11. simt_dev-0.6.3/docs/decisions/ADR-105-the-json-ceiling-shrinks-arrays-and-never-cuts-bytes.md +44 -0
  12. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/README.md +44 -0
  13. {simt_dev-0.6.2 → simt_dev-0.6.3}/package.json +1 -1
  14. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/mdc/preview-postflight.mdc +5 -6
  15. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/android.md +7 -8
  16. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/cloudflare-workers.md +1 -1
  17. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/container.md +2 -0
  18. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/jvm.md +1 -1
  19. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/react-native.md +3 -5
  20. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/react-web.md +9 -9
  21. simt_dev-0.6.3/src/agenthooks/decide.mjs +214 -0
  22. simt_dev-0.6.3/src/agenthooks/policy.mjs +162 -0
  23. simt_dev-0.6.3/src/agenthooks/shell.mjs +523 -0
  24. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/argv.mjs +54 -9
  25. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/agenthook.mjs +25 -3
  26. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/ci.mjs +28 -3
  27. simt_dev-0.6.3/src/commands/completions.mjs +27 -0
  28. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/decide.mjs +14 -1
  29. simt_dev-0.6.3/src/commands/doctor.mjs +367 -0
  30. simt_dev-0.6.3/src/commands/explain.mjs +52 -0
  31. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/help.mjs +66 -17
  32. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/hooks.mjs +208 -60
  33. simt_dev-0.6.3/src/commands/ignore.mjs +152 -0
  34. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/index.mjs +54 -100
  35. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/init.mjs +82 -12
  36. simt_dev-0.6.3/src/commands/lease.mjs +136 -0
  37. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/lessons.mjs +12 -0
  38. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/mcp.mjs +2 -2
  39. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/pack.mjs +9 -0
  40. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/plan.mjs +13 -1
  41. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/plugin.mjs +16 -1
  42. simt_dev-0.6.3/src/commands/prbody.mjs +45 -0
  43. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/repoindex.mjs +3 -0
  44. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/rules.mjs +145 -105
  45. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/shared.mjs +36 -5
  46. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/skills.mjs +293 -205
  47. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/skillsinstall.mjs +100 -30
  48. simt_dev-0.6.3/src/commands/slice.mjs +353 -0
  49. simt_dev-0.6.3/src/commands/status.mjs +62 -0
  50. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/sync.mjs +110 -15
  51. simt_dev-0.6.3/src/commands/undo.mjs +106 -0
  52. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/upgrade.mjs +70 -8
  53. simt_dev-0.6.3/src/completions.mjs +191 -0
  54. simt_dev-0.6.3/src/diff.mjs +254 -0
  55. simt_dev-0.6.3/src/explain.mjs +258 -0
  56. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/federation/config.mjs +44 -0
  57. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/graph/load.mjs +14 -5
  58. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/hooks/dispatcher.mjs +110 -0
  59. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/hooks/gates.mjs +14 -3
  60. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/hooks/resolve.mjs +14 -0
  61. simt_dev-0.6.3/src/ignore.mjs +133 -0
  62. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/index/persist.mjs +66 -9
  63. simt_dev-0.6.3/src/journal.mjs +326 -0
  64. simt_dev-0.6.3/src/lease.mjs +113 -0
  65. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/mcp/server.mjs +15 -1
  66. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/mcp/tools.mjs +296 -256
  67. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/memory/decide.mjs +6 -1
  68. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/memory/lessons.mjs +12 -0
  69. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/output/index.mjs +82 -12
  70. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/package-version.mjs +49 -1
  71. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/packs/manage.mjs +13 -4
  72. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/plan/index.mjs +6 -0
  73. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/plugins.mjs +27 -6
  74. simt_dev-0.6.3/src/prbody.mjs +251 -0
  75. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/projection/manifest.mjs +13 -2
  76. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/projection/shared.mjs +4 -1
  77. simt_dev-0.6.3/src/secrets.mjs +231 -0
  78. simt_dev-0.6.3/src/status.mjs +152 -0
  79. simt_dev-0.6.2/src/agenthooks/decide.mjs +0 -123
  80. simt_dev-0.6.2/src/agenthooks/policy.mjs +0 -86
  81. {simt_dev-0.6.2 → simt_dev-0.6.3}/LICENSE +0 -0
  82. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-001-push-requires-approval.md +0 -0
  83. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-002-refactor-blast-radius.md +0 -0
  84. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-003-test-breadth.md +0 -0
  85. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-004-hook-owns-format.md +0 -0
  86. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-005-file-length.md +0 -0
  87. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-006-coverage-bar.md +0 -0
  88. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-007-section-skeleton.md +0 -0
  89. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-008-verdict-vocabulary.md +0 -0
  90. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-009-skill-layout.md +0 -0
  91. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-010-runner-invocation.md +0 -0
  92. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-011-windows-support.md +0 -0
  93. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-012-drop-windows-support.md +0 -0
  94. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-013-genericity-by-facts-and-local-profiles.md +0 -0
  95. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-014-workspace-is-configuration.md +0 -0
  96. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-015-a-source-is-content-not-a-location.md +0 -0
  97. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-016-a-divergent-rule-is-retired-not-merged.md +0 -0
  98. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-017-a-declared-gate-must-be-runnable.md +0 -0
  99. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-018-an-unset-hooks-path-is-not-an-absent-hook.md +0 -0
  100. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-019-a-declared-command-is-the-runner.md +0 -0
  101. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-020-a-rule-is-written-per-surface-and-pointed-not-copied.md +0 -0
  102. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-021-one-surface-per-repo.md +0 -0
  103. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-022-a-key-simt-dev-reads-is-prefixed.md +0 -0
  104. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-023-the-gate-ships-as-a-file-the-repo-owns.md +0 -0
  105. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-024-simt-dev-overwrites-its-own-gate-file.md +0 -0
  106. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-025-a-baseline-is-a-region-in-a-file-the-repo-owns.md +0 -0
  107. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-026-a-config-without-a-region-is-a-file-the-repo-owns.md +0 -0
  108. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-027-the-one-gitattributes-line-that-is-neither-dangerous-nor-empty.md +0 -0
  109. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-028-a-base-file-is-a-floor-so-the-disagreement-it-cannot-repair-becomes-a-check.md +0 -0
  110. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-029-the-pins-a-repository-declares-are-its-own.md +0 -0
  111. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-030-what-a-plan-does-not-ship-is-a-decision-with-a-record.md +0 -0
  112. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-031-the-suite-stages-the-environment-it-needs.md +0 -0
  113. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-032-provenance-is-a-content-digest-not-a-commit.md +0 -0
  114. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-033-three-plan-rows-closed-by-decision-not-by-authoring.md +0 -0
  115. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-034-a-staged-tool-refuses-a-partially-staged-file.md +0 -0
  116. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-035-one-write-decision-and-one-json-document.md +0 -0
  117. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-036-a-writer-that-writes-says-so-and-the-instructions-naming-it-move-with-it.md +0 -0
  118. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-037-unchanged-means-writing-would-not-change-a-byte.md +0 -0
  119. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-038-the-gate-filter-belongs-to-every-manifest-writer.md +0 -0
  120. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-039-a-ci-step-runs-a-form-that-can-fail.md +0 -0
  121. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-040-the-last-writer-that-wrote-by-default-was-not-the-one-named.md +0 -0
  122. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-041-the-suite-installs-the-package-in-order-to-test-it.md +0 -0
  123. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-042-a-declared-glob-must-match-a-path-built-from-it.md +0 -0
  124. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-043-a-keyword-is-a-phrase-and-two-letters-is-a-word.md +0 -0
  125. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-044-compatibility-is-not-evidence.md +0 -0
  126. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-045-a-dashboard-that-counts-a-defect.md +0 -0
  127. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-046-one-rule-one-copy.md +0 -0
  128. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-047-a-profile-selects-on-what-a-repository-runs-on.md +0 -0
  129. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-048-a-baseline-carries-only-keys-a-reader-honours.md +0 -0
  130. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-049-a-ruling-that-a-later-record-moved-says-so-where-it-is-printed.md +0 -0
  131. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-050-a-byte-count-is-not-a-region-and-updated-is-not-a-change-of-rules.md +0 -0
  132. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-051-a-pointer-is-the-readers-only-route-so-it-is-not-a-convenience.md +0 -0
  133. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-052-a-dependency-is-counted-against-the-budget-and-there-is-one-budget.md +0 -0
  134. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-053-the-node-floor-is-22-20-0.md +0 -0
  135. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-054-the-digest-covers-every-byte-that-leaves-the-package.md +0 -0
  136. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-055-a-status-line-travels-so-it-may-not-name-a-location.md +0 -0
  137. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-056-three-names-one-of-which-is-cheap-to-move.md +0 -0
  138. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-057-an-identity-is-per-developer-and-a-repository-does-not-own-it.md +0 -0
  139. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-058-one-tool-three-channels-and-the-order-is-forced.md +0 -0
  140. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-059-the-version-a-repository-runs-is-the-one-it-pinned.md +0 -0
  141. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-060-a-repository-with-nothing-to-run-is-adopted-and-says-so.md +0 -0
  142. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-061-the-skill-registry-is-workspace-data.md +0 -0
  143. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-062-a-fresh-adoption-seeds-the-gates-it-can-run.md +0 -0
  144. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-063-the-adoption-escape-hatch-is-opt-in.md +0 -0
  145. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-064-the-context-meter-counts-what-the-tool-wrote.md +0 -0
  146. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-065-a-pack-is-one-shared-rule-set-pinned-by-digest.md +0 -0
  147. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-066-a-monorepo-projects-once-per-package.md +0 -0
  148. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-067-which-harnesses-read-agents-md-is-a-column.md +0 -0
  149. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-068-the-mcp-revision-list-cites-what-was-read.md +0 -0
  150. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-069-the-conformance-lint-checks-the-published-specification.md +0 -0
  151. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-070-the-json-payload-carries-its-own-version.md +0 -0
  152. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-071-a-rule-that-can-be-narrowed-is-written-narrow.md +0 -0
  153. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-072-the-budget-is-a-declaration-beside-the-gates.md +0 -0
  154. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-073-a-kernel-is-a-smaller-projection-the-repository-asks-for.md +0 -0
  155. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-074-a-rule-and-a-decision-are-readable-by-uri.md +0 -0
  156. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-075-nothing-leaves-the-machine.md +0 -0
  157. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-076-a-change-to-what-agents-read-is-measured.md +0 -0
  158. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-077-the-command-card-leads-the-region-and-reads-committed-evidence.md +0 -0
  159. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-078-a-line-the-repository-already-proves-does-not-ship.md +0 -0
  160. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-079-the-rules-are-enforced-at-the-tool-call-from-one-policy-table.md +0 -0
  161. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-080-the-tools-own-names-are-not-repositories-and-neither-reader-decides-by-shape.md +0 -0
  162. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-081-a-tracker-is-read-through-the-repositorys-template.md +0 -0
  163. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-082-the-tracker-override-is-a-manifest-key.md +0 -0
  164. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-083-a-budget-is-met-by-cutting-the-kernel-and-hard-is-the-floor.md +0 -0
  165. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-084-a-workspace-carries-its-repeated-rules-once.md +0 -0
  166. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-085-the-region-ends-with-the-names-it-kept-out.md +0 -0
  167. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-086-the-stable-prefix-comes-first-and-the-lock-records-both-digests.md +0 -0
  168. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-087-a-run-is-evidence-for-one-tree.md +0 -0
  169. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-088-a-marked-line-is-enforced-by-a-checker.md +0 -0
  170. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-089-the-local-index-is-a-cache-of-git-blobs.md +0 -0
  171. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-090-an-optional-adapter-is-off-until-named.md +0 -0
  172. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-091-the-map-ranks-files-a-task-mentions.md +0 -0
  173. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-092-tests-are-imports-conventions-and-coverage.md +0 -0
  174. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-093-why-names-what-governs-a-file.md +0 -0
  175. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-094-a-change-runs-the-tests-that-import-it.md +0 -0
  176. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-095-gate-output-keeps-the-failures.md +0 -0
  177. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-096-impact-names-who-a-change-reaches.md +0 -0
  178. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-097-the-channels-publish-by-hand-and-the-version-rides-in-as-an-input.md +0 -0
  179. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-098-the-fourth-channel-is-one-file-and-it-needs-no-toolchain.md +0 -0
  180. {simt_dev-0.6.2 → simt_dev-0.6.3}/docs/decisions/ADR-099-the-release-verifies-served-bytes-and-the-formula-mirrors-them.md +0 -0
  181. {simt_dev-0.6.2 → simt_dev-0.6.3}/pyproject.toml +0 -0
  182. {simt_dev-0.6.2 → simt_dev-0.6.3}/python/simt_dev/__init__.py +0 -0
  183. {simt_dev-0.6.2 → simt_dev-0.6.3}/python/simt_dev/cli.py +0 -0
  184. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/core.md +0 -0
  185. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/mdc/intake-questions.mdc +0 -0
  186. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/mdc/slice-commit.mdc +0 -0
  187. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/mdc/test-gate.mdc +0 -0
  188. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/connectiq.md +0 -0
  189. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/dart.md +0 -0
  190. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/deno.md +0 -0
  191. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/dotnet.md +0 -0
  192. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/elixir.md +0 -0
  193. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/go.md +0 -0
  194. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/node.md +0 -0
  195. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/python.md +0 -0
  196. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/ruby.md +0 -0
  197. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/rust.md +0 -0
  198. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/swift.md +0 -0
  199. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/typescript.md +0 -0
  200. {simt_dev-0.6.2 → simt_dev-0.6.3}/rules/stacks/uv.md +0 -0
  201. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/advice/advice.mjs +0 -0
  202. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/agenthooks/prompt.mjs +0 -0
  203. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/agenthooks/render.mjs +0 -0
  204. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/bench/ablate.mjs +0 -0
  205. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/bench/adapters.json +0 -0
  206. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/bench/grade.mjs +0 -0
  207. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/bench/mine.mjs +0 -0
  208. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/bench/probes.mjs +0 -0
  209. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/bench/report.mjs +0 -0
  210. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/bench/run.mjs +0 -0
  211. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/bench/tasks.mjs +0 -0
  212. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/bench/variants.mjs +0 -0
  213. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/brief/assemble.mjs +0 -0
  214. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/brief/kind.mjs +0 -0
  215. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/brief/packet.mjs +0 -0
  216. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/ci/dependabot.mjs +0 -0
  217. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/ci/workflow.mjs +0 -0
  218. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/bench.mjs +0 -0
  219. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/brief.mjs +0 -0
  220. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/compare.mjs +0 -0
  221. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/distill.mjs +0 -0
  222. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/evidence.mjs +0 -0
  223. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/gate.mjs +0 -0
  224. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/graph.mjs +0 -0
  225. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/harness.mjs +0 -0
  226. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/impact.mjs +0 -0
  227. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/local.mjs +0 -0
  228. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/map.mjs +0 -0
  229. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/review.mjs +0 -0
  230. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/skillscompile.mjs +0 -0
  231. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/tests.mjs +0 -0
  232. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/tokens.mjs +0 -0
  233. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/commands/why.mjs +0 -0
  234. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/compare/discover.mjs +0 -0
  235. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/compare/hooksstate.mjs +0 -0
  236. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/compare/learn.mjs +0 -0
  237. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/compare/row.mjs +0 -0
  238. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/decisions/index.mjs +0 -0
  239. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/distill/distill.mjs +0 -0
  240. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/distill/engine.mjs +0 -0
  241. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/distribute/release.mjs +0 -0
  242. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/federation/client.mjs +0 -0
  243. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/federation/query.mjs +0 -0
  244. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/graph/compile.mjs +0 -0
  245. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/graph/spec.mjs +0 -0
  246. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/graph/speccheck.mjs +0 -0
  247. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/hooks/capability.mjs +0 -0
  248. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/hooks/shim.mjs +0 -0
  249. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/hooks/where.mjs +0 -0
  250. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/identity.mjs +0 -0
  251. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/index/compact.mjs +0 -0
  252. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/index/extract.mjs +0 -0
  253. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/index/gate.mjs +0 -0
  254. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/index/govern.mjs +0 -0
  255. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/index/impact.mjs +0 -0
  256. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/index/map.mjs +0 -0
  257. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/index/store.mjs +0 -0
  258. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/index/tests.mjs +0 -0
  259. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/kernel/budget.mjs +0 -0
  260. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/kernel/card.mjs +0 -0
  261. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/kernel/checks.mjs +0 -0
  262. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/kernel/inferability.mjs +0 -0
  263. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/kernel/variants.mjs +0 -0
  264. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/ledger/index.mjs +0 -0
  265. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/local/client.mjs +0 -0
  266. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/local/config.mjs +0 -0
  267. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/locate.mjs +0 -0
  268. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/mcp/prompts.mjs +0 -0
  269. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/mcp/resources.mjs +0 -0
  270. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/mcp/schema.mjs +0 -0
  271. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/measure/context.mjs +0 -0
  272. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/measure/loaderView.mjs +0 -0
  273. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/measure/session.mjs +0 -0
  274. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/monorepo.mjs +0 -0
  275. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/name.mjs +0 -0
  276. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/packs.mjs +0 -0
  277. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/plan/template.mjs +0 -0
  278. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/projection/baselines.mjs +0 -0
  279. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/projection/conflicts.mjs +0 -0
  280. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/projection/disclosure.mjs +0 -0
  281. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/projection/loaders.mjs +0 -0
  282. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/projection/lock.mjs +0 -0
  283. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/projection/markers.mjs +0 -0
  284. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/projection/mdc.mjs +0 -0
  285. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/projection/project.mjs +0 -0
  286. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/projection/rules.mjs +0 -0
  287. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/projection/surfaces.mjs +0 -0
  288. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/projection/targets.mjs +0 -0
  289. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/resolve/body.mjs +0 -0
  290. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/resolve/eval.mjs +0 -0
  291. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/resolve/fingerprint.mjs +0 -0
  292. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/resolve/near.mjs +0 -0
  293. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/resolve/resolve.mjs +0 -0
  294. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/resolve/source.mjs +0 -0
  295. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/review/critic.mjs +0 -0
  296. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/toolchain.mjs +0 -0
  297. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/toolwords.mjs +0 -0
  298. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/tsconfig.mjs +0 -0
  299. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/upgrade/plan.mjs +0 -0
  300. {simt_dev-0.6.2 → simt_dev-0.6.3}/src/workspace.mjs +0 -0
  301. {simt_dev-0.6.2 → simt_dev-0.6.3}/templates/plan/tracker.json +0 -0
@@ -20,3 +20,14 @@ dist/
20
20
  .simt/gate/
21
21
  .simt/distilled/
22
22
  .simt/reviews/
23
+
24
+ # Write journal for `simt undo`. Local state, never shared.
25
+ .simt/journal/
26
+
27
+ # Gate state for `simt status --line`. Local state, never shared: it names the
28
+ # commit the last `check` measured, which is meaningless anywhere else.
29
+ .simt/check.json
30
+
31
+ # Worktrees `simt slice start` creates, one branch per row. Local state: the branch
32
+ # records where the work is, and the directory that holds it is not part of any commit.
33
+ .simt/worktrees/
@@ -6,6 +6,53 @@ All notable changes to this package are recorded here. The format follows
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.6.3] — 2026-10-29
10
+
11
+ ### Added
12
+
13
+ `simt explain <CODE>` names what a `check` finding means, the decision behind
14
+ it, how to fix it, and a concrete trigger — one table row per finding code, so
15
+ every code `check` can emit has an entry.
16
+
17
+ `simt doctor --fix` applies only the remedies flagged safe (local, idempotent,
18
+ journaled) and lists the rest; a fixture with three safe and two unsafe findings
19
+ fixes exactly three.
20
+
21
+ `simt status --line` prints the gate state from the last `check` in under
22
+ 50 ms from cache — `simt PASS ✓rules ✓hooks 3/3gates` — for shell prompts, tmux
23
+ and agent status lines.
24
+
25
+ Every write records `{path, beforeDigest, afterDigest, beforeBytes}` in
26
+ `.simt/journal/`, and `simt undo` restores the last set when every file in it
27
+ is untouched since.
28
+
29
+ `--diff` on every writer prints a unified diff of the plan next to the report,
30
+ changing nothing about what the run writes.
31
+
32
+ `simt completions <bash|zsh|fish>` prints a completion script generated from the
33
+ command registry, so the three shells complete exactly the commands the binary
34
+ dispatches.
35
+
36
+ One ignore list (`.simtignore`) renders `.cursorignore`, `.aiderignore`,
37
+ `.geminiignore` and Claude `permissions.deny`, and a zero-dependency
38
+ staged-diff secret scan (vendor patterns plus Shannon entropy over added lines
39
+ only) blocks a commit carrying a probable secret without printing the bytes.
40
+
41
+ `simt slice start <id>` isolates the work in a linked worktree on branch
42
+ `slice/<id>` with the brief preloaded and flips the tracker row In progress;
43
+ `simt slice finish <id>` runs the declared gates, commits a Conventional
44
+ subject from the row title, and records the SHA and test command on the row.
45
+
46
+ `simt lease <paths> --session <id>` claims files until a TTL in
47
+ `.simt/leases.json`, and the pre-edit hook denies an edit leased by another
48
+ session (ADR-101).
49
+
50
+ `simt pr-body [--base <ref>]` assembles the pull request body from the evidence
51
+ ledger, the decision records the diff touches, the gate state from the last
52
+ check, and the residual risk in ADR-008 vocabulary. It is also exposed as the
53
+ `pr_body` MCP tool; the two longest tool descriptions were shortened to hold
54
+ the 2 KB `tools/list` budget.
55
+
9
56
  ## [0.6.2] — 2026-10-27
10
57
 
11
58
  ### Fixed
@@ -16,7 +63,7 @@ shapes and the leaking-paths count, both designed to move with the corpus).
16
63
  Same product as v0.6.1; this tag exists so the release automation is proven by
17
64
  a green run rather than described by a red one.
18
65
 
19
- ## [0.6.1] — 2026-10-27
66
+ ## [0.6.1] — 2026-10-27 (tagged, never published to npm)
20
67
 
21
68
  ### Fixed
22
69
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: simt-dev
3
- Version: 0.6.2
3
+ Version: 0.6.3
4
4
  Summary: An intelligence amplifier for AI coding agents: rules and dual gates adopted by one command, plus local retrieval, task briefs, benches and repo memory — deterministic by default, with local-model adapters that propose and never select.
5
5
  Project-URL: Homepage, https://github.com/QuazarMedia/simt-dev
6
6
  Project-URL: Repository, https://github.com/QuazarMedia/simt-dev
@@ -56,18 +56,18 @@ to merge. It does not write the projection.
56
56
  ## Install
57
57
 
58
58
  Requires **Node >= 22.20.0** for the npm and PyPI channels; the release binary carries
59
- its own runtime. The current published release is **0.5.0**. Pin it. The tool writes a
59
+ its own runtime. Pin the release you install. The tool writes a
60
60
  content digest into the files it generates, and an unpinned upgrade changes them under
61
61
  you.
62
62
 
63
63
  ```sh
64
- npm i -D simt-dev@0.5.0
64
+ npm i -D simt-dev
65
65
 
66
66
  # or globally
67
- npm i -g simt-dev@0.5.0
67
+ npm i -g simt-dev
68
68
 
69
69
  # or once, with no install
70
- npx -y simt-dev@0.5.0 check
70
+ npx -y simt-dev check
71
71
  ```
72
72
 
73
73
  ### From PyPI
@@ -98,7 +98,7 @@ runtime: the command works with no Node installed.
98
98
  ### As a single-file binary
99
99
 
100
100
  Each release carries one executable per platform — macOS arm64 and x64, Linux x64 —
101
- beside its `.sha256`. The channel's first release is the version after 0.5.0; pin that,
101
+ beside its `.sha256`. Pin the release you download,
102
102
  and run this from the repository's top level:
103
103
 
104
104
  ```sh
@@ -115,7 +115,7 @@ published `.sha256` before running anything.
115
115
  ```sh
116
116
  # Adopt, inspect, and maintain a repository
117
117
  simt init # adopt or scaffold; prints a plan; --yes writes
118
- simt doctor # stack, facts, evidence, and config health
118
+ simt doctor [--fix] # stack, facts, evidence, and config health (--fix applies safe remedies, journaled)
119
119
  simt check [--frozen] # projection drift, manifest, lock, and declared checkers
120
120
  simt sync [--explain] --yes # regenerate the projection
121
121
  simt upgrade --yes # move every consumer in the workspace to this SHA
@@ -133,6 +133,7 @@ simt why [path] # ADRs, rules, skills, gates, and lessons go
133
133
  simt rules list [--root <path>] # rule catalogue and what applies to a repository
134
134
  simt rules show <id> # read one rule body (including rules deferred in kernel mode)
135
135
  simt rules why <id|ADR-NNN> [--all] # the decision that settled a rule, and whether it still stands
136
+ simt explain <CODE> [--json] # what a check finding means, why it is reported, and how to fix it
136
137
  simt decide "<title>" --yes # scaffold the next ADR with structured simt-affects / simt-supersedes
137
138
  simt lessons list # fail-to-fix, revert, review-block, and hook-denial candidates
138
139
  simt lessons review <id> --yes # promote a candidate to docs/lessons/NNNN-<slug>.md
@@ -155,11 +156,20 @@ simt agent-hooks status # what each harness will run, and whether Co
155
156
  simt agent-hook <event> --harness # evaluate pre-tool-use, post-tool-use, or prompt-submit
156
157
  simt evidence # gate and test runs recorded against the current git tree
157
158
  simt evidence check <msg-file> # verify a commit message does not claim unrecorded passing runs
159
+ simt pr-body [--base <ref>] # a PR body: the evidence block for this tree, changed
160
+ # decisions, gate state, and residual risk in ADR-008 vocabulary
158
161
 
159
162
  # Plans, context metering, workspace learning, benchmarks, local models, and MCP
160
163
  simt plan status # count queued, in-progress, complete, and accepted tracker rows
161
164
  simt plan next [<id>] # print the next ready slice section (~1 KB)
162
165
  simt plan done <id> [<sha>] --yes # mark a tracker row complete with its commit SHA and test command
166
+ simt status --line # one-line gate state from the last check, for prompts (< 50 ms)
167
+ simt undo --yes # restore the last journaled set of writes, if untouched since
168
+ simt slice start <id> --yes # a worktree on branch slice/<id> with the brief preloaded; row In progress
169
+ simt slice finish <id> --yes # run the pre-commit gates, commit a Conventional subject from the
170
+ # row's title, and record the SHA and --test command on the row
171
+ simt lease [<paths>] --session # claim files for this session (--ttl, default 1h) or list claims;
172
+ # the pre-edit hook refuses another session's edit until the TTL
163
173
  simt tokens [--repos] [--session] # measure bytes loaded at session start or split a transcript
164
174
  simt harness detect [--user] # detect configured harnesses at repo and user level
165
175
  simt harness loaders [--table] # what each harness loads, in what order, and where its cap truncates
@@ -173,25 +183,37 @@ simt bench report [--compare a b] # resolved rate, quality, cost, CPI, bootstr
173
183
  simt bench ablate --yes # leave-one-out rule ablation ranked by value per KB
174
184
  simt bench probes --yes # 12 deterministic rule-compliance probes
175
185
  simt bench variants --yes # evaluate simt-variants slots and lock winners in simt-dev.lock.json
186
+ simt review [--local] # an advisory ADR-008 verdict skeleton over the staged diff
187
+ simt distill <skill|doc> # a budgeted proposal summary with line citations, for a person to merge
176
188
  simt pack new <name> --source <spec> # scaffold a versioned pack: pack.json, bench.json, one rule
177
189
  simt pack lint [dir] [--require-measured] # validate a pack and state its measured ΔR
178
190
  simt pack publish [dir] --yes # publish an npm-sourced pack (git packs name the tag-and-push)
179
- simt mcp [--list] # serve the 13 read-only tools over stdio JSON-RPC
191
+ simt mcp [--list] # serve the 15 read-only tools over stdio JSON-RPC
192
+ simt completions <bash|zsh|fish> # a completion script generated from the command registry
193
+ simt ignore [--yes] [--diff] # render the one .simtignore list into .cursorignore,
194
+ # .aiderignore, .geminiignore and Claude's permissions.deny
180
195
  ```
181
196
 
182
197
  `init`, `sync`, `upgrade`, `hooks install`, `agent-hooks install`, `shared install`,
183
- `skills install`, `plan done`, `lessons review`, `decide`, `pack new`, `pack publish`
184
- and the `bench` writers print
185
- a plan and write nothing without `--yes`. None of them commit or push. `simt index`
198
+ `skills install`, `plan done`, `lessons review`, `decide`, `ignore`, `pack new`,
199
+ `pack publish`, `slice start`, `slice finish`, `lease` and the `bench` writers print
200
+ a plan and write nothing without `--yes`. None of them push, and only
201
+ `slice finish` commits — locally, through the pre-commit gates, and only what is
202
+ staged. `simt index`
186
203
  writes its cache without asking: the file is gitignored and `git ls-files` can rebuild it.
187
204
 
205
+ Declare `secret-scan` in `gates.preCommit` to block a commit whose staged diff
206
+ carries a probable secret: the scan runs inside the binary (vendor patterns plus
207
+ Shannon entropy, over added lines only), needs no install, and its report never
208
+ prints the matched bytes.
209
+
188
210
  `check` runs the checkers a rule names (`max-file-lines`, `forbid-regex`,
189
211
  `forbidden-path-edit`, `required-file`), verifies structured ADR supersessions
190
212
  (`prose-partial-supersession`), and flags expired lessons (`LESSON-EXPIRED`). A marked
191
213
  rule line leaves the projection as `Enforced:` and the checker's name. The file-length
192
214
  line warns past 400 lines and fails past 1000. `simt evidence check` warns when a commit
193
215
  message claims a passing run this tree does not have, and the commit fails when
194
- `gates.evidence` is `block`.
216
+ `gates.evidence` is `block`. Every finding `check` can emit is explained by `simt explain <CODE>` (DRIFT, UNMANAGED, PACK-DIGEST-MISMATCH, ...).
195
217
 
196
218
  ## Agent playbook: how and when to use each module
197
219
 
@@ -210,6 +232,7 @@ through `simt mcp`.
210
232
  | Rule violation or error | `simt lessons list` | `simt rules why <rule-id>` for the decision |
211
233
  | Working from a plan | `simt plan next` | `simt plan done <id> <sha> --yes` when finished |
212
234
  | Before committing | `simt check` | `simt evidence` to verify test claims |
235
+ | Opening a pull request | `simt pr-body` | `--base <ref>` to diff against another fork point |
213
236
  | Repository adoption | `simt init --yes` | `simt doctor` to verify stack detection |
214
237
  | Multi-repo workspace | `simt compare` | `simt shared plan` to find deduplication opportunities |
215
238
  | Local model available | `simt local doctor` | `simt index --embed` to build vector embeddings |
@@ -342,16 +365,16 @@ returns a JSON object with `task`, `commands`, `files`, `tests`, `decisions`, `s
342
365
  | **Governance & Provenance** | `simt why [path]`, `simt rules list`, `simt rules show <id>`, `simt rules why <id\|ADR-NNN>`, `simt decide` | `rules_list`, `rules_why` | Before touching governed files (`why`), when reading deferred kernel rules (`rules show`), or when checking/scaffolding ADRs (`rules why`, `decide`) |
343
366
  | **Skills & Disclosure** | `simt skills index\|brief\|show\|why\|find\|install\|compile\|eval`, `simt graph lint` | `skills_index`, `skills_find`, `skills_brief`, `skills_show`, `skills_why` | When a task requires domain workflows or reference docs without blowing the session token budget |
344
367
  | **Memory & Lessons** | `simt lessons list`, `simt lessons review <id> --yes` | — | After fixing a failing test/gate or hitting a hook denial, to inspect or promote reusable failure-to-fix lessons |
345
- | **Plans & Trackers** | `simt plan status`, `simt plan next [<id>]`, `simt plan done <id> [<sha>] --yes` | `plan_next`, `plan_done` | When executing a phased implementation or review plan row by row |
368
+ | **Plans & Trackers** | `simt plan status`, `simt plan next [<id>]`, `simt plan done <id> [<sha>] --yes`, `simt slice start\|finish <id>`, `simt lease`, `simt pr-body`, `simt status --line`, `simt undo` | `plan_next`, `plan_done`, `pr_body` | When executing a phased implementation or review plan row by row |
346
369
  | **Adoption & Projection** | `simt init`, `simt doctor`, `simt check [--frozen]`, `simt sync`, `simt upgrade`, `simt ci` | `doctor`, `check` | When adopting a repo, diagnosing stack/config health, or verifying zero drift before commit |
347
370
  | **Dual Gates & Evidence** | `simt hooks install\|status\|run`, `simt agent-hooks install\|status`, `simt agent-hook`, `simt evidence [check]` | — | When installing git/agent hooks, running gates manually, or verifying test claims before committing |
348
371
  | **Context & Harnesses** | `simt tokens [--repos] [--session]`, `simt harness detect\|loaders`, `simt shared plan\|install` | — | When auditing startup token cost across harnesses (`claude`, `codex`, `cursor`, `opencode`, `antigravity`, `copilot`, `deepseek`) or deduplicating workspace rules |
349
- | **Workspace & Benchmarks** | `simt compare`, `simt bench mine\|run\|report\|ablate\|probes\|variants`, `simt local doctor` | `compare` | When auditing an entire multi-repo estate, measuring rule uplift/cost, or probing local model endpoints |
372
+ | **Workspace & Benchmarks** | `simt compare`, `simt bench mine\|run\|report\|ablate\|probes\|variants`, `simt local doctor`, `simt review [--local]`, `simt distill` | `compare` | When auditing an entire multi-repo estate, measuring rule uplift/cost, or probing local model endpoints |
350
373
 
351
374
  ## Where the plan finishes
352
375
 
353
- Slices `R01`–`R45` are complete and shipped in `0.6.0`. The remaining queued slices are the
354
- small ergonomics:
376
+ Slices `R01`–`R55` are all complete. The small ergonomics (`R46`–`R55`) shipped
377
+ on top of `0.6.0`:
355
378
 
356
379
  - **The small doors (`R46`–`R55`).** `simt explain <CODE>` for every finding code, safe
357
380
  idempotent `simt doctor --fix`, a `< 50 ms` `simt status --line`, a write journal with
@@ -359,6 +382,12 @@ small ergonomics:
359
382
  plus a staged-diff secret scan, `simt slice start/finish <ID>` worktrees, file leases
360
383
  for parallel agents, and `simt pr-body` assembled from the evidence ledger.
361
384
 
385
+ The last two rows of review `0002` (`S38` workspace token cost, `S39` estate policy
386
+ as a pack) are closed by ruling in ADR-102: the instrument, the declaration and the
387
+ non-blocking finding shipped, the blocking gate and the registry-carrying pack were
388
+ refused by ruling, and the estate-side move is recorded as whose commit it waits on.
389
+ Everything in plans `0001`–`0003` and reviews `0001`–`0002` is Complete or Accepted.
390
+
362
391
  The local-model slices (`R38`–`R40`) shipped as they lab-written: `simt distill` proposes
363
392
  budgeted summaries with line citations, `simt review` proposes an advisory ADR-008
364
393
  verdict over the staged diff, and `simt brief` carries model/effort advice from bench
@@ -26,18 +26,18 @@ to merge. It does not write the projection.
26
26
  ## Install
27
27
 
28
28
  Requires **Node >= 22.20.0** for the npm and PyPI channels; the release binary carries
29
- its own runtime. The current published release is **0.5.0**. Pin it. The tool writes a
29
+ its own runtime. Pin the release you install. The tool writes a
30
30
  content digest into the files it generates, and an unpinned upgrade changes them under
31
31
  you.
32
32
 
33
33
  ```sh
34
- npm i -D simt-dev@0.5.0
34
+ npm i -D simt-dev
35
35
 
36
36
  # or globally
37
- npm i -g simt-dev@0.5.0
37
+ npm i -g simt-dev
38
38
 
39
39
  # or once, with no install
40
- npx -y simt-dev@0.5.0 check
40
+ npx -y simt-dev check
41
41
  ```
42
42
 
43
43
  ### From PyPI
@@ -68,7 +68,7 @@ runtime: the command works with no Node installed.
68
68
  ### As a single-file binary
69
69
 
70
70
  Each release carries one executable per platform — macOS arm64 and x64, Linux x64 —
71
- beside its `.sha256`. The channel's first release is the version after 0.5.0; pin that,
71
+ beside its `.sha256`. Pin the release you download,
72
72
  and run this from the repository's top level:
73
73
 
74
74
  ```sh
@@ -85,7 +85,7 @@ published `.sha256` before running anything.
85
85
  ```sh
86
86
  # Adopt, inspect, and maintain a repository
87
87
  simt init # adopt or scaffold; prints a plan; --yes writes
88
- simt doctor # stack, facts, evidence, and config health
88
+ simt doctor [--fix] # stack, facts, evidence, and config health (--fix applies safe remedies, journaled)
89
89
  simt check [--frozen] # projection drift, manifest, lock, and declared checkers
90
90
  simt sync [--explain] --yes # regenerate the projection
91
91
  simt upgrade --yes # move every consumer in the workspace to this SHA
@@ -103,6 +103,7 @@ simt why [path] # ADRs, rules, skills, gates, and lessons go
103
103
  simt rules list [--root <path>] # rule catalogue and what applies to a repository
104
104
  simt rules show <id> # read one rule body (including rules deferred in kernel mode)
105
105
  simt rules why <id|ADR-NNN> [--all] # the decision that settled a rule, and whether it still stands
106
+ simt explain <CODE> [--json] # what a check finding means, why it is reported, and how to fix it
106
107
  simt decide "<title>" --yes # scaffold the next ADR with structured simt-affects / simt-supersedes
107
108
  simt lessons list # fail-to-fix, revert, review-block, and hook-denial candidates
108
109
  simt lessons review <id> --yes # promote a candidate to docs/lessons/NNNN-<slug>.md
@@ -125,11 +126,20 @@ simt agent-hooks status # what each harness will run, and whether Co
125
126
  simt agent-hook <event> --harness # evaluate pre-tool-use, post-tool-use, or prompt-submit
126
127
  simt evidence # gate and test runs recorded against the current git tree
127
128
  simt evidence check <msg-file> # verify a commit message does not claim unrecorded passing runs
129
+ simt pr-body [--base <ref>] # a PR body: the evidence block for this tree, changed
130
+ # decisions, gate state, and residual risk in ADR-008 vocabulary
128
131
 
129
132
  # Plans, context metering, workspace learning, benchmarks, local models, and MCP
130
133
  simt plan status # count queued, in-progress, complete, and accepted tracker rows
131
134
  simt plan next [<id>] # print the next ready slice section (~1 KB)
132
135
  simt plan done <id> [<sha>] --yes # mark a tracker row complete with its commit SHA and test command
136
+ simt status --line # one-line gate state from the last check, for prompts (< 50 ms)
137
+ simt undo --yes # restore the last journaled set of writes, if untouched since
138
+ simt slice start <id> --yes # a worktree on branch slice/<id> with the brief preloaded; row In progress
139
+ simt slice finish <id> --yes # run the pre-commit gates, commit a Conventional subject from the
140
+ # row's title, and record the SHA and --test command on the row
141
+ simt lease [<paths>] --session # claim files for this session (--ttl, default 1h) or list claims;
142
+ # the pre-edit hook refuses another session's edit until the TTL
133
143
  simt tokens [--repos] [--session] # measure bytes loaded at session start or split a transcript
134
144
  simt harness detect [--user] # detect configured harnesses at repo and user level
135
145
  simt harness loaders [--table] # what each harness loads, in what order, and where its cap truncates
@@ -143,25 +153,37 @@ simt bench report [--compare a b] # resolved rate, quality, cost, CPI, bootstr
143
153
  simt bench ablate --yes # leave-one-out rule ablation ranked by value per KB
144
154
  simt bench probes --yes # 12 deterministic rule-compliance probes
145
155
  simt bench variants --yes # evaluate simt-variants slots and lock winners in simt-dev.lock.json
156
+ simt review [--local] # an advisory ADR-008 verdict skeleton over the staged diff
157
+ simt distill <skill|doc> # a budgeted proposal summary with line citations, for a person to merge
146
158
  simt pack new <name> --source <spec> # scaffold a versioned pack: pack.json, bench.json, one rule
147
159
  simt pack lint [dir] [--require-measured] # validate a pack and state its measured ΔR
148
160
  simt pack publish [dir] --yes # publish an npm-sourced pack (git packs name the tag-and-push)
149
- simt mcp [--list] # serve the 13 read-only tools over stdio JSON-RPC
161
+ simt mcp [--list] # serve the 15 read-only tools over stdio JSON-RPC
162
+ simt completions <bash|zsh|fish> # a completion script generated from the command registry
163
+ simt ignore [--yes] [--diff] # render the one .simtignore list into .cursorignore,
164
+ # .aiderignore, .geminiignore and Claude's permissions.deny
150
165
  ```
151
166
 
152
167
  `init`, `sync`, `upgrade`, `hooks install`, `agent-hooks install`, `shared install`,
153
- `skills install`, `plan done`, `lessons review`, `decide`, `pack new`, `pack publish`
154
- and the `bench` writers print
155
- a plan and write nothing without `--yes`. None of them commit or push. `simt index`
168
+ `skills install`, `plan done`, `lessons review`, `decide`, `ignore`, `pack new`,
169
+ `pack publish`, `slice start`, `slice finish`, `lease` and the `bench` writers print
170
+ a plan and write nothing without `--yes`. None of them push, and only
171
+ `slice finish` commits — locally, through the pre-commit gates, and only what is
172
+ staged. `simt index`
156
173
  writes its cache without asking: the file is gitignored and `git ls-files` can rebuild it.
157
174
 
175
+ Declare `secret-scan` in `gates.preCommit` to block a commit whose staged diff
176
+ carries a probable secret: the scan runs inside the binary (vendor patterns plus
177
+ Shannon entropy, over added lines only), needs no install, and its report never
178
+ prints the matched bytes.
179
+
158
180
  `check` runs the checkers a rule names (`max-file-lines`, `forbid-regex`,
159
181
  `forbidden-path-edit`, `required-file`), verifies structured ADR supersessions
160
182
  (`prose-partial-supersession`), and flags expired lessons (`LESSON-EXPIRED`). A marked
161
183
  rule line leaves the projection as `Enforced:` and the checker's name. The file-length
162
184
  line warns past 400 lines and fails past 1000. `simt evidence check` warns when a commit
163
185
  message claims a passing run this tree does not have, and the commit fails when
164
- `gates.evidence` is `block`.
186
+ `gates.evidence` is `block`. Every finding `check` can emit is explained by `simt explain <CODE>` (DRIFT, UNMANAGED, PACK-DIGEST-MISMATCH, ...).
165
187
 
166
188
  ## Agent playbook: how and when to use each module
167
189
 
@@ -180,6 +202,7 @@ through `simt mcp`.
180
202
  | Rule violation or error | `simt lessons list` | `simt rules why <rule-id>` for the decision |
181
203
  | Working from a plan | `simt plan next` | `simt plan done <id> <sha> --yes` when finished |
182
204
  | Before committing | `simt check` | `simt evidence` to verify test claims |
205
+ | Opening a pull request | `simt pr-body` | `--base <ref>` to diff against another fork point |
183
206
  | Repository adoption | `simt init --yes` | `simt doctor` to verify stack detection |
184
207
  | Multi-repo workspace | `simt compare` | `simt shared plan` to find deduplication opportunities |
185
208
  | Local model available | `simt local doctor` | `simt index --embed` to build vector embeddings |
@@ -312,16 +335,16 @@ returns a JSON object with `task`, `commands`, `files`, `tests`, `decisions`, `s
312
335
  | **Governance & Provenance** | `simt why [path]`, `simt rules list`, `simt rules show <id>`, `simt rules why <id\|ADR-NNN>`, `simt decide` | `rules_list`, `rules_why` | Before touching governed files (`why`), when reading deferred kernel rules (`rules show`), or when checking/scaffolding ADRs (`rules why`, `decide`) |
313
336
  | **Skills & Disclosure** | `simt skills index\|brief\|show\|why\|find\|install\|compile\|eval`, `simt graph lint` | `skills_index`, `skills_find`, `skills_brief`, `skills_show`, `skills_why` | When a task requires domain workflows or reference docs without blowing the session token budget |
314
337
  | **Memory & Lessons** | `simt lessons list`, `simt lessons review <id> --yes` | — | After fixing a failing test/gate or hitting a hook denial, to inspect or promote reusable failure-to-fix lessons |
315
- | **Plans & Trackers** | `simt plan status`, `simt plan next [<id>]`, `simt plan done <id> [<sha>] --yes` | `plan_next`, `plan_done` | When executing a phased implementation or review plan row by row |
338
+ | **Plans & Trackers** | `simt plan status`, `simt plan next [<id>]`, `simt plan done <id> [<sha>] --yes`, `simt slice start\|finish <id>`, `simt lease`, `simt pr-body`, `simt status --line`, `simt undo` | `plan_next`, `plan_done`, `pr_body` | When executing a phased implementation or review plan row by row |
316
339
  | **Adoption & Projection** | `simt init`, `simt doctor`, `simt check [--frozen]`, `simt sync`, `simt upgrade`, `simt ci` | `doctor`, `check` | When adopting a repo, diagnosing stack/config health, or verifying zero drift before commit |
317
340
  | **Dual Gates & Evidence** | `simt hooks install\|status\|run`, `simt agent-hooks install\|status`, `simt agent-hook`, `simt evidence [check]` | — | When installing git/agent hooks, running gates manually, or verifying test claims before committing |
318
341
  | **Context & Harnesses** | `simt tokens [--repos] [--session]`, `simt harness detect\|loaders`, `simt shared plan\|install` | — | When auditing startup token cost across harnesses (`claude`, `codex`, `cursor`, `opencode`, `antigravity`, `copilot`, `deepseek`) or deduplicating workspace rules |
319
- | **Workspace & Benchmarks** | `simt compare`, `simt bench mine\|run\|report\|ablate\|probes\|variants`, `simt local doctor` | `compare` | When auditing an entire multi-repo estate, measuring rule uplift/cost, or probing local model endpoints |
342
+ | **Workspace & Benchmarks** | `simt compare`, `simt bench mine\|run\|report\|ablate\|probes\|variants`, `simt local doctor`, `simt review [--local]`, `simt distill` | `compare` | When auditing an entire multi-repo estate, measuring rule uplift/cost, or probing local model endpoints |
320
343
 
321
344
  ## Where the plan finishes
322
345
 
323
- Slices `R01`–`R45` are complete and shipped in `0.6.0`. The remaining queued slices are the
324
- small ergonomics:
346
+ Slices `R01`–`R55` are all complete. The small ergonomics (`R46`–`R55`) shipped
347
+ on top of `0.6.0`:
325
348
 
326
349
  - **The small doors (`R46`–`R55`).** `simt explain <CODE>` for every finding code, safe
327
350
  idempotent `simt doctor --fix`, a `< 50 ms` `simt status --line`, a write journal with
@@ -329,6 +352,12 @@ small ergonomics:
329
352
  plus a staged-diff secret scan, `simt slice start/finish <ID>` worktrees, file leases
330
353
  for parallel agents, and `simt pr-body` assembled from the evidence ledger.
331
354
 
355
+ The last two rows of review `0002` (`S38` workspace token cost, `S39` estate policy
356
+ as a pack) are closed by ruling in ADR-102: the instrument, the declaration and the
357
+ non-blocking finding shipped, the blocking gate and the registry-carrying pack were
358
+ refused by ruling, and the estate-side move is recorded as whose commit it waits on.
359
+ Everything in plans `0001`–`0003` and reviews `0001`–`0002` is Complete or Accepted.
360
+
332
361
  The local-model slices (`R38`–`R40`) shipped as they lab-written: `simt distill` proposes
333
362
  budgeted summaries with line citations, `simt review` proposes an advisory ADR-008
334
363
  verdict over the staged diff, and `simt brief` carries model/effort advice from bench
@@ -4,26 +4,33 @@
4
4
  // POSIX only (ADR-012). package.json declares os: [darwin, linux], so npm refuses
5
5
  // the install elsewhere rather than letting a hook fail obscurely.
6
6
 
7
- import { parse } from '../src/argv.mjs';
7
+ import { parse, rawJsonFlag } from '../src/argv.mjs';
8
8
  import { EXIT, fail, jsonFailMode, jsonIndentDefault } from '../src/output/index.mjs';
9
9
 
10
10
  try {
11
11
  const argv = process.argv.slice(2);
12
12
  const parsed = parse(argv);
13
13
  if (!parsed.ok) {
14
- process.exit(parsed.code);
14
+ // The flags do not exist yet, so the JSON mode is read off the raw words:
15
+ // a parse failure under `--json` is a JSON document on stdout, not text on
16
+ // stderr with an empty stdout (Q11, ADR-070 ruling 4).
17
+ jsonFailMode(rawJsonFlag(argv));
18
+ process.exit(fail(parsed.error.message, parsed.error.code));
15
19
  }
16
20
  const { flags, positional } = parsed.value;
17
21
 
22
+ // Set before anything can fail: `no command given` under `--json` is a JSON
23
+ // document too, and a failure that prints as text with an empty stdout breaks
24
+ // the same ruling the parse failure above honours (Q11, ADR-070 ruling 4).
25
+ jsonIndentDefault(flags.pretty === true);
26
+ jsonFailMode(flags.json === true);
27
+
18
28
  // No arguments at all is a usage error, not a silent help dump: an agent that
19
29
  // ran the wrong thing should be told so rather than handed 40 lines of prose.
20
30
  if (positional.length === 0 && !flags.help && !flags.version) {
21
31
  process.exit(fail('no command given', EXIT.USAGE));
22
32
  }
23
33
 
24
- jsonIndentDefault(flags.pretty === true);
25
- jsonFailMode(flags.json === true);
26
-
27
34
  // The one command that runs on somebody else's hot path, and therefore the one that
28
35
  // does not load the registry. `agent-hook` is called before every tool call an agent
29
36
  // makes, so its latency is a product requirement rather than a nicety (plan 0003
@@ -41,7 +48,13 @@ try {
41
48
  }
42
49
 
43
50
  const { dispatch } = await import('../src/commands/index.mjs');
44
- process.exit((await dispatch(argv)) ?? EXIT.OK);
51
+ const code = (await dispatch(argv)) ?? EXIT.OK;
52
+ // Assigned, not forced: a large document on stdout (a `--json --diff` over a
53
+ // skill-sized body exceeds the 64 KiB pipe buffer) is still draining when the
54
+ // command resolves, and `process.exit()` cuts it — exit 0 with half a JSON
55
+ // document on stdout. Letting the loop empty first makes the exit honest
56
+ // (plan 0003 R50; the S10 contract asserts the document parses).
57
+ process.exitCode = code;
45
58
  } catch (error) {
46
59
  process.exit(fail(error?.message ?? String(error), EXIT.FAIL));
47
60
  }
@@ -0,0 +1,94 @@
1
+ ---
2
+ simt-affects: ["src/hooks/gates.mjs", "src/hooks/resolve.mjs", "src/hooks/dispatcher.mjs", "src/projection/manifest.mjs", "src/secrets.mjs"]
3
+ simt-supersedes: []
4
+ ---
5
+
6
+ # ADR-100 — a staged diff is the last gate before history, and it runs inside the tool
7
+
8
+ Status: **accepted** · 2026-10-27
9
+
10
+ Affects: `src/hooks/gates.mjs`, `src/hooks/resolve.mjs`,
11
+ `src/hooks/dispatcher.mjs`, `src/projection/manifest.mjs`, `src/secrets.mjs`
12
+
13
+ ## Context
14
+
15
+ Git history is append-only: a secret committed is a rotation exercise, not a
16
+ revert, and the one moment it can still be kept out is the commit. Every other
17
+ leak path in this tool is already gated — the projection, the manifest, the
18
+ evidence claim — but nothing gated the staged diff.
19
+
20
+ The three existing gate kinds cannot express this check. `staged` hands files
21
+ to a formatter binary in `node_modules/.bin`, `script` runs a `package.json`
22
+ script, and `command` runs a line the manifest declares: each resolves
23
+ something ON DISK, and each therefore has a way to be missing. A secret scan
24
+ has nothing to resolve — the implementation is the question being asked — and
25
+ making it a `command` gate would mean a repository declares `simt secrets`
26
+ (or installs a third-party scanner) before the check exists at all. That is
27
+ backwards for the repositories most at risk, which are frequently the ones with
28
+ the least toolchain to install into.
29
+
30
+ Plan 0003 R52 asks for both halves from one list and one binary: a
31
+ zero-dependency staged-diff scan (vendor patterns plus entropy), and no
32
+ repository needing anything to run it.
33
+
34
+ ## Ruling
35
+
36
+ 1. **A fourth gate kind, `builtin`, runs inside this binary.** It is declared
37
+ in the manifest like any other gate, a `gates.commands` entry overrides it
38
+ exactly as it overrides every other kind (the dispatcher's precedence is
39
+ unchanged), and its result flows through the same ledger line, the same
40
+ fail-closed reporting and the same `hooks status` view. What it never does
41
+ is resolve anything on disk: there is no script to miss, no formatter to
42
+ install and no command to declare, so `gateRunnable` reports it runnable and
43
+ `check` counts it as such. A `builtin` name with no implementation fails the
44
+ event with the name of the gate rather than passing.
45
+
46
+ 2. **`secret-scan` reads only the added lines of `git diff --cached`.** Two
47
+ detectors, both local: a pattern library for the shapes vendors publish
48
+ (AWS key ids, private key blocks, GitHub/Slack/Stripe/Google/OpenAI-style
49
+ tokens, JWTs, assigned secrets) and Shannon entropy (≥ 4.5 bits per
50
+ character over runs of ≥ 32 base64-ish characters) for the blobs no vendor
51
+ named. Values carrying placeholder markers (`example`, `changeme`,
52
+ `your_`, …) are documentation, not findings. Context lines are not
53
+ scanned: blocking a commit over bytes the author did not stage reproduces
54
+ the prohibition `format`'s staged-only rule exists for. If git cannot
55
+ answer, the gate fails rather than reading silence as a clean diff.
56
+
57
+ 3. **A finding never prints the matched bytes.** The report carries the
58
+ pattern id, the file, the line and a four-character prefix — the part a
59
+ vendor publishes as a type (`AKIA`, `sk-`, `ghp_`). Hook output lands in a
60
+ terminal, a CI log and often an agent's own transcript, and echoing the
61
+ secret into the report about the secret is the leak with extra steps.
62
+
63
+ 4. **The gate is opt-in, not an `init` default.** Entropy has a false-positive
64
+ rate no threshold eliminates, and a gate that blocks a first commit over a
65
+ sha256 digest teaches exactly the `--no-verify` habit the dispatcher exists
66
+ to prevent. A repository opts in by adding `secret-scan` to
67
+ `gates.preCommit`; from then on it is reported, counted and fail-closed like
68
+ every other declared gate.
69
+
70
+ ## Consequences
71
+
72
+ - A repository gets the scan by declaring the gate; nothing is installed,
73
+ nothing is fetched at hook time, and a fresh clone runs it identically.
74
+ - `unresolved()` and `gateRunnable()` know `builtin` as a runnable kind, so
75
+ `check` no longer has a gate it must call unrunnable-but-isn't; `hooks
76
+ status` prints `run builtin` for the entry.
77
+ - A `gates.commands["secret-scan"]` declaration replaces the built-in scan
78
+ with whatever line the repository names — the escape hatch every other kind
79
+ has, preserved for this one.
80
+ - The matcher lives in `src/secrets.mjs` and is unit-tested against sentinel
81
+ values, including the negative cases (hex digests, UUIDs, placeholders) that
82
+ decide whether the threshold is usable rather than merely strict.
83
+
84
+ ## Rejected
85
+
86
+ - **Shipping a third-party scanner (gitleaks, trufflehog).** It violates the
87
+ zero-dependency rule outright, and a hook that downloads a scanner at commit
88
+ time is a hook that fails on an offline machine — the failure mode ADR-010's
89
+ no-fetch-at-hook-time rule already refuses for `npx`.
90
+ - **Scanning the working tree or the whole repository.** That flags secrets
91
+ already in history on every subsequent commit (unfixable by the author of
92
+ this commit) and scans unstaged work nobody was about to record. The staged
93
+ diff is precisely the bytes the next commit would make permanent, and it is
94
+ the only bytes this gate claims to judge.
@@ -0,0 +1,95 @@
1
+ ---
2
+ simt-affects: ["src/lease.mjs", "src/commands/lease.mjs", "src/agenthooks/policy.mjs", "src/agenthooks/decide.mjs"]
3
+ simt-supersedes: []
4
+ ---
5
+
6
+ # ADR-101 — a file lease belongs to one session, and the pre-edit hook refuses another's edit
7
+
8
+ Status: **accepted** · 2026-10-28
9
+
10
+ Affects: `src/lease.mjs`, `src/commands/lease.mjs`,
11
+ `src/agenthooks/policy.mjs`, `src/agenthooks/decide.mjs`
12
+
13
+ ## Context
14
+
15
+ Parallel agents share one working tree, and the cheapest collision between them
16
+ is two sessions editing the same file at once: each edit is valid alone, and
17
+ the pair is neither — one session's work is overwritten by the other's save,
18
+ with no gate, no diff and no hook that ever sees a conflict. Git notices this
19
+ only at merge time, which is far after the fact either session can explain.
20
+
21
+ Plan 0003 R54 asks for a claim mechanism: `simt lease <paths>` records which
22
+ session is working on which path, with a TTL, and the pre-edit half of the
23
+ agent hook denies an edit from a session that does not hold the claim.
24
+
25
+ The policy table is where every other agent-time refusal lives (`push`,
26
+ `rewrite`, `generated`), so a lease refusal belongs there too — one table,
27
+ four harness dialects, one message. What the table has never had is a fact
28
+ that is not in the payload: which session is asking, and who else has claimed
29
+ the path.
30
+
31
+ ## Ruling
32
+
33
+ 1. **A lease is a claim, not a lock.** `.simt/leases.json` records one entry
34
+ per path: the repo-relative path, the session name, and an absolute expiry
35
+ timestamp. It is taken with `simt lease <paths>` (preview unless `--yes`),
36
+ the session comes from `--session` or `SIMT_SESSION`, and the TTL defaults
37
+ to an hour. There is no lock on the file and no daemon: a claim is advisory
38
+ data that expires on its own, last writer wins, and a claim lost to a race
39
+ is simply re-made. Coordination machinery would be a system built around a
40
+ file a TTL already cleans up.
41
+
42
+ 2. **A live claim held by a different session refuses a re-claim.** Stealing
43
+ is what expiry is for: the refusal names the holder and the expiry, and
44
+ the session that wants the path waits for the TTL or asks the holder. The
45
+ holder may re-claim (refresh) its own paths at any time.
46
+
47
+ 3. **The pre-edit hook denies an edit to a path another session holds.** The
48
+ check joins two facts at decision time: the active claims in the file, and
49
+ the asking session's name from `SIMT_SESSION` — one variable for the claim
50
+ and the check, because a denial is only explainable if the session it
51
+ protected is the same name the claim was filed under. A session that cannot
52
+ prove ownership is treated as another session: an unrecognised edit is
53
+ refused with the holder's name, not waved through. Expiry is read when the
54
+ hook runs, so a TTL needs no sweeper, and a claim with no file (the default
55
+ state of every repository) denies nothing.
56
+
57
+ 4. **An unreadable claim file fails closed for edits and only for edits.**
58
+ A `.simt/leases.json` that does not parse is evidence someone — possibly a
59
+ session routing around the check — broke the claims the hook is about to
60
+ enforce, so any write is refused until the file is fixed or removed; a
61
+ `lease` command refuses to write over it for the same reason. A shell
62
+ command with no file fact is not an edit and is not refused. This mirrors
63
+ the fail-closed contract every gate has, scoped to the question the lease
64
+ can actually answer.
65
+
66
+ 5. **The refusal is the `lease` policy, with the table's full machinery.** It
67
+ carries `ADR-101`, is lifted by `SIMT_ALLOW=lease` exactly as every other
68
+ policy is, exits with the harness's deny code, and its message names the
69
+ held paths, the holders and the expiry in ISO — the three things the
70
+ blocked session needs to act. The per-instance detail is a `detail` hook on
71
+ the row, so the message that quotes a timestamp does not become a special
72
+ case inside `decide`.
73
+
74
+ ## Consequences
75
+
76
+ - Two sessions in one working tree can coordinate with one command and no
77
+ shared process; a crashed session's claims lapse on their own.
78
+ - The hook's hot path gains one small `readFile` of a file that is usually
79
+ absent, and only when the payload named a file to write.
80
+ - `learn.mjs` reads policy rows by `id` and `adr` only, so the `lease` row
81
+ joins the estate's violation aggregation with no further wiring.
82
+ - The claim file is local state under `.simt` like the index and the journal:
83
+ never projected, never committed.
84
+
85
+ ## Rejected
86
+
87
+ - **File locking (`flock`, a lockfile protocol).** A lock that blocks is a
88
+ deadlock with a crashed session in it, and it needs the very daemon ruling 1
89
+ refuses. The TTL already bounds every claim.
90
+ - **Inferring leased paths from shell commands.** Only the edit tools name a
91
+ file with no guesswork; guessing at what a `sh -c` line will write is the
92
+ payload-shaped false positive the policy table was built to avoid — no fact
93
+ is not a violation.
94
+ - **A lease the holder must release to finish.** Forgetting to release is the
95
+ expected failure of any release-based protocol; an expiry is not.