agent-doc-system 0.0.0-stage → 1.0.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/INSTALL_FOR_AGENTS.md +60 -0
- package/LICENSE +21 -0
- package/README.md +151 -2
- package/adapters/cache.mjs +27 -0
- package/adapters/contract-consumers.mjs +56 -0
- package/adapters/database.mjs +116 -0
- package/adapters/deploy-config.mjs +34 -0
- package/adapters/dockerfile.mjs +26 -0
- package/adapters/events.mjs +145 -0
- package/adapters/generic.mjs +86 -0
- package/adapters/github-actions.mjs +106 -0
- package/adapters/go.mjs +91 -0
- package/adapters/graphql.mjs +28 -0
- package/adapters/index.mjs +55 -0
- package/adapters/node.mjs +118 -0
- package/adapters/object-store.mjs +64 -0
- package/adapters/oidc.mjs +56 -0
- package/adapters/openapi.mjs +50 -0
- package/adapters/pnpm.mjs +42 -0
- package/adapters/protobuf.mjs +35 -0
- package/adapters/registry.mjs +27 -0
- package/adapters/resource-client.mjs +61 -0
- package/adapters/turborepo.mjs +135 -0
- package/adapters/typescript.mjs +85 -0
- package/adapters/wrangler.mjs +206 -0
- package/bin/agentdoc.mjs +478 -0
- package/bin/usage.txt +26 -0
- package/core/acceptances.mjs +69 -0
- package/core/audit.mjs +407 -0
- package/core/authority/classes.mjs +39 -0
- package/core/authority/engine.mjs +243 -0
- package/core/authority/facts.mjs +41 -0
- package/core/codes.mjs +119 -0
- package/core/compile.mjs +881 -0
- package/core/contracts.mjs +121 -0
- package/core/derive.mjs +102 -0
- package/core/descriptors.mjs +486 -0
- package/core/determinism.mjs +95 -0
- package/core/discover.mjs +147 -0
- package/core/facts.mjs +53 -0
- package/core/fsx.mjs +342 -0
- package/core/graph.mjs +260 -0
- package/core/impact.mjs +175 -0
- package/core/indexes.mjs +165 -0
- package/core/jsonschema.mjs +298 -0
- package/core/observations.mjs +129 -0
- package/core/provenance.mjs +83 -0
- package/core/query.mjs +384 -0
- package/core/relations.mjs +286 -0
- package/core/scaffold.mjs +322 -0
- package/core/secrets.mjs +92 -0
- package/core/sourcescan.mjs +88 -0
- package/core/toml.mjs +163 -0
- package/core/yaml.mjs +475 -0
- package/docs/ADAPTERS.md +172 -0
- package/docs/AUTHORITY.md +260 -0
- package/docs/CI.md +136 -0
- package/docs/COMPARISON-KODA.md +164 -0
- package/docs/EVALS.md +166 -0
- package/docs/MIGRATION.md +193 -0
- package/docs/PROVENANCE.md +133 -0
- package/docs/QUERY.md +180 -0
- package/docs/SPEC.md +339 -0
- package/docs/VERIFICATION.md +28 -0
- package/docs/ci/generic-ci.sh +28 -0
- package/docs/ci/github-actions.yml +35 -0
- package/evals/harness.mjs +426 -0
- package/evals/scenarios/fixture-a-01-change-api.json +9 -0
- package/evals/scenarios/fixture-a-02-change-db.json +9 -0
- package/evals/scenarios/fixture-a-03-enforce-constraint.json +9 -0
- package/evals/scenarios/fixture-b-01-change-proto.json +9 -0
- package/evals/scenarios/fixture-b-02-change-write-path.json +9 -0
- package/evals/scenarios/fixture-b-03-change-shared-lib.json +9 -0
- package/evals/scenarios/fixture-b-04-journey.json +9 -0
- package/evals/scenarios/fixture-c-01-mixed-runtime-edge.json +19 -0
- package/evals/scenarios/fixture-c-02-stale-doc-contradiction.json +9 -0
- package/evals/scenarios/fixture-c-03-shared-vocabulary.json +9 -0
- package/evals/scenarios/fixture-c-04-contract-change.json +9 -0
- package/evals/scenarios/koda-01-modify-api-consumer.json +26 -0
- package/evals/scenarios/koda-02-change-db-schema.json +20 -0
- package/evals/scenarios/koda-03-change-auth.json +21 -0
- package/evals/scenarios/koda-04-add-event-producer.json +19 -0
- package/evals/scenarios/koda-05-modify-worker-binding.json +25 -0
- package/evals/scenarios/koda-06-change-cross-component-endpoint.json +22 -0
- package/evals/scenarios/koda-07-change-shared-package.json +16 -0
- package/evals/scenarios/koda-08-change-runtime-cron.json +23 -0
- package/evals/scenarios/koda-09-debug-production-mismatch.json +26 -0
- package/evals/thresholds.json +11 -0
- package/package.json +46 -4
- package/schemas/api.schema.json +84 -0
- package/schemas/common.schema.json +107 -0
- package/schemas/component.schema.json +40 -0
- package/schemas/config.schema.json +685 -0
- package/schemas/domain.schema.json +14 -0
- package/schemas/graph.schema.json +1084 -0
- package/schemas/journeys.schema.json +47 -0
- package/schemas/observation.schema.json +143 -0
- package/schemas/resource.schema.json +28 -0
- package/schemas/system.schema.json +26 -0
- package/skills/agent-doc-system/SKILL.md +113 -0
- package/skills/agent-doc-system/references/authority-and-conflicts.md +70 -0
- package/skills/agent-doc-system/references/cli.md +89 -0
- package/skills/agent-doc-system/references/create-migrate.md +101 -0
- package/skills/agent-doc-system/references/maintenance.md +52 -0
- package/templates/ADR.md +26 -0
- package/templates/ARCHITECTURE.md +19 -0
- package/templates/CONSTRAINTS.md +17 -0
- package/templates/PRODUCT.md +17 -0
- package/templates/api.yaml +10 -0
- package/templates/ci.yml +31 -0
- package/templates/component.yaml +14 -0
- package/templates/domain.yaml +6 -0
- package/templates/journey.yaml +7 -0
- package/templates/observation.yaml +19 -0
- package/templates/resource.yaml +8 -0
- package/templates/system.yaml +10 -0
- package/templates/warning-acceptance.yaml +14 -0
package/docs/SPEC.md
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
# SPEC
|
|
2
|
+
|
|
3
|
+
Normative specification of the agent documentation system. Where this document
|
|
4
|
+
and the code disagree, the code is the defect.
|
|
5
|
+
|
|
6
|
+
## 1. Purpose
|
|
7
|
+
|
|
8
|
+
Given a repository, the system produces one deterministic graph that answers,
|
|
9
|
+
for any source path or entity: what this is, what it depends on, what depends
|
|
10
|
+
on it, what it must not violate, and which command proves a change correct.
|
|
11
|
+
|
|
12
|
+
## 2. Namespace and versioning
|
|
13
|
+
|
|
14
|
+
| artefact | identity |
|
|
15
|
+
|---|---|
|
|
16
|
+
| entity descriptor | `apiVersion: agentdoc.dev/v1` |
|
|
17
|
+
| configuration | `apiVersion: agentdoc.dev/config/v1` |
|
|
18
|
+
| observation set | `apiVersion: agentdoc.dev/observation/v1` |
|
|
19
|
+
| journeys | `schemaVersion: agentdoc.dev/journeys/v1` |
|
|
20
|
+
| compiled graph | `schemaVersion: agentdoc.dev/graph/v1` |
|
|
21
|
+
| JSON Schema ids | `agentdoc.dev/schema/<name>.json` |
|
|
22
|
+
| compiler | `agentdoc-compiler@<semver>` |
|
|
23
|
+
|
|
24
|
+
**Evolution rules.**
|
|
25
|
+
|
|
26
|
+
- The major version in `apiVersion` changes only on a breaking change to the
|
|
27
|
+
descriptor shape. The compiler accepts exactly one major version and refuses
|
|
28
|
+
anything else with `AGENTDOC_API_VERSION`; a future format is never half-read.
|
|
29
|
+
- Every schema is `additionalProperties: false`. An unknown field is
|
|
30
|
+
`AGENTDOC_UNKNOWN_FIELD`, not a silently ignored key.
|
|
31
|
+
- Forward evolution happens through the per-entity `extensions` object, which is
|
|
32
|
+
typed as free-form and ignored by every core rule — including the prohibited
|
|
33
|
+
field check, so the escape hatch is genuinely usable for exactly the
|
|
34
|
+
slow-drifting metadata that has no home in an entity.
|
|
35
|
+
- The compiled graph records `schemaVersion`, `compiler.name`,
|
|
36
|
+
`compiler.version` and `compiler.adapters`. Freshness refuses a graph built by
|
|
37
|
+
a different compiler or schema.
|
|
38
|
+
- Schema files ship with the compiler, not with the target repository. A
|
|
39
|
+
project cannot loosen validation by editing a schema. Their content hashes are
|
|
40
|
+
folded into the graph input hash, so upgrading a schema invalidates every
|
|
41
|
+
graph compiled against the old one.
|
|
42
|
+
|
|
43
|
+
## 3. Source dialect
|
|
44
|
+
|
|
45
|
+
Authored sources are a strict YAML 1.2 subset, parsed by `core/yaml.mjs`:
|
|
46
|
+
|
|
47
|
+
- supported: multi-document streams, block mappings, block sequences, plain and
|
|
48
|
+
quoted scalars, flow sequences and mappings of scalars, literal and folded
|
|
49
|
+
block scalars, comments, and YAML 1.2 core scalar resolution.
|
|
50
|
+
- rejected with a dedicated code: anchors, aliases, custom tags, merge keys,
|
|
51
|
+
environment interpolation, duplicate mapping keys, tab indentation,
|
|
52
|
+
non-UTF-8 input, complex keys, and any nesting the parser would have to guess
|
|
53
|
+
at.
|
|
54
|
+
|
|
55
|
+
The rationale is that authored descriptors are templates plus human review, and
|
|
56
|
+
ambiguity in them is a defect rather than a feature.
|
|
57
|
+
|
|
58
|
+
## 4. Entity model
|
|
59
|
+
|
|
60
|
+
Five entity kinds, and five only. Journeys, events, external dependencies,
|
|
61
|
+
capabilities, verification entries, gates, contracts, assertions and
|
|
62
|
+
observations are **not** entities and may never appear as a relation endpoint.
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
Domain a bounded area of the product with its own vocabulary
|
|
66
|
+
System a responsibility inside a domain, grouping components
|
|
67
|
+
Component a deployable or importable software unit
|
|
68
|
+
API a durable cross-component boundary with one canonical contract
|
|
69
|
+
Resource a logical thing shared or owned across components
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
An entity carries: a stable ref, `metadata` (name, one-sentence description,
|
|
73
|
+
optional labels), an optional `spec`, and an `extensions` bag. Every entity is
|
|
74
|
+
authored in exactly one file, and the location is validated.
|
|
75
|
+
|
|
76
|
+
**Ref format:** `<kind>:<namespace>/<name>`, e.g. `component:default/teacher`.
|
|
77
|
+
The namespace comes from the configuration, so two repositories in one graph
|
|
78
|
+
never collide.
|
|
79
|
+
|
|
80
|
+
### Why no further entities
|
|
81
|
+
|
|
82
|
+
A `Team`, `Milestone` or `Tag` entity was considered and rejected: none of them
|
|
83
|
+
can be derived, none of them changes a fact in the graph, and all three would
|
|
84
|
+
need a lifecycle and an owner — the two things this system deliberately refuses
|
|
85
|
+
to model, because they are the fields that drift fastest and carry the least
|
|
86
|
+
architectural meaning. Ownership is expressed by placement; lifecycle belongs
|
|
87
|
+
in version control.
|
|
88
|
+
|
|
89
|
+
## 5. Facts, evidence and confidence
|
|
90
|
+
|
|
91
|
+
A **fact** is a claim about one `(subject, key)` pair. `key` is a dotted
|
|
92
|
+
name, optionally namespaced, e.g. `schedule.cron`, `binding.declared`,
|
|
93
|
+
`contract.supports`, `component.deployable`, `placement.system`,
|
|
94
|
+
`resource.ownership`. `core/authority/facts.mjs` documents the semantics of the
|
|
95
|
+
well-known keys.
|
|
96
|
+
|
|
97
|
+
Every fact carries an **evidence class** and a **confidence**:
|
|
98
|
+
|
|
99
|
+
| evidence class | meaning |
|
|
100
|
+
|---|---|
|
|
101
|
+
| `AUTHORED` | explicitly declared and intentionally maintained in this repository |
|
|
102
|
+
| `DERIVED` | deterministically extracted from committed inputs |
|
|
103
|
+
| `OBSERVED_RUNTIME` | read from an authoritative external or running system |
|
|
104
|
+
| `EXTERNAL_STANDARD` | the canonical authority is a published standard |
|
|
105
|
+
| `REVIEWED_OVERRIDE` | a reviewer approved an interpretation |
|
|
106
|
+
| `UNRESOLVED` | known ambiguity that must not become truth |
|
|
107
|
+
|
|
108
|
+
| confidence | meaning |
|
|
109
|
+
|---|---|
|
|
110
|
+
| `direct` | read straight from the named authority system |
|
|
111
|
+
| `deterministic` | a reproducible function of committed inputs |
|
|
112
|
+
| `declared` | asserted by a human-maintained document |
|
|
113
|
+
| `reviewed` | a reviewer signed off on an interpretation |
|
|
114
|
+
| `candidate` | heuristic; **never** allowed to become an elected fact |
|
|
115
|
+
|
|
116
|
+
See `AUTHORITY.md` for the full semantics and the conflict model.
|
|
117
|
+
|
|
118
|
+
## 6. Relations
|
|
119
|
+
|
|
120
|
+
No relation is ever authored. Placement edges come from authored placement
|
|
121
|
+
fields, provider edges from the API descriptor, and everything else from
|
|
122
|
+
deterministic extractors or bounded reviewed overrides.
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
partOf / hasPart Component->System|Domain, System->Domain, Resource->System
|
|
126
|
+
providesApi / apiProvidedBy Component<->API
|
|
127
|
+
consumesApi / apiConsumedBy Component<->API
|
|
128
|
+
buildDependsOn / buildDependencyOf
|
|
129
|
+
testDependsOn / testDependencyOf
|
|
130
|
+
runtimeCalls / runtimeCalledBy
|
|
131
|
+
usesResource / resourceUsedBy
|
|
132
|
+
schedules / scheduledBy
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Every relation is emitted with its inverse, its kind pair is validated, its
|
|
136
|
+
attribute keys are checked against a closed per-type whitelist, and duplicates
|
|
137
|
+
merge their provenance instead of forking the graph. Every relation carries at
|
|
138
|
+
least one provenance id and an evidence class.
|
|
139
|
+
|
|
140
|
+
## 7. The compiled graph
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
schemaVersion, source{commit, dirty, inputHash}, compiler{name, version, adapters}
|
|
144
|
+
entities[] ref, kind, name, entity, source, sourcePaths[], derived?
|
|
145
|
+
relations[] type, sourceRef, targetRef, evidenceClass, attributes, provenanceIds[]
|
|
146
|
+
interfaces.events[] pattern, producers, consumers, contract, resolution
|
|
147
|
+
externalDependencies[] componentRef, name, role, mechanism, evidenceClass
|
|
148
|
+
capabilities[] componentRef, name, evidenceClass
|
|
149
|
+
verification[] id, componentRefs, tier, command, configPaths
|
|
150
|
+
gates[] id, tier, command (repository-scoped checks)
|
|
151
|
+
contracts[] apiRef, ref, operations (pointer + inventory, never a copy)
|
|
152
|
+
journeys[] id, description, components
|
|
153
|
+
assertions[] id, subject, key, value, evidenceClass, confidence, status
|
|
154
|
+
conflicts[] id, subject, key, kind, status, assertionIds, election
|
|
155
|
+
observations[] id, environment, sourceSystem, collector, capturedAt, facts[]
|
|
156
|
+
provenance[] id, class, path, extractor, contentHash, subjects[]
|
|
157
|
+
diagnostics[] severity, code, message, acceptance?
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### 7.1 Determinism
|
|
161
|
+
|
|
162
|
+
The graph is a pure function of the checkout.
|
|
163
|
+
|
|
164
|
+
- Objects are constructed in schema order; every array is sorted by a total
|
|
165
|
+
order over its identifying key.
|
|
166
|
+
- No wall-clock value, host path, username, process id or random id is
|
|
167
|
+
introduced at compile time.
|
|
168
|
+
- **Observation timestamps are the one permitted time value**, and only because
|
|
169
|
+
they are read from a committed `ObservationSet`. Before emission, the
|
|
170
|
+
serialized graph is scanned and every timestamp present must be one the
|
|
171
|
+
compiler actually read; anything else fails with `AGENTDOC_NONDETERMINISTIC`.
|
|
172
|
+
- The serialized output is scanned for absolute paths, host directories and
|
|
173
|
+
process identity. The scan covers the graph's *structure* — refs, ids, paths,
|
|
174
|
+
hashes, keys, provenance — and not opaque free-text fields, which are copied
|
|
175
|
+
verbatim from committed files and are therefore a pure function of the
|
|
176
|
+
checkout by construction. A repository is free to mention `/tmp` in a CI
|
|
177
|
+
command; a compiler-introduced host path is not.
|
|
178
|
+
- Provenance ids are positional over a canonical sort, so they are stable.
|
|
179
|
+
|
|
180
|
+
`compile` is idempotent: compiling the same checkout twice produces identical
|
|
181
|
+
bytes, and `check` proves the committed bytes equal a fresh compile.
|
|
182
|
+
|
|
183
|
+
### 7.2 Freshness
|
|
184
|
+
|
|
185
|
+
`source.inputHash` is a length-prefixed hash over:
|
|
186
|
+
|
|
187
|
+
1. the compiler name and version, the graph schema version, the entity api
|
|
188
|
+
version, the authority-rule count, every enabled adapter's name and version,
|
|
189
|
+
and the content hash of every shipped schema;
|
|
190
|
+
2. every file the compiler read, as `path` + content;
|
|
191
|
+
3. every existence probe, as path + result;
|
|
192
|
+
4. every directory listing, as directory + sorted file list.
|
|
193
|
+
|
|
194
|
+
Every byte flows through the read tracker, so the record is complete by
|
|
195
|
+
construction. A consumer must refuse a graph whose `inputHash` or `dirty` flag
|
|
196
|
+
disagrees with the current checkout. There is no fallback.
|
|
197
|
+
|
|
198
|
+
The recorded `commit` is **provenance, not a gate**: committing the graph changes
|
|
199
|
+
`HEAD`, so a commit-equality check could never be satisfied by a committed graph.
|
|
200
|
+
What determines whether the graph still describes the repository is the input
|
|
201
|
+
hash and the dirty flag. A checkout with no VCS still compiles: the commit
|
|
202
|
+
becomes `0000000` and freshness rests on the hash alone.
|
|
203
|
+
|
|
204
|
+
`dirty` is true when a path that influenced the output differs from `HEAD`,
|
|
205
|
+
excluding the generated graph itself.
|
|
206
|
+
|
|
207
|
+
### 7.3 Time-dependent gates
|
|
208
|
+
|
|
209
|
+
Observation staleness is time-dependent and is therefore evaluated at gate time
|
|
210
|
+
(`check`, `query`), never at compile time. A compile stays a pure function of the
|
|
211
|
+
checkout; a gate may legitimately fail because time passed.
|
|
212
|
+
|
|
213
|
+
## 8. Contracts
|
|
214
|
+
|
|
215
|
+
Every durable cross-component boundary has exactly one canonical
|
|
216
|
+
machine-readable contract, and the graph **points at** it rather than copying
|
|
217
|
+
it. Supported dialects, all validated on load:
|
|
218
|
+
|
|
219
|
+
| type | validation |
|
|
220
|
+
|---|---|
|
|
221
|
+
| `openapi` | `openapi` 3.0/3.1, `info.title`, `paths`, `components` |
|
|
222
|
+
| `asyncapi` | `asyncapi` version, `channels` |
|
|
223
|
+
| `protobuf` | `syntax` or `edition`, at least one `service` |
|
|
224
|
+
| `graphql` / `graphql-sdl` | at least one type definition |
|
|
225
|
+
| `oidc` | a named standard plus an absolute discovery path; the provider must expose that path in its own source |
|
|
226
|
+
|
|
227
|
+
Two rules enforce the "exactly one" property: a contract file under a
|
|
228
|
+
configured `contractRoots` that no API claims is `AGENTDOC_CONTRACT_UNCLAIMED`,
|
|
229
|
+
and two APIs claiming the same file is `AGENTDOC_CONTRACT_SHARED`.
|
|
230
|
+
|
|
231
|
+
Consumers are discovered deterministically: a unit, other than the provider,
|
|
232
|
+
that references the contract file from a source or build-configuration file.
|
|
233
|
+
|
|
234
|
+
## 9. Discovery
|
|
235
|
+
|
|
236
|
+
The core has no knowledge of folder names. A directory is a unit when it holds
|
|
237
|
+
a component descriptor, when an adapter recognises it from a workspace file, or
|
|
238
|
+
when it is listed in `discovery.supplementalRoots`.
|
|
239
|
+
|
|
240
|
+
- Every discovered unit must have exactly one descriptor at its root, or
|
|
241
|
+
`AGENTDOC_COVERAGE_ZERO`.
|
|
242
|
+
- Two descriptors at one root, or a descriptor no adapter can corroborate, is an
|
|
243
|
+
error. A descriptor is a human claim; an uncorroborated claim is a defect.
|
|
244
|
+
- The authored `type` is cross-checked against the artifact evidence:
|
|
245
|
+
a `library` with no importable artifact, or a `service` with no deployable
|
|
246
|
+
artifact, is `AGENTDOC_ARTIFACT_TYPE`.
|
|
247
|
+
|
|
248
|
+
## 10. Provenance
|
|
249
|
+
|
|
250
|
+
See `PROVENANCE.md`. In summary: every important fact carries at least one
|
|
251
|
+
provenance record with a path, a content hash, an extractor identity and RFC
|
|
252
|
+
6901 subject pointers into the graph. Classes are `declared`, `observed`,
|
|
253
|
+
`validated`, `runtime` and `standard`.
|
|
254
|
+
|
|
255
|
+
## 11. Diagnostics and warning acceptance
|
|
256
|
+
|
|
257
|
+
Error-severity diagnostics block publication. Warnings may be **accepted** with
|
|
258
|
+
a reviewed disposition carrying `code`, `subject`, `classification`, `reason`,
|
|
259
|
+
`reviewWhen`, `observedRefs` and evidence content hashes.
|
|
260
|
+
|
|
261
|
+
An acceptance must match exactly one current warning, its `observedRefs` must
|
|
262
|
+
equal the diagnostic's current refs, and every evidence digest must still match.
|
|
263
|
+
If the evidence changes, the acceptance stops matching and compilation fails:
|
|
264
|
+
a review is forced, not inherited. Acceptance can never downgrade an error, and
|
|
265
|
+
only the codes in `ACCEPTABLE_WARNING_CODES` may be accepted.
|
|
266
|
+
|
|
267
|
+
## 12. Commands
|
|
268
|
+
|
|
269
|
+
| command | contract |
|
|
270
|
+
|---|---|
|
|
271
|
+
| `init [--force]` | write a configuration and documentation skeleton; never clobber unless `--force` |
|
|
272
|
+
| `scaffold [--write]` | generate descriptors from provable evidence; dry run by default |
|
|
273
|
+
| `audit` | classify every fact; runs even when the repository cannot compile |
|
|
274
|
+
| `validate` | sources, schemas, semantic checks; no artifact written |
|
|
275
|
+
| `compile [--require-clean]` | deterministic build, atomic replace |
|
|
276
|
+
| `check [--require-clean] [--allow-stale-observations]` | freshness, determinism, time gates |
|
|
277
|
+
| `query <path\|ref> [--json] [--md]` | route context; refuses a stale graph |
|
|
278
|
+
| `impact <paths> \| --diff <ref>` | change impact; compiles in memory |
|
|
279
|
+
| `eval routing [--json]` | routing evaluation; `SKIP` when the repository has no scenarios |
|
|
280
|
+
| `pin-evidence [--json]` | check the digests pinned by reviewed overrides |
|
|
281
|
+
| `doctor` | environment self-check: node version, schema bundle, git, writability |
|
|
282
|
+
|
|
283
|
+
Exit codes: `0` ok, `1` failure, `2` usage.
|
|
284
|
+
|
|
285
|
+
## 13. Error codes
|
|
286
|
+
|
|
287
|
+
Every failure carries a stable `AGENTDOC_*` code, a path or ref when relevant,
|
|
288
|
+
and an actionable message. Codes are listed in `core/codes.mjs` and are part of
|
|
289
|
+
the contract: tests and CI match on identity, never on message text.
|
|
290
|
+
|
|
291
|
+
## 14. Source schema dialect
|
|
292
|
+
|
|
293
|
+
Schemas use the JSON Schema 2020-12 subset the shipped validator implements:
|
|
294
|
+
`$ref` (bundle ids and `#/$defs/...`), `$defs`, `type`, `const`, `enum`,
|
|
295
|
+
`required`, `properties`, `additionalProperties`, `patternProperties`, `items`,
|
|
296
|
+
`prefixItems`, `minItems`, `maxItems`, `uniqueItems`, `minLength`, `maxLength`,
|
|
297
|
+
`pattern`, `minimum`, `maximum`, `allOf`, `anyOf`, `oneOf`, `not`, `if`/`then`/
|
|
298
|
+
`else`, `propertyNames`, `minProperties`.
|
|
299
|
+
|
|
300
|
+
Two things follow, and both are enforced rather than asserted:
|
|
301
|
+
|
|
302
|
+
- **No unsupported keyword can be used.** A test walks every shipped schema at
|
|
303
|
+
every position where a schema may appear, against the validator's own
|
|
304
|
+
exported keyword set, and fails on anything else. `format` is deliberately
|
|
305
|
+
*not* in that set, so a schema author who reaches for `format: date-time`
|
|
306
|
+
gets a failure rather than a validator that quietly does nothing.
|
|
307
|
+
- **`entities[].entity` and `entities[].derived` are opaque payloads** in the
|
|
308
|
+
graph schema. The authored half is validated against its per-kind entity
|
|
309
|
+
schema at input time, which is where a malformed descriptor must be caught;
|
|
310
|
+
re-validating the same document against the graph schema would be a second
|
|
311
|
+
source of truth for the same constraint. Every other graph surface is closed
|
|
312
|
+
(`additionalProperties: false`).
|
|
313
|
+
|
|
314
|
+
## 15. Dependencies
|
|
315
|
+
|
|
316
|
+
None. The YAML subset parser, the JSON Schema validator, the TOML reader, the
|
|
317
|
+
glob matcher, the hashing and the deterministic serializer are all in-tree.
|
|
318
|
+
Node 22 or newer. No network, no service, no hosted anything.
|
|
319
|
+
|
|
320
|
+
## Reviewed overrides are re-verified, and so are their review conditions
|
|
321
|
+
|
|
322
|
+
A `REVIEWED_OVERRIDE` is the highest-authority input the model accepts, and the
|
|
323
|
+
only thing that can falsify it is the evidence it cites. So each override:
|
|
324
|
+
|
|
325
|
+
- must state `reviewWhen` — the condition under which it is re-examined. A
|
|
326
|
+
review with no re-examination condition is a review that is never revisited,
|
|
327
|
+
and a defaulted string would be the same sentence on every override: a review
|
|
328
|
+
condition that conditions nothing, reported as though it were real;
|
|
329
|
+
- pins its evidence by content hash (`{path, sha256}`), and those digests are
|
|
330
|
+
re-verified on every compile. If a cited file changes, compilation fails with
|
|
331
|
+
`AGENTDOC_OVERRIDE_STALE` and the interpretation must be reviewed before the
|
|
332
|
+
digest is updated. A digest that is recorded but never compared is decoration;
|
|
333
|
+
`agentdoc pin-evidence` reports which digests are current so the repair is
|
|
334
|
+
possible without computing SHA-256 by hand.
|
|
335
|
+
|
|
336
|
+
The same discipline applies to accepted warnings, for the same reason. An
|
|
337
|
+
authority rule's own `reviewWhen` travels onto the conflict it settles, so
|
|
338
|
+
`query`'s `reviewCommitments` surface reports a real condition or says plainly
|
|
339
|
+
that none was recorded — never a pointer to a record that does not exist.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Verification record for this repository.
|
|
2
|
+
# Every claim below was executed; the commands are reproducible from the repo root.
|
|
3
|
+
|
|
4
|
+
node --test tests/*.test.mjs # unit, adversarial, mode and packaging tests
|
|
5
|
+
node evals/run-all.mjs # aggregate routing gate — verdict: PASS
|
|
6
|
+
|
|
7
|
+
Corpora (each compiles, checks, and passes its own routing scenarios):
|
|
8
|
+
fixtures/a-node-ts-postgres
|
|
9
|
+
fixtures/b-go-multi-service
|
|
10
|
+
fixtures/c-alt-monorepo
|
|
11
|
+
examples/koda/repo (golden corpus)
|
|
12
|
+
|
|
13
|
+
Distribution (covered by tests/packaging.test.mjs):
|
|
14
|
+
npm pack produces a tarball whose installed `agentdoc` binary runs
|
|
15
|
+
--version, --help, doctor, init, doctor --project, audit and
|
|
16
|
+
eval routing with no access to the source checkout.
|
|
17
|
+
|
|
18
|
+
Also verified:
|
|
19
|
+
- output is byte-identical across three consecutive compiles
|
|
20
|
+
- a checkout with no .git compiles and checks
|
|
21
|
+
- running the test suite does not modify the package
|
|
22
|
+
- a graph that violates its own schema is rejected
|
|
23
|
+
- a reviewed override stops applying when its cited evidence is rewritten
|
|
24
|
+
- `agentdoc init` creates project data only — never a copy of the CLI
|
|
25
|
+
- a catalog nested inside a larger checkout is not dirtied by outer-repo churn
|
|
26
|
+
|
|
27
|
+
Comparison regeneration (requires the reference graph, kept out of the repo):
|
|
28
|
+
python3 scripts/compare-koda.py <reference-graph> <portable-graph>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
# The drift gate, runner-agnostic. Any CI system that can run a shell can run
|
|
3
|
+
# this. The `agentdoc` CLI must be installed on the runner beforehand; exit
|
|
4
|
+
# status is the contract.
|
|
5
|
+
set -eu
|
|
6
|
+
|
|
7
|
+
if ! command -v agentdoc >/dev/null 2>&1; then
|
|
8
|
+
echo "agentdoc: CLI not on PATH — install it first:" >&2
|
|
9
|
+
echo " npm install -g github:lbframe/agent-doc-system" >&2
|
|
10
|
+
exit 1
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
echo "==> validate"
|
|
14
|
+
agentdoc validate
|
|
15
|
+
|
|
16
|
+
echo "==> compile"
|
|
17
|
+
agentdoc compile
|
|
18
|
+
|
|
19
|
+
echo "==> check (freshness, determinism, time gates)"
|
|
20
|
+
agentdoc check
|
|
21
|
+
|
|
22
|
+
echo "==> check (clean source required)"
|
|
23
|
+
agentdoc check --require-clean
|
|
24
|
+
|
|
25
|
+
echo "==> routing evaluation (skips cleanly when no scenarios are registered)"
|
|
26
|
+
agentdoc eval routing
|
|
27
|
+
|
|
28
|
+
echo "agentdoc: all gates passed"
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Drift gate. The graph is a build artifact: compile it, then prove the
|
|
2
|
+
# committed one is byte-identical to a fresh compile. A stale or hand-edited
|
|
3
|
+
# graph fails here, not in someone's review three weeks later.
|
|
4
|
+
#
|
|
5
|
+
# This is the workflow `agentdoc init` installs as
|
|
6
|
+
# .github/workflows/agentdoc.yml (see templates/ci.yml). It assumes nothing
|
|
7
|
+
# about the repository beyond a supported Node toolchain.
|
|
8
|
+
name: agentdoc
|
|
9
|
+
on:
|
|
10
|
+
pull_request:
|
|
11
|
+
push:
|
|
12
|
+
branches: [main]
|
|
13
|
+
jobs:
|
|
14
|
+
agentdoc:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
timeout-minutes: 5
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
with: { fetch-depth: 0 }
|
|
20
|
+
- uses: actions/setup-node@v4
|
|
21
|
+
with: { node-version: '24' }
|
|
22
|
+
- name: Install the agentdoc CLI
|
|
23
|
+
# Unpinned tracks main. For CI reproducibility pin a tag or commit:
|
|
24
|
+
# github:lbframe/agent-doc-system#v1.0.0
|
|
25
|
+
# A compiler upgrade intentionally invalidates committed graphs.
|
|
26
|
+
run: npm install -g github:lbframe/agent-doc-system
|
|
27
|
+
- name: Validate and compile
|
|
28
|
+
run: |
|
|
29
|
+
agentdoc validate
|
|
30
|
+
agentdoc compile
|
|
31
|
+
agentdoc check
|
|
32
|
+
- name: Reject dirty sources
|
|
33
|
+
run: agentdoc check --require-clean
|
|
34
|
+
- name: Routing evaluation
|
|
35
|
+
run: agentdoc eval routing
|