Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .agents/skills/init/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Stop instead of improvising when:
- 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 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.
- If the user wants non-default SessionStart guidance or deliberate document preload, read [Startup Configuration](../llmdoc/references/startup-config.md) and create `llmdoc.config.json`; otherwise do not add optional startup config during bootstrap.

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.
Expand Down
5 changes: 2 additions & 3 deletions .agents/skills/llmdoc/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ allowed-tools: 'Read, Glob, Grep, Bash, Write, Edit, WebSearch, WebFetch'

# /llmdoc

The operating protocol for V3 `llmdoc` projects. `llmdoc/` holds the architecture, constraints, and working agreements that source code does not cheaply give back; the CLI is how you reach them.

Every command below runs as `npx -y @tokenroll/llmdoc <cmd>`; the CLI Invocation section holds the full rules.
Use the CLI to retrieve durable architecture, constraints, and working agreements from V3 `llmdoc/` projects. Run commands as `npx -y @tokenroll/llmdoc <cmd>`.

## Retrieval Gate

Expand Down Expand Up @@ -51,6 +49,7 @@ These entry points are alternatives, not a sequence. Stop as soon as the task ha
- 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).
- For SessionStart reminders or document preload, read [Startup Configuration](references/startup-config.md).
- Never suggest `/llmdoc:upgrade`; it runs only when the user asks for it by name.

## Reflection Gate
Expand Down
40 changes: 40 additions & 0 deletions .agents/skills/llmdoc/references/startup-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
+# Startup Configuration

Read this reference when a user asks to configure SessionStart guidance or preload documents, or when a workflow creates, renames, merges, or deletes a document named in startup preload.

## File and schema

Place the optional `llmdoc.config.json` at the llmdoc workspace root. In a Git repository this is the nearest Git root that owns `llmdoc/`; the no-Git fallback is the directory that owns `llmdoc/`.

```json
{
"$schema": "https://llmdoc.tokenroll.ai/schemas/config.schema.json",
"schema": "llmdoc.config/v1",
"startup": {
"remindSkill": true,
"preload": [
"architecture.mdx",
"api-client/contracts.mdx"
]
}
}
```

- `startup.remindSkill` defaults to `true`. Set it to `false` only when the repository deliberately supplies equivalent operating guidance elsewhere or wants no proactive reminder.
- `startup.preload` contains exact `.mdx` document IDs in declaration order. An entry may include the `llmdoc/` prefix.
- Cold SessionStart injects configured bodies directly and has no llmdoc character or token budget. A final completion marker distinguishes a complete preload from host-side truncation; if it is absent, retrieve only the missing body with `show`.
- Compact re-entry lists configured document IDs without injecting the bodies again. Use the compacted `LLMDOC_STATE` first and retrieve a body only when needed.

## Validation and degradation

Run `validate` after creating or editing the file. Invalid JSON or schema cannot preserve field intent, so hooks use the default reminder and skip preload. When the schema is valid but a preload path is invalid or missing, hooks preserve the valid `remindSkill` choice and skip the preload field. Entries that normalize to the same document are deduplicated with a warning.

## Structural changes

A preload entry is a persistent reference and must stay synchronized with document identity:

- `llmdoc mv` rewrites matching preload entries transactionally with document references and the ledger.
- Before a prune workflow manually merges or deletes documents, inspect the report's startup preload references and update or remove affected entries in the same write set.
- After any manual path change, run `validate` before `commit`. A missing preload target is an error and intentionally blocks finalization.

Do not create this file during init unless the user or repository requirements call for non-default startup behavior or deliberate document preload.
2 changes: 2 additions & 0 deletions .agents/skills/prune/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ This command does not authorize source-code edits.

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.
- Read [Startup Configuration](../llmdoc/references/startup-config.md) when the report lists startup preload references. Update or remove affected config entries in the same write set before merging or deleting their documents; `mv` handles direct renames automatically.
- 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.
Expand All @@ -45,6 +46,7 @@ This command does not authorize source-code edits.
- Delete a document when it has no unique durable knowledge; canonical source, schema, help, or tests are valid destinations for discarded evidence. Do not copy low-value content elsewhere merely to justify deletion.

3. Re-validate the result.
- Confirm every configured startup preload still targets the surviving owner document.
- 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.
Expand Down
1 change: 1 addition & 0 deletions .agents/skills/update/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ This command does not authorize source-code edits.
- Scaffold brand-new docs with `new`; register docs that already exist as files with `adopt <path...>` — never hand-edit `meta.json` or recreate the file through `new`.

5. Finalize.
- If document identities changed, read [Startup Configuration](../llmdoc/references/startup-config.md). `mv` syncs renames; sync manual merges or deletions before validation.
- Run `validate`; after mapping or boundary changes, also run the reference's scoped routing acceptance.
- If prose changed, run `commit -m "<message>"`, adding `--verified <path...>` for reviewed unchanged docs. If all stayed unchanged, run `commit --verified <path...>`. Full verification uses `--all`, never with `--verified`.
- `commit` validates, commits prose, refreshes fingerprints, and lands `meta.json` separately. Never reconstruct this sequence manually or `--amend` it.
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"name": "llmdoc",
"source": "./",
"description": "Persistent engineering context powered by the llmdoc CLI and progressive MDX knowledge retrieval",
"version": "3.5.3"
"version": "3.6.0"
}
]
}
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "llmdoc",
"description": "Persistent engineering context powered by the llmdoc CLI and progressive MDX knowledge retrieval",
"version": "3.5.3",
"version": "3.6.0",
"author": {
"name": "DJJ & Danniel"
}
Expand Down
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "llmdoc",
"version": "3.5.3",
"version": "3.6.0",
"description": "Persistent engineering context powered by the llmdoc CLI and progressive MDX knowledge retrieval",
"skills": "./.agents/skills/"
}
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,30 @@ jobs:
npm init --yes >/dev/null
npm install "${GITHUB_WORKSPACE}/cli/${tarball}" >/dev/null
npx --no-install @tokenroll/llmdoc --help

website:
name: Website and published schema
runs-on: ubuntu-latest
timeout-minutes: 10
defaults:
run:
working-directory: website
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.2.2

- name: Use Node.js 22
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22
cache: npm
cache-dependency-path: website/package-lock.json

- name: Install
run: npm ci

- name: Check and build
run: npm run check && npm run build

- name: Verify published config schema
run: npm run check:schema
50 changes: 48 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,50 @@ Use `npx -y @tokenroll/llmdoc --help` or
reference. `status` and `delta` assess validity and impact; they are not
retrieval steps.

### Startup context configuration

Repositories that use the lifecycle hooks can add an optional
`llmdoc.config.json` at the llmdoc workspace root. In a Git repository, this is
the nearest Git root that owns `llmdoc/`:

```json
{
"$schema": "https://llmdoc.tokenroll.ai/schemas/config.schema.json",
"schema": "llmdoc.config/v1",
"startup": {
"remindSkill": true,
"preload": [
"architecture.mdx",
"plugin-packaging/claude-and-codex.mdx"
]
}
}
```

- `remindSkill` controls the SessionStart operating guidance: load the llmdoc
skill, use the CLI retrieval gate, and delegate to the llmdoc roles. It
defaults to `true`; set it to `false` to opt out.
- `preload` lists exact document IDs, with an optional `llmdoc/` prefix. Cold
SessionStart inserts their bodies directly in the listed order with no llmdoc
character or token budget. A final completion marker confirms that the host
supplied the full preload; without it, retrieve only the missing body with
`show`.
- Compact re-entry lists configured document IDs but does not inject their full
bodies again. Continue from `LLMDOC_STATE` and retrieve a body only if needed.
- `validate` reports malformed config, missing paths, and path escapes.
Normalized aliases of the same document are deduplicated with a warning.
Lifecycle hooks stay fail-open: unreadable schema/JSON uses the default
reminder, while a valid `remindSkill` choice survives preload-only errors.
- `mv` rewrites matching preload paths transactionally. `prune --report` lists
preload references that must be updated before a manual merge or deletion.

Without this file, SessionStart emits its state plus the default operating
guidance and does not preload documents.

All fixed CLI interface text is English, including help, diagnostics, hook
messages, and the local Viewer. Chinese queries and repository document content
remain fully supported and are returned unchanged.

## Knowledge and safety boundaries

- Stable knowledge belongs in tracked `llmdoc/`; investigations, caches, and
Expand All @@ -161,8 +205,10 @@ retrieval steps.
- Every workflow authorizes knowledge maintenance only, not source-code edits.
Structural writes are validated and confined to the repository's `llmdoc/`
boundary.
- Hooks emit read-only, fail-open signals through the scoped CLI. Review hooks
and trust the plugin source before enabling them.
- Hooks emit read-only, fail-open signals through the scoped CLI. SessionStart
also injects the configurable operating guidance, so projects do not need to
repeat it in CLAUDE.md/AGENTS.md. Review hooks and trust the plugin source
before enabling them.
- A `delta` match means “review this claim,” not “rewrite this document.”
Preserve decisions, rationale, boundaries, invariants, contracts, and
non-obvious failure semantics; leave reconstructable facts in source, schemas,
Expand Down
43 changes: 41 additions & 2 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,44 @@ npx -y @tokenroll/llmdoc serve
`npx -y @tokenroll/llmdoc help <command>` 为准。`status` 与 `delta`
用于评估有效性和影响面,不是检索步骤。

### 启动上下文配置

启用 lifecycle hooks 的仓库可以在 llmdoc workspace 根目录增加可选的
`llmdoc.config.json`;在 Git 仓库中,它就是拥有 `llmdoc/` 的最近 Git 根:

```json
{
"$schema": "https://llmdoc.tokenroll.ai/schemas/config.schema.json",
"schema": "llmdoc.config/v1",
"startup": {
"remindSkill": true,
"preload": [
"architecture.mdx",
"plugin-packaging/claude-and-codex.mdx"
]
}
}
```

- `remindSkill` 控制 SessionStart 是否注入最小操作守则:加载 llmdoc skill、
经过 CLI retrieval gate,并委派给 llmdoc roles。默认值为 `true`;显式设为
`false` 才关闭。
- `preload` 按顺序列出精确文档 ID,可以带或不带 `llmdoc/` 前缀。冷启动会按
声明顺序直接注入完整正文,llmdoc 不设置字符或 token 预算。只有最终完成标记
可见时才表示宿主提供了完整 preload;若标记缺失,只对缺少的正文执行 `show`。
- compact 重入只列出配置的文档 ID,不会再次注入完整正文;优先延续
`LLMDOC_STATE`,确有需要时才重新读取。
- `validate` 会报告非法配置、不存在的路径与路径越界;规范化后指向同一文档的
别名会去重并产生 warning。hook 保持 fail-open:JSON/schema 无法读取时使用
默认提醒;如果只有 preload 项无效,合法的 `remindSkill` 选择仍会保留。
- `mv` 会事务性重写匹配的 preload 路径;`prune --report` 会列出手工合并或删除
文档前必须同步的 preload 引用。

没有该文件时,SessionStart 输出状态和默认操作守则,但不预载文档。

CLI 自身的固定界面文案全部使用英文,包括 help、诊断、hook message 与本地
Viewer;中文查询与仓库文档正文仍完整支持,并保持原文返回。

## 知识与安全边界

- 稳定知识属于 tracked `llmdoc/`;调查、缓存和反思候选属于本地 `.llmdoc-tmp/`。
Expand All @@ -144,8 +182,9 @@ npx -y @tokenroll/llmdoc serve
安全的经验候选,`recorder` 是唯一写入 tracked knowledge 的角色。
- 每条 workflow 都只授权知识维护,不授权源码编辑。结构写入会经过校验,并被限制在
仓库的 `llmdoc/` 边界内。
- Hooks 通过 scoped CLI 发出只读、fail-open 的信号。启用前先审查 hooks,并
确认插件来源可信。
- Hooks 通过 scoped CLI 发出只读、fail-open 的信号。SessionStart 还会注入
可配置的最小操作守则,因此项目无需在 CLAUDE.md/AGENTS.md 重复该引导。
启用前先审查 hooks,并确认插件来源可信。
- `delta` 命中表示“复核这条结论”,不是“改写这篇文档”。保留决策及理由、
边界、不变量、契约和非显然失败语义;可重建事实应留在源码、schema、help、
测试或生成配置中。
Expand Down
22 changes: 11 additions & 11 deletions cli/assets/viewer-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ async function loadState() {
const response = await fetch("/api/state", { headers: { accept: "application/json" } });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const nextState = await response.json();
if (!Array.isArray(nextState.nodes) || !Array.isArray(nextState.edges)) throw new Error("服务返回了无效状态");
if (!Array.isArray(nextState.nodes) || !Array.isArray(nextState.edges)) throw new Error("The server returned invalid state");
state = nextState;
topicColors = createTopicColors(state.nodes);
if (selectedDocument && !state.nodes.some((node) => node.path === selectedDocument)) selectedDocument = null;
Expand All @@ -83,15 +83,15 @@ function renderHeader() {
const baseline = state.baseline;
const shortRevision = baseline.revision?.slice(0, 7);
if (!baseline.revision) {
setChip(elements.statBaseline, "baseline 缺失", "bad");
setChip(elements.statBaseline, "baseline missing", "bad");
} else if (baseline.degradedReason || baseline.relevantBehindHead === null) {
setChip(elements.statBaseline, `baseline ${shortRevision} · 状态未知`, "warn");
setChip(elements.statBaseline, `baseline ${shortRevision} · status unknown`, "warn");
} else if (baseline.relevantBehindHead > 0) {
setChip(elements.statBaseline, `baseline ${shortRevision} · ${baseline.relevantBehindHead} 个源码提交待复核`, "warn");
setChip(elements.statBaseline, `baseline ${shortRevision} · ${baseline.relevantBehindHead} source commit(s) need review`, "warn");
} else if (baseline.metadataOnlyBehind) {
setChip(elements.statBaseline, `baseline ${shortRevision} · metadata-only,知识干净`, "ok");
setChip(elements.statBaseline, `baseline ${shortRevision} · metadata-only, knowledge clean`, "ok");
} else {
setChip(elements.statBaseline, `baseline ${shortRevision} · 最新`, "ok");
setChip(elements.statBaseline, `baseline ${shortRevision} · current`, "ok");
}

const validation = state.validate;
Expand All @@ -103,9 +103,9 @@ function renderHeader() {

const stale = state.nodes.filter((node) => node.status !== "fresh").length;
const unmapped = state.delta.unmappedCommittedPaths.length + state.delta.unmappedDirtyPaths.length;
if (stale) setChip(elements.statDelta, `${stale} 份待同步 · 建议 ${state.delta.suggestedMode}`, "warn");
else if (unmapped) setChip(elements.statDelta, `${unmapped} 个未映射变化 · 建议 ${state.delta.suggestedMode}`, "warn");
else setChip(elements.statDelta, "知识面新鲜", "ok");
if (stale) setChip(elements.statDelta, `${stale} document(s) pending · ${state.delta.suggestedMode} recommended`, "warn");
else if (unmapped) setChip(elements.statDelta, `${unmapped} unmapped change(s) · ${state.delta.suggestedMode} recommended`, "warn");
else setChip(elements.statDelta, "knowledge is current", "ok");
}

function setChip(chip, text, stateClass) {
Expand Down Expand Up @@ -154,7 +154,7 @@ function renderSidebar() {
fragment.append(item);
}
}
if (!fragment.childNodes.length) fragment.append(element("div", "empty-list", "没有匹配的文档"));
if (!fragment.childNodes.length) fragment.append(element("div", "empty-list", "No matching documents"));
elements.documentList.replaceChildren(fragment);
}

Expand Down Expand Up @@ -195,7 +195,7 @@ async function selectDocument(path) {
}

function showError(message) {
elements.error.textContent = `Viewer 加载失败:${message}`;
elements.error.textContent = `Viewer load failed: ${message}`;
elements.error.hidden = false;
}

Expand Down
Loading
Loading