agent-doc-system 1.1.0 → 1.3.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 +402 -0
- package/README.md +38 -0
- package/adapters/ansible.mjs +1 -1
- package/adapters/cache.mjs +9 -2
- package/adapters/contract-consumers.mjs +1 -1
- package/adapters/database.mjs +19 -4
- package/adapters/deploy-config.mjs +3 -2
- package/adapters/dockerfile.mjs +3 -2
- package/adapters/events.mjs +1 -1
- package/adapters/generic.mjs +2 -1
- package/adapters/github-actions.mjs +245 -85
- package/adapters/go.mjs +5 -4
- package/adapters/index.mjs +3 -1
- package/adapters/node.mjs +3 -2
- package/adapters/object-store.mjs +2 -2
- package/adapters/python.mjs +1142 -0
- package/adapters/resource-client.mjs +1 -1
- package/adapters/rust.mjs +990 -0
- package/adapters/turborepo.mjs +3 -2
- package/adapters/typescript.mjs +7 -5
- package/adapters/wrangler.mjs +3 -2
- package/bin/agentdoc.mjs +11 -4
- package/bin/usage.txt +2 -0
- package/core/audit.mjs +12 -8
- package/core/codes.mjs +4 -0
- package/core/compile.mjs +131 -16
- package/core/dependents.mjs +42 -0
- package/core/derive.mjs +4 -3
- package/core/descriptors.mjs +3 -2
- package/core/discover.mjs +61 -9
- package/core/fsx.mjs +185 -36
- package/core/graph.mjs +1 -1
- package/core/impact.mjs +66 -48
- package/core/paths.mjs +71 -0
- package/core/query.mjs +76 -31
- package/core/scaffold.mjs +216 -44
- package/core/sourcescan.mjs +14 -2
- package/core/toml.mjs +463 -140
- package/docs/ADAPTERS.md +196 -6
- package/docs/BENCHMARK.md +130 -0
- package/docs/CI.md +7 -1
- package/docs/EVALS.md +239 -16
- package/docs/MIGRATION.md +26 -6
- package/docs/PROVENANCE.md +6 -0
- package/docs/QUERY.md +78 -7
- package/docs/SPEC.md +69 -2
- package/docs/ci/github-actions.yml +1 -1
- package/evals/baseline-search.mjs +272 -0
- package/evals/facts.mjs +28 -0
- package/evals/harness.mjs +149 -119
- package/evals/scenarios/fixture-b-03-change-shared-lib.json +8 -1
- package/evals/scenarios/fixture-c-03-shared-vocabulary.json +7 -1
- package/evals/scenarios/fixture-e-01-change-shared-lib.json +14 -0
- package/evals/scenarios/fixture-e-02-change-manifest.json +9 -0
- package/evals/scenarios/fixture-e-03-local-module.json +9 -0
- package/evals/scenarios/fixture-e-04-ambiguous-crate.json +14 -0
- package/evals/scenarios/fixture-f-01-change-shared-lib.json +9 -0
- package/evals/scenarios/fixture-f-02-change-manifest.json +9 -0
- package/evals/scenarios/fixture-f-03-shadowed-import.json +9 -0
- package/evals/scenarios/fixture-f-04-nested-workspace.json +9 -0
- package/evals/scenarios/fixture-f-05-alembic-database.json +9 -0
- package/evals/scenarios/fixture-f-06-unittest-job.json +9 -0
- package/package.json +5 -2
- package/skills/agent-doc-system/SKILL.md +2 -1
- package/skills/agent-doc-system/references/cli.md +6 -1
- package/skills/agent-doc-system/references/create-migrate.md +21 -5
- package/templates/ci.yml +1 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to AgentDoc are documented here.
|
|
4
|
+
|
|
5
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
|
6
|
+
the project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). The
|
|
7
|
+
compiler version is the package version: a graph compiled by one release is
|
|
8
|
+
refused by the next with `AGENTDOC_COMPILER_MISMATCH` until it is recompiled.
|
|
9
|
+
|
|
10
|
+
## [Unreleased]
|
|
11
|
+
|
|
12
|
+
## [1.3.0] - 2026-11-07
|
|
13
|
+
|
|
14
|
+
A graph compiled on your machine now passes `check` in CI and in a clean
|
|
15
|
+
checkout. Files git ignores no longer count as compiler inputs, so a local
|
|
16
|
+
build that fills an ignored directory no longer changes `inputHash`. A
|
|
17
|
+
component whose descriptor sits at the repository root now owns the root files
|
|
18
|
+
no other component owns, so `query` and `impact` route them. `init` and
|
|
19
|
+
`scaffold --write` no longer write into your product's `docs/`: they follow the
|
|
20
|
+
configured `docs.*` paths, and a new install without a configuration gets its
|
|
21
|
+
skeleton under `agentdoc/docs/`. Releases are now published from CI with npm
|
|
22
|
+
provenance, so `npm audit signatures` can verify that a release was built from
|
|
23
|
+
this repository. The benchmark claim made in the 1.2.0 release notes is
|
|
24
|
+
withdrawn, because its gap came from the evaluation and not from routing.
|
|
25
|
+
|
|
26
|
+
Before you upgrade:
|
|
27
|
+
|
|
28
|
+
- **Recompile committed graphs.** As with every release, a graph compiled by
|
|
29
|
+
1.2.0 is refused with `AGENTDOC_COMPILER_MISMATCH` until you run
|
|
30
|
+
`agentdoc compile` again.
|
|
31
|
+
- **A descriptor or configuration path that points at a git-ignored file now
|
|
32
|
+
fails** with `AGENTDOC_PATH_UNRESOLVED`, as it would in a clean checkout.
|
|
33
|
+
Commit the file or stop ignoring it ([#45]).
|
|
34
|
+
- **New installs write the documentation skeleton to `agentdoc/docs/`**
|
|
35
|
+
instead of `docs/`. A configuration that declares `docs.*` keeps its paths,
|
|
36
|
+
and no existing file is moved ([#59]).
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- A deterministic `baseline-search` routing evaluation using working-tree file
|
|
41
|
+
reads and text search, without compiled relations ([#46]). CLI reports compare
|
|
42
|
+
catalog, corrected targeted and search recall/noise/check selectivity per
|
|
43
|
+
scenario, corpus and aggregate; `docs/EVALS.md` documents every heuristic.
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
|
|
47
|
+
- Releases are now published only through a manual GitHub Actions workflow,
|
|
48
|
+
using npm trusted publishing (no token) with provenance, so `npm audit
|
|
49
|
+
signatures` can verify that a release was built from this repository
|
|
50
|
+
([#51]). `RELEASING.md` in the repository describes the process.
|
|
51
|
+
|
|
52
|
+
- **Behaviour change for new installs only:** without a configuration,
|
|
53
|
+
`agentdoc init` (and `scaffold --write`) now writes the documentation
|
|
54
|
+
skeleton to `agentdoc/docs/PRODUCT.md`, `agentdoc/docs/ARCHITECTURE.md`,
|
|
55
|
+
`agentdoc/docs/CONSTRAINTS.md` and `agentdoc/docs/adr/`, and records those
|
|
56
|
+
paths in the `docs:` block of the generated `agentdoc/agentdoc.config.yaml`
|
|
57
|
+
([#59]). It used to write to `docs/`, which in many repositories is the
|
|
58
|
+
product's own user documentation and the source of a published docs site
|
|
59
|
+
(MkDocs, Docusaurus, GitHub Pages). Authored AgentDoc material now lives in
|
|
60
|
+
`agentdoc/`; generated output stays in `.agentdoc/`. Existing configurations
|
|
61
|
+
are unaffected: a configuration that declares `docs.*` keeps its paths,
|
|
62
|
+
`docs/...` included, and no existing file is moved. To keep `docs/` on a new
|
|
63
|
+
install, declare `docs.product`, `docs.architecture`, `docs.constraints` and
|
|
64
|
+
`docs.adrDir` in `agentdoc/agentdoc.config.yaml` before running `init`.
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
|
|
68
|
+
- A component whose descriptor sits at the repository root now owns the files
|
|
69
|
+
no nested component owns ([#50]). Before, `query vite.config.ts` failed with
|
|
70
|
+
`AGENTDOC_REF_UNRESOLVED` and `impact` listed the file in `unmatchedFiles`,
|
|
71
|
+
for both `vite.config.ts` and `./vite.config.ts`. Paths are now compared in
|
|
72
|
+
one canonical repository-relative form (no `./`), by whole path segment
|
|
73
|
+
(`src` never owns `src2/x`), and the longest owning root wins, so nested
|
|
74
|
+
components keep precedence and a contract file still routes to its API. A
|
|
75
|
+
root unit's derived paths (`README.md`, `package.json`, markers, provenance,
|
|
76
|
+
verification config paths) are no longer recorded as `./README.md`, so
|
|
77
|
+
`impact` now recognises them as documentation and compiler inputs. Without a
|
|
78
|
+
root descriptor, root files stay unmatched. Graphs of repositories without a
|
|
79
|
+
root component are unchanged.
|
|
80
|
+
|
|
81
|
+
- `agentdoc scaffold --write` and `agentdoc init` now write the documentation
|
|
82
|
+
skeleton (`PRODUCT.md`, `ARCHITECTURE.md`, `CONSTRAINTS.md`, the ADR README)
|
|
83
|
+
to the configured `docs.product`, `docs.architecture`, `docs.constraints` and
|
|
84
|
+
`docs.adrDir` paths ([#49]). Both used to write to `docs/` even when the
|
|
85
|
+
configuration said otherwise, and `docs/` is often the product's own user
|
|
86
|
+
documentation. The paths are read through the same loader as `compile` and
|
|
87
|
+
`audit`. A role the configuration omits is listed under `notConfigured`
|
|
88
|
+
instead of falling back to `docs/`. An existing file is still skipped unless
|
|
89
|
+
`init --force` is given. A path that leaves the repository, including through
|
|
90
|
+
a symlink, fails with `AGENTDOC_PATH_ESCAPE` before anything is written.
|
|
91
|
+
Without a configuration, `init` uses the `agentdoc/docs/` defaults (see
|
|
92
|
+
[#59] under Changed).
|
|
93
|
+
|
|
94
|
+
- Files git ignores no longer enter the compiler's inputs or `inputHash`
|
|
95
|
+
([#45]). A local build writing into an ignored directory (`astro build`
|
|
96
|
+
filling `.astro/`, a `build/` tree, `*.log`) used to change the hash, so a
|
|
97
|
+
graph compiled after it failed `check` with `AGENTDOC_GRAPH_FRESHNESS` in CI
|
|
98
|
+
and in every clean checkout, while passing on the author's machine. Reads,
|
|
99
|
+
existence probes, listings and discovery now exclude git-ignored paths, with
|
|
100
|
+
git itself as the oracle: tracked files always count, and nested
|
|
101
|
+
`.gitignore`, `.git/info/exclude`, `core.excludesFile` and negations behave
|
|
102
|
+
exactly as in git. A non-ignored untracked file is still an input. Without
|
|
103
|
+
git the previous behaviour (filesystem minus `discovery.generatedDirs`)
|
|
104
|
+
holds. Committed graphs keep their hash. A descriptor or configuration
|
|
105
|
+
that points at a git-ignored file (for example a spec generated into an
|
|
106
|
+
ignored directory before `compile`) now fails with
|
|
107
|
+
`AGENTDOC_PATH_UNRESOLVED`, as it would in a clean checkout: commit the file
|
|
108
|
+
or stop ignoring it. The `git clean -fdX` before
|
|
109
|
+
`compile` documented as a workaround in lbframe/klozeo's `AGENTS.md` is no
|
|
110
|
+
longer needed.
|
|
111
|
+
|
|
112
|
+
- `npm publish` no longer auto-corrects `package.json`: the `bin` path is
|
|
113
|
+
committed in npm's normalized form, `bin/agentdoc.mjs` ([#55]).
|
|
114
|
+
|
|
115
|
+
- All routing evaluation systems and the noise closure now share fact labels
|
|
116
|
+
([#46]). Corrected targeted micro-recall is 100/101 (0.9901), rather than
|
|
117
|
+
the previously reported gap. Search matches catalog recall in 21/30 scenarios;
|
|
118
|
+
measurements and limitations are in `docs/BENCHMARK.md`. Normalized full fact
|
|
119
|
+
counts fall below the existing size floor, so aggregate size reduction is
|
|
120
|
+
reported as unmeasured. Thresholds, scenarios and core routing are unchanged.
|
|
121
|
+
|
|
122
|
+
- **Withdrawn benchmark claim.** The README, `docs/BENCHMARK.md` and the 1.2.0
|
|
123
|
+
release notes reported that routing retrieves 100% of the facts a change
|
|
124
|
+
needs against 58% for a baseline that reads only the touched component, with
|
|
125
|
+
noise under 9% against 40%, and an answer about 70% smaller than the whole
|
|
126
|
+
catalog. The gap came from the evaluation, not from
|
|
127
|
+
routing: the baseline already held almost every expected fact under a
|
|
128
|
+
different label, and it read relations from the compiled graph that an agent
|
|
129
|
+
without AgentDoc does not have. The size figure counted the same component
|
|
130
|
+
once per relation label; deduplicated, every corpus falls below the size
|
|
131
|
+
floor. Both claims are
|
|
132
|
+
removed. A baseline that finds
|
|
133
|
+
relations with search alone is now measured in the benchmark. The
|
|
134
|
+
[correction](docs/BENCHMARK.md#correction-the-fact-recall-comparison-is-withdrawn)
|
|
135
|
+
gives the details.
|
|
136
|
+
|
|
137
|
+
## [1.2.0] - 2026-10-27
|
|
138
|
+
|
|
139
|
+
Rust and Python are now supported at the same level as Node and Go. Before
|
|
140
|
+
this release, a Cargo crate or a Python package was invisible to the compiler:
|
|
141
|
+
`agentdoc audit` reported zero units, and a hand-written descriptor produced a
|
|
142
|
+
component with no language, no dependency edges and no verification commands.
|
|
143
|
+
|
|
144
|
+
The release also fixes how a change is routed. `impact` and `query` now follow
|
|
145
|
+
the components that depend on the changed one, not the ones it depends on, and
|
|
146
|
+
recommend those dependents' checks.
|
|
147
|
+
|
|
148
|
+
### Added
|
|
149
|
+
|
|
150
|
+
- **`rust` adapter** ([#17]). Reads `Cargo.toml` and never runs Cargo or reads
|
|
151
|
+
`Cargo.lock`.
|
|
152
|
+
- A `[package]` is a unit. `[[bin]]`, `src/main.rs` or `src/bin/` make it
|
|
153
|
+
deployable; `[lib]` or `src/lib.rs` make it importable.
|
|
154
|
+
- Workspace members come from every `[workspace]` manifest, including one
|
|
155
|
+
below the repository root (`rust/Cargo.toml` next to other languages).
|
|
156
|
+
- Sibling crates become `buildDependsOn` / `testDependsOn` edges when the
|
|
157
|
+
manifest says so: a `path`, `workspace = true` resolved through the nearest
|
|
158
|
+
`[workspace.dependencies]`, or a `[patch.<registry>]` / `[replace]` path
|
|
159
|
+
redirect inside the repository. `use`, `extern crate` and `<crate>::` paths
|
|
160
|
+
add provenance to those edges but never create one, because Rust cannot
|
|
161
|
+
use a crate the manifest does not declare.
|
|
162
|
+
- Verification commands: `cargo test -p <name>` and `cargo clippy -p <name>`.
|
|
163
|
+
- Resource vocabulary: sqlx, diesel (`diesel.toml`), tokio-postgres,
|
|
164
|
+
deadpool, sea-orm, the `redis` crate and `aws-sdk-s3`.
|
|
165
|
+
- **`python` adapter** ([#18]). Reads `pyproject.toml` (PEP 621 and Poetry),
|
|
166
|
+
`setup.cfg`, `setup.py` and `requirements*.txt`. It never runs Python,
|
|
167
|
+
resolves a lockfile or inspects a virtualenv.
|
|
168
|
+
- Shape comes from evidence. An entrypoint (`[project.scripts]`,
|
|
169
|
+
`__main__.py`, `manage.py`, an ASGI/WSGI app object) makes a unit
|
|
170
|
+
deployable; a build backend plus a package makes it importable.
|
|
171
|
+
- uv workspace members come from the repository root and from workspaces
|
|
172
|
+
below it. A member with no build backend is still a unit.
|
|
173
|
+
- Sibling packages become edges from `[project] dependencies`,
|
|
174
|
+
`[tool.uv.sources]`, Poetry `path` dependencies, `-e <dir>` requirements,
|
|
175
|
+
and `import` / `from` statements. Dev groups and dev/test extras give
|
|
176
|
+
`testDependsOn`. An import that the importing unit provides itself, such
|
|
177
|
+
as a local `utils.py`, is not read as a sibling.
|
|
178
|
+
- Verification commands are derived only from evidence: `pytest`,
|
|
179
|
+
`python -m unittest discover` for unittest-only suites, `ruff check` and
|
|
180
|
+
`mypy`. `uv run` / `poetry run` is prefixed only when the lockfile names
|
|
181
|
+
the tool.
|
|
182
|
+
- Also derived: `requiresPython` when declared, and Alembic migrations as
|
|
183
|
+
database evidence.
|
|
184
|
+
- Resource vocabulary: SQLAlchemy, asyncpg, psycopg, Django `DATABASES`,
|
|
185
|
+
`redis.Redis` and boto3.
|
|
186
|
+
- `agentdoc init` enables `rust` and `python` when it finds their manifests.
|
|
187
|
+
`agentdoc scaffold` names crates and distributions from their manifests and
|
|
188
|
+
types them from their artifact shape: `service`, `library`, or `other` when
|
|
189
|
+
neither is proven. A virtual Cargo or uv workspace manifest is not scaffolded.
|
|
190
|
+
- A reproducible benchmark, `scripts/bench/run.mjs` ([docs/BENCHMARK.md]).
|
|
191
|
+
It clones four public repositories at pinned commits, runs a fresh
|
|
192
|
+
`init` → `scaffold` → `compile`, counts every hand edit the setup still
|
|
193
|
+
needs (zero for all four), checks that the graph is byte-identical across
|
|
194
|
+
compiles, and measures `query` answers.
|
|
195
|
+
- The routing evaluation reports **check selectivity**: the share of the
|
|
196
|
+
repository's checks that the answer for a change contains ([#43]). The
|
|
197
|
+
baseline's verification recall is now scored with the same rule as the
|
|
198
|
+
catalog's. It is 1.0 by construction, because the baseline runs every check.
|
|
199
|
+
- Rust and Python sample repositories (`fixtures/e-rust-workspace`,
|
|
200
|
+
`fixtures/f-python-workspace`), checked in CI and used to test context
|
|
201
|
+
routing ([#23]).
|
|
202
|
+
|
|
203
|
+
### Changed
|
|
204
|
+
|
|
205
|
+
- **Change routing follows dependents** ([#30], [#25]).
|
|
206
|
+
- A change to a component reaches the components that depend on it,
|
|
207
|
+
transitively, through reverse `buildDependsOn` / `testDependsOn` edges.
|
|
208
|
+
Before, `impact` also listed the components it depends on as affected,
|
|
209
|
+
and did not follow transitive dependents.
|
|
210
|
+
- Dependencies stay visible as typed relations in `query`. They are no
|
|
211
|
+
longer reported as affected components.
|
|
212
|
+
- `query` and `impact` recommend the dependents' checks after the changed
|
|
213
|
+
component's own: every tier for build dependents, unit checks only for test
|
|
214
|
+
dependents.
|
|
215
|
+
- `impact` adds `recommendedVerificationTotal` and
|
|
216
|
+
`recommendedVerificationTruncated`, so a capped list is never mistaken for
|
|
217
|
+
the whole.
|
|
218
|
+
- **`query` markdown shows an entity's context** ([#28]). Resources and
|
|
219
|
+
Systems now list their `docs`, `CONSTRAINTS` and `runbooks`, as components
|
|
220
|
+
already did. Constraints are never capped by default. Docs and runbooks show
|
|
221
|
+
12 paths each, and `--budget docs=…,constraints=…,runbooks=…` sets explicit
|
|
222
|
+
caps with a `[truncated: x of y]` marker.
|
|
223
|
+
- **`discovery.notUnitRoots` excludes a whole subtree from inferred units**
|
|
224
|
+
([#27]). An adapter marker or a scaffold proposal at or below an excluded
|
|
225
|
+
root is no longer a unit. A hand-written descriptor below an excluded root
|
|
226
|
+
is still honoured. A descriptor exactly at an excluded root is refused with
|
|
227
|
+
a message that names the exclusion.
|
|
228
|
+
- **GitHub Actions checks are scoped to the components they run for**
|
|
229
|
+
([#29]). A step becomes a component check only when its command is a
|
|
230
|
+
recognised test, lint or build invocation, scoped by `working-directory`,
|
|
231
|
+
`cd <dir> &&`, a path argument, a package selector (`--filter`, turbo, nx,
|
|
232
|
+
`make -C`) or a `paths:` filter. Repository scripts whose names say what
|
|
233
|
+
they check (`./scripts/test.sh`, `bash scripts/lint.sh`) are recognised
|
|
234
|
+
with the same scoping ([#40]). Anything else is a repository gate.
|
|
235
|
+
- Before, every step was attached to every component whose path or package
|
|
236
|
+
name appeared anywhere in the workflow, including multi-line ops scripts.
|
|
237
|
+
A shell `test -n` was also recorded as a unit test.
|
|
238
|
+
- `impact` on a workflow file now names the components and gates derived
|
|
239
|
+
from it, plus their dependents' checks.
|
|
240
|
+
- **The TOML reader conforms to TOML 1.0** ([#18], [#31]). It reads
|
|
241
|
+
`Cargo.toml`, `pyproject.toml` and `wrangler.toml`, and passes every case of
|
|
242
|
+
the official [toml-test](https://github.com/toml-lang/toml-test) 1.0.0
|
|
243
|
+
suite: 208 valid and 501 invalid documents. Before, it rejected valid
|
|
244
|
+
documents, such as multi-line strings and lowercase date-time delimiters,
|
|
245
|
+
which lost every fact in the file. It also accepted invalid ones, such as a
|
|
246
|
+
trailing comma in an inline table or a table declared twice. Invalid TOML
|
|
247
|
+
is rejected with `AGENTDOC_YAML_PARSE`.
|
|
248
|
+
|
|
249
|
+
### Fixed
|
|
250
|
+
|
|
251
|
+
- **A unit nested inside another unit no longer leaks its facts into the
|
|
252
|
+
parent** ([#21]). Every per-unit scan stops at nested units, so each file
|
|
253
|
+
belongs to the deepest unit that contains it. Before, an enclosing unit also
|
|
254
|
+
claimed its nested unit's health routes, ports, capabilities, resource and
|
|
255
|
+
migration evidence, imports, contract consumers, TypeScript routes, Ansible
|
|
256
|
+
playbooks and test markers. This affects any layout with nested units, such
|
|
257
|
+
as a service containing a tool package, a Cargo root package with member
|
|
258
|
+
crates below it, or a uv workspace root with its own `[project]`.
|
|
259
|
+
- An Alembic `alembic/versions` directory was listed as a migration location
|
|
260
|
+
but never recognised. It now counts as migration evidence. The evidence file
|
|
261
|
+
is a qualifying `alembic.ini` or `[tool.alembic]` configuration when one
|
|
262
|
+
exists, and otherwise a revision file.
|
|
263
|
+
- A changed migration, including an Alembic revision, now lists the logical
|
|
264
|
+
database its component uses in `impact`'s `affectedResources` ([#30]).
|
|
265
|
+
Before, the list stayed empty.
|
|
266
|
+
- The audit no longer reports a document as orphaned when it is linked only
|
|
267
|
+
from a Resource's or System's `context` ([#28]).
|
|
268
|
+
- `agentdoc scaffold --write` no longer writes descriptors into directories
|
|
269
|
+
listed in `discovery.notUnitRoots` ([#27]).
|
|
270
|
+
- **A fresh setup compiles without hand edits** ([#37], [#38]).
|
|
271
|
+
- `scaffold` now types every unit from its artifact evidence: `service`,
|
|
272
|
+
`library`, or `other` when neither is proven. Before, a Node app without
|
|
273
|
+
`exports` or `main`, or a Go module, was written as `library` and failed
|
|
274
|
+
`validate` straight away.
|
|
275
|
+
- `init` now discovers descriptors with the `*/**/agentdoc.yaml` glob
|
|
276
|
+
instead of an explicit list, and `scaffold` covers every unit an adapter
|
|
277
|
+
declares, including workspace members under `examples/`.
|
|
278
|
+
- A `setup.py` unit is named after the distribution it declares, and the
|
|
279
|
+
`python` adapter reads `name`, `python_requires` and `install_requires`
|
|
280
|
+
inside a one-line `setup(…)` or `setuptools.setup(…)` call ([#41]).
|
|
281
|
+
- On the four public repositories used for benchmarking (tokio-rs/axum,
|
|
282
|
+
pydantic/pydantic-ai, fastapi/full-stack-fastapi-template and
|
|
283
|
+
t3-oss/create-t3-turbo), `init` + `scaffold --write` + `compile` now pass
|
|
284
|
+
with no edits other than choosing each component's placement.
|
|
285
|
+
|
|
286
|
+
### Upgrading
|
|
287
|
+
|
|
288
|
+
- The compiler version is now `1.2.0`. A graph committed with 1.1.0 fails
|
|
289
|
+
`agentdoc check` with `AGENTDOC_COMPILER_MISMATCH`. Run `agentdoc compile`
|
|
290
|
+
and commit the graph.
|
|
291
|
+
- An existing catalog keeps its adapter list. To use the new adapters, add
|
|
292
|
+
`rust` and/or `python` to `adapters:` in `agentdoc/agentdoc.config.yaml`,
|
|
293
|
+
then run `agentdoc audit`: units that were invisible appear as
|
|
294
|
+
`AGENTDOC_COVERAGE_ZERO` until they have a descriptor.
|
|
295
|
+
`agentdoc scaffold --write` writes those descriptors.
|
|
296
|
+
- If your repository has nested units, recompiling removes facts that were
|
|
297
|
+
wrongly attributed to an enclosing component. Review the affected facts,
|
|
298
|
+
dependency edges and verification commands, and any descriptor or document
|
|
299
|
+
that relied on them.
|
|
300
|
+
- Tools that read `impact --json` will see fewer `affectedComponents`
|
|
301
|
+
(dependencies are gone) and more `recommendedVerification` entries
|
|
302
|
+
(dependents' checks).
|
|
303
|
+
- A unit inferred below a `notUnitRoots` entry, with no descriptor, is no
|
|
304
|
+
longer reported as `AGENTDOC_COVERAGE_ZERO`. If it should be a component,
|
|
305
|
+
write its descriptor, or remove the directory from `notUnitRoots`.
|
|
306
|
+
- If your workflows run checks for specific components, recompiling changes
|
|
307
|
+
which checks are attached to which component. Review the diff: checks that
|
|
308
|
+
were attached only because a path was mentioned elsewhere in the workflow
|
|
309
|
+
move to repository gates.
|
|
310
|
+
- Recompiling always updates the compiler version, source commit and input
|
|
311
|
+
hash. Review the other derived changes, especially in repositories with
|
|
312
|
+
nested units, Alembic migrations or Wrangler TOML manifests: a manifest the
|
|
313
|
+
old TOML reader could not parse now yields facts.
|
|
314
|
+
|
|
315
|
+
## [1.1.0] - 2026-10-18
|
|
316
|
+
|
|
317
|
+
### Added
|
|
318
|
+
|
|
319
|
+
- **MIGRATE gates normative requirements and section coverage** ([#5]).
|
|
320
|
+
Documentation checks now state their real scope, and the strict gate refuses
|
|
321
|
+
unverified requirements.
|
|
322
|
+
- **`ansible` adapter** ([#6]). Reads playbooks without running anything and
|
|
323
|
+
derives installed paths and managed services. A requirement with
|
|
324
|
+
`satisfiedBy: [ansible]` and the new `expects` field
|
|
325
|
+
(`installs: <path>` | `service: <name>`) is checked against them, so a missing
|
|
326
|
+
install ends in a conflict instead of `AGENTDOC_REQUIREMENT_UNVERIFIED`.
|
|
327
|
+
- `agentdoc <command> --help` lists each command's flags and exit codes ([#7]).
|
|
328
|
+
|
|
329
|
+
### Changed
|
|
330
|
+
|
|
331
|
+
- **The CLI rejects unknown flags** ([#7]) and names the closest valid flag. A
|
|
332
|
+
typo such as `check --strcit` no longer silently runs a non-strict check.
|
|
333
|
+
Scripts that passed flags a command does not accept now exit 2.
|
|
334
|
+
|
|
335
|
+
### Fixed
|
|
336
|
+
|
|
337
|
+
- A committed graph passes CI ([#11]). `check` no longer fails with
|
|
338
|
+
`AGENTDOC_GRAPH_FRESHNESS` after `compile` on a clean checkout, where the
|
|
339
|
+
graph file itself was counted as a changed input.
|
|
340
|
+
- A nested `.github/workflows` directory no longer fails `validate` ([#12]).
|
|
341
|
+
Only the repository-root directory is read, as GitHub does.
|
|
342
|
+
|
|
343
|
+
### Upgrading
|
|
344
|
+
|
|
345
|
+
- A graph committed with 1.0.0 fails `agentdoc check` with
|
|
346
|
+
`AGENTDOC_COMPILER_MISMATCH` until it is recompiled.
|
|
347
|
+
|
|
348
|
+
## [1.0.0] - 2026-09-29
|
|
349
|
+
|
|
350
|
+
First public release.
|
|
351
|
+
|
|
352
|
+
### Added
|
|
353
|
+
|
|
354
|
+
- The machine-installed `agentdoc` CLI for Node 22, 24 and 26, with zero
|
|
355
|
+
runtime dependencies.
|
|
356
|
+
- A deterministic repository graph: repeated compiles of the same tree are
|
|
357
|
+
byte-identical.
|
|
358
|
+
- Evidence separation between AUTHORED documentation, DERIVED facts extracted
|
|
359
|
+
from code, and OBSERVED runtime evidence.
|
|
360
|
+
- A fail-closed authority model: contradictions surface as conflicts and are
|
|
361
|
+
never silently overwritten.
|
|
362
|
+
- `agentdoc query`, which routes minimal, budgeted context for a task, and
|
|
363
|
+
`agentdoc impact`, which reports what a change forces you to keep consistent.
|
|
364
|
+
- CREATE and MIGRATE workflows through `init`, `audit`, `scaffold`,
|
|
365
|
+
`validate`, `compile` and `check`.
|
|
366
|
+
- `agentdoc doctor` for machine diagnostics, and `agentdoc doctor --project`
|
|
367
|
+
for project health.
|
|
368
|
+
- An Agent Skill under `skills/agent-doc-system/`.
|
|
369
|
+
|
|
370
|
+
[Unreleased]: https://github.com/lbframe/agent-doc-system/compare/v1.3.0...HEAD
|
|
371
|
+
[1.3.0]: https://github.com/lbframe/agent-doc-system/compare/v1.2.0...v1.3.0
|
|
372
|
+
[1.2.0]: https://github.com/lbframe/agent-doc-system/compare/v1.1.0...v1.2.0
|
|
373
|
+
[1.1.0]: https://github.com/lbframe/agent-doc-system/compare/v1.0.0...v1.1.0
|
|
374
|
+
[1.0.0]: https://github.com/lbframe/agent-doc-system/releases/tag/v1.0.0
|
|
375
|
+
[docs/BENCHMARK.md]: docs/BENCHMARK.md
|
|
376
|
+
[#5]: https://github.com/lbframe/agent-doc-system/issues/5
|
|
377
|
+
[#6]: https://github.com/lbframe/agent-doc-system/issues/6
|
|
378
|
+
[#7]: https://github.com/lbframe/agent-doc-system/issues/7
|
|
379
|
+
[#11]: https://github.com/lbframe/agent-doc-system/issues/11
|
|
380
|
+
[#12]: https://github.com/lbframe/agent-doc-system/issues/12
|
|
381
|
+
[#17]: https://github.com/lbframe/agent-doc-system/issues/17
|
|
382
|
+
[#18]: https://github.com/lbframe/agent-doc-system/issues/18
|
|
383
|
+
[#21]: https://github.com/lbframe/agent-doc-system/issues/21
|
|
384
|
+
[#23]: https://github.com/lbframe/agent-doc-system/issues/23
|
|
385
|
+
[#25]: https://github.com/lbframe/agent-doc-system/issues/25
|
|
386
|
+
[#27]: https://github.com/lbframe/agent-doc-system/issues/27
|
|
387
|
+
[#28]: https://github.com/lbframe/agent-doc-system/issues/28
|
|
388
|
+
[#29]: https://github.com/lbframe/agent-doc-system/issues/29
|
|
389
|
+
[#30]: https://github.com/lbframe/agent-doc-system/issues/30
|
|
390
|
+
[#31]: https://github.com/lbframe/agent-doc-system/issues/31
|
|
391
|
+
[#37]: https://github.com/lbframe/agent-doc-system/issues/37
|
|
392
|
+
[#38]: https://github.com/lbframe/agent-doc-system/issues/38
|
|
393
|
+
[#40]: https://github.com/lbframe/agent-doc-system/issues/40
|
|
394
|
+
[#41]: https://github.com/lbframe/agent-doc-system/issues/41
|
|
395
|
+
[#43]: https://github.com/lbframe/agent-doc-system/issues/43
|
|
396
|
+
[#45]: https://github.com/lbframe/agent-doc-system/issues/45
|
|
397
|
+
[#46]: https://github.com/lbframe/agent-doc-system/issues/46
|
|
398
|
+
[#49]: https://github.com/lbframe/agent-doc-system/issues/49
|
|
399
|
+
[#50]: https://github.com/lbframe/agent-doc-system/issues/50
|
|
400
|
+
[#51]: https://github.com/lbframe/agent-doc-system/issues/51
|
|
401
|
+
[#55]: https://github.com/lbframe/agent-doc-system/issues/55
|
|
402
|
+
[#59]: https://github.com/lbframe/agent-doc-system/issues/59
|
package/README.md
CHANGED
|
@@ -69,6 +69,41 @@ AgentDoc turns scattered repository knowledge into task-specific context your co
|
|
|
69
69
|
|
|
70
70
|

|
|
71
71
|
|
|
72
|
+
## What it understands
|
|
73
|
+
|
|
74
|
+
AgentDoc reads manifests, contracts and configuration. It never runs your toolchain.
|
|
75
|
+
|
|
76
|
+
Support comes from adapters and from built-in contract validation (AsyncAPI needs no adapter).
|
|
77
|
+
- `agentdoc init` picks `node`, `go`, `rust`, `python`, `dockerfile` and `wrangler` from the files it finds.
|
|
78
|
+
- It always includes `database`, `openapi`, `events` and `github-actions`.
|
|
79
|
+
- Add the others in `agentdoc/agentdoc.config.yaml`.
|
|
80
|
+
|
|
81
|
+
| area | supported |
|
|
82
|
+
|---|---|
|
|
83
|
+
| languages & packages | Node (npm, pnpm workspaces, Turborepo), TypeScript, Go (modules, `go.work`), Rust (Cargo packages and workspaces), Python (`pyproject.toml` with PEP 621 or Poetry, uv workspaces, `setup.cfg` / `setup.py`, `requirements*.txt`) |
|
|
84
|
+
| contracts | OpenAPI, protobuf, GraphQL, AsyncAPI, OIDC discovery |
|
|
85
|
+
| deployment & CI | Dockerfile / Containerfile, `fly.toml`, `Procfile` and similar deploy configs, Cloudflare Wrangler, Ansible playbooks, GitHub Actions |
|
|
86
|
+
| resources | databases (migrations, ORM config, connection evidence), caches, object stores, event subjects |
|
|
87
|
+
|
|
88
|
+
For each language, AgentDoc derives:
|
|
89
|
+
|
|
90
|
+
- the units;
|
|
91
|
+
- whether each one is deployable or importable;
|
|
92
|
+
- dependency edges between sibling units;
|
|
93
|
+
- verification commands taken from the repository's own evidence (`go test`, `cargo test -p`, `pytest`, `python -m unittest`, npm scripts, …).
|
|
94
|
+
|
|
95
|
+
What every adapter derives, and what it deliberately cannot see, is in [docs/ADAPTERS.md](docs/ADAPTERS.md).
|
|
96
|
+
|
|
97
|
+
## By the numbers
|
|
98
|
+
|
|
99
|
+
Measured, reproducible, and with no model in the loop. Method and caveats are in [docs/BENCHMARK.md](docs/BENCHMARK.md).
|
|
100
|
+
|
|
101
|
+
- **The checks a change needs, not the whole suite.** Across 30 routing scenarios (Node, Go, Rust, Python), every check the change requires is in the answer, and that answer holds about half of the repository's checks (29% on the largest corpus), not all of them. The thresholds were fixed before the first run and have not moved since.
|
|
102
|
+
- **Seconds to map a real repository.** A fresh `init` → `scaffold` → `compile` takes 1.0–4.6 s on four public repositories, from 141 to 5,142 files (axum, pydantic-ai, full-stack-fastapi-template, create-t3-turbo). No edit was needed beyond choosing each component's placement.
|
|
103
|
+
- **A briefing, not a dump.** A `query` answer is about 100–260 tokens: what the change reaches, what to read, and which checks to run.
|
|
104
|
+
- **The same graph every time.** Compiles are byte-identical, and CI can verify it.
|
|
105
|
+
- **Small and strict.** Zero runtime dependencies, a package of about 285 kB packed, 21 adapters, and 709/709 cases on the official TOML 1.0 conformance suite.
|
|
106
|
+
|
|
72
107
|
## Install manually
|
|
73
108
|
|
|
74
109
|
Requires Node.js 22+.
|
|
@@ -92,7 +127,10 @@ AgentDoc also ships with an Agent Skill at [`skills/agent-doc-system/`](skills/a
|
|
|
92
127
|
- [Authority & conflicts](docs/AUTHORITY.md)
|
|
93
128
|
- [CI & verification](docs/CI.md)
|
|
94
129
|
- [Specification](docs/SPEC.md)
|
|
130
|
+
- [Adapters](docs/ADAPTERS.md)
|
|
131
|
+
- [Benchmark](docs/BENCHMARK.md)
|
|
95
132
|
- [Agent Skill](skills/agent-doc-system/SKILL.md)
|
|
133
|
+
- [Changelog](CHANGELOG.md)
|
|
96
134
|
|
|
97
135
|
## License
|
|
98
136
|
|
package/adapters/ansible.mjs
CHANGED
|
@@ -132,7 +132,7 @@ function isYaml(f) {
|
|
|
132
132
|
|
|
133
133
|
function playbooks(repo, root) {
|
|
134
134
|
const out = [];
|
|
135
|
-
for (const f of repo.
|
|
135
|
+
for (const f of repo.walkUnit(root)) {
|
|
136
136
|
if (!isYaml(f) || /(^|\/)(tasks|handlers|vars|defaults|meta|group_vars|host_vars|templates|files)\//.test(f.slice(root.length))) continue;
|
|
137
137
|
const docs = parse(repo, f);
|
|
138
138
|
if (!docs) continue;
|
package/adapters/cache.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Cache adapter: Redis / in-memory cache client evidence as a derived binding.
|
|
2
2
|
import { Adapter } from "./registry.mjs";
|
|
3
|
+
import { joinPath } from "../core/paths.mjs";
|
|
3
4
|
|
|
4
|
-
const CACHE_HINT = /(@upstash\/redis|ioredis|redis|go-redis|redis\.go|valkey|memcache|@memcached)/i;
|
|
5
|
+
const CACHE_HINT = /(@upstash\/redis|ioredis|redis\.Redis|redis|go-redis|redis\.go|valkey|memcache|@memcached)/i;
|
|
5
6
|
|
|
6
7
|
export class CacheAdapter extends Adapter {
|
|
7
8
|
static adapterName = "cache";
|
|
@@ -10,7 +11,13 @@ export class CacheAdapter extends Adapter {
|
|
|
10
11
|
}
|
|
11
12
|
extract(ctx, unit) {
|
|
12
13
|
const { repo, prov, compRef } = ctx;
|
|
13
|
-
const evFile = unit.goModule
|
|
14
|
+
const evFile = unit.goModule
|
|
15
|
+
? joinPath(unit.root, "go.mod")
|
|
16
|
+
: unit.pythonManifest
|
|
17
|
+
? unit.pythonManifest
|
|
18
|
+
: repo.exists(joinPath(unit.root, "package.json"))
|
|
19
|
+
? joinPath(unit.root, "package.json")
|
|
20
|
+
: joinPath(unit.root, "Cargo.toml");
|
|
14
21
|
if (!repo.exists(evFile)) return {};
|
|
15
22
|
const text = repo.readText(evFile);
|
|
16
23
|
if (!CACHE_HINT.test(text)) return {};
|
|
@@ -18,7 +18,7 @@ const DOC_EXT = /\.(md|mdx|txt|adoc|rst)$/;
|
|
|
18
18
|
|
|
19
19
|
export function contractReferenceSites(repo, unit) {
|
|
20
20
|
const out = new Map(); // file -> true
|
|
21
|
-
for (const f of repo.
|
|
21
|
+
for (const f of repo.walkUnit(unit.root)) {
|
|
22
22
|
const base = path.posix.basename(f);
|
|
23
23
|
if (DOC_EXT.test(f)) continue;
|
|
24
24
|
if (f.includes("/docs/") || f.startsWith("docs/")) continue;
|
package/adapters/database.mjs
CHANGED
|
@@ -9,12 +9,16 @@
|
|
|
9
9
|
// library shipped migrations but explicitly did not own a database.
|
|
10
10
|
import { Adapter } from "./registry.mjs";
|
|
11
11
|
import { firstExistingFile, findMigrationDirs } from "../core/sourcescan.mjs";
|
|
12
|
+
import { joinPath } from "../core/paths.mjs";
|
|
12
13
|
|
|
13
14
|
const ORM_CONFIG = [
|
|
14
15
|
"drizzle.config.ts", "drizzle.config.js", "drizzle.config.mjs",
|
|
15
16
|
"prisma/schema.prisma", "schema.prisma",
|
|
16
17
|
"knexfile.js", "knexfile.ts", "sequelize.config.js", "ormconfig.json",
|
|
17
18
|
];
|
|
19
|
+
// Probed only for a Cargo package. Adding it to the list above would record
|
|
20
|
+
// a new existence probe on every non-Rust unit and change those graphs.
|
|
21
|
+
const RUST_ORM_CONFIG = ["diesel.toml"];
|
|
18
22
|
|
|
19
23
|
export class DatabaseAdapter extends Adapter {
|
|
20
24
|
static adapterName = "database";
|
|
@@ -25,12 +29,23 @@ export class DatabaseAdapter extends Adapter {
|
|
|
25
29
|
const { repo, prov, compRef } = ctx;
|
|
26
30
|
const root = unit.root;
|
|
27
31
|
const migrationDirs = findMigrationDirs(repo, root);
|
|
28
|
-
const ormConfig = firstExistingFile(repo, root, ORM_CONFIG);
|
|
32
|
+
const ormConfig = firstExistingFile(repo, root, unit.cargoPackage ? ORM_CONFIG.concat(RUST_ORM_CONFIG) : ORM_CONFIG);
|
|
29
33
|
if (!migrationDirs.length && !ormConfig) return {};
|
|
30
34
|
|
|
31
35
|
let evidencePath = ormConfig;
|
|
32
36
|
if (migrationDirs.length) {
|
|
33
|
-
evidencePath = repo.
|
|
37
|
+
evidencePath = repo.walkUnit(root, migrationDirs[0])[0] || migrationDirs[0];
|
|
38
|
+
}
|
|
39
|
+
const alembicDir = migrationDirs.find((d) => d === "alembic/versions" || d.endsWith("/alembic/versions"));
|
|
40
|
+
if (alembicDir) {
|
|
41
|
+
const ini = joinPath(root, "alembic.ini");
|
|
42
|
+
const pyproject = joinPath(root, "pyproject.toml");
|
|
43
|
+
if (repo.exists(ini)) {
|
|
44
|
+
const text = repo.readText(ini);
|
|
45
|
+
if (/^\s*\[alembic\]/m.test(text) || /^\s*script_location\s*=/m.test(text)) evidencePath = ini;
|
|
46
|
+
} else if (repo.exists(pyproject) && /\[tool\.alembic\]/.test(repo.readText(pyproject))) {
|
|
47
|
+
evidencePath = pyproject;
|
|
48
|
+
}
|
|
34
49
|
}
|
|
35
50
|
const pr = prov.add("observed", evidencePath, "migration-extractor", ["der:" + compRef + ":/bindings"]);
|
|
36
51
|
|
|
@@ -93,10 +108,10 @@ export class DatabaseAdapter extends Adapter {
|
|
|
93
108
|
}
|
|
94
109
|
}
|
|
95
110
|
|
|
96
|
-
const POOL_HINT = /(createPool|new Pool|pg\.Pool|psycopg2?\.connect|sql\.Open|mysql\.createConnection|Pool\(|DataSource|prisma\.(datasource|client)|DATABASE_URL|DB_DSN)/;
|
|
111
|
+
const POOL_HINT = /(createPool|new Pool|pg\.Pool|PgPool|psycopg2?\.connect|asyncpg\.(?:connect|create_pool)|sql\.Open|mysql\.createConnection|Pool\(|DataSource|prisma\.(datasource|client)|DATABASE_URL|DB_DSN|sqlx::migrate!|tokio_postgres|tokio-postgres|deadpool|sea_orm|sea-orm|diesel::|create_engine\s*\(|\bDATABASES\s*=)/;
|
|
97
112
|
|
|
98
113
|
function hasConnectionEvidence(ctx, unit) {
|
|
99
|
-
for (const f of ctx.repo.
|
|
114
|
+
for (const f of ctx.repo.walkUnit(unit.root)) {
|
|
100
115
|
if (/\.(ts|tsx|js|mjs|go|py|rb|java|kt|rs|ex|cs|php)$/.test(f)) {
|
|
101
116
|
if (/(^|\/)(tests?|__tests__)\//.test(f)) continue;
|
|
102
117
|
if (POOL_HINT.test(ctx.repo.readText(f))) return true;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Only the file's existence is treated as evidence; no value from these files
|
|
3
3
|
// is ever reported as deployed state.
|
|
4
4
|
import { Adapter } from "./registry.mjs";
|
|
5
|
+
import { joinPath } from "../core/paths.mjs";
|
|
5
6
|
|
|
6
7
|
const DEPLOY_FILES = [
|
|
7
8
|
"fly.toml", "app.yaml", "render.yaml", "railway.json", "vercel.json",
|
|
@@ -16,7 +17,7 @@ export class DeployConfigAdapter extends Adapter {
|
|
|
16
17
|
}
|
|
17
18
|
detect(ctx, root) {
|
|
18
19
|
for (const n of DEPLOY_FILES) {
|
|
19
|
-
if (ctx.repo.exists(root
|
|
20
|
+
if (ctx.repo.exists(joinPath(root, n))) return { path: joinPath(root, n), shape: "deployable" };
|
|
20
21
|
}
|
|
21
22
|
return null;
|
|
22
23
|
}
|
|
@@ -24,7 +25,7 @@ export class DeployConfigAdapter extends Adapter {
|
|
|
24
25
|
const { repo, prov, compRef } = ctx;
|
|
25
26
|
const out = { deployConfigs: [] };
|
|
26
27
|
for (const n of DEPLOY_FILES) {
|
|
27
|
-
const p = unit.root
|
|
28
|
+
const p = joinPath(unit.root, n);
|
|
28
29
|
if (!repo.exists(p)) continue;
|
|
29
30
|
prov.add("observed", p, "deploy-extractor", ["der:" + compRef + ":/artifact"]);
|
|
30
31
|
out.deployConfigs.push(p);
|
package/adapters/dockerfile.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Dockerfile adapter: a Dockerfile is deployable-artifact evidence.
|
|
2
2
|
import { Adapter } from "./registry.mjs";
|
|
3
|
+
import { joinPath } from "../core/paths.mjs";
|
|
3
4
|
|
|
4
5
|
export class DockerfileAdapter extends Adapter {
|
|
5
6
|
static adapterName = "dockerfile";
|
|
@@ -8,7 +9,7 @@ export class DockerfileAdapter extends Adapter {
|
|
|
8
9
|
}
|
|
9
10
|
detect(ctx, root) {
|
|
10
11
|
for (const n of ["Dockerfile", "Dockerfile.prod", "Containerfile"]) {
|
|
11
|
-
if (ctx.repo.exists(root
|
|
12
|
+
if (ctx.repo.exists(joinPath(root, n))) return { path: joinPath(root, n), shape: "deployable" };
|
|
12
13
|
}
|
|
13
14
|
return null;
|
|
14
15
|
}
|
|
@@ -16,7 +17,7 @@ export class DockerfileAdapter extends Adapter {
|
|
|
16
17
|
const { repo, prov, compRef } = ctx;
|
|
17
18
|
const out = { dockerfiles: [] };
|
|
18
19
|
for (const n of ["Dockerfile", "Dockerfile.prod", "Containerfile"]) {
|
|
19
|
-
const p = unit.root
|
|
20
|
+
const p = joinPath(unit.root, n);
|
|
20
21
|
if (!repo.exists(p)) continue;
|
|
21
22
|
prov.add("observed", p, "deploy-extractor", ["der:" + compRef + ":/artifact"]);
|
|
22
23
|
out.dockerfiles.push(p);
|
package/adapters/events.mjs
CHANGED
|
@@ -70,7 +70,7 @@ export class EventsAdapter extends Adapter {
|
|
|
70
70
|
if (other.component && visible.has(other.component.ref) && other.component.ref !== compRef) collectDecls(other.root);
|
|
71
71
|
}
|
|
72
72
|
const families = new Set();
|
|
73
|
-
for (const f of repo.
|
|
73
|
+
for (const f of repo.walkUnit(unit.root)) {
|
|
74
74
|
if (!SRC_EXT.test(f)) continue;
|
|
75
75
|
if (TEST_PATH.test(f) || TEST_FILE.test(f)) continue;
|
|
76
76
|
const text = repo.readText(f);
|
package/adapters/generic.mjs
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { Adapter } from "./registry.mjs";
|
|
8
8
|
import { resolveClientResources } from "./resource-client.mjs";
|
|
9
9
|
import { sourceFiles } from "../core/sourcescan.mjs";
|
|
10
|
+
import { joinPath } from "../core/paths.mjs";
|
|
10
11
|
|
|
11
12
|
// Conservative: a health route is an absolute string literal that looks like a
|
|
12
13
|
// liveness or readiness endpoint. Anything more specific belongs to a
|
|
@@ -50,7 +51,7 @@ export class GenericAdapter extends Adapter {
|
|
|
50
51
|
// Provenance must name a file that exists. The dependency evidence is the
|
|
51
52
|
// manifest when there is one, and otherwise the unit's descriptor.
|
|
52
53
|
const manifest = ["package.json", "go.mod", "Cargo.toml", "pyproject.toml", "pom.xml"]
|
|
53
|
-
.map((n) => unit.root
|
|
54
|
+
.map((n) => joinPath(unit.root, n))
|
|
54
55
|
.find((p) => repo.exists(p)) || ctx.componentEntity().file;
|
|
55
56
|
const clientProv = prov.add("observed", manifest, "client-resolver", ["rel:pending", "der:" + compRef + ":/bindings"]);
|
|
56
57
|
resolveClientResources(ctx, unit, compRef, clientProv);
|