Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
fd5c302
Unify Diátaxis Docs repository selection
Statusnone420 Jul 28, 2026
cb54d76
Fix exported Init adoption measurement
Statusnone420 Jul 28, 2026
e75eb88
Fix shared measurement test hook
Statusnone420 Jul 28, 2026
eee78ad
Sanitize Git inventory failures
Statusnone420 Jul 28, 2026
0d3942d
fix(docs): close unified selection review gaps
Statusnone420 Jul 28, 2026
ca57a2d
fix(docs): close missing-map init journeys
Statusnone420 Jul 28, 2026
f16feda
test(docs): align component init contract
Statusnone420 Jul 28, 2026
98fbe1a
fix(docs): bound and reuse discovery inventory
Statusnone420 Jul 28, 2026
36072ca
fix(docs): confine component setup inputs
Statusnone420 Jul 28, 2026
5481a2d
fix(docs): route direct checks through selection
Statusnone420 Jul 28, 2026
4df606b
fix(docs): preserve component scope in init receipts
Statusnone420 Jul 28, 2026
fb66e68
fix(docs): preserve init selection evidence
Statusnone420 Jul 28, 2026
535b420
fix(docs): confine roots before inventory
Statusnone420 Jul 28, 2026
1c58a5b
docs: align Doctor with repository selection
Statusnone420 Jul 28, 2026
3618b4c
fix(docs): reject occupied Init map targets
Statusnone420 Jul 28, 2026
9caa539
fix(docs): report projected Init health
Statusnone420 Jul 28, 2026
be0449c
fix(docs): fail closed on selection read errors
Statusnone420 Jul 28, 2026
516ddf9
fix(docs): keep selection evidence comparable
Statusnone420 Jul 28, 2026
bd05038
fix(docs): preserve corpus map spelling
Statusnone420 Jul 28, 2026
47f42af
fix(docs): enforce doctor and closeout bounds
Statusnone420 Jul 29, 2026
1a03a3e
fix(docs): preserve deleted-path closeout semantics
Statusnone420 Jul 29, 2026
0a99701
fix(docs): report nested selection failures
Statusnone420 Jul 29, 2026
7b8d868
fix(docs): fail closed on unreadable map targets
Statusnone420 Jul 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ The canonical product lives in `skills/docs/`. Everything under `adapters/` and
- `scripts/check.py` is the network-free entrypoint to the deterministic checker.
- `_docs_checker/scan.py` measures maintained Markdown, MarkdownX, links, anchors, titles, and reachability without executing repository code.
- `_docs_checker/paths.py` confines every path to the repository and rejects unsafe reparse boundaries.
- `_docs_checker/manifest.py` builds the additive, immutable documentation manifest: repository-complete accounting, the recorded measured boundary with its map and provider entry routes, classification facts, exclusions, limits, and a deterministic identity over normalized routes and inspected-body digests. It reuses `health.normalized_content_digest` rather than defining a second content identity. No command consumes it yet.
- `_docs_checker/selection.py` is the one place that decides which documentation a read command measures: the boundary, the map route, and — with the manifest — the entry route. The repository is the default; only an explicit human request narrows it, and that selection is recorded as partial. It reads directory listings and the repository inventory the manifest needs, never local operational state.
- `_docs_checker/manifest.py` builds the additive, immutable documentation manifest: repository-complete accounting, the recorded measured boundary with its map and provider entry routes, classification facts, exclusions, limits, and a deterministic identity over normalized routes and inspected-body digests. It reuses `health.normalized_content_digest` rather than defining a second content identity. Every read command route through `check.py` builds exactly one and publishes its identity, selected routes, and coverage completeness. `evidence_receipt.py` still takes its own explicit map and scope from the pinned corpus manifest and does not build one.
- `_docs_checker/memory.py` reads the optional `.diataxis/` control plane.
- `_docs_checker/lifecycle.py` decides whether a requested state change is authorized; `lifecycle_io.py` performs the transactional write.
- `init_adoption.py` and the closeout modules bind a preview to the exact evidence that must still be true at apply time.
Expand All @@ -25,8 +26,8 @@ The structural percentage, Trust state, semantic findings, unavailable evidence,

## The known structural defect

There is no single engine-owned documentation manifest. Boundary selection is spread across several routes that can disagree: `check.py` defaults an omitted `--scope` to `docs`, the stateless Doctor baseline runs its own discovery, an initialized Doctor uses its recorded state, and the prompt contract asks the host model to supply the map and current-truth paths. `scan.py` computes a repository-wide documentation inventory during a scan and then discards it, so the public result envelope carries no inventory and a displayed map tree is assembled by the model rather than by the engine.
Boundary selection used to be spread across several routes that could disagree: `check.py` defaulted an omitted `--scope` to `docs`, the stateless Doctor baseline ran its own discovery, an initialized Doctor used its recorded state, and the prompt contract asked the host model to supply the map and current-truth paths. Those routes now share `selection.py` and one manifest per invocation.

Consolidating those routes into one manifest that every read command consumes is the current work. The reproduced evidence is in [current state](docs/STATE.md); the target is in the [product constitution](PRODUCT.md).
What remains: the public result envelope still carries no document inventory, so a displayed map tree is assembled by the model rather than by the engine, and every role outside the measured surface is still `unresolved` rather than classified. The reproduced evidence is in [current state](docs/STATE.md); the target is in the [product constitution](PRODUCT.md).

For module diagrams and design rationale, see the [Architecture wiki page](https://github.com/Statusnone420/Skills/wiki/Architecture). For measured limits and current proof, see [BENCHMARK.md](BENCHMARK.md).
12 changes: 6 additions & 6 deletions BENCHMARK.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ This is the sole ledger for changing test counts, prompt sizes, dogfood results,

| Evidence | Result |
| --- | --- |
| Windows deterministic groups | Pass: 997 current tests — 385 core, 433 lifecycle, and 179 trajectory; 3 lifecycle cases skipped as POSIX-only; 6 lifecycle cases are strict expected failures naming the later phase that owns each unmet contract |
| Windows lifecycle feedback | Five local shards passed all 433 tests in 138.1 s; repeated local runs of the same five shards ranged 135–148 s. Hosted sharding is now measured: PR #27's `validate` run completed in 3m21s, and its slowest Windows lifecycle shard took 3m08s, against PR 0's final serial CI runs of 11m41s–12m06s. Those are single-run host counters for this repository on GitHub-hosted runners, not a general throughput claim. |
| Generated adapter prompts | 3,460–34,944 UTF-8 bytes |
| Windows deterministic groups | Current partition: 1,087 tests — 457 core, 451 lifecycle, and 179 trajectory. The focused PR 2 correction suites pass locally; the complete current Windows matrix is delegated to PR CI and is not claimed here before it runs. The prior 1,059-test snapshot passed with 3 lifecycle cases skipped as POSIX-only and 6 strict expected failures naming the later phase that owns each unmet contract. |
| Windows lifecycle feedback | Five local shards passed the prior 438-test lifecycle snapshot in 182.1 s. The current 451-test lifecycle partition is delegated to PR CI. Hosted sharding is measured separately: PR #27's `validate` run completed in 3m21s, and its slowest Windows lifecycle shard took 3m08s, against PR 0's final serial CI runs of 11m41s–12m06s. Those are single-run host counters for this repository on GitHub-hosted runners, not a general throughput claim. |
| Generated adapter prompts | 3,557–34,971 UTF-8 bytes |
| Generator regression guard | 45,000 bytes; packaging telemetry, not a product or health limit |
| Repository documentation check | At `--scope .`: 89%; 152/152 links valid; all 41 non-generated maintained pages reachable; remaining 20 unreachable and 7 duplicate-title findings are generated marketplace copies. The same checker with the scope omitted measures 2 documents and reports `clean` — see the boundary-divergence entry below. |
| Full Linux rerun for this branch | The pre-guidance 906-test snapshot passed on Ubuntu/Python 3.14.4 in 94 s. The eight guided-recovery lifecycle cases and the 76 documentation-manifest and journey-parity cases added since have not run on Linux yet; fresh CI remains required before release. |
| Repository documentation check | The default and explicit `--scope .` routes both measure boundary `.`: 89%; 151/151 links valid; all 41 non-generated maintained pages reachable; remaining 20 unreachable and 7 duplicate-title findings are generated marketplace copies. |
| Full Linux rerun for this branch | The pre-guidance 906-test snapshot passed on Ubuntu/Python 3.14.4 in 94 s. The current 1,087-test snapshot has not run on Linux yet; fresh CI remains required before release. |
| Installed-package no-state retry | Pass: 49/49 links valid, a stateless approval receipt was produced, and the repository remained unchanged without `.diataxis/` |
| Installed-package guided recovery | Pass outside the source tree: foreign-only, tracked-missing, merge-conflicted, and absent-state fixtures selected the expected four outcomes with zero writes and no private sentinel exposure |
| Installed-package treatment canary | Pass: exact stateless preview → one-file apply → candidate and installed verification clean; zero control writes, no `.diataxis/`, unchanged real Git index, and only the intended disposable worktree file changed |
Expand Down Expand Up @@ -56,7 +56,7 @@ This proves routing and safety contracts for those fixtures. It does not prove a

- A 2026-07-17 Claude/Cline canary showed that a tracked Mintlify/MDX corpus could be misread as empty. The repair made MarkdownX inert text, protected unsupported provider surfaces, and reports unmeasured evidence instead of a misleading zero.
- A 2026-07-27 no-state dogfood run exposed an uninitialized-lifecycle conflict: Doctor produced a valid read-only scan, then closeout treated absent `.diataxis/` state as corruption and recovery offered no action. The 0.1.8 candidate now distinguishes a genuinely stateless repository from partial or malformed controls, and the installed-package retry passed.
- A 2026-07-27 measurement reproduced a command boundary divergence on this repository at commit `da02ba2`: two default command routes disagreed about which documentation exists, with no repository change between runs. This is an open defect, not a repaired one. The three-route comparison is tabulated in [docs/STATE.md](docs/STATE.md), against the contract in [PRODUCT.md](PRODUCT.md).
- A 2026-07-27 measurement reproduced a command boundary divergence on this repository at commit `da02ba2`: two default command routes disagreed about which documentation exists, with no repository change between runs. The current PR 2 candidate repairs that divergence locally: the default checker, explicit repository boundary, first-contact Doctor, and Init routes consume the same repository selection and manifest identity. Hosted Linux and installed-host proof remain pending. The three-route comparison is tabulated in [docs/STATE.md](docs/STATE.md), against the contract in [PRODUCT.md](PRODUCT.md).
- A 2026-07-27 adversarial audit reproduced the same dead end for non-transactional corruption: missing, malformed, merge-conflicted, or foreign-only `.diataxis` evidence failed closed but recovery returned `action: none`. The candidate now returns one zero-write operator action, never applies it automatically, and preserves exact-approved transaction recovery unchanged.

Failures remain in this ledger after repair so the safety story cannot be rewritten as uninterrupted success.
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## 0.1.8 — Initialized-state Doctor lifecycle (unreleased candidate; entries dated 2026-07-21)

- Gave Map, Check, Doctor, Audit, and Init one engine-owned selection policy. A command with no boundary now measures the whole repository instead of silently defaulting to `docs/`, so a root document such as `GLOSSARY.md` can no longer disappear from every result. Only an explicit scope narrows the measurement, and that result reports itself as a partial component view. Every read result carries the boundary it measured, who chose it, whether the accounting is complete, and the documentation manifest identity behind it.
- Made normal nonignored untracked documentation follow the same inventory, map-selection, and provider rules as tracked documentation. Git staging no longer changes what Map or Doctor sees; ignored and excluded bodies remain unread by default.
- Routed the public Init preview through that repository measurement before any setup choice. An explicit component remains confined to its own map, and Init reports the repository measurement separately instead of allowing legacy discovery or recorded state to replace it.
- Recorded Init state now supplies adopted intent rather than a second reality: an initialized repository and a fresh clone of the same documentation produce the same manifest identity. Doctor still reports the adopted map and withholds its treatment authority when that map has left the measured documentation entirely.
- Changed which document a repository's map is when its documentation lives below the top level. A root entry document such as `README.md` now wins over a nested `packages/<name>/docs/README.md`, because the earlier rule let a vendored, example, or test-fixture `docs/README.md` represent the whole repository. A repository whose documentation is *only* nested still selects the nested map, in the same two shapes Init discovery offers.
- The shipped prompt no longer asks the host to supply `--map` or `--hot`; the engine selects the boundary, the map, the reader's entry route, and the current-truth routes. **This changes Trust coverage for existing repositories:** a current-truth route is one your map marks with `<!-- docs:current -->` or `<!-- docs:authoritative -->`. A map that names its current state in prose alone now reports Trust as `unverified` and only the map itself as hot path. Add the marker to the link to restore the previous coverage.

- Fixed the public Init → Doctor journey: bare `$docs doctor` on a validly initialized repository now returns a measured `initialized-state` baseline bound to the state's maintained map and selected scope, instead of collapsing the lifecycle preflight into a generic `discovery-not-ready` rejection with exit 2.
- Root cause was a state-machine seam present since 0.1.5: the first-contact baseline routed init-preflight lifecycle payloads through the scope-discovery accept-list, so `already-initialized` and `state-conflict` received the same rejection. The engine now dispatches lifecycle payloads explicitly, and unrecognized lifecycle statuses fail closed instead of falling through.
- Kept conflicted state fail-closed under a distinct `state-conflict` baseline that hands off to the existing Doctor recovery preview. Corrupted state, events, findings, or manifests and a missing bound local map still refuse measurement, and maintained-map treatment authority requires the measurement's own full operational-memory inspection to remain free of `state-conflict` findings.
Expand Down
6 changes: 3 additions & 3 deletions COMMANDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ Unknown or missing commands return help without side effects.

## Init: one-time adoption

Init's first response is a read-only preview built by the deterministic engine — the installed entrypoint selects the scope, accounts for every document in that scope, and constructs the preview; the model presents that verified result rather than improvising one. The engine selects and accounts; it does not yet hand back a repository-wide inventory, so a displayed map *tree* is still assembled by the model from the engine's result ([gap 2](PRODUCT.md#what-the-current-candidate-does-not-do-yet)). The preview covers the selected scope, the proposed map, the `.diataxis/` memory files, and a complete disposition manifest. `--scope <repository-relative-directory>` is the only public scope override. Nothing is written until you approve the exact preview.
Init's first response is a read-only preview built by the deterministic engine. It first measures the same repository reality as Map and Doctor, then reports any narrower setup choice separately. The model presents that verified result rather than improvising one. The engine builds a repository-wide inventory but does not yet publish its full path list in the result, so a displayed map *tree* is still assembled by the model from the engine's summary ([gap 2](PRODUCT.md#what-the-current-candidate-does-not-do-yet)). The preview covers the measured repository, the proposed setup map, the `.diataxis/` memory files, and a complete disposition manifest. `--scope <repository-relative-directory>` is the only public component override. Nothing is written until you approve the exact preview.

## Doctor: ongoing diagnosis

Doctor reports every finding in the evidenced scope, groups them into treatments, and binds each treatment to a content-derived `DOC-*` ID plus a full fingerprint — so the thing you approve is exactly the thing that runs.

> [!IMPORTANT]
> **Read the scope line on every result.** Commands do not yet agree on which files they measure: an omitted scope defaults to `docs/`, Doctor may select a different boundary, and Doctor returns no score at all on a repository with more than one candidate documentation root. Two runs that report different numbers may simply have measured different files. See [current state](docs/STATE.md) for the reproduced evidence.
> **Read the boundary line on every result.** Commands now measure the same files: an omitted scope means the whole repository, and every read result reports the boundary it measured, whether that view is `partial`, and whether the accounting behind it is complete. Ask for a component with an explicit scope and the result says so. Multiple Init setup candidates do not block Doctor's repository measurement; Doctor reports the measured repository while Init keeps the setup choice separate. See [current state](docs/STATE.md) for the reproduced evidence.

## Check: the score

`check` reports the structural percentage separately from Trust coverage (are declared current-truth routes verified?) and hash freshness. Byte measurements are telemetry with provenance — never a score input, a health failure, or a reason to delete anything.
`check` reports the structural percentage separately from Trust coverage (are declared current-truth routes verified?) and hash freshness. A route counts as declared current truth when your documentation map marks it: append `<!-- docs:current -->` (or `<!-- docs:authoritative -->`) to the end of the map line that links your current-state document. The engine reads that marker; it never infers a current-truth route from prose, and a map that declares none reports Trust as `unverified` rather than guessing. Byte measurements are telemetry with provenance — never a score input, a health failure, or a reason to delete anything.

## Boundaries

Expand Down
2 changes: 1 addition & 1 deletion INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Diátaxis Docs is a public alpha. Install from a revision you trust, review proposed changes before approving them, and keep your normal Git safeguards.

**Python 3.14 is required for the current candidate.** It is the only runtime version presently verified by CI. The deterministic engine that inspects, measures, diagnoses, and verifies a repository is Python. Installing the skill into a host is not enough: without the verified runtime and repository file access, no repository command can produce a real result — only `$docs help`, which inspects nothing. The current candidate does not yet fail cleanly when the runtime is missing or unsupported, so install Python 3.14 before you rely on a result. See [required runtime](PRODUCT.md#required-runtime).
**Python 3.14 is required for the current candidate.** It is the only runtime version presently verified by CI. The deterministic engine that inspects, measures, diagnoses, and verifies a repository is Python. Installing the skill into a host is not enough: without the verified runtime and repository file access, no repository command can produce a real result — only `$docs help`, which inspects nothing. The current candidate checks the runtime before repository inspection; if Python 3.14 cannot start, it gives one concise prerequisite message and stops without a manual or model-built fallback. See [required runtime](PRODUCT.md#required-runtime).

## Claude Code

Expand Down
Loading