@christang/keel 5.3.0 → 5.3.3

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.
@@ -1,8 +1,8 @@
1
- <!-- keel:start version=5.3.0 -->
1
+ <!-- keel:start version=5.3.3 -->
2
2
  ## Keel Bootstrap
3
3
 
4
4
  - Start every session with `keel context`; OpenSpec artifacts and Git are the only durable authority — never native memory, goals, or transcripts.
5
- - Obey the selected task capsule: `keel gate task-start` before implementing, record its fingerprint in the task Evidence `Contract` line, and pass `keel gate task-complete` before checking complete. Touch is the write boundary; on Claude a passing `task-start` guards it by default (`--no-guard`/`keel guard clear` opt out).
5
+ - Obey the selected task capsule: `keel gate task-start` before implementing, record its fingerprint in Evidence `Contract`, and pass `keel gate task-complete` before checking complete. Touch is the write boundary for product files; on Claude a passing `task-start` guards it by default (`--no-guard`/`keel guard clear` opt out).
6
6
  - One current agent owns writes; helpers return read-only report/evidence only. No commit, sync, or archive without explicit authorization.
7
7
  - Native plugin projections (SessionStart context) are disposable views, never authority; without the plugin or hook, run the commands manually.
8
8
  - Keel skills and hooks come from the `keel` native plugin (`codex plugin add` / `claude plugin install`); `keel --init` owns only the OpenSpec schema, overlays, and this bootstrap.
@@ -139,8 +139,18 @@ artifacts:
139
139
  are `none` or carry a durable owner — a `Discard reason:`/`Discard
140
140
  rationale:` prefix, a `keel/archive/…` path, or an existing
141
141
  `openspec/changes/…` artifact; `keel/HANDOFF.md` is never the owner.
142
- tasks.md ends with a `## Expectation Coverage` section that change-close
143
- requires: one `- E<n>: <expectation> Covered by: <task ids>` line per
142
+ tasks.md carries two change-level sections beside its tasks.
143
+ `## Invalidates` is required by task-start, before any task of the
144
+ change runs: one `- I<n>: "the wording that is now wrong" — where it lives.`
145
+ line per statement this change makes stale, closed by `Updated by: <task
146
+ ids>` naming tasks of this change, a `Durable owner:`, or a `Discard
147
+ reason:`, or `- None.` when the change makes no existing statement wrong.
148
+ Quote the wording a reader would search for rather than only listing
149
+ files, because the text that goes stale is the text the author was not
150
+ already holding in mind; naming it while tasks are authored is what lets
151
+ the affected paths be declared in Touch instead of forcing a
152
+ reauthorization mid-task. `## Expectation Coverage` is required by
153
+ change-close: one `- E<n>: <expectation> Covered by: <task ids>` line per
144
154
  critical expectation (or a `Durable owner:` / `Discard reason:` closure),
145
155
  or `- None.` when the change has no critical expectations.
146
156
  requires:
@@ -76,6 +76,22 @@
76
76
  - Findings: pending
77
77
  - Blocker: none
78
78
 
79
+ ## Invalidates
80
+
81
+ <!-- task-start requires this section before any task of this change runs, so
82
+ the statements this change makes stale can be named while their paths can
83
+ still be declared in Touch instead of forcing a reauthorization later.
84
+ Each entry quotes the wording a reader would SEARCH for — not just the
85
+ files you already remembered, because the text that goes stale is the text
86
+ you were not thinking about — then says where it lives, then closes:
87
+ `Updated by: 1.1` (tasks of this change), `Durable owner: <url or path>`,
88
+ or `Discard reason: why it stands`. Use `- None.` when this change makes
89
+ no existing statement wrong.
90
+
91
+ - I1: "the exact wording that is now wrong" — where that wording lives. Updated by: 1.1
92
+ -->
93
+ - None.
94
+
79
95
  ## Expectation Coverage
80
96
 
81
97
  <!-- change-close requires this section. One line per critical expectation:
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@christang/keel",
3
3
  "displayName": "Keel",
4
4
  "description": "Keel OpenSpec execution discipline CLI for Claude Code, Codex, and OpenCode.",
5
- "version": "5.3.0",
5
+ "version": "5.3.3",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keel",
3
- "version": "5.3.0",
3
+ "version": "5.3.3",
4
4
  "description": "Keel OpenSpec execution discipline: stateless continuity, task capsules, deterministic gates, and expectation alignment for Codex and Claude Code.",
5
5
  "author": {
6
6
  "name": "TanglmChris",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keel",
3
- "version": "5.3.0",
3
+ "version": "5.3.3",
4
4
  "description": "Keel OpenSpec execution discipline: stateless continuity, task capsules, deterministic gates, and expectation alignment for Codex and Claude Code.",
5
5
  "author": {
6
6
  "name": "TanglmChris",
@@ -15,6 +15,11 @@ const fs = require("fs");
15
15
  const path = require("path");
16
16
  const { spawnSync } = require("child_process");
17
17
 
18
+ // This text is injected into the agent and never rendered for the human, so
19
+ // without an explicit instruction the projection reaches nobody who can catch
20
+ // it being wrong. Every branch carries the same phrase, degraded ones included.
21
+ const DISCLOSURE = "to the user in your first reply";
22
+
18
23
  const TIMEOUT_MS = Number(process.env.KEEL_HOOK_TIMEOUT_MS || 8000) || 8000;
19
24
  const MAX_REASONS = 3;
20
25
  const MAX_REASON_LENGTH = 300;
@@ -51,7 +56,8 @@ function runKeel(cwd, args) {
51
56
  function fallback(reason) {
52
57
  emit(
53
58
  `Keel hook fallback: ${reason} Run \`keel context\` manually; `
54
- + "OpenSpec and Git remain the durable authority."
59
+ + "OpenSpec and Git remain the durable authority. Report this failure "
60
+ + `and that command ${DISCLOSURE}.`
55
61
  );
56
62
  }
57
63
 
@@ -145,6 +151,7 @@ function main() {
145
151
  + "does not guess among candidates."
146
152
  );
147
153
  }
154
+ lines.push(`- report this state ${DISCLOSURE}; it authorizes nothing.`);
148
155
  emit(lines.join("\n"));
149
156
  return 0;
150
157
  }