From a88e034a9bc97f509eb3be1c862b5958b017e9a4 Mon Sep 17 00:00:00 2001 From: DJJ Date: Thu, 27 Aug 2026 20:02:34 +0800 Subject: [PATCH 1/4] fix: enforce llmdoc context floor routing --- .agents/skills/init/SKILL.md | 12 +- .agents/skills/llmdoc/SKILL.md | 1 + .../llmdoc/references/knowledge-topology.md | 243 ++++++++++++++++++ .agents/skills/prune/SKILL.md | 2 + .agents/skills/update/SKILL.md | 10 +- .claude-plugin/marketplace.json | 2 +- .claude-plugin/plugin.json | 2 +- .codex-plugin/plugin.json | 2 +- .codex/agents/recorder.toml | 19 +- README.md | 3 + README.zh-CN.md | 3 + agents/recorder.md | 19 +- cli/package-lock.json | 4 +- cli/package.json | 2 +- cli/schemas/output.schema.json | 8 + cli/src/commands/context.ts | 17 +- cli/src/lib/workspace.ts | 44 ++++ cli/tests/cli.test.ts | 73 ++++++ docs/agent-integration.md | 2 + docs/v3-design/03-cli.md | 4 +- package-lock.json | 6 +- package.json | 2 +- scripts/check-codex-surface.mjs | 44 ++++ skills/init/SKILL.md | 12 +- skills/llmdoc/SKILL.md | 1 + .../llmdoc/references/knowledge-topology.md | 243 ++++++++++++++++++ skills/prune/SKILL.md | 2 + skills/update/SKILL.md | 10 +- website/src/pages/docs/cli/index.astro | 4 +- website/src/pages/docs/concepts/index.astro | 18 ++ website/src/pages/docs/workflows/index.astro | 4 +- website/src/pages/zh/docs/cli/index.astro | 4 +- .../src/pages/zh/docs/concepts/index.astro | 18 ++ .../src/pages/zh/docs/workflows/index.astro | 4 +- 34 files changed, 796 insertions(+), 48 deletions(-) create mode 100644 .agents/skills/llmdoc/references/knowledge-topology.md create mode 100644 skills/llmdoc/references/knowledge-topology.md diff --git a/.agents/skills/init/SKILL.md b/.agents/skills/init/SKILL.md index 10b7489..b76454c 100644 --- a/.agents/skills/init/SKILL.md +++ b/.agents/skills/init/SKILL.md @@ -33,18 +33,21 @@ Stop instead of improvising when: ## Workflow 1. Inventory the repository surface. + - Before choosing boundaries, read [Knowledge Topology and Context Floor](../llmdoc/references/knowledge-topology.md). Use its domain/topic tests and Context Floor acceptance contract. - Read top-level manifests, README files, entrypoints, test surfaces, and release/config files. - Use one or more `investigator` subagents for complementary evidence scopes when the repository is large enough to benefit; keep their write ownership in `.llmdoc-tmp/`. - - Check coverage and resolve conflicting evidence before handing the result to `recorder`. + - Build the reference's scratch domain/owner matrix. Give every first-class subsystem an expected owner document or an explicit no-doc reason; resolve conflicting evidence before handing the result to `recorder`. 2. Build the first V3 knowledge surface with `recorder`. - Define topic boundaries before drafting leaf docs. - - Prefer a small number of high-value docs over broad shallow coverage. + - Prefer the smallest sufficient set of high-value owner docs over broad shallow inventory. Depth never excuses a first-class subsystem with neither an owner nor an intentional no-doc decision. - Keep stable knowledge in `llmdoc/` and validity state in `llmdoc/meta.json`. - - Create the V3 root singleton plus one-level topic directories; topics are plain directories with no `index.mdx` entry node. + - Create root singleton docs only for genuinely cross-topic contracts; otherwise create only the necessary one-level topic directories. Topics are plain directories with no `index.mdx` entry node. 3. Validate before reporting success. - Seed the ledger with `init-state` (writes meta.json with null revisions), then run `validate` and fix all schema, routing, and reference failures. + - Treat `validate` as structural only. After it passes, run the reference's Context Floor acceptance: natural-query searches, per-boundary `context --files` probes, broad-glob precision probes, and `tree --docs` plus `index`/`context` relation review. + - Repair missing or imprecise routes before success. An intended owner must be reached directly; a generic root document alone is not sufficient. - Docs added after `init-state` already seeded the ledger get their entries via `adopt `; never hand-edit `meta.json` or recreate existing files through `new`. - Finalize with `commit --all -m "docs: bootstrap llmdoc"` — it commits the surface, brands fingerprints, and lands the meta follow-up commit in one step. - On a validation failure that cannot be repaired in-run, roll back the init write-set. @@ -68,5 +71,6 @@ Always report: - whether init ran or was refused - the investigation report path or paths used - the topics and stable docs created +- the domain/owner matrix outcome, including concept routes, representative file routes, and intentional no-doc decisions - the `validate` and `commit` results -- any material gaps left for later `/llmdoc:update` +- any intentionally reconstructable areas or non-blocking follow-ups; an unresolved first-class gap makes init `incomplete`, not `success` diff --git a/.agents/skills/llmdoc/SKILL.md b/.agents/skills/llmdoc/SKILL.md index d68c421..1455682 100644 --- a/.agents/skills/llmdoc/SKILL.md +++ b/.agents/skills/llmdoc/SKILL.md @@ -50,6 +50,7 @@ These entry points are alternatives, not a sequence. Stop as soon as the task ha - Before non-trivial edits, align with the user. - If `llmdoc/` does not exist, suggest `/llmdoc:init`; do not fabricate the knowledge surface ad hoc. - When a task produces durable knowledge changes, suggest `/llmdoc:update` at the end. +- For topology or routing work, read [Knowledge Topology](references/knowledge-topology.md). - Never suggest `/llmdoc:upgrade`; it runs only when the user asks for it by name. ## Reflection Gate diff --git a/.agents/skills/llmdoc/references/knowledge-topology.md b/.agents/skills/llmdoc/references/knowledge-topology.md new file mode 100644 index 0000000..ada1818 --- /dev/null +++ b/.agents/skills/llmdoc/references/knowledge-topology.md @@ -0,0 +1,243 @@ +# Knowledge Topology and Context Floor + +Use this reference when bootstrapping llmdoc, creating or moving a topic or document, repairing unmapped code, or judging whether the knowledge surface reaches the Context Floor. It expands the mandatory gates in the operating skills; it is not a checklist for routine retrieval. + +## Design model + +llmdoc is a task-oriented semantic routing graph, not a compressed copy of the repository. Its job is to make the right durable context reachable before broad source exploration while leaving live implementation facts in their canonical sources. + +Five principles shape the model: + +1. **Minimum sufficient graph.** Optimize for the smallest connected knowledge surface that supports correct work, not maximum prose, file coverage, or taxonomy completeness. +2. **Decisions over observations.** Stable documents preserve costly-to-recover decisions, rationale, boundaries, invariants, contracts, failure semantics, and risky workflows. Source, schema, tests, manifests, and CLI help remain authoritative for cheap live facts. +3. **Ownership over layout.** Knowledge follows stable responsibility and decision boundaries. A domain may cross packages, and one package may contain several domains. +4. **Progressive disclosure.** `tree` exposes the map, descriptions and search expose semantic candidates, `context --files` exposes change owners, relations add required closure, and `show` loads only selected bodies. Each layer must support a stop decision. +5. **Review coupling.** `code.paths` connects changes to the documents whose claims may become false. Mapping therefore follows semantic review obligation, not provenance alone or a coverage target. + +These principles create a deliberate split of authority: + +| Concern | Owner | +|---|---| +| Current implementation facts | Source, tests, schema, manifests, generated config | +| Durable engineering meaning | llmdoc document body | +| Concept and change routing | `description`, document path, `code.paths`, `relations` | +| Freshness and validity | Git-based llmdoc ledger and CLI | +| Investigation evidence | `.llmdoc-tmp/` | + +An authoring choice is justified only when it improves retrieval, comprehension, or review coupling without duplicating a cheaper source of truth. This is why V3 has one topic level, no hand-maintained index pages, only three document kinds, and a small front matter surface. + +## The two independent gates + +Do not use one gate as a substitute for the other: + +1. **Stable Knowledge Gate — prose value.** Preserve only durable decisions, rationale, boundaries, invariants, failure semantics, contracts, and risky workflows that source does not cheaply reconstruct. +2. **Routing Gate — owner reachability.** A representative concept query and a representative decision-bearing source file must reach the document that owns that knowledge. + +Mapping a file does not require narrating the file in prose. Conversely, concise prose does not excuse a missing route. `validate` proves structural validity; it does not prove semantic ownership or Context Floor coverage. + +## What the Context Floor means + +The Context Floor is the smallest connected knowledge surface from which a new agent can: + +- find the owner of each first-class subsystem using the vocabulary a developer would naturally query; +- route from a concrete change to the document whose claims need review; +- recover the decisions, boundaries, invariants, and failure model needed before reading implementation details; +- follow mandatory prerequisites across topics without loading unrelated documents. + +It is not a target document count, token count, or percentage of files mapped. Generated files, barrels, trivial helpers, and code with no durable knowledge may intentionally remain unmapped. + +A subsystem is usually first-class when at least one of these is true: + +- it owns an external or cross-module contract; +- it has a distinct lifecycle, authority boundary, or failure model; +- changes to it require decisions that are not local implementation details; +- it contains a risky repeatable operational or maintenance workflow. + +Package and directory boundaries are evidence, not automatic knowledge boundaries. + +## Domain, topic, and document + +Use three reasoning levels: + +| Level | Question | llmdoc representation | +|---|---|---| +| Domain | What stable responsibility or decision boundary exists? | Analysis unit; it may span packages or split one package | +| Topic | What retrieval neighborhood should a caller enter? | One directory directly below `llmdoc/` | +| Document | What single owner answers one coherent class of questions? | One `.mdx` file with a kind and routing metadata | + +### Domain boundary test + +Keep concerns in the same domain when they share most of the following: + +- the same conceptual owner or authority; +- the same invariants and failure model; +- the same change reasons and review questions; +- the same vocabulary in natural-language searches. + +Split domains when the owner, authority, failure model, or common questions remain distinct even if the code is colocated. Join code from different packages into one domain when it implements one contract or execution model. + +Avoid domains named after temporary projects, release phases, teams, or generic layers such as `utils`. Prefer stable responsibility names such as identity delegation, request execution, or release integrity. + +### Topic boundary test + +A topic is the physical retrieval partition for one stable domain or a coherent subdomain. Create a new topic only when it gives callers a durable vocabulary and keeps unrelated searches or file routes from loading each other. + +Use the same topic when documents share a bounded responsibility and are commonly needed together. Split a topic when it contains independent owners or failure models and callers usually need only one side. A one-document topic is valid only when the boundary is genuinely distinct and expected to persist. + +Root-level singleton documents are reserved for contracts that are truly cross-topic, such as the repository-wide execution model. Do not use a generic root architecture document as the only owner for otherwise independent subsystems. + +### Document boundary and kind + +Choose the kind from the question the document answers: + +- `architecture`: Why is this responsibility shaped this way? Who owns what? What flow, invariants, tradeoffs, and failure semantics constrain changes? +- `guide`: When and how is a risky or non-obvious workflow performed? What are its branches, safety checks, verification, recovery, and stopping conditions? +- `reference`: What stable vocabulary, contract, compatibility rule, default, or decision table must be looked up precisely? + +Split when a document has more than one conceptual owner, more than one independently invoked workflow, or unrelated query vocabularies. Keep it intact when a split would break one execution model or invariant chain merely to satisfy a line target. + +## What to write + +Use these skeletons selectively. Omit empty sections rather than filling them with source inventory. + +### Architecture + +1. Scope and ownership boundary +2. Execution or data flow +3. Decisions and rationale, including rejected alternatives when they affect future choices +4. Invariants, authority boundaries, and non-obvious failure semantics +5. Cross-topic contracts and change consequences +6. A few canonical source anchors + +### Guide + +1. Trigger and when not to use the workflow +2. Preconditions and safety boundary +3. Steps with meaningful decision branches +4. Verification and success signals +5. Failure handling, rollback, and escalation conditions + +### Reference + +1. Scope and source of authority +2. Stable terms, fields, states, defaults, or compatibility rules +3. Decision table or lookup structure +4. Exceptions and relationships to owner documents + +Do not preserve current file lists, line counts, release snapshots, copied CLI help, investigation narratives, or facts that a canonical manifest or schema answers in minutes. Source anchors support durable claims; they do not replace those claims. + +## Front matter as retrieval design + +### `description` + +Write a compact retrieval promise, not an abstract summary. Include the distinctive responsibility, contract terms, and questions a developer is likely to search. Avoid descriptions that could apply to several documents, such as “architecture overview” or “core behavior.” + +### `code.paths` + +Map semantic ownership rather than directory membership. Useful anchors include: + +- canonical contract, schema, or protocol definitions; +- entrypoints and orchestrators that establish the execution model; +- boundary adapters whose behavior changes the documented contract; +- persistence or configuration surfaces that encode documented invariants; +- tests only when they are the clearest owner of a non-obvious contract. + +Apply both tests: + +- **Recall:** every first-class decision-bearing surface has a route to its owner document. +- **Precision:** every matched file is relevant enough that changing it should trigger review of that document. + +Do not add a broad package glob merely to raise coverage. If an unrelated sibling file matches, narrow the glob or add exact patterns. Do not map generated, vendored, barrel, or incidental helper files unless they genuinely own part of the contract. + +### `relations` + +Use `requires` only when a caller must read the prerequisite to apply this document safely. Use `related` for useful neighbors. Relations connect owner documents; they do not compensate for missing `code.paths` or recreate a manual index tree. + +## Bootstrap procedure + +Before drafting, keep a scratch domain/owner matrix in `.llmdoc-tmp/`: + +| Domain or subsystem | Natural queries | Declared implementation boundaries | Entry/contract probes | Leaf/boundary probes | Expected owner doc | Status and evidence | +|---|---|---|---|---|---|---| + +Allowed statuses are `documented`, `intentionally reconstructable`, and `gap`. A first-class subsystem left unclassified or at `gap` makes init incomplete; do not silently defer it while reporting success. + +List every distinct package, adapter, runtime, authority, or external boundary that participates in a domain. A cross-package contract is not covered merely because two probes from the same package pass. + +An `intentionally reconstructable` row must name its canonical recovery source, estimate that recovery takes only a few minutes, state why no durable decision or failure model is hidden there, and include a representative file expected to remain unmapped. Missing or conflicting evidence makes it a `gap`, not a no-doc decision. + +Then: + +1. Inventory first-class domains from manifests, entrypoints, external contracts, tests, release/config surfaces, and failure boundaries. +2. Group them into topics using ownership, invariants, failure model, change reasons, and query vocabulary. +3. Assign one canonical owner document for every durable decision cluster or risky workflow. +4. Draft only claims that pass the Stable Knowledge Gate. +5. Add precise routes from representative decision-bearing files to those owners. +6. Add `requires` only for mandatory reading order. +7. Run the Context Floor acceptance checks below. + +Keep the executable evidence in a scratch probe table rather than stable prose: + +| Domain and boundary | Query or file | Expected owner/result | Actual owner/rank/result | Pass or repair reason | +|---|---|---|---|---| + +“A few high-value docs” means the smallest sufficient owner set. It never means leaving a first-class subsystem without an explicit owner or an intentional no-doc decision. + +## Context Floor acceptance + +Run these checks after `validate` during init, and for the affected scope during update or topology changes. + +### 1. Concept route + +For each first-class subsystem, run two or three natural queries, including one term that does not simply repeat the document title: + +```sh +npx -y @tokenroll/llmdoc search "" +``` + +The intended owner should be the first relevant result from its description and content. If it is not first, record the actual rank and why earlier results do not make routing ambiguous; otherwise repair the description or boundary. If only a generic root document appears, the subsystem is not adequately owned. + +### 2. File route + +Test at least one canonical entry or contract file and one representative leaf or boundary file per documented subsystem, plus at least one owner file from every declared implementation boundary. Invoke once per file because `unmappedFiles` is attributed per input while owner documents remain a union: + +```sh +npx -y @tokenroll/llmdoc context --files +npx -y @tokenroll/llmdoc context --files +``` + +The intended owner must appear, along with genuinely required prerequisites. Zero results or only a generic cross-topic document is a routing gap. + +### 3. Precision probe + +Treat every `code.paths` pattern containing glob metacharacters such as `*`, `?`, `[]`, or `{}` as a wildcard mapping. For each wildcard—especially recursive or package-level patterns—probe an unrelated sibling inside the matched tree. If that file routes to the document even though its change would not require reviewing the document, narrow the mapping. Exact paths are exempt. + +### 4. Connected floor + +Use `tree --docs` to confirm that a cold reader can name the repository-wide contract and enter every first-class topic. Then use `index --topic ` to inspect declared relations and per-file `context --files` to verify the actual `requires` closure. The chain must work without a catch-all document; `tree` alone does not expose relations. + +### 5. Explicit gaps + +Record intentional no-doc decisions and unresolved gaps in the init/update report. An unresolved first-class gap prevents init success. Do not create filler prose to make the matrix look complete. + +The floor passes when every first-class subsystem has a useful concept route, every documented decision-bearing surface has a precise file route, prerequisites are connected, and all omissions are intentional. Structural `validate` success alone is insufficient. + +## Update triage + +When `delta` reports an unmapped or newly moved file, classify it before writing: + +1. **Missing mapping:** an existing document already owns the durable knowledge; repair `code.paths` and run scoped routing checks. +2. **Missing owner:** the change exposes a stable domain, decision cluster, or workflow with no suitable document; decide the topic and create or split the owner. +3. **Intentional no-doc:** the file is reconstructable implementation detail and owns no durable knowledge; leave it unmapped and state that decision in the report when material. + +When boundaries, names, or source locations change, rerun concept, file, and precision checks for the affected topics even if the prose remains semantically true. + +## Failure patterns + +- Treating package folders as topics without testing ownership or query vocabulary +- Using one repository architecture doc as a catch-all owner +- Mapping a whole source tree to one doc to manufacture coverage +- Writing detailed file inventories while omitting rationale, invariants, or failure semantics +- Splitting by document size while breaking a coherent execution model +- Assuming `validate` proves retrieval quality +- Declaring sparse output healthy solely because every sentence passes the Stable Knowledge Gate diff --git a/.agents/skills/prune/SKILL.md b/.agents/skills/prune/SKILL.md index 4168d33..020ae2c 100644 --- a/.agents/skills/prune/SKILL.md +++ b/.agents/skills/prune/SKILL.md @@ -36,6 +36,7 @@ This command does not authorize source-code edits. - A clean duplicate/fragment report does not prove good knowledge density; semantic review remains the recorder's job. 2. Decide the convergence plan with `recorder`. + - If the plan moves ownership, changes topic boundaries, or merges/splits documents, read [Knowledge Topology and Context Floor](../llmdoc/references/knowledge-topology.md) before rewriting. - Merge duplicated docs. - Rewrite fragmented docs when a clearer topic boundary exists. - Apply the Stable Knowledge Gate sentence by sentence. Remove command/file inventories, current-state evidence, and other facts that a reader can cheaply recover from canonical sources. @@ -45,6 +46,7 @@ This command does not authorize source-code edits. 3. Re-validate the result. - Run `validate`. + - When ownership or routing changed, run the reference's scoped concept, per-file owner, broad-glob precision, and prerequisite checks; structural validation alone is insufficient. - Re-run `prune --report` and compare document/token scale with the first report. - Confirm surviving stable concepts retain accurate `code.paths`. Do not attach unrelated paths merely to preserve a coverage metric; call out any intentional coverage reduction. - Finalize with `commit -m ""`, which fingerprints the surviving docs and lands the `meta.json` follow-up commit automatically. diff --git a/.agents/skills/update/SKILL.md b/.agents/skills/update/SKILL.md index e1c8339..80e837d 100644 --- a/.agents/skills/update/SKILL.md +++ b/.agents/skills/update/SKILL.md @@ -43,19 +43,22 @@ This command does not authorize source-code edits. - Light: owners are mapped and facts are clear. - Deep: files are unmapped, owner/root cause is unclear, boundaries changed, facts conflict, or impact is broad. - This choice controls evidence gathering only. It does not decide whether prose must change. + - For unmapped or moved code and boundary changes, read [Knowledge Topology and Context Floor](../llmdoc/references/knowledge-topology.md) and classify each surface as missing mapping, missing owner, or intentional no-doc. 4. Decide the semantic outcome with `recorder`. - Treat `delta` and candidates as review evidence, not a write list or prose to copy. - Rewrite only false/incomplete claims or new conclusions that pass the Stable Knowledge Gate. Reflection candidates must pass both gates. + - Gate prose and routing independently; true prose may still need routing metadata repair. - If the document remains true and the change adds only reconstructable evidence, mark it verified unchanged. - Light: `recorder` decides from targeted CLI reads. Deep: `investigator` reports evidence, then `recorder` applies the gate. - Scaffold brand-new docs with `new`; register docs that already exist as files with `adopt ` — never hand-edit `meta.json` or recreate the file through `new`. 5. Finalize. + - Run `validate`; after mapping or boundary changes, also run the reference's scoped routing acceptance. - If prose changed, run `commit -m ""`, adding `--verified ` for reviewed unchanged docs. If all stayed unchanged, run `commit --verified `. Full verification uses `--all`, never with `--verified`. - - `commit` gates on validate, commits any `llmdoc/` prose write-set, refreshes the changed and verified fingerprints, and lands `meta.json` separately. Never hand-roll this sequence out of `validate` plus `fingerprint`, and never `--amend` (that rewrites the hash fingerprints just recorded). - - `commit` preflights the fingerprint preconditions before creating any commit: if mapped source is still dirty it fails closed with the worktree untouched. Commit or clean the related source first, then rerun `commit` — do not fall back to a manual sequence. - - Re-check `status` when you need a final stale/clean signal. After a successful finalize, `N commits behind HEAD, metadata-only; knowledge clean` is the expected end state (the meta follow-up commit), not staleness — do not chase it with another update. + - `commit` validates, commits prose, refreshes fingerprints, and lands `meta.json` separately. Never reconstruct this sequence manually or `--amend` it. + - Dirty mapped source makes `commit` fail closed; commit or clean that source, then retry. + - After success, `N commits behind HEAD, metadata-only; knowledge clean` reflects the meta follow-up commit, not staleness. 6. Fold durable lessons into stable docs directly. - Put reusable cautions, invariants, and workflow fixes into the relevant architecture or guide docs. @@ -83,4 +86,5 @@ Always report: - any investigation report path - each reflection candidate and its disposition (`promoted`, `already_covered`, `dismissed`, or `pending`) - the stable docs changed and the docs verified unchanged by `recorder` +- routing classifications and checks when topology changed - the `commit` result — validate gate, fingerprint refresh, and the meta follow-up commit — or why finalization was skipped diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 0ee1543..aa0c720 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -10,7 +10,7 @@ "name": "llmdoc", "source": "./", "description": "Persistent engineering context powered by the llmdoc CLI and progressive MDX knowledge retrieval", - "version": "3.5.1" + "version": "3.5.2" } ] } diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 456a0f1..d34bbb6 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "llmdoc", "description": "Persistent engineering context powered by the llmdoc CLI and progressive MDX knowledge retrieval", - "version": "3.5.1", + "version": "3.5.2", "author": { "name": "DJJ & Danniel" } diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 6500572..dcae0bc 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "llmdoc", - "version": "3.5.1", + "version": "3.5.2", "description": "Persistent engineering context powered by the llmdoc CLI and progressive MDX knowledge retrieval", "skills": "./.agents/skills/" } diff --git a/.codex/agents/recorder.toml b/.codex/agents/recorder.toml index 12cff27..92abded 100644 --- a/.codex/agents/recorder.toml +++ b/.codex/agents/recorder.toml @@ -19,17 +19,18 @@ When invoked: - current wording before a rewrite → `show ` - convergence candidates when pruning → `prune --report` 2. Read scoped investigator reports and declared `.llmdoc-tmp/reflections/pending/` candidates only when the task actually depends on them. Treat candidates as evidence to verify, never as prose to copy. -3. Determine the impacted concepts, the correct topic boundaries, and whether durable knowledge actually changed. A changed source file or a `delta` hit creates a review obligation, not a documentation obligation. +3. Determine the impacted concepts, the correct topic boundaries, and whether durable knowledge actually changed. A changed source file or a `delta` hit creates a review obligation, not a documentation obligation. Before initializing, creating/moving/splitting/merging a document or topic, repairing unmapped ownership, or auditing the Context Floor, read `knowledge-topology.md` from the installed llmdoc skill's `references/` directory. 4. Apply the Stable Knowledge Gate before adding or retaining a claim. A stable claim should satisfy all of these tests: - **Decision effect:** reading it changes a future design, implementation, operation, or review choice. - **Recovery cost:** it cannot be reconstructed reliably in a few minutes from source, schema, CLI help, tests, or generated configuration. - **Durability:** it is expected to survive routine commits instead of describing one release or the current investigation. - **Canonical ownership:** it has one clear home and adds rationale, boundaries, consequences, or relationships beyond a source pointer. Transitional facts are allowed only when omitting them would cause unsafe behavior; state the condition that retires them. -5. Write or rewrite only claims that pass the gate. Keep `code.paths`, relations, and a few canonical anchors as provenance and routing metadata; do not repeat their inventories in prose. Never hand-edit `llmdoc/meta.json`: every ledger change goes through the CLI (`new`, `adopt`, `mv`, `fingerprint`, `commit`), which keeps the format and revisions honest. When a valid `.mdx` already exists but is missing from the ledger, register it with `llmdoc adopt ` instead of recreating it through `new`. -6. Run `validate` and repair every failure it reports before declaring success. -7. Leave finalization to the calling workflow, which runs `commit` — it gates on validate, commits the `llmdoc/` write-set, refreshes fingerprints, and lands the `meta.json` follow-up commit in one step. Docs reviewed but left unchanged are passed through `commit --verified `. Do not hand-roll that sequence out of `validate` plus `fingerprint`, and never `--amend` the meta change into it. Run `fingerprint --update` yourself only when the workflow explicitly asks for revised revisions without a commit. -8. Report created, updated, deleted, and verified-unchanged documents separately. +5. Apply the Routing Gate independently. `code.paths` is semantic ownership, not prose inventory or a coverage score. Every first-class decision-bearing surface needs a route to its canonical owner; every mapped file should be relevant enough that changing it creates a real review obligation. A mapping change may be required even when stable prose remains true. +6. Write or rewrite only claims that pass the Stable Knowledge Gate. Keep `code.paths`, relations, and a few canonical anchors as routing and provenance metadata; do not repeat their inventories in prose. Never hand-edit `llmdoc/meta.json`: every ledger change goes through the CLI (`new`, `adopt`, `mv`, `fingerprint`, `commit`), which keeps the format and revisions honest. When a valid `.mdx` already exists but is missing from the ledger, register it with `llmdoc adopt ` instead of recreating it through `new`. +7. Run `validate` and repair every failure it reports. Treat it as structural only. When topology or mappings changed, also run scoped concept, per-file owner, broad-glob precision, and prerequisite checks from the knowledge-topology reference before declaring success. +8. Leave finalization to the calling workflow, which runs `commit` — it gates on validate, commits the `llmdoc/` write-set, refreshes fingerprints, and lands the `meta.json` follow-up commit in one step. Docs reviewed but left unchanged are passed through `commit --verified `. Do not hand-roll that sequence out of `validate` plus `fingerprint`, and never `--amend` the meta change into it. Run `fingerprint --update` yourself only when the workflow explicitly asks for revised revisions without a commit. +9. Report created, updated, deleted, and verified-unchanged documents separately, plus missing-mapping, missing-owner, intentional no-doc, and routing-check outcomes when relevant. Consistency rules: @@ -53,10 +54,14 @@ V3 document model: Routing tests: -- Topic purpose and boundary belong in the topic's `architecture` doc when they need prose; otherwise rely on document descriptions. +- Domain is an analysis boundary; topic is a durable retrieval boundary. Package and directory layouts are evidence, not automatic topics. +- Topic purpose and boundary belong in the topic's `architecture` doc when they need durable prose; otherwise rely on document descriptions. - Use `kind=architecture` for flows, ownership boundaries, invariants, and why the implementation is shaped that way. - Use `kind=reference` for stable lookup facts and contracts. - Use `kind=guide` for repeatable workflows. +- A `description` is a retrieval promise: name the distinctive responsibility, contract terms, and questions the document answers. +- A broad `code.paths` glob is valid only when an unrelated sibling cannot spuriously route to the document. Test representative owner files one at a time with `context --files` so a successful match cannot hide an unmapped input. +- `requires` means mandatory prior reading; `related` means a useful neighbor. Relations do not repair missing source routes. - Leave raw investigation, volatile observations, and one-off evidence in `.llmdoc-tmp/`. Split rules: @@ -64,7 +69,7 @@ Split rules: - One concept per document. - One workflow per guide. - One ownership boundary or invariant cluster per architecture doc. -- During init, depth beats premature fragmentation. Prefer a small set of strong core docs before broad expansion. +- During init, depth beats premature fragmentation, but never missing ownership. Prefer the smallest sufficient set of strong owner docs; classify every first-class subsystem as documented, intentionally reconstructable, or a blocking gap. - If a document grows large only because it is preserving one coherent execution model, invariant set, or contract cluster, keep it intact until a clean split is obvious. - If a document exceeds roughly 150 lines (the `validate` warning limit), covers more than one workflow, or mixes stable facts with transient notes, split it when doing so improves retrieval without discarding essential reasoning flow. - Keep `code.paths` and `relations` accurate when merging, splitting, or deleting docs. diff --git a/README.md b/README.md index c8e1eb8..f8cc49c 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,9 @@ These are alternatives, not a fixed sequence. Once llmdoc narrows the working set, use native tools for exact source text, line numbers, test behavior, counts, and Git state. +`context --files` evaluates every input independently and reports +`unmappedFiles`; a non-empty impacted set never hides unmapped siblings. + ```bash # Map the knowledge surface npx -y @tokenroll/llmdoc tree --docs diff --git a/README.zh-CN.md b/README.zh-CN.md index 9da1db2..ba1e0a7 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -105,6 +105,9 @@ flowchart LR 这些入口是备选关系,不是固定步骤。llmdoc 圈定工作集后,再使用原生工具核对 源码原文、行号、测试行为、计数和 Git 状态。 +`context --files` 会逐个判断输入并报告 `unmappedFiles`;非空的 impacted +结果不会再掩盖同批查询中未映射的其他路径。 + ```bash # 展开知识地图 npx -y @tokenroll/llmdoc tree --docs diff --git a/agents/recorder.md b/agents/recorder.md index a4d07f1..3c710a0 100644 --- a/agents/recorder.md +++ b/agents/recorder.md @@ -21,17 +21,18 @@ When invoked: - current wording before a rewrite → `show ` - convergence candidates when pruning → `prune --report` 2. Read scoped investigator reports and declared `.llmdoc-tmp/reflections/pending/` candidates only when the task actually depends on them. Treat candidates as evidence to verify, never as prose to copy. -3. Determine the impacted concepts, the correct topic boundaries, and whether durable knowledge actually changed. A changed source file or a `delta` hit creates a review obligation, not a documentation obligation. +3. Determine the impacted concepts, the correct topic boundaries, and whether durable knowledge actually changed. A changed source file or a `delta` hit creates a review obligation, not a documentation obligation. Before initializing, creating/moving/splitting/merging a document or topic, repairing unmapped ownership, or auditing the Context Floor, read `knowledge-topology.md` from the installed llmdoc skill's `references/` directory. 4. Apply the Stable Knowledge Gate before adding or retaining a claim. A stable claim should satisfy all of these tests: - **Decision effect:** reading it changes a future design, implementation, operation, or review choice. - **Recovery cost:** it cannot be reconstructed reliably in a few minutes from source, schema, CLI help, tests, or generated configuration. - **Durability:** it is expected to survive routine commits instead of describing one release or the current investigation. - **Canonical ownership:** it has one clear home and adds rationale, boundaries, consequences, or relationships beyond a source pointer. Transitional facts are allowed only when omitting them would cause unsafe behavior; state the condition that retires them. -5. Write or rewrite only claims that pass the gate. Keep `code.paths`, relations, and a few canonical anchors as provenance and routing metadata; do not repeat their inventories in prose. Never hand-edit `llmdoc/meta.json`: every ledger change goes through the CLI (`new`, `adopt`, `mv`, `fingerprint`, `commit`), which keeps the format and revisions honest. When a valid `.mdx` already exists but is missing from the ledger, register it with `llmdoc adopt ` instead of recreating it through `new`. -6. Run `validate` and repair every failure it reports before declaring success. -7. Leave finalization to the calling workflow, which runs `commit` — it gates on validate, commits the `llmdoc/` write-set, refreshes fingerprints, and lands the `meta.json` follow-up commit in one step. Docs reviewed but left unchanged are passed through `commit --verified `. Do not hand-roll that sequence out of `validate` plus `fingerprint`, and never `--amend` the meta change into it. Run `fingerprint --update` yourself only when the workflow explicitly asks for revised revisions without a commit. -8. Report created, updated, deleted, and verified-unchanged documents separately. +5. Apply the Routing Gate independently. `code.paths` is semantic ownership, not prose inventory or a coverage score. Every first-class decision-bearing surface needs a route to its canonical owner; every mapped file should be relevant enough that changing it creates a real review obligation. A mapping change may be required even when stable prose remains true. +6. Write or rewrite only claims that pass the Stable Knowledge Gate. Keep `code.paths`, relations, and a few canonical anchors as routing and provenance metadata; do not repeat their inventories in prose. Never hand-edit `llmdoc/meta.json`: every ledger change goes through the CLI (`new`, `adopt`, `mv`, `fingerprint`, `commit`), which keeps the format and revisions honest. When a valid `.mdx` already exists but is missing from the ledger, register it with `llmdoc adopt ` instead of recreating it through `new`. +7. Run `validate` and repair every failure it reports. Treat it as structural only. When topology or mappings changed, also run scoped concept, per-file owner, broad-glob precision, and prerequisite checks from the knowledge-topology reference before declaring success. +8. Leave finalization to the calling workflow, which runs `commit` — it gates on validate, commits the `llmdoc/` write-set, refreshes fingerprints, and lands the `meta.json` follow-up commit in one step. Docs reviewed but left unchanged are passed through `commit --verified `. Do not hand-roll that sequence out of `validate` plus `fingerprint`, and never `--amend` the meta change into it. Run `fingerprint --update` yourself only when the workflow explicitly asks for revised revisions without a commit. +9. Report created, updated, deleted, and verified-unchanged documents separately, plus missing-mapping, missing-owner, intentional no-doc, and routing-check outcomes when relevant. Consistency rules: @@ -55,10 +56,14 @@ V3 document model: Routing tests: -- Topic purpose and boundary belong in the topic's `architecture` doc when they need prose; otherwise rely on document descriptions. +- Domain is an analysis boundary; topic is a durable retrieval boundary. Package and directory layouts are evidence, not automatic topics. +- Topic purpose and boundary belong in the topic's `architecture` doc when they need durable prose; otherwise rely on document descriptions. - Use `kind=architecture` for flows, ownership boundaries, invariants, and why the implementation is shaped that way. - Use `kind=reference` for stable lookup facts and contracts. - Use `kind=guide` for repeatable workflows. +- A `description` is a retrieval promise: name the distinctive responsibility, contract terms, and questions the document answers. +- A broad `code.paths` glob is valid only when an unrelated sibling cannot spuriously route to the document. Test representative owner files one at a time with `context --files` so a successful match cannot hide an unmapped input. +- `requires` means mandatory prior reading; `related` means a useful neighbor. Relations do not repair missing source routes. - Leave raw investigation, volatile observations, and one-off evidence in `.llmdoc-tmp/`. Split rules: @@ -66,7 +71,7 @@ Split rules: - One concept per document. - One workflow per guide. - One ownership boundary or invariant cluster per architecture doc. -- During init, depth beats premature fragmentation. Prefer a small set of strong core docs before broad expansion. +- During init, depth beats premature fragmentation, but never missing ownership. Prefer the smallest sufficient set of strong owner docs; classify every first-class subsystem as documented, intentionally reconstructable, or a blocking gap. - If a document grows large only because it is preserving one coherent execution model, invariant set, or contract cluster, keep it intact until a clean split is obvious. - If a document exceeds roughly 150 lines (the `validate` warning limit), covers more than one workflow, or mixes stable facts with transient notes, split it when doing so improves retrieval without discarding essential reasoning flow. - Keep `code.paths` and `relations` accurate when merging, splitting, or deleting docs. diff --git a/cli/package-lock.json b/cli/package-lock.json index 085d5d3..5cd71e8 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -1,12 +1,12 @@ { "name": "@tokenroll/llmdoc", - "version": "3.5.1", + "version": "3.5.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@tokenroll/llmdoc", - "version": "3.5.1", + "version": "3.5.2", "dependencies": { "ajv": "^8.17.1", "commander": "^13.1.0", diff --git a/cli/package.json b/cli/package.json index ee94ca1..5b0103f 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@tokenroll/llmdoc", - "version": "3.5.1", + "version": "3.5.2", "description": "V3 runtime CLI for llmdoc repositories", "homepage": "https://github.com/TokenRollAI/llmdoc", "repository": { diff --git a/cli/schemas/output.schema.json b/cli/schemas/output.schema.json index c5e7f0f..049cc48 100644 --- a/cli/schemas/output.schema.json +++ b/cli/schemas/output.schema.json @@ -425,6 +425,7 @@ "required": [ "impacted", "prerequisites", + "unmappedFiles", "pagination" ], "properties": { @@ -440,6 +441,13 @@ "$ref": "#/$defs/docRef" } }, + "unmappedFiles": { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + } + }, "pagination": { "$ref": "#/$defs/pagination" } diff --git a/cli/src/commands/context.ts b/cli/src/commands/context.ts index 03873fb..5c2eed8 100644 --- a/cli/src/commands/context.ts +++ b/cli/src/commands/context.ts @@ -28,11 +28,19 @@ export function runContext(options: ContextOptions): unknown { absolutePath }; }); - const impacted = workspace.documents.filter((document) => - normalizedFiles.some((file) => + const documentsByFile = normalizedFiles.map((file) => ({ + file, + documents: workspace.documents.filter((document) => (document.frontmatter.code?.paths ?? []).some((pattern) => matchesCodePathPattern(pattern, file.normalized)) ) + })); + const impactedPaths = new Set( + documentsByFile.flatMap(({ documents }) => documents.map((document) => document.llmdocPath)) ); + const impacted = workspace.documents.filter((document) => impactedPaths.has(document.llmdocPath)); + const unmappedFiles = documentsByFile + .filter(({ documents }) => documents.length === 0) + .map(({ file }) => file.normalized); const prerequisites = collectRequires(workspace, impacted); const rows = [ @@ -49,6 +57,7 @@ export function runContext(options: ContextOptions): unknown { return { impacted: result.items.filter((row) => row.role === "impacted").map((row) => toPayload(row.document)), prerequisites: result.items.filter((row) => row.role === "requires").map((row) => toPayload(row.document)), + unmappedFiles, pagination: paginationMetadata(result) }; } @@ -60,6 +69,10 @@ export function runContext(options: ContextOptions): unknown { lines.push(`${prefix} llmdoc/${document.llmdocPath} [${document.frontmatter.kind}]`); lines.push(` ${document.frontmatter.description}`); } + lines.push("", `unmapped files: ${unmappedFiles.length}`); + for (const file of unmappedFiles) { + lines.push(` unmapped -> ${file}`); + } lines.push("", ...formatPaginationSummary(result)); return lines.join("\n"); } diff --git a/cli/src/lib/workspace.ts b/cli/src/lib/workspace.ts index 6c65d9d..1cb323c 100644 --- a/cli/src/lib/workspace.ts +++ b/cli/src/lib/workspace.ts @@ -9,6 +9,7 @@ import { estimateTokens, extractCodeRefs, extractLinks, extractTitle, resolveDoc import { assertDocKindMatchesShape, parseDocTargetShape } from "./doc-shape.js"; import { normalizeRepoRelativePath, repoPath, resolveInsideRoot } from "./fs.js"; import { gitCommitExists, isShallowRepository } from "./git.js"; +import { matchesCodePathPattern } from "./search.js"; import { validateDocFrontmatter, validateMeta } from "./schema.js"; export function loadWorkspace(rootDir: string): WorkspaceData { @@ -313,6 +314,16 @@ export function validateWorkspace(workspace: WorkspaceData): ValidationIssue[] { path: document.repoPath, message: `code.paths 指向不存在的路径: ${codePath}` }); + } else if ( + normalized.isGlob && + !globMatchesExistingFile(workspace.rootDir, normalized.absolutePath, normalized.normalized) + ) { + issues.push({ + severity: "error", + code: "code.paths.unmatched", + path: document.repoPath, + message: `code.paths glob 未命中任何现有文件: ${codePath}` + }); } } @@ -464,3 +475,36 @@ function validateCodePathPattern( return { ok: false, message: (error as Error).message }; } } + +function globMatchesExistingFile(rootDir: string, staticPrefixPath: string, pattern: string): boolean { + const pending = [staticPrefixPath]; + + while (pending.length > 0) { + const currentPath = pending.pop()!; + const stat = fs.lstatSync(currentPath); + if (stat.isSymbolicLink()) { + continue; + } + if (stat.isFile()) { + if (matchesCodePathPattern(pattern, repoPath(rootDir, currentPath))) { + return true; + } + continue; + } + if (!stat.isDirectory()) { + continue; + } + + for (const entry of fs.readdirSync(currentPath, { withFileTypes: true })) { + if (entry.isSymbolicLink()) { + continue; + } + if (entry.isDirectory() && [".git", ".llmdoc-tmp", "node_modules"].includes(entry.name)) { + continue; + } + pending.push(path.join(currentPath, entry.name)); + } + } + + return false; +} diff --git a/cli/tests/cli.test.ts b/cli/tests/cli.test.ts index 44cbf36..106592e 100644 --- a/cli/tests/cli.test.ts +++ b/cli/tests/cli.test.ts @@ -142,6 +142,79 @@ describe("llmdoc cli", () => { expect(invalid.stdout).toContain("路径必须是仓库内规范化相对路径"); }); + test("context reports mapped and unmapped inputs independently", async () => { + const rootDir = createFixture(); + + const mapped = await runCli(["--json", "context", "--files", "src/api/retry.ts"], rootDir); + expect(mapped.exitCode).toBe(0); + const mappedPayload = JSON.parse(mapped.stdout) as { + impacted: Array<{ path: string }>; + unmappedFiles: string[]; + }; + expect(mappedPayload.impacted.some((document) => document.path === "llmdoc/api-client/retry-policy.mdx")).toBe(true); + expect(mappedPayload.unmappedFiles).toEqual([]); + + const unmapped = await runCli(["--json", "context", "--files", "src/api/new-feature.ts"], rootDir); + expect(unmapped.exitCode).toBe(0); + const unmappedPayload = JSON.parse(unmapped.stdout) as { + impacted: Array<{ path: string }>; + prerequisites: Array<{ path: string }>; + unmappedFiles: string[]; + }; + expect(unmappedPayload.impacted).toEqual([]); + expect(unmappedPayload.prerequisites).toEqual([]); + expect(unmappedPayload.unmappedFiles).toEqual(["src/api/new-feature.ts"]); + + const mixedJson = await runCli( + [ + "--json", + "context", + "--files", + "src/api/retry.ts", + "src/api/new-feature.ts", + "src/core/unmapped.ts" + ], + rootDir + ); + expect(mixedJson.exitCode).toBe(0); + const mixedPayload = JSON.parse(mixedJson.stdout) as { + impacted: Array<{ path: string }>; + unmappedFiles: string[]; + }; + expect(mixedPayload.impacted.some((document) => document.path === "llmdoc/api-client/retry-policy.mdx")).toBe( + true + ); + expect(mixedPayload.unmappedFiles).toEqual(["src/api/new-feature.ts", "src/core/unmapped.ts"]); + + const mixed = await runCli(["context", "--files", "src/api/retry.ts", "src/api/new-feature.ts"], rootDir); + expect(mixed.exitCode).toBe(0); + expect(mixed.stdout).toContain("retry-policy.mdx"); + expect(mixed.stdout).toContain("unmapped files: 1"); + expect(mixed.stdout).toContain("unmapped -> src/api/new-feature.ts"); + }); + + test("validate rejects a code.paths glob whose existing static prefix has zero file matches", async () => { + const rootDir = createFixture(); + fs.writeFileSync( + path.join(rootDir, "llmdoc", "architecture.mdx"), + `--- +description: 整体架构与关键引导。 +kind: architecture +code: + paths: + - src/api/*.tsx +--- + +# 整体架构 +` + ); + + const result = await runCli(["validate"], rootDir); + expect(result.exitCode).toBe(1); + expect(result.stdout).toContain("code.paths.unmatched"); + expect(result.stdout).toContain("src/api/*.tsx"); + }); + test("metadata commands budget their projected output instead of full document bodies", async () => { const rootDir = createFixture(); fs.appendFileSync(path.join(rootDir, "llmdoc", "api-client", "overview.mdx"), `\n${"large body ".repeat(4000)}`); diff --git a/docs/agent-integration.md b/docs/agent-integration.md index 2a1df9f..928fbea 100644 --- a/docs/agent-integration.md +++ b/docs/agent-integration.md @@ -39,6 +39,8 @@ This project uses llmdoc V3 as persistent engineering context. - bodies of documents already identified → `show ` - These entry points are alternatives, not a fixed sequence. Stop when the task has enough context. +- `context --files` evaluates inputs independently and reports `unmappedFiles`; + do not infer that all inputs are mapped merely because `impacted` is non-empty. - Broad native discovery means recursive or cross-directory exploration outside the working set identified by llmdoc. After llmdoc narrows that set, use native tools for exact source text, line numbers, test behavior, counts, Git diff --git a/docs/v3-design/03-cli.md b/docs/v3-design/03-cli.md index ae552a4..82f65e7 100644 --- a/docs/v3-design/03-cli.md +++ b/docs/v3-design/03-cli.md @@ -20,7 +20,7 @@ CLI 是 V3 的 Runtime 实体:所有确定性、可测试、重复出现的工 | `llmdoc index [--topic t] [--kind k]` | 批量输出文档 front matter 投影(path/description/kind/relations/code.paths)。L2 | | `llmdoc show ` | 按路径取正文,多文档合并输出,带预算。L3 | | `llmdoc search [--topic] [--kind]` | 词法检索(front matter + 标题 + 正文,BM25 级),返回 path + description + 命中片段 | -| `llmdoc context --files ` | **给 AI 的核心入口**:"我要改这些源码文件,应该先读哪些文档"——用 `code.paths` 反查 + requires 闭包 | +| `llmdoc context --files ` | **给 AI 的核心入口**:"我要改这些源码文件,应该先读哪些文档"——逐输入用 `code.paths` 反查 + requires 闭包,并独立报告 `unmappedFiles` | 搜索索引缓存于 `.llmdoc-tmp/cache/`,按 mtime/revision 增量重建,删除可再生。不做 embedding。 @@ -32,7 +32,7 @@ CLI 是 V3 的 Runtime 实体:所有确定性、可测试、重复出现的工 |---|---| | `llmdoc status` | baseline vs HEAD、失效/待复核文档数、dirty 信号、growth 概况。hook 与人共用 | | `llmdoc delta [--scope ]` | 变更代码 → 受影响文档闭包 + unmapped paths + light/deep 建议信号(见 04) | -| `llmdoc validate` | 全量校验:front matter schema、kind 合法、禁 index.mdx、层级深度(禁嵌套)、链接/requires 悬空、CodeRef path 存在、ledger 与文件树一致、体积告警。CI 与写入门控共用 | +| `llmdoc validate` | 全量校验:front matter schema、kind 合法、禁 index.mdx、层级深度(禁嵌套)、链接/requires 悬空、CodeRef path 存在、`code.paths` 精确路径存在且 glob 至少命中一项、ledger 与文件树一致、体积告警。CI 与写入门控共用 | | `llmdoc fingerprint --update ` | 只刷新 revision 的低层台账原语;普通 update 收尾优先用 `commit`/`commit --verified` 保证 validate 与 git 提交闭环 | | `llmdoc init-state` | 首次生成 `meta.json` 台账骨架:全部文档 `validatedRevision: null` + 实测 convergence;init/upgrade 场景专用,拒绝覆盖已有台账 | | `llmdoc commit [-m] [--verified \| --all] [--no-verify]` | **一体化收尾**:validate 门控 → 可选提交正文写集(不卷入用户 staged 的其他文件)→ 刷新正文改动与 verified-unchanged 文档 → meta 单独小 commit。`--all` 表示全量复核且不能与 `--verified` 同用;无正文改动时可只提交 meta。消灭手工三步曲与 `--amend` 追尾陷阱 | diff --git a/package-lock.json b/package-lock.json index 4d4c89b..e6659d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@tokenroll/llmdoc-repository", - "version": "3.5.1", + "version": "3.5.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@tokenroll/llmdoc-repository", - "version": "3.5.1", + "version": "3.5.2", "devDependencies": { "@tokenroll/llmdoc": "file:cli", "gray-matter": "^4.0.3" @@ -17,7 +17,7 @@ }, "cli": { "name": "@tokenroll/llmdoc", - "version": "3.5.1", + "version": "3.5.2", "dev": true, "dependencies": { "ajv": "^8.17.1", diff --git a/package.json b/package.json index c8a4dd3..2f899a3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tokenroll/llmdoc-repository", - "version": "3.5.1", + "version": "3.5.2", "private": true, "description": "Development workspace for the llmdoc V3 CLI and plugin surfaces", "scripts": { diff --git a/scripts/check-codex-surface.mjs b/scripts/check-codex-surface.mjs index 5001076..7e56f62 100644 --- a/scripts/check-codex-surface.mjs +++ b/scripts/check-codex-surface.mjs @@ -164,6 +164,50 @@ for (const name of ["llmdoc", "init", "update", "prune", "upgrade"]) { } } +// Skill references are part of the executable prompt surface too. A mirrored SKILL.md +// is not sufficient when its conditionally loaded guidance is missing or stale. +for (const rel of ["llmdoc/references/knowledge-topology.md"]) { + const claudePath = `skills/${rel}`; + const codexPath = `.agents/skills/${rel}`; + const claudeReference = readText(claudePath); + const codexReference = readText(codexPath); + if ( + claudeReference !== null && + codexReference !== null && + normalizeBody(claudeReference) !== normalizeBody(codexReference) + ) { + errors.push(`${codexPath}: reference 与 canonical ${claudePath} 不一致`); + } +} + +for (const rel of [ + "skills/init/SKILL.md", + ".agents/skills/init/SKILL.md", + "skills/update/SKILL.md", + ".agents/skills/update/SKILL.md", + "skills/prune/SKILL.md", + ".agents/skills/prune/SKILL.md" +]) { + const content = readText(rel); + if (content !== null && !content.includes("../llmdoc/references/knowledge-topology.md")) { + errors.push(`${rel}: 未按需路由到 knowledge-topology reference`); + } +} + +for (const rel of ["skills/llmdoc/SKILL.md", ".agents/skills/llmdoc/SKILL.md"]) { + const content = readText(rel); + if (content !== null && !content.includes("references/knowledge-topology.md")) { + errors.push(`${rel}: operating skill 未暴露 knowledge-topology reference`); + } +} + +for (const rel of ["agents/recorder.md", ".codex/agents/recorder.toml"]) { + const content = readText(rel); + if (content !== null && !content.includes("knowledge-topology.md")) { + errors.push(`${rel}: Recorder 未声明 knowledge-topology 加载条件`); + } +} + for (const name of ["investigator", "reflector", "recorder"]) { const claudePath = `agents/${name}.md`; const codexPath = `.codex/agents/${name}.toml`; diff --git a/skills/init/SKILL.md b/skills/init/SKILL.md index f84b568..149894f 100644 --- a/skills/init/SKILL.md +++ b/skills/init/SKILL.md @@ -31,18 +31,21 @@ Stop instead of improvising when: ## Workflow 1. Inventory the repository surface. + - Before choosing boundaries, read [Knowledge Topology and Context Floor](../llmdoc/references/knowledge-topology.md). Use its domain/topic tests and Context Floor acceptance contract. - Read top-level manifests, README files, entrypoints, test surfaces, and release/config files. - Use one or more `investigator` subagents for complementary evidence scopes when the repository is large enough to benefit; keep their write ownership in `.llmdoc-tmp/`. - - Check coverage and resolve conflicting evidence before handing the result to `recorder`. + - Build the reference's scratch domain/owner matrix. Give every first-class subsystem an expected owner document or an explicit no-doc reason; resolve conflicting evidence before handing the result to `recorder`. 2. Build the first V3 knowledge surface with `recorder`. - Define topic boundaries before drafting leaf docs. - - Prefer a small number of high-value docs over broad shallow coverage. + - Prefer the smallest sufficient set of high-value owner docs over broad shallow inventory. Depth never excuses a first-class subsystem with neither an owner nor an intentional no-doc decision. - Keep stable knowledge in `llmdoc/` and validity state in `llmdoc/meta.json`. - - Create the V3 root singleton plus one-level topic directories; topics are plain directories with no `index.mdx` entry node. + - Create root singleton docs only for genuinely cross-topic contracts; otherwise create only the necessary one-level topic directories. Topics are plain directories with no `index.mdx` entry node. 3. Validate before reporting success. - Seed the ledger with `init-state` (writes meta.json with null revisions), then run `validate` and fix all schema, routing, and reference failures. + - Treat `validate` as structural only. After it passes, run the reference's Context Floor acceptance: natural-query searches, per-boundary `context --files` probes, broad-glob precision probes, and `tree --docs` plus `index`/`context` relation review. + - Repair missing or imprecise routes before success. An intended owner must be reached directly; a generic root document alone is not sufficient. - Docs added after `init-state` already seeded the ledger get their entries via `adopt `; never hand-edit `meta.json` or recreate existing files through `new`. - Finalize with `commit --all -m "docs: bootstrap llmdoc"` — it commits the surface, brands fingerprints, and lands the meta follow-up commit in one step. - On a validation failure that cannot be repaired in-run, roll back the init write-set. @@ -66,5 +69,6 @@ Always report: - whether init ran or was refused - the investigation report path or paths used - the topics and stable docs created +- the domain/owner matrix outcome, including concept routes, representative file routes, and intentional no-doc decisions - the `validate` and `commit` results -- any material gaps left for later `/llmdoc:update` +- any intentionally reconstructable areas or non-blocking follow-ups; an unresolved first-class gap makes init `incomplete`, not `success` diff --git a/skills/llmdoc/SKILL.md b/skills/llmdoc/SKILL.md index 9e55210..483806a 100644 --- a/skills/llmdoc/SKILL.md +++ b/skills/llmdoc/SKILL.md @@ -47,6 +47,7 @@ These entry points are alternatives, not a sequence. Stop as soon as the task ha - Before non-trivial edits, align with the user. - If `llmdoc/` does not exist, suggest `/llmdoc:init`; do not fabricate the knowledge surface ad hoc. - When a task produces durable knowledge changes, suggest `/llmdoc:update` at the end. +- For topology or routing work, read [Knowledge Topology](references/knowledge-topology.md). - Never suggest `/llmdoc:upgrade`; it runs only when the user asks for it by name. ## Reflection Gate diff --git a/skills/llmdoc/references/knowledge-topology.md b/skills/llmdoc/references/knowledge-topology.md new file mode 100644 index 0000000..ada1818 --- /dev/null +++ b/skills/llmdoc/references/knowledge-topology.md @@ -0,0 +1,243 @@ +# Knowledge Topology and Context Floor + +Use this reference when bootstrapping llmdoc, creating or moving a topic or document, repairing unmapped code, or judging whether the knowledge surface reaches the Context Floor. It expands the mandatory gates in the operating skills; it is not a checklist for routine retrieval. + +## Design model + +llmdoc is a task-oriented semantic routing graph, not a compressed copy of the repository. Its job is to make the right durable context reachable before broad source exploration while leaving live implementation facts in their canonical sources. + +Five principles shape the model: + +1. **Minimum sufficient graph.** Optimize for the smallest connected knowledge surface that supports correct work, not maximum prose, file coverage, or taxonomy completeness. +2. **Decisions over observations.** Stable documents preserve costly-to-recover decisions, rationale, boundaries, invariants, contracts, failure semantics, and risky workflows. Source, schema, tests, manifests, and CLI help remain authoritative for cheap live facts. +3. **Ownership over layout.** Knowledge follows stable responsibility and decision boundaries. A domain may cross packages, and one package may contain several domains. +4. **Progressive disclosure.** `tree` exposes the map, descriptions and search expose semantic candidates, `context --files` exposes change owners, relations add required closure, and `show` loads only selected bodies. Each layer must support a stop decision. +5. **Review coupling.** `code.paths` connects changes to the documents whose claims may become false. Mapping therefore follows semantic review obligation, not provenance alone or a coverage target. + +These principles create a deliberate split of authority: + +| Concern | Owner | +|---|---| +| Current implementation facts | Source, tests, schema, manifests, generated config | +| Durable engineering meaning | llmdoc document body | +| Concept and change routing | `description`, document path, `code.paths`, `relations` | +| Freshness and validity | Git-based llmdoc ledger and CLI | +| Investigation evidence | `.llmdoc-tmp/` | + +An authoring choice is justified only when it improves retrieval, comprehension, or review coupling without duplicating a cheaper source of truth. This is why V3 has one topic level, no hand-maintained index pages, only three document kinds, and a small front matter surface. + +## The two independent gates + +Do not use one gate as a substitute for the other: + +1. **Stable Knowledge Gate — prose value.** Preserve only durable decisions, rationale, boundaries, invariants, failure semantics, contracts, and risky workflows that source does not cheaply reconstruct. +2. **Routing Gate — owner reachability.** A representative concept query and a representative decision-bearing source file must reach the document that owns that knowledge. + +Mapping a file does not require narrating the file in prose. Conversely, concise prose does not excuse a missing route. `validate` proves structural validity; it does not prove semantic ownership or Context Floor coverage. + +## What the Context Floor means + +The Context Floor is the smallest connected knowledge surface from which a new agent can: + +- find the owner of each first-class subsystem using the vocabulary a developer would naturally query; +- route from a concrete change to the document whose claims need review; +- recover the decisions, boundaries, invariants, and failure model needed before reading implementation details; +- follow mandatory prerequisites across topics without loading unrelated documents. + +It is not a target document count, token count, or percentage of files mapped. Generated files, barrels, trivial helpers, and code with no durable knowledge may intentionally remain unmapped. + +A subsystem is usually first-class when at least one of these is true: + +- it owns an external or cross-module contract; +- it has a distinct lifecycle, authority boundary, or failure model; +- changes to it require decisions that are not local implementation details; +- it contains a risky repeatable operational or maintenance workflow. + +Package and directory boundaries are evidence, not automatic knowledge boundaries. + +## Domain, topic, and document + +Use three reasoning levels: + +| Level | Question | llmdoc representation | +|---|---|---| +| Domain | What stable responsibility or decision boundary exists? | Analysis unit; it may span packages or split one package | +| Topic | What retrieval neighborhood should a caller enter? | One directory directly below `llmdoc/` | +| Document | What single owner answers one coherent class of questions? | One `.mdx` file with a kind and routing metadata | + +### Domain boundary test + +Keep concerns in the same domain when they share most of the following: + +- the same conceptual owner or authority; +- the same invariants and failure model; +- the same change reasons and review questions; +- the same vocabulary in natural-language searches. + +Split domains when the owner, authority, failure model, or common questions remain distinct even if the code is colocated. Join code from different packages into one domain when it implements one contract or execution model. + +Avoid domains named after temporary projects, release phases, teams, or generic layers such as `utils`. Prefer stable responsibility names such as identity delegation, request execution, or release integrity. + +### Topic boundary test + +A topic is the physical retrieval partition for one stable domain or a coherent subdomain. Create a new topic only when it gives callers a durable vocabulary and keeps unrelated searches or file routes from loading each other. + +Use the same topic when documents share a bounded responsibility and are commonly needed together. Split a topic when it contains independent owners or failure models and callers usually need only one side. A one-document topic is valid only when the boundary is genuinely distinct and expected to persist. + +Root-level singleton documents are reserved for contracts that are truly cross-topic, such as the repository-wide execution model. Do not use a generic root architecture document as the only owner for otherwise independent subsystems. + +### Document boundary and kind + +Choose the kind from the question the document answers: + +- `architecture`: Why is this responsibility shaped this way? Who owns what? What flow, invariants, tradeoffs, and failure semantics constrain changes? +- `guide`: When and how is a risky or non-obvious workflow performed? What are its branches, safety checks, verification, recovery, and stopping conditions? +- `reference`: What stable vocabulary, contract, compatibility rule, default, or decision table must be looked up precisely? + +Split when a document has more than one conceptual owner, more than one independently invoked workflow, or unrelated query vocabularies. Keep it intact when a split would break one execution model or invariant chain merely to satisfy a line target. + +## What to write + +Use these skeletons selectively. Omit empty sections rather than filling them with source inventory. + +### Architecture + +1. Scope and ownership boundary +2. Execution or data flow +3. Decisions and rationale, including rejected alternatives when they affect future choices +4. Invariants, authority boundaries, and non-obvious failure semantics +5. Cross-topic contracts and change consequences +6. A few canonical source anchors + +### Guide + +1. Trigger and when not to use the workflow +2. Preconditions and safety boundary +3. Steps with meaningful decision branches +4. Verification and success signals +5. Failure handling, rollback, and escalation conditions + +### Reference + +1. Scope and source of authority +2. Stable terms, fields, states, defaults, or compatibility rules +3. Decision table or lookup structure +4. Exceptions and relationships to owner documents + +Do not preserve current file lists, line counts, release snapshots, copied CLI help, investigation narratives, or facts that a canonical manifest or schema answers in minutes. Source anchors support durable claims; they do not replace those claims. + +## Front matter as retrieval design + +### `description` + +Write a compact retrieval promise, not an abstract summary. Include the distinctive responsibility, contract terms, and questions a developer is likely to search. Avoid descriptions that could apply to several documents, such as “architecture overview” or “core behavior.” + +### `code.paths` + +Map semantic ownership rather than directory membership. Useful anchors include: + +- canonical contract, schema, or protocol definitions; +- entrypoints and orchestrators that establish the execution model; +- boundary adapters whose behavior changes the documented contract; +- persistence or configuration surfaces that encode documented invariants; +- tests only when they are the clearest owner of a non-obvious contract. + +Apply both tests: + +- **Recall:** every first-class decision-bearing surface has a route to its owner document. +- **Precision:** every matched file is relevant enough that changing it should trigger review of that document. + +Do not add a broad package glob merely to raise coverage. If an unrelated sibling file matches, narrow the glob or add exact patterns. Do not map generated, vendored, barrel, or incidental helper files unless they genuinely own part of the contract. + +### `relations` + +Use `requires` only when a caller must read the prerequisite to apply this document safely. Use `related` for useful neighbors. Relations connect owner documents; they do not compensate for missing `code.paths` or recreate a manual index tree. + +## Bootstrap procedure + +Before drafting, keep a scratch domain/owner matrix in `.llmdoc-tmp/`: + +| Domain or subsystem | Natural queries | Declared implementation boundaries | Entry/contract probes | Leaf/boundary probes | Expected owner doc | Status and evidence | +|---|---|---|---|---|---|---| + +Allowed statuses are `documented`, `intentionally reconstructable`, and `gap`. A first-class subsystem left unclassified or at `gap` makes init incomplete; do not silently defer it while reporting success. + +List every distinct package, adapter, runtime, authority, or external boundary that participates in a domain. A cross-package contract is not covered merely because two probes from the same package pass. + +An `intentionally reconstructable` row must name its canonical recovery source, estimate that recovery takes only a few minutes, state why no durable decision or failure model is hidden there, and include a representative file expected to remain unmapped. Missing or conflicting evidence makes it a `gap`, not a no-doc decision. + +Then: + +1. Inventory first-class domains from manifests, entrypoints, external contracts, tests, release/config surfaces, and failure boundaries. +2. Group them into topics using ownership, invariants, failure model, change reasons, and query vocabulary. +3. Assign one canonical owner document for every durable decision cluster or risky workflow. +4. Draft only claims that pass the Stable Knowledge Gate. +5. Add precise routes from representative decision-bearing files to those owners. +6. Add `requires` only for mandatory reading order. +7. Run the Context Floor acceptance checks below. + +Keep the executable evidence in a scratch probe table rather than stable prose: + +| Domain and boundary | Query or file | Expected owner/result | Actual owner/rank/result | Pass or repair reason | +|---|---|---|---|---| + +“A few high-value docs” means the smallest sufficient owner set. It never means leaving a first-class subsystem without an explicit owner or an intentional no-doc decision. + +## Context Floor acceptance + +Run these checks after `validate` during init, and for the affected scope during update or topology changes. + +### 1. Concept route + +For each first-class subsystem, run two or three natural queries, including one term that does not simply repeat the document title: + +```sh +npx -y @tokenroll/llmdoc search "" +``` + +The intended owner should be the first relevant result from its description and content. If it is not first, record the actual rank and why earlier results do not make routing ambiguous; otherwise repair the description or boundary. If only a generic root document appears, the subsystem is not adequately owned. + +### 2. File route + +Test at least one canonical entry or contract file and one representative leaf or boundary file per documented subsystem, plus at least one owner file from every declared implementation boundary. Invoke once per file because `unmappedFiles` is attributed per input while owner documents remain a union: + +```sh +npx -y @tokenroll/llmdoc context --files +npx -y @tokenroll/llmdoc context --files +``` + +The intended owner must appear, along with genuinely required prerequisites. Zero results or only a generic cross-topic document is a routing gap. + +### 3. Precision probe + +Treat every `code.paths` pattern containing glob metacharacters such as `*`, `?`, `[]`, or `{}` as a wildcard mapping. For each wildcard—especially recursive or package-level patterns—probe an unrelated sibling inside the matched tree. If that file routes to the document even though its change would not require reviewing the document, narrow the mapping. Exact paths are exempt. + +### 4. Connected floor + +Use `tree --docs` to confirm that a cold reader can name the repository-wide contract and enter every first-class topic. Then use `index --topic ` to inspect declared relations and per-file `context --files` to verify the actual `requires` closure. The chain must work without a catch-all document; `tree` alone does not expose relations. + +### 5. Explicit gaps + +Record intentional no-doc decisions and unresolved gaps in the init/update report. An unresolved first-class gap prevents init success. Do not create filler prose to make the matrix look complete. + +The floor passes when every first-class subsystem has a useful concept route, every documented decision-bearing surface has a precise file route, prerequisites are connected, and all omissions are intentional. Structural `validate` success alone is insufficient. + +## Update triage + +When `delta` reports an unmapped or newly moved file, classify it before writing: + +1. **Missing mapping:** an existing document already owns the durable knowledge; repair `code.paths` and run scoped routing checks. +2. **Missing owner:** the change exposes a stable domain, decision cluster, or workflow with no suitable document; decide the topic and create or split the owner. +3. **Intentional no-doc:** the file is reconstructable implementation detail and owns no durable knowledge; leave it unmapped and state that decision in the report when material. + +When boundaries, names, or source locations change, rerun concept, file, and precision checks for the affected topics even if the prose remains semantically true. + +## Failure patterns + +- Treating package folders as topics without testing ownership or query vocabulary +- Using one repository architecture doc as a catch-all owner +- Mapping a whole source tree to one doc to manufacture coverage +- Writing detailed file inventories while omitting rationale, invariants, or failure semantics +- Splitting by document size while breaking a coherent execution model +- Assuming `validate` proves retrieval quality +- Declaring sparse output healthy solely because every sentence passes the Stable Knowledge Gate diff --git a/skills/prune/SKILL.md b/skills/prune/SKILL.md index 6e26786..9bce0ac 100644 --- a/skills/prune/SKILL.md +++ b/skills/prune/SKILL.md @@ -34,6 +34,7 @@ This command does not authorize source-code edits. - A clean duplicate/fragment report does not prove good knowledge density; semantic review remains the recorder's job. 2. Decide the convergence plan with `recorder`. + - If the plan moves ownership, changes topic boundaries, or merges/splits documents, read [Knowledge Topology and Context Floor](../llmdoc/references/knowledge-topology.md) before rewriting. - Merge duplicated docs. - Rewrite fragmented docs when a clearer topic boundary exists. - Apply the Stable Knowledge Gate sentence by sentence. Remove command/file inventories, current-state evidence, and other facts that a reader can cheaply recover from canonical sources. @@ -43,6 +44,7 @@ This command does not authorize source-code edits. 3. Re-validate the result. - Run `validate`. + - When ownership or routing changed, run the reference's scoped concept, per-file owner, broad-glob precision, and prerequisite checks; structural validation alone is insufficient. - Re-run `prune --report` and compare document/token scale with the first report. - Confirm surviving stable concepts retain accurate `code.paths`. Do not attach unrelated paths merely to preserve a coverage metric; call out any intentional coverage reduction. - Finalize with `commit -m ""`, which fingerprints the surviving docs and lands the `meta.json` follow-up commit automatically. diff --git a/skills/update/SKILL.md b/skills/update/SKILL.md index 8ed435a..97cf7e1 100644 --- a/skills/update/SKILL.md +++ b/skills/update/SKILL.md @@ -43,19 +43,22 @@ This command does not authorize source-code edits. - Light: owners are mapped and facts are clear. - Deep: files are unmapped, owner/root cause is unclear, boundaries changed, facts conflict, or impact is broad. - This choice controls evidence gathering only. It does not decide whether prose must change. + - For unmapped or moved code and boundary changes, read [Knowledge Topology and Context Floor](../llmdoc/references/knowledge-topology.md) and classify each surface as missing mapping, missing owner, or intentional no-doc. 4. Decide the semantic outcome with `recorder`. - Treat `delta` and candidates as review evidence, not a write list or prose to copy. - Rewrite only false/incomplete claims or new conclusions that pass the Stable Knowledge Gate. Reflection candidates must pass both gates. + - Gate prose and routing independently; true prose may still need routing metadata repair. - If the document remains true and the change adds only reconstructable evidence, mark it verified unchanged. - Light: `recorder` decides from targeted CLI reads. Deep: `investigator` reports evidence, then `recorder` applies the gate. - Scaffold brand-new docs with `new`; register docs that already exist as files with `adopt ` — never hand-edit `meta.json` or recreate the file through `new`. 5. Finalize. + - Run `validate`; after mapping or boundary changes, also run the reference's scoped routing acceptance. - If prose changed, run `commit -m ""`, adding `--verified ` for reviewed unchanged docs. If all stayed unchanged, run `commit --verified `. Full verification uses `--all`, never with `--verified`. - - `commit` gates on validate, commits any `llmdoc/` prose write-set, refreshes the changed and verified fingerprints, and lands `meta.json` separately. Never hand-roll this sequence out of `validate` plus `fingerprint`, and never `--amend` (that rewrites the hash fingerprints just recorded). - - `commit` preflights the fingerprint preconditions before creating any commit: if mapped source is still dirty it fails closed with the worktree untouched. Commit or clean the related source first, then rerun `commit` — do not fall back to a manual sequence. - - Re-check `status` when you need a final stale/clean signal. After a successful finalize, `N commits behind HEAD, metadata-only; knowledge clean` is the expected end state (the meta follow-up commit), not staleness — do not chase it with another update. + - `commit` validates, commits prose, refreshes fingerprints, and lands `meta.json` separately. Never reconstruct this sequence manually or `--amend` it. + - Dirty mapped source makes `commit` fail closed; commit or clean that source, then retry. + - After success, `N commits behind HEAD, metadata-only; knowledge clean` reflects the meta follow-up commit, not staleness. 6. Fold durable lessons into stable docs directly. - Put reusable cautions, invariants, and workflow fixes into the relevant architecture or guide docs. @@ -83,4 +86,5 @@ Always report: - any investigation report path - each reflection candidate and its disposition (`promoted`, `already_covered`, `dismissed`, or `pending`) - the stable docs changed and the docs verified unchanged by `recorder` +- routing classifications and checks when topology changed - the `commit` result — validate gate, fingerprint refresh, and the meta follow-up commit — or why finalization was skipped diff --git a/website/src/pages/docs/cli/index.astro b/website/src/pages/docs/cli/index.astro index b341f87..dd6bee3 100644 --- a/website/src/pages/docs/cli/index.astro +++ b/website/src/pages/docs/cli/index.astro @@ -15,7 +15,7 @@ import DocsLayout from "../../../layouts/DocsLayout.astro";
tree
Dynamic map of root documents and topics.
index [--topic …] [--kind …]
Front-matter projection for document discovery.
search <query>
Lexical search across tracked knowledge.
-
context --files <src…>
Map source paths to owner documents and required prerequisites.
+
context --files <src…>
Map each source path to owner documents and required prerequisites, while reporting unmapped inputs explicitly.
show <path…>
Read selected document bodies.
serve
Start the local Viewer on 127.0.0.1 to inspect document structure, relations, and status.
@@ -24,7 +24,7 @@ import DocsLayout from "../../../layouts/DocsLayout.astro";
status
Validity, baseline, dirty, and growth signals.
delta
Changed code to impacted-document closure.
-
validate
Schema, structure, relations, links, code paths, and ledger consistency.
+
validate
Schema, structure, relations, links, code paths—including zero-match globs—and ledger consistency.

Mutate safely

diff --git a/website/src/pages/docs/concepts/index.astro b/website/src/pages/docs/concepts/index.astro index 161c3cd..612487e 100644 --- a/website/src/pages/docs/concepts/index.astro +++ b/website/src/pages/docs/concepts/index.astro @@ -14,6 +14,15 @@ import DocsLayout from "../../../layouts/DocsLayout.astro";

The Context Floor is the richness of context an agent needs to solve the current problem. Tool calls, token footprint, and the density of key information all shape the time it takes to reach that floor.

llmdoc raises information density before broad source exploration. It does not replace source code: once it narrows the working set, native tools verify live details such as implementation text, line numbers, tests, and Git state.

+

Design model: a semantic routing graph

+

llmdoc is not a compressed copy of the repository. It is the smallest connected graph of durable engineering meaning that lets an agent find the right owner, understand the decisions that constrain a task, and then continue into authoritative source.

+
    +
  • Decisions over observations: documents preserve rationale, boundaries, invariants, contracts, failure semantics, and risky workflows; source, tests, schemas, and manifests retain live facts.
  • +
  • Ownership over layout: knowledge follows stable responsibility and review boundaries, not package or directory shape.
  • +
  • Progressive disclosure: the map, routing metadata, selected bodies, and source form successively deeper layers.
  • +
  • Review coupling: code.paths maps a change to the documents whose claims may need review, rather than manufacturing a file-coverage score.
  • +
+

Progressive reading

The retrieval surface reveals knowledge in layers: map or metadata first, then search or source ownership, then selected bodies. A caller may stop at any layer.

tree / index  →  search / context  →  show
@@ -34,6 +43,15 @@ import DocsLayout from "../../../layouts/DocsLayout.astro"; │ └── retry-policy.mdx └── meta.json +

From domain to topic to document

+

A domain is an analysis boundary: one stable responsibility, authority, invariant set, failure model, and change vocabulary. A topic is its persistent retrieval neighborhood under llmdoc/. A document is the canonical owner of one coherent question, contract, invariant cluster, or workflow.

+

Package boundaries are only evidence. Split a topic when ownership, failure semantics, or common queries are independently stable; join code from different packages when it implements one contract. Reserve root documents for genuinely cross-topic knowledge.

+

Use architecture for boundaries, flows, rationale, and invariants; guide for repeatable workflows with verification and recovery; and reference for stable lookup contracts and decision tables.

+ +

Two gates, not one

+

The Stable Knowledge Gate controls what prose deserves to persist. A separate Routing Gate checks whether natural concept queries and representative decision-bearing files reach the correct owner. Concise prose does not excuse a missing route, and mapping a file does not require narrating it.

+

validate checks structure. Context Floor acceptance additionally probes natural-language search, individual entry and leaf files with context --files, unrelated siblings against broad globs, and mandatory prerequisite relations. Every first-class subsystem must be documented, intentionally reconstructable, or reported as a blocking gap.

+

Validity is Git-based

llmdoc/meta.json tracks validated Git revisions. Dirty worktree state is an additional signal, never a fabricated revision. A delta hit creates a review obligation; it does not automatically require a prose change.

diff --git a/website/src/pages/docs/workflows/index.astro b/website/src/pages/docs/workflows/index.astro index 331bef2..d0447ac 100644 --- a/website/src/pages/docs/workflows/index.astro +++ b/website/src/pages/docs/workflows/index.astro @@ -19,10 +19,12 @@ import DocsLayout from "../../../layouts/DocsLayout.astro";

Initialize

-

Use the init workflow only when a repository has no valid V3 knowledge surface. It investigates topic boundaries, writes a small number of high-value documents, validates them, and finishes with Git-backed state.

+

Use the init workflow only when a repository has no valid V3 knowledge surface. It designs domain and topic boundaries, writes the smallest sufficient set of owner documents, and classifies every first-class subsystem as documented, intentionally reconstructable, or a blocking gap.

+

After structural validation, init verifies natural concept queries, representative files from every implementation boundary, wildcard negative probes, and prerequisite closure before it can finish with Git-backed state.

Update

Update semantically verifies existing knowledge against code deltas and authorized reflection candidates. A document that is still correct is verified unchanged; it does not accumulate a change log.

+

Prose and routing are reviewed independently: true prose may still need description, code.paths, or relations repaired.

An update signal is a review set, not a prose-writing list.

Prune

diff --git a/website/src/pages/zh/docs/cli/index.astro b/website/src/pages/zh/docs/cli/index.astro index c1e0f40..2e8521b 100644 --- a/website/src/pages/zh/docs/cli/index.astro +++ b/website/src/pages/zh/docs/cli/index.astro @@ -16,7 +16,7 @@ import DocsLayout from "../../../../layouts/DocsLayout.astro";
tree
根文档与 topic 的动态地图。
index [--topic …] [--kind …]
用于发现文档的 front matter 投影。
search <query>
在跟踪知识中执行词法搜索。
-
context --files <src…>
把源码路径映射到 owner 文档与依赖前置。
+
context --files <src…>
逐个把源码路径映射到 owner 文档与依赖前置,并明确报告未映射输入。
show <path…>
读取选中的文档正文。
serve
127.0.0.1 启动本地 Viewer,查看文档结构、关系与状态。
@@ -25,7 +25,7 @@ import DocsLayout from "../../../../layouts/DocsLayout.astro";
status
有效性、baseline、dirty 与增长信号。
delta
从代码变化计算受影响文档闭包。
-
validate
校验 schema、结构、关系、链接、代码路径与 ledger 一致性。
+
validate
校验 schema、结构、关系、链接、代码路径(含零命中 glob)与 ledger 一致性。

安全改写

diff --git a/website/src/pages/zh/docs/concepts/index.astro b/website/src/pages/zh/docs/concepts/index.astro index 437dd27..0c0eb00 100644 --- a/website/src/pages/zh/docs/concepts/index.astro +++ b/website/src/pages/zh/docs/concepts/index.astro @@ -15,6 +15,15 @@ import DocsLayout from "../../../../layouts/DocsLayout.astro";

Context Floor 是 Agent 解决当前问题所需的上下文丰富度。工具调用数量、Token 占用和关键信息密度,共同决定到达这条线需要多久。

llmdoc 在广泛探索源码前提高信息密度,但不替代源码。它收窄工作集后,原生工具继续核对实现文本、行号、测试与 Git 状态等实时事实。

+

设计模型:语义路由图

+

llmdoc 不是仓库的压缩副本,而是最小且连通的持久工程知识图:让 Agent 找到正确 owner,理解约束当前任务的设计决策,再进入权威源码核对实时事实。

+
    +
  • 决策优先于观察:文档保存理由、边界、不变量、契约、失败语义与高风险工作流;源码、测试、schema 和 manifest 保存实时事实。
  • +
  • 所有权优先于目录:知识跟随稳定职责与 review 边界,而不是机械映射 package 或文件夹。
  • +
  • 渐进披露:地图、路由元数据、选中正文与源码构成逐层加深的读取路径。
  • +
  • 复核耦合:code.paths 把代码变化连到可能需要复核的文档,而不是制造文件覆盖率。
  • +
+

渐进读取

检索面逐层披露:先给地图或元数据,再按搜索或源码所有权定位,最后读取选中的正文。调用者可以在任一层停止。

tree / index  →  search / context  →  show
@@ -35,6 +44,15 @@ import DocsLayout from "../../../../layouts/DocsLayout.astro"; │ └── retry-policy.mdx └── meta.json +

从 domain 到 topic 再到 document

+

Domain 是分析边界:一组稳定职责、权威归属、不变量、失败模型和变更词汇。Topic 是它在 llmdoc/ 下的持久检索邻域。Document 是一个完整问题、契约、不变量簇或工作流的 canonical owner。

+

Package 边界只是证据。所有权、失败语义或常见查询能够独立稳定时才拆 topic;跨 package 的代码若共同实现一个契约,则应归入同一语义域。根文档只承载真正跨 topic 的知识。

+

architecture 用于边界、流程、设计因果与不变量;guide 用于带验证和恢复步骤的可重复工作流;reference 用于稳定契约、精确查表与决策矩阵。

+ +

两道独立门

+

Stable Knowledge Gate 决定哪些正文值得长期保存;Routing Gate 则检查自然语言概念查询和代表性决策源码能否到达正确 owner。正文精炼不能掩盖路由缺失,映射源码也不等于要在正文逐文件复述。

+

validate 只检查结构。Context Floor 验收还要用自然语言 search、逐个入口与叶子文件的 context --files、宽 glob 的无关兄弟负例,以及必读关系做验证。每个 first-class 子系统都必须被归类为“已文档化”“有意由源码重建”,或作为阻塞缺口报告。

+

有效性以 Git 为基础

llmdoc/meta.json 跟踪经过验证的 Git revision。工作树 dirty 是额外信号,不会被伪装成 revision。delta 命中意味着必须复核,并不自动意味着正文需要改写。

diff --git a/website/src/pages/zh/docs/workflows/index.astro b/website/src/pages/zh/docs/workflows/index.astro index 8418707..841a382 100644 --- a/website/src/pages/zh/docs/workflows/index.astro +++ b/website/src/pages/zh/docs/workflows/index.astro @@ -20,10 +20,12 @@ import DocsLayout from "../../../../layouts/DocsLayout.astro";

初始化

-

只有仓库不存在有效 V3 知识面时,才使用 init。它调查 topic 边界、写入少量高价值文档、完成校验,并以 Git 状态收尾。

+

只有仓库不存在有效 V3 知识面时,才使用 init。它设计 domain 与 topic 边界、写入最小充分的 owner 文档,并把每个 first-class 子系统归类为“已文档化”“有意由源码重建”或阻塞缺口。

+

结构校验通过后,init 还要验证自然语言概念查询、每个 implementation boundary 的代表文件、wildcard 负例与必读关系闭包,才能以 Git 状态收尾。

更新

update 对照代码 delta 与已授权的 reflection candidate,语义复核现有知识。仍然正确的文档会被标记为 verified unchanged,不会累积变更日志。

+

正文与路由必须独立复核:正文仍然正确时,descriptioncode.paths 或 relations 仍可能需要修复。

update 信号产生的是复核集合,不是正文写入列表。

收敛

From c4ab503b053420051eff1a8b59acdcc1e372246a Mon Sep 17 00:00:00 2001 From: DJJ Date: Thu, 27 Aug 2026 20:02:54 +0800 Subject: [PATCH 2/4] docs: document context floor routing --- llmdoc/architecture.mdx | 15 +++++++++++++-- llmdoc/cli-runtime/retrieval-and-mutation.mdx | 4 ++-- llmdoc/cli-runtime/state-and-validation.mdx | 4 ++-- llmdoc/plugin-packaging/claude-and-codex.mdx | 6 ++++-- llmdoc/workflows/init-and-update.mdx | 10 ++++++++-- 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/llmdoc/architecture.mdx b/llmdoc/architecture.mdx index a6a56aa..a3d8b0c 100644 --- a/llmdoc/architecture.mdx +++ b/llmdoc/architecture.mdx @@ -1,5 +1,5 @@ --- -description: llmdoc 的职责分层、三道知识门与跨宿主真相源边界。 +description: llmdoc 语义路由图的设计原则、职责分层,以及稳定知识与 owner 路由的独立门槛。 kind: architecture relations: related: @@ -22,10 +22,20 @@ code: - README.md - README.zh-CN.md - docs/v3-design/*.md + - skills/llmdoc/references/knowledge-topology.md + - .agents/skills/llmdoc/references/knowledge-topology.md --- # llmdoc 仓库整体架构 +## 设计模型:最小充分的语义路由图 + +llmdoc 不是仓库的压缩副本,而是让任务在广泛探索前抵达正确 owner 的最小连通知识图。稳定正文保存难以从源码快速恢复的决策、理由、边界、不变量、契约与失败语义;源码、测试、schema 和 manifest 继续保存实时事实。知识边界因此跟随职责、authority 和 review obligation,而不是机械复制 package 或目录布局。 + +渐进披露是这张图的读取约束:`tree` 提供地图,description 与 search 提供概念候选,`code.paths` 与 context 提供变更 owner,relations 补充必读闭包,最后才加载选中正文并进入源码。每一层都应允许调用者停止,而不是迫使其先读完整仓库知识。 + +`code.paths` 的目的不是制造覆盖率,而是把变化与可能失效的知识耦合。最小充分意味着每个 first-class 决策表面都可达,同时允许生成物、barrel、普通 helper 和没有持久语义的实现细节有意保持 unmapped。 + ## 职责分层 - `cli/` 承担扫描、schema 校验、检索、git revision、delta、hook 与安全改写等确定性能力。 @@ -35,10 +45,11 @@ code: 核心分工是“提示词做判断,CLI 做机械”:prompt 不复制 diff、schema 或 git 逻辑;稳定正文也不复制命令、文件和测试库存。 -## 三道知识门 +## 检索、反思与双重维护门 - **Retrieval Gate**:首次探索或进入新子系统时,按意图选择一个 CLI 入口;CLI 圈定工作集后,原生工具核对源码、行号、测试与 git 等实时事实。 - **Reflection Gate**:用户纠正、验证证伪、重大返工、指令违规等强信号,由 `reflector` 写成 `.llmdoc-tmp/reflections/pending/` 候选;不保存 transcript,也不直接写 tracked knowledge。 - **Stable Knowledge Gate**:`recorder` 只晋升会改变未来选择、难以从 canonical source 快速恢复、足够持久且归属明确的结论。候选和代码 delta 都只是复核证据,不是正文写入指令。 +- **Routing Gate**:独立检查自然概念查询与代表性决策源码能否到达 canonical owner。正文仍正确时可能只需修复路由;文件被映射也不要求在正文中逐项转述。 pending 候选即使没有代码 delta 也能触发 update;只有显式授权的 reflection update 才能验证、查重并把成熟规则折入既有 architecture/guide,永不恢复 tracked reflection 树。 diff --git a/llmdoc/cli-runtime/retrieval-and-mutation.mdx b/llmdoc/cli-runtime/retrieval-and-mutation.mdx index 735224c..ed38702 100644 --- a/llmdoc/cli-runtime/retrieval-and-mutation.mdx +++ b/llmdoc/cli-runtime/retrieval-and-mutation.mdx @@ -1,5 +1,5 @@ --- -description: 渐进读取模型,以及结构改写和 commit 的安全、事务边界。 +description: 渐进读取、逐输入 source-owner 路由,以及结构改写和 commit 的安全事务边界。 kind: reference relations: related: @@ -38,7 +38,7 @@ code: ## 渐进读取模型 -读取面按“地图/索引或搜索/正文”逐层暴露,调用者在任一层都可以停止;这些命令返回受预算约束的公开投影,不泄漏内部解析对象。`context --files` 用 `code.paths` 反查 owner,并补齐 `relations.requires` 前置闭包。文本与 JSON 输出共用 schema 契约,避免不同宿主形成第二套语义。 +读取面按“地图/索引或搜索/正文”逐层暴露,调用者在任一层都可以停止;这些命令返回受预算约束的公开投影,不泄漏内部解析对象。`context --files` 对每个输入独立用 `code.paths` 反查 owner,再对 owner 并集补齐 `relations.requires` 前置闭包;未命中的输入通过 `unmappedFiles` 单独返回,不能被同批查询中的成功命中掩盖。文本与 JSON 输出共用 schema 契约,避免不同宿主形成第二套语义。 Viewer 是同一知识面的只读本地投影,不是新的改写入口。服务命令只负责 loopback 生命周期与装配;HTTP 层只接受 GET/HEAD 和显式资产/API 路由,文档读取必须命中 workspace 扫描得到的 canonical ID,不能把请求路径解释成文件系统路径;状态层把 workspace、delta、validate 与 growth 投影为可序列化 DTO,并以 `requires > related > link` 的优先级确定同向关系,反向关系仍独立保留。 diff --git a/llmdoc/cli-runtime/state-and-validation.mdx b/llmdoc/cli-runtime/state-and-validation.mdx index fc51b2e..5f4cd51 100644 --- a/llmdoc/cli-runtime/state-and-validation.mdx +++ b/llmdoc/cli-runtime/state-and-validation.mdx @@ -1,5 +1,5 @@ --- -description: Workspace 边界、revision 有效性、delta 影响扩展与 hook 信号契约。 +description: Workspace 边界、结构校验与 glob 有效性、revision/delta 影响扩展及 hook 信号契约。 kind: architecture code: paths: @@ -30,7 +30,7 @@ code: CLI 只接受最近 Git 根直属的 `llmdoc/`,避免跨仓库误认;没有 Git 边界时才保留初始化场景的向上兼容查找。V3 文档树固定为根 singleton 加一层 topic,路径即文档 ID;不设 `index.mdx`,topic 摘要由 CLI 聚合。`meta.json` 只保存有效性台账,不复制可扫描的树结构。 -`validate` 的责任是保证 schema、两层结构、引用、代码锚点、realpath 边界与 ledger/文件树一致。精确字段集合属于 schema,不在稳定正文重复维护。 +`validate` 的责任是保证 schema、两层结构、引用、代码锚点、realpath 边界与 ledger/文件树一致;`code.paths` 的精确路径必须存在,glob 也必须至少命中一个现有文件,避免陈旧 pattern 静默通过。它只证明结构有效,不判断某个 pattern 是否错误吸附无关文件,或 first-class owner 是否缺失;这些语义问题属于 Routing Gate 与 Context Floor 验收。精确字段集合属于 schema,不在稳定正文重复维护。 ## Revision 与影响语义 diff --git a/llmdoc/plugin-packaging/claude-and-codex.mdx b/llmdoc/plugin-packaging/claude-and-codex.mdx index 130e977..2a9ebd9 100644 --- a/llmdoc/plugin-packaging/claude-and-codex.mdx +++ b/llmdoc/plugin-packaging/claude-and-codex.mdx @@ -13,6 +13,8 @@ code: - agents/*.md - hooks/hooks.json - scripts/check-codex-surface.mjs + - skills/llmdoc/references/knowledge-topology.md + - .agents/skills/llmdoc/references/knowledge-topology.md - tests/parity-checklist.md - README.md - README.zh-CN.md @@ -28,8 +30,8 @@ Claude 根插件是手工维护的 canonical surface:skills 定义 Retrieval/R ## 生成与一致性不变量 -转换必须在临时副本生成后替换式同步,因为生成器不保证清除陈旧输出。Codex 角色文本不手工维护;宿主特有 front matter/TOML 可以不同,实际 skill 与 agent 指令正文必须与 Claude canonical 一致。 +转换必须在临时副本生成后替换式同步,因为生成器不保证清除陈旧输出。Codex 角色文本不手工维护;宿主特有 front matter/TOML 可以不同,实际 skill 与 agent 指令正文必须与 Claude canonical 一致。被 skill 按需加载的 reference 同样属于可执行 prompt surface:Codex 镜像必须包含相同正文,相关 skill/agent 也必须保留可发现的加载路径。 -`scripts/check-codex-surface.mjs` 在 CI 中机械校验版本/marketplace 身份、五个 skill 与三个 agent 的正文一致性、Reflection Gate 约束和 hook 调用。它还分别遍历 `skills/` 与 `.agents/skills/`,用 `gray-matter` 解析每份 `SKILL.md` 的 YAML front matter,并要求 `name`、`description` 是非空字符串;这是两侧各自的语法门槛,不替代跨宿主正文 parity。人工 checklist 只补宿主 UI policy 与信任模型等无法从正文等价判断的部分。 +`scripts/check-codex-surface.mjs` 在 CI 中机械校验版本/marketplace 身份、五个 skill 与三个 agent 的正文一致性、按需 reference 的正文 parity 与加载路径、Reflection Gate 约束和 hook 调用。它还分别遍历 `skills/` 与 `.agents/skills/`,用 `gray-matter` 解析每份 `SKILL.md` 的 YAML front matter,并要求 `name`、`description` 是非空字符串;这是两侧各自的语法门槛,不替代跨宿主正文 parity。人工 checklist 只补宿主 UI policy、知识拓扑质量与信任模型等无法从正文等价判断的部分。 hooks 位于共享插件根,一份配置供两种宿主使用;它们保持 fail-open、只读,且由安装宿主按自己的信任模型启用。 diff --git a/llmdoc/workflows/init-and-update.mdx b/llmdoc/workflows/init-and-update.mdx index 3305eda..caf31ff 100644 --- a/llmdoc/workflows/init-and-update.mdx +++ b/llmdoc/workflows/init-and-update.mdx @@ -1,5 +1,5 @@ --- -description: init/update 的授权边界、reflection 与稳定知识双门、light/deep 分流及 verified 收尾。 +description: init/update 的 domain-topic-owner 设计、Stable/Routing 双门、Context Floor 验收及 verified 收尾。 kind: guide relations: related: @@ -15,6 +15,8 @@ code: - cli/src/commands/status.ts - cli/src/commands/delta.ts - cli/src/commands/fingerprint.ts + - skills/llmdoc/references/knowledge-topology.md + - .agents/skills/llmdoc/references/knowledge-topology.md --- # Init 与 Update @@ -23,7 +25,9 @@ code: 两条工作流第一次正式写入前都要求 `llmdoc/` clean,写后必须 validate,失败且无法修复时回滚本次文档写集。它们只授权知识面与临时候选处理,不授权源码编辑。 -`init` 只用于没有有效 V3 知识面的仓库;已有 V3 转 update,legacy 结构只能走显式 upgrade。首次知识面先调查和确定 topic 边界,再由 `recorder` 写少量高价值核心文档,不追求源码全量转述。 +`init` 只用于没有有效 V3 知识面的仓库;已有 V3 转 update,legacy 结构只能走显式 upgrade。首次知识面先以稳定职责、authority、failure model 与查询词汇识别 domain,再把它们组织为持久 retrieval topic,最后由 `recorder` 为每个决策簇或风险工作流建立 canonical owner。Package 与目录只是边界证据;root singleton 只承载真正跨 topic 的契约。 + +目标是最小充分 owner 集,不是源码全量转述或固定文档数量。每个 first-class 子系统都必须在 scratch domain/owner matrix 中归为 documented、intentionally reconstructable 或 gap;no-doc 决定需要可快速恢复的 canonical source 与无隐藏持久语义的证据,未决 gap 会阻止 init success。 ## Update 是语义复核 @@ -36,6 +40,8 @@ reflection candidate 先验证 trigger、错误动作、根因、预防规则、 代码 delta 同样只产生复核义务。原文失效或出现合格新结论才改写;原文仍成立时标记 verified unchanged,不追加本次 diff、路径库存或证据。 +Stable Knowledge Gate 与 Routing Gate 独立:前者决定正文是否值得持久化,后者决定概念和决策源码是否能到达正确 owner。`validate` 只关闭结构问题;init 必须在其后用自然语言 search、每个实现边界的逐文件 context probe、宽 glob 的无关 sibling 负例,以及 `tree --docs` 配合 `index`/context 的 requires 闭包完成 Context Floor 验收。Update 在 unmapped、移动或边界变化时先分类为 missing mapping、missing owner 或 intentional no-doc,再对受影响范围运行同样的路由检查。 + ## 收尾与 revision `recorder` 负责正文和 validate,calling workflow 负责 `commit`:正文改动与 `--verified` 文档可一次取 fingerprint 并集;全部未改时用 meta-only `commit --verified`;全仓复核才用 `--all`。相关实现仍 dirty 时不得推进 revision。 From 2b114c1e18652ea1ef337848f5837a67157bf057 Mon Sep 17 00:00:00 2001 From: DJJ Date: Thu, 27 Aug 2026 20:02:54 +0800 Subject: [PATCH 3/4] chore(llmdoc): refresh fingerprints --- llmdoc/meta.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/llmdoc/meta.json b/llmdoc/meta.json index c173676..473d0e0 100644 --- a/llmdoc/meta.json +++ b/llmdoc/meta.json @@ -6,28 +6,28 @@ }, "documents": { "architecture.mdx": { - "validatedRevision": "33b263754aa85d53e3a19a1daa67e24420e0a45e" + "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" }, "cli-runtime/state-and-validation.mdx": { - "validatedRevision": "33b263754aa85d53e3a19a1daa67e24420e0a45e" + "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" }, "cli-runtime/retrieval-and-mutation.mdx": { - "validatedRevision": "33b263754aa85d53e3a19a1daa67e24420e0a45e" + "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" }, "plugin-packaging/claude-and-codex.mdx": { - "validatedRevision": "33b263754aa85d53e3a19a1daa67e24420e0a45e" + "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" }, "plugin-packaging/development-and-release.mdx": { - "validatedRevision": "33b263754aa85d53e3a19a1daa67e24420e0a45e" + "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" }, "workflows/init-and-update.mdx": { - "validatedRevision": "33b263754aa85d53e3a19a1daa67e24420e0a45e" + "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" }, "workflows/prune-and-upgrade.mdx": { - "validatedRevision": "33b263754aa85d53e3a19a1daa67e24420e0a45e" + "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" }, "website/product-and-deployment.mdx": { - "validatedRevision": "c13545ef43718fa7114c57b382019027b2169451" + "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" } }, "convergence": { From 4922bb1ddce5fac9bd8328ba8e798a063b3717c1 Mon Sep 17 00:00:00 2001 From: DJJ Date: Thu, 27 Aug 2026 20:03:28 +0800 Subject: [PATCH 4/4] chore(llmdoc): refresh fingerprints --- llmdoc/meta.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/llmdoc/meta.json b/llmdoc/meta.json index 473d0e0..63965ea 100644 --- a/llmdoc/meta.json +++ b/llmdoc/meta.json @@ -1,33 +1,33 @@ { "schema": "llmdoc.meta/v3", "baseline": { - "revision": "61ef5822ec305f61ebf41bb826e143a889c31e5e", - "verifiedAt": "2026-08-27T04:39:35.370Z" + "revision": "2b114c1e18652ea1ef337848f5837a67157bf057", + "verifiedAt": "2026-08-27T12:03:28.648Z" }, "documents": { "architecture.mdx": { - "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" + "validatedRevision": "2b114c1e18652ea1ef337848f5837a67157bf057" }, "cli-runtime/state-and-validation.mdx": { - "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" + "validatedRevision": "2b114c1e18652ea1ef337848f5837a67157bf057" }, "cli-runtime/retrieval-and-mutation.mdx": { - "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" + "validatedRevision": "2b114c1e18652ea1ef337848f5837a67157bf057" }, "plugin-packaging/claude-and-codex.mdx": { - "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" + "validatedRevision": "2b114c1e18652ea1ef337848f5837a67157bf057" }, "plugin-packaging/development-and-release.mdx": { - "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" + "validatedRevision": "2b114c1e18652ea1ef337848f5837a67157bf057" }, "workflows/init-and-update.mdx": { - "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" + "validatedRevision": "2b114c1e18652ea1ef337848f5837a67157bf057" }, "workflows/prune-and-upgrade.mdx": { - "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" + "validatedRevision": "2b114c1e18652ea1ef337848f5837a67157bf057" }, "website/product-and-deployment.mdx": { - "validatedRevision": "c4ab503b053420051eff1a8b59acdcc1e372246a" + "validatedRevision": "2b114c1e18652ea1ef337848f5837a67157bf057" } }, "convergence": {