@aisy/core 0.1.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 (270) hide show
  1. package/LICENSE +202 -0
  2. package/dist/agent-loop/index.d.ts +4 -0
  3. package/dist/agent-loop/index.d.ts.map +1 -0
  4. package/dist/agent-loop/index.js +352 -0
  5. package/dist/agent-loop/index.js.map +1 -0
  6. package/dist/agent-loop/types.d.ts +183 -0
  7. package/dist/agent-loop/types.d.ts.map +1 -0
  8. package/dist/agent-loop/types.js +3 -0
  9. package/dist/agent-loop/types.js.map +1 -0
  10. package/dist/bin/aisy.d.ts +3 -0
  11. package/dist/bin/aisy.d.ts.map +1 -0
  12. package/dist/bin/aisy.js +14 -0
  13. package/dist/bin/aisy.js.map +1 -0
  14. package/dist/cli/index.d.ts +17 -0
  15. package/dist/cli/index.d.ts.map +1 -0
  16. package/dist/cli/index.js +114 -0
  17. package/dist/cli/index.js.map +1 -0
  18. package/dist/context-engine/index.d.ts +4 -0
  19. package/dist/context-engine/index.d.ts.map +1 -0
  20. package/dist/context-engine/index.js +126 -0
  21. package/dist/context-engine/index.js.map +1 -0
  22. package/dist/context-engine/types.d.ts +54 -0
  23. package/dist/context-engine/types.d.ts.map +1 -0
  24. package/dist/context-engine/types.js +4 -0
  25. package/dist/context-engine/types.js.map +1 -0
  26. package/dist/eval/index.d.ts +20 -0
  27. package/dist/eval/index.d.ts.map +1 -0
  28. package/dist/eval/index.js +128 -0
  29. package/dist/eval/index.js.map +1 -0
  30. package/dist/eval/types.d.ts +62 -0
  31. package/dist/eval/types.d.ts.map +1 -0
  32. package/dist/eval/types.js +17 -0
  33. package/dist/eval/types.js.map +1 -0
  34. package/dist/gateway/index.d.ts +5 -0
  35. package/dist/gateway/index.d.ts.map +1 -0
  36. package/dist/gateway/index.js +288 -0
  37. package/dist/gateway/index.js.map +1 -0
  38. package/dist/gateway/types.d.ts +194 -0
  39. package/dist/gateway/types.d.ts.map +1 -0
  40. package/dist/gateway/types.js +94 -0
  41. package/dist/gateway/types.js.map +1 -0
  42. package/dist/goals/index.d.ts +11 -0
  43. package/dist/goals/index.d.ts.map +1 -0
  44. package/dist/goals/index.js +21 -0
  45. package/dist/goals/index.js.map +1 -0
  46. package/dist/goals/types.d.ts +47 -0
  47. package/dist/goals/types.d.ts.map +1 -0
  48. package/dist/goals/types.js +5 -0
  49. package/dist/goals/types.js.map +1 -0
  50. package/dist/index.d.ts +56 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +50 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/mcp/index.d.ts +5 -0
  55. package/dist/mcp/index.d.ts.map +1 -0
  56. package/dist/mcp/index.js +215 -0
  57. package/dist/mcp/index.js.map +1 -0
  58. package/dist/mcp/types.d.ts +148 -0
  59. package/dist/mcp/types.d.ts.map +1 -0
  60. package/dist/mcp/types.js +4 -0
  61. package/dist/mcp/types.js.map +1 -0
  62. package/dist/memory/index.d.ts +6 -0
  63. package/dist/memory/index.d.ts.map +1 -0
  64. package/dist/memory/index.js +419 -0
  65. package/dist/memory/index.js.map +1 -0
  66. package/dist/memory/types.d.ts +131 -0
  67. package/dist/memory/types.d.ts.map +1 -0
  68. package/dist/memory/types.js +33 -0
  69. package/dist/memory/types.js.map +1 -0
  70. package/dist/nightly/index.d.ts +4 -0
  71. package/dist/nightly/index.d.ts.map +1 -0
  72. package/dist/nightly/index.js +470 -0
  73. package/dist/nightly/index.js.map +1 -0
  74. package/dist/nightly/types.d.ts +326 -0
  75. package/dist/nightly/types.d.ts.map +1 -0
  76. package/dist/nightly/types.js +3 -0
  77. package/dist/nightly/types.js.map +1 -0
  78. package/dist/observability/index.d.ts +11 -0
  79. package/dist/observability/index.d.ts.map +1 -0
  80. package/dist/observability/index.js +396 -0
  81. package/dist/observability/index.js.map +1 -0
  82. package/dist/observability/types.d.ts +139 -0
  83. package/dist/observability/types.d.ts.map +1 -0
  84. package/dist/observability/types.js +4 -0
  85. package/dist/observability/types.js.map +1 -0
  86. package/dist/onboarding/index.d.ts +16 -0
  87. package/dist/onboarding/index.d.ts.map +1 -0
  88. package/dist/onboarding/index.js +787 -0
  89. package/dist/onboarding/index.js.map +1 -0
  90. package/dist/onboarding/interactive.d.ts +23 -0
  91. package/dist/onboarding/interactive.d.ts.map +1 -0
  92. package/dist/onboarding/interactive.js +45 -0
  93. package/dist/onboarding/interactive.js.map +1 -0
  94. package/dist/onboarding/types.d.ts +388 -0
  95. package/dist/onboarding/types.d.ts.map +1 -0
  96. package/dist/onboarding/types.js +35 -0
  97. package/dist/onboarding/types.js.map +1 -0
  98. package/dist/orchestration/index.d.ts +8 -0
  99. package/dist/orchestration/index.d.ts.map +1 -0
  100. package/dist/orchestration/index.js +706 -0
  101. package/dist/orchestration/index.js.map +1 -0
  102. package/dist/orchestration/types.d.ts +391 -0
  103. package/dist/orchestration/types.d.ts.map +1 -0
  104. package/dist/orchestration/types.js +30 -0
  105. package/dist/orchestration/types.js.map +1 -0
  106. package/dist/personality/index.d.ts +65 -0
  107. package/dist/personality/index.d.ts.map +1 -0
  108. package/dist/personality/index.js +339 -0
  109. package/dist/personality/index.js.map +1 -0
  110. package/dist/personality/types.d.ts +103 -0
  111. package/dist/personality/types.d.ts.map +1 -0
  112. package/dist/personality/types.js +15 -0
  113. package/dist/personality/types.js.map +1 -0
  114. package/dist/provider/index.d.ts +4 -0
  115. package/dist/provider/index.d.ts.map +1 -0
  116. package/dist/provider/index.js +236 -0
  117. package/dist/provider/index.js.map +1 -0
  118. package/dist/provider/types.d.ts +180 -0
  119. package/dist/provider/types.d.ts.map +1 -0
  120. package/dist/provider/types.js +4 -0
  121. package/dist/provider/types.js.map +1 -0
  122. package/dist/runtime/agent-cards.d.ts +14 -0
  123. package/dist/runtime/agent-cards.d.ts.map +1 -0
  124. package/dist/runtime/agent-cards.js +90 -0
  125. package/dist/runtime/agent-cards.js.map +1 -0
  126. package/dist/runtime/agent-runner.d.ts +30 -0
  127. package/dist/runtime/agent-runner.d.ts.map +1 -0
  128. package/dist/runtime/agent-runner.js +37 -0
  129. package/dist/runtime/agent-runner.js.map +1 -0
  130. package/dist/runtime/budget.d.ts +15 -0
  131. package/dist/runtime/budget.d.ts.map +1 -0
  132. package/dist/runtime/budget.js +24 -0
  133. package/dist/runtime/budget.js.map +1 -0
  134. package/dist/runtime/delegation-driver.d.ts +11 -0
  135. package/dist/runtime/delegation-driver.d.ts.map +1 -0
  136. package/dist/runtime/delegation-driver.js +132 -0
  137. package/dist/runtime/delegation-driver.js.map +1 -0
  138. package/dist/runtime/exact-cache.d.ts +10 -0
  139. package/dist/runtime/exact-cache.d.ts.map +1 -0
  140. package/dist/runtime/exact-cache.js +30 -0
  141. package/dist/runtime/exact-cache.js.map +1 -0
  142. package/dist/runtime/execute-tool.d.ts +29 -0
  143. package/dist/runtime/execute-tool.d.ts.map +1 -0
  144. package/dist/runtime/execute-tool.js +80 -0
  145. package/dist/runtime/execute-tool.js.map +1 -0
  146. package/dist/runtime/guardian.d.ts +9 -0
  147. package/dist/runtime/guardian.d.ts.map +1 -0
  148. package/dist/runtime/guardian.js +41 -0
  149. package/dist/runtime/guardian.js.map +1 -0
  150. package/dist/runtime/hook-gate.d.ts +17 -0
  151. package/dist/runtime/hook-gate.d.ts.map +1 -0
  152. package/dist/runtime/hook-gate.js +56 -0
  153. package/dist/runtime/hook-gate.js.map +1 -0
  154. package/dist/runtime/memory-adapter.d.ts +6 -0
  155. package/dist/runtime/memory-adapter.d.ts.map +1 -0
  156. package/dist/runtime/memory-adapter.js +38 -0
  157. package/dist/runtime/memory-adapter.js.map +1 -0
  158. package/dist/runtime/nightly-adapters.d.ts +48 -0
  159. package/dist/runtime/nightly-adapters.d.ts.map +1 -0
  160. package/dist/runtime/nightly-adapters.js +139 -0
  161. package/dist/runtime/nightly-adapters.js.map +1 -0
  162. package/dist/runtime/nightly-generator.d.ts +10 -0
  163. package/dist/runtime/nightly-generator.d.ts.map +1 -0
  164. package/dist/runtime/nightly-generator.js +335 -0
  165. package/dist/runtime/nightly-generator.js.map +1 -0
  166. package/dist/runtime/onboarding-node.d.ts +6 -0
  167. package/dist/runtime/onboarding-node.d.ts.map +1 -0
  168. package/dist/runtime/onboarding-node.js +356 -0
  169. package/dist/runtime/onboarding-node.js.map +1 -0
  170. package/dist/runtime/provider-anthropic.d.ts +43 -0
  171. package/dist/runtime/provider-anthropic.d.ts.map +1 -0
  172. package/dist/runtime/provider-anthropic.js +148 -0
  173. package/dist/runtime/provider-anthropic.js.map +1 -0
  174. package/dist/runtime/provider-cli.d.ts +18 -0
  175. package/dist/runtime/provider-cli.d.ts.map +1 -0
  176. package/dist/runtime/provider-cli.js +73 -0
  177. package/dist/runtime/provider-cli.js.map +1 -0
  178. package/dist/runtime/provider-openai.d.ts +30 -0
  179. package/dist/runtime/provider-openai.d.ts.map +1 -0
  180. package/dist/runtime/provider-openai.js +114 -0
  181. package/dist/runtime/provider-openai.js.map +1 -0
  182. package/dist/runtime/providers.d.ts +43 -0
  183. package/dist/runtime/providers.d.ts.map +1 -0
  184. package/dist/runtime/providers.js +72 -0
  185. package/dist/runtime/providers.js.map +1 -0
  186. package/dist/runtime/sandbox-bash.d.ts +21 -0
  187. package/dist/runtime/sandbox-bash.d.ts.map +1 -0
  188. package/dist/runtime/sandbox-bash.js +51 -0
  189. package/dist/runtime/sandbox-bash.js.map +1 -0
  190. package/dist/runtime/scoped-tool-executor.d.ts +10 -0
  191. package/dist/runtime/scoped-tool-executor.d.ts.map +1 -0
  192. package/dist/runtime/scoped-tool-executor.js +30 -0
  193. package/dist/runtime/scoped-tool-executor.js.map +1 -0
  194. package/dist/runtime/session-log.d.ts +6 -0
  195. package/dist/runtime/session-log.d.ts.map +1 -0
  196. package/dist/runtime/session-log.js +54 -0
  197. package/dist/runtime/session-log.js.map +1 -0
  198. package/dist/runtime/settings.d.ts +24 -0
  199. package/dist/runtime/settings.d.ts.map +1 -0
  200. package/dist/runtime/settings.js +29 -0
  201. package/dist/runtime/settings.js.map +1 -0
  202. package/dist/runtime/spawn-plan.d.ts +13 -0
  203. package/dist/runtime/spawn-plan.d.ts.map +1 -0
  204. package/dist/runtime/spawn-plan.js +107 -0
  205. package/dist/runtime/spawn-plan.js.map +1 -0
  206. package/dist/runtime/spend.d.ts +41 -0
  207. package/dist/runtime/spend.d.ts.map +1 -0
  208. package/dist/runtime/spend.js +0 -0
  209. package/dist/runtime/spend.js.map +1 -0
  210. package/dist/runtime/sub-agent-runner.d.ts +19 -0
  211. package/dist/runtime/sub-agent-runner.d.ts.map +1 -0
  212. package/dist/runtime/sub-agent-runner.js +47 -0
  213. package/dist/runtime/sub-agent-runner.js.map +1 -0
  214. package/dist/safety/grants.d.ts +7 -0
  215. package/dist/safety/grants.d.ts.map +1 -0
  216. package/dist/safety/grants.js +53 -0
  217. package/dist/safety/grants.js.map +1 -0
  218. package/dist/safety/index.d.ts +72 -0
  219. package/dist/safety/index.d.ts.map +1 -0
  220. package/dist/safety/index.js +464 -0
  221. package/dist/safety/index.js.map +1 -0
  222. package/dist/safety/types.d.ts +254 -0
  223. package/dist/safety/types.d.ts.map +1 -0
  224. package/dist/safety/types.js +3 -0
  225. package/dist/safety/types.js.map +1 -0
  226. package/dist/skills/index.d.ts +4 -0
  227. package/dist/skills/index.d.ts.map +1 -0
  228. package/dist/skills/index.js +463 -0
  229. package/dist/skills/index.js.map +1 -0
  230. package/dist/skills/types.d.ts +177 -0
  231. package/dist/skills/types.d.ts.map +1 -0
  232. package/dist/skills/types.js +3 -0
  233. package/dist/skills/types.js.map +1 -0
  234. package/dist/testing/clock.d.ts +8 -0
  235. package/dist/testing/clock.d.ts.map +1 -0
  236. package/dist/testing/clock.js +13 -0
  237. package/dist/testing/clock.js.map +1 -0
  238. package/dist/testing/effect-verifier.d.ts +15 -0
  239. package/dist/testing/effect-verifier.d.ts.map +1 -0
  240. package/dist/testing/effect-verifier.js +27 -0
  241. package/dist/testing/effect-verifier.js.map +1 -0
  242. package/dist/testing/index.d.ts +5 -0
  243. package/dist/testing/index.d.ts.map +1 -0
  244. package/dist/testing/index.js +5 -0
  245. package/dist/testing/index.js.map +1 -0
  246. package/dist/testing/provider-fake.d.ts +14 -0
  247. package/dist/testing/provider-fake.d.ts.map +1 -0
  248. package/dist/testing/provider-fake.js +18 -0
  249. package/dist/testing/provider-fake.js.map +1 -0
  250. package/dist/testing/sandbox-stub.d.ts +15 -0
  251. package/dist/testing/sandbox-stub.d.ts.map +1 -0
  252. package/dist/testing/sandbox-stub.js +15 -0
  253. package/dist/testing/sandbox-stub.js.map +1 -0
  254. package/dist/tools/index.d.ts +11 -0
  255. package/dist/tools/index.d.ts.map +1 -0
  256. package/dist/tools/index.js +0 -0
  257. package/dist/tools/index.js.map +1 -0
  258. package/dist/tools/types.d.ts +138 -0
  259. package/dist/tools/types.d.ts.map +1 -0
  260. package/dist/tools/types.js +4 -0
  261. package/dist/tools/types.js.map +1 -0
  262. package/dist/triggers/index.d.ts +4 -0
  263. package/dist/triggers/index.d.ts.map +1 -0
  264. package/dist/triggers/index.js +187 -0
  265. package/dist/triggers/index.js.map +1 -0
  266. package/dist/triggers/types.d.ts +74 -0
  267. package/dist/triggers/types.d.ts.map +1 -0
  268. package/dist/triggers/types.js +5 -0
  269. package/dist/triggers/types.js.map +1 -0
  270. package/package.json +36 -0
@@ -0,0 +1,463 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ // ---------------------------------------------------------------------------
3
+ // Hashing — SHA-256 over the exact candidate bytes (§4.2, ADR-0029 #3).
4
+ // rawBytes is the byte-stable artifact; the pin is taken at stage() time and
5
+ // re-checked at promote() to close the TOCTOU window.
6
+ // ---------------------------------------------------------------------------
7
+ function hashBytes(bytes) {
8
+ return createHash('sha256').update(bytes).digest('hex');
9
+ }
10
+ // ---------------------------------------------------------------------------
11
+ // SKILL.md parser — frontmatter contract (§4.1, ADR-0015).
12
+ // Deterministic, fail-closed: a malformed candidate is dropped pre-judge.
13
+ // We use a minimal YAML reader for the fixed frontmatter shape rather than a
14
+ // general parser — the contract is a flat scalar/list block (§4.1).
15
+ // ---------------------------------------------------------------------------
16
+ const NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
17
+ const REQUIRED_FIELDS = ['name', 'description', 'version', 'provenance', 'triggers'];
18
+ const VALID_PROVENANCE = new Set(['human', 'agent-authored', 'imported']);
19
+ /** Split the leading `---`…`---` block from the body. null = no frontmatter. */
20
+ function splitFrontmatter(raw) {
21
+ const text = raw.replace(/\r\n/g, '\n');
22
+ if (!text.startsWith('---\n'))
23
+ return null;
24
+ // Closing fence must be a line that is EXACTLY `---` (trimmed) — a body line
25
+ // like `----` or `---yaml` is a `\n---` *prefix* but not the fence, and must
26
+ // not truncate the frontmatter. Scan line-by-line from after the opener.
27
+ const lines = text.split('\n');
28
+ let fenceLine = -1;
29
+ for (let i = 1; i < lines.length; i++) {
30
+ if (lines[i].trim() === '---') {
31
+ fenceLine = i;
32
+ break;
33
+ }
34
+ }
35
+ if (fenceLine < 0)
36
+ return null;
37
+ const fm = lines.slice(1, fenceLine).join('\n');
38
+ // body starts after the closing fence line
39
+ const body = lines.slice(fenceLine + 1).join('\n').replace(/^\n+/, '');
40
+ return { fm, body };
41
+ }
42
+ /** Minimal flat-YAML reader for the frontmatter contract (scalars + one list). */
43
+ function readFrontmatter(fm) {
44
+ const out = {};
45
+ const lines = fm.split('\n');
46
+ for (let i = 0; i < lines.length; i++) {
47
+ const line = lines[i];
48
+ if (line.trim() === '' || line.trim().startsWith('#'))
49
+ continue;
50
+ // List items belong to the most recent `key:` with no inline value.
51
+ const kv = /^([a-zA-Z_][a-zA-Z0-9_]*):\s*(.*)$/.exec(line);
52
+ if (!kv)
53
+ continue;
54
+ const key = kv[1];
55
+ const value = kv[2];
56
+ if (key === 'triggers') {
57
+ const items = [];
58
+ for (let j = i + 1; j < lines.length; j++) {
59
+ const lj = lines[j];
60
+ // A blank line within the list is skipped, not a terminator — items
61
+ // listed after it still belong to the trigger list. A non-blank,
62
+ // non-list line ends the list.
63
+ if (lj.trim() === '') {
64
+ i = j;
65
+ continue;
66
+ }
67
+ const m = /^\s*-\s+(.*)$/.exec(lj);
68
+ if (!m)
69
+ break;
70
+ items.push(m[1].trim());
71
+ i = j;
72
+ }
73
+ out.triggers = items;
74
+ }
75
+ else if (key === 'version') {
76
+ if (value !== '')
77
+ out.version = Number(value);
78
+ }
79
+ else if (key === 'name') {
80
+ out.name = value;
81
+ }
82
+ else if (key === 'description') {
83
+ out.description = value;
84
+ }
85
+ else if (key === 'provenance') {
86
+ out.provenance = value;
87
+ }
88
+ }
89
+ return out;
90
+ }
91
+ function parseSkill(raw) {
92
+ const split = splitFrontmatter(raw);
93
+ if (!split) {
94
+ return { ok: false, errors: [{ kind: 'malformed_frontmatter', detail: 'missing or unterminated --- fence' }] };
95
+ }
96
+ const rf = readFrontmatter(split.fm);
97
+ const errors = [];
98
+ // Required-field presence (§9 AC-06-2).
99
+ for (const field of REQUIRED_FIELDS) {
100
+ const present = field === 'triggers'
101
+ ? Array.isArray(rf.triggers) && rf.triggers.length > 0
102
+ : rf[field] !== undefined && rf[field] !== '';
103
+ if (!present)
104
+ errors.push({ kind: 'missing_field', field });
105
+ }
106
+ // description ≤ 60 chars (§4.1, AC-06-1) — reported independently so an
107
+ // over-long description is caught even when all fields are present.
108
+ if (typeof rf.description === 'string' && rf.description.length > 60) {
109
+ errors.push({ kind: 'description_too_long', length: rf.description.length });
110
+ }
111
+ // name format /^[a-z0-9][a-z0-9-]*$/ (§4.1).
112
+ if (typeof rf.name === 'string' && rf.name !== '' && !NAME_RE.test(rf.name)) {
113
+ errors.push({ kind: 'invalid_name_format', name: rf.name });
114
+ }
115
+ // provenance enum + version numeric.
116
+ if (typeof rf.provenance === 'string' && rf.provenance !== '' && !VALID_PROVENANCE.has(rf.provenance)) {
117
+ errors.push({ kind: 'malformed_frontmatter', detail: `invalid provenance '${rf.provenance}'` });
118
+ }
119
+ if (rf.version !== undefined && (Number.isNaN(rf.version) || !Number.isFinite(rf.version))) {
120
+ errors.push({ kind: 'malformed_frontmatter', detail: 'version is not a number' });
121
+ }
122
+ if (errors.length > 0)
123
+ return { ok: false, errors };
124
+ const frontmatter = {
125
+ name: rf.name,
126
+ description: rf.description,
127
+ version: rf.version,
128
+ provenance: rf.provenance,
129
+ triggers: rf.triggers,
130
+ };
131
+ return {
132
+ ok: true,
133
+ skill: {
134
+ frontmatter,
135
+ body: split.body,
136
+ rawBytes: new TextEncoder().encode(raw),
137
+ },
138
+ };
139
+ }
140
+ // ---------------------------------------------------------------------------
141
+ // Deterministic validators (§6, §5.2). All four run in code, 100%; the AND of
142
+ // the four (`ok`) gates a candidate before the judge (Nightly 10) sees it.
143
+ // ---------------------------------------------------------------------------
144
+ const VERIFICATION_HEADING = /(^|\n)##\s+verification\b/i;
145
+ /** refs_exist: a candidate may not reference a path/tool that does not exist. */
146
+ function checkRefsExist(body) {
147
+ // Heuristic deterministic check: local relative refs (`./…`, `../…`) and
148
+ // `Requires:` declarations must resolve. In this pure-core build there is no
149
+ // skill/tool registry on disk, so any local relative ref is treated as
150
+ // dangling (fail-closed) — matching AC-06-8's `./nonexistent-tool.sh`.
151
+ return !/(^|\s)\.{1,2}\/\S+/.test(body);
152
+ }
153
+ /**
154
+ * no_constitution_conflict: a candidate body may not assert a directive that
155
+ * contradicts the constitution (e.g. an unconditional always/never policy that
156
+ * would override Safety's HARD_DENY / autonomy gradient). Deterministic phrase
157
+ * set, not a model call (§8 OWASP-LLM01 mitigation).
158
+ */
159
+ const CONSTITUTION_CONFLICT_PATTERNS = [
160
+ /\balways\s+deny\s+all\b/i,
161
+ /\bdeny\s+all\s+requests\s+unconditionally\b/i,
162
+ /\bignore\s+(?:the\s+)?constitution\b/i,
163
+ /\bdisable\s+(?:all\s+)?safety\b/i,
164
+ /\bbypass\s+hard[_-]?deny\b/i,
165
+ ];
166
+ function checkNoConstitutionConflict(body) {
167
+ return !CONSTITUTION_CONFLICT_PATTERNS.some((p) => p.test(body));
168
+ }
169
+ function checkHasVerificationSection(body) {
170
+ return VERIFICATION_HEADING.test('\n' + body);
171
+ }
172
+ // ---------------------------------------------------------------------------
173
+ // Negative-skill / failure-classification model (§4.4, §5.4, ADR-0025).
174
+ // ---------------------------------------------------------------------------
175
+ const NEGATIVE_THRESHOLD = 3; // N ≥ 3 distinct sessions of permanent failures.
176
+ /** Destructive operations in a skill BODY that force step-up (§8 ADR-0029 #5). */
177
+ const DESTRUCTIVE_BODY_PATTERNS = [
178
+ /\brm\s+-[a-z]*r[a-z]*f?/i, // rm -rf / rm -fr / rm -r ...
179
+ /\bdrop\s+(?:table|database|schema)\b/i,
180
+ /\btruncate\s+table\b/i,
181
+ /\bgit\s+push\s+(?:--force|-f)\b/i,
182
+ /\bforce[- ]?push\b/i,
183
+ /\bgit\s+reset\s+--hard\b/i,
184
+ /\b(?:mkfs|dd\s+if=|shred)\b/i,
185
+ /\b(?:drop|wipe|destroy|delete\s+all|format)\b/i,
186
+ ];
187
+ /**
188
+ * Detect a permanence/irreversible-flagged candidate (§5.3, §8 ADR-0029 #5).
189
+ * Step-up is required to promote one. The flag is derived deterministically
190
+ * from the frontmatter AND the body, never from a model-set trust field — a
191
+ * benign-titled skill whose body performs a destructive operation must not
192
+ * bypass step-up.
193
+ */
194
+ function isIrreversible(fm, body) {
195
+ const hay = `${fm.name} ${fm.description}`.toLowerCase();
196
+ if (/\b(irreversible|permanence|permanent|wipe|destroy|delete\s+all)\b/.test(hay))
197
+ return true;
198
+ return DESTRUCTIVE_BODY_PATTERNS.some((p) => p.test(body));
199
+ }
200
+ export function makeSkillRegistry(deps) {
201
+ // Promoted (active+trusted) skills, keyed by name. Cold start: empty (§7).
202
+ const promoted = new Map();
203
+ // Staged candidates awaiting human approval.
204
+ const staged = new Map();
205
+ // Distinct-session permanent-failure tallies, keyed by target (§4.4).
206
+ const tallies = new Map();
207
+ // Active negative-skill records (bi-temporal; probe sets invalid_at) (§4.4).
208
+ const negatives = new Map();
209
+ // Trigger phrases for promoted skills, kept OUT of the byte-stable menu line
210
+ // (§5.1, ADR-0019). Per-instance; matchTriggers resolves against this.
211
+ const promotedTriggers = new Map();
212
+ /** Telemetry emit is fail-open: it must never block serving (§7, AC-06-27). */
213
+ const emit = (event, payload) => {
214
+ try {
215
+ deps.observability.emit(event, payload);
216
+ }
217
+ catch {
218
+ /* sidecar unavailable — serving is never blocked on telemetry */
219
+ }
220
+ };
221
+ return {
222
+ // ---- resident path (deterministic, every prompt assembly) ----
223
+ menu() {
224
+ // Active + TRUSTED only. A staged-but-unpromoted (untrusted) skill never
225
+ // appears here (AC-06-4, AC-06-11). Body text is never included — only
226
+ // the byte-stable name+description menu line (§4.1, ADR-0019).
227
+ const entries = [];
228
+ for (const skill of promoted.values()) {
229
+ entries.push({ name: skill.name, description: skill.description });
230
+ }
231
+ return entries;
232
+ },
233
+ matchTriggers(request) {
234
+ // Deterministic phrase match against TRUSTED skills only — an unverified
235
+ // recipe can never fire (§5.1). Case-insensitive substring on triggers.
236
+ const q = request.toLowerCase();
237
+ const names = [];
238
+ for (const skill of promoted.values()) {
239
+ const triggers = promotedTriggers.get(skill.name) ?? [];
240
+ if (triggers.some((t) => q.includes(t.toLowerCase()))) {
241
+ names.push(skill.name);
242
+ }
243
+ }
244
+ return names;
245
+ },
246
+ async loadBody(name) {
247
+ // Lazy body load into working context, NOT the prefix (§5.1, AC-06-6).
248
+ // Serving is never blocked on telemetry (AC-06-27): emit is fail-open.
249
+ const skill = promoted.get(name);
250
+ if (!skill)
251
+ return '';
252
+ emit('skill.loaded', { name });
253
+ return skill.body;
254
+ },
255
+ // ---- authoring path ----
256
+ parse(raw) {
257
+ return parseSkill(raw);
258
+ },
259
+ async validate(candidate) {
260
+ const body = candidate.body;
261
+ const refs_exist = checkRefsExist(body);
262
+ const no_constitution_conflict = checkNoConstitutionConflict(body);
263
+ const has_verification_section = checkHasVerificationSection(body);
264
+ // dry_run_ok: the body must run in Safety's network-none sandbox
265
+ // (§6, ADR-0012). The sandbox is owned by Safety; Skills calls into it.
266
+ // Fail-closed two ways (§7, AC-06-9): if invoking the sandbox fails
267
+ // (unavailable) OR the sandbox runs the body and REJECTS it by resolving
268
+ // `{ok:false}`, dry_run_ok is false and the candidate is not staged. We
269
+ // await the verdict — same pattern as probe() (OWASP-LLM01 mitigation).
270
+ let dry_run_ok = false;
271
+ try {
272
+ const result = await deps.sandbox.dryRun(body);
273
+ dry_run_ok = result.ok;
274
+ }
275
+ catch {
276
+ dry_run_ok = false;
277
+ }
278
+ const ok = refs_exist && no_constitution_conflict && dry_run_ok && has_verification_section;
279
+ return { refs_exist, no_constitution_conflict, dry_run_ok, has_verification_section, ok };
280
+ },
281
+ stage(candidate, ctx) {
282
+ // Hash-pin the exact candidate bytes at stage time (ADR-0029 #3).
283
+ const artifactHash = hashBytes(candidate.rawBytes);
284
+ const stageId = `stage-${randomUUID()}`;
285
+ const fullText = new TextDecoder().decode(candidate.rawBytes);
286
+ // trace_verified is set ONLY from a real Observability trace, never a
287
+ // self-report (ADR-0017, AC-06-13). At stage time we have not yet run the
288
+ // verification section against real traces, so it stays false until
289
+ // promote() consults Observability. The staged artifact carries NO
290
+ // approved/trusted field (AC-06-16) — TypeScript + this record enforce it.
291
+ const record = {
292
+ stageId,
293
+ artifactHash,
294
+ diff: '',
295
+ triggerContext: { request: ctx.request, sessionId: ctx.sessionId },
296
+ traceVerified: false,
297
+ provenance: candidate.frontmatter.provenance,
298
+ fullText,
299
+ frontmatter: candidate.frontmatter,
300
+ body: candidate.body,
301
+ approved: false,
302
+ promotedVersion: null,
303
+ };
304
+ staged.set(stageId, record);
305
+ emit('skill.staged', { stageId, name: candidate.frontmatter.name, provenance: record.provenance });
306
+ // Return only the public StagedSkill surface.
307
+ return {
308
+ stageId,
309
+ artifactHash,
310
+ diff: record.diff,
311
+ triggerContext: record.triggerContext,
312
+ traceVerified: record.traceVerified,
313
+ provenance: record.provenance,
314
+ fullText,
315
+ };
316
+ },
317
+ reviewPayload(stageId) {
318
+ const record = staged.get(stageId);
319
+ if (!record)
320
+ throw new Error(`skills.reviewPayload: unknown stageId '${stageId}'`);
321
+ // Full text + diff + triggering context (§2, AC-06-15).
322
+ return {
323
+ stageId: record.stageId,
324
+ fullText: record.fullText,
325
+ diff: record.diff,
326
+ triggerContext: record.triggerContext,
327
+ };
328
+ },
329
+ // ---- promotion path (ADR-0029) ----
330
+ async promote(stageId, approval) {
331
+ const record = staged.get(stageId);
332
+ // No pending action for this stage id (§7, AC-06-18 alt reason).
333
+ if (!record)
334
+ return { ok: false, reason: 'no_pending_action' };
335
+ // TOCTOU close: re-hash the staged bytes and require equality with the
336
+ // human-approved hash before anything else (ADR-0029 #3, AC-06-17).
337
+ const currentHash = hashBytes(new TextEncoder().encode(record.fullText));
338
+ if (approval.artifactHash !== currentHash) {
339
+ return { ok: false, reason: 'hash_mismatch' };
340
+ }
341
+ // Single-use, per-action nonce (ADR-0029 #4, AC-06-18). A replayed/stale
342
+ // nonce is rejected and nothing is committed.
343
+ if (!deps.nonceStore.consume(approval.nonce, stageId)) {
344
+ return { ok: false, reason: 'replayed_nonce' };
345
+ }
346
+ // TOCTOU close on the staged record itself: claim it synchronously, before
347
+ // the first await. The NonceStore is keyed per-nonce, so two distinct valid
348
+ // nonces for the same stageId would otherwise both pass the consume check
349
+ // and race to a double git.commit(). Deleting here (no await between get and
350
+ // delete) makes a concurrent promote on the same stageId see no record and
351
+ // return no_pending_action — exactly one promotion wins (ADR-0029 #4).
352
+ staged.delete(stageId);
353
+ // Trace-based trust: promotion requires a real passing trace on record,
354
+ // never a self-report (ADR-0017, AC-06-12/AC-06-13). Observability owns
355
+ // the trace journal; Skills only reads it.
356
+ const traceVerified = await deps.observability.hasPassingTrace(record.frontmatter.name);
357
+ if (!traceVerified) {
358
+ return { ok: false, reason: 'not_trace_verified' };
359
+ }
360
+ // Step-up second factor for permanence/irreversible items (ADR-0029 #5,
361
+ // AC-06-19). A plain tap is insufficient for these.
362
+ if (isIrreversible(record.frontmatter, record.body) && !approval.stepUpSatisfied) {
363
+ return { ok: false, reason: 'stepup_missing' };
364
+ }
365
+ // All gates passed. Commit to prod git with a version bump, binding the
366
+ // human tap to the commit (ADR-0029 #2, AC-06-14/AC-06-20). The approved
367
+ // flag is set ONLY here, in code, bound to a real human action.
368
+ const prior = promoted.get(record.frontmatter.name);
369
+ const version = (prior?.version ?? record.frontmatter.version - 1) + 1;
370
+ const filename = `skills/${record.frontmatter.name}/SKILL.md`;
371
+ const commit = await deps.git.commit(`skill: promote ${record.frontmatter.name} v${version} (tap ${approval.humanTapAuditId})`, { [filename]: record.fullText });
372
+ record.approved = true;
373
+ record.promotedVersion = version;
374
+ promoted.set(record.frontmatter.name, {
375
+ name: record.frontmatter.name,
376
+ description: record.frontmatter.description,
377
+ body: record.body,
378
+ version,
379
+ provenance: record.provenance,
380
+ });
381
+ promotedTriggers.set(record.frontmatter.name, record.frontmatter.triggers);
382
+ // (staged record already removed above, before the first await — TOCTOU close.)
383
+ // tap→commit audit binding (AC-06-20) — emitted to Observability 12.
384
+ emit('skill.promoted', {
385
+ name: record.frontmatter.name,
386
+ commit,
387
+ version,
388
+ humanTapAuditId: approval.humanTapAuditId,
389
+ });
390
+ return { ok: true, commit, version };
391
+ },
392
+ // ---- failure / negative-skill path (ADR-0025) ----
393
+ recordFailure(_name, f) {
394
+ // Every signal produces a journal note (AC-06-21). Transient signals and
395
+ // sub-threshold permanent signals are notes only — never a skill (§4.5).
396
+ emit('skill.failure_recorded', { target: f.target, class: f.class, sessionId: f.sessionId, detail: f.detail });
397
+ if (f.class !== 'permanent')
398
+ return;
399
+ // Distinct-session permanent tally, keyed by target (§4.4). One session
400
+ // cannot mint a negative skill (AC-06-22): the Set dedupes session ids.
401
+ let tally = tallies.get(f.target);
402
+ if (!tally) {
403
+ tally = { target: f.target, sessionIds: new Set() };
404
+ tallies.set(f.target, tally);
405
+ }
406
+ tally.sessionIds.add(f.sessionId);
407
+ // Below threshold → transient note only, no negative skill (AC-06-22).
408
+ if (tally.sessionIds.size < NEGATIVE_THRESHOLD)
409
+ return;
410
+ // Already fossilized and still active → do not re-draft.
411
+ const existing = negatives.get(f.target);
412
+ if (existing && existing.invalid_at === null)
413
+ return;
414
+ // N ≥ 3 distinct sessions → draft a negative-skill candidate that enters
415
+ // the staging path (AC-06-23). It is advisory only, never a HARD_DENY
416
+ // (AC-06-24): priority is lowered, the capability stays callable.
417
+ const record = {
418
+ target: f.target,
419
+ failureCount: tally.sessionIds.size,
420
+ sessionIds: [...tally.sessionIds],
421
+ valid_at: new Date().toISOString(),
422
+ invalid_at: null,
423
+ advisory: true,
424
+ };
425
+ negatives.set(f.target, record);
426
+ emit('skill.negative_created', record);
427
+ },
428
+ async probe() {
429
+ // Nightly un-fossilize re-test (§5.4, AC-06-25). For each active negative
430
+ // skill, re-test the failed strategy in the sandbox. First success sets
431
+ // invalid_at (NOT a hard delete) and emits an un-fossilize diff card.
432
+ const unfossilized = [];
433
+ const stillFailing = [];
434
+ const checkedAt = new Date().toISOString();
435
+ for (const [target, record] of negatives) {
436
+ if (record.invalid_at !== null)
437
+ continue;
438
+ let ok = false;
439
+ try {
440
+ const result = await deps.sandbox.dryRun(`probe: ${target}`);
441
+ ok = result.ok;
442
+ }
443
+ catch {
444
+ ok = false;
445
+ }
446
+ if (ok) {
447
+ // Bi-temporal: set invalid_at, keep the row (recoverable from git).
448
+ record.invalid_at = checkedAt;
449
+ unfossilized.push(target);
450
+ // Clear the tally so a future outage starts a fresh distinct-session
451
+ // count (hysteresis: a flaky tool does not immediately re-fossilize).
452
+ tallies.delete(target);
453
+ emit('skill.unfossilized', { name: target, invalid_at: checkedAt });
454
+ }
455
+ else {
456
+ stillFailing.push(target);
457
+ }
458
+ }
459
+ return { unfossilized, stillFailing, checkedAt };
460
+ },
461
+ };
462
+ }
463
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/skills/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,177 @@
1
+ export type Provenance = 'human' | 'agent-authored' | 'imported';
2
+ export interface SkillFrontmatter {
3
+ /** Stable id; telemetry join key; immutable once promoted. /^[a-z0-9][a-z0-9-]*$/ */
4
+ name: string;
5
+ /** <= 60 chars — the single menu line injected into the prefix. */
6
+ description: string;
7
+ /** Bumped on every approved edit; mirrors git commit chain. */
8
+ version: number;
9
+ provenance: Provenance;
10
+ /** Phrases/intents matched deterministically at runtime. */
11
+ triggers: string[];
12
+ }
13
+ /** The raw body text of a skill (Markdown after the frontmatter). */
14
+ export type SkillBody = string;
15
+ export interface ParsedSkill {
16
+ frontmatter: SkillFrontmatter;
17
+ body: SkillBody;
18
+ /** Raw bytes of the complete SKILL.md, used for hash-pinning. */
19
+ rawBytes: Uint8Array;
20
+ }
21
+ export type ParseError = {
22
+ kind: 'description_too_long';
23
+ length: number;
24
+ } | {
25
+ kind: 'missing_field';
26
+ field: keyof SkillFrontmatter;
27
+ } | {
28
+ kind: 'invalid_name_format';
29
+ name: string;
30
+ } | {
31
+ kind: 'malformed_frontmatter';
32
+ detail: string;
33
+ };
34
+ export type ParseResult = {
35
+ ok: true;
36
+ skill: ParsedSkill;
37
+ } | {
38
+ ok: false;
39
+ errors: ParseError[];
40
+ };
41
+ /** What enters the always-loaded prefix: one line per active+trusted skill. */
42
+ export interface MenuEntry {
43
+ name: string;
44
+ description: string;
45
+ }
46
+ export interface SkillTrigger {
47
+ skillName: string;
48
+ phrase: string;
49
+ }
50
+ export interface ValidationReport {
51
+ refs_exist: boolean;
52
+ no_constitution_conflict: boolean;
53
+ dry_run_ok: boolean;
54
+ has_verification_section: boolean;
55
+ /** AND of all four; false drops the candidate before the judge. */
56
+ ok: boolean;
57
+ }
58
+ export interface TriggerContext {
59
+ /** The request text or trace excerpt that caused the draft. */
60
+ request: string;
61
+ sessionId: string;
62
+ }
63
+ export interface StagedSkill {
64
+ stageId: string;
65
+ /** SHA-256 of the exact bytes the judge accepted; re-checked at promote. */
66
+ artifactHash: string;
67
+ /** Unified diff vs current prod skill, or empty for a new skill. */
68
+ diff: string;
69
+ triggerContext: TriggerContext;
70
+ /**
71
+ * True only when the verification section has passed against real traces
72
+ * (ADR-0017). Never set from a self-report.
73
+ */
74
+ traceVerified: boolean;
75
+ provenance: Provenance;
76
+ /** Full text of the candidate (body + frontmatter). */
77
+ fullText: string;
78
+ }
79
+ /** Payload sent to the reviewer / approval card. */
80
+ export interface ReviewCard {
81
+ stageId: string;
82
+ fullText: string;
83
+ diff: string;
84
+ triggerContext: TriggerContext;
85
+ }
86
+ export interface ApprovalVerdict {
87
+ stageId: string;
88
+ /** Must equal the judge-accept hash (TOCTOU close, ADR-0029 §3). */
89
+ artifactHash: string;
90
+ /** Single-use, bound to this exact pending action (ADR-0029 §4). */
91
+ nonce: string;
92
+ /** Required for permanence/irreversible items (ADR-0029 §5). */
93
+ stepUpSatisfied: boolean;
94
+ /** Binding: which human tap → which action → when. */
95
+ humanTapAuditId: string;
96
+ }
97
+ /**
98
+ * promote() claims the staged record synchronously (deleting it before the
99
+ * first await) to close the concurrent-double-promote TOCTOU (ADR-0029 #4).
100
+ * A consequence: if a post-claim gate fails (`not_trace_verified`,
101
+ * `stepup_missing`) or the git commit throws, the staged artifact is already
102
+ * consumed — the caller must re-stage and re-approve with a fresh nonce.
103
+ */
104
+ export type PromoteResult = {
105
+ ok: true;
106
+ commit: string;
107
+ version: number;
108
+ } | {
109
+ ok: false;
110
+ reason: 'hash_mismatch' | 'replayed_nonce' | 'stepup_missing' | 'not_trace_verified' | 'no_pending_action';
111
+ };
112
+ export type FailureClass = 'transient' | 'permanent';
113
+ export interface FailureSignal {
114
+ /** The tool or strategy that failed. */
115
+ target: string;
116
+ class: FailureClass;
117
+ sessionId: string;
118
+ detail?: string;
119
+ }
120
+ export interface NegativeSkillRecord {
121
+ /** The tool/strategy the negative skill deprioritizes. */
122
+ target: string;
123
+ /** Distinct-session permanent-class failure count. Threshold: >= 3. */
124
+ failureCount: number;
125
+ sessionIds: string[];
126
+ valid_at: string;
127
+ invalid_at: string | null;
128
+ /** Always true: advisory only, never HARD_DENY (ADR-0025). */
129
+ advisory: true;
130
+ }
131
+ export interface ProbeReport {
132
+ unfossilized: string[];
133
+ stillFailing: string[];
134
+ checkedAt: string;
135
+ }
136
+ export interface Skills {
137
+ menu(): MenuEntry[];
138
+ matchTriggers(request: string): string[];
139
+ loadBody(name: string): Promise<SkillBody>;
140
+ parse(raw: string): ParseResult;
141
+ /**
142
+ * §6 deterministic validators. Async because `dry_run_ok` awaits Safety's
143
+ * network-none sandbox: a body the sandbox REJECTS (resolves `{ok:false}`)
144
+ * must fail-closed, not just one whose invocation throws.
145
+ */
146
+ validate(candidate: ParsedSkill): Promise<ValidationReport>;
147
+ stage(candidate: ParsedSkill, ctx: TriggerContext): StagedSkill;
148
+ reviewPayload(stageId: string): ReviewCard;
149
+ promote(stageId: string, approval: ApprovalVerdict): Promise<PromoteResult>;
150
+ recordFailure(name: string | null, f: FailureSignal): void;
151
+ probe(): Promise<ProbeReport>;
152
+ }
153
+ export interface SandboxPort {
154
+ /** Run the skill body in a network-none, read-only one-shot sandbox. */
155
+ dryRun(body: SkillBody): Promise<{
156
+ ok: boolean;
157
+ detail?: string;
158
+ }>;
159
+ }
160
+ export interface ObservabilityPort {
161
+ /** Check whether the given skill's verification section has passed against real traces. */
162
+ hasPassingTrace(skillName: string): Promise<boolean>;
163
+ emit(event: string, payload: unknown): void;
164
+ }
165
+ export interface GitPort {
166
+ commit(message: string, files: Record<string, string>): Promise<string>;
167
+ }
168
+ export interface NonceStore {
169
+ consume(nonce: string, stageId: string): boolean;
170
+ }
171
+ export interface SkillsDeps {
172
+ sandbox: SandboxPort;
173
+ observability: ObservabilityPort;
174
+ git: GitPort;
175
+ nonceStore: NonceStore;
176
+ }
177
+ //# sourceMappingURL=types.d.ts.map