@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.
- package/LICENSE +202 -0
- package/dist/agent-loop/index.d.ts +4 -0
- package/dist/agent-loop/index.d.ts.map +1 -0
- package/dist/agent-loop/index.js +352 -0
- package/dist/agent-loop/index.js.map +1 -0
- package/dist/agent-loop/types.d.ts +183 -0
- package/dist/agent-loop/types.d.ts.map +1 -0
- package/dist/agent-loop/types.js +3 -0
- package/dist/agent-loop/types.js.map +1 -0
- package/dist/bin/aisy.d.ts +3 -0
- package/dist/bin/aisy.d.ts.map +1 -0
- package/dist/bin/aisy.js +14 -0
- package/dist/bin/aisy.js.map +1 -0
- package/dist/cli/index.d.ts +17 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +114 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/context-engine/index.d.ts +4 -0
- package/dist/context-engine/index.d.ts.map +1 -0
- package/dist/context-engine/index.js +126 -0
- package/dist/context-engine/index.js.map +1 -0
- package/dist/context-engine/types.d.ts +54 -0
- package/dist/context-engine/types.d.ts.map +1 -0
- package/dist/context-engine/types.js +4 -0
- package/dist/context-engine/types.js.map +1 -0
- package/dist/eval/index.d.ts +20 -0
- package/dist/eval/index.d.ts.map +1 -0
- package/dist/eval/index.js +128 -0
- package/dist/eval/index.js.map +1 -0
- package/dist/eval/types.d.ts +62 -0
- package/dist/eval/types.d.ts.map +1 -0
- package/dist/eval/types.js +17 -0
- package/dist/eval/types.js.map +1 -0
- package/dist/gateway/index.d.ts +5 -0
- package/dist/gateway/index.d.ts.map +1 -0
- package/dist/gateway/index.js +288 -0
- package/dist/gateway/index.js.map +1 -0
- package/dist/gateway/types.d.ts +194 -0
- package/dist/gateway/types.d.ts.map +1 -0
- package/dist/gateway/types.js +94 -0
- package/dist/gateway/types.js.map +1 -0
- package/dist/goals/index.d.ts +11 -0
- package/dist/goals/index.d.ts.map +1 -0
- package/dist/goals/index.js +21 -0
- package/dist/goals/index.js.map +1 -0
- package/dist/goals/types.d.ts +47 -0
- package/dist/goals/types.d.ts.map +1 -0
- package/dist/goals/types.js +5 -0
- package/dist/goals/types.js.map +1 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.d.ts +5 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +215 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/types.d.ts +148 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +4 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/memory/index.d.ts +6 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +419 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/types.d.ts +131 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +33 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/nightly/index.d.ts +4 -0
- package/dist/nightly/index.d.ts.map +1 -0
- package/dist/nightly/index.js +470 -0
- package/dist/nightly/index.js.map +1 -0
- package/dist/nightly/types.d.ts +326 -0
- package/dist/nightly/types.d.ts.map +1 -0
- package/dist/nightly/types.js +3 -0
- package/dist/nightly/types.js.map +1 -0
- package/dist/observability/index.d.ts +11 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +396 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/types.d.ts +139 -0
- package/dist/observability/types.d.ts.map +1 -0
- package/dist/observability/types.js +4 -0
- package/dist/observability/types.js.map +1 -0
- package/dist/onboarding/index.d.ts +16 -0
- package/dist/onboarding/index.d.ts.map +1 -0
- package/dist/onboarding/index.js +787 -0
- package/dist/onboarding/index.js.map +1 -0
- package/dist/onboarding/interactive.d.ts +23 -0
- package/dist/onboarding/interactive.d.ts.map +1 -0
- package/dist/onboarding/interactive.js +45 -0
- package/dist/onboarding/interactive.js.map +1 -0
- package/dist/onboarding/types.d.ts +388 -0
- package/dist/onboarding/types.d.ts.map +1 -0
- package/dist/onboarding/types.js +35 -0
- package/dist/onboarding/types.js.map +1 -0
- package/dist/orchestration/index.d.ts +8 -0
- package/dist/orchestration/index.d.ts.map +1 -0
- package/dist/orchestration/index.js +706 -0
- package/dist/orchestration/index.js.map +1 -0
- package/dist/orchestration/types.d.ts +391 -0
- package/dist/orchestration/types.d.ts.map +1 -0
- package/dist/orchestration/types.js +30 -0
- package/dist/orchestration/types.js.map +1 -0
- package/dist/personality/index.d.ts +65 -0
- package/dist/personality/index.d.ts.map +1 -0
- package/dist/personality/index.js +339 -0
- package/dist/personality/index.js.map +1 -0
- package/dist/personality/types.d.ts +103 -0
- package/dist/personality/types.d.ts.map +1 -0
- package/dist/personality/types.js +15 -0
- package/dist/personality/types.js.map +1 -0
- package/dist/provider/index.d.ts +4 -0
- package/dist/provider/index.d.ts.map +1 -0
- package/dist/provider/index.js +236 -0
- package/dist/provider/index.js.map +1 -0
- package/dist/provider/types.d.ts +180 -0
- package/dist/provider/types.d.ts.map +1 -0
- package/dist/provider/types.js +4 -0
- package/dist/provider/types.js.map +1 -0
- package/dist/runtime/agent-cards.d.ts +14 -0
- package/dist/runtime/agent-cards.d.ts.map +1 -0
- package/dist/runtime/agent-cards.js +90 -0
- package/dist/runtime/agent-cards.js.map +1 -0
- package/dist/runtime/agent-runner.d.ts +30 -0
- package/dist/runtime/agent-runner.d.ts.map +1 -0
- package/dist/runtime/agent-runner.js +37 -0
- package/dist/runtime/agent-runner.js.map +1 -0
- package/dist/runtime/budget.d.ts +15 -0
- package/dist/runtime/budget.d.ts.map +1 -0
- package/dist/runtime/budget.js +24 -0
- package/dist/runtime/budget.js.map +1 -0
- package/dist/runtime/delegation-driver.d.ts +11 -0
- package/dist/runtime/delegation-driver.d.ts.map +1 -0
- package/dist/runtime/delegation-driver.js +132 -0
- package/dist/runtime/delegation-driver.js.map +1 -0
- package/dist/runtime/exact-cache.d.ts +10 -0
- package/dist/runtime/exact-cache.d.ts.map +1 -0
- package/dist/runtime/exact-cache.js +30 -0
- package/dist/runtime/exact-cache.js.map +1 -0
- package/dist/runtime/execute-tool.d.ts +29 -0
- package/dist/runtime/execute-tool.d.ts.map +1 -0
- package/dist/runtime/execute-tool.js +80 -0
- package/dist/runtime/execute-tool.js.map +1 -0
- package/dist/runtime/guardian.d.ts +9 -0
- package/dist/runtime/guardian.d.ts.map +1 -0
- package/dist/runtime/guardian.js +41 -0
- package/dist/runtime/guardian.js.map +1 -0
- package/dist/runtime/hook-gate.d.ts +17 -0
- package/dist/runtime/hook-gate.d.ts.map +1 -0
- package/dist/runtime/hook-gate.js +56 -0
- package/dist/runtime/hook-gate.js.map +1 -0
- package/dist/runtime/memory-adapter.d.ts +6 -0
- package/dist/runtime/memory-adapter.d.ts.map +1 -0
- package/dist/runtime/memory-adapter.js +38 -0
- package/dist/runtime/memory-adapter.js.map +1 -0
- package/dist/runtime/nightly-adapters.d.ts +48 -0
- package/dist/runtime/nightly-adapters.d.ts.map +1 -0
- package/dist/runtime/nightly-adapters.js +139 -0
- package/dist/runtime/nightly-adapters.js.map +1 -0
- package/dist/runtime/nightly-generator.d.ts +10 -0
- package/dist/runtime/nightly-generator.d.ts.map +1 -0
- package/dist/runtime/nightly-generator.js +335 -0
- package/dist/runtime/nightly-generator.js.map +1 -0
- package/dist/runtime/onboarding-node.d.ts +6 -0
- package/dist/runtime/onboarding-node.d.ts.map +1 -0
- package/dist/runtime/onboarding-node.js +356 -0
- package/dist/runtime/onboarding-node.js.map +1 -0
- package/dist/runtime/provider-anthropic.d.ts +43 -0
- package/dist/runtime/provider-anthropic.d.ts.map +1 -0
- package/dist/runtime/provider-anthropic.js +148 -0
- package/dist/runtime/provider-anthropic.js.map +1 -0
- package/dist/runtime/provider-cli.d.ts +18 -0
- package/dist/runtime/provider-cli.d.ts.map +1 -0
- package/dist/runtime/provider-cli.js +73 -0
- package/dist/runtime/provider-cli.js.map +1 -0
- package/dist/runtime/provider-openai.d.ts +30 -0
- package/dist/runtime/provider-openai.d.ts.map +1 -0
- package/dist/runtime/provider-openai.js +114 -0
- package/dist/runtime/provider-openai.js.map +1 -0
- package/dist/runtime/providers.d.ts +43 -0
- package/dist/runtime/providers.d.ts.map +1 -0
- package/dist/runtime/providers.js +72 -0
- package/dist/runtime/providers.js.map +1 -0
- package/dist/runtime/sandbox-bash.d.ts +21 -0
- package/dist/runtime/sandbox-bash.d.ts.map +1 -0
- package/dist/runtime/sandbox-bash.js +51 -0
- package/dist/runtime/sandbox-bash.js.map +1 -0
- package/dist/runtime/scoped-tool-executor.d.ts +10 -0
- package/dist/runtime/scoped-tool-executor.d.ts.map +1 -0
- package/dist/runtime/scoped-tool-executor.js +30 -0
- package/dist/runtime/scoped-tool-executor.js.map +1 -0
- package/dist/runtime/session-log.d.ts +6 -0
- package/dist/runtime/session-log.d.ts.map +1 -0
- package/dist/runtime/session-log.js +54 -0
- package/dist/runtime/session-log.js.map +1 -0
- package/dist/runtime/settings.d.ts +24 -0
- package/dist/runtime/settings.d.ts.map +1 -0
- package/dist/runtime/settings.js +29 -0
- package/dist/runtime/settings.js.map +1 -0
- package/dist/runtime/spawn-plan.d.ts +13 -0
- package/dist/runtime/spawn-plan.d.ts.map +1 -0
- package/dist/runtime/spawn-plan.js +107 -0
- package/dist/runtime/spawn-plan.js.map +1 -0
- package/dist/runtime/spend.d.ts +41 -0
- package/dist/runtime/spend.d.ts.map +1 -0
- package/dist/runtime/spend.js +0 -0
- package/dist/runtime/spend.js.map +1 -0
- package/dist/runtime/sub-agent-runner.d.ts +19 -0
- package/dist/runtime/sub-agent-runner.d.ts.map +1 -0
- package/dist/runtime/sub-agent-runner.js +47 -0
- package/dist/runtime/sub-agent-runner.js.map +1 -0
- package/dist/safety/grants.d.ts +7 -0
- package/dist/safety/grants.d.ts.map +1 -0
- package/dist/safety/grants.js +53 -0
- package/dist/safety/grants.js.map +1 -0
- package/dist/safety/index.d.ts +72 -0
- package/dist/safety/index.d.ts.map +1 -0
- package/dist/safety/index.js +464 -0
- package/dist/safety/index.js.map +1 -0
- package/dist/safety/types.d.ts +254 -0
- package/dist/safety/types.d.ts.map +1 -0
- package/dist/safety/types.js +3 -0
- package/dist/safety/types.js.map +1 -0
- package/dist/skills/index.d.ts +4 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +463 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/types.d.ts +177 -0
- package/dist/skills/types.d.ts.map +1 -0
- package/dist/skills/types.js +3 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/testing/clock.d.ts +8 -0
- package/dist/testing/clock.d.ts.map +1 -0
- package/dist/testing/clock.js +13 -0
- package/dist/testing/clock.js.map +1 -0
- package/dist/testing/effect-verifier.d.ts +15 -0
- package/dist/testing/effect-verifier.d.ts.map +1 -0
- package/dist/testing/effect-verifier.js +27 -0
- package/dist/testing/effect-verifier.js.map +1 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/provider-fake.d.ts +14 -0
- package/dist/testing/provider-fake.d.ts.map +1 -0
- package/dist/testing/provider-fake.js +18 -0
- package/dist/testing/provider-fake.js.map +1 -0
- package/dist/testing/sandbox-stub.d.ts +15 -0
- package/dist/testing/sandbox-stub.d.ts.map +1 -0
- package/dist/testing/sandbox-stub.js +15 -0
- package/dist/testing/sandbox-stub.js.map +1 -0
- package/dist/tools/index.d.ts +11 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +0 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/types.d.ts +138 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +4 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/triggers/index.d.ts +4 -0
- package/dist/triggers/index.d.ts.map +1 -0
- package/dist/triggers/index.js +187 -0
- package/dist/triggers/index.js.map +1 -0
- package/dist/triggers/types.d.ts +74 -0
- package/dist/triggers/types.d.ts.map +1 -0
- package/dist/triggers/types.js +5 -0
- package/dist/triggers/types.js.map +1 -0
- 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
|