project-librarian 0.4.1 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +36 -9
- package/README.md +36 -8
- package/SKILL.md +6 -1
- package/dist/agent-surfaces.js +67 -0
- package/dist/args.js +92 -90
- package/dist/code-index/modes.js +7 -1
- package/dist/init-project-wiki.js +67 -26
- package/dist/install-skill.js +3 -3
- package/dist/modes.js +48 -21
- package/dist/templates.js +53 -25
- package/package.json +7 -1
package/README.ko.md
CHANGED
|
@@ -52,7 +52,7 @@ Project Librarian은 에이전트에게 두 가지 로컬 정본을 제공합니
|
|
|
52
52
|
| 표면 | 에이전트가 얻는 것 |
|
|
53
53
|
| --- | --- |
|
|
54
54
|
| `wiki/startup.md` + `wiki/index.md` | 짧은 세션 시작 요약과 라우터. 관련 계획 페이지만 읽습니다. |
|
|
55
|
-
| `wiki/canonical
|
|
55
|
+
| `wiki/canonical/`, `wiki/roadmaps/`, `wiki/plans/`, `wiki/decisions/` | 현재 정본은 canonical, 큰 미래 작업은 roadmaps, 상세 실행은 plans, 지속되는 근거는 decisions에 둡니다. |
|
|
56
56
|
| `wiki/meta/document-taxonomy.md` | PRD, 정책, UX, 데이터, 개발, QA, 릴리즈, 운영 정본을 어디에 둘지 안내하는 서비스 생애주기 분류 지도. |
|
|
57
57
|
| `.codex/`, `.claude/`, `.cursor/`, `.gemini/` 훅 | 전체 위키를 불러오지 않는 Codex/Claude Code/Cursor/Gemini CLI 시작 컨텍스트. |
|
|
58
58
|
| `GEMINI.md` 및 `.cursor/rules/` | Gemini CLI와 Cursor를 같은 간결한 위키 우선 계약으로 안내하는 지침 파일. |
|
|
@@ -75,17 +75,19 @@ npm run benchmark:release:preview
|
|
|
75
75
|
npm run benchmark:release -- --allow-codex-run
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
+
실측 릴리스 실행은 stderr에 `[benchmark:progress]` 줄을 스트리밍하여 시나리오 수, 예상 Codex 실행 총량, 현재 실행 순번, 단계, 프롬프트 ID, 종료 상태, 경과 시간, 원시 JSONL 경로를 보여줍니다. stdout은 최종 JSON 결과 전용으로 유지됩니다.
|
|
79
|
+
|
|
78
80
|
### 위키 트랙 (계획 문서 라우팅)
|
|
79
81
|
|
|
80
82
|
비용 가중 토큰, Project Librarian 대 대조군:
|
|
81
83
|
|
|
82
84
|
| 규모 | decision_lookup | aggregation | multi_session (2번째 세션) |
|
|
83
85
|
| --- | --- | --- | --- |
|
|
84
|
-
| 소형 |
|
|
85
|
-
| 중형 |
|
|
86
|
-
| 대형 | 71.
|
|
86
|
+
| 소형 | 14.4% 적음 | 81.0% 많음 | 22.0% 적음 |
|
|
87
|
+
| 중형 | 52.0% 적음 | 19.0% 적음 | 54.1% 적음 |
|
|
88
|
+
| 대형 | 71.1% 적음 | 29.0% 적음 | 71.8% 적음 |
|
|
87
89
|
|
|
88
|
-
최신 합성 위키 트랙 릴리스 후보는 2026-06-
|
|
90
|
+
최신 합성 위키 트랙 릴리스 후보는 2026-06-19에 `gpt-5.5`로 측정했으며, 42개 시나리오를 각 3회 측정하고 1회 예열했습니다. 전체 주장 게이트는 **통과**했습니다. 42/42개 시나리오가 정확성 검사를 통과했고, 42개 시나리오가 모두 claimable이었으며, 모든 corpus 게이트가 3회 실행 최소 조건을 충족했습니다. 이 릴리스 주장은 여전히 합성 위키 라우팅 트랙과 표기된 작업 유형에 한정됩니다. 코드 그래프 동작, 실제 저장소, 모든 에이전트 표면, 모든 질문 형태에 대한 주장이 아닙니다. 숨기지 않는 한계도 그대로 남습니다. 소형 `aggregation`은 위키를 켰을 때 여전히 81.0% 비싸고, 전체 보고서의 소형 `release_policy`도 9.4% 비싸며, `aggregation`은 토큰 비용이 줄어드는 규모에서도 실행 시간은 매번 더 느립니다.
|
|
89
91
|
|
|
90
92
|
### 코드 그래프 트랙 (코드 근거 인덱스, 실제 저장소)
|
|
91
93
|
|
|
@@ -143,6 +145,8 @@ npx project-librarian install-skill --scope project --agents all
|
|
|
143
145
|
|
|
144
146
|
`--agents`는 `codex,claude,cursor,gemini`처럼 쉼표로 구분한 값도 받습니다. `all`은 지원하는 모든 에이전트를 대상으로 합니다. `--scope`는 `user` 또는 `project`를 받습니다.
|
|
145
147
|
|
|
148
|
+
프로젝트 설정/갱신 실행기도 `--agents`를 받습니다. 새로 설정할 때는 프로젝트 범위 Project Librarian 스킬 설치가 없을 때만 지원하는 모든 에이전트 표면을 기본으로 만듭니다. 저장소에 이미 `.codex/skills/project-librarian/`, `.claude/skills/project-librarian/` 같은 프로젝트 범위 스킬이 있으면 첫 설정도 그 설치된 에이전트 집합을 기본값으로 사용합니다. 마이그레이션 없는 기존 설정 갱신은 저장소에 이미 있는 에이전트 표면만 보존해서 갱신합니다. 따라서 Codex와 Claude 파일만 있던 저장소는 일반 갱신만으로 Cursor나 Gemini 파일이 새로 생기지 않습니다. 새 표면을 의도적으로 추가하려면 `project-librarian update --agents cursor` 또는 `project-librarian update --agents all`처럼 명시합니다. 목록에 없는 표면을 삭제하지는 않습니다.
|
|
149
|
+
|
|
146
150
|
## 실행 경로
|
|
147
151
|
|
|
148
152
|
이 경로들은 주로 에이전트와 자동화를 위한 참조입니다. 설치 후 에이전트는 `npx`가 아니라 설치된 로컬 복사본을 `node`로 실행해야 합니다. 이렇게 하면 제한된 에이전트 환경에서 네트워크 접근과 버전이 고정되지 않은 패키지 실행을 피할 수 있습니다.
|
|
@@ -168,6 +172,7 @@ npx project-librarian install-skill --scope project --agents all
|
|
|
168
172
|
| --- | --- | --- |
|
|
169
173
|
| 위키 생성 또는 갱신 | "Project Librarian으로 이 저장소의 계획 위키를 설정하거나 갱신해줘." | `[init]` |
|
|
170
174
|
| 마이그레이션 없이 기존 설정 갱신 | "위키를 마이그레이션하지 말고 이 저장소의 Project Librarian 설정을 갱신해줘." | `update` |
|
|
175
|
+
| 기존 설정에 특정 에이전트 표면 추가 | "위키 마이그레이션 없이 Cursor Project Librarian 표면을 추가해줘." | `update --agents cursor` |
|
|
171
176
|
| 기존 문서/위키 마이그레이션 | "Project Librarian으로 기존 docs/wiki 내용을 마이그레이션해줘." | `--migrate` |
|
|
172
177
|
| 생성된 설정 검증 | "Project Librarian 검증을 실행해줘." | `--lint` |
|
|
173
178
|
| 링크와 문서 품질 점검 | "Project Librarian 진단을 실행해줘." | `--doctor` |
|
|
@@ -188,7 +193,7 @@ npx project-librarian install-skill --scope project --agents all
|
|
|
188
193
|
| 증분 갱신 요구 | "Project Librarian 코드 근거 인덱스를 증분 갱신해줘." | `--code-index --incremental` |
|
|
189
194
|
| 전체 재생성 강제 | "Project Librarian 코드 근거 인덱스를 전체 재생성해줘." | `--code-index --code-index-full` |
|
|
190
195
|
| 선택적 Tree-sitter 백엔드 사용 | "Tree-sitter 파서로 Project Librarian 코드 근거를 만들어줘." | `--code-index --code-parser tree-sitter` |
|
|
191
|
-
| 캐시 호환성 진단 | "Project Librarian 코드 근거 캐시
|
|
196
|
+
| 캐시 호환성 진단 | "Project Librarian 코드 근거 캐시 상태와 호환성을 진단해줘." | `--code-index-health` |
|
|
192
197
|
| 캐시 상태 보기 | "Project Librarian 코드 근거 상태를 보여줘." | `--code-status` |
|
|
193
198
|
| 인덱싱된 파일 목록 | "Project Librarian 코드 근거에 인덱싱된 파일을 보여줘." | `--code-files` |
|
|
194
199
|
| 아키텍처/소유권 보고서 출력 | "Project Librarian 코드 보고서를 보여줘." | `--code-report` |
|
|
@@ -202,6 +207,8 @@ npx project-librarian install-skill --scope project --agents all
|
|
|
202
207
|
|
|
203
208
|
## 설치되는 파일
|
|
204
209
|
|
|
210
|
+
새로 설정할 때는 `--agents`로 좁히지 않았고 프로젝트 범위 Project Librarian 스킬 설치도 없을 때 아래 지원 에이전트 표면을 설치합니다. 마이그레이션 없는 기존 설정 갱신은 기본적으로 감지된 표면만 보존해서 갱신하고, 공통 위키/git 훅 파일은 계속 갱신합니다.
|
|
211
|
+
|
|
205
212
|
프로젝트 지침 파일:
|
|
206
213
|
|
|
207
214
|
- `AGENTS.md`
|
|
@@ -229,6 +236,8 @@ Git 훅 파일:
|
|
|
229
236
|
위키 디렉터리:
|
|
230
237
|
|
|
231
238
|
- `wiki/canonical/`
|
|
239
|
+
- `wiki/roadmaps/`
|
|
240
|
+
- `wiki/plans/`
|
|
232
241
|
- `wiki/decisions/`
|
|
233
242
|
- `wiki/inbox/`
|
|
234
243
|
- `wiki/meta/`
|
|
@@ -369,6 +378,9 @@ npm install
|
|
|
369
378
|
npm run typecheck
|
|
370
379
|
npm run build
|
|
371
380
|
npm test
|
|
381
|
+
npm run test:coverage
|
|
382
|
+
npm run benchmark:llm:raw-audit
|
|
383
|
+
npm run benchmark:llm:delta-analysis
|
|
372
384
|
npm run benchmark:claim-ledger
|
|
373
385
|
npm run release:check
|
|
374
386
|
npm pack --dry-run
|
|
@@ -376,19 +388,34 @@ npm pack --dry-run
|
|
|
376
388
|
|
|
377
389
|
`src/` 아래 TypeScript를 수정할 때는 커밋 전에 빌드해 `dist/`를 최신 상태로 유지하세요.
|
|
378
390
|
|
|
379
|
-
`npm run
|
|
391
|
+
`npm run test:coverage`는 Node 내장 test coverage에 보수적인 line, branch, function threshold를 적용하므로 coverage를 단순 보고서가 아니라 회귀 게이트로 사용합니다.
|
|
392
|
+
|
|
393
|
+
`npm run release:check`는 로컬 전용 관리자 게이트입니다. 테스트, Node 내장 coverage, 벤치마크 파서 smoke, real-corpus 오프라인 데모, 벤치마크 release preview, 벤치마크 claim ledger 분류, raw 보관 상태 감사, package dry-run 검사, dist 실행 가능 여부, README 벤치마크 claim 경계 문구를 확인합니다. publish하지 않고 raw 벤치마크 산출물을 삭제하지 않으며 measured Codex 벤치마크도 실행하지 않습니다.
|
|
394
|
+
|
|
395
|
+
`release:check` 통과는 런타임 보증이 아니라 재현 가능한 릴리스 준비 근거로 봐야 합니다. 현재 checkout에서 위 로컬 게이트를 통과했음을 증명하며, package dry run이 예상 publish 경계(`agents/`, `dist/`, `LICENSE`, `README.md`, `README.ko.md`, `SKILL.md`) 안에 머물고 소스 파일, 테스트, 저장소 로컬 위키/워크플로 상태, raw 벤치마크 출력, 로컬 캐시를 제외하는지도 확인합니다.
|
|
396
|
+
|
|
397
|
+
배포는 GitHub Release가 published 상태가 된 뒤 `.github/workflows/publish.yml`에서 처리합니다. 이 워크플로는 GitHub OIDC 기반 npm trusted publishing(`id-token: write`)과 `npm publish --access public`을 사용하므로 npm provenance가 자동 생성됩니다. `NODE_AUTH_TOKEN`이나 npm token secret을 쓰면 안 되며, 릴리스 핵심 GitHub 공식 Actions는 전체 commit SHA로 고정합니다. `release:check`는 이 워크플로 계약도 로컬에서 검사합니다.
|
|
398
|
+
|
|
399
|
+
trusted publishing과 npm provenance는 패키지가 이 GitHub OIDC 워크플로를 통해 게시되었음을 증명합니다. 벤치마크 정확성, 최종 사용자 저장소의 코드 근거 freshness, 보안 감사를 증명하지는 않으며, 그런 항목은 별도의 근거 트랙으로 다룹니다.
|
|
380
400
|
|
|
381
401
|
관리자 벤치마크 명령은 [benchmarks/README.md](benchmarks/README.md)에 있습니다. 이 명령은 릴리스 근거와 공개 주장 검증을 위한 것이며, 일반 사용자 설정 절차가 아닙니다.
|
|
382
402
|
|
|
383
|
-
코드 근거 런타임/스토리지 점검에는 `npm run perf:code-efficiency`를 사용합니다. 이 명령은 3k/10k/50k 픽스처를 생성하고 `benchmarks/reports/code-performance-efficiency/current.json`과 `.md`를 작성합니다. 명령 시간에는 CLI 시작과 freshness 확인이 포함되며, `query_groups` 섹션은 대표 file/symbol/route/import/edge 쿼리의 직접 DB 시간을 따로 보고합니다.
|
|
403
|
+
코드 근거 런타임/스토리지 점검에는 `npm run perf:code-efficiency`를 사용합니다. 이 명령은 3k/10k/50k 픽스처를 생성하고 `benchmarks/reports/code-performance-efficiency/current.json`과 `.md`를 작성합니다. 명령 시간에는 CLI 시작과 freshness 확인이 포함되며, `query_groups` 섹션은 대표 file/symbol/route/import/edge 쿼리의 직접 DB 시간을 따로 보고합니다. 보고서는 `mixed-monorepo`, `web-service`, `python-cli`, `docs-heavy` 체크인 corpus도 합성 scale fixture와 분리해 측정합니다.
|
|
384
404
|
|
|
385
|
-
|
|
405
|
+
측정형 LLM 벤치마크 실행은 1일보다 오래된 이전 raw run 디렉터리와 격리 Codex home을 자동 삭제하고, claimable 실행 실패 시에도 현재 실행의 home을 삭제한 뒤 종료합니다. raw JSONL, stderr, 보고서, manifest는 보존 기간 안의 실행에 대해서만 감사용으로 유지됩니다. 무시된 오래된 raw 출력은 격리 Codex home을 삭제하기 전에 dry-run-first 헬퍼로 여전히 먼저 감사할 수 있습니다.
|
|
386
406
|
|
|
387
407
|
```bash
|
|
408
|
+
npm run benchmark:llm:raw-audit -- --older-than-days 14
|
|
388
409
|
npm run benchmark:llm:prune-raw -- --older-than-days 14
|
|
389
410
|
npm run benchmark:llm:prune-raw -- --older-than-days 14 --execute
|
|
390
411
|
```
|
|
391
412
|
|
|
413
|
+
`npm run benchmark:llm:delta-analysis`는 체크인된 measured LLM 보고서를 읽고 Codex를 실행하지 않은 채 cost-weighted regression을 순위화합니다. 대표 raw JSONL command trace와 broad-search/router-read driver 분류까지 보려면 `-- --include-traces`를 붙입니다. 작은 scale aggregation처럼 약한 셀을 새 공개 claim보다 먼저 진단하는 첫 경로입니다.
|
|
414
|
+
|
|
415
|
+
측정형 LLM 실행은 기본적으로 `--scenario-order run-major-balanced`를 사용합니다. 각 measured run index마다 선택된 모든 scenario를 실행하고 반복마다 순서를 뒤집어, 반복 실행에서 with/without 조건이 한쪽으로 몰리지 않게 합니다. 이전의 scenario별 묶음 실행 진단을 재현할 때만 `--scenario-order scenario-major`를 사용하세요.
|
|
416
|
+
|
|
417
|
+
`npm run typecheck:ts7`은 opt-in TypeScript 7 RC 호환성 probe입니다. `npx`를 사용하며, compiler API와 이 프로젝트 TypeScript extractor의 parity 기록이 생기기 전까지 `test`, `release:check`, CI 게이트 밖에 둡니다.
|
|
418
|
+
|
|
392
419
|
## 영감
|
|
393
420
|
|
|
394
421
|
이 프로젝트는 Andrej Karpathy의 [LLM Wiki](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) 패턴에서 영감을 받았습니다. 긴 대화 기록에서 프로젝트 상태를 재구성하는 대신, 지속되는 markdown 컨텍스트를 작업 가까이에 둡니다.
|
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ Project Librarian gives agents two local sources of truth:
|
|
|
52
52
|
| Surface | What It Gives The Agent |
|
|
53
53
|
| --- | --- |
|
|
54
54
|
| `wiki/startup.md` + `wiki/index.md` | A compact session-start summary and router, so only the relevant planning pages are read. |
|
|
55
|
-
| `wiki/canonical
|
|
55
|
+
| `wiki/canonical/`, `wiki/roadmaps/`, `wiki/plans/`, and `wiki/decisions/` | Current truth stays in canonical pages, broad future work stays in roadmaps, detailed execution stays in plans, and durable rationale stays in decisions. |
|
|
56
56
|
| `wiki/meta/document-taxonomy.md` | A service-lifecycle classification map that tells agents where PRD, policy, UX, data, engineering, QA, release, and operations truth should live. |
|
|
57
57
|
| `.codex/`, `.claude/`, `.cursor/`, and `.gemini/` hooks | Automatic startup context for Codex, Claude Code, Cursor, and Gemini CLI without loading the full wiki. |
|
|
58
58
|
| `GEMINI.md` and `.cursor/rules/` | Gemini CLI and Cursor instruction files that route agents to the same compact wiki-first contract. |
|
|
@@ -75,17 +75,19 @@ npm run benchmark:release:preview
|
|
|
75
75
|
npm run benchmark:release -- --allow-codex-run
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
+
Measured release runs stream `[benchmark:progress]` lines to stderr for the scenario count, expected Codex exec total, current exec ordinal, phase, prompt id, exit status, elapsed time, and raw JSONL path. stdout stays reserved for the final JSON result.
|
|
79
|
+
|
|
78
80
|
### Wiki track (planning-doc routing)
|
|
79
81
|
|
|
80
82
|
Cost-weighted tokens, Project Librarian vs control:
|
|
81
83
|
|
|
82
84
|
| Scale | decision_lookup | aggregation | multi_session (2nd session) |
|
|
83
85
|
| --- | --- | --- | --- |
|
|
84
|
-
| Small |
|
|
85
|
-
| Medium |
|
|
86
|
-
| Large | 71.
|
|
86
|
+
| Small | 14.4% less | 81.0% more | 22.0% less |
|
|
87
|
+
| Medium | 52.0% less | 19.0% less | 54.1% less |
|
|
88
|
+
| Large | 71.1% less | 29.0% less | 71.8% less |
|
|
87
89
|
|
|
88
|
-
Latest synthetic wiki-track release candidate: 2026-06-
|
|
90
|
+
Latest synthetic wiki-track release candidate: 2026-06-19, `gpt-5.5`, 42 scenarios, 3 measured runs plus 1 warmup each. The overall claim gate **passed**: 42/42 scenarios passed correctness, all 42 scenarios were claimable, and every corpus gate met the 3-run minimum. The release claim is still bounded to the synthetic wiki-routing track and the listed task families; it is not a claim about code-graph behavior, real repositories, every agent surface, or every question shape. Published boundaries remain visible: small `aggregation` still costs 81.0% more with the wiki, small `release_policy` costs 9.4% more in the full report, and `aggregation` stays slower at every scale even when token cost drops.
|
|
89
91
|
|
|
90
92
|
### Code-graph track (code evidence index, real repositories)
|
|
91
93
|
|
|
@@ -143,6 +145,8 @@ npx project-librarian install-skill --scope project --agents all
|
|
|
143
145
|
|
|
144
146
|
`--agents` also accepts comma-separated values such as `codex,claude,cursor,gemini`. `all` targets every supported agent. `--scope` accepts `user` or `project`.
|
|
145
147
|
|
|
148
|
+
The project setup/update runner also accepts `--agents`. Fresh setup defaults to all supported agent surfaces only when no project-scoped Project Librarian skill install is present. If the repository already has project-scoped skills such as `.codex/skills/project-librarian/` and `.claude/skills/project-librarian/`, the first setup uses that installed agent set by default. Existing non-migration updates preserve the agent surfaces already present in the repository, so a repo that has only Codex and Claude files will not gain Cursor or Gemini files on a plain update. Use `project-librarian update --agents cursor` or `project-librarian update --agents all` when you intentionally want to add newly supported surfaces; unlisted surfaces are not deleted.
|
|
149
|
+
|
|
146
150
|
## Runner Paths
|
|
147
151
|
|
|
148
152
|
These paths are mainly for agents and automation. After installation, agents should run the installed local copy with `node`, not `npx`. This avoids network access and unpinned package execution in restricted agent environments.
|
|
@@ -168,6 +172,7 @@ Wiki setup and maintenance:
|
|
|
168
172
|
| --- | --- | --- |
|
|
169
173
|
| Create or update the wiki | "Use Project Librarian to set up or update this repository's planning wiki." | `[init]` |
|
|
170
174
|
| Update existing setup without migration | "Update this repository's Project Librarian setup without migrating the wiki." | `update` |
|
|
175
|
+
| Add a specific agent surface to an existing setup | "Add the Cursor Project Librarian surface without migrating the wiki." | `update --agents cursor` |
|
|
171
176
|
| Migrate existing docs/wiki content | "Use Project Librarian to migrate the existing docs/wiki content." | `--migrate` |
|
|
172
177
|
| Validate generated setup | "Run Project Librarian validation." | `--lint` |
|
|
173
178
|
| Check links and document quality | "Run Project Librarian diagnostics." | `--doctor` |
|
|
@@ -188,6 +193,7 @@ Code evidence:
|
|
|
188
193
|
| Require incremental update | "Update the Project Librarian code evidence index incrementally." | `--code-index --incremental` |
|
|
189
194
|
| Force a full rebuild | "Fully rebuild the Project Librarian code evidence index." | `--code-index --code-index-full` |
|
|
190
195
|
| Use optional Tree-sitter backend | "Build Project Librarian code evidence with the Tree-sitter parser." | `--code-index --code-parser tree-sitter` |
|
|
196
|
+
| Inspect cache compatibility | "Inspect Project Librarian code evidence cache health." | `--code-index-health` |
|
|
191
197
|
| Show cache status | "Show Project Librarian code evidence status." | `--code-status` |
|
|
192
198
|
| List indexed files | "List files in the Project Librarian code evidence index." | `--code-files` |
|
|
193
199
|
| Print architecture and ownership report | "Show the Project Librarian code report." | `--code-report` |
|
|
@@ -201,6 +207,8 @@ Only one code evidence mode can run at a time. `--incremental`, `--code-index-fu
|
|
|
201
207
|
|
|
202
208
|
## What Gets Installed
|
|
203
209
|
|
|
210
|
+
Fresh setup installs the supported agent surfaces below unless you pass `--agents` or the repository already has project-scoped Project Librarian skills for a narrower agent set. Existing non-migration updates preserve the detected surface set by default and update only those selected surfaces plus the common wiki/git-hook files.
|
|
211
|
+
|
|
204
212
|
Project instruction files:
|
|
205
213
|
|
|
206
214
|
- `AGENTS.md`
|
|
@@ -228,6 +236,8 @@ Git hook files:
|
|
|
228
236
|
Wiki directories:
|
|
229
237
|
|
|
230
238
|
- `wiki/canonical/`
|
|
239
|
+
- `wiki/roadmaps/`
|
|
240
|
+
- `wiki/plans/`
|
|
231
241
|
- `wiki/decisions/`
|
|
232
242
|
- `wiki/inbox/`
|
|
233
243
|
- `wiki/meta/`
|
|
@@ -368,6 +378,9 @@ npm install
|
|
|
368
378
|
npm run typecheck
|
|
369
379
|
npm run build
|
|
370
380
|
npm test
|
|
381
|
+
npm run test:coverage
|
|
382
|
+
npm run benchmark:llm:raw-audit
|
|
383
|
+
npm run benchmark:llm:delta-analysis
|
|
371
384
|
npm run benchmark:claim-ledger
|
|
372
385
|
npm run release:check
|
|
373
386
|
npm pack --dry-run
|
|
@@ -375,19 +388,34 @@ npm pack --dry-run
|
|
|
375
388
|
|
|
376
389
|
When editing TypeScript under `src/`, rebuild before committing so `dist/` stays current.
|
|
377
390
|
|
|
378
|
-
`npm run
|
|
391
|
+
`npm run test:coverage` uses Node's native test coverage with conservative line, branch, and function thresholds so coverage is a regression gate, not only a report.
|
|
392
|
+
|
|
393
|
+
`npm run release:check` is a local-only maintainer gate: it runs tests, native Node coverage, benchmark parser smoke, the real-corpus offline demo, benchmark release preview, benchmark claim-ledger classification, raw hygiene audit, package dry-run inspection, dist executable checks, and README benchmark-claim boundary checks. It never publishes, never deletes raw benchmark artifacts, and never launches a measured Codex benchmark.
|
|
394
|
+
|
|
395
|
+
Treat a green `release:check` as a reproducible release-readiness bundle, not a runtime guarantee: it proves those local gates on the current checkout, including that the package dry run stays inside the expected publish boundary (`agents/`, `dist/`, `LICENSE`, `README.md`, `README.ko.md`, and `SKILL.md`) and excludes source files, tests, repo-local wiki/workflow state, raw benchmark output, and local caches.
|
|
396
|
+
|
|
397
|
+
Publishing is handled by `.github/workflows/publish.yml` after a GitHub Release is published. The workflow uses npm trusted publishing through GitHub OIDC (`id-token: write`) and `npm publish --access public`, which generates npm provenance automatically; it must not use `NODE_AUTH_TOKEN` or npm token secrets, and release-critical first-party GitHub Actions are pinned to full commit SHAs. `release:check` verifies this workflow contract locally.
|
|
398
|
+
|
|
399
|
+
Trusted publishing and npm provenance prove the package was published through that GitHub OIDC workflow. They do not prove benchmark correctness, code-evidence freshness in an end-user repository, or a security audit; those remain separate evidence tracks.
|
|
379
400
|
|
|
380
401
|
Maintainer benchmark commands live in [benchmarks/README.md](benchmarks/README.md). They are for release evidence and public claim validation, not normal end-user setup.
|
|
381
402
|
|
|
382
|
-
For code-evidence runtime/storage checks, `npm run perf:code-efficiency` generates 3k/10k/50k fixtures and writes `benchmarks/reports/code-performance-efficiency/current.json` plus `.md`. Command timings include CLI startup and freshness checks; the `query_groups` section reports direct DB timings for representative file/symbol/route/import/edge queries. The report also
|
|
403
|
+
For code-evidence runtime/storage checks, `npm run perf:code-efficiency` generates 3k/10k/50k fixtures and writes `benchmarks/reports/code-performance-efficiency/current.json` plus `.md`. Command timings include CLI startup and freshness checks; the `query_groups` section reports direct DB timings for representative file/symbol/route/import/edge queries. The report also measures checked-in `mixed-monorepo`, `web-service`, `python-cli`, and `docs-heavy` corpora separately from synthetic scale fixtures.
|
|
383
404
|
|
|
384
|
-
|
|
405
|
+
Measured LLM benchmark runs automatically prune stale prior raw run directories and isolated Codex homes older than 1 day, then prune the current run's homes even on claimable-run failure; raw JSONL, stderr, reports, and manifests remain for runs inside the retention window. Old ignored raw output can still be audited with the dry-run-first helper before deleting retained isolated Codex homes:
|
|
385
406
|
|
|
386
407
|
```bash
|
|
408
|
+
npm run benchmark:llm:raw-audit -- --older-than-days 14
|
|
387
409
|
npm run benchmark:llm:prune-raw -- --older-than-days 14
|
|
388
410
|
npm run benchmark:llm:prune-raw -- --older-than-days 14 --execute
|
|
389
411
|
```
|
|
390
412
|
|
|
413
|
+
`npm run benchmark:llm:delta-analysis` reads the checked-in measured LLM report and ranks cost-weighted regressions without launching Codex. Add `-- --include-traces` to include representative raw JSONL command traces and classify broad-search/router-read drivers. It is the first diagnostic stop for weak cells such as small-scale aggregation before adding new benchmark claims.
|
|
414
|
+
|
|
415
|
+
Measured LLM runs default to `--scenario-order run-major-balanced`: each measured run index executes all selected scenarios, reversing the order on alternating repetitions so with/without pairs are not grouped by condition across repeated runs. Use `--scenario-order scenario-major` only when reproducing older scenario-grouped diagnostics.
|
|
416
|
+
|
|
417
|
+
`npm run typecheck:ts7` is an opt-in TypeScript 7 RC compatibility probe. It uses `npx` and is intentionally outside `test`, `release:check`, and CI gates until the compiler API and this project's TypeScript extractor have a measured parity record.
|
|
418
|
+
|
|
391
419
|
## Inspiration
|
|
392
420
|
|
|
393
421
|
This project is inspired by Andrej Karpathy's [LLM Wiki](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) pattern: keep persistent markdown context close to the work instead of reconstructing project state from long chat history.
|
package/SKILL.md
CHANGED
|
@@ -200,6 +200,7 @@ Execution contract:
|
|
|
200
200
|
3. Separate evidence mapping from canonical truth:
|
|
201
201
|
- Code structure, entrypoints, module relationships, execution flows, read-on-demand routes, and evidence paths belong under `wiki/meta/` with descriptive project-specific filenames chosen by the LLM.
|
|
202
202
|
- Code-backed current project behavior, features, policies, constraints, terminology, domain rules, and operational facts belong under `wiki/canonical/`.
|
|
203
|
+
- Broad future work belongs under `wiki/roadmaps/`; detailed execution plans belong under `wiki/plans/`. After completion, update canonical truth and remove completed roadmap/plan content after rationale and evidence are preserved.
|
|
203
204
|
- Important design rationale or tradeoffs inferred from code may belong under `wiki/decisions/` when they meet the decision policy.
|
|
204
205
|
- Unclear, conflicting, or low-confidence interpretations belong in `wiki/inbox/` or a focused canonical questions page created for the topic, not directly in canonical truth.
|
|
205
206
|
4. Do not use fixed canonical filenames. Choose or create files from topic boundaries, expected read frequency, and token budget.
|
|
@@ -228,6 +229,8 @@ It installs:
|
|
|
228
229
|
- `wiki/startup.md` compact session-start context.
|
|
229
230
|
- `wiki/index.md` router with read/update/token-budget hints.
|
|
230
231
|
- `wiki/canonical/` directory for project-current-truth documents, created only when real content exists.
|
|
232
|
+
- `wiki/roadmaps/` for broad future scope and priority queues, created only when real content exists.
|
|
233
|
+
- `wiki/plans/` for detailed future execution plans, created only when real content exists.
|
|
231
234
|
- Optional `wiki/canonical/glossary.md` project terminology contract when `--glossary-init` is used.
|
|
232
235
|
- `wiki/decisions/` project-decision directory and lightweight decision ledgers.
|
|
233
236
|
- `wiki/meta/` wiki operating rules, project decision policy, and wiki-operations Decision Pack.
|
|
@@ -247,7 +250,7 @@ Project canonical wiki content should not default to Korean or English. Choose t
|
|
|
247
250
|
|
|
248
251
|
## Boundary Rule
|
|
249
252
|
|
|
250
|
-
`wiki/canonical
|
|
253
|
+
`wiki/canonical/`, `wiki/roadmaps/`, `wiki/plans/`, and `wiki/decisions/` are for project planning only. Do not store wiki operating decisions, hook/bootstrap/lint/migration details, LLM collaboration preferences, assistant reminders, or non-project workflow memory there.
|
|
251
254
|
|
|
252
255
|
Use:
|
|
253
256
|
|
|
@@ -255,6 +258,8 @@ Use:
|
|
|
255
258
|
- Root `AGENTS.md`, hooks, or skills for durable project-wide LLM instructions and collaboration memory.
|
|
256
259
|
- `wiki/AGENTS.md` for wiki-internal editing rules that should apply only under `wiki/`.
|
|
257
260
|
- `wiki/canonical/` only for current project truth.
|
|
261
|
+
- `wiki/roadmaps/` only for broad future scope, priority queues, and milestone sequences.
|
|
262
|
+
- `wiki/plans/` only for detailed future execution plans.
|
|
258
263
|
- `wiki/decisions/` only for project decision history.
|
|
259
264
|
|
|
260
265
|
Every wiki markdown file should include a compact metadata header with `status`, `updated`, `scope`, `read_budget`, `decision_ref`, and `review_trigger`.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.agentSurfaceRequiredFiles = exports.allAgentSurfaces = void 0;
|
|
4
|
+
exports.parseAgentSurfaceValues = parseAgentSurfaceValues;
|
|
5
|
+
exports.hasProjectLibrarianInstall = hasProjectLibrarianInstall;
|
|
6
|
+
exports.activeAgentSurfaces = activeAgentSurfaces;
|
|
7
|
+
exports.resolveBootstrapAgentSurfaces = resolveBootstrapAgentSurfaces;
|
|
8
|
+
exports.includesAgentSurface = includesAgentSurface;
|
|
9
|
+
exports.allAgentSurfaces = ["codex", "claude", "cursor", "gemini"];
|
|
10
|
+
exports.agentSurfaceRequiredFiles = {
|
|
11
|
+
codex: [".codex/hooks/wiki-session-start.js", ".codex/hooks.json"],
|
|
12
|
+
claude: ["CLAUDE.md", ".claude/hooks/wiki-session-start.js", ".claude/settings.json"],
|
|
13
|
+
cursor: [".cursor/rules/project-librarian.mdc", ".cursor/hooks/wiki-session-start.js", ".cursor/hooks.json"],
|
|
14
|
+
gemini: ["GEMINI.md", ".gemini/hooks/wiki-session-start.js", ".gemini/settings.json"],
|
|
15
|
+
};
|
|
16
|
+
const agentSurfaceProjectSkillFiles = {
|
|
17
|
+
codex: [".codex/skills/project-librarian/SKILL.md"],
|
|
18
|
+
claude: [".claude/skills/project-librarian/SKILL.md"],
|
|
19
|
+
cursor: [".cursor/skills/project-librarian/SKILL.md"],
|
|
20
|
+
gemini: [".gemini/skills/project-librarian/SKILL.md"],
|
|
21
|
+
};
|
|
22
|
+
const projectLibrarianCommonInstallFiles = [
|
|
23
|
+
"wiki/startup.md",
|
|
24
|
+
"wiki/index.md",
|
|
25
|
+
"wiki/AGENTS.md",
|
|
26
|
+
];
|
|
27
|
+
function parseAgentSurfaceValues(values) {
|
|
28
|
+
const surfaces = new Set();
|
|
29
|
+
const invalid = [];
|
|
30
|
+
for (const value of values) {
|
|
31
|
+
if (value === "all") {
|
|
32
|
+
for (const surface of exports.allAgentSurfaces)
|
|
33
|
+
surfaces.add(surface);
|
|
34
|
+
}
|
|
35
|
+
else if (exports.allAgentSurfaces.includes(value)) {
|
|
36
|
+
surfaces.add(value);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
invalid.push(value);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return { surfaces: Array.from(surfaces), invalid };
|
|
43
|
+
}
|
|
44
|
+
function hasProjectLibrarianInstall(fileExists, readFile) {
|
|
45
|
+
if (projectLibrarianCommonInstallFiles.some((file) => fileExists(file)))
|
|
46
|
+
return true;
|
|
47
|
+
if (exports.allAgentSurfaces.some((surface) => agentSurfaceProjectSkillFiles[surface].some((file) => fileExists(file))))
|
|
48
|
+
return true;
|
|
49
|
+
if (fileExists("AGENTS.md") && readFile) {
|
|
50
|
+
return readFile("AGENTS.md").includes("PROJECT-WIKI-FIRST:START");
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
function activeAgentSurfaces(fileExists) {
|
|
55
|
+
return exports.allAgentSurfaces.filter((surface) => (exports.agentSurfaceRequiredFiles[surface].some((file) => fileExists(file))
|
|
56
|
+
|| agentSurfaceProjectSkillFiles[surface].some((file) => fileExists(file))));
|
|
57
|
+
}
|
|
58
|
+
function resolveBootstrapAgentSurfaces(explicitSurfaces, fileExists, readFile) {
|
|
59
|
+
if (explicitSurfaces.length > 0)
|
|
60
|
+
return Array.from(explicitSurfaces);
|
|
61
|
+
if (hasProjectLibrarianInstall(fileExists, readFile))
|
|
62
|
+
return activeAgentSurfaces(fileExists);
|
|
63
|
+
return Array.from(exports.allAgentSurfaces);
|
|
64
|
+
}
|
|
65
|
+
function includesAgentSurface(surfaces, surface) {
|
|
66
|
+
return surfaces.includes(surface);
|
|
67
|
+
}
|
package/dist/args.js
CHANGED
|
@@ -1,80 +1,74 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.issueDraftTitle = exports.issueBodyFile = exports.captureCategory = exports.captureContent = exports.captureTitle = exports.codeIndexScopes = exports.codeParser = exports.codeIndexOutput = void 0;
|
|
3
|
+
exports.codeQuerySql = exports.codeImpactTarget = exports.codeContextPackTarget = exports.wikiVisualizeOutput = exports.wikiVisualizeMode = exports.wikiImpactTarget = exports.wikiImpactMode = exports.queryTerm = exports.codeSearchSymbolMode = exports.codeQueryMode = exports.codeImpactMode = exports.codeParserMode = exports.codeContextPackMode = exports.codeFilesMode = exports.codeStatusMode = exports.codeReportMode = exports.codeIndexHealthMode = exports.codeIndexFullMode = exports.codeIndexIncrementalMode = exports.codeIndexMode = exports.acknowledgeSmallRepoMode = exports.noGitConfigMode = exports.reviewMigrationMode = exports.pruneCheckMode = exports.captureInboxMode = exports.refreshIndexMode = exports.issueDraftMode = exports.issueCreateMode = exports.glossaryMode = exports.fixMode = exports.doctorMode = exports.qualityCheckMode = exports.linkCheckMode = exports.migrationQualityCheckMode = exports.migrationLintMode = exports.migrationDoctorMode = exports.lintMode = exports.migrateMode = exports.invalidAgentTargets = exports.missingValueOptions = exports.unexpectedValueOptions = exports.unknownOptions = exports.args = exports.commandArgs = exports.command = exports.unknownCommand = exports.helpMode = exports.agentTargets = exports.parsedArgs = exports.rawArgs = void 0;
|
|
4
|
+
exports.issueDraftTitle = exports.issueBodyFile = exports.captureCategory = exports.captureContent = exports.captureTitle = exports.codeIndexScopes = exports.codeParser = exports.codeIndexOutput = exports.codeSearchSymbol = exports.codeReportSection = void 0;
|
|
5
5
|
exports.parseArgs = parseArgs;
|
|
6
6
|
exports.argValue = argValue;
|
|
7
7
|
exports.argValues = argValues;
|
|
8
|
+
const agent_surfaces_1 = require("./agent-surfaces");
|
|
8
9
|
exports.rawArgs = process.argv.slice(2);
|
|
9
10
|
const knownCommands = new Set(["init", "update", "install-skill", "mcp"]);
|
|
10
|
-
const
|
|
11
|
-
"--acknowledge-small-repo",
|
|
12
|
-
"--adopt-existing",
|
|
13
|
-
"--
|
|
14
|
-
"--
|
|
15
|
-
"--
|
|
16
|
-
"--code-evidence-
|
|
17
|
-
"--code-files",
|
|
18
|
-
"--code-
|
|
19
|
-
"--code-index",
|
|
20
|
-
"--code-index-full",
|
|
21
|
-
"--code-index-health",
|
|
22
|
-
"--code-index-incremental",
|
|
23
|
-
"--code-
|
|
24
|
-
"--code-evidence-
|
|
25
|
-
"--code-
|
|
26
|
-
"--code-
|
|
27
|
-
"--code-evidence-report",
|
|
28
|
-
"--
|
|
29
|
-
"--
|
|
30
|
-
"--
|
|
31
|
-
"--
|
|
32
|
-
"--
|
|
33
|
-
"--
|
|
34
|
-
"--
|
|
35
|
-
"--
|
|
36
|
-
"--
|
|
37
|
-
"--
|
|
38
|
-
"--
|
|
39
|
-
"--
|
|
40
|
-
"--
|
|
41
|
-
"--
|
|
42
|
-
"--
|
|
43
|
-
"--
|
|
44
|
-
"--
|
|
45
|
-
"--
|
|
46
|
-
"--
|
|
47
|
-
"--
|
|
48
|
-
"--
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"--
|
|
52
|
-
"--
|
|
53
|
-
"--
|
|
54
|
-
"--
|
|
55
|
-
"--
|
|
56
|
-
"--
|
|
57
|
-
"--
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
"--issue-title",
|
|
72
|
-
"--query",
|
|
73
|
-
"--scope",
|
|
74
|
-
"--title",
|
|
75
|
-
"--wiki-impact",
|
|
76
|
-
"--wiki-visualize-out",
|
|
77
|
-
]);
|
|
11
|
+
const flagDefinitions = [
|
|
12
|
+
{ name: "--acknowledge-small-repo", value: "none" },
|
|
13
|
+
{ name: "--adopt-existing", value: "none" },
|
|
14
|
+
{ name: "--agents", value: "value" },
|
|
15
|
+
{ name: "--capture-inbox", value: "none" },
|
|
16
|
+
{ name: "--category", value: "value" },
|
|
17
|
+
{ name: "--code-context-pack", value: "value", aliases: ["--code-evidence-context-pack"] },
|
|
18
|
+
{ name: "--code-files", value: "none", aliases: ["--code-evidence-files"] },
|
|
19
|
+
{ name: "--code-impact", value: "value", aliases: ["--code-evidence-impact"] },
|
|
20
|
+
{ name: "--code-index", value: "none", aliases: ["--code-evidence-index"] },
|
|
21
|
+
{ name: "--code-index-full", value: "none", aliases: ["--code-evidence-index-full"] },
|
|
22
|
+
{ name: "--code-index-health", value: "none" },
|
|
23
|
+
{ name: "--code-index-incremental", value: "none", aliases: ["--incremental", "--code-incremental", "--code-evidence-index-incremental"] },
|
|
24
|
+
{ name: "--code-index-out", value: "value", aliases: ["--code-evidence-out"] },
|
|
25
|
+
{ name: "--code-parser", value: "value", aliases: ["--code-evidence-parser"] },
|
|
26
|
+
{ name: "--code-query", value: "value", aliases: ["--code-evidence-query"] },
|
|
27
|
+
{ name: "--code-report", value: "none", aliases: ["--code-evidence-report"] },
|
|
28
|
+
{ name: "--code-report-section", value: "value", aliases: ["--code-evidence-report-section"] },
|
|
29
|
+
{ name: "--code-scope", value: "value", aliases: ["--code-evidence-scope"] },
|
|
30
|
+
{ name: "--code-search-symbol", value: "value", aliases: ["--code-evidence-symbol"] },
|
|
31
|
+
{ name: "--code-status", value: "none", aliases: ["--code-evidence-status"] },
|
|
32
|
+
{ name: "--content", value: "value" },
|
|
33
|
+
{ name: "--doctor", value: "none" },
|
|
34
|
+
{ name: "--dry-run", value: "none" },
|
|
35
|
+
{ name: "--fix", value: "none" },
|
|
36
|
+
{ name: "--glossary-init", value: "none" },
|
|
37
|
+
{ name: "--issue-body-file", value: "value" },
|
|
38
|
+
{ name: "--issue-create", value: "none" },
|
|
39
|
+
{ name: "--issue-draft", value: "none" },
|
|
40
|
+
{ name: "--issue-title", value: "value" },
|
|
41
|
+
{ name: "--link-check", value: "none" },
|
|
42
|
+
{ name: "--lint", value: "none" },
|
|
43
|
+
{ name: "--migrate", value: "none" },
|
|
44
|
+
{ name: "--migration-doctor", value: "none" },
|
|
45
|
+
{ name: "--migration-lint", value: "none" },
|
|
46
|
+
{ name: "--migration-quality-check", value: "none" },
|
|
47
|
+
{ name: "--no-git-config", value: "none" },
|
|
48
|
+
{ name: "--prune-check", value: "none" },
|
|
49
|
+
{ name: "--quality-check", value: "none" },
|
|
50
|
+
{ name: "--query", value: "value" },
|
|
51
|
+
{ name: "--refresh-index", value: "none" },
|
|
52
|
+
{ name: "--review-migration", value: "none", aliases: ["--semantic-migrate"] },
|
|
53
|
+
{ name: "--scope", value: "value" },
|
|
54
|
+
{ name: "--title", value: "value" },
|
|
55
|
+
{ name: "--wiki-graph-html", value: "none" },
|
|
56
|
+
{ name: "--wiki-impact", value: "value" },
|
|
57
|
+
{ name: "--wiki-visualize", value: "none" },
|
|
58
|
+
{ name: "--wiki-visualize-out", value: "value" },
|
|
59
|
+
];
|
|
60
|
+
function definitionNames(definition) {
|
|
61
|
+
return [definition.name, ...(definition.aliases ?? [])];
|
|
62
|
+
}
|
|
63
|
+
function flagNamesByPolicy(value) {
|
|
64
|
+
return flagDefinitions.filter((definition) => definition.value === value).flatMap(definitionNames);
|
|
65
|
+
}
|
|
66
|
+
function namesForFlag(name) {
|
|
67
|
+
const definition = flagDefinitions.find((candidate) => definitionNames(candidate).includes(name));
|
|
68
|
+
return definition ? definitionNames(definition) : [name];
|
|
69
|
+
}
|
|
70
|
+
const flagsWithoutValues = new Set(flagNamesByPolicy("none"));
|
|
71
|
+
const flagsWithValues = new Set(flagNamesByPolicy("value"));
|
|
78
72
|
const knownFlags = new Set([...flagsWithoutValues, ...flagsWithValues, "--help", "-h"]);
|
|
79
73
|
function flagName(arg) {
|
|
80
74
|
return arg.startsWith("--") ? arg.split("=", 1)[0] ?? arg : arg;
|
|
@@ -135,37 +129,42 @@ function parseArgs(argv) {
|
|
|
135
129
|
const hasFlag = (name) => hasFlagIn(commandArgs, name);
|
|
136
130
|
const argValue = (name) => argValueFrom(commandArgs, name);
|
|
137
131
|
const argValues = (name) => argValuesFrom(commandArgs, name);
|
|
138
|
-
const
|
|
139
|
-
const
|
|
140
|
-
const
|
|
141
|
-
const
|
|
132
|
+
const hasAnyFlag = (name) => namesForFlag(name).some(hasFlag);
|
|
133
|
+
const argValueFromAny = (name) => namesForFlag(name).map(argValue).find(Boolean) ?? "";
|
|
134
|
+
const argValuesFromAny = (name) => namesForFlag(name).flatMap(argValues);
|
|
135
|
+
const codeImpactTarget = argValueFromAny("--code-impact");
|
|
136
|
+
const codeContextPackTarget = argValueFromAny("--code-context-pack");
|
|
137
|
+
const codeQuerySql = argValueFromAny("--code-query");
|
|
138
|
+
const codeSearchSymbol = argValueFromAny("--code-search-symbol");
|
|
139
|
+
const parsedAgentTargets = (0, agent_surfaces_1.parseAgentSurfaceValues)(argValues("--agents"));
|
|
142
140
|
return {
|
|
143
141
|
acknowledgeSmallRepoMode: args.has("--acknowledge-small-repo"),
|
|
142
|
+
agentTargets: parsedAgentTargets.surfaces,
|
|
144
143
|
args,
|
|
145
144
|
captureCategory: argValue("--category") || "project-candidate",
|
|
146
145
|
captureContent: argValue("--content"),
|
|
147
146
|
captureInboxMode: args.has("--capture-inbox"),
|
|
148
147
|
captureTitle: argValue("--title"),
|
|
149
|
-
codeContextPackMode:
|
|
148
|
+
codeContextPackMode: hasAnyFlag("--code-context-pack"),
|
|
150
149
|
codeContextPackTarget,
|
|
151
|
-
codeFilesMode:
|
|
152
|
-
codeImpactMode:
|
|
150
|
+
codeFilesMode: hasAnyFlag("--code-files"),
|
|
151
|
+
codeImpactMode: hasAnyFlag("--code-impact"),
|
|
153
152
|
codeImpactTarget,
|
|
154
|
-
codeIndexFullMode:
|
|
153
|
+
codeIndexFullMode: hasAnyFlag("--code-index-full"),
|
|
155
154
|
codeIndexHealthMode: args.has("--code-index-health"),
|
|
156
|
-
codeIndexIncrementalMode:
|
|
157
|
-
codeIndexMode:
|
|
158
|
-
codeIndexOutput:
|
|
159
|
-
codeIndexScopes:
|
|
160
|
-
codeParser:
|
|
161
|
-
codeParserMode:
|
|
162
|
-
codeQueryMode:
|
|
155
|
+
codeIndexIncrementalMode: hasAnyFlag("--code-index-incremental"),
|
|
156
|
+
codeIndexMode: hasAnyFlag("--code-index"),
|
|
157
|
+
codeIndexOutput: argValueFromAny("--code-index-out") || ".project-wiki/code-evidence.sqlite",
|
|
158
|
+
codeIndexScopes: argValuesFromAny("--code-scope"),
|
|
159
|
+
codeParser: argValueFromAny("--code-parser") || "default",
|
|
160
|
+
codeParserMode: hasAnyFlag("--code-parser"),
|
|
161
|
+
codeQueryMode: hasAnyFlag("--code-query"),
|
|
163
162
|
codeQuerySql,
|
|
164
|
-
codeReportMode:
|
|
165
|
-
codeReportSection:
|
|
163
|
+
codeReportMode: hasAnyFlag("--code-report"),
|
|
164
|
+
codeReportSection: argValueFromAny("--code-report-section"),
|
|
166
165
|
codeSearchSymbol,
|
|
167
|
-
codeSearchSymbolMode:
|
|
168
|
-
codeStatusMode:
|
|
166
|
+
codeSearchSymbolMode: hasAnyFlag("--code-search-symbol"),
|
|
167
|
+
codeStatusMode: hasAnyFlag("--code-status"),
|
|
169
168
|
command,
|
|
170
169
|
commandArgs,
|
|
171
170
|
doctorMode: args.has("--doctor"),
|
|
@@ -176,6 +175,7 @@ function parseArgs(argv) {
|
|
|
176
175
|
issueCreateMode: args.has("--issue-create"),
|
|
177
176
|
issueDraftMode: args.has("--issue-draft"),
|
|
178
177
|
issueDraftTitle: argValue("--issue-title"),
|
|
178
|
+
invalidAgentTargets: parsedAgentTargets.invalid,
|
|
179
179
|
linkCheckMode: args.has("--link-check"),
|
|
180
180
|
lintMode: args.has("--lint"),
|
|
181
181
|
migrationDoctorMode: args.has("--migration-doctor"),
|
|
@@ -189,7 +189,7 @@ function parseArgs(argv) {
|
|
|
189
189
|
queryTerm: argValue("--query"),
|
|
190
190
|
rawArgs: argv,
|
|
191
191
|
refreshIndexMode: args.has("--refresh-index"),
|
|
192
|
-
reviewMigrationMode:
|
|
192
|
+
reviewMigrationMode: hasAnyFlag("--review-migration"),
|
|
193
193
|
unexpectedValueOptions: Array.from(new Set(commandArgs
|
|
194
194
|
.filter((arg) => arg.startsWith("--") && arg.includes("="))
|
|
195
195
|
.map(flagName)
|
|
@@ -206,6 +206,7 @@ function parseArgs(argv) {
|
|
|
206
206
|
};
|
|
207
207
|
}
|
|
208
208
|
exports.parsedArgs = parseArgs(exports.rawArgs);
|
|
209
|
+
exports.agentTargets = exports.parsedArgs.agentTargets;
|
|
209
210
|
exports.helpMode = exports.parsedArgs.helpMode;
|
|
210
211
|
exports.unknownCommand = exports.parsedArgs.unknownCommand;
|
|
211
212
|
exports.command = exports.parsedArgs.command;
|
|
@@ -214,6 +215,7 @@ exports.args = exports.parsedArgs.args;
|
|
|
214
215
|
exports.unknownOptions = exports.parsedArgs.unknownOptions;
|
|
215
216
|
exports.unexpectedValueOptions = exports.parsedArgs.unexpectedValueOptions;
|
|
216
217
|
exports.missingValueOptions = exports.parsedArgs.missingValueOptions;
|
|
218
|
+
exports.invalidAgentTargets = exports.parsedArgs.invalidAgentTargets;
|
|
217
219
|
exports.migrateMode = exports.parsedArgs.migrateMode;
|
|
218
220
|
exports.lintMode = exports.parsedArgs.lintMode;
|
|
219
221
|
exports.migrationDoctorMode = exports.parsedArgs.migrationDoctorMode;
|
package/dist/code-index/modes.js
CHANGED
|
@@ -60,7 +60,13 @@ function printJson(value) {
|
|
|
60
60
|
function requireCompatibleDatabase(database, runtime) {
|
|
61
61
|
const schemaVersion = (0, schema_1.readMetaValue)(database, "schema_version");
|
|
62
62
|
if (schemaVersion !== schema_1.codeIndexSchemaVersion) {
|
|
63
|
-
|
|
63
|
+
const databasePath = runtime.codeEvidenceDatabasePath();
|
|
64
|
+
runtime.fail([
|
|
65
|
+
`code evidence index schema version ${schemaVersion || "(missing)"} is incompatible with ${schema_1.codeIndexSchemaVersion}`,
|
|
66
|
+
`inspect: project-librarian --code-index-health`,
|
|
67
|
+
`rebuild: project-librarian --code-index --code-index-full`,
|
|
68
|
+
`database: ${databasePath.relativePath}`,
|
|
69
|
+
].join("\n"));
|
|
64
70
|
}
|
|
65
71
|
}
|
|
66
72
|
function runCodeIndexMode(runtime) {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
const args_1 = require("./args");
|
|
5
|
+
const agent_surfaces_1 = require("./agent-surfaces");
|
|
5
6
|
const hooks_1 = require("./hooks");
|
|
6
7
|
const install_skill_1 = require("./install-skill");
|
|
7
8
|
const modes_1 = require("./modes");
|
|
@@ -39,6 +40,7 @@ Options:
|
|
|
39
40
|
--refresh-index Update the managed auto-discovered wiki index block.
|
|
40
41
|
--capture-inbox Append a candidate note with --title, --content, and optional --category.
|
|
41
42
|
--glossary-init Create and route the optional glossary page.
|
|
43
|
+
--agents <list> With init/update, write only selected agent surfaces: codex, claude, cursor, gemini, or all. Existing project skill/setup surfaces are preserved by default.
|
|
42
44
|
--prune-check Report active pages with stale or unresolved signals.
|
|
43
45
|
--review-migration Sync unit coverage and compatible inbox statuses into migration review files.
|
|
44
46
|
--no-git-config Install hook files without changing git core.hooksPath.
|
|
@@ -107,6 +109,11 @@ if (args_1.missingValueOptions.length > 0) {
|
|
|
107
109
|
printUsage();
|
|
108
110
|
process.exit(1);
|
|
109
111
|
}
|
|
112
|
+
if (args_1.invalidAgentTargets.length > 0) {
|
|
113
|
+
console.error(`invalid --agents entr${args_1.invalidAgentTargets.length === 1 ? "y" : "ies"}: ${args_1.invalidAgentTargets.join(", ")}; expected codex, claude, cursor, gemini, or all`);
|
|
114
|
+
printUsage();
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
110
117
|
if (args_1.command === "update" && args_1.migrateMode) {
|
|
111
118
|
console.error("update cannot be combined with --migrate or --adopt-existing; use project-librarian --migrate for migration.");
|
|
112
119
|
process.exit(1);
|
|
@@ -247,6 +254,16 @@ function runInitCommand() {
|
|
|
247
254
|
runRefreshIndexOnlyMode();
|
|
248
255
|
process.exit(0);
|
|
249
256
|
}
|
|
257
|
+
const selectedAgentSurfaces = args_1.agentTargets.length > 0
|
|
258
|
+
? args_1.agentTargets
|
|
259
|
+
: args_1.migrateMode
|
|
260
|
+
? Array.from(agent_surfaces_1.allAgentSurfaces)
|
|
261
|
+
: (0, agent_surfaces_1.resolveBootstrapAgentSurfaces)(args_1.agentTargets, workspace_1.exists, workspace_1.read);
|
|
262
|
+
const shouldWriteSurface = (surface) => (0, agent_surfaces_1.includesAgentSurface)(selectedAgentSurfaces, surface);
|
|
263
|
+
const writeCodexSurface = shouldWriteSurface("codex");
|
|
264
|
+
const writeClaudeSurface = shouldWriteSurface("claude");
|
|
265
|
+
const writeCursorSurface = shouldWriteSurface("cursor");
|
|
266
|
+
const writeGeminiSurface = shouldWriteSurface("gemini");
|
|
250
267
|
const migrationState = args_1.migrateMode ? (0, migration_1.prepareMigrationMode)() : null;
|
|
251
268
|
const results = [];
|
|
252
269
|
if (migrationState)
|
|
@@ -256,11 +273,16 @@ function runInitCommand() {
|
|
|
256
273
|
(0, workspace_1.mkdirp)("wiki/inbox");
|
|
257
274
|
(0, workspace_1.mkdirp)("wiki/meta");
|
|
258
275
|
(0, workspace_1.mkdirp)("wiki/sources");
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
276
|
+
if (writeCodexSurface)
|
|
277
|
+
(0, workspace_1.mkdirp)(".codex/hooks");
|
|
278
|
+
if (writeClaudeSurface)
|
|
279
|
+
(0, workspace_1.mkdirp)(".claude/hooks");
|
|
280
|
+
if (writeCursorSurface) {
|
|
281
|
+
(0, workspace_1.mkdirp)(".cursor/hooks");
|
|
282
|
+
(0, workspace_1.mkdirp)(".cursor/rules");
|
|
283
|
+
}
|
|
284
|
+
if (writeGeminiSurface)
|
|
285
|
+
(0, workspace_1.mkdirp)(".gemini/hooks");
|
|
264
286
|
(0, workspace_1.mkdirp)(".githooks");
|
|
265
287
|
// B1 fallback: sync the CURRENT startup.md TL;DR into the managed AGENTS.md block
|
|
266
288
|
// so non-interactive `codex exec` (which does not run SessionStart hooks) still
|
|
@@ -271,23 +293,34 @@ function runInitCommand() {
|
|
|
271
293
|
const startupForSync = (0, workspace_1.exists)("wiki/startup.md") ? (0, workspace_1.read)("wiki/startup.md") : templates_1.startup;
|
|
272
294
|
const startupTldrForAgents = (0, templates_1.extractStartupTldr)(startupForSync);
|
|
273
295
|
results.push(["AGENTS.md", (0, workspace_1.upsertMarkedSection)("AGENTS.md", "<!-- PROJECT-WIKI-FIRST:START -->", "<!-- PROJECT-WIKI-FIRST:END -->", (0, templates_1.agentsSection)(startupTldrForAgents))]);
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
296
|
+
if (writeClaudeSurface)
|
|
297
|
+
results.push(["CLAUDE.md", (0, workspace_1.upsertMarkedSection)("CLAUDE.md", "<!-- PROJECT-WIKI-CLAUDE:START -->", "<!-- PROJECT-WIKI-CLAUDE:END -->", templates_1.claudeSection)]);
|
|
298
|
+
if (writeGeminiSurface)
|
|
299
|
+
results.push(["GEMINI.md", (0, workspace_1.upsertMarkedSection)("GEMINI.md", "<!-- PROJECT-WIKI-GEMINI:START -->", "<!-- PROJECT-WIKI-GEMINI:END -->", templates_1.geminiSection)]);
|
|
300
|
+
if (writeCursorSurface)
|
|
301
|
+
results.push([".cursor/rules/project-librarian.mdc", (0, workspace_1.writeManaged)(".cursor/rules/project-librarian.mdc", templates_1.cursorRule)]);
|
|
277
302
|
results.push(["wiki/AGENTS.md", (0, workspace_1.upsertMarkedSection)("wiki/AGENTS.md", "<!-- PROJECT-WIKI-INTERNAL:START -->", "<!-- PROJECT-WIKI-INTERNAL:END -->", templates_1.wikiAgentsSection)]);
|
|
278
303
|
results.push([".githooks/prepare-commit-msg", (0, workspace_1.writeManaged)(".githooks/prepare-commit-msg", hooks_1.gitPrepareCommitMsgHook)]);
|
|
279
304
|
(0, workspace_1.makeExecutable)(".githooks/prepare-commit-msg");
|
|
280
305
|
results.push([".githooks/wiki-commit-trailers.js", (0, workspace_1.writeManaged)(".githooks/wiki-commit-trailers.js", hooks_1.gitWikiCommitTrailersScript)]);
|
|
281
306
|
(0, workspace_1.makeExecutable)(".githooks/wiki-commit-trailers.js");
|
|
282
307
|
results.push(["git core.hooksPath", (0, hooks_1.upsertGitHooksPath)()]);
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
308
|
+
if (writeCodexSurface) {
|
|
309
|
+
results.push([".codex/hooks.json", (0, hooks_1.upsertHookConfig)()]);
|
|
310
|
+
results.push([".codex/hooks/wiki-session-start.js", (0, workspace_1.writeManaged)(".codex/hooks/wiki-session-start.js", hooks_1.hookScript)]);
|
|
311
|
+
}
|
|
312
|
+
if (writeClaudeSurface) {
|
|
313
|
+
results.push([".claude/settings.json", (0, hooks_1.upsertClaudeHookConfig)()]);
|
|
314
|
+
results.push([".claude/hooks/wiki-session-start.js", (0, workspace_1.writeManaged)(".claude/hooks/wiki-session-start.js", hooks_1.hookScript)]);
|
|
315
|
+
}
|
|
316
|
+
if (writeCursorSurface) {
|
|
317
|
+
results.push([".cursor/hooks.json", (0, hooks_1.upsertCursorHookConfig)()]);
|
|
318
|
+
results.push([".cursor/hooks/wiki-session-start.js", (0, workspace_1.writeManaged)(".cursor/hooks/wiki-session-start.js", hooks_1.cursorHookScript)]);
|
|
319
|
+
}
|
|
320
|
+
if (writeGeminiSurface) {
|
|
321
|
+
results.push([".gemini/settings.json", (0, hooks_1.upsertGeminiHookConfig)()]);
|
|
322
|
+
results.push([".gemini/hooks/wiki-session-start.js", (0, workspace_1.writeManaged)(".gemini/hooks/wiki-session-start.js", hooks_1.hookScript)]);
|
|
323
|
+
}
|
|
291
324
|
// Bootstrap-managed MCP registration (preservation-first, idempotent). Claude
|
|
292
325
|
// Code reads `.mcp.json`, Cursor reads `.cursor/mcp.json`, and Gemini reads
|
|
293
326
|
// `mcpServers` inside `.gemini/settings.json`. Codex only supports user-level MCP
|
|
@@ -296,16 +329,24 @@ function runInitCommand() {
|
|
|
296
329
|
// Registration is scale-gated (2026-06-12 decision): below the measured
|
|
297
330
|
// file-count threshold with no existing .project-wiki index, the rows report the
|
|
298
331
|
// skip reason instead of writing config; an existing index registers regardless.
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
332
|
+
if (writeClaudeSurface || writeCursorSurface || writeGeminiSurface) {
|
|
333
|
+
const mcpGate = (0, hooks_1.mcpRegistrationGate)();
|
|
334
|
+
if (mcpGate.register) {
|
|
335
|
+
if (writeClaudeSurface)
|
|
336
|
+
results.push([".mcp.json", (0, hooks_1.upsertClaudeMcpConfig)()]);
|
|
337
|
+
if (writeCursorSurface)
|
|
338
|
+
results.push([".cursor/mcp.json", (0, hooks_1.upsertCursorMcpConfig)()]);
|
|
339
|
+
if (writeGeminiSurface)
|
|
340
|
+
results.push([".gemini/settings.json mcpServers", (0, hooks_1.upsertGeminiMcpConfig)()]);
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
if (writeClaudeSurface)
|
|
344
|
+
results.push([".mcp.json", mcpGate.reason]);
|
|
345
|
+
if (writeCursorSurface)
|
|
346
|
+
results.push([".cursor/mcp.json", mcpGate.reason]);
|
|
347
|
+
if (writeGeminiSurface)
|
|
348
|
+
results.push([".gemini/settings.json mcpServers", mcpGate.reason]);
|
|
349
|
+
}
|
|
309
350
|
}
|
|
310
351
|
// Routers accumulate user-maintained project state after bootstrap, so they are
|
|
311
352
|
// starter files: templates are written only when the file is absent, never rebuilt.
|
package/dist/install-skill.js
CHANGED
|
@@ -37,9 +37,9 @@ exports.runInstallSkillMode = runInstallSkillMode;
|
|
|
37
37
|
const fs = __importStar(require("node:fs"));
|
|
38
38
|
const os = __importStar(require("node:os"));
|
|
39
39
|
const path = __importStar(require("node:path"));
|
|
40
|
+
const agent_surfaces_1 = require("./agent-surfaces");
|
|
40
41
|
const args_1 = require("./args");
|
|
41
42
|
const skillName = "project-librarian";
|
|
42
|
-
const allAgentTargets = ["codex", "claude", "cursor", "gemini"];
|
|
43
43
|
const packageFiles = [
|
|
44
44
|
"SKILL.md",
|
|
45
45
|
"dist",
|
|
@@ -65,10 +65,10 @@ function installAgents() {
|
|
|
65
65
|
const agents = new Set();
|
|
66
66
|
for (const part of parts) {
|
|
67
67
|
if (part === "all") {
|
|
68
|
-
for (const agent of
|
|
68
|
+
for (const agent of agent_surfaces_1.allAgentSurfaces)
|
|
69
69
|
agents.add(agent);
|
|
70
70
|
}
|
|
71
|
-
else if (
|
|
71
|
+
else if (agent_surfaces_1.allAgentSurfaces.includes(part)) {
|
|
72
72
|
agents.add(part);
|
|
73
73
|
}
|
|
74
74
|
else {
|
package/dist/modes.js
CHANGED
|
@@ -57,6 +57,7 @@ const fs = __importStar(require("node:fs"));
|
|
|
57
57
|
const childProcess = __importStar(require("node:child_process"));
|
|
58
58
|
const os = __importStar(require("node:os"));
|
|
59
59
|
const path = __importStar(require("node:path"));
|
|
60
|
+
const agent_surfaces_1 = require("./agent-surfaces");
|
|
60
61
|
const args_1 = require("./args");
|
|
61
62
|
const workspace_1 = require("./workspace");
|
|
62
63
|
const templates_1 = require("./templates");
|
|
@@ -66,6 +67,7 @@ const wiki_graph_1 = require("./wiki-graph");
|
|
|
66
67
|
const wiki_corpus_1 = require("./wiki-corpus");
|
|
67
68
|
const wiki_diagnostics_1 = require("./wiki-diagnostics");
|
|
68
69
|
const scopedAutoIndexThreshold = 40;
|
|
70
|
+
const scopedAutoIndexCharLimit = 7600;
|
|
69
71
|
const scopedAutoIndexMarker = "<!-- PROJECT-WIKI-SCOPED-AUTO-INDEX -->";
|
|
70
72
|
function isScopedAutoIndex(file) {
|
|
71
73
|
return /^wiki\/indexes\/auto-[a-z0-9-]+\.md$/.test(file);
|
|
@@ -89,16 +91,18 @@ function routeAreaForWikiFile(file) {
|
|
|
89
91
|
return slugPart(directory);
|
|
90
92
|
return "misc";
|
|
91
93
|
}
|
|
92
|
-
function scopedIndexPath(area) {
|
|
93
|
-
|
|
94
|
+
function scopedIndexPath(area, partIndex = 0, partCount = 1) {
|
|
95
|
+
const slug = slugPart(area);
|
|
96
|
+
return partCount <= 1 ? `wiki/indexes/auto-${slug}.md` : `wiki/indexes/auto-${slug}-${partIndex + 1}.md`;
|
|
94
97
|
}
|
|
95
|
-
function scopedIndexContent(area, files) {
|
|
98
|
+
function scopedIndexContent(area, files, partIndex = 0, partCount = 1) {
|
|
99
|
+
const title = partCount <= 1 ? area : `${area} (${partIndex + 1}/${partCount})`;
|
|
96
100
|
const rows = files.map((file) => {
|
|
97
101
|
const meta = (0, wiki_files_1.metadataSummary)(file, (0, workspace_1.read)(file));
|
|
98
102
|
return `| ${(0, wiki_files_1.wikiLinkForFile)(file)} | ${meta.scope} | ${meta.status} | ${meta.budget} |`;
|
|
99
103
|
}).join("\n");
|
|
100
104
|
return `${(0, templates_1.metadata)("wiki-router", "medium", "wiki/meta/wiki-ops-v1-decisions.md", "auto-discovered scoped routes change")}${scopedAutoIndexMarker}
|
|
101
|
-
# Auto Index: ${
|
|
105
|
+
# Auto Index: ${title}
|
|
102
106
|
|
|
103
107
|
## TL;DR
|
|
104
108
|
|
|
@@ -110,6 +114,23 @@ function scopedIndexContent(area, files) {
|
|
|
110
114
|
${rows}
|
|
111
115
|
`;
|
|
112
116
|
}
|
|
117
|
+
function splitScopedIndexFiles(area, files) {
|
|
118
|
+
const parts = [];
|
|
119
|
+
let current = [];
|
|
120
|
+
for (const file of files) {
|
|
121
|
+
const candidate = [...current, file];
|
|
122
|
+
if (current.length > 0 && scopedIndexContent(area, candidate).length > scopedAutoIndexCharLimit) {
|
|
123
|
+
parts.push(current);
|
|
124
|
+
current = [file];
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
current = candidate;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (current.length > 0)
|
|
131
|
+
parts.push(current);
|
|
132
|
+
return parts;
|
|
133
|
+
}
|
|
113
134
|
function removeStaleScopedAutoIndexes(keepPaths) {
|
|
114
135
|
if (!(0, workspace_1.exists)("wiki/indexes"))
|
|
115
136
|
return;
|
|
@@ -126,16 +147,23 @@ function syncScopedAutoIndexes(files) {
|
|
|
126
147
|
const area = routeAreaForWikiFile(file);
|
|
127
148
|
groups.set(area, [...(groups.get(area) ?? []), file]);
|
|
128
149
|
}
|
|
129
|
-
const summaries = Array.from(groups.entries()).
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
150
|
+
const summaries = Array.from(groups.entries()).flatMap(([area, areaFiles]) => {
|
|
151
|
+
const sortedFiles = areaFiles.sort();
|
|
152
|
+
const parts = splitScopedIndexFiles(area, sortedFiles);
|
|
153
|
+
return parts.map((files, partIndex) => ({
|
|
154
|
+
area: parts.length <= 1 ? area : `${area} ${partIndex + 1}`,
|
|
155
|
+
baseArea: area,
|
|
156
|
+
count: files.length,
|
|
157
|
+
file: scopedIndexPath(area, partIndex, parts.length),
|
|
158
|
+
files,
|
|
159
|
+
partIndex,
|
|
160
|
+
partCount: parts.length,
|
|
161
|
+
}));
|
|
162
|
+
}).sort((left, right) => right.count - left.count || left.area.localeCompare(right.area));
|
|
135
163
|
const keepPaths = new Set(summaries.map((summary) => summary.file));
|
|
136
164
|
removeStaleScopedAutoIndexes(keepPaths);
|
|
137
165
|
for (const summary of summaries)
|
|
138
|
-
(0, workspace_1.write)(summary.file, scopedIndexContent(summary.
|
|
166
|
+
(0, workspace_1.write)(summary.file, scopedIndexContent(summary.baseArea, summary.files, summary.partIndex, summary.partCount));
|
|
139
167
|
return summaries.map(({ area, count, file }) => ({ area, count, file }));
|
|
140
168
|
}
|
|
141
169
|
function buildRefreshIndexBlock() {
|
|
@@ -149,8 +177,6 @@ function buildRefreshIndexBlock() {
|
|
|
149
177
|
return `<!-- PROJECT-WIKI-AUTO-INDEX:START -->
|
|
150
178
|
## Auto-Discovered Pages
|
|
151
179
|
|
|
152
|
-
This block is managed by \`--refresh-index\`. Large route sets are split into scoped generated routers to keep \`wiki/index.md\` within startup-hook budget.
|
|
153
|
-
|
|
154
180
|
| Scoped Router | Area | Pages |
|
|
155
181
|
| --- | --- | ---: |
|
|
156
182
|
${rows}
|
|
@@ -192,6 +218,10 @@ function scoreQueryBlock(block, terms) {
|
|
|
192
218
|
function hasMigrationQueryIntent(terms) {
|
|
193
219
|
return terms.some((term) => /^(migrat|legacy|coverage|unit|ledger|review)/.test(term));
|
|
194
220
|
}
|
|
221
|
+
function hasDeepReferenceQueryIntent(terms) {
|
|
222
|
+
return hasMigrationQueryIntent(terms)
|
|
223
|
+
|| terms.some((term) => /^(archive|audit|decision|detail|history|ledger|raw|record|source|trace|verification)/.test(term));
|
|
224
|
+
}
|
|
195
225
|
function isMigrationSurface(file, meta) {
|
|
196
226
|
return file.startsWith("wiki/migration/")
|
|
197
227
|
|| /(?:^|-)migration(?:-|$)/.test(file)
|
|
@@ -204,6 +234,9 @@ function querySurfaceScore(file, meta, rawScore, terms) {
|
|
|
204
234
|
return Math.max(1, Math.floor(rawScore * 0.25) - 20);
|
|
205
235
|
}
|
|
206
236
|
let score = rawScore;
|
|
237
|
+
if (meta.budget === "on-demand" && !hasDeepReferenceQueryIntent(terms)) {
|
|
238
|
+
score = Math.max(1, Math.min(Math.floor(score * 0.5), 24));
|
|
239
|
+
}
|
|
207
240
|
if (file.startsWith("wiki/canonical/") && meta.status === "active")
|
|
208
241
|
score += 12;
|
|
209
242
|
else if (meta.status === "active")
|
|
@@ -889,15 +922,9 @@ const commonLintRequiredFiles = [
|
|
|
889
922
|
".githooks/prepare-commit-msg",
|
|
890
923
|
".githooks/wiki-commit-trailers.js",
|
|
891
924
|
];
|
|
892
|
-
const agentLintRequiredFiles = {
|
|
893
|
-
codex: [".codex/hooks/wiki-session-start.js", ".codex/hooks.json"],
|
|
894
|
-
claude: ["CLAUDE.md", ".claude/hooks/wiki-session-start.js", ".claude/settings.json"],
|
|
895
|
-
cursor: [".cursor/rules/project-librarian.mdc", ".cursor/hooks/wiki-session-start.js", ".cursor/hooks.json"],
|
|
896
|
-
gemini: ["GEMINI.md", ".gemini/hooks/wiki-session-start.js", ".gemini/settings.json"],
|
|
897
|
-
};
|
|
898
925
|
function activeLintAgentSurfaces() {
|
|
899
926
|
const active = new Set();
|
|
900
|
-
for (const [agent, files] of Object.entries(
|
|
927
|
+
for (const [agent, files] of Object.entries(agent_surfaces_1.agentSurfaceRequiredFiles)) {
|
|
901
928
|
if (files.some((file) => (0, workspace_1.exists)(file)))
|
|
902
929
|
active.add(agent);
|
|
903
930
|
}
|
|
@@ -909,7 +936,7 @@ function runLintMode(corpus) {
|
|
|
909
936
|
const activeAgents = activeLintAgentSurfaces();
|
|
910
937
|
const requiredFiles = [
|
|
911
938
|
...commonLintRequiredFiles,
|
|
912
|
-
...Array.from(activeAgents).flatMap((agent) =>
|
|
939
|
+
...Array.from(activeAgents).flatMap((agent) => agent_surfaces_1.agentSurfaceRequiredFiles[agent]),
|
|
913
940
|
];
|
|
914
941
|
for (const file of requiredFiles) {
|
|
915
942
|
if (!(0, workspace_1.exists)(file))
|
package/dist/templates.js
CHANGED
|
@@ -70,7 +70,7 @@ At the start of every session:
|
|
|
70
70
|
|
|
71
71
|
1. Review \`wiki/startup.md\` for compact current context.
|
|
72
72
|
2. Review \`wiki/index.md\` as the router for which files to read next.
|
|
73
|
-
3. Read detailed \`wiki/canonical/\`, \`wiki/decisions/\`, \`wiki/meta/\`, and \`wiki/sources/\` files on demand only when the current question needs them.
|
|
73
|
+
3. Read detailed \`wiki/canonical/\`, \`wiki/roadmaps/\`, \`wiki/plans/\`, \`wiki/decisions/\`, \`wiki/meta/\`, and \`wiki/sources/\` files on demand only when the current question needs them.
|
|
74
74
|
|
|
75
75
|
### ${exports.startupTldrSyncLabel}
|
|
76
76
|
|
|
@@ -133,12 +133,14 @@ Language policy:
|
|
|
133
133
|
Reading rules:
|
|
134
134
|
|
|
135
135
|
- Treat \`startup.md\` as compact session context and \`index.md\` as the router.
|
|
136
|
-
- Read detailed \`canonical/\`, \`decisions/\`, \`meta/\`, and \`sources/\` files on demand only when the current question needs them.
|
|
136
|
+
- Read detailed \`canonical/\`, \`roadmaps/\`, \`plans/\`, \`decisions/\`, \`meta/\`, and \`sources/\` files on demand only when the current question needs them.
|
|
137
137
|
- Prefer each file's TL;DR and metadata before reading the full body.
|
|
138
138
|
|
|
139
139
|
Storage boundaries:
|
|
140
140
|
|
|
141
141
|
- \`canonical/\` contains current project-planning truth only.
|
|
142
|
+
- \`roadmaps/\` contains broad future scope, priority queues, and milestone sequences only; it is not canonical truth.
|
|
143
|
+
- \`plans/\` contains detailed execution plans for roadmap items only; it is not canonical truth.
|
|
142
144
|
- \`decisions/\` contains project decision history only.
|
|
143
145
|
- \`meta/\` contains wiki operating rules, decision policy, bootstrap, lint, hook, and migration decisions.
|
|
144
146
|
- \`sources/\` contains external reference summaries and source notes.
|
|
@@ -150,6 +152,8 @@ Classification rules:
|
|
|
150
152
|
|
|
151
153
|
- Before adding or consolidating project content, classify it with \`meta/document-taxonomy.md\`.
|
|
152
154
|
- Write current agreement to the narrowest durable canonical document that fits the taxonomy; do not append unrelated material to \`canonical/project-brief.md\`.
|
|
155
|
+
- Put broad future work in \`roadmaps/\` and detailed execution plans in \`plans/\`, not \`canonical/\`.
|
|
156
|
+
- When roadmap or plan work is completed, update canonical truth first, preserve rationale/evidence where needed, then remove the completed roadmap/plan content.
|
|
153
157
|
- If one input crosses several lifecycle areas, split it into separate canonical updates and link the related pages.
|
|
154
158
|
- If the input explains why a direction changed, update the relevant decision log or Decision Pack in addition to canonical truth.
|
|
155
159
|
- If an external artifact is the better source of truth (for example Figma, OpenAPI, ERD, issue tracker, or code), keep a concise canonical summary and link the external source as the authoritative location.
|
|
@@ -187,10 +191,11 @@ exports.startup = `${(0, exports.metadata)("startup-router", "short", "wiki/meta
|
|
|
187
191
|
## TL;DR
|
|
188
192
|
|
|
189
193
|
- This project is in an initial planning state unless the canonical wiki says otherwise.
|
|
190
|
-
- Project truth lives in \`wiki/canonical/\`,
|
|
194
|
+
- Project truth lives in \`wiki/canonical/\`, future work in \`wiki/roadmaps/\` and \`wiki/plans/\`, project decisions in \`wiki/decisions/\`, and sources in \`wiki/sources/\`.
|
|
191
195
|
- Wiki operating rules and wiki operating decisions live in \`wiki/meta/\`.
|
|
192
196
|
- At session start, read only this file and \`wiki/index.md\` first; read detailed files on demand.
|
|
193
197
|
- Project canonical content language is not fixed by this bootstrap. The LLM should choose the language that best matches the user and project context.
|
|
198
|
+
- Completed roadmaps/plans are removed after truth/rationale/evidence capture.
|
|
194
199
|
- Update the wiki in the same turn when project-planning content changes.
|
|
195
200
|
- Classify new project-planning content with \`wiki/meta/document-taxonomy.md\` before writing or consolidating it.
|
|
196
201
|
|
|
@@ -239,7 +244,9 @@ This file is a router, not a file to expand into every answer. Read only the fil
|
|
|
239
244
|
|
|
240
245
|
## Boundary Rule
|
|
241
246
|
|
|
242
|
-
- \`wiki/canonical
|
|
247
|
+
- \`wiki/canonical/\`: current accepted project truth only.
|
|
248
|
+
- \`wiki/roadmaps/\`: broad future scope only; \`wiki/plans/\`: detailed execution only.
|
|
249
|
+
- \`wiki/decisions/\`: project decision history only.
|
|
243
250
|
- Wiki operating rules and wiki operating decisions live in \`wiki/meta/\`.
|
|
244
251
|
- Non-project LLM memory, collaboration reminders, and workflow instructions belong in \`AGENTS.md\`, \`wiki/AGENTS.md\`, hooks, or skills, not in project canonical/decision docs.
|
|
245
252
|
|
|
@@ -254,7 +261,7 @@ This file is a router, not a file to expand into every answer. Read only the fil
|
|
|
254
261
|
|
|
255
262
|
No empty canonical starter pages are created by default. Create focused pages under \`wiki/canonical/\` only when durable project truth exists, then route them here or with \`--refresh-index\`.
|
|
256
263
|
|
|
257
|
-
##
|
|
264
|
+
## Decisions
|
|
258
265
|
|
|
259
266
|
- [[decisions/recent]]
|
|
260
267
|
- Read: recent important project decisions.
|
|
@@ -335,6 +342,7 @@ exports.wikiOperatingModel = `${(0, exports.metadata)("wiki-meta", "medium", "wi
|
|
|
335
342
|
- This wiki keeps project-planning knowledge as durable markdown.
|
|
336
343
|
- Codex, Claude Code, Cursor, and Gemini CLI session-start hooks inject only \`wiki/startup.md\` and \`wiki/index.md\`.
|
|
337
344
|
- Detailed canonical and decision files are read on demand.
|
|
345
|
+
- Roadmaps and plans are separate from canonical truth; canonical pages keep the current accepted state.
|
|
338
346
|
- Root \`AGENTS.md\` keeps the project-wide wiki-first contract; \`wiki/AGENTS.md\` keeps detailed wiki editing rules.
|
|
339
347
|
- Operating documents generated by bootstrap are English by default.
|
|
340
348
|
- Project canonical content language is selected from user/project context, not hardcoded by this bootstrap.
|
|
@@ -352,24 +360,28 @@ Karpathy's LLM Wiki pattern favors a continuously maintained markdown wiki over
|
|
|
352
360
|
## Layers
|
|
353
361
|
|
|
354
362
|
1. Sources: external docs, links, user notes, and evidence summaries.
|
|
355
|
-
2. Canonical project truth: current
|
|
356
|
-
3.
|
|
357
|
-
4.
|
|
358
|
-
5.
|
|
359
|
-
6.
|
|
363
|
+
2. Canonical project truth: current accepted specs, contracts, policies, and operating state under \`wiki/canonical/\`.
|
|
364
|
+
3. Roadmaps: broad future scope, priority queues, and milestone sequences under \`wiki/roadmaps/\` or an external tracker.
|
|
365
|
+
4. Plans: detailed execution plans for roadmap items under \`wiki/plans/\` or an external tracker.
|
|
366
|
+
5. Project decisions: rationale, rejected alternatives, and revisit triggers under \`wiki/decisions/\`.
|
|
367
|
+
6. Startup context: compact session summary in \`wiki/startup.md\`.
|
|
368
|
+
7. Router: read/update/token-budget guidance in \`wiki/index.md\`.
|
|
369
|
+
8. Wiki meta: operating rules, decision policy, bootstrap, migration, lint, and language policy under \`wiki/meta/\`.
|
|
360
370
|
|
|
361
371
|
## Content Classification Procedure
|
|
362
372
|
|
|
363
373
|
Before writing or reorganizing project-planning content:
|
|
364
374
|
|
|
365
375
|
1. Identify the content's lifecycle area with [[meta/document-taxonomy]].
|
|
366
|
-
2. Decide whether the content is current truth, decision rationale, source evidence, an unresolved candidate, or a wiki operating rule.
|
|
367
|
-
3. Write current truth to the narrowest relevant \`canonical/\` page, decision rationale to \`decisions/\`, source notes to \`sources/\`, candidates to \`inbox/\`, and wiki operating rules to \`meta/\`.
|
|
376
|
+
2. Decide whether the content is current truth, roadmap, detailed plan, decision rationale, source evidence, an unresolved candidate, or a wiki operating rule.
|
|
377
|
+
3. Write current truth to the narrowest relevant \`canonical/\` page, broad future scope to \`roadmaps/\`, detailed execution plans to \`plans/\`, decision rationale to \`decisions/\`, source notes to \`sources/\`, candidates to \`inbox/\`, and wiki operating rules to \`meta/\`.
|
|
368
378
|
4. Split multi-area inputs instead of making one catch-all document.
|
|
369
379
|
5. Link upstream and downstream pages when the content derives from another artifact or produces another artifact.
|
|
370
380
|
|
|
371
381
|
Do not treat \`canonical/project-brief.md\` as a default dumping ground. It should summarize direction, audience, scope, and success criteria; detailed product, policy, UX, data, engineering, QA, release, or operations truth should move into focused pages when it grows.
|
|
372
382
|
|
|
383
|
+
Do not treat \`wiki/canonical/\` as a plan archive. If a whole document is mainly about future scope, implementation sequence, migration wave, branch status, or work result log, keep it outside canonical truth and link it from the relevant current-spec page only when readers need that context. When the work is done, update canonical truth and then remove completed roadmap/plan content after rationale and evidence are preserved in their proper places.
|
|
384
|
+
|
|
373
385
|
## Language Policy
|
|
374
386
|
|
|
375
387
|
- Bootstrap-generated operating documents are English.
|
|
@@ -448,14 +460,15 @@ exports.documentTaxonomy = `${(0, exports.metadata)("wiki-meta", "medium", "wiki
|
|
|
448
460
|
## TL;DR
|
|
449
461
|
|
|
450
462
|
- Classify new project-planning content before writing it into the wiki.
|
|
451
|
-
-
|
|
452
|
-
- Keep \`canonical/project-brief.md\` compact; move
|
|
463
|
+
- Classify into \`canonical/\`, \`roadmaps/\`, \`plans/\`, \`decisions/\`, \`sources/\`, \`inbox/\`, or \`meta/\`.
|
|
464
|
+
- Keep \`canonical/project-brief.md\` compact; move details into focused pages.
|
|
465
|
+
- Keep future work outside canonical; canonical pages may include brief change pointers.
|
|
453
466
|
- Preserve derivation links: evidence -> strategy -> requirements -> design/data/engineering -> QA -> release/operations -> feedback.
|
|
454
467
|
|
|
455
468
|
## Top-Level Flow
|
|
456
469
|
|
|
457
470
|
\`\`\`text
|
|
458
|
-
0.
|
|
471
|
+
0. Governance
|
|
459
472
|
-> 1. Research and evidence
|
|
460
473
|
-> 2. Strategy and business model
|
|
461
474
|
-> 3. Product scope and requirements
|
|
@@ -469,27 +482,37 @@ exports.documentTaxonomy = `${(0, exports.metadata)("wiki-meta", "medium", "wiki
|
|
|
469
482
|
-> 11. Release and operations
|
|
470
483
|
-> 12. Business operations
|
|
471
484
|
-> 13. Improvement, migration, and end-of-life
|
|
472
|
-
->
|
|
485
|
+
-> roadmap -> plan -> canonical update
|
|
473
486
|
\`\`\`
|
|
474
487
|
|
|
475
488
|
## Storage Decision
|
|
476
489
|
|
|
477
490
|
| Content Type | Store In | Notes |
|
|
478
491
|
| --- | --- | --- |
|
|
479
|
-
| Current
|
|
492
|
+
| Current project truth | \`wiki/canonical/\` | Accepted spec, contract, policy, or operating state. |
|
|
493
|
+
| Roadmap, milestone sequence, or priority queue | \`wiki/roadmaps/\` or tracker | Broad future scope, not canonical truth. |
|
|
494
|
+
| Detailed plan, proposal, migration, or task sequence | \`wiki/plans/\` or external tracker | Execution detail, not canonical truth. |
|
|
480
495
|
| Why a choice was made | \`wiki/decisions/\` | Use log, Decision Pack, or ADR by impact. |
|
|
481
496
|
| Source material or summarized evidence | \`wiki/sources/\` | Keep links, checked dates, and applicability. |
|
|
482
497
|
| Unreviewed or ambiguous material | \`wiki/inbox/\` | Do not treat as canonical truth. |
|
|
483
498
|
| Wiki operation, taxonomy, hooks, migration, lint, language rules | \`wiki/meta/\` | Keep outside project canonical truth. |
|
|
484
499
|
| Better external source of truth | External artifact plus a concise wiki route | Examples: Figma, OpenAPI, ERD, Jira, code. |
|
|
485
500
|
|
|
501
|
+
## Canonical vs Roadmap vs Plan Boundary
|
|
502
|
+
|
|
503
|
+
\`wiki/canonical/\` is for the state readers should treat as true now. A page mainly about future change, implementation sequence, migration wave, branch status, or work log is not canonical truth.
|
|
504
|
+
|
|
505
|
+
Use \`wiki/roadmaps/\` for broad ordered future work. Use \`wiki/plans/\` for one roadmap item's details. Put only short planned-change notes in canonical pages.
|
|
506
|
+
|
|
507
|
+
After acceptance or release, rewrite canonical truth. Move rationale to \`wiki/decisions/\` and evidence to \`wiki/sources/\`, release notes, or reports. Then delete completed roadmap/plan content unless external retention is required.
|
|
508
|
+
|
|
486
509
|
## Lifecycle Areas
|
|
487
510
|
|
|
488
511
|
| Area | Put Here | Usually Derives From | Usually Produces |
|
|
489
512
|
| --- | --- | --- | --- |
|
|
490
513
|
| 0. Governance | source-of-truth map, owners, RACI, approval flow, change rules, glossary, state dictionary, assumptions, risk register | team/process constraints | routing, ownership, conflict resolution |
|
|
491
514
|
| 1. Research | market, competitor, user interviews, VOC, analytics, legal/regulatory, technical feasibility, cost, vendor, accessibility research | raw discovery | strategy, risks, sources |
|
|
492
|
-
| 2. Strategy | service overview, vision, problem, target users, personas, jobs-to-be-done, value offer, positioning, business model, KPI/OKR, success/stop criteria, roadmap, MVP, non-goals | research | PRD, roadmap, scope |
|
|
515
|
+
| 2. Strategy | service overview, vision, problem, target users, personas, jobs-to-be-done, value offer, positioning, business model, KPI/OKR, success/stop criteria, committed roadmap summary, MVP, non-goals | research | PRD, roadmap, scope |
|
|
493
516
|
| 3. Product | PRD, user stories, use cases, priorities, backlog rules, acceptance criteria, feature spec, exceptions, state definitions, notification rules, search/filter/sort rules, admin requirements | strategy and policy | UX, API, data, QA |
|
|
494
517
|
| 4. Policy | operations policy, auth/account, permissions, pricing, payment/refund, coupon/credit, content moderation, notifications, retention/deletion, abuse response, support, EOL | business model, law, risks | feature constraints, API rules, CS/ops |
|
|
495
518
|
| 5. UX and Content | IA, sitemap, user flow, task flow, screen list, wireframes, screen specs, content model, UX writing, empty/error states, help/FAQ, localization, SEO, accessibility criteria | product and policy | design, frontend, QA |
|
|
@@ -498,7 +521,7 @@ exports.documentTaxonomy = `${(0, exports.metadata)("wiki-meta", "medium", "wiki
|
|
|
498
521
|
| 8. Engineering | architecture, technology decisions, API/OpenAPI, integrations, webhooks/idempotency, state machines, jobs/cron, error codes, env vars, secrets, local dev, conventions, branch/release strategy, CI/CD, feature flags, dependencies, migrations, performance, scalability, FinOps | product, UX, data, policy | implementation and verification |
|
|
499
522
|
| 9. Security/Legal | security requirements, threat model, privacy rules, privacy impact, terms, privacy policy, audit logs, permission history, internal access controls, key rotation, vulnerability response, licenses, vendor and DPA documents | data, architecture, law | controls, tests, release gates |
|
|
500
523
|
| 10. QA | test strategy, QA scenarios, test cases, regression checklist, UAT, browser/device matrix, accessibility tests, performance tests, security tests, data quality tests, design QA, quality gates | requirements, design, engineering | release approval |
|
|
501
|
-
| 11. Release/Ops | release
|
|
524
|
+
| 11. Release/Ops | current release policy, deployment procedure, rollback, release notes, operator manual, runbooks, monitoring, observability, SLO/SLA, on-call/escalation, incident response, backup/restore, DR/BCP, recurring checks | QA and infrastructure | stable operation |
|
|
502
525
|
| 12. Business Ops | CS macros, support policy, training, sales/adoption guide, CRM rules, onboarding playbook, churn/offboarding, admin operations, communication templates, revenue recognition, tax/invoice, partner operations | policy, release, sales motion | customer-facing operation |
|
|
503
526
|
| 13. Improvement/EOL | VOC summary, retrospectives, experiments, experiment results, cohort/retention analysis, feature deprecation, migration/data transfer, service end-of-life | operations and analytics | next PRD, policy, roadmap |
|
|
504
527
|
|
|
@@ -507,11 +530,14 @@ exports.documentTaxonomy = `${(0, exports.metadata)("wiki-meta", "medium", "wiki
|
|
|
507
530
|
When a new note arrives:
|
|
508
531
|
|
|
509
532
|
1. Identify the lifecycle area and storage location.
|
|
510
|
-
2.
|
|
511
|
-
3.
|
|
512
|
-
4.
|
|
513
|
-
5.
|
|
514
|
-
6.
|
|
533
|
+
2. Decide whether content is current truth, roadmap, plan, decision rationale, evidence, candidate, or wiki operating rule.
|
|
534
|
+
3. Update an existing focused canonical page only when the content changes current truth.
|
|
535
|
+
4. Create a new focused page only when the topic is durable, likely to be read independently, or too large for its current page.
|
|
536
|
+
5. If the document is future-oriented, store broad scope in \`roadmaps/\` and detailed execution in \`plans/\`.
|
|
537
|
+
6. Add an \`index.md\` route when the page becomes durable.
|
|
538
|
+
7. Add upstream/downstream links in prose or tables when one artifact derives from another.
|
|
539
|
+
8. Record decision rationale separately when the change explains why the project chose one option over another.
|
|
540
|
+
9. When roadmap/plan work is done, update canonical truth, preserve rationale/evidence, then remove completed roadmap/plan content.
|
|
515
541
|
|
|
516
542
|
## Page Shape
|
|
517
543
|
|
|
@@ -670,7 +696,7 @@ No project decisions yet.
|
|
|
670
696
|
## TL;DR
|
|
671
697
|
|
|
672
698
|
- This Decision Pack records accepted wiki operating choices for project-librarian.
|
|
673
|
-
- It covers wiki structure, document taxonomy, startup hook scope, metadata, language policy, git hook behavior, migration review, and
|
|
699
|
+
- It covers wiki structure, document taxonomy, startup hook scope, metadata, language policy, git hook behavior, migration review, inbox handling, and canonical/roadmap/plan boundaries.
|
|
674
700
|
- Project product decisions belong in \`wiki/decisions/\`, while these operating decisions stay in \`wiki/meta/\`.
|
|
675
701
|
|
|
676
702
|
Status: accepted
|
|
@@ -685,6 +711,8 @@ Canonical: [[meta/operating-model]], [[meta/decision-policy]], [[meta/document-t
|
|
|
685
711
|
| ${workspace_1.today} | Inject only \`startup.md\` and \`index.md\` through Codex, Claude Code, Cursor, and Gemini CLI startup hooks; route detailed files Read On Demand. | Full canonical and decision bodies waste startup tokens. | Always read detailed canonical and decision files first. | Important context is repeatedly missed at startup. | [[startup]], [[index]] |
|
|
686
712
|
| ${workspace_1.today} | Use metadata headers on wiki knowledge pages. | Agents and humans can quickly judge status, scope, budget, and review triggers. | Body-only conventions. | Header maintenance costs more than it saves. | [[meta/operating-model]] |
|
|
687
713
|
| ${workspace_1.today} | Keep wiki operating docs in \`wiki/meta/\`. | Project truth stays focused on product/project content. | Store operating docs in \`canonical/\` or \`decisions/\`. | Meta docs become hard to discover. | [[meta/operating-model]] |
|
|
714
|
+
| ${workspace_1.today} | Split future work into \`roadmaps/\` and \`plans/\`, outside canonical truth. | Roadmaps list broad future scope and sequencing; plans describe detailed execution for one roadmap item; canonical pages should show only the current accepted spec, contract, policy, or operating state. | Store roadmap, improvement, migration, and implementation plans directly in \`canonical/\` as if they were current truth, or mix roadmaps and detailed plans in one directory. | Teams need a different planning directory convention, or plan artifacts become the authoritative source for current behavior. | [[meta/document-taxonomy]], [[meta/operating-model]] |
|
|
715
|
+
| ${workspace_1.today} | Remove completed roadmap and plan content after canonical truth, rationale, and evidence are updated. | Completed future-work documents become stale logs once their outcome is reflected in canonical pages, decisions, and evidence artifacts. | Keep completed roadmap/plan documents indefinitely inside the wiki. | Audit, legal, or release process requires retaining completed plan artifacts in a dedicated external system. | [[meta/document-taxonomy]], [[meta/operating-model]] |
|
|
688
716
|
| ${workspace_1.today} | Bootstrap-generated operating documents are English by default. | Repository entry points and operating contracts are easier for public users to inspect. | Generate operating docs in a fixed non-English language. | The project intentionally targets a single-language local audience. | [[meta/operating-model]] |
|
|
689
717
|
| ${workspace_1.today} | Project canonical content language is chosen from user/project context. | User language and source material should drive project truth, not the bootstrap tool. | Hardcode Korean or English as the canonical content language. | A team requires a fixed language policy. | [[startup]], [[index]] |
|
|
690
718
|
| ${workspace_1.today} | Install git hook files but preserve existing \`core.hooksPath\` values and allow \`--no-git-config\`. | Public users may already have a hook chain such as Husky. | Always replace \`core.hooksPath\`. | Users prefer automatic setup and accept the side effect. | [[meta/operating-model]] |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "project-librarian",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "Create and maintain compact project context for humans and LLM coding agents.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -41,19 +41,25 @@
|
|
|
41
41
|
"benchmark:ci": "npm run benchmark:ci-smoke",
|
|
42
42
|
"benchmark:ci-smoke": "npm run benchmark:llm:parse-smoke && npm run benchmark:llm:dry-run",
|
|
43
43
|
"benchmark:llm": "npm run build && node benchmarks/codex-llm-metrics.js",
|
|
44
|
+
"benchmark:llm:delta-analysis": "node benchmarks/tools/analyze-llm-deltas.js",
|
|
44
45
|
"benchmark:llm:dry-run": "npm run build && node benchmarks/codex-llm-metrics.js --dry-run",
|
|
45
46
|
"benchmark:llm:parse-smoke": "node tests/validators/codex-llm-benchmark-smoke.js",
|
|
46
47
|
"benchmark:llm:prune-raw": "node benchmarks/tools/prune-llm-raw.js",
|
|
48
|
+
"benchmark:llm:raw-audit": "node benchmarks/tools/audit-llm-raw.js",
|
|
47
49
|
"benchmark:injection-sentinel": "node benchmarks/tools/injection-sentinel.js",
|
|
50
|
+
"benchmark:agent-surface-smoke": "node benchmarks/tools/agent-surface-smoke.js",
|
|
48
51
|
"benchmark:claim-ledger": "node benchmarks/tools/benchmark-claim-ledger.js benchmarks/llm/samples/codex-measured-report.json benchmarks/reports/llm/payload-preview.json",
|
|
49
52
|
"benchmark:real-corpus:demo": "npm run build && node benchmarks/tools/real-corpus-offline-demo.js",
|
|
50
53
|
"benchmark:release:preview": "npm run benchmark:llm -- --payload-preview benchmarks/reports/llm/payload-preview.json --sanitized-pack --full-matrix --runs 3 --warmup-runs 1 --min-runs-for-claim 3 --require-clean --require-claimable --model gpt-5.5",
|
|
54
|
+
"benchmark:release:diagnose": "npm run benchmark:llm -- --sanitized-pack --runs 1 --warmup-runs 0 --model gpt-5.5 --out benchmarks/reports/llm/diagnostic-current.json --markdown benchmarks/reports/llm/diagnostic-current.md",
|
|
51
55
|
"benchmark:release": "npm run benchmark:llm -- --sanitized-pack --full-matrix --runs 3 --warmup-runs 1 --min-runs-for-claim 3 --require-clean --require-claimable --model gpt-5.5 --out benchmarks/reports/llm/current.json --markdown benchmarks/reports/llm/current.md",
|
|
52
56
|
"build": "tsc && chmod +x dist/init-project-wiki.js",
|
|
53
57
|
"perf:code-efficiency": "node benchmarks/tools/code-performance-efficiency.js --full",
|
|
54
58
|
"release:check": "node benchmarks/tools/release-readiness.js",
|
|
55
59
|
"typecheck": "tsc --noEmit",
|
|
60
|
+
"typecheck:ts7": "npx --yes -p typescript@rc tsc --noEmit --project tsconfig.json",
|
|
56
61
|
"unit": "node --test tests/unit/*.test.js",
|
|
62
|
+
"test:coverage": "node --test --experimental-test-coverage --test-coverage-include=dist/**/*.js --test-coverage-include=benchmarks/**/*.js --test-coverage-lines=65 --test-coverage-branches=65 --test-coverage-functions=65 tests/unit/*.test.js",
|
|
57
63
|
"test": "npm run build && npm run typecheck && npm run unit && bash tests/smoke.sh",
|
|
58
64
|
"prepack": "npm run build"
|
|
59
65
|
},
|