crewly 1.8.9 → 1.8.12
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/config/constants.d.ts.map +1 -0
- package/config/index.d.ts.map +1 -0
- package/config/roles/_common/memory-instructions.md +6 -5
- package/config/roles/_common/wiki-instructions.md +49 -0
- package/config/roles/architect/prompt.md +2 -2
- package/config/roles/backend-developer/prompt.md +2 -2
- package/config/roles/designer/prompt.md +2 -2
- package/config/roles/developer/prompt.md +2 -2
- package/config/roles/frontend-developer/prompt.md +2 -2
- package/config/roles/fullstack-dev/prompt.md +2 -2
- package/config/roles/generalist/prompt.md +2 -2
- package/config/roles/ops/prompt.md +2 -2
- package/config/roles/orchestrator/prompt.md +135 -11
- package/config/roles/product-manager/prompt.md +2 -2
- package/config/roles/qa/prompt.md +2 -2
- package/config/roles/qa-engineer/prompt.md +2 -2
- package/config/roles/researcher/prompt.md +15 -6
- package/config/roles/sales/prompt.md +2 -2
- package/config/roles/support/prompt.md +2 -2
- package/config/roles/team-leader/prompt.md +17 -2
- package/config/roles/tpm/prompt.md +2 -2
- package/config/roles/ux-designer/prompt.md +2 -2
- package/config/skills/orchestrator/wiki-cleanup/SKILL.md +89 -0
- package/config/skills/orchestrator/wiki-cleanup/execute.sh +139 -0
- package/config/skills/orchestrator/wiki-lint/SKILL.md +75 -0
- package/config/skills/orchestrator/wiki-lint/execute.sh +66 -0
- package/config/skills/orchestrator/wiki-migrate/SKILL.md +103 -0
- package/config/skills/orchestrator/wiki-migrate/execute.sh +82 -0
- package/config/skills/orchestrator/wiki-process-queue/SKILL.md +9 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts +169 -0
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js +1779 -0
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts +18 -0
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js +63 -0
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.routes.js +5 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/wiki/wiki.controller.d.ts +109 -0
- package/dist/backend/backend/src/controllers/wiki/wiki.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/wiki/wiki.controller.js +419 -4
- package/dist/backend/backend/src/controllers/wiki/wiki.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/wiki/wiki.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/wiki/wiki.routes.js +11 -1
- package/dist/backend/backend/src/controllers/wiki/wiki.routes.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +78 -3
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/index.js.orc-bak-20260529 +3130 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.d.ts +513 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.js +1568 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.d.ts +86 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.js +147 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.d.ts +68 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.js +131 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.d.ts +130 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.js +263 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.d.ts +74 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.js +140 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.d.ts +29 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.js +279 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.d.ts +340 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.js +1176 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.d.ts +79 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.js +145 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.d.ts +79 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.js +218 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/index.d.ts +16 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/index.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/index.js +16 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/index.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.d.ts +135 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.js +185 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts +141 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js +310 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.d.ts +91 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.js +143 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.d.ts +103 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.js +256 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.d.ts +143 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.js +264 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.d.ts +13 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.js +91 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.js.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.d.ts +135 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.js +1937 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.js.map +1 -0
- package/dist/backend/backend/src/services/ai/prompt-builder.service.js +1 -1
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.d.ts +429 -0
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.js +852 -0
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.js.map +1 -0
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts +171 -0
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/project/task-tracking.service.js +725 -0
- package/dist/backend/backend/src/services/project/task-tracking.service.js.map +1 -0
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.d.ts.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js +50 -0
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts +19 -0
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js +45 -0
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.js +34 -1
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.d.ts +118 -0
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.js +326 -0
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-backlinks.service.d.ts +72 -0
- package/dist/backend/backend/src/services/wiki/wiki-backlinks.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-backlinks.service.js +186 -0
- package/dist/backend/backend/src/services/wiki/wiki-backlinks.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.d.ts +27 -4
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.js +133 -10
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep.service.d.ts +18 -1
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep.service.js +15 -4
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.d.ts +74 -0
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.js +154 -0
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-cleanup.service.d.ts +160 -0
- package/dist/backend/backend/src/services/wiki/wiki-cleanup.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-cleanup.service.js +399 -0
- package/dist/backend/backend/src/services/wiki/wiki-cleanup.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-lint.service.d.ts +182 -0
- package/dist/backend/backend/src/services/wiki/wiki-lint.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-lint.service.js +505 -0
- package/dist/backend/backend/src/services/wiki/wiki-lint.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-migrate.service.d.ts +232 -0
- package/dist/backend/backend/src/services/wiki/wiki-migrate.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-migrate.service.js +1416 -0
- package/dist/backend/backend/src/services/wiki/wiki-migrate.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-recent.service.d.ts +51 -0
- package/dist/backend/backend/src/services/wiki/wiki-recent.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-recent.service.js +102 -0
- package/dist/backend/backend/src/services/wiki/wiki-recent.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-reflect-trigger.service.d.ts +104 -0
- package/dist/backend/backend/src/services/wiki/wiki-reflect-trigger.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-reflect-trigger.service.js +229 -0
- package/dist/backend/backend/src/services/wiki/wiki-reflect-trigger.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-search.service.d.ts +90 -0
- package/dist/backend/backend/src/services/wiki/wiki-search.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-search.service.js +190 -0
- package/dist/backend/backend/src/services/wiki/wiki-search.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.d.ts +164 -0
- package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.js +675 -0
- package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.js.map +1 -0
- package/dist/backend/backend/src/services/workflow/cron-task.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/workflow/cron-task.service.js +65 -0
- package/dist/backend/backend/src/services/workflow/cron-task.service.js.map +1 -1
- package/dist/backend/backend/src/types/auto-assign.types.d.ts +271 -0
- package/dist/backend/backend/src/types/auto-assign.types.d.ts.map +1 -0
- package/dist/backend/backend/src/types/auto-assign.types.js +136 -0
- package/dist/backend/backend/src/types/auto-assign.types.js.map +1 -0
- package/dist/backend/backend/src/types/cron-task.types.d.ts +16 -1
- package/dist/backend/backend/src/types/cron-task.types.d.ts.map +1 -1
- package/dist/backend/backend/src/utils/esm-require.utils.d.ts +111 -0
- package/dist/backend/backend/src/utils/esm-require.utils.d.ts.map +1 -0
- package/dist/backend/backend/src/utils/esm-require.utils.js +124 -0
- package/dist/backend/backend/src/utils/esm-require.utils.js.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts +220 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts.map +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.js +37 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.js.map +1 -0
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.d.ts +56 -0
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.d.ts.map +1 -0
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.js +91 -0
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.js.map +1 -0
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.d.ts +159 -0
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.js +304 -0
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.js.map +1 -0
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.d.ts +115 -0
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.js +215 -0
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.js.map +1 -0
- package/dist/cli/backend/src/services/memory/embedding-provider.d.ts +78 -0
- package/dist/cli/backend/src/services/memory/embedding-provider.d.ts.map +1 -0
- package/dist/cli/backend/src/services/memory/embedding-provider.js +179 -0
- package/dist/cli/backend/src/services/memory/embedding-provider.js.map +1 -0
- package/dist/cli/backend/src/services/memory/vector-store.service.d.ts +331 -0
- package/dist/cli/backend/src/services/memory/vector-store.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/memory/vector-store.service.js +814 -0
- package/dist/cli/backend/src/services/memory/vector-store.service.js.map +1 -0
- package/dist/cli/backend/src/services/project/task-tracking.service.d.ts +171 -0
- package/dist/cli/backend/src/services/project/task-tracking.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/project/task-tracking.service.js +725 -0
- package/dist/cli/backend/src/services/project/task-tracking.service.js.map +1 -0
- package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts +19 -0
- package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js +45 -0
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/cli/backend/src/types/auto-assign.types.d.ts +271 -0
- package/dist/cli/backend/src/types/auto-assign.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/auto-assign.types.js +136 -0
- package/dist/cli/backend/src/types/auto-assign.types.js.map +1 -0
- package/dist/cli/cli/src/index.js +0 -0
- package/frontend/dist/assets/{index-db3f5041.css → index-068bb4f6.css} +10 -1
- package/frontend/dist/assets/index-c24ceb15.js +4960 -0
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
- package/config/skills/agent/core/query-knowledge/SKILL.md +0 -87
- package/config/skills/agent/core/query-knowledge/execute.sh +0 -30
- package/config/skills/orchestrator/query-knowledge/SKILL.md +0 -75
- package/config/skills/orchestrator/query-knowledge/execute.sh +0 -30
- package/frontend/dist/assets/index-cc115bb4.js +0 -4926
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WikiCleanupService — detect + remove low-quality pages from a wiki vault.
|
|
3
|
+
*
|
|
4
|
+
* Origin: the 2026-05-27 migration dumped every agent's `memory.json`
|
|
5
|
+
* roleKnowledge entries as their own wiki page (~3,277 pages across 6
|
|
6
|
+
* project vaults). Many are stream-of-consciousness daily memory rather
|
|
7
|
+
* than team-level patterns. Symptom: each project vault has 500+ pages
|
|
8
|
+
* under `patterns/`, most low-quality (confidence < 0.5, verbatim memory
|
|
9
|
+
* dump shape). Karpathy's wiki spec says "frequently-read distilled
|
|
10
|
+
* knowledge" — 500 stream-of-consciousness pages violates that.
|
|
11
|
+
*
|
|
12
|
+
* Detection is **rule-based + mechanical** (OSS does this). The actual
|
|
13
|
+
* keep/delete decision can be deferred to an agent via the bridge —
|
|
14
|
+
* this service exposes both `scan(rules)` (mechanical candidate list)
|
|
15
|
+
* and `apply(pages)` (executes the explicit page list provided).
|
|
16
|
+
*
|
|
17
|
+
* Design rules (mirror WikiMigrateService):
|
|
18
|
+
* - Default DRY-RUN. Caller must pass `{ apply: true }` to delete.
|
|
19
|
+
* - Idempotent + reversible. Every deleted page body + frontmatter is
|
|
20
|
+
* archived to `<vault>/.wiki-cleanup-archive.json` BEFORE the file
|
|
21
|
+
* is removed. Re-running with the same input is a no-op.
|
|
22
|
+
* - Migrate manifest is updated so the SAME source entry is not
|
|
23
|
+
* re-imported by the next `wiki-migrate --apply` (would defeat the
|
|
24
|
+
* cleanup).
|
|
25
|
+
* - LEGACY FILES (`memory.json`, `.crewly/knowledge/*`) are NEVER
|
|
26
|
+
* touched. The cleanup ONLY removes pages from the wiki vault.
|
|
27
|
+
* - Frozen folders (`memory/`, `sop/`, `sop-overrides/`, `okr/`,
|
|
28
|
+
* `decisions/manual/`) are never scanned.
|
|
29
|
+
*
|
|
30
|
+
* @module services/wiki/wiki-cleanup.service
|
|
31
|
+
*/
|
|
32
|
+
import * as fs from 'fs/promises';
|
|
33
|
+
import * as path from 'path';
|
|
34
|
+
import { existsSync } from 'fs';
|
|
35
|
+
import { LoggerService } from '../core/logger.service.js';
|
|
36
|
+
import { atomicWriteJson, safeReadJson, ensureDir } from '../../utils/file-io.utils.js';
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Constants
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
export const WIKI_CLEANUP_ARCHIVE_FILENAME = '.wiki-cleanup-archive.json';
|
|
41
|
+
export const WIKI_CLEANUP_ARCHIVE_VERSION = 1;
|
|
42
|
+
/** Folders we never scan — managed by OSS code path, not LLM-editable. */
|
|
43
|
+
const FROZEN_FOLDERS = new Set([
|
|
44
|
+
'memory',
|
|
45
|
+
'sop',
|
|
46
|
+
'sop-overrides',
|
|
47
|
+
'okr',
|
|
48
|
+
]);
|
|
49
|
+
/** Folder under the vault where llm-curated pages live. */
|
|
50
|
+
const LLM_CURATED_DIR = 'llm-curated';
|
|
51
|
+
/** Hard cap on candidates returned per scan — defensive (prevents OOM on a
|
|
52
|
+
* corrupted vault with 100k+ files). */
|
|
53
|
+
const SCAN_HARD_CAP = 5_000;
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Service
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
export class WikiCleanupService {
|
|
58
|
+
static instance = null;
|
|
59
|
+
logger;
|
|
60
|
+
constructor() {
|
|
61
|
+
this.logger = LoggerService.getInstance().createComponentLogger('WikiCleanup');
|
|
62
|
+
}
|
|
63
|
+
static getInstance() {
|
|
64
|
+
if (!this.instance)
|
|
65
|
+
this.instance = new WikiCleanupService();
|
|
66
|
+
return this.instance;
|
|
67
|
+
}
|
|
68
|
+
/** Test-only reset. */
|
|
69
|
+
static resetInstance() {
|
|
70
|
+
this.instance = null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Walk the vault's `llm-curated/` tree, parse frontmatter, return all
|
|
74
|
+
* pages matching at least one cleanup rule. Pure read — no writes.
|
|
75
|
+
*/
|
|
76
|
+
async scan(input) {
|
|
77
|
+
const validation = this.validateVault(input.vaultPath);
|
|
78
|
+
if (!validation.ok)
|
|
79
|
+
return validation;
|
|
80
|
+
const rules = {
|
|
81
|
+
minConfidence: input.rules?.minConfidence ?? 0.5,
|
|
82
|
+
dropAgentMemoryDumps: input.rules?.dropAgentMemoryDumps ?? true,
|
|
83
|
+
maxPerAgent: input.rules?.maxPerAgent ?? 0,
|
|
84
|
+
};
|
|
85
|
+
const llmCuratedRoot = path.join(input.vaultPath, LLM_CURATED_DIR);
|
|
86
|
+
const allPages = [];
|
|
87
|
+
let truncated = false;
|
|
88
|
+
if (existsSync(llmCuratedRoot)) {
|
|
89
|
+
truncated = await this.walkPages(llmCuratedRoot, input.vaultPath, allPages, SCAN_HARD_CAP);
|
|
90
|
+
}
|
|
91
|
+
const flagged = new Map();
|
|
92
|
+
const summary = { lowConfidence: 0, agentMemoryDump: 0, perAgentCapped: 0 };
|
|
93
|
+
for (const page of allPages) {
|
|
94
|
+
const fm = page.frontmatter;
|
|
95
|
+
const reasons = [];
|
|
96
|
+
const conf = parseConfidence(fm['confidence']);
|
|
97
|
+
if (conf !== null && conf < rules.minConfidence) {
|
|
98
|
+
reasons.push(`confidence ${conf} < ${rules.minConfidence}`);
|
|
99
|
+
summary.lowConfidence++;
|
|
100
|
+
}
|
|
101
|
+
const migratedFrom = typeof fm['migrated_from'] === 'string' ? fm['migrated_from'] : null;
|
|
102
|
+
if (rules.dropAgentMemoryDumps && migratedFrom?.startsWith('agent/') && migratedFrom.endsWith('/memory.json')) {
|
|
103
|
+
reasons.push('migrated from agent memory.json');
|
|
104
|
+
summary.agentMemoryDump++;
|
|
105
|
+
}
|
|
106
|
+
if (reasons.length > 0) {
|
|
107
|
+
flagged.set(page.relPath, {
|
|
108
|
+
reasons,
|
|
109
|
+
meta: {
|
|
110
|
+
confidence: conf,
|
|
111
|
+
originalAuthor: typeof fm['original_author'] === 'string' ? fm['original_author'] : null,
|
|
112
|
+
originalDate: typeof fm['original_date'] === 'string' ? fm['original_date'] : null,
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Second pass — per-agent cap. Only considers pages NOT already flagged
|
|
118
|
+
// by other rules (so a low-confidence page doesn't take a "cap slot").
|
|
119
|
+
if (rules.maxPerAgent > 0) {
|
|
120
|
+
const byAuthor = new Map();
|
|
121
|
+
for (const page of allPages) {
|
|
122
|
+
if (flagged.has(page.relPath))
|
|
123
|
+
continue;
|
|
124
|
+
const fm = page.frontmatter;
|
|
125
|
+
const author = typeof fm['original_author'] === 'string' ? fm['original_author'] : null;
|
|
126
|
+
if (!author)
|
|
127
|
+
continue;
|
|
128
|
+
const conf = parseConfidence(fm['confidence']) ?? 0;
|
|
129
|
+
const date = typeof fm['original_date'] === 'string' ? fm['original_date'] : '';
|
|
130
|
+
const arr = byAuthor.get(author) ?? [];
|
|
131
|
+
arr.push({ relPath: page.relPath, confidence: conf, date });
|
|
132
|
+
byAuthor.set(author, arr);
|
|
133
|
+
}
|
|
134
|
+
for (const [author, arr] of byAuthor) {
|
|
135
|
+
if (arr.length <= rules.maxPerAgent)
|
|
136
|
+
continue;
|
|
137
|
+
// Keep top-N by confidence desc, then date desc.
|
|
138
|
+
arr.sort((a, b) => (b.confidence - a.confidence) || b.date.localeCompare(a.date));
|
|
139
|
+
for (const overflow of arr.slice(rules.maxPerAgent)) {
|
|
140
|
+
const existing = flagged.get(overflow.relPath);
|
|
141
|
+
if (existing) {
|
|
142
|
+
existing.reasons.push(`per-agent cap (${author}: keep ${rules.maxPerAgent})`);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
flagged.set(overflow.relPath, {
|
|
146
|
+
reasons: [`per-agent cap (${author}: keep ${rules.maxPerAgent})`],
|
|
147
|
+
meta: { confidence: overflow.confidence, originalAuthor: author, originalDate: overflow.date },
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
summary.perAgentCapped++;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const candidates = [];
|
|
155
|
+
for (const page of allPages) {
|
|
156
|
+
const flag = flagged.get(page.relPath);
|
|
157
|
+
if (!flag)
|
|
158
|
+
continue;
|
|
159
|
+
const fm = page.frontmatter;
|
|
160
|
+
candidates.push({
|
|
161
|
+
relPath: page.relPath,
|
|
162
|
+
reasons: flag.reasons,
|
|
163
|
+
confidence: flag.meta.confidence,
|
|
164
|
+
originalAuthor: flag.meta.originalAuthor,
|
|
165
|
+
migratedFrom: typeof fm['migrated_from'] === 'string' ? fm['migrated_from'] : null,
|
|
166
|
+
originalId: typeof fm['original_id'] === 'string' ? fm['original_id'] : null,
|
|
167
|
+
bytes: page.bytes,
|
|
168
|
+
});
|
|
169
|
+
if (candidates.length >= SCAN_HARD_CAP) {
|
|
170
|
+
truncated = true;
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
this.logger.info('Wiki cleanup scan complete', {
|
|
175
|
+
vaultPath: input.vaultPath,
|
|
176
|
+
scannedCount: allPages.length,
|
|
177
|
+
candidateCount: candidates.length,
|
|
178
|
+
truncated,
|
|
179
|
+
summary,
|
|
180
|
+
});
|
|
181
|
+
return {
|
|
182
|
+
ok: true,
|
|
183
|
+
vaultPath: input.vaultPath,
|
|
184
|
+
candidates,
|
|
185
|
+
scannedCount: allPages.length,
|
|
186
|
+
truncated,
|
|
187
|
+
summary,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Delete the listed pages from the vault, archive each one (body +
|
|
192
|
+
* frontmatter) to `.wiki-cleanup-archive.json`, and invalidate the
|
|
193
|
+
* corresponding entry in the migrate manifest so the same source can't
|
|
194
|
+
* resurrect the page on the next `wiki-migrate --apply`.
|
|
195
|
+
*/
|
|
196
|
+
async apply(input) {
|
|
197
|
+
const validation = this.validateVault(input.vaultPath);
|
|
198
|
+
if (!validation.ok)
|
|
199
|
+
return validation;
|
|
200
|
+
if (!Array.isArray(input.pages) || input.pages.length === 0) {
|
|
201
|
+
return { ok: false, reason: 'invalid_input', message: 'pages must be a non-empty array' };
|
|
202
|
+
}
|
|
203
|
+
const archivePath = path.join(input.vaultPath, WIKI_CLEANUP_ARCHIVE_FILENAME);
|
|
204
|
+
const archive = await safeReadJson(archivePath, { version: WIKI_CLEANUP_ARCHIVE_VERSION, entries: [] }, this.logger);
|
|
205
|
+
if (archive.version !== WIKI_CLEANUP_ARCHIVE_VERSION) {
|
|
206
|
+
// Migrate-style: don't trust an unknown version, just start fresh.
|
|
207
|
+
archive.version = WIKI_CLEANUP_ARCHIVE_VERSION;
|
|
208
|
+
archive.entries = [];
|
|
209
|
+
}
|
|
210
|
+
const deleted = [];
|
|
211
|
+
const skipped = [];
|
|
212
|
+
for (const relPath of input.pages) {
|
|
213
|
+
const safe = this.normalizeRelPath(relPath);
|
|
214
|
+
if (!safe) {
|
|
215
|
+
skipped.push({ relPath, reason: 'outside_vault' });
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
// Defence: even if the caller passes a frozen-folder path, refuse.
|
|
219
|
+
// The top-level segment is the folder name (`memory/secret.md` →
|
|
220
|
+
// `memory`); pages directly under the vault root are never frozen.
|
|
221
|
+
const segments = safe.split('/');
|
|
222
|
+
if (segments.length >= 2 && FROZEN_FOLDERS.has(segments[0])) {
|
|
223
|
+
skipped.push({ relPath, reason: 'frozen' });
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
const abs = path.join(input.vaultPath, safe);
|
|
227
|
+
if (!existsSync(abs)) {
|
|
228
|
+
skipped.push({ relPath, reason: 'not_found' });
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
// Read + parse before delete so we can archive shape.
|
|
232
|
+
const raw = await fs.readFile(abs, 'utf8');
|
|
233
|
+
const { frontmatter, body } = parseFrontmatter(raw);
|
|
234
|
+
archive.entries.push({
|
|
235
|
+
relPath: safe,
|
|
236
|
+
archivedAt: new Date().toISOString(),
|
|
237
|
+
reasons: ['apply-list'],
|
|
238
|
+
body,
|
|
239
|
+
frontmatter,
|
|
240
|
+
});
|
|
241
|
+
await fs.unlink(abs);
|
|
242
|
+
deleted.push(safe);
|
|
243
|
+
}
|
|
244
|
+
// Persist archive — the rollback source of truth.
|
|
245
|
+
//
|
|
246
|
+
// **Manifest is deliberately NOT modified** (2026-05-28 fix). Earlier
|
|
247
|
+
// versions removed the matching entries from `.migration-state.json`
|
|
248
|
+
// on the theory "now nothing pins the page in place." That was
|
|
249
|
+
// exactly backwards: the migrate manifest is what makes
|
|
250
|
+
// `wiki-migrate --apply` IDEMPOTENT. With the entry present + hash
|
|
251
|
+
// match, migrate sees "already migrated" → skips. With the entry
|
|
252
|
+
// removed, migrate sees "new content" → re-imports → the
|
|
253
|
+
// just-deleted page reappears on the next bridge tick. Symptom seen
|
|
254
|
+
// 2026-05-28 ~05:30: 20 pages deleted, then 20 re-imported by the
|
|
255
|
+
// next migrate tick, candidate count never dropped. The page on
|
|
256
|
+
// disk is gone; that is sufficient. Manifest stays intact.
|
|
257
|
+
await ensureDir(input.vaultPath);
|
|
258
|
+
await atomicWriteJson(archivePath, archive);
|
|
259
|
+
this.logger.info('Wiki cleanup apply complete', {
|
|
260
|
+
vaultPath: input.vaultPath,
|
|
261
|
+
requested: input.pages.length,
|
|
262
|
+
deleted: deleted.length,
|
|
263
|
+
skipped: skipped.length,
|
|
264
|
+
archivePath,
|
|
265
|
+
});
|
|
266
|
+
return {
|
|
267
|
+
ok: true,
|
|
268
|
+
vaultPath: input.vaultPath,
|
|
269
|
+
deleted,
|
|
270
|
+
skipped,
|
|
271
|
+
archivePath,
|
|
272
|
+
manifestEntriesInvalidated: 0,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
// -------------------------------------------------------------------------
|
|
276
|
+
// Internals
|
|
277
|
+
// -------------------------------------------------------------------------
|
|
278
|
+
validateVault(vaultPath) {
|
|
279
|
+
if (!vaultPath || !path.isAbsolute(vaultPath)) {
|
|
280
|
+
return { ok: false, reason: 'invalid_input', message: 'vaultPath must be an absolute path' };
|
|
281
|
+
}
|
|
282
|
+
if (!existsSync(vaultPath)) {
|
|
283
|
+
return { ok: false, reason: 'vault_missing', message: `vault not found: ${vaultPath}` };
|
|
284
|
+
}
|
|
285
|
+
return { ok: true };
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Best-effort safe-rel normalisation. Returns null if the path would
|
|
289
|
+
* resolve outside the vault (`..` traversal etc).
|
|
290
|
+
*/
|
|
291
|
+
normalizeRelPath(rel) {
|
|
292
|
+
const normalised = path.posix.normalize(rel.replace(/\\/g, '/'));
|
|
293
|
+
if (normalised.startsWith('..') || path.isAbsolute(normalised))
|
|
294
|
+
return null;
|
|
295
|
+
return normalised;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Walk the vault tree, parsing frontmatter on each `.md` file. Skips
|
|
299
|
+
* frozen folders + non-md files. Returns true if the scan was truncated
|
|
300
|
+
* by the hard cap.
|
|
301
|
+
*/
|
|
302
|
+
async walkPages(dir, vaultPath, accumulator, cap) {
|
|
303
|
+
let entries;
|
|
304
|
+
try {
|
|
305
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
for (const entry of entries) {
|
|
311
|
+
if (accumulator.length >= cap)
|
|
312
|
+
return true;
|
|
313
|
+
// Skip frozen folders only at the vault-root level (`llm-curated/`
|
|
314
|
+
// sits next to them, so we never recurse INTO sibling frozen dirs
|
|
315
|
+
// — but defence-in-depth this check covers anyone who calls
|
|
316
|
+
// `walkPages` with the vault root directly).
|
|
317
|
+
if (entry.isDirectory()) {
|
|
318
|
+
const relParent = path.relative(vaultPath, path.join(dir, entry.name));
|
|
319
|
+
const topLevel = relParent.split(path.sep)[0];
|
|
320
|
+
if (FROZEN_FOLDERS.has(topLevel))
|
|
321
|
+
continue;
|
|
322
|
+
const truncated = await this.walkPages(path.join(dir, entry.name), vaultPath, accumulator, cap);
|
|
323
|
+
if (truncated)
|
|
324
|
+
return true;
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
if (!entry.isFile() || !entry.name.endsWith('.md'))
|
|
328
|
+
continue;
|
|
329
|
+
const abs = path.join(dir, entry.name);
|
|
330
|
+
try {
|
|
331
|
+
const stat = await fs.stat(abs);
|
|
332
|
+
const raw = await fs.readFile(abs, 'utf8');
|
|
333
|
+
const { frontmatter } = parseFrontmatter(raw);
|
|
334
|
+
accumulator.push({
|
|
335
|
+
relPath: path.relative(vaultPath, abs).split(path.sep).join('/'),
|
|
336
|
+
frontmatter,
|
|
337
|
+
bytes: stat.size,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
catch (err) {
|
|
341
|
+
this.logger.debug('walkPages: skipping unreadable file', {
|
|
342
|
+
path: abs,
|
|
343
|
+
error: err instanceof Error ? err.message : String(err),
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// ---------------------------------------------------------------------------
|
|
351
|
+
// Helpers (module-private, exported for tests)
|
|
352
|
+
// ---------------------------------------------------------------------------
|
|
353
|
+
/**
|
|
354
|
+
* Parse `confidence` from frontmatter into a number, or null if absent /
|
|
355
|
+
* unparseable. Accepts both numeric (`0.3`) and string (`"0.3"`) shapes
|
|
356
|
+
* because YAML quoting is inconsistent across older migrated pages.
|
|
357
|
+
*/
|
|
358
|
+
export function parseConfidence(raw) {
|
|
359
|
+
if (typeof raw === 'number' && Number.isFinite(raw))
|
|
360
|
+
return raw;
|
|
361
|
+
if (typeof raw === 'string') {
|
|
362
|
+
const parsed = parseFloat(raw);
|
|
363
|
+
if (Number.isFinite(parsed))
|
|
364
|
+
return parsed;
|
|
365
|
+
}
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Minimal YAML frontmatter parser. Handles the shapes our migrate service
|
|
370
|
+
* emits — `key: value` lines, with optional quotes around values. NOT a
|
|
371
|
+
* general YAML parser. Returns `{}` when no frontmatter is present.
|
|
372
|
+
*/
|
|
373
|
+
export function parseFrontmatter(raw) {
|
|
374
|
+
const match = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
|
375
|
+
if (!match)
|
|
376
|
+
return { frontmatter: {}, body: raw };
|
|
377
|
+
const fm = {};
|
|
378
|
+
for (const line of match[1].split('\n')) {
|
|
379
|
+
const lineMatch = line.match(/^([A-Za-z_][A-Za-z0-9_]*):\s*(.*)$/);
|
|
380
|
+
if (!lineMatch)
|
|
381
|
+
continue;
|
|
382
|
+
let value = lineMatch[2].trim();
|
|
383
|
+
// Strip wrapping quotes.
|
|
384
|
+
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|
|
385
|
+
value = value.slice(1, -1);
|
|
386
|
+
}
|
|
387
|
+
// Coerce a few common scalar shapes.
|
|
388
|
+
if (value === 'true')
|
|
389
|
+
fm[lineMatch[1]] = true;
|
|
390
|
+
else if (value === 'false')
|
|
391
|
+
fm[lineMatch[1]] = false;
|
|
392
|
+
else if (/^-?\d+(\.\d+)?$/.test(value))
|
|
393
|
+
fm[lineMatch[1]] = parseFloat(value);
|
|
394
|
+
else
|
|
395
|
+
fm[lineMatch[1]] = value;
|
|
396
|
+
}
|
|
397
|
+
return { frontmatter: fm, body: match[2] };
|
|
398
|
+
}
|
|
399
|
+
//# sourceMappingURL=wiki-cleanup.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiki-cleanup.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/wiki/wiki-cleanup.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WikiLintService — deterministic validation pass over a vault.
|
|
3
|
+
*
|
|
4
|
+
* Per v2.1 spec §3, the third Phase 1 skill (alongside `wiki-ingest` and
|
|
5
|
+
* `wiki-query`). Unlike `wiki-bookkeep` (vault HEALTH metrics — counts,
|
|
6
|
+
* recent activity, duplicate clusters), lint focuses on CORRECTNESS:
|
|
7
|
+
*
|
|
8
|
+
* - **frozenPathRespected** — no markdown content in folders flagged
|
|
9
|
+
* `frozen: true` in SCHEMA.md (other than the SCHEMA.md itself /
|
|
10
|
+
* legitimate frozen content). Lint refuses to alter frozen paths.
|
|
11
|
+
* - **missingEntities** — `[[wikilinks]]` that don't resolve to any
|
|
12
|
+
* page in the vault. Either the target was renamed, deleted, or the
|
|
13
|
+
* wikilink was made up. The lint flags them; the agent decides.
|
|
14
|
+
* - **orphanPages** — pages with zero incoming wikilinks, excluding
|
|
15
|
+
* seed pages (log.md, index.md, README*). These are candidates for
|
|
16
|
+
* either deletion or new linking.
|
|
17
|
+
* - **staleClaims** — files un-touched for `staleDays` (default 90).
|
|
18
|
+
* - **restructureProposals** — heuristics for llm-curated/ only: large
|
|
19
|
+
* un-indexed folders, near-duplicate filenames.
|
|
20
|
+
*
|
|
21
|
+
* The service never writes. The agent's LLM reads the report and decides
|
|
22
|
+
* whether to ingest a consolidation, archive stale pages, etc.
|
|
23
|
+
*
|
|
24
|
+
* @module services/wiki/wiki-lint.service
|
|
25
|
+
*/
|
|
26
|
+
/** Default age threshold (days) for marking a page stale. */
|
|
27
|
+
export declare const WIKI_LINT_DEFAULT_STALE_DAYS = 90;
|
|
28
|
+
/** Folder size threshold above which lint proposes an `index.md` rollup. */
|
|
29
|
+
export declare const WIKI_LINT_ROLLUP_THRESHOLD = 20;
|
|
30
|
+
/** Max number of pages walked per lint pass. */
|
|
31
|
+
export declare const WIKI_LINT_MAX_PAGES = 1000;
|
|
32
|
+
/** Cap per category to keep the payload bounded. */
|
|
33
|
+
export declare const WIKI_LINT_MAX_ROWS_PER_SECTION = 50;
|
|
34
|
+
/** Pages with these basenames never count as "orphans". */
|
|
35
|
+
export declare const WIKI_LINT_SEED_BASENAMES: Set<string>;
|
|
36
|
+
/**
|
|
37
|
+
* A `[[wikilink]]` target is "concept-shaped" (vs a dangling typo) when
|
|
38
|
+
* it appears at least this many times across the vault. Below this, the
|
|
39
|
+
* unresolved target is just noise; at or above this, the concept is
|
|
40
|
+
* load-bearing and deserves its own page.
|
|
41
|
+
*/
|
|
42
|
+
export declare const WIKI_LINT_MISSING_CONCEPT_THRESHOLD = 3;
|
|
43
|
+
export interface WikiLintInput {
|
|
44
|
+
vaultPath: string;
|
|
45
|
+
staleDays?: number;
|
|
46
|
+
}
|
|
47
|
+
export interface WikiLintFrozenViolation {
|
|
48
|
+
/** Relative path of the offending file. */
|
|
49
|
+
path: string;
|
|
50
|
+
/** The frozen folder it lives in. */
|
|
51
|
+
frozenFolder: string;
|
|
52
|
+
}
|
|
53
|
+
export interface WikiLintMissingEntity {
|
|
54
|
+
/** Page that contains the dangling wikilink. */
|
|
55
|
+
sourcePath: string;
|
|
56
|
+
/** The unresolved wikilink target. */
|
|
57
|
+
target: string;
|
|
58
|
+
/** Line number in the source page (1-based). */
|
|
59
|
+
lineNumber: number;
|
|
60
|
+
}
|
|
61
|
+
export interface WikiLintRestructureProposal {
|
|
62
|
+
/** Plain-English description of the proposal, e.g. "folder X has 31 pages without an index.md — propose llm-curated/X/index.md". */
|
|
63
|
+
description: string;
|
|
64
|
+
/** Optional related path (folder or page). */
|
|
65
|
+
path?: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A wikilink target that appears repeatedly across the vault but has no
|
|
69
|
+
* dedicated page. Karpathy's lint contract names this explicitly:
|
|
70
|
+
* *"important concepts mentioned but lacking their own page."* Different
|
|
71
|
+
* from `missingEntities` (which is one-off dangling refs / typos):
|
|
72
|
+
* `missingConcepts` is **frequency-weighted** signal that the team keeps
|
|
73
|
+
* mentioning a thing → write a page for it.
|
|
74
|
+
*/
|
|
75
|
+
export interface WikiLintMissingConcept {
|
|
76
|
+
/** The wikilink target referenced (e.g. `verify-output`). */
|
|
77
|
+
target: string;
|
|
78
|
+
/** How many distinct wikilink occurrences resolved to nothing. */
|
|
79
|
+
referenceCount: number;
|
|
80
|
+
/** Sample sources (capped) that reference this concept. */
|
|
81
|
+
sources: string[];
|
|
82
|
+
}
|
|
83
|
+
export interface WikiLintReport {
|
|
84
|
+
vault: {
|
|
85
|
+
scope: string;
|
|
86
|
+
id: string;
|
|
87
|
+
path: string;
|
|
88
|
+
};
|
|
89
|
+
generatedAt: string;
|
|
90
|
+
staleDays: number;
|
|
91
|
+
frozenPathRespected: boolean;
|
|
92
|
+
frozenViolations: WikiLintFrozenViolation[];
|
|
93
|
+
missingEntities: WikiLintMissingEntity[];
|
|
94
|
+
/** New 2026-05-26: frequency-weighted "missing concept" signals. */
|
|
95
|
+
missingConcepts: WikiLintMissingConcept[];
|
|
96
|
+
orphanPages: string[];
|
|
97
|
+
staleClaims: string[];
|
|
98
|
+
restructureProposals: WikiLintRestructureProposal[];
|
|
99
|
+
truncated: boolean;
|
|
100
|
+
}
|
|
101
|
+
export type WikiLintOutcome = {
|
|
102
|
+
ok: true;
|
|
103
|
+
report: WikiLintReport;
|
|
104
|
+
} | {
|
|
105
|
+
ok: false;
|
|
106
|
+
reason: 'vault_missing' | 'schema_missing' | 'invalid_input';
|
|
107
|
+
message: string;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Singleton lint service. Stateless — pattern mirrors the other wiki
|
|
111
|
+
* services so the controller wiring is uniform.
|
|
112
|
+
*/
|
|
113
|
+
export declare class WikiLintService {
|
|
114
|
+
private static instance;
|
|
115
|
+
private readonly logger;
|
|
116
|
+
private readonly schemaLoader;
|
|
117
|
+
private constructor();
|
|
118
|
+
static getInstance(): WikiLintService;
|
|
119
|
+
static resetInstance(): void;
|
|
120
|
+
/**
|
|
121
|
+
* Generate a lint report for the given vault.
|
|
122
|
+
*/
|
|
123
|
+
generate(input: WikiLintInput): Promise<WikiLintOutcome>;
|
|
124
|
+
/**
|
|
125
|
+
* Recursive walk collecting `.md` files. Honors `WIKI_LINT_MAX_PAGES`.
|
|
126
|
+
*/
|
|
127
|
+
private collectFiles;
|
|
128
|
+
/**
|
|
129
|
+
* Find `.md` files that live inside any frozen folder. SCHEMA.md and
|
|
130
|
+
* legitimate sibling files inside frozen dirs (e.g. `sop/<role>.md`)
|
|
131
|
+
* are excluded — frozen folders ARE allowed to contain content; what's
|
|
132
|
+
* NOT allowed is `wiki-ingest` writing INTO them. That's a runtime
|
|
133
|
+
* check elsewhere. Lint surfaces files only when they look like they
|
|
134
|
+
* were created by ingest patterns (timestamp-prefixed slugs).
|
|
135
|
+
*/
|
|
136
|
+
private detectFrozenViolations;
|
|
137
|
+
/**
|
|
138
|
+
* One read pass per file: pulls `[[wikilink]]` references, builds the
|
|
139
|
+
* inverse "incoming" map for orphan detection, and emits missing-entity
|
|
140
|
+
* rows for any link that resolves to nothing.
|
|
141
|
+
*/
|
|
142
|
+
private scanWikilinks;
|
|
143
|
+
/**
|
|
144
|
+
* A page is an orphan when no other page wikilinks to it AND it is
|
|
145
|
+
* not a seed page (log.md / index.md / README.md / SCHEMA.md).
|
|
146
|
+
*/
|
|
147
|
+
private detectOrphans;
|
|
148
|
+
/**
|
|
149
|
+
* Find load-bearing concepts referenced repeatedly across the vault
|
|
150
|
+
* but lacking a dedicated page. Karpathy's lint contract names this:
|
|
151
|
+
* *"important concepts mentioned but lacking their own page."*
|
|
152
|
+
*
|
|
153
|
+
* Frequency-filtered (`WIKI_LINT_MISSING_CONCEPT_THRESHOLD`, default 3)
|
|
154
|
+
* so we ignore typos and inline-code-style `[[X]]` brackets that aren't
|
|
155
|
+
* meant as wikilinks. Distinct from `missingEntities`, which flags every
|
|
156
|
+
* dangling ref individually.
|
|
157
|
+
*
|
|
158
|
+
* Results sort by referenceCount desc — highest-leverage concepts first.
|
|
159
|
+
*/
|
|
160
|
+
private detectMissingConcepts;
|
|
161
|
+
/**
|
|
162
|
+
* Files whose content is older than `staleDays`.
|
|
163
|
+
*
|
|
164
|
+
* Migrated pages may have an `original_date` frontmatter field
|
|
165
|
+
* (e.g. the legacy decision was made 2026-02-01 but we wrote the
|
|
166
|
+
* markdown TODAY). Stale detection should respect the original date
|
|
167
|
+
* when present — otherwise every freshly-migrated old page would look
|
|
168
|
+
* "new" by mtime alone. Falls back to mtime when frontmatter is absent.
|
|
169
|
+
*/
|
|
170
|
+
private detectStale;
|
|
171
|
+
/**
|
|
172
|
+
* Heuristic restructure proposals — only for `llm-curated/` since
|
|
173
|
+
* frozen folders cannot be restructured.
|
|
174
|
+
*
|
|
175
|
+
* (1) A subfolder with > WIKI_LINT_ROLLUP_THRESHOLD pages and NO `index.md`
|
|
176
|
+
* gets an "add an index.md rollup" proposal.
|
|
177
|
+
* (2) Near-duplicate filename prefixes (e.g. `pricing-v1.md`, `pricing-v2.md`)
|
|
178
|
+
* get a "consider merging" proposal.
|
|
179
|
+
*/
|
|
180
|
+
private proposeRestructures;
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=wiki-lint.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiki-lint.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/wiki/wiki-lint.service.ts"],"names":[],"mappings":"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"}
|