@rahmantech/knl-view 0.0.0-stage → 0.2.0
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/LICENSE +201 -0
- package/README.md +483 -2
- package/bin/knl-view.js +1320 -0
- package/dist/assets/abnfDiagram-WEYOIA3C-hoSbsMOz.js +1 -0
- package/dist/assets/arc-g87Np6E5.js +1 -0
- package/dist/assets/architecture-WOLXFQ4H-DOIq-0IA.js +1 -0
- package/dist/assets/architectureDiagram-ZHVYKT53-Dxwe8n7m.js +36 -0
- package/dist/assets/array-BifhSqXX.js +1 -0
- package/dist/assets/blockDiagram-RJAE7QA3-BnGng59Z.js +140 -0
- package/dist/assets/c4Diagram-XDPPPE54-C5LjqIIo.js +38 -0
- package/dist/assets/channel-BVWkRFBw.js +1 -0
- package/dist/assets/chunk-2E7WHVMD-BJ1dyGLq.js +88 -0
- package/dist/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/dist/assets/chunk-4EMNKR2T-DXF02Sgw.js +1 -0
- package/dist/assets/chunk-55XCU76K-CM1akAbu.js +1 -0
- package/dist/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/dist/assets/chunk-7S6XSTFO-BOUjqldL.js +2 -0
- package/dist/assets/chunk-AQDTSKZB-C4isdNLA.js +72 -0
- package/dist/assets/chunk-DSNLSHJZ-CbOTkSVM.js +129 -0
- package/dist/assets/chunk-DUW6YSOI-Dgx8z5s3.js +1 -0
- package/dist/assets/chunk-HAGFOTED-CRfnketR.js +62 -0
- package/dist/assets/chunk-HNE4Q36P-rxlpGUU8.js +1 -0
- package/dist/assets/chunk-J5ZVWO5B-oDCd-gWO.js +1 -0
- package/dist/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/dist/assets/chunk-NGNAAXSQ-C2Wy9Xmz.js +136 -0
- package/dist/assets/chunk-NQOKRVIF-BOYCgTmV.js +213 -0
- package/dist/assets/chunk-UHW7PFBP-Cnogp1Fb.js +1 -0
- package/dist/assets/chunk-VQ5W62QI-Cu1WY5Uo.js +1 -0
- package/dist/assets/chunk-WQQL4CDK-BJc3FPE2.js +10 -0
- package/dist/assets/chunk-XXDRQBXY-BlPj4H7s.js +1 -0
- package/dist/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/dist/assets/chunk-YZO67HFG-V85H31x4.js +1 -0
- package/dist/assets/chunk-ZAUX2LTX-C3XKXW09.js +1 -0
- package/dist/assets/chunk-ZCHMQSOR-B0mmpEgW.js +2 -0
- package/dist/assets/classDiagram-v2-4MYWR3UA-oMd7YaHP.js +217 -0
- package/dist/assets/cose-bilkent-JH36ORCC-J0kSVsDf.js +1 -0
- package/dist/assets/cynefin-EF2NZ3EQ-DK2TNhel.js +1 -0
- package/dist/assets/cynefinDiagram-WF24UDRP-DDvKgieA.js +62 -0
- package/dist/assets/cytoscape.esm-BegBNzOV.js +321 -0
- package/dist/assets/dagre-NK4GIZVX-Ca2Fe-i-.js +4 -0
- package/dist/assets/defaultLocale-BFoDCU3G.js +1 -0
- package/dist/assets/diagram-CBK3MWTC-L6dmeQ2V.js +24 -0
- package/dist/assets/diagram-I5XIIV2D-DhG8R-v5.js +24 -0
- package/dist/assets/diagram-ODIL2UCW-BpYYbYBT.js +30 -0
- package/dist/assets/diagram-PFBEJUXE-DKQpHSsC.js +3 -0
- package/dist/assets/diagram-RJA3I4VV-DP7Dsnya.js +41 -0
- package/dist/assets/diagram-TYUNFSNR-CfSFewUS.js +200 -0
- package/dist/assets/dist-CQNjnrld.js +1 -0
- package/dist/assets/ebnfDiagram-V4P3TTPT-DE3MZoJO.js +1 -0
- package/dist/assets/elk-QONTBCTQ-p_aAQPHU.js +27 -0
- package/dist/assets/erDiagram-KYQIGQAA-DZO3vQrk.js +99 -0
- package/dist/assets/eventmodeling-K75KTNOO-BII9EPl5.js +1 -0
- package/dist/assets/flowDiagram-IUGLLWBU-D9uPno39.js +1 -0
- package/dist/assets/ganttDiagram-R7GPNTJY-BKiH3v2r.js +292 -0
- package/dist/assets/gitGraph-VSP46ZUC-oHL6cr73.js +1 -0
- package/dist/assets/gitGraphDiagram-PDYL7XHY-CqPVIEeo.js +106 -0
- package/dist/assets/graphlib-DS17s2tU.js +1 -0
- package/dist/assets/index-CSpirV16.js +76 -0
- package/dist/assets/index-DLgMsUs2.css +1 -0
- package/dist/assets/info-OHQRW6UA-Drrbnhpd.js +1 -0
- package/dist/assets/infoDiagram-MVDRKAX5-DnQQFMAd.js +2 -0
- package/dist/assets/init-C-OQMol4.js +1 -0
- package/dist/assets/ishikawaDiagram-HPEHV2GE-DIpQlxRh.js +70 -0
- package/dist/assets/journeyDiagram-BOSHW7O7-EBR9I5h1.js +139 -0
- package/dist/assets/kanban-definition-FNSA4HC5-CdvNsjik.js +89 -0
- package/dist/assets/katex-B_JcIwqj.js +257 -0
- package/dist/assets/line-CDLzgxDc.js +1 -0
- package/dist/assets/linear-DfXKql9u.js +1 -0
- package/dist/assets/mermaid-parser.core-DnXGphT2.js +7 -0
- package/dist/assets/mermaid.core-h6fiCaSZ.js +44 -0
- package/dist/assets/mindmap-definition-6OY57UG3-BiNfio-j.js +98 -0
- package/dist/assets/ordinal-BDEzSJ7C.js +1 -0
- package/dist/assets/packet-JDAUHWVQ-D76byv1S.js +1 -0
- package/dist/assets/path-fybaL0A-.js +1 -0
- package/dist/assets/pegDiagram-ECIUJNBX-Drs8Pxdt.js +1 -0
- package/dist/assets/pie-XZMESJXO-D_83z1lM.js +1 -0
- package/dist/assets/pieDiagram-GNMPY74T-wvzIphSf.js +39 -0
- package/dist/assets/quadrantDiagram-D57K4MC3-B7EfMRWb.js +7 -0
- package/dist/assets/radar-ABXABTNO-Bs6dVdAR.js +1 -0
- package/dist/assets/railroad-I3PHUGI6-lKaN4miw.js +1 -0
- package/dist/assets/railroad-abnf-LNEFI6M7-Bhh16b7Z.js +1 -0
- package/dist/assets/railroad-ebnf-DWYD2UWJ-m6ybW-Y_.js +1 -0
- package/dist/assets/railroad-peg-JR7BVNR7-DNn72e7r.js +1 -0
- package/dist/assets/railroadDiagram-Y72NRBL7-DNeop1iZ.js +1 -0
- package/dist/assets/requirementDiagram-EQYSW5RA-BVYZ2XYJ.js +84 -0
- package/dist/assets/rough.esm-Dy-Kn_BL.js +1 -0
- package/dist/assets/sankeyDiagram-SY24JHO5-B2MP51on.js +40 -0
- package/dist/assets/sequenceDiagram-BLEHNHQU-BUvxstXG.js +169 -0
- package/dist/assets/sizeCapture-INFHLROL-3uHXrFqA.js +1 -0
- package/dist/assets/src-BrR0lqlG.js +1 -0
- package/dist/assets/stateDiagram-v2-A6IESKWZ-Ba84OGKE.js +291 -0
- package/dist/assets/swimlanes-B3ENRKFQ-BMSl2PNA.js +1 -0
- package/dist/assets/swimlanesDiagram-AYQRV4AK-M1dmvq7m.js +8 -0
- package/dist/assets/timeline-definition-JXYKGLGB-DOdW-dxq.js +120 -0
- package/dist/assets/treeView-D4JQ5SDB-DZ9KQyn5.js +1 -0
- package/dist/assets/treemap-SAJKECNS-WEC5wtDV.js +1 -0
- package/dist/assets/usecaseDiagram-WPOLBNNX-cldTztFL.js +328 -0
- package/dist/assets/vennDiagram-Q3Y3IDCW-c41KySoY.js +34 -0
- package/dist/assets/wardley-7MLQ67FV-Bf9_aSSZ.js +1 -0
- package/dist/assets/wardleyDiagram-IVAIDKWA-BeKEvEBG.js +78 -0
- package/dist/assets/xychartDiagram-4URNHDU4-tNkAxTxG.js +7 -0
- package/dist/index.html +22 -0
- package/package.json +50 -4
- package/server/config.js +389 -0
- package/server/consensus.js +180 -0
- package/server/graph/anchordb_client.js +253 -0
- package/server/graph/model.js +157 -0
- package/server/graph/parser.js +327 -0
- package/server/graph/sources.js +801 -0
- package/server/graph/syntax.js +437 -0
- package/server/index.js +742 -0
- package/server/install.js +437 -0
- package/server/map.js +126 -0
- package/server/models_registry.js +109 -0
- package/server/scaffold.js +466 -0
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
|
|
4
|
+
// Knowledge base builder for --init and --seed-skill.
|
|
5
|
+
// Same principle as the map: NEVER destroy anything that already exists.
|
|
6
|
+
// Existing files are skipped, and the .gitignore line is only added when
|
|
7
|
+
// not already present.
|
|
8
|
+
|
|
9
|
+
export const STANDARD_DIRS = ['roadmap', 'features', 'docs']
|
|
10
|
+
export const SKILL_ID = 'knl-view'
|
|
11
|
+
|
|
12
|
+
const ROOT_README = `# Knowledge Base
|
|
13
|
+
|
|
14
|
+
Lede: write a one-paragraph summary of this base here.
|
|
15
|
+
|
|
16
|
+
## How to read
|
|
17
|
+
|
|
18
|
+
- \`roadmap/\`: direction and plans.
|
|
19
|
+
- \`features/\`: feature notes.
|
|
20
|
+
- \`docs/\`: general documents.
|
|
21
|
+
|
|
22
|
+
Add \`map.json\` to this folder if you want to control menu labels and
|
|
23
|
+
display order without moving files. See the \`knl-view\` skill for the
|
|
24
|
+
full format.
|
|
25
|
+
`
|
|
26
|
+
|
|
27
|
+
const SECTION_README = (name) => `# ${name}
|
|
28
|
+
|
|
29
|
+
Nothing here yet. Put markdown files in this folder.
|
|
30
|
+
`
|
|
31
|
+
|
|
32
|
+
export async function scaffoldBase({ root, structure, folders = [] }) {
|
|
33
|
+
const actions = []
|
|
34
|
+
const rootAbs = path.resolve(root)
|
|
35
|
+
await fs.mkdir(rootAbs, { recursive: true })
|
|
36
|
+
actions.push({ kind: 'dir', path: rootAbs, status: 'created' })
|
|
37
|
+
|
|
38
|
+
if (structure === 'empty') return actions
|
|
39
|
+
|
|
40
|
+
const dirs = structure === 'custom' ? folders.map(cleanRel).filter(Boolean) : STANDARD_DIRS
|
|
41
|
+
|
|
42
|
+
await writeFileSafe(path.join(rootAbs, 'README.md'), ROOT_README, actions)
|
|
43
|
+
for (const dir of dirs) {
|
|
44
|
+
const abs = path.resolve(rootAbs, dir)
|
|
45
|
+
if (!abs.startsWith(rootAbs + path.sep)) continue
|
|
46
|
+
await fs.mkdir(abs, { recursive: true })
|
|
47
|
+
actions.push({ kind: 'dir', path: abs, status: 'created' })
|
|
48
|
+
await writeFileSafe(path.join(abs, 'README.md'), SECTION_README(dir), actions)
|
|
49
|
+
}
|
|
50
|
+
return actions
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function seedSkill({ scope, cwd, home = process.env.HOME, xdgConfig = process.env.XDG_CONFIG_HOME }) {
|
|
54
|
+
const base =
|
|
55
|
+
scope === 'global'
|
|
56
|
+
? path.join(xdgConfig || path.join(home, '.config'), 'opencode', 'skills')
|
|
57
|
+
: path.join(cwd, '.agents', 'skills')
|
|
58
|
+
const target = path.join(base, SKILL_ID, 'SKILL.md')
|
|
59
|
+
|
|
60
|
+
const exists = await statOrNull(target)
|
|
61
|
+
if (exists) return { path: target, status: 'skipped' }
|
|
62
|
+
|
|
63
|
+
await fs.mkdir(path.dirname(target), { recursive: true })
|
|
64
|
+
await fs.writeFile(target, SKILL_MD, 'utf8')
|
|
65
|
+
return { path: target, status: 'created' }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export async function ensureGitignore({ cwd }) {
|
|
69
|
+
const abs = path.join(cwd, '.gitignore')
|
|
70
|
+
const line = '.knowledges/'
|
|
71
|
+
let content = ''
|
|
72
|
+
const stat = await statOrNull(abs)
|
|
73
|
+
if (stat && stat.isFile()) content = await fs.readFile(abs, 'utf8')
|
|
74
|
+
|
|
75
|
+
const present = content.split(/\r?\n/).some((row) => row.trim() === line || row.trim() === '.knowledges')
|
|
76
|
+
if (present) return { path: abs, status: 'skipped' }
|
|
77
|
+
|
|
78
|
+
const next = content.length && !content.endsWith('\n') ? `${content}\n${line}\n` : `${content}${line}\n`
|
|
79
|
+
await fs.writeFile(abs, next, 'utf8')
|
|
80
|
+
return { path: abs, status: 'created' }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function buildAgentInstructionBlock(hasGraphify = false) {
|
|
84
|
+
const fallback = hasGraphify
|
|
85
|
+
? `- Graphify is the fallback. Use it only when a specific need remains unresolved by KNL-View or the user explicitly requests Graphify. If KNL-View answers the task, stop; do not run Graphify for duplicate analysis.
|
|
86
|
+
- When the user explicitly invokes \`/graphify\`, honor that request without automatically running both tools.
|
|
87
|
+
|
|
88
|
+
`
|
|
89
|
+
: ''
|
|
90
|
+
|
|
91
|
+
return `<!-- knl-view:start -->
|
|
92
|
+
# Knowledge graph tools
|
|
93
|
+
- KNL-View is the primary graph tool. For \`.knowledges\`, source graphs, and project graph questions, read the project's \`knl-view\` skill and use the relevant KNL-View feature first.
|
|
94
|
+
${fallback}## KNL-View graph access
|
|
95
|
+
- Use the KNL-View feature that fits the task (\`graph trace\`, \`sources trace/sync/collect\`, \`model check/new\`, consensus commands, or the viewer). Do not approximate a supported KNL-View operation with ad-hoc graph queries.
|
|
96
|
+
- Route all graph reads and writes through KNL-View's documented CLI, viewer, or application endpoints. Never connect to AnchorDB directly through AnchorWire, its CLI, direct database endpoints, files, SQL, or custom clients/scripts. If KNL-View cannot perform a requested operation, explain the limitation; do not bypass it.
|
|
97
|
+
- Keep graph work targeted: specify the relevant node/path, direction, and smallest useful hop count; summarize only relevant nodes and edges; avoid dumping whole graphs or large raw JSON.
|
|
98
|
+
- Follow the KNL-View skill's trace-before-edit and \`sources sync\`-after-change rules. Treat edge direction as lineage; do not claim causality without separate evidence.
|
|
99
|
+
<!-- knl-view:end -->`
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function stripLegacyKnlInstructions(text) {
|
|
103
|
+
let cleaned = text
|
|
104
|
+
cleaned = cleaned.replace(/<!-- knl-view:start -->[\s\S]*?<!-- knl-view:end -->/g, '\n')
|
|
105
|
+
cleaned = cleaned.replace(/<!--\s*knl-view:(?:start|end)\s*-->/g, '\n')
|
|
106
|
+
cleaned = cleaned.replace(
|
|
107
|
+
/(?:^|\n)# Knowledge graph tools[\s\S]*?(?=(?:\n#+\s)|$)/g,
|
|
108
|
+
'\n'
|
|
109
|
+
)
|
|
110
|
+
cleaned = cleaned.replace(
|
|
111
|
+
/(?:^|\n)## KNL-View graph access[\s\S]*?(?=(?:\n#+\s)|$)/g,
|
|
112
|
+
'\n'
|
|
113
|
+
)
|
|
114
|
+
return cleaned.trim()
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function seedAgentInstructions({ cwd = process.cwd(), home = process.env.HOME, hasGraphify = false }) {
|
|
118
|
+
const block = buildAgentInstructionBlock(hasGraphify)
|
|
119
|
+
const candidatePaths = [
|
|
120
|
+
// Project files:
|
|
121
|
+
path.join(cwd, 'AGENTS.md'),
|
|
122
|
+
path.join(cwd, 'GEMINI.md'),
|
|
123
|
+
path.join(cwd, 'CLAUDE.md'),
|
|
124
|
+
// Global files:
|
|
125
|
+
path.join(home || '', '.codex', 'AGENTS.md'),
|
|
126
|
+
path.join(home || '', '.gemini', 'GEMINI.md'),
|
|
127
|
+
path.join(home || '', '.claude', 'CLAUDE.md'),
|
|
128
|
+
path.join(home || '', '.agents', 'AGENTS.md')
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
const actions = []
|
|
132
|
+
|
|
133
|
+
for (const abs of candidatePaths) {
|
|
134
|
+
const parentDir = path.dirname(abs)
|
|
135
|
+
const parentExists = await statOrNull(parentDir)
|
|
136
|
+
if (!parentExists) continue
|
|
137
|
+
|
|
138
|
+
const stat = await statOrNull(abs)
|
|
139
|
+
if (stat && stat.isFile()) {
|
|
140
|
+
const content = await fs.readFile(abs, 'utf8')
|
|
141
|
+
const cleaned = stripLegacyKnlInstructions(content)
|
|
142
|
+
const next = cleaned.length ? `${cleaned}\n\n${block}\n` : `${block}\n`
|
|
143
|
+
|
|
144
|
+
if (next !== content) {
|
|
145
|
+
await fs.writeFile(abs, next, 'utf8')
|
|
146
|
+
actions.push({ path: abs, status: 'updated' })
|
|
147
|
+
} else {
|
|
148
|
+
actions.push({ path: abs, status: 'skipped' })
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// If no project file was found/updated, create ./AGENTS.md
|
|
154
|
+
const projectAgent = path.join(cwd, 'AGENTS.md')
|
|
155
|
+
if (!actions.some((a) => a.path.startsWith(cwd))) {
|
|
156
|
+
const stat = await statOrNull(projectAgent)
|
|
157
|
+
if (!stat) {
|
|
158
|
+
await fs.writeFile(projectAgent, `${block}\n`, 'utf8')
|
|
159
|
+
actions.push({ path: projectAgent, status: 'created' })
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return actions
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async function writeFileSafe(abs, content, actions) {
|
|
167
|
+
const exists = await statOrNull(abs)
|
|
168
|
+
if (exists) {
|
|
169
|
+
actions.push({ kind: 'file', path: abs, status: 'skipped' })
|
|
170
|
+
return
|
|
171
|
+
}
|
|
172
|
+
await fs.writeFile(abs, content, 'utf8')
|
|
173
|
+
actions.push({ kind: 'file', path: abs, status: 'created' })
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function cleanRel(value) {
|
|
177
|
+
const cleaned = String(value || '').trim()
|
|
178
|
+
const normalized = path.normalize(cleaned).replace(/^(\.\.[\/\\])+/, '').replace(/^[\/\\]+/, '').replace(/[\/\\]+$/, '')
|
|
179
|
+
if (!normalized || normalized === '.' || normalized === '..' || normalized.startsWith('..' + path.sep)) {
|
|
180
|
+
return ''
|
|
181
|
+
}
|
|
182
|
+
return normalized
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async function statOrNull(abs) {
|
|
186
|
+
try {
|
|
187
|
+
return await fs.stat(abs)
|
|
188
|
+
} catch {
|
|
189
|
+
return null
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// The skill is in English, following skill ecosystem conventions. It teaches
|
|
194
|
+
// the agent how to read the .knowledges base: README first, then map.json as
|
|
195
|
+
// the source of labels and menu order, then the anchor-connector-like
|
|
196
|
+
// structure.
|
|
197
|
+
const SKILL_MD = `---
|
|
198
|
+
name: knl-view
|
|
199
|
+
description: Read and maintain .knowledges knowledge bases. Use whenever a task involves a .knowledges folder, its map.json, or the knl-view viewer.
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
# Knowledges base
|
|
203
|
+
|
|
204
|
+
A \`.knowledges\` folder is a plain-directory knowledge base, viewed with
|
|
205
|
+
knl-view. The disk is the source of truth: files and folders exist because
|
|
206
|
+
they exist on disk, never because a map says so.
|
|
207
|
+
|
|
208
|
+
## Read in this order
|
|
209
|
+
|
|
210
|
+
1. \`README.md\` at the base root: the lede and the overview.
|
|
211
|
+
2. \`map.json\` at the base root, when present: the authoritative menu
|
|
212
|
+
labels, grouping, and order for everything below.
|
|
213
|
+
3. Then the structure the map (or the disk) describes. A typical base
|
|
214
|
+
mirrors anchor-connector: \`roadmap/\`, \`features/\`, \`futures/\`,
|
|
215
|
+
\`audit/\`, \`roasted/\`, plus root files \`coding-rules.md\` and
|
|
216
|
+
\`documentation-rules.md\`. Anything not on disk does not exist; do not
|
|
217
|
+
invent it from map entries.
|
|
218
|
+
|
|
219
|
+
## map.json
|
|
220
|
+
|
|
221
|
+
Optional. Every entry is decoration only. It sets the label shown in the
|
|
222
|
+
menu, the order in menus, and a short note. It never creates, moves, or
|
|
223
|
+
deletes files. Entries pointing at paths that are not on disk are ignored
|
|
224
|
+
silently. Without \`map.json\`, the viewer falls back to the first
|
|
225
|
+
\`# heading\` of each markdown file and plain name order: files first,
|
|
226
|
+
then folders.
|
|
227
|
+
|
|
228
|
+
\`\`\`json
|
|
229
|
+
{
|
|
230
|
+
"title": "Base title shown in the masthead",
|
|
231
|
+
"sections": {
|
|
232
|
+
"roadmap": { "title": "Roadmap", "order": 1, "meta": "Where this is going" },
|
|
233
|
+
"features": {
|
|
234
|
+
"title": "Features",
|
|
235
|
+
"order": 2,
|
|
236
|
+
"docs": { "auth.md": { "title": "Auth", "order": 1 } }
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
"docs": {
|
|
240
|
+
"coding-rules.md": { "title": "Coding rules", "order": 1 },
|
|
241
|
+
"documentation-rules.md": { "title": "Documentation rules", "order": 2 }
|
|
242
|
+
},
|
|
243
|
+
"files": {
|
|
244
|
+
"personal-assistant.md": { "title": "Personal Assistant" },
|
|
245
|
+
"secret.md": { "ignore": true }
|
|
246
|
+
},
|
|
247
|
+
"dirs": {
|
|
248
|
+
"old-drafts": { "ignore": true }
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
\`\`\`
|
|
252
|
+
|
|
253
|
+
| Field | Applies to | Effect |
|
|
254
|
+
| --- | --- | --- |
|
|
255
|
+
| \`title\` | the whole file | Masthead title; wins over the README heading |
|
|
256
|
+
| \`sections.<dir>\` / \`dirs.<path>\` | a directory | \`title\` is the menu label, \`meta\` is a short note |
|
|
257
|
+
| \`sections.<dir>.docs.<file>\` | a file inside that directory | same shape as \`docs\` entries |
|
|
258
|
+
| \`docs.<file>\` / \`files.<path>\` | a file | \`title\` is the menu label |
|
|
259
|
+
| \`order\` | any entry | Ascending menu order. Entries without \`order\` follow, still files before folders |
|
|
260
|
+
| \`ignore\` (or \`hidden\`) | any entry | \`true\` hides the file or folder from the menu, lists, search, home, and contents. Hiding a folder hides everything inside it |
|
|
261
|
+
|
|
262
|
+
\`ignore\` is view-only: the file still exists on disk. Remove the flag to
|
|
263
|
+
bring it back:
|
|
264
|
+
|
|
265
|
+
\`\`\`json
|
|
266
|
+
{ "files": { "secret.md": { "ignore": true } }, "dirs": { "old-drafts": { "ignore": true } } }
|
|
267
|
+
\`\`\`
|
|
268
|
+
|
|
269
|
+
Paths are relative to the \`.knowledges\` root, use \`/\` separators, and
|
|
270
|
+
must match the on-disk path exactly as the viewer shows it, for example
|
|
271
|
+
\`features/auth.md\`. Nested folders use the full relative path as the key.
|
|
272
|
+
|
|
273
|
+
The sidebar always opens with two fixed entries above the tree: \`index\`
|
|
274
|
+
(the root \`README.md\`) and \`contents\` (\`#/a/contents\`, a system route with
|
|
275
|
+
no file on disk that lists the whole base). The root README is therefore
|
|
276
|
+
not repeated inside the tree.
|
|
277
|
+
|
|
278
|
+
## Config (two layers)
|
|
279
|
+
|
|
280
|
+
knl-view reads two optional config files. A missing file is never an error;
|
|
281
|
+
a broken file is ignored with one warning.
|
|
282
|
+
|
|
283
|
+
**Global (\`~/.knlview/knl-config.json\`)**: shared by every project on this
|
|
284
|
+
machine. Holds the \`anchordb\` block (connection). Without it, AnchorDB
|
|
285
|
+
stays completely off:
|
|
286
|
+
|
|
287
|
+
\`\`\`json
|
|
288
|
+
{
|
|
289
|
+
"anchordb": {
|
|
290
|
+
"url": "wire://127.0.0.1:7448",
|
|
291
|
+
"token": "your-token",
|
|
292
|
+
"sync": true
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
\`\`\`
|
|
296
|
+
|
|
297
|
+
**Per project: \`knl-config.json\` at the project root**, machine-local,
|
|
298
|
+
gitignored. Holds only \`path\`, \`port\`, \`host\`, and the \`models\` map:
|
|
299
|
+
|
|
300
|
+
\`\`\`json
|
|
301
|
+
{
|
|
302
|
+
"path": ".knowledges",
|
|
303
|
+
"port": 8085,
|
|
304
|
+
"models": { "knowledges": "vez0vqrp" }
|
|
305
|
+
}
|
|
306
|
+
\`\`\`
|
|
307
|
+
|
|
308
|
+
The map owns model naming: role → AnchorDB model name, names may be
|
|
309
|
+
random; the map records what each name is for, and names stay stable
|
|
310
|
+
across project renames. Create names with \`knl-view model new <role>\`
|
|
311
|
+
and inspect ownership with \`knl-view model check\`. Without a map entry
|
|
312
|
+
for a role, that role runs fully local. CLI flags always win over
|
|
313
|
+
config values.
|
|
314
|
+
|
|
315
|
+
Installing AnchorDB (optional; the viewer runs fully local without it):
|
|
316
|
+
\`knl-view install anchordb\`: native binary from GitHub Releases on
|
|
317
|
+
Linux and macOS (SHA256-verified), or a container from
|
|
318
|
+
ghcr.io/rachmanzz/anchordb via docker/podman on other platforms. Flags:
|
|
319
|
+
\`--yes\`, \`--method=binary|container\`, \`--token=...\`.
|
|
320
|
+
|
|
321
|
+
Two-way lineage: graph traces take \`--direction\` (CLI) or
|
|
322
|
+
\`?direction=\` (HTTP): \`out\` follows edges leaving the target, \`in\`
|
|
323
|
+
follows edges entering it, \`both\` is the local default. Direction is
|
|
324
|
+
mechanical (edge direction), never cause-and-effect interpretation.
|
|
325
|
+
Each node in the result carries \`via\` (\`center\`, \`in\`, \`out\`,
|
|
326
|
+
\`in+out\`). On /api/anchordb/trace the default is \`out\`; \`in\` is
|
|
327
|
+
walked backwards from the local sync mirror and reported with
|
|
328
|
+
\`mirrored: true\`.
|
|
329
|
+
|
|
330
|
+
Consensus (claims): a second AnchorDB model (the \`consensus\` role in
|
|
331
|
+
the models map) holds agreement and conflict between claims only (never
|
|
332
|
+
decisions or files). Claims are content-addressed:
|
|
333
|
+
\`knl-view consensus claim "<statement>"\` prints the id (\`c-\` + 16 hex
|
|
334
|
+
chars of the statement hash); the same text is the same claim everywhere.
|
|
335
|
+
Relations: \`agree\`, \`contradict\`, \`retract\` take two claim
|
|
336
|
+
ids. \`status <id>\` derives: any incoming \`contradicts\` → \`disputed\`,
|
|
337
|
+
else incoming \`agrees_with\` → \`consensus\`, else \`uncontested\`.
|
|
338
|
+
\`list\` shows every locally known claim. Mutations are CLI-only;
|
|
339
|
+
\`GET /api/consensus?target=<claimId>\` is read-only. Requires AnchorDB
|
|
340
|
+
plus a mapped \`consensus\` role.
|
|
341
|
+
|
|
342
|
+
Sources graph (whole project): a third AnchorDB model, the \`sources\`
|
|
343
|
+
role, holds the dependency graph of the whole project: files and their
|
|
344
|
+
named symbols. Every file is a node (id = repo-relative path); import
|
|
345
|
+
edges are extracted with tree-sitter syntax parsing (JS family and Go
|
|
346
|
+
today) and stored in both directions (\`imports\`, \`imported_by\`).
|
|
347
|
+
Each file also defines symbol nodes: ids are \`<path>#<name>\` (class
|
|
348
|
+
methods \`Class.method\`; a name defined more than once in one file gets
|
|
349
|
+
a line suffix \`<path>#<name>@<line>\`), kinds are \`function\`,
|
|
350
|
+
\`class\`, \`method\`, \`type\`. Edges: \`defines\`/\`defined_in\`
|
|
351
|
+
(file → symbol) and \`calls\`/\`called_by\` (symbol → symbol), both
|
|
352
|
+
directions stored. Call resolution is conservative: the call belongs to
|
|
353
|
+
its innermost enclosing symbol and the callee must match exactly one
|
|
354
|
+
definition project-wide; ambiguous names are skipped, never guessed.
|
|
355
|
+
Label text (symbol names and kinds; AnchorDB attributes are
|
|
356
|
+
numeric-only) lives in \`.knowledges/.knl-data/<path>.md\`, one file per
|
|
357
|
+
source file that has symbols; override with \`labelDir\` in the project
|
|
358
|
+
config. Hidden folders are skipped except .github; node_modules, dist,
|
|
359
|
+
and .gitignore patterns are ignored. \`knl-view sources sync\` is
|
|
360
|
+
idempotent and server-authoritative (no local mirror);
|
|
361
|
+
\`knl-view sources trace --target=<id>\` and
|
|
362
|
+
\`GET /api/sources/trace?target=<id>\` answer lineage: a target
|
|
363
|
+
containing \`#\` walks symbol lineage (\`calls\`/\`called_by\`), a
|
|
364
|
+
plain path walks file lineage (\`imports\`/\`imported_by\`). A removed
|
|
365
|
+
file or symbol is tombstoned (attribute \`tombstone = 2\`) after its
|
|
366
|
+
edges are unlinked; if it comes back, the tombstone lifts and the edges
|
|
367
|
+
are relinked.
|
|
368
|
+
|
|
369
|
+
Decision history skill: recording architectural decisions is delegated
|
|
370
|
+
to the separate decision-history skill (its decision block format is its
|
|
371
|
+
own domain; this skill never writes decision blocks). If it is not
|
|
372
|
+
installed in the project yet, install it first:
|
|
373
|
+
\`npx skills add rachmanzz/decisionskills --skill decision-history\`
|
|
374
|
+
or, with agy: \`agy plugin install https://github.com/rachmanzz/decisionskills\`.
|
|
375
|
+
|
|
376
|
+
## Rules
|
|
377
|
+
|
|
378
|
+
- Never move or delete files to satisfy the map. Either add the file or
|
|
379
|
+
remove the stale map entry.
|
|
380
|
+
- Give every markdown file a top-level \`# heading\` so it still reads well
|
|
381
|
+
when no map entry covers it.
|
|
382
|
+
- Keep \`order\` values small and dense per menu level (1, 2, 3).
|
|
383
|
+
- When the map and disk disagree about existence, the disk wins.
|
|
384
|
+
|
|
385
|
+
## Features writing rules
|
|
386
|
+
|
|
387
|
+
Under \`features/{feature_name}/\`, prefer to keep at least:
|
|
388
|
+
- \`prd.md\`: Product Requirements Document for this feature
|
|
389
|
+
- \`detail-plan.md\`: concrete implementation plan, decisions, trade-offs
|
|
390
|
+
|
|
391
|
+
Names are kebab-case for the folder. Keep other artifacts minimal and cover
|
|
392
|
+
them via \`map.json\` if they need custom menu labels/order.
|
|
393
|
+
|
|
394
|
+
## Futures writing rules
|
|
395
|
+
|
|
396
|
+
Under \`futures/\`, the base typically has:
|
|
397
|
+
- \`README.md\`: vision/overview
|
|
398
|
+
- \`prd.md\`: global PRD covering proposed future work
|
|
399
|
+
|
|
400
|
+
Use kebab-case for any additional future documents. Defer exotic filenames
|
|
401
|
+
to \`map.json\`.
|
|
402
|
+
|
|
403
|
+
## Roadmap writing rules
|
|
404
|
+
|
|
405
|
+
Under \`roadmap/\`, maintain milestone-oriented notes. Keep \`README.md\` as
|
|
406
|
+
the index and split by milestones only when they grow large. Use
|
|
407
|
+
\`map.json\` to reorder milestones/files without renaming.
|
|
408
|
+
|
|
409
|
+
## Roasted writing rules
|
|
410
|
+
|
|
411
|
+
All artifacts from roasting/audits go under \`roasted/\` (relative to the
|
|
412
|
+
knowledge base root in use; i.e. the directory passed via \`--path\`, which
|
|
413
|
+
may be \`.knowledges\` or a custom one). Do **not** place them in the root
|
|
414
|
+
of that directory.
|
|
415
|
+
|
|
416
|
+
### Naming
|
|
417
|
+
|
|
418
|
+
\`roasted/{roasted_name}_v{number}.md\`: kebab-case name, integer
|
|
419
|
+
\`number\` starting at \`1\`.
|
|
420
|
+
|
|
421
|
+
### Stack order
|
|
422
|
+
|
|
423
|
+
- \`_v1\` is the first roast → placed at the bottom of the stack
|
|
424
|
+
- each new roast increments number and goes at the top (highest number =
|
|
425
|
+
newest)
|
|
426
|
+
- files are immutable by number; updates belong to the same file, not a
|
|
427
|
+
new one
|
|
428
|
+
|
|
429
|
+
### Classification
|
|
430
|
+
|
|
431
|
+
Every roast must state:
|
|
432
|
+
- \`Severity\`: \`P0|P1|P2|P3\`
|
|
433
|
+
- \`Class\`: \`BUG|PERF|VULN|DEBT|CEILING|PROCESS\`
|
|
434
|
+
|
|
435
|
+
## When the agent triggers the graph
|
|
436
|
+
|
|
437
|
+
The graph stays true only if the agent feeds it. Every trigger goes
|
|
438
|
+
through the single \`knl-view\` entrypoint with the existing subcommands
|
|
439
|
+
below; never invent another binary, script, or wrapper to fire any of
|
|
440
|
+
this.
|
|
441
|
+
|
|
442
|
+
- After creating, editing, renaming, or deleting any project file:
|
|
443
|
+
run \`knl-view sources sync\`. It is server-authoritative and
|
|
444
|
+
idempotent: run it again and only the difference is applied.
|
|
445
|
+
- Before changing a file that other files may depend on:
|
|
446
|
+
\`knl-view sources trace --target=<path> --direction=in\` shows who
|
|
447
|
+
depends on it first (the blast radius).
|
|
448
|
+
- Before adding an import to, or moving logic out of, another file:
|
|
449
|
+
\`knl-view sources trace --target=<path> --direction=out\` shows what
|
|
450
|
+
it already touches.
|
|
451
|
+
- Before changing or removing a function, method, or type:
|
|
452
|
+
\`knl-view sources trace --target=<path>#<name> --direction=in\` shows
|
|
453
|
+
every symbol that calls it first.
|
|
454
|
+
- Before renaming a symbol or moving it to another file: remember its
|
|
455
|
+
record id contains the old name/path. Sync tombstones the stale record
|
|
456
|
+
and creates the new one; trace by the new id afterwards.
|
|
457
|
+
- A new architectural decision: trigger the decision-history skill
|
|
458
|
+
(install it first if missing; see "Decision history skill" above).
|
|
459
|
+
The decision block format is that skill's domain; this skill never
|
|
460
|
+
writes decision blocks.
|
|
461
|
+
- A technical disagreement worth recording as claims:
|
|
462
|
+
\`knl-view consensus claim "<statement>"\`, then
|
|
463
|
+
\`knl-view consensus agree <id> <id>\` or
|
|
464
|
+
\`knl-view consensus contradict <id> <id>\`. A claim that lost its
|
|
465
|
+
ground: \`knl-view consensus retract <id> <id>\`.
|
|
466
|
+
`
|