simt-dev 0.2.2__tar.gz → 0.3.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.
- {simt_dev-0.2.2 → simt_dev-0.3.0}/.gitignore +7 -1
- {simt_dev-0.2.2 → simt_dev-0.3.0}/CHANGELOG.md +37 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/PKG-INFO +1 -1
- simt_dev-0.3.0/bin/simt-dev.mjs +47 -0
- simt_dev-0.3.0/docs/decisions/ADR-074-a-rule-and-a-decision-are-readable-by-uri.md +99 -0
- simt_dev-0.3.0/docs/decisions/ADR-075-nothing-leaves-the-machine.md +56 -0
- simt_dev-0.3.0/docs/decisions/ADR-076-a-change-to-what-agents-read-is-measured.md +70 -0
- simt_dev-0.3.0/docs/decisions/ADR-077-the-command-card-leads-the-region-and-reads-committed-evidence.md +91 -0
- simt_dev-0.3.0/docs/decisions/ADR-078-a-line-the-repository-already-proves-does-not-ship.md +117 -0
- simt_dev-0.3.0/docs/decisions/ADR-079-the-rules-are-enforced-at-the-tool-call-from-one-policy-table.md +162 -0
- simt_dev-0.3.0/docs/decisions/ADR-080-the-tools-own-names-are-not-repositories-and-neither-reader-decides-by-shape.md +99 -0
- simt_dev-0.3.0/docs/decisions/ADR-081-a-tracker-is-read-through-the-repositorys-template.md +36 -0
- simt_dev-0.3.0/docs/decisions/ADR-082-the-tracker-override-is-a-manifest-key.md +35 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/package.json +2 -1
- {simt_dev-0.2.2 → simt_dev-0.3.0}/pyproject.toml +2 -0
- simt_dev-0.3.0/src/agenthooks/decide.mjs +123 -0
- simt_dev-0.3.0/src/agenthooks/policy.mjs +78 -0
- simt_dev-0.3.0/src/agenthooks/render.mjs +240 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/argv.mjs +36 -1
- simt_dev-0.3.0/src/bench/ablate.mjs +630 -0
- simt_dev-0.3.0/src/bench/adapters.json +149 -0
- simt_dev-0.3.0/src/bench/grade.mjs +229 -0
- simt_dev-0.3.0/src/bench/mine.mjs +811 -0
- simt_dev-0.3.0/src/bench/probes.mjs +1350 -0
- simt_dev-0.3.0/src/bench/report.mjs +899 -0
- simt_dev-0.3.0/src/bench/run.mjs +1002 -0
- simt_dev-0.3.0/src/commands/agenthook.mjs +282 -0
- simt_dev-0.3.0/src/commands/bench.mjs +359 -0
- simt_dev-0.3.0/src/commands/harness.mjs +301 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/commands/help.mjs +58 -1
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/commands/index.mjs +25 -1
- simt_dev-0.3.0/src/commands/plan.mjs +99 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/commands/tokens.mjs +31 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/decisions/index.mjs +23 -5
- simt_dev-0.3.0/src/kernel/card.mjs +254 -0
- simt_dev-0.3.0/src/kernel/inferability.mjs +188 -0
- simt_dev-0.3.0/src/mcp/resources.mjs +157 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/mcp/server.mjs +37 -6
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/mcp/tools.mjs +84 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/measure/context.mjs +177 -6
- simt_dev-0.3.0/src/measure/loaderView.mjs +435 -0
- simt_dev-0.3.0/src/measure/session.mjs +267 -0
- simt_dev-0.3.0/src/plan/index.mjs +650 -0
- simt_dev-0.3.0/src/plan/template.mjs +331 -0
- simt_dev-0.3.0/src/projection/loaders.mjs +689 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/projection/manifest.mjs +26 -3
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/projection/rules.mjs +80 -5
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/projection/surfaces.mjs +22 -8
- simt_dev-0.3.0/src/toolwords.mjs +69 -0
- simt_dev-0.3.0/templates/plan/tracker.json +36 -0
- simt_dev-0.2.2/bin/simt-dev.mjs +0 -28
- simt_dev-0.2.2/src/commands/harness.mjs +0 -150
- {simt_dev-0.2.2 → simt_dev-0.3.0}/LICENSE +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/README.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-001-push-requires-approval.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-002-refactor-blast-radius.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-003-test-breadth.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-004-hook-owns-format.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-005-file-length.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-006-coverage-bar.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-007-section-skeleton.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-008-verdict-vocabulary.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-009-skill-layout.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-010-runner-invocation.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-011-windows-support.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-012-drop-windows-support.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-013-genericity-by-facts-and-local-profiles.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-014-workspace-is-configuration.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-015-a-source-is-content-not-a-location.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-016-a-divergent-rule-is-retired-not-merged.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-017-a-declared-gate-must-be-runnable.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-018-an-unset-hooks-path-is-not-an-absent-hook.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-019-a-declared-command-is-the-runner.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-020-a-rule-is-written-per-surface-and-pointed-not-copied.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-021-one-surface-per-repo.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-022-a-key-simt-dev-reads-is-prefixed.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-023-the-gate-ships-as-a-file-the-repo-owns.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-024-simt-dev-overwrites-its-own-gate-file.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-025-a-baseline-is-a-region-in-a-file-the-repo-owns.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-026-a-config-without-a-region-is-a-file-the-repo-owns.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-027-the-one-gitattributes-line-that-is-neither-dangerous-nor-empty.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-028-a-base-file-is-a-floor-so-the-disagreement-it-cannot-repair-becomes-a-check.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-029-the-pins-a-repository-declares-are-its-own.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-030-what-a-plan-does-not-ship-is-a-decision-with-a-record.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-031-the-suite-stages-the-environment-it-needs.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-032-provenance-is-a-content-digest-not-a-commit.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-033-three-plan-rows-closed-by-decision-not-by-authoring.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-034-a-staged-tool-refuses-a-partially-staged-file.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-035-one-write-decision-and-one-json-document.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-036-a-writer-that-writes-says-so-and-the-instructions-naming-it-move-with-it.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-037-unchanged-means-writing-would-not-change-a-byte.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-038-the-gate-filter-belongs-to-every-manifest-writer.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-039-a-ci-step-runs-a-form-that-can-fail.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-040-the-last-writer-that-wrote-by-default-was-not-the-one-named.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-041-the-suite-installs-the-package-in-order-to-test-it.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-042-a-declared-glob-must-match-a-path-built-from-it.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-043-a-keyword-is-a-phrase-and-two-letters-is-a-word.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-044-compatibility-is-not-evidence.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-045-a-dashboard-that-counts-a-defect.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-046-one-rule-one-copy.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-047-a-profile-selects-on-what-a-repository-runs-on.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-048-a-baseline-carries-only-keys-a-reader-honours.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-049-a-ruling-that-a-later-record-moved-says-so-where-it-is-printed.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-050-a-byte-count-is-not-a-region-and-updated-is-not-a-change-of-rules.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-051-a-pointer-is-the-readers-only-route-so-it-is-not-a-convenience.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-052-a-dependency-is-counted-against-the-budget-and-there-is-one-budget.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-053-the-node-floor-is-22-20-0.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-054-the-digest-covers-every-byte-that-leaves-the-package.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-055-a-status-line-travels-so-it-may-not-name-a-location.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-056-three-names-one-of-which-is-cheap-to-move.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-057-an-identity-is-per-developer-and-a-repository-does-not-own-it.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-058-one-tool-three-channels-and-the-order-is-forced.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-059-the-version-a-repository-runs-is-the-one-it-pinned.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-060-a-repository-with-nothing-to-run-is-adopted-and-says-so.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-061-the-skill-registry-is-workspace-data.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-062-a-fresh-adoption-seeds-the-gates-it-can-run.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-063-the-adoption-escape-hatch-is-opt-in.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-064-the-context-meter-counts-what-the-tool-wrote.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-065-a-pack-is-one-shared-rule-set-pinned-by-digest.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-066-a-monorepo-projects-once-per-package.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-067-which-harnesses-read-agents-md-is-a-column.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-068-the-mcp-revision-list-cites-what-was-read.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-069-the-conformance-lint-checks-the-published-specification.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-070-the-json-payload-carries-its-own-version.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-071-a-rule-that-can-be-narrowed-is-written-narrow.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-072-the-budget-is-a-declaration-beside-the-gates.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/ADR-073-a-kernel-is-a-smaller-projection-the-repository-asks-for.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/docs/decisions/README.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/python/simt_dev/__init__.py +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/python/simt_dev/cli.py +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/core.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/mdc/intake-questions.mdc +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/mdc/preview-postflight.mdc +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/mdc/slice-commit.mdc +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/mdc/test-gate.mdc +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/android.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/cloudflare-workers.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/connectiq.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/container.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/dart.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/deno.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/dotnet.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/elixir.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/go.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/jvm.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/node.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/python.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/react-native.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/react-web.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/ruby.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/rust.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/swift.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/typescript.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/rules/stacks/uv.md +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/ci/dependabot.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/ci/workflow.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/commands/ci.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/commands/compare.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/commands/graph.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/commands/hooks.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/commands/init.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/commands/mcp.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/commands/rules.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/commands/skills.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/commands/skillsinstall.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/commands/sync.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/commands/upgrade.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/compare/discover.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/compare/hooksstate.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/compare/row.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/graph/load.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/graph/spec.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/graph/speccheck.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/hooks/capability.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/hooks/dispatcher.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/hooks/gates.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/hooks/resolve.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/hooks/shim.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/hooks/where.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/identity.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/locate.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/mcp/schema.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/monorepo.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/name.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/output/index.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/package-version.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/packs.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/projection/baselines.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/projection/conflicts.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/projection/markers.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/projection/mdc.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/projection/project.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/projection/targets.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/resolve/eval.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/resolve/fingerprint.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/resolve/near.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/resolve/resolve.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/resolve/source.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/toolchain.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/tsconfig.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/upgrade/plan.mjs +0 -0
- {simt_dev-0.2.2 → simt_dev-0.3.0}/src/workspace.mjs +0 -0
|
@@ -7,4 +7,10 @@
|
|
|
7
7
|
git.config
|
|
8
8
|
|
|
9
9
|
.pybuild/
|
|
10
|
-
dist/
|
|
10
|
+
dist/
|
|
11
|
+
|
|
12
|
+
# Local index, evidence ledger and benchmark run outputs (plan 0003 §4).
|
|
13
|
+
# Task descriptors in .simt-dev/bench/tasks/*.json are committed; runs are not.
|
|
14
|
+
.simt-dev/index.sqlite
|
|
15
|
+
.simt-dev/ledger.jsonl
|
|
16
|
+
.simt-dev/bench/runs/
|
|
@@ -6,6 +6,42 @@ All notable changes to this package are recorded here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.3.0] — 2026-10-17
|
|
10
|
+
|
|
11
|
+
### The rules and the decisions are readable as MCP resources
|
|
12
|
+
|
|
13
|
+
A client that wants to browse this tool's rules and rulings had no way to: every answer came back from a tool call with an argument in it. They are addressable now, as one URI per rule and one per decision record, with the byte size each will cost stated up front — the one number a client cannot get without spending the read.
|
|
14
|
+
|
|
15
|
+
Both resource revisions of the specification were read rather than recalled, and they disagree about the behaviour that decides whether a client retries or gives up: a missing resource is `-32602` on the newest revision and `-32002` on the two older ones, and neither lets a server answer with an empty body. A decision record is redacted on the way out, because a resource travels further than the CLI did (ADR-074).
|
|
16
|
+
|
|
17
|
+
### A plan is resumed one slice at a time
|
|
18
|
+
|
|
19
|
+
`simt plan next` returns the next ready slice and only its section. `simt plan done` rewrites that one row, and previews the change unless `--yes` is given. The directories and the table format come from the `plans` key in `simt.json` when a repository sets one; otherwise the tracker template delivered with the tool is used, which reads `docs/plans` and `docs/reviews` (ADR-081, ADR-082). `init` keeps a manifest key it does not write, which is what lets `plans` survive a re-init.
|
|
20
|
+
|
|
21
|
+
### The rules are enforced at the tool call
|
|
22
|
+
|
|
23
|
+
Three rules that text does not hold — a `git push`, a `--no-verify`, an edit inside a generated region — are now a decision before the tool call. `simt agent-hooks install` writes one policy into the harnesses that read a hooks file, and keeps every key it does not own. `simt agent-hook` is the entry point those harnesses call (ADR-079).
|
|
24
|
+
|
|
25
|
+
### A line the repository already proves does not ship
|
|
26
|
+
|
|
27
|
+
A rule line may say when the repository already proves it. `simt sync` drops that line, and `--explain` names the line and the fact, so a removal is visible rather than silent (ADR-078).
|
|
28
|
+
|
|
29
|
+
### The region leads with this repository's commands
|
|
30
|
+
|
|
31
|
+
The projected region opens with the commands this repository actually runs, derived from its committed gates and runner, in both the full projection and kernel mode (ADR-077).
|
|
32
|
+
|
|
33
|
+
### A change to what an agent reads can be measured
|
|
34
|
+
|
|
35
|
+
`simt bench mine`, `run`, `report`, `ablate` and `probes` measure a change to projected context against tasks taken from this repository's own history. A change that cannot be run says `unmeasured` in its record rather than implying a result (ADR-076).
|
|
36
|
+
|
|
37
|
+
### What each reader loads, and a transcript split
|
|
38
|
+
|
|
39
|
+
`simt harness loaders` reports what each reader loads at session start, in bytes, and what its size cap drops. DeepSeek is one of those readers. `simt tokens --session` splits a local Claude Code or Codex transcript into rules, file reads and tool output.
|
|
40
|
+
|
|
41
|
+
### A name this tool owns is not reported as a repository
|
|
42
|
+
|
|
43
|
+
`simt rules why` keeps this tool's own names (`simt-priority`, `simt-hooks`, and the rest) and still redacts a repository the reader cannot open (ADR-080).
|
|
44
|
+
|
|
9
45
|
## [0.2.2] — 2026-10-14
|
|
10
46
|
|
|
11
47
|
### A repository can ask for a smaller projection
|
|
@@ -527,6 +563,7 @@ never ran `simt hooks install` again will find nothing until the dependency is r
|
|
|
527
563
|
and `simt hooks install --yes` is re-run. That is a real upgrade step and it is called out
|
|
528
564
|
here rather than discovered.
|
|
529
565
|
|
|
566
|
+
[0.3.0]: https://github.com/QuazarMedia/simt-dev/releases/tag/v0.3.0
|
|
530
567
|
[0.2.2]: https://github.com/QuazarMedia/simt-dev/releases/tag/v0.2.2
|
|
531
568
|
[0.2.1]: https://github.com/QuazarMedia/simt-dev/releases/tag/v0.2.1
|
|
532
569
|
[0.2.0]: https://github.com/QuazarMedia/simt-dev/releases/tag/v0.2.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: simt-dev
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Shared agent rules, skills and git hooks for a repository: one command adopts a repo, and every gate it declares is probed before it is written.
|
|
5
5
|
Project-URL: Homepage, https://github.com/QuazarMedia/simt-dev
|
|
6
6
|
Project-URL: Repository, https://github.com/QuazarMedia/simt-dev
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// simt-dev - developer and agent tooling for the SIMT ecosystem.
|
|
3
|
+
//
|
|
4
|
+
// POSIX only (ADR-012). package.json declares os: [darwin, linux], so npm refuses
|
|
5
|
+
// the install elsewhere rather than letting a hook fail obscurely.
|
|
6
|
+
|
|
7
|
+
import { parse } from '../src/argv.mjs';
|
|
8
|
+
import { EXIT, fail, jsonFailMode, jsonIndentDefault } from '../src/output/index.mjs';
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
const argv = process.argv.slice(2);
|
|
12
|
+
const parsed = parse(argv);
|
|
13
|
+
if (!parsed.ok) {
|
|
14
|
+
process.exit(parsed.code);
|
|
15
|
+
}
|
|
16
|
+
const { flags, positional } = parsed.value;
|
|
17
|
+
|
|
18
|
+
// No arguments at all is a usage error, not a silent help dump: an agent that
|
|
19
|
+
// ran the wrong thing should be told so rather than handed 40 lines of prose.
|
|
20
|
+
if (positional.length === 0 && !flags.help && !flags.version) {
|
|
21
|
+
process.exit(fail('no command given', EXIT.USAGE));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
jsonIndentDefault(flags.pretty === true);
|
|
25
|
+
jsonFailMode(flags.json === true);
|
|
26
|
+
|
|
27
|
+
// The one command that runs on somebody else's hot path, and therefore the one that
|
|
28
|
+
// does not load the registry. `agent-hook` is called before every tool call an agent
|
|
29
|
+
// makes, so its latency is a product requirement rather than a nicety (plan 0003
|
|
30
|
+
// R15), and the registry's imports - detection, projection, the bench corpus - cost
|
|
31
|
+
// tens of milliseconds before the command itself starts. Measured on the machine
|
|
32
|
+
// this was written on: 127.7 ms through the registry against 91.5 ms with only this
|
|
33
|
+
// module's imports, where the bare runtime is 86.9 ms of it.
|
|
34
|
+
//
|
|
35
|
+
// Only the exact spelling the renderers write takes this path. Anything else -
|
|
36
|
+
// including `agent-hook --help` - loads the registry, so help stays the one list of
|
|
37
|
+
// every command and this shortcut cannot become a second, thinner command surface.
|
|
38
|
+
if (positional[0] === 'agent-hook' && !flags.help && !flags.version) {
|
|
39
|
+
const { agentHookCommand } = await import('../src/commands/agenthook.mjs');
|
|
40
|
+
process.exit((await agentHookCommand(positional.slice(1), flags)) ?? EXIT.OK);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const { dispatch } = await import('../src/commands/index.mjs');
|
|
44
|
+
process.exit((await dispatch(argv)) ?? EXIT.OK);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
process.exit(fail(error?.message ?? String(error), EXIT.FAIL));
|
|
47
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# ADR-074 — A rule and a decision are addressable, so they are readable by URI
|
|
2
|
+
|
|
3
|
+
Status: **accepted** · 2026-10-14 · filed as S43
|
|
4
|
+
**Affects:** `src/mcp/resources.mjs`, `src/mcp/server.mjs`, `test/mcp.test.mjs`
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
Review 0002 filed that the MCP server is two protocol revisions behind and returns text
|
|
9
|
+
only. ADR-068 closed the revision half and every tool now declares an output schema and
|
|
10
|
+
annotations. What remained was the other half of the finding: the server has no
|
|
11
|
+
**resources**, so the two things this tool is actually authoritative about — the rules it
|
|
12
|
+
projects and the decisions it settles — are reachable only through a tool call with an
|
|
13
|
+
argument in it.
|
|
14
|
+
|
|
15
|
+
That matters for a client that wants to browse rather than query. A tool call asks a
|
|
16
|
+
question and gets an answer; a resource is something a client can list, show in a picker,
|
|
17
|
+
attach to a context window and re-read on demand. The CLI already answers both by id
|
|
18
|
+
(`rules show`, `rules why`); what was missing was the addressable form.
|
|
19
|
+
|
|
20
|
+
So the specification was fetched and read for both revisions rather than recalled, and it
|
|
21
|
+
turned out the two disagree in a way that decides an observable behaviour: **a missing
|
|
22
|
+
resource is `-32602` (Invalid Params) in 2026-07-28 and `-32002` (Resource not found) in
|
|
23
|
+
2025-06-18.** 2026-07-28 keeps `-32002` only as something a *client* should still accept.
|
|
24
|
+
Both revisions forbid an empty `contents` array for a resource that does not exist, because
|
|
25
|
+
empty is ambiguous — it reads as "here is a resource with no body".
|
|
26
|
+
|
|
27
|
+
Both revisions also require the capability to be declared, and both permit the empty
|
|
28
|
+
object for a server with no subscriptions and no change notifications. The newer one adds
|
|
29
|
+
`ttlMs` and `cacheScope` to resource results, which is why a resource list is cacheable on
|
|
30
|
+
the newest revision and is a bare list on the two older ones — the same rule ADR-068
|
|
31
|
+
already applies to tools.
|
|
32
|
+
|
|
33
|
+
## Rulings
|
|
34
|
+
|
|
35
|
+
1. **Two collections and no others: the rules and the decisions.**
|
|
36
|
+
`simt://rules/{id}` and `simt://decisions/{adr}`. A resource set that grew with the
|
|
37
|
+
registry would be a second index to keep honest, and the registry is workspace data
|
|
38
|
+
(ADR-061) — the package ships none of it, so a client browsing this server in one
|
|
39
|
+
repository and another would see different sets anyway.
|
|
40
|
+
|
|
41
|
+
2. **The capability is declared unconditionally, as an empty object.** Every rule and every
|
|
42
|
+
decision record ships with the package, so there is always something to read; and
|
|
43
|
+
`{}` is the documented way to say "no subscriptions, no change notifications", which
|
|
44
|
+
are the two things this server has no way to honour. The previous code gated the
|
|
45
|
+
capability on a property hung on the tools array that nothing ever set — a promise a
|
|
46
|
+
client waits on forever, only quieter.
|
|
47
|
+
|
|
48
|
+
3. **A missing resource is an error, and the code is the revision's own.** `-32602` from
|
|
49
|
+
2026-07-28, `-32002` from the two older revisions, and never an empty `contents`. A
|
|
50
|
+
client that reads a URI and gets silence cannot tell a bug from an empty rule, and the
|
|
51
|
+
two revisions disagree about which code that silence should wear.
|
|
52
|
+
|
|
53
|
+
4. **Every listed resource carries the bytes it will cost.** `size` is in the specification
|
|
54
|
+
and it is the one number a client cannot get without reading: an agent assembling a
|
|
55
|
+
context window needs to know what a resource costs before it spends it. This is the
|
|
56
|
+
same argument as `simt tokens`, arriving at a different surface.
|
|
57
|
+
|
|
58
|
+
5. **The frontmatter is rebuilt, unprefixed, and the body's own heading is not repeated.**
|
|
59
|
+
A rule on disk opens with frontmatter this tool's namespace owns (`simt-`); a resource
|
|
60
|
+
is read by a client that knows nothing about that namespace, so the identity is
|
|
61
|
+
reconstructed under plain keys. The loader no longer carries the H1, so the title lives
|
|
62
|
+
in the frontmatter rather than being re-added by hand in two places.
|
|
63
|
+
|
|
64
|
+
6. **A decision body is redacted on the way out.** `redactInternalPaths(redactEstate(...))`,
|
|
65
|
+
the same pass the CLI applies. A resource is readable by anyone holding the connection,
|
|
66
|
+
which is a wider audience than the repository the CLI is aimed at, and a record whose
|
|
67
|
+
argument names an estate repository should not travel further just because it became
|
|
68
|
+
addressable.
|
|
69
|
+
|
|
70
|
+
7. **Every URI is validated, and a rules id cannot contain a slash.** Custom schemes are
|
|
71
|
+
allowed, which is precisely why the server checks: a URI naming another scheme, a
|
|
72
|
+
`..` segment, an empty id or a nested path is refused with the same revision-correct
|
|
73
|
+
error as one that simply does not exist. A refusal that is distinguishable from a miss
|
|
74
|
+
is a way to probe the filesystem.
|
|
75
|
+
|
|
76
|
+
## Consequences
|
|
77
|
+
|
|
78
|
+
`resources/list` answers 97 entries in this checkout — 20 rules, the process rules, and 73
|
|
79
|
+
decision records — and a client can attach any of them without a tool call. The templates
|
|
80
|
+
list publishes the two shapes, so a client can build the URI for an id it has not listed
|
|
81
|
+
yet.
|
|
82
|
+
|
|
83
|
+
What this does not do: subscribe to a rule changing, because there is no stream to
|
|
84
|
+
subscribe to and the capability says so. That is a feature, not an omission — a client
|
|
85
|
+
that believes it is subscribed to a projection that only changes on `sync` would be
|
|
86
|
+
waiting for an event this tool will never emit.
|
|
87
|
+
|
|
88
|
+
## Rejected
|
|
89
|
+
|
|
90
|
+
- **Serving resources only through tool calls.** That is what the server already did, and
|
|
91
|
+
the finding is that a client cannot browse what it can only ask about.
|
|
92
|
+
- **An empty `contents` array for a URI that does not exist.** Both revisions treat it as
|
|
93
|
+
ambiguous, and ambiguity here is what makes a client retry forever.
|
|
94
|
+
- **Exposing the registry as resources too.** It is workspace data and this package ships
|
|
95
|
+
none of it (ADR-061); a resource list that differed per repository would be the
|
|
96
|
+
same definition-of-one-thing-twice defect, one layer up.
|
|
97
|
+
- **One error code for all three revisions.** `-32602` on the older two would be a code
|
|
98
|
+
that revision never defined, and `-32002` on the newest would be advice to clients
|
|
99
|
+
rather than the specification's own answer.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# ADR-075 — Nothing leaves the machine: no telemetry, local transcripts, loopback models by default
|
|
2
|
+
|
|
3
|
+
Status: **accepted** · 2026-10-14 · filed as D7 (R06)
|
|
4
|
+
**Affects:** `src/measure/session.mjs`, `src/measure/context.mjs`, `src/commands/tokens.mjs`, `src/argv.mjs`, `test/tokens.test.mjs`
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
The context meter (`simt tokens`) now goes beyond static repository files to inspect
|
|
9
|
+
recorded agent transcripts (`simt tokens --session <path>`), and later slices in the
|
|
10
|
+
research programme connect optional local model servers for embeddings, distillation and
|
|
11
|
+
pre-review critique.
|
|
12
|
+
|
|
13
|
+
Session transcripts are among the most sensitive files on a developer's machine: they hold
|
|
14
|
+
every file an agent read, every command output it saw, uncommitted diffs, environment
|
|
15
|
+
diagnostics and prompts written in the middle of debugging. A tool that fetched remote
|
|
16
|
+
session URLs, phoned home usage metrics, or defaulted model calls to a hosted endpoint
|
|
17
|
+
would turn a local measurement command into an exfiltration surface.
|
|
18
|
+
|
|
19
|
+
## Rulings
|
|
20
|
+
|
|
21
|
+
1. **No command emits telemetry, analytics or background network traffic.** Every command
|
|
22
|
+
operates over the local filesystem and stdio alone unless the user explicitly invokes a
|
|
23
|
+
documented network flag in a later adapter.
|
|
24
|
+
|
|
25
|
+
2. **`simt tokens --session <path>` accepts local filesystem paths only and refuses URLs.**
|
|
26
|
+
Any argument carrying a URI scheme (`http://`, `https://`, `ws://`, `ssh://` or any
|
|
27
|
+
`<scheme>://`) is rejected at argument validation with a configuration exit code and a
|
|
28
|
+
remedy naming a local file path, before any socket or filesystem read is attempted.
|
|
29
|
+
|
|
30
|
+
3. **Session attribution is computed deterministically in process with zero dependencies.**
|
|
31
|
+
Transcript JSON and JSONL records from Claude Code and Codex are split into `rules`
|
|
32
|
+
(system instructions, inline instruction blocks, and reads of instruction, rule or skill
|
|
33
|
+
files), `fileReads` (reads of repository source and config files) and `toolOutput`
|
|
34
|
+
(command and tool execution results) by inspecting the local file alone.
|
|
35
|
+
|
|
36
|
+
4. **Future local-model adapters default to loopback (`127.0.0.1` / `localhost`) and refuse
|
|
37
|
+
remote hosts unless explicitly overridden.** When no local model is configured in
|
|
38
|
+
`simt-dev.json`, no socket is opened at all.
|
|
39
|
+
|
|
40
|
+
## Consequences
|
|
41
|
+
|
|
42
|
+
`simt tokens --session <path>` can be run safely on production incident transcripts and
|
|
43
|
+
private repositories because the parser cannot open a network connection. And coupling the
|
|
44
|
+
static meter to the harness loader table (`R14`) means `simt tokens` now counts what each
|
|
45
|
+
reader actually loads at session start — flat `.agents/rules/` scans for Antigravity,
|
|
46
|
+
`alwaysApply: true` for Cursor, `@path` imports for Claude Code, and root-to-cwd chain
|
|
47
|
+
caps for Codex — without leaving the machine.
|
|
48
|
+
|
|
49
|
+
## Rejected
|
|
50
|
+
|
|
51
|
+
- **Fetching remote session URLs or cloud share links in `simt tokens --session`.** Convenience
|
|
52
|
+
for a shared link is also an outbound request from a tool whose contract is that it
|
|
53
|
+
only reads local state.
|
|
54
|
+
- **Anonymous opt-out telemetry for context budget numbers.** Even aggregate byte counts
|
|
55
|
+
reveal repository names, adoption state and working hours, and an opt-out flag still
|
|
56
|
+
ships a network client in the default path.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# ADR-076 — A change to what agents read is measured before it ships, or labelled unmeasured in its record
|
|
2
|
+
|
|
3
|
+
Status: **accepted** · 2026-10-15 · filed as D1 (R01)
|
|
4
|
+
**Affects:** `src/bench/mine.mjs`, `src/commands/bench.mjs`, `src/commands/index.mjs`, `src/commands/help.mjs`, `test/bench.test.mjs`
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
Every rule and profile projected by this package enters an agent's context window on every
|
|
9
|
+
turn, yet nothing in the repository could say whether a paragraph improved resolution,
|
|
10
|
+
increased token cost, or did neither. Controlled studies on repository context files show
|
|
11
|
+
that unmeasured instructions routinely raise inference cost by 20% or more without moving
|
|
12
|
+
task resolution when they repeat facts the repository already proves.
|
|
13
|
+
|
|
14
|
+
Without a repository-native task suite and a rule requiring evidence, changes to projected
|
|
15
|
+
context are judged by how plausible the prose sounds to a reviewer rather than by what an
|
|
16
|
+
agent does with it. And a task suite whose verification tests sit inside the agent's
|
|
17
|
+
worktree is trivial to game: an agent can read or weaken the test it is being graded by.
|
|
18
|
+
|
|
19
|
+
## Rulings
|
|
20
|
+
|
|
21
|
+
1. **A change to projected context is measured against the benchmark suite before it ships,
|
|
22
|
+
or its decision record states `unmeasured` and why.** Context changes include core
|
|
23
|
+
rules, stack profiles, process rules, kernel compilation, command cards and brief
|
|
24
|
+
assembly. When a slice cannot be run through the benchmark (for example, before the
|
|
25
|
+
runner is wired or when a rule governs an external release gate), the decision record
|
|
26
|
+
must carry the explicit label `unmeasured` rather than implying an empirical win.
|
|
27
|
+
|
|
28
|
+
2. **Benchmark tasks are mined deterministically from non-merge git history.** `simt bench mine`
|
|
29
|
+
walks non-merge commits with a parent, selects commits that modify both test paths and
|
|
30
|
+
implementation paths, splits each commit into `test.patch` (test files) and `gold.patch`
|
|
31
|
+
(implementation files), and assigns the deterministic identifier `t-<shortSha>-01`.
|
|
32
|
+
|
|
33
|
+
3. **Every mined task is validated twice in an isolated worktree before acceptance.** At
|
|
34
|
+
the parent commit `BASE`:
|
|
35
|
+
- `BASE` plus `test.patch` must fail (`RED`) on two consecutive runs with the same
|
|
36
|
+
failing and passing test identifiers;
|
|
37
|
+
- `BASE` plus `test.patch` plus `gold.patch` must pass (`GOLD`) on two consecutive runs
|
|
38
|
+
with zero failing tests and the same passing test identifiers;
|
|
39
|
+
- any commit whose test outcome differs between the two runs is discarded as flaky.
|
|
40
|
+
|
|
41
|
+
4. **Test identifiers are extracted from runner-native machine output, never from human
|
|
42
|
+
console summaries.** The miner parses TAP (`node --test --test-reporter=tap`), Vitest
|
|
43
|
+
JSON (`--reporter=json`), JUnit XML (Gradle, Maven and `pytest --junitxml`) and Go JSON
|
|
44
|
+
event streams (`go test -json`) to record exact `f2p` (`FAIL_TO_PASS`) and `p2p`
|
|
45
|
+
(`PASS_TO_PASS`) test identifiers.
|
|
46
|
+
|
|
47
|
+
5. **Hidden test patches live in a verifier vault outside every worktree.** Task metadata
|
|
48
|
+
is written to the adopting repository's benchmark task directory so the suite
|
|
49
|
+
membership is versioned and reviewable, while `test.patch` and `gold.patch` are written
|
|
50
|
+
to the user's cache vault (`~/.cache/simt-dev/vault/<repo-id>/<id>/`, or the platform
|
|
51
|
+
cache equivalent) so an agent running inside a task workspace cannot inspect the
|
|
52
|
+
verifier test diff or the oracle fix.
|
|
53
|
+
|
|
54
|
+
## Consequences
|
|
55
|
+
|
|
56
|
+
`simt bench mine --yes` mines a deterministic, flake-filtered task suite from a
|
|
57
|
+
repository's own commits without network access or model calls. Re-running the miner over
|
|
58
|
+
the same commit history produces byte-identical task JSON files and vault patches.
|
|
59
|
+
|
|
60
|
+
## Rejected
|
|
61
|
+
|
|
62
|
+
- **Keeping `test.patch` inside the repository's committed task directory.** An agent
|
|
63
|
+
evaluated in a checkout of the repository could read the hidden test expectations or the
|
|
64
|
+
oracle patch directly from disk.
|
|
65
|
+
- **Accepting any commit that touches a test file without running `RED` and `GOLD` twice.**
|
|
66
|
+
Refactors, formatting commits and flaky tests touch test files without failing on `BASE`,
|
|
67
|
+
producing tasks where a no-op agent scores 100% or a valid fix fails at random.
|
|
68
|
+
- **Scraping human-formatted test summaries with regular expressions.** Console summaries
|
|
69
|
+
vary by locale, terminal width and runner version, and do not name individual
|
|
70
|
+
`FAIL_TO_PASS` test cases needed to grade partial regressions.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# ADR-077 — The command card leads the region, and is derived from committed evidence only
|
|
2
|
+
|
|
3
|
+
Status: **accepted** · 2026-10-16 · filed as R10 (plan 0003)
|
|
4
|
+
**Affects:** `src/kernel/card.mjs`, `src/projection/rules.mjs`, `rules/core.md` (indirectly, as
|
|
5
|
+
the region's first bytes), `test/card.test.mjs`
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
Plan 0003 R10 asks for the highest-value, non-inferable bytes: the exact commands for *this*
|
|
10
|
+
repository, at the top of the region, in a block of at most 600 B, "derived from gates and
|
|
11
|
+
runner detection alone, so it needs no index". A reader who has the rules has the same rules
|
|
12
|
+
every other repository has; what they cannot infer is that *their* tests run under
|
|
13
|
+
`./gradlew :app:testDebugUnitTest` and not `npm test`.
|
|
14
|
+
|
|
15
|
+
Two things the plan leaves open, and both are the kind an implementer gets wrong once:
|
|
16
|
+
|
|
17
|
+
1. **Which modes carry the card.** R07's kernel is a smaller projection a repository asks
|
|
18
|
+
for (ADR-073), and R10 says "at the top of the kernel". Read literally, the card would
|
|
19
|
+
appear only for the repositories that opted into kernel mode — that is, only for the
|
|
20
|
+
readers who already measured that they can do without guidance. The reader who kept
|
|
21
|
+
`full` is the one who has the commands nowhere.
|
|
22
|
+
|
|
23
|
+
2. **What evidence the card may read.** "Runner detection" has two possible meanings here.
|
|
24
|
+
`readCapability` answers "can this machine run it" by probing PATH and `node_modules`,
|
|
25
|
+
and that answer is machine-specific. But the projected region is required to be
|
|
26
|
+
byte-identical on two machines (plan 0003 P4 and R13): the whole reason the tool has no
|
|
27
|
+
model and no network is that a pull request can meaningfully diff a projection. A card
|
|
28
|
+
that named whichever linter happened to be installed would differ between a laptop and
|
|
29
|
+
CI for no reason a diff could explain, and `check` would flake on a clean tree.
|
|
30
|
+
|
|
31
|
+
## Rulings
|
|
32
|
+
|
|
33
|
+
1. **The card leads the region in both modes.** `full` and `kernel` differ in which *rules*
|
|
34
|
+
are packed (ADR-073 ruling 5); neither withholds the commands. The card is bytes the
|
|
35
|
+
reader most needs and the rules never carry, so it is above even the core, and it is not
|
|
36
|
+
a rule the kernel can defer.
|
|
37
|
+
|
|
38
|
+
2. **It is derived from committed evidence only.** Three sources, in precedence order: the
|
|
39
|
+
manifest's declared `gates.commands`, the repository's own `package.json` scripts, and
|
|
40
|
+
the marker facts that name its ecosystem. It never reads PATH or `node_modules`.
|
|
41
|
+
Runnability is a property of the machine; a command is a property of the repository, and
|
|
42
|
+
only the second belongs in bytes that leave it.
|
|
43
|
+
|
|
44
|
+
3. **The ecosystem table is the single source, and the gate list cannot disagree with it.**
|
|
45
|
+
The fallback for a marker that has no declared command is the same `ECOSYSTEMS` table
|
|
46
|
+
`manifest.mjs` seeds gates from. Two tables would eventually name two different test
|
|
47
|
+
commands for one repository, which is the drift this tool exists to remove. Python is the
|
|
48
|
+
one ecosystem the table does not seed, because its runner varies (uv, poetry, tox, nox); the
|
|
49
|
+
card still names the command a committed lockfile proves — `uv run -m pytest`, never
|
|
50
|
+
`uv run pytest`, because the uv profile is explicit that the console entrypoint can run a
|
|
51
|
+
different copy of the package than the one under test.
|
|
52
|
+
|
|
53
|
+
4. **A template is labelled as a template, per path kind.** The focused-test entries carry
|
|
54
|
+
`{file}`, `{pkg}`, `{Test}` and `{class}` placeholders and are labelled by the kind of
|
|
55
|
+
path they apply to, so a reader never pastes a brace into a shell. Which test a given
|
|
56
|
+
`{file}` maps to is R24's refinement, not R10's.
|
|
57
|
+
|
|
58
|
+
5. **The ceiling is 600 B, enforced by dropping whole lines, never silently.** Lines drop in
|
|
59
|
+
a stated order — `format`, `typecheck`, `lint`, `build`, then focused templates from the
|
|
60
|
+
last — and `test` is never among them, because a card that dropped the test command would
|
|
61
|
+
have dropped the command it exists to carry. Every drop is named in the projection notes;
|
|
62
|
+
a card that lost a command in silence is a card the reader cannot tell is incomplete.
|
|
63
|
+
|
|
64
|
+
6. **It is computed in `desiredRegion`, the one place the region is computed.** `plan` and
|
|
65
|
+
`checkTarget` therefore cannot hold two opinions about the same card, which is the same
|
|
66
|
+
property that keeps a clean tree from reporting drift (the comment on `desiredRegion`).
|
|
67
|
+
|
|
68
|
+
## Consequences
|
|
69
|
+
|
|
70
|
+
Every adopted repository's region gains the card on the next `sync`, in both modes. That is
|
|
71
|
+
the point of the slice: the bytes were absent everywhere, and the ones added are the ones a
|
|
72
|
+
reader can act on. The card is derived, so it moves only when the repository's own commands
|
|
73
|
+
move — a new `package.json` script, a declared command, or a marker file appearing.
|
|
74
|
+
|
|
75
|
+
What is not here: which test a `{file}` should be mapped to (R24), the inferability filter
|
|
76
|
+
that would drop a card line the repository already states (R09), and the cost measurement
|
|
77
|
+
that would say whether the card earns its bytes (R02, R27). This ruling is what makes those
|
|
78
|
+
measurable rather than what concludes them.
|
|
79
|
+
|
|
80
|
+
## Rejected
|
|
81
|
+
|
|
82
|
+
- **Kernel mode only.** It withholds the card from the readers who kept the larger
|
|
83
|
+
projection, which is all of them until R02 has run.
|
|
84
|
+
- **Probing PATH or `node_modules`** so the card shows only commands that will run here. The
|
|
85
|
+
answer would not survive a second machine, and the region is required to.
|
|
86
|
+
- **Writing the commands as rule text.** The commands are data about one repository; a rule
|
|
87
|
+
is the same in every repository, and a rule that stated one repository's test command would
|
|
88
|
+
be wrong in every other.
|
|
89
|
+
- **Letting the card grow past 600 B, or trimming it silently.** An unbounded card is a
|
|
90
|
+
second copy of the rules, and a silently short one is a reader who trusts a card that is
|
|
91
|
+
missing a command.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# ADR-078 — A line the repository already proves does not ship, and the author says so
|
|
2
|
+
|
|
3
|
+
Status: **accepted** · 2026-10-16 · filed as R09 (plan 0003)
|
|
4
|
+
**Affects:** `src/kernel/inferability.mjs`, `src/projection/rules.mjs`, `src/kernel/card.mjs`
|
|
5
|
+
(the verb vocabulary), `src/argv.mjs`, `src/commands/help.mjs`, `test/inferability.test.mjs`,
|
|
6
|
+
`test/shipped.test.mjs` (the estate-name guard's allowlist of the tool's own words)
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
Plan 0003 R09 asks for an inferability filter: a rule line may declare
|
|
11
|
+
`simt-inferable-when: <fact expression>`, and when the repository already proves the
|
|
12
|
+
expression the line is dropped — "use `./gradlew`" when the wrapper is the only runner and
|
|
13
|
+
the card names it, "use pnpm" when only `pnpm-lock.yaml` exists. The basis is that content
|
|
14
|
+
the repository already states does not help its reader.
|
|
15
|
+
|
|
16
|
+
ADR-077 built the card that names this repository's commands and left R09 open as the filter
|
|
17
|
+
"that would drop a card line the repository already states". What the plan leaves open is
|
|
18
|
+
the part that decides whether the mechanism is usable or a trap:
|
|
19
|
+
|
|
20
|
+
1. **Who may drop a line.** An inferability filter that guesses is a filter that deletes
|
|
21
|
+
rules a reader needed. "The repository has a `.editorconfig`, so the indentation rule is
|
|
22
|
+
inferable" is exactly the reasoning that is right most of the time and silent when it is
|
|
23
|
+
wrong.
|
|
24
|
+
|
|
25
|
+
2. **What evidence may be read.** The same choice ADR-077 ruling 2 had to make, and the same
|
|
26
|
+
answer applies: the projected region is required to be byte-identical on two machines
|
|
27
|
+
(plan 0003 P4, R13), so evidence read off the machine cannot decide what leaves.
|
|
28
|
+
|
|
29
|
+
3. **What a removal costs the author.** A line that leaves a projection with no trace is the
|
|
30
|
+
mistake ADR-073 rejected for deferred rules. But a `## Dropped` section would spend region
|
|
31
|
+
bytes on lines the reader is being told not to read, which is the opposite of the slice's
|
|
32
|
+
purpose.
|
|
33
|
+
|
|
34
|
+
## Rulings
|
|
35
|
+
|
|
36
|
+
1. **A line leaves only when its author says it may.** The mechanism is opt-in per block, by
|
|
37
|
+
a marker the rule author writes — `<!-- simt-inferable-when: <expression> -->`. Nothing is
|
|
38
|
+
dropped by inference alone. The tool checks a claim; it does not make one.
|
|
39
|
+
|
|
40
|
+
2. **The unit is the blank-line-delimited block, and the marker never reaches the region.**
|
|
41
|
+
A wrapped bullet is marked once and leaves whole, rather than leaving half a sentence
|
|
42
|
+
behind. The comment is stripped from the region whether or not the line is dropped:
|
|
43
|
+
`simt-` vocabulary is for the rule's author, not for its reader.
|
|
44
|
+
|
|
45
|
+
3. **The expression is a conjunction of positive terms over a closed vocabulary.** A term is
|
|
46
|
+
a fact or stack tag in `KNOWN_TAGS`, a `card:<verb>` for one of the card's five verbs, or
|
|
47
|
+
a `gate:<name>` the repository declares. There is no negation: every reason a line is
|
|
48
|
+
redundant is a positive proof the repository offers, and a grammar for a case nobody has
|
|
49
|
+
is a grammar nobody can be taught. A term outside the vocabulary is a defect, reported
|
|
50
|
+
through the same field as a broken frontmatter key, so `check` and `rules list` need no
|
|
51
|
+
second path to a broken rule.
|
|
52
|
+
|
|
53
|
+
4. **The proofs are committed bytes only.** The repository's own facts and stack, the gates
|
|
54
|
+
its manifest declares, and the verbs its card names. Never PATH and never `node_modules`,
|
|
55
|
+
for the reason ADR-077 ruling 2 already settled: a proof read off the machine would make
|
|
56
|
+
the region differ between a laptop and CI for no reason a diff could explain.
|
|
57
|
+
|
|
58
|
+
5. **The filter is about the repository's evidence, not about the mode.** It runs in both
|
|
59
|
+
`full` and `kernel`, for the same reason the card does (ADR-077 ruling 1): inferability is
|
|
60
|
+
a property of what the repository commits, and inferability of the mode would withhold the
|
|
61
|
+
saving from every reader who kept the larger projection.
|
|
62
|
+
|
|
63
|
+
6. **Never silent, and never a heading.** By default a removal is reported as one count in
|
|
64
|
+
the projection notes, with the command that names each one: `--explain` prints every
|
|
65
|
+
removal and the evidence behind it. A count is enough to act on; the per-line detail is
|
|
66
|
+
what an author needs, and a reader is not an author.
|
|
67
|
+
|
|
68
|
+
7. **The vocabulary has one definition.** `card.mjs` exports the five verbs the card can
|
|
69
|
+
name, and the filter validates `card:<verb>` against that same list. A copy of the list in
|
|
70
|
+
the filter would let the card name a verb the filter called unknown.
|
|
71
|
+
|
|
72
|
+
## Consequences
|
|
73
|
+
|
|
74
|
+
The region of a repository whose rules carry no marker does not move a byte: the filter
|
|
75
|
+
returns the body by identity when there is nothing marked, so this ruling cannot drift a
|
|
76
|
+
repository that did not ask for it. Where a marker is written — in a repository's own
|
|
77
|
+
`.simt-dev/profiles`, or in a pack — the marked line leaves the region on the next `sync`,
|
|
78
|
+
and `sync --explain` names it and the evidence.
|
|
79
|
+
|
|
80
|
+
**What has not landed: no shipped rule carries a marker.** `rules/stacks/go.md` states
|
|
81
|
+
"`go build ./...`, `go test ./...` are the entrypoints; `go vet ./...` runs with them" and
|
|
82
|
+
`rules/stacks/uv.md` states "`uv run -m pytest`; **never** `uv run pytest`" — both duplicate a
|
|
83
|
+
card line, and neither is *wholly* inferable, because each also carries a reason the card does
|
|
84
|
+
not state. Dropping them would lose the reason. Marking shipped rule text is therefore a
|
|
85
|
+
content pass with its own blast radius (a change to shipped rule text changes every repository
|
|
86
|
+
at once), not a step of this slice; the mechanism ships first so that pass can be measured.
|
|
87
|
+
|
|
88
|
+
A marker stays visible in `simt rules show <id>`, which prints the rule's own text. That is
|
|
89
|
+
deliberate: it is the author's annotation, and it is the reason a line they can see in the
|
|
90
|
+
file is absent from the region. It is not region text, and it never reaches one.
|
|
91
|
+
|
|
92
|
+
`--explain` is a `sync` flag and not a `check` flag, because `sync` is the command that prints
|
|
93
|
+
projection notes and the preview a reader reads before writing. The JSON payload of `sync`
|
|
94
|
+
does not carry notes, so this adds no contract.
|
|
95
|
+
|
|
96
|
+
One visible oddity, stated because the reader will meet it: `simt rules why ADR-078` prints
|
|
97
|
+
`simt-inferable-when` as a repository this record surveyed, because the decisions reader
|
|
98
|
+
treats every `simt-` word outside its allowlist as one. That is a defect in the reader rather
|
|
99
|
+
than in this ruling — ADR-073 carries the identical one for `simt-priority` — and it is not
|
|
100
|
+
fixed here.
|
|
101
|
+
|
|
102
|
+
## Rejected
|
|
103
|
+
|
|
104
|
+
- **Dropping a line the tool judges inferable without a marker.** It is the failure the slice
|
|
105
|
+
exists to avoid: a rule deleted by a heuristic with no way for the author to see the
|
|
106
|
+
heuristic was wrong.
|
|
107
|
+
- **A marker on every physical line.** A wrapped bullet is one sentence across two lines;
|
|
108
|
+
marking lines would let a removal leave half of one behind.
|
|
109
|
+
- **Negation, parentheses or disjunction in the expression.** No shipped reason for a removal
|
|
110
|
+
is negative, and a grammar with a case nobody uses is a grammar nobody can be taught.
|
|
111
|
+
- **Letting the filter run in `kernel` mode only.** It would withhold a saving from the
|
|
112
|
+
readers who kept the larger projection, which is all of them until R02 has run.
|
|
113
|
+
- **A `## Dropped` section in the region.** It spends bytes on lines the reader is told not
|
|
114
|
+
to read, and it moves the rule set for a reason that is not about the reader.
|
|
115
|
+
- **Marking shipped rules now.** No shipped line is wholly inferable, so it would delete
|
|
116
|
+
rationales to save bytes that the card already saves, and it would change every
|
|
117
|
+
repository's region in a slice about a mechanism.
|