simt-dev 0.7.0 → 0.8.0
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.
- package/CHANGELOG.md +191 -870
- package/README.md +188 -213
- package/bin/simt.mjs +19 -55
- package/docs/decisions/ADR-014-workspace-is-configuration.md +2 -2
- package/docs/decisions/ADR-025-a-baseline-is-a-region-in-a-file-the-repo-owns.md +1 -1
- package/docs/decisions/ADR-026-a-config-without-a-region-is-a-file-the-repo-owns.md +1 -1
- package/docs/decisions/ADR-027-the-one-gitattributes-line-that-is-neither-dangerous-nor-empty.md +1 -1
- package/docs/decisions/ADR-028-a-base-file-is-a-floor-so-the-disagreement-it-cannot-repair-becomes-a-check.md +1 -1
- package/docs/decisions/ADR-029-the-pins-a-repository-declares-are-its-own.md +1 -1
- package/docs/decisions/ADR-030-what-a-plan-does-not-ship-is-a-decision-with-a-record.md +1 -1
- package/docs/decisions/ADR-048-a-baseline-carries-only-keys-a-reader-honours.md +1 -1
- package/docs/decisions/ADR-082-the-tracker-override-is-a-manifest-key.md +1 -1
- package/docs/decisions/ADR-099-the-release-verifies-served-bytes-and-the-formula-mirrors-them.md +1 -1
- package/docs/decisions/ADR-117-the-darwin-release-builds-on-supported-macos-15-runners-and-a-re-run-is-idempotent.md +81 -0
- package/docs/decisions/ADR-118-the-bench-corpus-is-keyed-on-history-is-append-only-and-is-portable-as-a-sealed-document.md +91 -0
- package/docs/decisions/ADR-119-the-environment-variable-points-into-a-workspace-the-repo-declared.md +90 -0
- package/docs/decisions/ADR-120-a-pre-push-whose-tree-is-already-proven-green-skips-the-test-gate-on-that-evidence.md +96 -0
- package/docs/decisions/ADR-122-the-shims-move-into-the-state-directory-and-the-legacy-directory-removes-itself.md +94 -0
- package/docs/decisions/ADR-123-a-surplus-positional-is-not-refused-because-arity-is-not-in-the-source.md +57 -0
- package/docs/decisions/ADR-124-the-manifest-has-a-schema-in-the-tool-and-its-unknown-keys-stay-the-repositorys.md +64 -0
- package/docs/decisions/ADR-125-a-shared-context-belongs-to-a-read-and-a-writer-reads-directly.md +65 -0
- package/docs/decisions/ADR-126-the-mcp-surface-stays-a-reader-so-there-is-no-write-path-to-build.md +68 -0
- package/docs/decisions/ADR-127-the-mcp-tool-list-is-written-by-hand-and-roots-is-not-asked-for.md +65 -0
- package/docs/decisions/ADR-128-a-research-plan-is-a-plan-and-the-tracker-reads-it.md +42 -0
- package/ecosystems/bun.json +6 -0
- package/ecosystems/cargo.json +25 -0
- package/ecosystems/composer.json +6 -0
- package/ecosystems/dart.json +24 -0
- package/ecosystems/deno.json +21 -0
- package/ecosystems/devcontainers.json +6 -0
- package/ecosystems/docker-compose.json +6 -0
- package/ecosystems/docker.json +6 -0
- package/ecosystems/dotnet.json +25 -0
- package/ecosystems/elixir.json +23 -0
- package/ecosystems/gitsubmodule.json +6 -0
- package/ecosystems/go.json +25 -0
- package/ecosystems/gradle.json +13 -0
- package/ecosystems/maven.json +23 -0
- package/ecosystems/node.json +25 -0
- package/ecosystems/python.json +20 -0
- package/ecosystems/ruby.json +23 -0
- package/ecosystems/swift.json +25 -0
- package/ecosystems/terraform.json +6 -0
- package/ecosystems/uv.json +6 -0
- package/harnesses/antigravity.json +162 -0
- package/harnesses/claude.json +206 -0
- package/harnesses/codex.json +136 -0
- package/harnesses/copilot.json +88 -0
- package/harnesses/cursor.json +140 -0
- package/harnesses/deepseek.json +99 -0
- package/harnesses/gemini.json +122 -0
- package/harnesses/opencode.json +173 -0
- package/package.json +12 -2
- package/rules/core.md +7 -0
- package/rules/mdc/intake-questions.mdc +8 -0
- package/rules/mdc/slice-commit.mdc +57 -4
- package/src/advice/advice.mjs +3 -2
- package/src/agenthooks/prompt.mjs +5 -2
- package/src/agenthooks/render.mjs +86 -180
- package/src/agenthooks/shim.mjs +1 -1
- package/src/agents/render.mjs +15 -18
- package/src/api.mjs +31 -0
- package/src/argv.mjs +48 -3
- package/src/bench/ablate.mjs +3 -4
- package/src/bench/adapters.json +163 -105
- package/src/bench/adapters.mjs +466 -0
- package/src/bench/arms.mjs +333 -0
- package/src/bench/grade.mjs +33 -73
- package/src/bench/graders.mjs +42 -0
- package/src/bench/mine.mjs +121 -475
- package/src/bench/probe-ledger.mjs +149 -0
- package/src/bench/probes.catalog.mjs +918 -0
- package/src/bench/probes.mjs +79 -1064
- package/src/bench/render.mjs +111 -0
- package/src/bench/report.mjs +120 -962
- package/src/bench/run.mjs +185 -802
- package/src/bench/variants.mjs +4 -5
- package/src/bench/workspace.mjs +160 -0
- package/src/brief/assemble.mjs +48 -15
- package/src/ci/dependabot.mjs +25 -55
- package/src/ci/workflow.mjs +30 -7
- package/src/cli.mjs +45 -0
- package/src/commands/agent.mjs +4 -13
- package/src/commands/agenthook.mjs +70 -40
- package/src/commands/bench.mjs +191 -18
- package/src/commands/brief.mjs +5 -4
- package/src/commands/ci.mjs +13 -14
- package/src/commands/compare.mjs +42 -42
- package/src/commands/completions.mjs +2 -6
- package/src/commands/decide.mjs +4 -4
- package/src/commands/distill.mjs +4 -3
- package/src/commands/docs.mjs +88 -0
- package/src/commands/doctor.mjs +11 -7
- package/src/commands/evidence.mjs +6 -9
- package/src/commands/explain.mjs +0 -1
- package/src/commands/gate.mjs +26 -25
- package/src/commands/graph.mjs +2 -3
- package/src/commands/harness.mjs +6 -5
- package/src/commands/help.mjs +168 -19
- package/src/commands/hooks.mjs +119 -49
- package/src/commands/ignore.mjs +13 -8
- package/src/commands/impact.mjs +8 -15
- package/src/commands/index.mjs +318 -193
- package/src/commands/init-scan.mjs +90 -0
- package/src/commands/init.mjs +124 -105
- package/src/commands/lease.mjs +73 -25
- package/src/commands/lessons.mjs +10 -9
- package/src/commands/local.mjs +3 -3
- package/src/commands/map.mjs +24 -14
- package/src/commands/mcp.mjs +2 -18
- package/src/commands/pack.mjs +9 -6
- package/src/commands/plan.mjs +6 -5
- package/src/commands/plugin.mjs +2 -2
- package/src/commands/prbody.mjs +3 -3
- package/src/commands/repoindex.mjs +12 -11
- package/src/commands/review.mjs +2 -2
- package/src/commands/rules.mjs +37 -16
- package/src/commands/shared.mjs +14 -19
- package/src/commands/skills.mjs +33 -32
- package/src/commands/skillscompile.mjs +7 -8
- package/src/commands/skillsinstall.mjs +7 -6
- package/src/commands/slice.mjs +220 -74
- package/src/commands/spec.mjs +167 -0
- package/src/commands/status.mjs +27 -18
- package/src/commands/sync.mjs +27 -25
- package/src/commands/tests.mjs +18 -21
- package/src/commands/tokens.mjs +21 -26
- package/src/commands/undo.mjs +5 -15
- package/src/commands/upgrade.mjs +15 -7
- package/src/commands/why.mjs +15 -21
- package/src/compare/hooksstate.mjs +2 -6
- package/src/compare/learn.mjs +3 -1
- package/src/compare/row.mjs +0 -2
- package/src/context.mjs +64 -0
- package/src/decisions/index-doc.mjs +46 -0
- package/src/decisions/index.mjs +3 -2
- package/src/diff.mjs +1 -1
- package/src/distill/distill.mjs +14 -1
- package/src/distill/engine.mjs +5 -1
- package/src/docs/commands.mjs +65 -0
- package/src/ecosystem/records.mjs +219 -0
- package/src/explain.mjs +31 -0
- package/src/gates/index.mjs +385 -0
- package/src/graph/compile.mjs +8 -4
- package/src/graph/load.mjs +6 -2
- package/src/graph/spec.mjs +10 -8
- package/src/harness/records.mjs +143 -0
- package/src/hooks/capability.mjs +7 -5
- package/src/hooks/dispatcher.mjs +209 -60
- package/src/hooks/gates.mjs +10 -43
- package/src/hooks/resolve.mjs +4 -14
- package/src/hooks/shim.mjs +5 -2
- package/src/hooks/where.mjs +2 -7
- package/src/identity.mjs +31 -12
- package/src/index/coverage.mjs +58 -0
- package/src/index/extract.mjs +6 -16
- package/src/index/gate.mjs +1 -1
- package/src/index/govern.mjs +26 -9
- package/src/index/impact.mjs +4 -8
- package/src/index/map.mjs +14 -15
- package/src/index/open.mjs +173 -0
- package/src/index/persist.mjs +224 -57
- package/src/index/store.mjs +82 -39
- package/src/index/tests.mjs +2 -6
- package/src/journal.mjs +94 -20
- package/src/kernel/card.mjs +37 -63
- package/src/kernel/checks.mjs +4 -10
- package/src/lease.mjs +102 -7
- package/src/ledger/index.mjs +150 -14
- package/src/local/client.mjs +4 -6
- package/src/locate.mjs +33 -9
- package/src/manifest/schema.mjs +213 -0
- package/src/mcp/paginate.mjs +33 -0
- package/src/mcp/resources.mjs +7 -10
- package/src/mcp/schemas.mjs +512 -0
- package/src/mcp/server.mjs +119 -25
- package/src/mcp/tools-facts.mjs +326 -0
- package/src/mcp/tools-read.mjs +221 -0
- package/src/mcp/tools.mjs +4 -967
- package/src/measure/corpus.mjs +150 -0
- package/src/measure/metrics.mjs +236 -0
- package/src/measure/records.mjs +211 -0
- package/src/measure/session.mjs +3 -2
- package/src/measure/stats.mjs +538 -0
- package/src/measure/task-schema.mjs +125 -0
- package/src/measure/tasks.mjs +69 -0
- package/src/memory/decide.mjs +6 -15
- package/src/memory/lesson-text.mjs +61 -0
- package/src/memory/lessons.mjs +29 -82
- package/src/name.mjs +7 -0
- package/src/node-version.mjs +37 -0
- package/src/output/index.mjs +209 -10
- package/src/packs/manage.mjs +32 -12
- package/src/packs.mjs +20 -2
- package/src/plan/index.mjs +1 -1
- package/src/plugins.mjs +22 -16
- package/src/prbody.mjs +7 -11
- package/src/projection/loaders.mjs +7 -692
- package/src/projection/lock.mjs +11 -1
- package/src/projection/manifest.mjs +29 -468
- package/src/projection/mdc.mjs +7 -8
- package/src/projection/project.mjs +126 -221
- package/src/projection/region.mjs +561 -0
- package/src/projection/rules.mjs +20 -550
- package/src/projection/surfaces.mjs +43 -210
- package/src/projection/targets.mjs +5 -5
- package/src/repo-root.mjs +31 -0
- package/src/resolve/eval.mjs +2 -1
- package/src/resolve/fingerprint.mjs +19 -22
- package/src/resolve/resolve.mjs +1 -41
- package/src/review/critic.mjs +10 -13
- package/src/run.mjs +98 -0
- package/src/secrets.mjs +14 -22
- package/src/state/events.mjs +129 -0
- package/src/status-snapshot.mjs +233 -0
- package/src/status.mjs +2 -6
- package/src/sys/git.mjs +82 -0
- package/src/sys/proc.mjs +151 -0
- package/src/testing/parsers.mjs +265 -0
- package/src/testing/patches.mjs +23 -0
- package/src/testing/paths.mjs +49 -0
- package/src/testing/runners.mjs +186 -0
- package/src/testing/vault.mjs +68 -0
- package/src/text/frontmatter.mjs +49 -0
- package/src/text/tokens.mjs +52 -0
- package/src/toolwords.mjs +3 -0
- package/src/util/fs.mjs +20 -0
- package/src/util/sort.mjs +12 -0
- package/src/workspace.mjs +58 -11
- package/src/write/plan.mjs +82 -0
- package/templates/plan/tracker.json +1 -0
- package/docs/decisions/ADR-033-three-plan-rows-closed-by-decision-not-by-authoring.md +0 -82
- package/docs/decisions/ADR-102-the-two-queued-review-rows-are-closed-by-ruling.md +0 -49
- package/docs/decisions/README.md +0 -600
- package/src/bench/tasks.mjs +0 -36
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
// The MCP schemas and the two helpers every tool handler shares.
|
|
2
|
+
//
|
|
3
|
+
// Split out of tools.mjs, which crossed the repository ceiling carrying the tool list
|
|
4
|
+
// and the shapes it answers with. The shapes are data a client validates against; the
|
|
5
|
+
// handlers are the tools. A tool module imports both and defines neither.
|
|
6
|
+
|
|
7
|
+
import { loadRegistry } from '../graph/load.mjs';
|
|
8
|
+
import { provenanceDigest } from '../projection/project.mjs';
|
|
9
|
+
import { discover } from '../compare/discover.mjs';
|
|
10
|
+
import { buildRows, resolveConcurrency, summarise } from '../compare/row.mjs';
|
|
11
|
+
import { GATES } from '../hooks/gates.mjs';
|
|
12
|
+
import { checkRepo } from '../commands/sync.mjs';
|
|
13
|
+
import { diagnose, serialisedFindings } from '../commands/doctor.mjs';
|
|
14
|
+
import { rulesCatalogue, rulesWhyFacts } from '../commands/rules.mjs';
|
|
15
|
+
import { skillsBriefFacts, skillsFindFacts, skillsShowFacts, skillsWhyFacts } from '../commands/skills.mjs';
|
|
16
|
+
import { assembleBrief } from '../brief/assemble.mjs';
|
|
17
|
+
import { DEFAULT_BRIEF_BYTES } from '../brief/packet.mjs';
|
|
18
|
+
import { federationAccess, readFederation } from '../federation/config.mjs';
|
|
19
|
+
import { consult } from '../federation/query.mjs';
|
|
20
|
+
import { planNext, planDone } from '../plan/index.mjs';
|
|
21
|
+
import { buildPrBody } from '../prbody.mjs';
|
|
22
|
+
import { configPaths, readUserConfig, resolveWorkspace } from '../workspace.mjs';
|
|
23
|
+
import { measureSkill } from '../graph/load.mjs';
|
|
24
|
+
import { CLI } from '../name.mjs';
|
|
25
|
+
|
|
26
|
+
export const GATE_KINDS = new Map(Object.entries(GATES).map(([name, g]) => [name, g.kind]));
|
|
27
|
+
|
|
28
|
+
/** A schema with no required fields still needs the object declared. */
|
|
29
|
+
export const noArgs = { type: 'object', properties: {}, required: [] };
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Output schemas, one per tool, describing what a SUCCESSFUL call returns.
|
|
33
|
+
*
|
|
34
|
+
* Every one of these tools is a reader: none writes, and none writes twice. The
|
|
35
|
+
* annotations say so, and the schemas say what comes back — because a client that can
|
|
36
|
+
* validate an answer against a declared shape catches a wrong answer at the boundary,
|
|
37
|
+
* while one handed a bag of JSON has to trust that the tool meant it.
|
|
38
|
+
*
|
|
39
|
+
* Properties are required unless the payload can legitimately omit them: `error` is
|
|
40
|
+
* absent when there is none, `body` is null when there is none, and a schema that
|
|
41
|
+
* required the exception would describe a shape that never occurs. `additionalProperties`
|
|
42
|
+
* is left open, which is what the 2026-07-28 revision permits and what a reader wants:
|
|
43
|
+
* these payloads are data, and a new field from a future release should not make an
|
|
44
|
+
* older client's validation fail.
|
|
45
|
+
*/
|
|
46
|
+
/**
|
|
47
|
+
* The shape of a failure, exported because a client validating an answer needs it and
|
|
48
|
+
* because the test that checks every tool's answer needs it for the failures. Two
|
|
49
|
+
* copies of this schema would drift, and the copy that drifted would be the one nobody
|
|
50
|
+
* validates against - which is exactly how a remedy quietly stops being a string.
|
|
51
|
+
*/
|
|
52
|
+
export const ERROR_SHAPE = {
|
|
53
|
+
type: 'object',
|
|
54
|
+
properties: { error: { type: 'string' }, remedy: { type: ['string', 'null'] } },
|
|
55
|
+
required: ['error'],
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const output = {
|
|
59
|
+
doctor: {
|
|
60
|
+
// The `doctor --json` document minus its envelope: the same findings, the
|
|
61
|
+
// same workspace answer, the same fingerprint. (Q15)
|
|
62
|
+
type: 'object',
|
|
63
|
+
properties: {
|
|
64
|
+
root: { type: 'string' },
|
|
65
|
+
stack: { type: 'array', items: { type: 'string' } },
|
|
66
|
+
facts: { type: 'array', items: { type: 'string' } },
|
|
67
|
+
factEvidence: { type: 'object', additionalProperties: { type: ['string', 'null'] } },
|
|
68
|
+
signals: { type: 'array', items: { type: 'string' } },
|
|
69
|
+
// One entry per signal, naming the file that proved it. The payload is a list of
|
|
70
|
+
// paths, not of records - `fingerprint` returns evidence as the paths themselves.
|
|
71
|
+
evidence: { type: 'array', items: { type: 'string' } },
|
|
72
|
+
manifest: { type: ['object', 'null'] },
|
|
73
|
+
error: { type: ['string', 'null'] },
|
|
74
|
+
workspace: {
|
|
75
|
+
type: 'object',
|
|
76
|
+
properties: {
|
|
77
|
+
// Null is the honest value for a repository that is not inside a workspace:
|
|
78
|
+
// there is no root to name, and naming the repository as one would be a claim
|
|
79
|
+
// about the reader's directory layout that nothing established.
|
|
80
|
+
root: { type: ['string', 'null'] },
|
|
81
|
+
source: { type: ['string', 'null'] },
|
|
82
|
+
detail: { type: ['string', 'null'] },
|
|
83
|
+
error: { type: ['string', 'null'] },
|
|
84
|
+
},
|
|
85
|
+
required: ['root', 'source'],
|
|
86
|
+
},
|
|
87
|
+
shared: { type: ['object', 'null'] },
|
|
88
|
+
findings: {
|
|
89
|
+
type: 'array',
|
|
90
|
+
items: {
|
|
91
|
+
type: 'object',
|
|
92
|
+
properties: {
|
|
93
|
+
id: { type: 'string' },
|
|
94
|
+
severity: { type: 'string' },
|
|
95
|
+
detail: { type: 'string' },
|
|
96
|
+
remedy: { type: ['string', 'null'] },
|
|
97
|
+
why: { type: ['string', 'null'] },
|
|
98
|
+
safe: { type: 'boolean' },
|
|
99
|
+
fixed: { type: 'boolean' },
|
|
100
|
+
},
|
|
101
|
+
required: ['id', 'severity', 'detail', 'safe', 'fixed'],
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
fix: {
|
|
105
|
+
type: 'object',
|
|
106
|
+
properties: {
|
|
107
|
+
requested: { type: 'boolean' },
|
|
108
|
+
applied: { type: 'boolean' },
|
|
109
|
+
fixed: { type: 'array', items: { type: 'string' } },
|
|
110
|
+
failed: { type: 'array', items: { type: 'object' } },
|
|
111
|
+
},
|
|
112
|
+
required: ['requested', 'applied', 'fixed', 'failed'],
|
|
113
|
+
},
|
|
114
|
+
remedy: { type: ['string', 'null'] },
|
|
115
|
+
},
|
|
116
|
+
required: ['root', 'workspace', 'stack', 'facts', 'signals', 'evidence', 'findings'],
|
|
117
|
+
},
|
|
118
|
+
skills_index: {
|
|
119
|
+
type: 'object',
|
|
120
|
+
properties: {
|
|
121
|
+
skills: { type: 'number' },
|
|
122
|
+
totalBytes: { type: 'number' },
|
|
123
|
+
deferred: { type: 'array', items: { type: 'string' } },
|
|
124
|
+
workspace: { type: 'object' },
|
|
125
|
+
verified: { type: 'boolean' },
|
|
126
|
+
entries: {
|
|
127
|
+
type: 'array',
|
|
128
|
+
items: {
|
|
129
|
+
type: 'object',
|
|
130
|
+
properties: {
|
|
131
|
+
name: { type: 'string' },
|
|
132
|
+
summary: { type: 'string' },
|
|
133
|
+
bytes: { type: 'number' },
|
|
134
|
+
stack: { type: 'array', items: { type: 'string' } },
|
|
135
|
+
deferred: { type: 'boolean' },
|
|
136
|
+
},
|
|
137
|
+
required: ['name', 'bytes'],
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
required: ['skills', 'totalBytes', 'entries'],
|
|
142
|
+
},
|
|
143
|
+
// The `skills brief --json` document minus its envelope, or the `--all` one.
|
|
144
|
+
// The CLI keeps its field names; this adopts them. (Q15)
|
|
145
|
+
skills_brief: {
|
|
146
|
+
anyOf: [
|
|
147
|
+
{
|
|
148
|
+
type: 'object',
|
|
149
|
+
properties: {
|
|
150
|
+
repo: {
|
|
151
|
+
type: 'object',
|
|
152
|
+
properties: {
|
|
153
|
+
root: { type: 'string' },
|
|
154
|
+
stack: { type: 'array', items: { type: 'string' } },
|
|
155
|
+
facts: { type: 'array', items: { type: 'string' } },
|
|
156
|
+
},
|
|
157
|
+
required: ['root', 'stack', 'facts'],
|
|
158
|
+
},
|
|
159
|
+
workspace: { type: 'string' },
|
|
160
|
+
task: { type: ['string', 'null'] },
|
|
161
|
+
budget: { type: 'number' },
|
|
162
|
+
inlineBytes: { type: 'number' },
|
|
163
|
+
resolved: {
|
|
164
|
+
type: 'array',
|
|
165
|
+
items: {
|
|
166
|
+
type: 'object',
|
|
167
|
+
properties: {
|
|
168
|
+
name: { type: 'string' },
|
|
169
|
+
bytes: { type: 'number' },
|
|
170
|
+
summary: { type: 'string' },
|
|
171
|
+
why: { type: 'array', items: { type: 'string' } },
|
|
172
|
+
},
|
|
173
|
+
required: ['name', 'bytes', 'why'],
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
deferred: {
|
|
177
|
+
type: 'array',
|
|
178
|
+
items: {
|
|
179
|
+
type: 'object',
|
|
180
|
+
properties: { name: { type: 'string' }, bytes: { type: 'number' }, reason: { type: 'string' } },
|
|
181
|
+
required: ['name', 'bytes', 'reason'],
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
excluded: {
|
|
185
|
+
type: 'array',
|
|
186
|
+
items: {
|
|
187
|
+
type: 'object',
|
|
188
|
+
properties: { name: { type: 'string' }, reason: { type: 'string' } },
|
|
189
|
+
required: ['name', 'reason'],
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
warning: { type: 'string' },
|
|
193
|
+
},
|
|
194
|
+
required: ['repo', 'budget', 'inlineBytes', 'resolved', 'deferred', 'excluded'],
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
type: 'object',
|
|
198
|
+
properties: {
|
|
199
|
+
all: { type: 'boolean', enum: [true] },
|
|
200
|
+
repoStack: { type: 'array', items: { type: 'string' } },
|
|
201
|
+
inline: { type: 'array', items: { type: 'string' } },
|
|
202
|
+
deferred: { type: 'array', items: { type: 'string' } },
|
|
203
|
+
warning: { type: 'string' },
|
|
204
|
+
},
|
|
205
|
+
required: ['all', 'repoStack', 'inline', 'deferred'],
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
},
|
|
209
|
+
// The `skills show --json` document minus its envelope, plus the body text the
|
|
210
|
+
// command prints below the metadata. (Q15)
|
|
211
|
+
skills_show: {
|
|
212
|
+
type: 'object',
|
|
213
|
+
properties: {
|
|
214
|
+
name: { type: 'string' },
|
|
215
|
+
summary: { type: 'string' },
|
|
216
|
+
bytes: { type: 'number' },
|
|
217
|
+
capabilities: { type: 'array', items: { type: 'string' } },
|
|
218
|
+
stack: { type: 'array', items: { type: 'string' } },
|
|
219
|
+
keywords: { type: 'array', items: { type: 'string' } },
|
|
220
|
+
deferred: { type: 'boolean' },
|
|
221
|
+
requires: { type: 'array', items: { type: 'string' } },
|
|
222
|
+
variants: {
|
|
223
|
+
type: 'array',
|
|
224
|
+
items: {
|
|
225
|
+
type: 'object',
|
|
226
|
+
properties: { id: { type: 'string' }, stack: { type: 'array', items: { type: 'string' } }, bytes: { type: 'number' } },
|
|
227
|
+
required: ['id'],
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
sources: { type: 'array', items: { type: 'object' } },
|
|
231
|
+
aliasOf: { type: ['string', 'null'] },
|
|
232
|
+
variantOf: { type: ['string', 'null'] },
|
|
233
|
+
workspace: { type: 'string' },
|
|
234
|
+
body: { type: ['string', 'null'] },
|
|
235
|
+
bodyFrom: { type: 'string' },
|
|
236
|
+
bodyText: { type: ['string', 'null'] },
|
|
237
|
+
reason: { type: ['string', 'null'], description: 'why there is no body, when there is none' },
|
|
238
|
+
},
|
|
239
|
+
required: ['name', 'bytes', 'body', 'bodyFrom', 'bodyText', 'reason', 'requires', 'variants'],
|
|
240
|
+
},
|
|
241
|
+
skills_find: {
|
|
242
|
+
type: 'object',
|
|
243
|
+
properties: {
|
|
244
|
+
query: { type: 'string' },
|
|
245
|
+
results: {
|
|
246
|
+
type: 'array',
|
|
247
|
+
items: {
|
|
248
|
+
type: 'object',
|
|
249
|
+
properties: {
|
|
250
|
+
name: { type: 'string' },
|
|
251
|
+
score: { type: 'number' },
|
|
252
|
+
summary: { type: 'string' },
|
|
253
|
+
reasons: { type: 'array', items: { type: 'string' } },
|
|
254
|
+
},
|
|
255
|
+
required: ['name', 'score', 'reasons'],
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
required: ['query', 'results'],
|
|
260
|
+
},
|
|
261
|
+
// The `skills why --json` document minus its envelope. (Q15)
|
|
262
|
+
skills_why: {
|
|
263
|
+
type: 'object',
|
|
264
|
+
properties: {
|
|
265
|
+
skill: { type: 'string' },
|
|
266
|
+
score: { type: 'number' },
|
|
267
|
+
compatible: { type: 'boolean' },
|
|
268
|
+
gate: { type: 'string' },
|
|
269
|
+
repo: {
|
|
270
|
+
type: 'object',
|
|
271
|
+
properties: {
|
|
272
|
+
root: { type: 'string' },
|
|
273
|
+
stack: { type: 'array', items: { type: 'string' } },
|
|
274
|
+
facts: { type: 'array', items: { type: 'string' } },
|
|
275
|
+
evidence: { type: 'array', items: { type: 'string' } },
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
workspace: { type: 'object' },
|
|
279
|
+
paths: { type: 'array', items: { type: 'string' } },
|
|
280
|
+
taskTokens: { type: 'array', items: { type: 'string' } },
|
|
281
|
+
signals: { type: 'array', items: { type: 'string' } },
|
|
282
|
+
variants: { type: 'array', items: { type: 'object' } },
|
|
283
|
+
aliasOf: { type: ['string', 'null'] },
|
|
284
|
+
variantOf: { type: ['string', 'null'] },
|
|
285
|
+
requires: { type: 'array', items: { type: 'string' } },
|
|
286
|
+
},
|
|
287
|
+
required: ['skill', 'score', 'compatible', 'signals'],
|
|
288
|
+
},
|
|
289
|
+
rules_list: {
|
|
290
|
+
type: 'object',
|
|
291
|
+
properties: {
|
|
292
|
+
sha: { type: 'string' },
|
|
293
|
+
notes: { type: 'array', items: { type: 'string' } },
|
|
294
|
+
rules: {
|
|
295
|
+
type: 'array',
|
|
296
|
+
items: {
|
|
297
|
+
type: 'object',
|
|
298
|
+
properties: {
|
|
299
|
+
id: { type: ['string', 'null'] },
|
|
300
|
+
title: { type: ['string', 'null'] },
|
|
301
|
+
// A profile may name one signal or several, and the frontmatter keeps both
|
|
302
|
+
// spellings. Describing only the list would make a conforming rule look
|
|
303
|
+
// broken.
|
|
304
|
+
applies: { anyOf: [{ type: 'array', items: { type: 'string' } }, { type: 'string' }] },
|
|
305
|
+
origin: { type: 'string' },
|
|
306
|
+
source: { type: 'string' },
|
|
307
|
+
bytes: { type: 'number' },
|
|
308
|
+
adrs: { type: 'array', items: { type: 'string' } },
|
|
309
|
+
error: { type: ['string', 'null'] },
|
|
310
|
+
fallback: { type: 'boolean' },
|
|
311
|
+
selected: { type: ['boolean', 'null'] },
|
|
312
|
+
},
|
|
313
|
+
required: ['source', 'bytes', 'selected'],
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
required: ['sha', 'rules'],
|
|
318
|
+
},
|
|
319
|
+
// The `rules why --json` document minus its envelope, either direction. (Q15)
|
|
320
|
+
rules_why: {
|
|
321
|
+
type: 'object',
|
|
322
|
+
properties: {
|
|
323
|
+
direction: { type: 'string', enum: ['rule', 'decision'] },
|
|
324
|
+
id: { type: 'string' },
|
|
325
|
+
rule: { type: 'string' },
|
|
326
|
+
title: { type: ['string', 'null'] },
|
|
327
|
+
source: { type: 'string' },
|
|
328
|
+
origin: { type: 'string' },
|
|
329
|
+
adrs: { type: 'array', items: { type: 'object' } },
|
|
330
|
+
uncited: { type: 'boolean' },
|
|
331
|
+
others: { type: 'array', items: { type: 'string' } },
|
|
332
|
+
adr: { type: 'object' },
|
|
333
|
+
supersededBy: { type: ['object', 'null'] },
|
|
334
|
+
inForce: { type: 'object' },
|
|
335
|
+
rules: { type: 'array', items: { type: 'string' } },
|
|
336
|
+
},
|
|
337
|
+
required: ['direction', 'id'],
|
|
338
|
+
},
|
|
339
|
+
check: {
|
|
340
|
+
type: 'object',
|
|
341
|
+
properties: {
|
|
342
|
+
root: { type: 'string' },
|
|
343
|
+
ok: { type: 'boolean' },
|
|
344
|
+
findings: {
|
|
345
|
+
type: 'array',
|
|
346
|
+
items: {
|
|
347
|
+
type: 'object',
|
|
348
|
+
properties: {
|
|
349
|
+
file: { type: 'string' },
|
|
350
|
+
status: { type: 'string' },
|
|
351
|
+
detail: { type: ['string', 'null'] },
|
|
352
|
+
remedy: { type: ['string', 'null'] },
|
|
353
|
+
},
|
|
354
|
+
required: ['file', 'status'],
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
required: ['root', 'ok', 'findings'],
|
|
359
|
+
},
|
|
360
|
+
compare: {
|
|
361
|
+
type: 'object',
|
|
362
|
+
properties: {
|
|
363
|
+
root: { type: 'string' },
|
|
364
|
+
shape: { type: 'string', enum: ['repo', 'workspace'] },
|
|
365
|
+
expectedSha: { type: 'string' },
|
|
366
|
+
summary: { type: 'object' },
|
|
367
|
+
repos: { type: 'array', items: { type: 'object' } },
|
|
368
|
+
worktrees: { type: 'array', items: { type: 'object' } },
|
|
369
|
+
directories: { type: 'array', items: { type: 'string' } },
|
|
370
|
+
partial: { type: 'boolean' },
|
|
371
|
+
cursor: { type: ['string', 'null'] },
|
|
372
|
+
total: { type: 'number' },
|
|
373
|
+
},
|
|
374
|
+
required: ['root', 'shape', 'expectedSha', 'summary', 'repos'],
|
|
375
|
+
},
|
|
376
|
+
plan_next: {
|
|
377
|
+
type: 'object',
|
|
378
|
+
properties: {
|
|
379
|
+
root: { type: 'string' },
|
|
380
|
+
next: { type: ['object', 'null'] },
|
|
381
|
+
reason: { type: ['string', 'null'] },
|
|
382
|
+
},
|
|
383
|
+
required: ['root', 'next', 'reason'],
|
|
384
|
+
},
|
|
385
|
+
plan_done: {
|
|
386
|
+
type: 'object',
|
|
387
|
+
properties: {
|
|
388
|
+
root: { type: 'string' },
|
|
389
|
+
id: { type: 'string' },
|
|
390
|
+
doc: { type: 'string' },
|
|
391
|
+
line: { type: 'number' },
|
|
392
|
+
from: { type: 'string' },
|
|
393
|
+
to: { type: 'string' },
|
|
394
|
+
wouldChange: { type: 'boolean' },
|
|
395
|
+
dryRun: { type: 'boolean' },
|
|
396
|
+
remedy: { type: ['string', 'null'] },
|
|
397
|
+
},
|
|
398
|
+
required: ['root', 'id', 'wouldChange', 'dryRun'],
|
|
399
|
+
},
|
|
400
|
+
brief: {
|
|
401
|
+
type: 'object',
|
|
402
|
+
properties: {
|
|
403
|
+
root: { type: 'string' },
|
|
404
|
+
kind: { type: 'string' },
|
|
405
|
+
basis: { type: 'string' },
|
|
406
|
+
task: { type: 'string' },
|
|
407
|
+
scope: { type: 'array', items: { type: 'string' } },
|
|
408
|
+
budget: { type: 'number' },
|
|
409
|
+
bytes: { type: 'number' },
|
|
410
|
+
before: { type: 'number' },
|
|
411
|
+
floorHeld: { type: 'boolean' },
|
|
412
|
+
cut: { type: 'array', items: { type: 'string' } },
|
|
413
|
+
sections: { type: 'object', additionalProperties: { type: 'array', items: { type: 'string' } } },
|
|
414
|
+
text: { type: 'string' },
|
|
415
|
+
note: { type: ['string', 'null'] },
|
|
416
|
+
},
|
|
417
|
+
required: ['root', 'kind', 'basis', 'task', 'scope', 'budget', 'bytes', 'before', 'floorHeld', 'cut', 'sections', 'text'],
|
|
418
|
+
},
|
|
419
|
+
pr_body: {
|
|
420
|
+
type: 'object',
|
|
421
|
+
properties: {
|
|
422
|
+
root: { type: 'string' },
|
|
423
|
+
base: { type: ['string', 'null'] },
|
|
424
|
+
tree: { type: ['string', 'null'] },
|
|
425
|
+
verdict: { type: 'string' },
|
|
426
|
+
unreviewed: { type: 'array', items: { type: 'string' } },
|
|
427
|
+
paths: { type: 'array', items: { type: 'string' } },
|
|
428
|
+
decisions: {
|
|
429
|
+
type: 'array',
|
|
430
|
+
items: {
|
|
431
|
+
type: 'object',
|
|
432
|
+
properties: {
|
|
433
|
+
path: { type: 'string' },
|
|
434
|
+
id: { type: 'string' },
|
|
435
|
+
title: { type: 'string' },
|
|
436
|
+
status: { type: 'string' },
|
|
437
|
+
},
|
|
438
|
+
required: ['path', 'id', 'title', 'status'],
|
|
439
|
+
},
|
|
440
|
+
},
|
|
441
|
+
gates: {
|
|
442
|
+
type: 'object',
|
|
443
|
+
properties: {
|
|
444
|
+
declared: { type: 'array', items: { type: 'string' } },
|
|
445
|
+
evidenceMode: { type: ['string', 'null'] },
|
|
446
|
+
run: { type: ['object', 'null'] },
|
|
447
|
+
rulesOk: { type: ['boolean', 'null'] },
|
|
448
|
+
hooksOk: { type: ['boolean', 'null'] },
|
|
449
|
+
blocking: { type: 'number' },
|
|
450
|
+
warnings: { type: 'number' },
|
|
451
|
+
cached: { type: 'boolean' },
|
|
452
|
+
},
|
|
453
|
+
required: ['declared', 'blocking', 'warnings', 'cached'],
|
|
454
|
+
},
|
|
455
|
+
evidence: {
|
|
456
|
+
type: 'object',
|
|
457
|
+
properties: {
|
|
458
|
+
entries: { type: 'array', items: { type: 'object' } },
|
|
459
|
+
errors: { type: 'array', items: { type: 'string' } },
|
|
460
|
+
},
|
|
461
|
+
required: ['entries', 'errors'],
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
required: ['root', 'base', 'tree', 'verdict', 'unreviewed', 'decisions', 'gates', 'evidence', 'paths'],
|
|
465
|
+
},
|
|
466
|
+
federation_query: {
|
|
467
|
+
type: 'object',
|
|
468
|
+
properties: {
|
|
469
|
+
root: { type: 'string' },
|
|
470
|
+
query: { type: 'string' },
|
|
471
|
+
servers: { type: 'array', items: { type: 'string' } },
|
|
472
|
+
answers: {
|
|
473
|
+
type: 'array',
|
|
474
|
+
items: {
|
|
475
|
+
type: 'object',
|
|
476
|
+
properties: {
|
|
477
|
+
server: { type: 'string' },
|
|
478
|
+
tool: { type: 'string' },
|
|
479
|
+
query: { type: 'string' },
|
|
480
|
+
text: { type: 'string' },
|
|
481
|
+
},
|
|
482
|
+
required: ['server', 'tool', 'query', 'text'],
|
|
483
|
+
},
|
|
484
|
+
},
|
|
485
|
+
findings: { type: 'array', items: { type: 'string' } },
|
|
486
|
+
},
|
|
487
|
+
required: ['root', 'query', 'servers', 'answers', 'findings'],
|
|
488
|
+
},
|
|
489
|
+
/** The shape of every tool failure, which is a result and not a protocol error. */
|
|
490
|
+
error: ERROR_SHAPE,
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
export const rootArg = {
|
|
494
|
+
type: 'object',
|
|
495
|
+
properties: { root: { type: 'string', description: 'repository root; defaults to the editor cwd' } },
|
|
496
|
+
required: [],
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
export function rootOf(args) {
|
|
501
|
+
return typeof args?.root === 'string' && args.root.length > 0 ? args.root : process.cwd();
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
export async function registry(args) {
|
|
505
|
+
const { registry, errors, ok, verified, workspace } = await loadRegistry(null, args ?? {});
|
|
506
|
+
if (!ok) {
|
|
507
|
+
throw Object.assign(new Error(errors[0]), {
|
|
508
|
+
remedy: `run: ${CLI} graph lint`,
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
return { registry, verified, workspace };
|
|
512
|
+
}
|