@renzrollon/interlock 1.5.0 → 1.5.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "interlock",
3
3
  "displayName": "Interlock",
4
- "version": "1.5.0",
4
+ "version": "1.5.1",
5
5
  "description": "Spec-driven development for Claude Code, layered on OpenSpec. You read one spec; parallel agents ship it to a tested commit.",
6
6
  "author": {
7
7
  "name": "Carl Rollon",
package/CHANGELOG.md CHANGED
@@ -7,6 +7,17 @@ this project adheres to Semantic Versioning 2.0.0.
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## 1.5.1 — 2026-10-11
11
+
12
+ ### Changed
13
+
14
+ - **`docs/08` is about Interlock's own harness.** It was a survey of OpenClaw, Hermes Agent and DeepSeek Harness. It now maps the parts of the harness, what holds on each host, and what is left out on purpose; the other projects are one comparison table. The page no longer says lane isolation is closed on the Workflow host, which still halts with `LANE BASE MISMATCH` after the first fold.
15
+ - **The README says what the one network call sends.** It said a push happens when `INTERLOCK_NTFY_TOPIC` is set. It now names what goes out (the close summary's first line, the change name and the run id; the change name at the spec checkpoint; the title and body of a `notify` you type), which server receives it, that the topic is the only thing in the request that identifies you, and that no request is made without one. It also says the plugin's `ntfy topic` option reaches the CLI through the session's environment, and that `interlock doctor` reads a model credential by name and never by value. The plugin directory holds a plugin that reads a value from the environment and posts to a server until a reviewer has read this.
16
+
17
+ ### Fixed
18
+
19
+ - **The session-start hook returns the forward itself.** The `classic.SessionStart` hook in `hooks/mod.mjs` held the forward in a variable, awaited the preflight read, and returned the variable. The plugin directory's reader could not tell that return from a first message or a permission decision of the hook's own, and held the version. The hook now returns the forward call, continued once to read the preflight's report and hand back the value the chain resolved with. Nothing a session sees changes: the read still finishes before the event resolves, and a chain that rejects still skips it. `test/mod/session-start.test.ts` and `test/spine/mod-pins.test.mjs` cover it unchanged.
20
+
10
21
  ## 1.5.0 — 2026-10-11
11
22
 
12
23
  ### Added
package/README.md CHANGED
@@ -96,7 +96,7 @@ Most of the category competes on how much structure you write before coding —
96
96
  | OpenSpec | the artifact loop and its CLI | the CLI validates artifacts; skills run the loop |
97
97
  | **Interlock** | how many decisions the model may not make | a CLI with exit codes, and a runtime with no channel for a question |
98
98
 
99
- It composes OpenSpec rather than replacing it. `openspec init` installs its own skills, and `/interlock:spec` drives the `openspec` CLI directly, so both stay available. Use `/interlock:spec` when you want the gates, and the stock skills when you want the plain artifact loop. What Interlock adds, and when plain OpenSpec is the right call: [03](docs/03-openspec-vs-interlock.md). Where it sits against OpenClaw, Hermes Agent and DeepSeek Harness: [08](docs/08-harness-landscape.md).
99
+ It composes OpenSpec rather than replacing it. `openspec init` installs its own skills, and `/interlock:spec` drives the `openspec` CLI directly, so both stay available. Use `/interlock:spec` when you want the gates, and the stock skills when you want the plain artifact loop. What Interlock adds, and when plain OpenSpec is the right call: [03](docs/03-openspec-vs-interlock.md). What the harness is made of, and where it sits beside OpenClaw, Hermes Agent and DeepSeek Harness: [08](docs/08-harness-landscape.md).
100
100
 
101
101
  The trade is portability. Claude Code is the **default and supported host**; Cursor and Copilot are not supported. Everything the loop decides lives in a CLI any host can shell out to, so portability means a second host adapter, not thirty prompt templates.
102
102
 
@@ -118,7 +118,7 @@ Three zero-dependency Node binaries land on your `PATH`, and they work without t
118
118
  | `interlock-graph` | A local, deterministic code knowledge graph. No vector store, no network |
119
119
  | `interlock-run` | The experimental runner above |
120
120
 
121
- Everything runs without a model and without the network, with one exception. `interlock notify` and `run close --notify` push a message when a run halts or completes, and only when `INTERLOCK_NTFY_TOPIC` is set; `INTERLOCK_NTFY_URL` points it at a self-hosted server. Reference and every environment variable: [07 — CLI and configuration](docs/07-cli-and-configuration.md).
121
+ Everything runs without a model and without the network, with one exception: an opt-in push for a run that stops while nobody is watching. `run close --notify` sends the close summary's first line, the change name and the run id; the spec checkpoint sends the change name; an `interlock notify` you type sends the title and body you give it. The request goes to the [ntfy](https://ntfy.sh) server named by `INTERLOCK_NTFY_URL`, the public `https://ntfy.sh` by default, under the topic you chose in the plugin's `ntfy topic` option or in `INTERLOCK_NTFY_TOPIC`. Session start copies a set option into the session's environment when the variable is not already set, because the CLI call that pushes is not a hook and the option reaches hooks only. No account, key or token goes with the request: the topic is the only thing in it that identifies you, so treat it as a secret. With no topic set, no request is ever made. Interlock makes no other request. `interlock doctor` reports whether `ANTHROPIC_API_KEY` or `CLAUDE_CODE_OAUTH_TOKEN` is set, by name and never by value, and the vendor CLIs a run spawns inherit the environment as any child process does; what they send is theirs. Reference and every environment variable: [07 — CLI and configuration](docs/07-cli-and-configuration.md).
122
122
 
123
123
  ## Docs
124
124
 
@@ -133,7 +133,7 @@ New here? Start with **[01 — The first hour](docs/01-first-hour.md)**. Only ev
133
133
  | [05 — Continuity](docs/05-continuity.md) | When `--continue` may skip the human read |
134
134
  | [06 — Why it works](docs/06-why-it-works.md) | The mechanisms, low-level, with the costs stated |
135
135
  | [07 — CLI and configuration](docs/07-cli-and-configuration.md) | Every subcommand, environment variable and host |
136
- | [08 — The harness landscape](docs/08-harness-landscape.md) | OpenClaw, Hermes Agent, DeepSeek Harness, and the spec-driven neighbours |
136
+ | [08 — The Interlock harness](docs/08-harness-landscape.md) | The parts of the harness, what holds on each host, and a short comparison with other harnesses |
137
137
  | [09 — From prompt to workflow](docs/09-from-prompt-to-workflow.md) | New to agentic workflows? Every term defined, then why `ship` is a script |
138
138
  | [10 — Ship and spec for prompt-only engineers](docs/10-agentic-workflow-ship-and-spec.md) | Primer, review of spec+ship, token and quality tactics |
139
139
  | [11 — The indicators](docs/11-the-indicators.md) | What `interlock report` measures and why it gates nothing; whether to commit the run corpora |
package/hooks/mod.mjs CHANGED
@@ -2125,14 +2125,18 @@ export function register(on) {
2125
2125
  // The kit raises this event; Claude Code 2.1.291 raises no classic event to
2126
2126
  // a module, so there the prompt hook above reads the report instead.
2127
2127
  //
2128
- // Pass the event on unchanged. The value this hook returns is the forward
2129
- // itself: no first message, no permission decision. The meter's reset runs
2130
- // before that chain and the preflight read after it; neither becomes the return.
2128
+ // Pass the event on unchanged. The hook returns the forward call itself,
2129
+ // continued once: when the chain beneath has resolved, the preflight's
2130
+ // report is read, and the continuation hands back the value that chain
2131
+ // resolved with, as it came. No first message and no permission decision
2132
+ // come from this hook. The meter's reset runs before the chain. A chain
2133
+ // that rejects skips the read, and the rejection goes on as it came.
2131
2134
  on('classic.SessionStart', async (meterSessionApi, meterSessionInput, meterSessionForward) => {
2132
2135
  endRunAtBoundary(meterSessionApi, meterSessionInput)
2133
- const sessionForwarded = meterSessionForward(meterSessionInput)
2134
- await sessionForwarded.then(() => readPreflightAfterStart(meterSessionApi, meterSessionInput))
2135
- return sessionForwarded
2136
+ return meterSessionForward(meterSessionInput).then(async started => {
2137
+ await readPreflightAfterStart(meterSessionApi, meterSessionInput)
2138
+ return started
2139
+ })
2136
2140
  })
2137
2141
 
2138
2142
  on('ui.render', { component: 'Spinner' }, ($, e, next) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@renzrollon/interlock",
3
- "version": "1.5.0",
3
+ "version": "1.5.1",
4
4
  "description": "Spec-driven development for Claude Code, layered on OpenSpec. You read one spec; parallel agents ship it to a tested commit.",
5
5
  "type": "module",
6
6
  "engines": {