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.
Files changed (64) hide show
  1. package/CHANGELOG.md +149 -93
  2. package/CREDITS.md +14 -14
  3. package/LICENSE.md +76 -76
  4. package/LIMITATIONS.md +33 -23
  5. package/PRIVACY.md +30 -30
  6. package/README.md +170 -117
  7. package/SECURITY.md +78 -46
  8. package/action/post-comment.mjs +94 -89
  9. package/action.yml +62 -62
  10. package/bin/knosky.mjs +279 -105
  11. package/core/CONTRACT.md +70 -70
  12. package/core/append-only-checkpoint.mjs +215 -0
  13. package/core/audit-writer.mjs +317 -0
  14. package/core/benchmark-results.mjs +225 -225
  15. package/core/bundle.mjs +178 -178
  16. package/core/churn.mjs +23 -23
  17. package/core/ci.mjs +268 -268
  18. package/core/comparison.mjs +189 -189
  19. package/core/config.mjs +189 -189
  20. package/core/constants.mjs +13 -13
  21. package/core/contract.mjs +123 -123
  22. package/core/cross-repo.mjs +111 -111
  23. package/core/decision-codes.mjs +92 -0
  24. package/core/destination.mjs +161 -161
  25. package/core/district-classification.mjs +111 -0
  26. package/core/doctor-scorecard.mjs +369 -0
  27. package/core/domain-store.mjs +347 -0
  28. package/core/edges.mjs +43 -43
  29. package/core/escalate.mjs +68 -68
  30. package/core/freshness.mjs +198 -194
  31. package/core/fs-indexer.mjs +218 -218
  32. package/core/key-store.mjs +348 -348
  33. package/core/layout.mjs +46 -46
  34. package/core/ledger.mjs +176 -141
  35. package/core/local-ipc-identity.mjs +500 -0
  36. package/core/lod.mjs +155 -155
  37. package/core/mode-b.mjs +410 -0
  38. package/core/multi-model-benchmark.mjs +405 -405
  39. package/core/net-lockdown.mjs +421 -0
  40. package/core/onboarding.mjs +223 -223
  41. package/core/operator-auth.mjs +317 -0
  42. package/core/overlays.mjs +45 -45
  43. package/core/policy-lattice.mjs +142 -0
  44. package/core/pr-comment.mjs +198 -198
  45. package/core/protocol-spec.mjs +460 -460
  46. package/core/provenance.mjs +320 -0
  47. package/core/retrieve.mjs +63 -63
  48. package/core/route.mjs +304 -304
  49. package/core/schema.mjs +275 -275
  50. package/core/signing-tiers.mjs +1265 -0
  51. package/core/swarm-bench.mjs +106 -0
  52. package/core/swarm-coordinator.mjs +867 -0
  53. package/core/trust-root-rekey.mjs +410 -0
  54. package/mcp/server.mjs +264 -108
  55. package/package.json +56 -46
  56. package/renderer/art/kenney/buildingTiles_sheet.xml +130 -130
  57. package/renderer/art/kenney/cityDetails_sheet.xml +12 -12
  58. package/renderer/art/kenney/landscapeTiles_sheet.xml +129 -129
  59. package/renderer/art/kenney/sheet_allCars.xml +545 -545
  60. package/renderer/build-rich.mjs +43 -43
  61. package/renderer/city.template.html +808 -808
  62. package/ssot/decision-codes.json +133 -0
  63. package/ssot/ladder-l0-l3.md +232 -0
  64. package/ssot/tool-menu.json +130 -0
@@ -1,189 +1,189 @@
1
- // KnoSky naive-vs-guided agent comparison protocol (SAT-458).
2
- // Defines the artifact schema and validators for a single comparison run:
3
- // tokens (in + out), tool-calls, time-to-relevant-file, correctness
4
- // for both a naive agent and an identical task run with KnoSky guidance.
5
- // Pure Node stdlib, ESM — no new deps.
6
-
7
- import { PROTOCOL_VERSION } from './schema.mjs';
8
-
9
- // ---------------------------------------------------------------------------
10
- // Artifact type constant
11
- // ---------------------------------------------------------------------------
12
-
13
- /** @type {string} */
14
- export const COMPARISON_ARTIFACT_TYPE = 'comparison-run';
15
-
16
- // ---------------------------------------------------------------------------
17
- // Internal helpers
18
- // ---------------------------------------------------------------------------
19
-
20
- /**
21
- * Return true when `p` is a relative-safe file path:
22
- * — non-empty string
23
- * — does not start with `/` (Unix absolute) or Windows drive letter
24
- * — contains no `..` path segment
25
- * @param {string} p
26
- * @returns {boolean}
27
- */
28
- function isRelativeSafePath(p) {
29
- if (!p || typeof p !== 'string') return false;
30
- if (p.startsWith('/')) return false;
31
- if (/^[A-Za-z]:[\\\/]/.test(p)) return false;
32
- if (p.split(/[/\\]/).some(s => s === '..')) return false;
33
- return true;
34
- }
35
-
36
- /**
37
- * Validate one metric side object (either `naive` or `guided`).
38
- * Returns an array of violation strings; empty means valid.
39
- *
40
- * @param {unknown} side
41
- * @param {string} label — "naive" or "guided"
42
- * @returns {string[]}
43
- */
44
- function validateSide(side, label) {
45
- const errors = [];
46
-
47
- if (!side || typeof side !== 'object') {
48
- errors.push(`${label} must be an object`);
49
- return errors; // can't go further
50
- }
51
-
52
- // tokens_in: non-negative integer
53
- if (!Number.isInteger(side.tokens_in) || side.tokens_in < 0) {
54
- errors.push(`${label}.tokens_in must be a non-negative integer, got: ${JSON.stringify(side.tokens_in)}`);
55
- }
56
-
57
- // tokens_out: non-negative integer
58
- if (!Number.isInteger(side.tokens_out) || side.tokens_out < 0) {
59
- errors.push(`${label}.tokens_out must be a non-negative integer, got: ${JSON.stringify(side.tokens_out)}`);
60
- }
61
-
62
- // tool_calls: non-negative integer
63
- if (!Number.isInteger(side.tool_calls) || side.tool_calls < 0) {
64
- errors.push(`${label}.tool_calls must be a non-negative integer, got: ${JSON.stringify(side.tool_calls)}`);
65
- }
66
-
67
- // time_to_relevant_file_ms: null (never found) or non-negative number
68
- const ttrf = side.time_to_relevant_file_ms;
69
- if (ttrf !== null && !(typeof ttrf === 'number' && ttrf >= 0)) {
70
- errors.push(
71
- `${label}.time_to_relevant_file_ms must be null or a non-negative number, got: ${JSON.stringify(ttrf)}`,
72
- );
73
- }
74
-
75
- // correct: boolean
76
- if (typeof side.correct !== 'boolean') {
77
- errors.push(`${label}.correct must be a boolean, got: ${JSON.stringify(side.correct)}`);
78
- }
79
-
80
- return errors;
81
- }
82
-
83
- // ---------------------------------------------------------------------------
84
- // makeComparisonRun
85
- // ---------------------------------------------------------------------------
86
-
87
- /**
88
- * Construct a KnoSky `comparison-run` artifact envelope.
89
- *
90
- * @param {object} opts
91
- * @param {string} opts.task_id Short identifier for this task.
92
- * @param {string} opts.task_description Human-readable description of the task.
93
- * @param {string[]} opts.target_files Relative paths to the "relevant" files for this task.
94
- * @param {object} opts.naive Metrics for the naive agent (no KnoSky guidance).
95
- * @param {number} opts.naive.tokens_in Input tokens consumed.
96
- * @param {number} opts.naive.tokens_out Output tokens produced.
97
- * @param {number} opts.naive.tool_calls Total tool/function calls made.
98
- * @param {number|null} opts.naive.time_to_relevant_file_ms ms until first relevant-file hit, or null.
99
- * @param {boolean} opts.naive.correct Whether the agent arrived at the correct answer.
100
- * @param {object} opts.guided Same metric shape for the KnoSky-guided agent.
101
- * @returns {object}
102
- */
103
- export function makeComparisonRun({
104
- task_id,
105
- task_description,
106
- target_files = [],
107
- naive,
108
- guided,
109
- } = {}) {
110
- return {
111
- knosky_protocol: PROTOCOL_VERSION,
112
- artifact_type: COMPARISON_ARTIFACT_TYPE,
113
- advisory: true,
114
- generated_at: new Date().toISOString(),
115
- task_id,
116
- task_description,
117
- target_files,
118
- naive,
119
- guided,
120
- };
121
- }
122
-
123
- // ---------------------------------------------------------------------------
124
- // validateComparisonRun
125
- // ---------------------------------------------------------------------------
126
-
127
- /**
128
- * Validate a KnoSky `comparison-run` document.
129
- * Collects every violation; `ok` is true only when `errors` is empty.
130
- *
131
- * @param {object} doc
132
- * @returns {{ ok: boolean, errors: string[] }}
133
- */
134
- export function validateComparisonRun(doc) {
135
- const errors = [];
136
-
137
- if (!doc || typeof doc !== 'object') {
138
- return { ok: false, errors: ['doc must be an object'] };
139
- }
140
-
141
- if (doc.knosky_protocol !== PROTOCOL_VERSION) {
142
- errors.push(
143
- `knosky_protocol must be "${PROTOCOL_VERSION}", got: ${JSON.stringify(doc.knosky_protocol)}`,
144
- );
145
- }
146
-
147
- if (doc.artifact_type !== COMPARISON_ARTIFACT_TYPE) {
148
- errors.push(
149
- `artifact_type must be "${COMPARISON_ARTIFACT_TYPE}", got: ${JSON.stringify(doc.artifact_type)}`,
150
- );
151
- }
152
-
153
- if (doc.advisory !== true) {
154
- errors.push(`advisory must be true, got: ${JSON.stringify(doc.advisory)}`);
155
- }
156
-
157
- // task_id: non-empty string
158
- if (typeof doc.task_id !== 'string' || doc.task_id.length === 0) {
159
- errors.push(`task_id must be a non-empty string, got: ${JSON.stringify(doc.task_id)}`);
160
- }
161
-
162
- // task_description: non-empty string
163
- if (typeof doc.task_description !== 'string' || doc.task_description.length === 0) {
164
- errors.push(
165
- `task_description must be a non-empty string, got: ${JSON.stringify(doc.task_description)}`,
166
- );
167
- }
168
-
169
- // target_files: non-empty array of relative-safe path strings
170
- if (!Array.isArray(doc.target_files) || doc.target_files.length === 0) {
171
- errors.push('target_files must be a non-empty array');
172
- } else {
173
- for (let i = 0; i < doc.target_files.length; i++) {
174
- const p = doc.target_files[i];
175
- if (typeof p !== 'string' || p.length === 0) {
176
- errors.push(`target_files[${i}] must be a non-empty string`);
177
- } else if (!isRelativeSafePath(p)) {
178
- errors.push(`target_files[${i}] must be a relative path with no ".." segments: ${JSON.stringify(p)}`);
179
- }
180
- }
181
- }
182
-
183
- // naive and guided sides
184
- for (const side of ['naive', 'guided']) {
185
- errors.push(...validateSide(doc[side], side));
186
- }
187
-
188
- return { ok: errors.length === 0, errors };
189
- }
1
+ // KnoSky naive-vs-guided agent comparison protocol (SAT-458).
2
+ // Defines the artifact schema and validators for a single comparison run:
3
+ // tokens (in + out), tool-calls, time-to-relevant-file, correctness
4
+ // for both a naive agent and an identical task run with KnoSky guidance.
5
+ // Pure Node stdlib, ESM — no new deps.
6
+
7
+ import { PROTOCOL_VERSION } from './schema.mjs';
8
+
9
+ // ---------------------------------------------------------------------------
10
+ // Artifact type constant
11
+ // ---------------------------------------------------------------------------
12
+
13
+ /** @type {string} */
14
+ export const COMPARISON_ARTIFACT_TYPE = 'comparison-run';
15
+
16
+ // ---------------------------------------------------------------------------
17
+ // Internal helpers
18
+ // ---------------------------------------------------------------------------
19
+
20
+ /**
21
+ * Return true when `p` is a relative-safe file path:
22
+ * — non-empty string
23
+ * — does not start with `/` (Unix absolute) or Windows drive letter
24
+ * — contains no `..` path segment
25
+ * @param {string} p
26
+ * @returns {boolean}
27
+ */
28
+ function isRelativeSafePath(p) {
29
+ if (!p || typeof p !== 'string') return false;
30
+ if (p.startsWith('/')) return false;
31
+ if (/^[A-Za-z]:[\\\/]/.test(p)) return false;
32
+ if (p.split(/[/\\]/).some(s => s === '..')) return false;
33
+ return true;
34
+ }
35
+
36
+ /**
37
+ * Validate one metric side object (either `naive` or `guided`).
38
+ * Returns an array of violation strings; empty means valid.
39
+ *
40
+ * @param {unknown} side
41
+ * @param {string} label — "naive" or "guided"
42
+ * @returns {string[]}
43
+ */
44
+ function validateSide(side, label) {
45
+ const errors = [];
46
+
47
+ if (!side || typeof side !== 'object') {
48
+ errors.push(`${label} must be an object`);
49
+ return errors; // can't go further
50
+ }
51
+
52
+ // tokens_in: non-negative integer
53
+ if (!Number.isInteger(side.tokens_in) || side.tokens_in < 0) {
54
+ errors.push(`${label}.tokens_in must be a non-negative integer, got: ${JSON.stringify(side.tokens_in)}`);
55
+ }
56
+
57
+ // tokens_out: non-negative integer
58
+ if (!Number.isInteger(side.tokens_out) || side.tokens_out < 0) {
59
+ errors.push(`${label}.tokens_out must be a non-negative integer, got: ${JSON.stringify(side.tokens_out)}`);
60
+ }
61
+
62
+ // tool_calls: non-negative integer
63
+ if (!Number.isInteger(side.tool_calls) || side.tool_calls < 0) {
64
+ errors.push(`${label}.tool_calls must be a non-negative integer, got: ${JSON.stringify(side.tool_calls)}`);
65
+ }
66
+
67
+ // time_to_relevant_file_ms: null (never found) or non-negative number
68
+ const ttrf = side.time_to_relevant_file_ms;
69
+ if (ttrf !== null && !(typeof ttrf === 'number' && ttrf >= 0)) {
70
+ errors.push(
71
+ `${label}.time_to_relevant_file_ms must be null or a non-negative number, got: ${JSON.stringify(ttrf)}`,
72
+ );
73
+ }
74
+
75
+ // correct: boolean
76
+ if (typeof side.correct !== 'boolean') {
77
+ errors.push(`${label}.correct must be a boolean, got: ${JSON.stringify(side.correct)}`);
78
+ }
79
+
80
+ return errors;
81
+ }
82
+
83
+ // ---------------------------------------------------------------------------
84
+ // makeComparisonRun
85
+ // ---------------------------------------------------------------------------
86
+
87
+ /**
88
+ * Construct a KnoSky `comparison-run` artifact envelope.
89
+ *
90
+ * @param {object} opts
91
+ * @param {string} opts.task_id Short identifier for this task.
92
+ * @param {string} opts.task_description Human-readable description of the task.
93
+ * @param {string[]} opts.target_files Relative paths to the "relevant" files for this task.
94
+ * @param {object} opts.naive Metrics for the naive agent (no KnoSky guidance).
95
+ * @param {number} opts.naive.tokens_in Input tokens consumed.
96
+ * @param {number} opts.naive.tokens_out Output tokens produced.
97
+ * @param {number} opts.naive.tool_calls Total tool/function calls made.
98
+ * @param {number|null} opts.naive.time_to_relevant_file_ms ms until first relevant-file hit, or null.
99
+ * @param {boolean} opts.naive.correct Whether the agent arrived at the correct answer.
100
+ * @param {object} opts.guided Same metric shape for the KnoSky-guided agent.
101
+ * @returns {object}
102
+ */
103
+ export function makeComparisonRun({
104
+ task_id,
105
+ task_description,
106
+ target_files = [],
107
+ naive,
108
+ guided,
109
+ } = {}) {
110
+ return {
111
+ knosky_protocol: PROTOCOL_VERSION,
112
+ artifact_type: COMPARISON_ARTIFACT_TYPE,
113
+ advisory: true,
114
+ generated_at: new Date().toISOString(),
115
+ task_id,
116
+ task_description,
117
+ target_files,
118
+ naive,
119
+ guided,
120
+ };
121
+ }
122
+
123
+ // ---------------------------------------------------------------------------
124
+ // validateComparisonRun
125
+ // ---------------------------------------------------------------------------
126
+
127
+ /**
128
+ * Validate a KnoSky `comparison-run` document.
129
+ * Collects every violation; `ok` is true only when `errors` is empty.
130
+ *
131
+ * @param {object} doc
132
+ * @returns {{ ok: boolean, errors: string[] }}
133
+ */
134
+ export function validateComparisonRun(doc) {
135
+ const errors = [];
136
+
137
+ if (!doc || typeof doc !== 'object') {
138
+ return { ok: false, errors: ['doc must be an object'] };
139
+ }
140
+
141
+ if (doc.knosky_protocol !== PROTOCOL_VERSION) {
142
+ errors.push(
143
+ `knosky_protocol must be "${PROTOCOL_VERSION}", got: ${JSON.stringify(doc.knosky_protocol)}`,
144
+ );
145
+ }
146
+
147
+ if (doc.artifact_type !== COMPARISON_ARTIFACT_TYPE) {
148
+ errors.push(
149
+ `artifact_type must be "${COMPARISON_ARTIFACT_TYPE}", got: ${JSON.stringify(doc.artifact_type)}`,
150
+ );
151
+ }
152
+
153
+ if (doc.advisory !== true) {
154
+ errors.push(`advisory must be true, got: ${JSON.stringify(doc.advisory)}`);
155
+ }
156
+
157
+ // task_id: non-empty string
158
+ if (typeof doc.task_id !== 'string' || doc.task_id.length === 0) {
159
+ errors.push(`task_id must be a non-empty string, got: ${JSON.stringify(doc.task_id)}`);
160
+ }
161
+
162
+ // task_description: non-empty string
163
+ if (typeof doc.task_description !== 'string' || doc.task_description.length === 0) {
164
+ errors.push(
165
+ `task_description must be a non-empty string, got: ${JSON.stringify(doc.task_description)}`,
166
+ );
167
+ }
168
+
169
+ // target_files: non-empty array of relative-safe path strings
170
+ if (!Array.isArray(doc.target_files) || doc.target_files.length === 0) {
171
+ errors.push('target_files must be a non-empty array');
172
+ } else {
173
+ for (let i = 0; i < doc.target_files.length; i++) {
174
+ const p = doc.target_files[i];
175
+ if (typeof p !== 'string' || p.length === 0) {
176
+ errors.push(`target_files[${i}] must be a non-empty string`);
177
+ } else if (!isRelativeSafePath(p)) {
178
+ errors.push(`target_files[${i}] must be a relative path with no ".." segments: ${JSON.stringify(p)}`);
179
+ }
180
+ }
181
+ }
182
+
183
+ // naive and guided sides
184
+ for (const side of ['naive', 'guided']) {
185
+ errors.push(...validateSide(doc[side], side));
186
+ }
187
+
188
+ return { ok: errors.length === 0, errors };
189
+ }