@christang/keel 5.1.1

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 (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +250 -0
  3. package/README.zh-CN.md +295 -0
  4. package/assets/bootstrap/AGENTS.md +9 -0
  5. package/assets/openspec/schemas/keel-spec-driven/schema.yaml +166 -0
  6. package/assets/openspec/schemas/keel-spec-driven/templates/design.md +52 -0
  7. package/assets/openspec/schemas/keel-spec-driven/templates/proposal.md +21 -0
  8. package/assets/openspec/schemas/keel-spec-driven/templates/spec.md +8 -0
  9. package/assets/openspec/schemas/keel-spec-driven/templates/tasks.md +68 -0
  10. package/bin/keel.js +1490 -0
  11. package/package.json +35 -0
  12. package/plugins/keel/.claude-plugin/plugin.json +17 -0
  13. package/plugins/keel/.codex-plugin/plugin.json +29 -0
  14. package/plugins/keel/agents/keel-single-task-goal-claude.md +16 -0
  15. package/plugins/keel/agents/keel-single-task-goal-codex.md +16 -0
  16. package/plugins/keel/hooks/hooks.json +30 -0
  17. package/plugins/keel/scripts/pretooluse-guard.js +156 -0
  18. package/plugins/keel/scripts/session-start.js +182 -0
  19. package/plugins/keel/skills/keel-align-expectations/SKILL.md +53 -0
  20. package/plugins/keel/skills/keel-align-expectations/references/hardware-dsl.md +21 -0
  21. package/plugins/keel/skills/keel-align-expectations/references/hardware.md +21 -0
  22. package/plugins/keel/skills/keel-align-expectations/references/web.md +21 -0
  23. package/plugins/keel/skills/keel-debug-failure/SKILL.md +41 -0
  24. package/plugins/keel/skills/keel-handoff/SKILL.md +45 -0
  25. package/plugins/keel/skills/keel-review-checklist/SKILL.md +73 -0
  26. package/plugins/keel/skills/keel-run-single-task-goal/SKILL.md +68 -0
  27. package/plugins/keel/skills/keel-tdd-or-test-first/SKILL.md +45 -0
  28. package/scripts/install_to_repo.py +1122 -0
  29. package/scripts/run_python.js +63 -0
  30. package/scripts/validate_plugin.py +9869 -0
  31. package/src/core/capabilities.js +291 -0
  32. package/src/core/context.js +514 -0
  33. package/src/core/gates.js +643 -0
  34. package/src/core/goal.js +230 -0
  35. package/src/core/guard.js +295 -0
  36. package/src/core/helper.js +319 -0
  37. package/src/core/projection.js +195 -0
  38. package/src/core/task-contract.js +736 -0
  39. package/src/core/tasksview.js +123 -0
@@ -0,0 +1,291 @@
1
+ "use strict";
2
+
3
+ // Keel 4.1.0 capability contract.
4
+
5
+ const fs = require("fs");
6
+ const os = require("os");
7
+ const path = require("path");
8
+ const { guardStatus } = require("./guard");
9
+
10
+ const CAPABILITY_COMMANDS = {
11
+ "continuity.start": "keel project --target <target> --event startup --json",
12
+ "continuity.reinject":
13
+ "keel project --target <target> --event resume --json",
14
+ "gate.task-start": "keel gate task-start --change <change> --task <task> --json",
15
+ "gate.task-complete":
16
+ "keel gate task-complete --change <change> --task <task> --json",
17
+ "gate.change-close":
18
+ "keel gate change-close --change <change> --action <sync|archive> --json",
19
+ "execution.goal":
20
+ "keel project --target <target> --event goal --authorize goal --json",
21
+ "execution.task-view":
22
+ "keel project --target <target> --event task-view --authorize task-view --json",
23
+ "execution.worktree":
24
+ "keel project --target <target> --event worktree --expected-owner <owner> --json",
25
+ "delegation.context":
26
+ "keel project --target <target> --event subagent-start --authorize subagent --json",
27
+ "delegation.return":
28
+ "keel project --target <target> --event subagent-stop --authorize subagent --json",
29
+ };
30
+
31
+ const SUPPORTED_TARGETS = new Set(["claude", "codex", "opencode"]);
32
+
33
+ function codexHome() {
34
+ const configured = (process.env.CODEX_HOME || "").trim();
35
+ return path.resolve(configured || path.join(os.homedir(), ".codex"));
36
+ }
37
+
38
+ function pluginObservation(repo, target) {
39
+ if (target === "opencode") {
40
+ return "OpenCode has no v4 native plugin surface; manual CLI compatibility only";
41
+ }
42
+ const manifestRelative = path.join(
43
+ "plugins",
44
+ "keel",
45
+ target === "codex" ? ".codex-plugin" : ".claude-plugin",
46
+ "plugin.json"
47
+ );
48
+ const manifestPath = path.join(repo, manifestRelative);
49
+ let sourceState = `plugin source absent at ${manifestRelative}`;
50
+ if (fs.existsSync(manifestPath)) {
51
+ try {
52
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
53
+ sourceState =
54
+ manifest.name === "keel" && manifest.version
55
+ ? `plugin source valid at ${manifestRelative} (version ${manifest.version})`
56
+ : `plugin source invalid at ${manifestRelative}`;
57
+ } catch {
58
+ sourceState = `plugin source unreadable at ${manifestRelative}`;
59
+ }
60
+ }
61
+ return (
62
+ `${sourceState}; installed/enabled/trusted/active/behavior-verified plugin `
63
+ + "states need native runtime evidence and remain advisory or manual "
64
+ + "until probed"
65
+ );
66
+ }
67
+
68
+ function targetObservation(repo, target) {
69
+ const observations = [];
70
+ observations.push(pluginObservation(repo, target));
71
+
72
+ if (target === "claude") {
73
+ const hook = path.join(
74
+ repo,
75
+ ".claude",
76
+ "hooks",
77
+ "keel-gate",
78
+ "keel-gate.js"
79
+ );
80
+ const settings = path.join(repo, ".claude", "settings.json");
81
+ if (fs.existsSync(hook) && fs.existsSync(settings)) {
82
+ observations.push(
83
+ "Claude hook files and project settings are present; runtime trust, "
84
+ + "activation, and reliable blocking are not verifiable"
85
+ );
86
+ } else {
87
+ observations.push("Claude hook activation evidence is incomplete");
88
+ }
89
+ } else if (target === "codex") {
90
+ const hooks = path.join(codexHome(), "hooks.json");
91
+ observations.push(
92
+ fs.existsSync(hooks)
93
+ ? "Codex hook-like state exists but enablement, trust, version, and "
94
+ + "blocking behavior are unverified"
95
+ : "Codex activation evidence is unavailable"
96
+ );
97
+ } else {
98
+ const plugins = path.join(repo, ".opencode", "plugins");
99
+ observations.push(
100
+ fs.existsSync(plugins)
101
+ ? "OpenCode plugin state exists but enablement, version, and blocking "
102
+ + "behavior are unverified"
103
+ : "OpenCode activation evidence is unavailable"
104
+ );
105
+ }
106
+ return observations.join("; ");
107
+ }
108
+
109
+ function probeCapabilities(repo, target) {
110
+ if (!SUPPORTED_TARGETS.has(target)) {
111
+ throw new Error(`unsupported target: ${target}`);
112
+ }
113
+ const observation = targetObservation(repo, target);
114
+ const capabilities = {};
115
+ for (const [key, command] of Object.entries(CAPABILITY_COMMANDS)) {
116
+ capabilities[key] = {
117
+ level: "manual",
118
+ surface: "explicit Keel Core command",
119
+ evidence: observation,
120
+ command,
121
+ };
122
+ }
123
+ return {
124
+ schemaVersion: 1,
125
+ target,
126
+ capabilities,
127
+ helper: helperDiagnostics(repo, target, observation),
128
+ guard: guardDiagnostics(repo, target),
129
+ compaction: compactionDiagnostics(target),
130
+ warnings: [
131
+ "No capability is promoted above manual without verifiable runtime "
132
+ + "activation, trust, version, and behavior evidence.",
133
+ "Helper absence never disables current-agent goal execution; goal, "
134
+ + "gates, and the manual loop stay usable without any helper.",
135
+ ],
136
+ };
137
+ }
138
+
139
+ function helperDiagnostics(repo, target, observation) {
140
+ // Each dimension is reported separately with its own enforced/advisory/manual
141
+ // level: byte-stability and nested-delegation prevention are enforced by Keel
142
+ // Core deterministically, native tool restriction and discovery stay advisory
143
+ // until runtime-probed, and actual native helper execution stays manual.
144
+ return {
145
+ discovery: {
146
+ level: "advisory",
147
+ evidence: observation,
148
+ },
149
+ toolRestriction: {
150
+ level: "advisory",
151
+ evidence:
152
+ "Native helper tool allowlists are runtime-configured and cannot be "
153
+ + "verified from Keel Core.",
154
+ },
155
+ nestedDelegationPrevention: {
156
+ level: "enforced",
157
+ evidence:
158
+ "keel project helper compiles a non-delegating brief and refuses "
159
+ + "nested helpers or spawned agents.",
160
+ },
161
+ byteStability: {
162
+ level: "enforced",
163
+ evidence:
164
+ "keel project helper --verify accepts a return only after before/after "
165
+ + "repository byte identity and never cleans up.",
166
+ },
167
+ execution: {
168
+ level: "manual",
169
+ evidence:
170
+ "Native bounded-helper execution stays manual until runtime activation, "
171
+ + "trust, and tool restriction are probed.",
172
+ },
173
+ };
174
+ }
175
+
176
+ function guardDiagnostics(repo, target) {
177
+ // The write guard is Claude-only in v4: the plugin ships a deterministic
178
+ // manifest-gated PreToolUse denial, but runtime activation, trust, and
179
+ // reliable blocking cannot be verified from Keel Core, so the shipped
180
+ // level stays advisory until behaviorally probed. Other targets have no
181
+ // verified guard hook surface and stay manual.
182
+ if (target !== "claude") {
183
+ return {
184
+ enforcement: {
185
+ level: "manual",
186
+ evidence:
187
+ `${target} has no verified native guard hook surface; the Touch `
188
+ + "write boundary stays disciplinary via the resident protocol.",
189
+ },
190
+ };
191
+ }
192
+ const manifestState = guardStatus(repo).status;
193
+ return {
194
+ hookDelivery: {
195
+ level: "advisory",
196
+ evidence:
197
+ "The keel plugin ships a manifest-gated PreToolUse hook; runtime "
198
+ + "activation, trust, and enablement need native runtime evidence.",
199
+ },
200
+ manifest: {
201
+ level: "advisory",
202
+ evidence: `keel/guard.json state observed as ${manifestState}.`,
203
+ },
204
+ enforcement: {
205
+ level: "advisory",
206
+ evidence:
207
+ "Out-of-Touch denial is deterministic in the shipped hook; promotion "
208
+ + "above advisory requires behavioral runtime probe evidence of an "
209
+ + "actual blocked call.",
210
+ },
211
+ boundary: {
212
+ level: "advisory",
213
+ evidence:
214
+ "The guard covers file-edit tools only (Edit, Write, NotebookEdit); "
215
+ + "Bash and other indirect writes stay disciplinary, and paths outside "
216
+ + "the repository are not product writes.",
217
+ },
218
+ };
219
+ }
220
+
221
+ function compactionDiagnostics(target) {
222
+ // Pre-compaction preservation is probed, not assumed: no pre-compaction
223
+ // hook is registered anywhere until a behavioral probe proves the contract,
224
+ // so the shipped behavior is post-compact reinjection on Claude and the
225
+ // manual `keel project --event compaction` command elsewhere.
226
+ if (target === "claude") {
227
+ return {
228
+ postCompactReinjection: {
229
+ level: "advisory",
230
+ evidence:
231
+ "The plugin SessionStart hook reinjects the recomputed task pointer "
232
+ + "after a compact-source start; delivery of the compact source "
233
+ + "needs native runtime evidence.",
234
+ },
235
+ preCompaction: {
236
+ level: "manual",
237
+ evidence:
238
+ "No pre-compaction hook is registered; the pre-compaction "
239
+ + "preservation contract stays unverified until behaviorally "
240
+ + "probed, and post-compact reinjection is the shipped fallback.",
241
+ },
242
+ };
243
+ }
244
+ return {
245
+ postCompactReinjection: {
246
+ level: "manual",
247
+ evidence:
248
+ `${target} has no verified compaction hook surface; reinject manually `
249
+ + `with keel project --target ${target} --event compaction --json.`,
250
+ },
251
+ preCompaction: {
252
+ level: "manual",
253
+ evidence:
254
+ "No verified pre-compaction surface; manual post-compaction "
255
+ + "reinjection is the declared fallback.",
256
+ },
257
+ };
258
+ }
259
+
260
+ function renderCapabilities(result) {
261
+ const lines = [`Target capabilities (${result.target}):`];
262
+ for (const [key, capability] of Object.entries(result.capabilities)) {
263
+ lines.push(
264
+ `${key}: ${capability.level} - ${capability.evidence}; `
265
+ + `command: ${capability.command}`
266
+ );
267
+ }
268
+ if (result.helper) {
269
+ for (const [dimension, entry] of Object.entries(result.helper)) {
270
+ lines.push(`helper ${dimension}: ${entry.level} - ${entry.evidence}`);
271
+ }
272
+ }
273
+ if (result.guard) {
274
+ for (const [dimension, entry] of Object.entries(result.guard)) {
275
+ lines.push(`guard ${dimension}: ${entry.level} - ${entry.evidence}`);
276
+ }
277
+ }
278
+ if (result.compaction) {
279
+ for (const [dimension, entry] of Object.entries(result.compaction)) {
280
+ lines.push(`compaction ${dimension}: ${entry.level} - ${entry.evidence}`);
281
+ }
282
+ }
283
+ for (const warning of result.warnings) lines.push(`capability warning: ${warning}`);
284
+ return `${lines.join("\n")}\n`;
285
+ }
286
+
287
+ module.exports = {
288
+ CAPABILITY_COMMANDS,
289
+ probeCapabilities,
290
+ renderCapabilities,
291
+ };