knosky 0.6.3 → 0.7.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/CHANGELOG.md +149 -93
- package/CREDITS.md +14 -14
- package/LICENSE.md +76 -76
- package/LIMITATIONS.md +33 -23
- package/PRIVACY.md +30 -30
- package/README.md +170 -117
- package/SECURITY.md +78 -46
- package/action/post-comment.mjs +94 -89
- package/action.yml +62 -62
- package/bin/knosky.mjs +279 -105
- package/core/CONTRACT.md +70 -70
- package/core/append-only-checkpoint.mjs +215 -0
- package/core/audit-writer.mjs +317 -0
- package/core/benchmark-results.mjs +225 -225
- package/core/bundle.mjs +178 -178
- package/core/churn.mjs +23 -23
- package/core/ci.mjs +268 -268
- package/core/comparison.mjs +189 -189
- package/core/config.mjs +189 -189
- package/core/constants.mjs +13 -13
- package/core/contract.mjs +123 -123
- package/core/cross-repo.mjs +111 -111
- package/core/decision-codes.mjs +92 -0
- package/core/destination.mjs +161 -161
- package/core/district-classification.mjs +111 -0
- package/core/doctor-scorecard.mjs +369 -0
- package/core/domain-store.mjs +347 -0
- package/core/edges.mjs +43 -43
- package/core/escalate.mjs +68 -68
- package/core/freshness.mjs +198 -194
- package/core/fs-indexer.mjs +218 -218
- package/core/key-store.mjs +348 -348
- package/core/layout.mjs +46 -46
- package/core/ledger.mjs +176 -141
- package/core/local-ipc-identity.mjs +500 -0
- package/core/lod.mjs +155 -155
- package/core/mode-b.mjs +410 -0
- package/core/multi-model-benchmark.mjs +405 -405
- package/core/net-lockdown.mjs +421 -0
- package/core/onboarding.mjs +223 -223
- package/core/operator-auth.mjs +317 -0
- package/core/overlays.mjs +45 -45
- package/core/policy-lattice.mjs +142 -0
- package/core/pr-comment.mjs +198 -198
- package/core/protocol-spec.mjs +460 -460
- package/core/provenance.mjs +320 -0
- package/core/retrieve.mjs +63 -63
- package/core/route.mjs +304 -304
- package/core/schema.mjs +275 -275
- package/core/signing-tiers.mjs +1265 -0
- package/core/swarm-bench.mjs +106 -0
- package/core/swarm-coordinator.mjs +867 -0
- package/core/trust-root-rekey.mjs +410 -0
- package/mcp/server.mjs +264 -108
- package/package.json +56 -46
- package/renderer/art/kenney/buildingTiles_sheet.xml +130 -130
- package/renderer/art/kenney/cityDetails_sheet.xml +12 -12
- package/renderer/art/kenney/landscapeTiles_sheet.xml +129 -129
- package/renderer/art/kenney/sheet_allCars.xml +545 -545
- package/renderer/build-rich.mjs +43 -43
- package/renderer/city.template.html +808 -808
- package/ssot/decision-codes.json +133 -0
- package/ssot/ladder-l0-l3.md +232 -0
- package/ssot/tool-menu.json +130 -0
package/core/onboarding.mjs
CHANGED
|
@@ -1,223 +1,223 @@
|
|
|
1
|
-
// KnoSky generic onboarding contract (SAT-463).
|
|
2
|
-
// Model-agnostic system-prompt artifact: enumerates every available tool,
|
|
3
|
-
// hard usage rules, and starter examples — no model-specific formatting or IDs.
|
|
4
|
-
// Pure data + make/validate/render. No I/O, no external imports.
|
|
5
|
-
|
|
6
|
-
export const ONBOARDING_SCHEMA_VERSION = '1.0';
|
|
7
|
-
|
|
8
|
-
// ---------------------------------------------------------------------------
|
|
9
|
-
// Tool catalogue — must stay in sync with mcp/server.mjs registrations.
|
|
10
|
-
// ---------------------------------------------------------------------------
|
|
11
|
-
|
|
12
|
-
/** @type {Array<{ name: string, description: string, params: Record<string,string>, example: string }>} */
|
|
13
|
-
export const TOOL_DEFS = [
|
|
14
|
-
{
|
|
15
|
-
name: 'kc_search',
|
|
16
|
-
description:
|
|
17
|
-
'Search the knowledge index by keywords. Returns ranked items (title, summary, category) ' +
|
|
18
|
-
'each with a provenance citation (source path + revision) that links back to the live file. ' +
|
|
19
|
-
'Use for "where does X live / what was decided about Y / how does this connect". ' +
|
|
20
|
-
'Navigation, not full-text code search.',
|
|
21
|
-
params: {
|
|
22
|
-
query: 'keywords (string, max 500 chars)',
|
|
23
|
-
limit: 'max results (integer 1–50, default 10)',
|
|
24
|
-
category: 'restrict to a category id (optional)',
|
|
25
|
-
},
|
|
26
|
-
example: 'kc_search("authentication")',
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
name: 'kc_get_node',
|
|
30
|
-
description:
|
|
31
|
-
'Fetch a single indexed item by id (title, summary, category, kind) with its provenance citation.',
|
|
32
|
-
params: { id: 'node id, e.g. fs:src/index.ts (string, max 400 chars)' },
|
|
33
|
-
example: 'kc_get_node("fs:src/auth.js")',
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
name: 'kc_list_categories',
|
|
37
|
-
description: 'List the knowledge categories (city districts) with item counts.',
|
|
38
|
-
params: {},
|
|
39
|
-
example: 'kc_list_categories()',
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
name: 'kc_get_provenance',
|
|
43
|
-
description:
|
|
44
|
-
'Get the citation for an item: the live source ref + revision, plus its links to related items.',
|
|
45
|
-
params: { id: 'node id (string, max 400 chars)' },
|
|
46
|
-
example: 'kc_get_provenance("fs:src/auth.js")',
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
name: 'kc_related',
|
|
50
|
-
description:
|
|
51
|
-
'How a file connects to others: which files it imports (out-edges), which import it (in-edges), ' +
|
|
52
|
-
'and its recent-change (churn) signal. File-level structure with citations, not code analysis.',
|
|
53
|
-
params: { id: 'node id, e.g. fs:src/auth.js (string, max 400 chars)' },
|
|
54
|
-
example: 'kc_related("fs:src/auth.js")',
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
name: 'kc_route',
|
|
58
|
-
description:
|
|
59
|
-
'Advisory, metadata-only route through the repo towards a destination. Returns ranked ' +
|
|
60
|
-
'waypoints (where to look first), alternates, related tests, related docs, caveats, and a ' +
|
|
61
|
-
'confidence score. Structural navigation only — does NOT read or analyse code meaning.',
|
|
62
|
-
params: {
|
|
63
|
-
destination:
|
|
64
|
-
'navigation target — file:src/auth.js, folder:src/auth, or keywords (string, max 400 chars)',
|
|
65
|
-
limit: 'max route entries (integer 1–20, default 8)',
|
|
66
|
-
},
|
|
67
|
-
example: 'kc_route("file:src/auth.js")',
|
|
68
|
-
},
|
|
69
|
-
];
|
|
70
|
-
|
|
71
|
-
// ---------------------------------------------------------------------------
|
|
72
|
-
// Hard usage rules — model-agnostic, applies to every deployment.
|
|
73
|
-
// ---------------------------------------------------------------------------
|
|
74
|
-
|
|
75
|
-
export const CONSTRAINTS = [
|
|
76
|
-
'All results are advisory-only — verify before acting on any waypoint or route.',
|
|
77
|
-
'KnoSky reads metadata and pointers only; it never reads or uploads full file bodies.',
|
|
78
|
-
'All paths in results are repo-relative (never absolute). Do not construct absolute paths from them.',
|
|
79
|
-
'Citations (provenance) reference the live file; the index may be stale — treat confidence scores accordingly.',
|
|
80
|
-
'Secret and PII patterns are scrubbed from projections; do not assume scrubbing is exhaustive (see LIMITATIONS.md).',
|
|
81
|
-
'kc_route is structural / file-level only — it does not understand code semantics.',
|
|
82
|
-
];
|
|
83
|
-
|
|
84
|
-
// ---------------------------------------------------------------------------
|
|
85
|
-
// Starter prompts — illustrative, not exhaustive.
|
|
86
|
-
// ---------------------------------------------------------------------------
|
|
87
|
-
|
|
88
|
-
export const EXAMPLES = [
|
|
89
|
-
'Using KnoSky, where does authentication live in this repo?',
|
|
90
|
-
'Using KnoSky, what are the entry points of this project?',
|
|
91
|
-
'Using KnoSky, which files should I read to understand billing?',
|
|
92
|
-
'Using KnoSky, list the categories in this codebase.',
|
|
93
|
-
'Using KnoSky, what connects to src/auth.js?',
|
|
94
|
-
];
|
|
95
|
-
|
|
96
|
-
// ---------------------------------------------------------------------------
|
|
97
|
-
// makeOnboardingDoc — construct a KnoSky `onboarding` artifact envelope.
|
|
98
|
-
// ---------------------------------------------------------------------------
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Construct a KnoSky `onboarding` artifact envelope.
|
|
102
|
-
*
|
|
103
|
-
* @param {object} [opts]
|
|
104
|
-
* @param {string} [opts.generatedAt] ISO-8601 timestamp; defaults to now.
|
|
105
|
-
* @returns {object}
|
|
106
|
-
*/
|
|
107
|
-
export function makeOnboardingDoc({ generatedAt } = {}) {
|
|
108
|
-
return {
|
|
109
|
-
knosky_protocol: ONBOARDING_SCHEMA_VERSION,
|
|
110
|
-
artifact_type: 'onboarding',
|
|
111
|
-
advisory: true,
|
|
112
|
-
generated_at: generatedAt || new Date().toISOString(),
|
|
113
|
-
tools: TOOL_DEFS.map(t => ({ ...t, params: { ...t.params } })),
|
|
114
|
-
constraints: [...CONSTRAINTS],
|
|
115
|
-
examples: [...EXAMPLES],
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// ---------------------------------------------------------------------------
|
|
120
|
-
// validateOnboardingDoc — collect all constraint violations; ok iff empty.
|
|
121
|
-
// ---------------------------------------------------------------------------
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Validate a KnoSky `onboarding` document.
|
|
125
|
-
* Collects every violation; `ok` is true only when `errors` is empty.
|
|
126
|
-
*
|
|
127
|
-
* @param {object} doc
|
|
128
|
-
* @returns {{ ok: boolean, errors: string[] }}
|
|
129
|
-
*/
|
|
130
|
-
export function validateOnboardingDoc(doc) {
|
|
131
|
-
const errors = [];
|
|
132
|
-
|
|
133
|
-
if (!doc || typeof doc !== 'object') {
|
|
134
|
-
return { ok: false, errors: ['doc is not an object'] };
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (doc.knosky_protocol !== '1.0') {
|
|
138
|
-
errors.push(`knosky_protocol must be "1.0", got: ${JSON.stringify(doc.knosky_protocol)}`);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (doc.artifact_type !== 'onboarding') {
|
|
142
|
-
errors.push(`artifact_type must be "onboarding", got: ${JSON.stringify(doc.artifact_type)}`);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (doc.advisory !== true) {
|
|
146
|
-
errors.push(`advisory must be true, got: ${JSON.stringify(doc.advisory)}`);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (!Array.isArray(doc.tools) || doc.tools.length === 0) {
|
|
150
|
-
errors.push('tools must be a non-empty array');
|
|
151
|
-
} else {
|
|
152
|
-
for (let i = 0; i < doc.tools.length; i++) {
|
|
153
|
-
const t = doc.tools[i];
|
|
154
|
-
if (!t || typeof t !== 'object') {
|
|
155
|
-
errors.push(`tools[${i}] must be an object`);
|
|
156
|
-
continue;
|
|
157
|
-
}
|
|
158
|
-
if (typeof t.name !== 'string' || t.name.length === 0) {
|
|
159
|
-
errors.push(`tools[${i}].name must be a non-empty string`);
|
|
160
|
-
}
|
|
161
|
-
if (typeof t.description !== 'string' || t.description.length === 0) {
|
|
162
|
-
errors.push(`tools[${i}].description must be a non-empty string`);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
if (!Array.isArray(doc.constraints)) {
|
|
168
|
-
errors.push('constraints must be an array');
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (!Array.isArray(doc.examples)) {
|
|
172
|
-
errors.push('examples must be an array');
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return { ok: errors.length === 0, errors };
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// ---------------------------------------------------------------------------
|
|
179
|
-
// renderOnboardingText — plain text suitable for any model system prompt.
|
|
180
|
-
// ---------------------------------------------------------------------------
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Render a KnoSky `onboarding` document as plain text.
|
|
184
|
-
* Suitable for pasting directly into any model system prompt.
|
|
185
|
-
*
|
|
186
|
-
* @param {object} doc Validated onboarding document.
|
|
187
|
-
* @returns {string}
|
|
188
|
-
*/
|
|
189
|
-
export function renderOnboardingText(doc) {
|
|
190
|
-
const lines = [];
|
|
191
|
-
|
|
192
|
-
lines.push('# KnoSky — onboarding');
|
|
193
|
-
lines.push('');
|
|
194
|
-
lines.push(
|
|
195
|
-
'KnoSky is a local, offline knowledge city. It turns a repo or docs folder into a navigable ' +
|
|
196
|
-
'index of pointers and projections. It reads metadata only — it never uploads code.',
|
|
197
|
-
);
|
|
198
|
-
lines.push('');
|
|
199
|
-
|
|
200
|
-
lines.push('## Available tools');
|
|
201
|
-
lines.push('');
|
|
202
|
-
for (const t of (doc.tools || [])) {
|
|
203
|
-
lines.push(`### ${t.name}`);
|
|
204
|
-
lines.push(t.description || '');
|
|
205
|
-
if (t.example) lines.push(`Example: ${t.example}`);
|
|
206
|
-
lines.push('');
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
lines.push('## Rules');
|
|
210
|
-
lines.push('');
|
|
211
|
-
for (const c of (doc.constraints || [])) {
|
|
212
|
-
lines.push(`- ${c}`);
|
|
213
|
-
}
|
|
214
|
-
lines.push('');
|
|
215
|
-
|
|
216
|
-
lines.push('## Starter prompts');
|
|
217
|
-
lines.push('');
|
|
218
|
-
for (const e of (doc.examples || [])) {
|
|
219
|
-
lines.push(`- ${e}`);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return lines.join('\n');
|
|
223
|
-
}
|
|
1
|
+
// KnoSky generic onboarding contract (SAT-463).
|
|
2
|
+
// Model-agnostic system-prompt artifact: enumerates every available tool,
|
|
3
|
+
// hard usage rules, and starter examples — no model-specific formatting or IDs.
|
|
4
|
+
// Pure data + make/validate/render. No I/O, no external imports.
|
|
5
|
+
|
|
6
|
+
export const ONBOARDING_SCHEMA_VERSION = '1.0';
|
|
7
|
+
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Tool catalogue — must stay in sync with mcp/server.mjs registrations.
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
/** @type {Array<{ name: string, description: string, params: Record<string,string>, example: string }>} */
|
|
13
|
+
export const TOOL_DEFS = [
|
|
14
|
+
{
|
|
15
|
+
name: 'kc_search',
|
|
16
|
+
description:
|
|
17
|
+
'Search the knowledge index by keywords. Returns ranked items (title, summary, category) ' +
|
|
18
|
+
'each with a provenance citation (source path + revision) that links back to the live file. ' +
|
|
19
|
+
'Use for "where does X live / what was decided about Y / how does this connect". ' +
|
|
20
|
+
'Navigation, not full-text code search.',
|
|
21
|
+
params: {
|
|
22
|
+
query: 'keywords (string, max 500 chars)',
|
|
23
|
+
limit: 'max results (integer 1–50, default 10)',
|
|
24
|
+
category: 'restrict to a category id (optional)',
|
|
25
|
+
},
|
|
26
|
+
example: 'kc_search("authentication")',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'kc_get_node',
|
|
30
|
+
description:
|
|
31
|
+
'Fetch a single indexed item by id (title, summary, category, kind) with its provenance citation.',
|
|
32
|
+
params: { id: 'node id, e.g. fs:src/index.ts (string, max 400 chars)' },
|
|
33
|
+
example: 'kc_get_node("fs:src/auth.js")',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'kc_list_categories',
|
|
37
|
+
description: 'List the knowledge categories (city districts) with item counts.',
|
|
38
|
+
params: {},
|
|
39
|
+
example: 'kc_list_categories()',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: 'kc_get_provenance',
|
|
43
|
+
description:
|
|
44
|
+
'Get the citation for an item: the live source ref + revision, plus its links to related items.',
|
|
45
|
+
params: { id: 'node id (string, max 400 chars)' },
|
|
46
|
+
example: 'kc_get_provenance("fs:src/auth.js")',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: 'kc_related',
|
|
50
|
+
description:
|
|
51
|
+
'How a file connects to others: which files it imports (out-edges), which import it (in-edges), ' +
|
|
52
|
+
'and its recent-change (churn) signal. File-level structure with citations, not code analysis.',
|
|
53
|
+
params: { id: 'node id, e.g. fs:src/auth.js (string, max 400 chars)' },
|
|
54
|
+
example: 'kc_related("fs:src/auth.js")',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'kc_route',
|
|
58
|
+
description:
|
|
59
|
+
'Advisory, metadata-only route through the repo towards a destination. Returns ranked ' +
|
|
60
|
+
'waypoints (where to look first), alternates, related tests, related docs, caveats, and a ' +
|
|
61
|
+
'confidence score. Structural navigation only — does NOT read or analyse code meaning.',
|
|
62
|
+
params: {
|
|
63
|
+
destination:
|
|
64
|
+
'navigation target — file:src/auth.js, folder:src/auth, or keywords (string, max 400 chars)',
|
|
65
|
+
limit: 'max route entries (integer 1–20, default 8)',
|
|
66
|
+
},
|
|
67
|
+
example: 'kc_route("file:src/auth.js")',
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// Hard usage rules — model-agnostic, applies to every deployment.
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
export const CONSTRAINTS = [
|
|
76
|
+
'All results are advisory-only — verify before acting on any waypoint or route.',
|
|
77
|
+
'KnoSky reads metadata and pointers only; it never reads or uploads full file bodies.',
|
|
78
|
+
'All paths in results are repo-relative (never absolute). Do not construct absolute paths from them.',
|
|
79
|
+
'Citations (provenance) reference the live file; the index may be stale — treat confidence scores accordingly.',
|
|
80
|
+
'Secret and PII patterns are scrubbed from projections; do not assume scrubbing is exhaustive (see LIMITATIONS.md).',
|
|
81
|
+
'kc_route is structural / file-level only — it does not understand code semantics.',
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
// Starter prompts — illustrative, not exhaustive.
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
|
|
88
|
+
export const EXAMPLES = [
|
|
89
|
+
'Using KnoSky, where does authentication live in this repo?',
|
|
90
|
+
'Using KnoSky, what are the entry points of this project?',
|
|
91
|
+
'Using KnoSky, which files should I read to understand billing?',
|
|
92
|
+
'Using KnoSky, list the categories in this codebase.',
|
|
93
|
+
'Using KnoSky, what connects to src/auth.js?',
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// makeOnboardingDoc — construct a KnoSky `onboarding` artifact envelope.
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Construct a KnoSky `onboarding` artifact envelope.
|
|
102
|
+
*
|
|
103
|
+
* @param {object} [opts]
|
|
104
|
+
* @param {string} [opts.generatedAt] ISO-8601 timestamp; defaults to now.
|
|
105
|
+
* @returns {object}
|
|
106
|
+
*/
|
|
107
|
+
export function makeOnboardingDoc({ generatedAt } = {}) {
|
|
108
|
+
return {
|
|
109
|
+
knosky_protocol: ONBOARDING_SCHEMA_VERSION,
|
|
110
|
+
artifact_type: 'onboarding',
|
|
111
|
+
advisory: true,
|
|
112
|
+
generated_at: generatedAt || new Date().toISOString(),
|
|
113
|
+
tools: TOOL_DEFS.map(t => ({ ...t, params: { ...t.params } })),
|
|
114
|
+
constraints: [...CONSTRAINTS],
|
|
115
|
+
examples: [...EXAMPLES],
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
// validateOnboardingDoc — collect all constraint violations; ok iff empty.
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Validate a KnoSky `onboarding` document.
|
|
125
|
+
* Collects every violation; `ok` is true only when `errors` is empty.
|
|
126
|
+
*
|
|
127
|
+
* @param {object} doc
|
|
128
|
+
* @returns {{ ok: boolean, errors: string[] }}
|
|
129
|
+
*/
|
|
130
|
+
export function validateOnboardingDoc(doc) {
|
|
131
|
+
const errors = [];
|
|
132
|
+
|
|
133
|
+
if (!doc || typeof doc !== 'object') {
|
|
134
|
+
return { ok: false, errors: ['doc is not an object'] };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (doc.knosky_protocol !== '1.0') {
|
|
138
|
+
errors.push(`knosky_protocol must be "1.0", got: ${JSON.stringify(doc.knosky_protocol)}`);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (doc.artifact_type !== 'onboarding') {
|
|
142
|
+
errors.push(`artifact_type must be "onboarding", got: ${JSON.stringify(doc.artifact_type)}`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (doc.advisory !== true) {
|
|
146
|
+
errors.push(`advisory must be true, got: ${JSON.stringify(doc.advisory)}`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (!Array.isArray(doc.tools) || doc.tools.length === 0) {
|
|
150
|
+
errors.push('tools must be a non-empty array');
|
|
151
|
+
} else {
|
|
152
|
+
for (let i = 0; i < doc.tools.length; i++) {
|
|
153
|
+
const t = doc.tools[i];
|
|
154
|
+
if (!t || typeof t !== 'object') {
|
|
155
|
+
errors.push(`tools[${i}] must be an object`);
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (typeof t.name !== 'string' || t.name.length === 0) {
|
|
159
|
+
errors.push(`tools[${i}].name must be a non-empty string`);
|
|
160
|
+
}
|
|
161
|
+
if (typeof t.description !== 'string' || t.description.length === 0) {
|
|
162
|
+
errors.push(`tools[${i}].description must be a non-empty string`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (!Array.isArray(doc.constraints)) {
|
|
168
|
+
errors.push('constraints must be an array');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (!Array.isArray(doc.examples)) {
|
|
172
|
+
errors.push('examples must be an array');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return { ok: errors.length === 0, errors };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ---------------------------------------------------------------------------
|
|
179
|
+
// renderOnboardingText — plain text suitable for any model system prompt.
|
|
180
|
+
// ---------------------------------------------------------------------------
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Render a KnoSky `onboarding` document as plain text.
|
|
184
|
+
* Suitable for pasting directly into any model system prompt.
|
|
185
|
+
*
|
|
186
|
+
* @param {object} doc Validated onboarding document.
|
|
187
|
+
* @returns {string}
|
|
188
|
+
*/
|
|
189
|
+
export function renderOnboardingText(doc) {
|
|
190
|
+
const lines = [];
|
|
191
|
+
|
|
192
|
+
lines.push('# KnoSky — onboarding');
|
|
193
|
+
lines.push('');
|
|
194
|
+
lines.push(
|
|
195
|
+
'KnoSky is a local, offline knowledge city. It turns a repo or docs folder into a navigable ' +
|
|
196
|
+
'index of pointers and projections. It reads metadata only — it never uploads code.',
|
|
197
|
+
);
|
|
198
|
+
lines.push('');
|
|
199
|
+
|
|
200
|
+
lines.push('## Available tools');
|
|
201
|
+
lines.push('');
|
|
202
|
+
for (const t of (doc.tools || [])) {
|
|
203
|
+
lines.push(`### ${t.name}`);
|
|
204
|
+
lines.push(t.description || '');
|
|
205
|
+
if (t.example) lines.push(`Example: ${t.example}`);
|
|
206
|
+
lines.push('');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
lines.push('## Rules');
|
|
210
|
+
lines.push('');
|
|
211
|
+
for (const c of (doc.constraints || [])) {
|
|
212
|
+
lines.push(`- ${c}`);
|
|
213
|
+
}
|
|
214
|
+
lines.push('');
|
|
215
|
+
|
|
216
|
+
lines.push('## Starter prompts');
|
|
217
|
+
lines.push('');
|
|
218
|
+
for (const e of (doc.examples || [])) {
|
|
219
|
+
lines.push(`- ${e}`);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return lines.join('\n');
|
|
223
|
+
}
|