@kawacode/mcp 6.6.1 → 6.8.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.
- package/CLAUDE.md.example +21 -0
- package/README.md +16 -0
- package/build/kawacode-on-pre-edit.js +33 -4
- package/build/kawacode-on-pre-edit.js.map +1 -1
- package/build/kawacode-on-stop.d.ts +9 -5
- package/build/kawacode-on-stop.js +125 -26
- package/build/kawacode-on-stop.js.map +1 -1
- package/build/services/muninn-ipc.d.ts +13 -6
- package/build/services/muninn-ipc.js +35 -14
- package/build/services/muninn-ipc.js.map +1 -1
- package/build/stop/uncompleted-commit.d.ts +60 -7
- package/build/stop/uncompleted-commit.js +132 -23
- package/build/stop/uncompleted-commit.js.map +1 -1
- package/build/stop/uncompleted-commit.test.js +100 -1
- package/build/stop/uncompleted-commit.test.js.map +1 -1
- package/build/telemetry.d.ts +65 -0
- package/build/telemetry.js +99 -0
- package/build/telemetry.js.map +1 -0
- package/build/tools/check-active-intent.js +30 -16
- package/build/tools/check-active-intent.js.map +1 -1
- package/build/tools/complete-intent.d.ts +14 -10
- package/build/tools/complete-intent.js +26 -57
- package/build/tools/complete-intent.js.map +1 -1
- package/build/tools/get-relevant-context.js +14 -1
- package/build/tools/get-relevant-context.js.map +1 -1
- package/build/tools/index.d.ts +6 -0
- package/build/tools/pre-edit-acknowledge.d.ts +12 -0
- package/build/tools/pre-edit-acknowledge.js +21 -0
- package/build/tools/pre-edit-acknowledge.js.map +1 -1
- package/package.json +1 -1
package/CLAUDE.md.example
CHANGED
|
@@ -20,6 +20,27 @@ Guidance for Claude Code when working in this repository.
|
|
|
20
20
|
|
|
21
21
|
Skip the entire workflow for trivial one-liners (typos, obvious bugs) — just make the change.
|
|
22
22
|
|
|
23
|
+
### Reuse before you build — and recall per sub-task, not just per turn
|
|
24
|
+
|
|
25
|
+
Before creating any new component, store, or shared utility:
|
|
26
|
+
|
|
27
|
+
1. **Search the codebase** (Grep/Explore) for an existing one — this is the *authoritative* existence check.
|
|
28
|
+
2. **`get_relevant_context`** on that area — this surfaces *why* it exists and the prior decisions around it.
|
|
29
|
+
|
|
30
|
+
`get_relevant_context` is semantic over **decisions and intents**, not a file index — an empty result is **not** proof the component doesn't exist. Always pair it with a codebase search before concluding you need to build something new.
|
|
31
|
+
|
|
32
|
+
Recall is scoped to a sub-task, not blanket coverage for the session. When a request **expands into a new area mid-turn** (e.g. a small fix grows into adding a new helper or UI component), re-run recall for the *new* area before writing — an earlier recall for a different sub-task doesn't cover it. **Self-initiated additions you bundle onto the original ask are where this gets skipped most.**
|
|
33
|
+
|
|
34
|
+
### Migrations & rewrites — recall-transplant from the source repo
|
|
35
|
+
|
|
36
|
+
When porting code from another repository (language port, rewrite, repo split), the source repo's decisions do NOT surface here automatically — recall is per-repo. Before porting each slice:
|
|
37
|
+
|
|
38
|
+
1. `get_relevant_context` against the **source** repo (its `repoPath`), describing the subsystem being ported + its key files.
|
|
39
|
+
2. `get_decision_detail` on the load-bearing hits.
|
|
40
|
+
3. Transplant only **stack-portable** decisions (domain truths, protocol contracts, cost/scale rationale, security discoveries, retired-approach warnings) — not the old stack's tooling/runtime mechanics.
|
|
41
|
+
4. `record_decision` them in **this** repo with provenance: `[transplanted from <source-repo> <decision-id>]`. Merge one-lineage decisions into a single record.
|
|
42
|
+
5. Let transplanted rationale drive the port's tests (a durability guarantee becomes a test; a retired approach must not be reintroduced).
|
|
43
|
+
|
|
23
44
|
---
|
|
24
45
|
|
|
25
46
|
## When to create an intent — vs skip
|
package/README.md
CHANGED
|
@@ -111,6 +111,22 @@ Disable telemetry with `KAWA_PRE_EDIT_TELEMETRY=off`.
|
|
|
111
111
|
- **Zero-knowledge encryption** — code blocks encrypted client-side before sync. The Kawa cloud cannot decrypt your team's code.
|
|
112
112
|
- **Cross-platform** — works with Claude Code, Cursor, and any MCP-compatible AI assistant.
|
|
113
113
|
|
|
114
|
+
## Migrating or rewriting a codebase? Transplant its decisions
|
|
115
|
+
|
|
116
|
+
When you port a codebase to a new language or rebuild it in a fresh repository, the code moves — but the *reasoning* usually doesn't. The source repo's decision history knows why retired approaches were retired, which constraints are load-bearing, and where the security landmines are. With Kawa Code, that history becomes a first-class migration input.
|
|
117
|
+
|
|
118
|
+
Decisions are scoped per repository, so the new repo won't surface the old repo's history automatically. Transplant them slice by slice as you port — this is the **recall-transplant workflow**:
|
|
119
|
+
|
|
120
|
+
1. **Recall before porting each slice.** Call `get_relevant_context` against the *source* repo with a description of the subsystem you're about to port (name its key files). This surfaces the forks, constraints, trade-offs, and discoveries that shaped it.
|
|
121
|
+
2. **Expand what matters.** Recall returns summaries — call `get_decision_detail` on the load-bearing hits for the full rationale and consequences.
|
|
122
|
+
3. **Classify: stack-portable vs stack-bound.** Domain truths port: protocol contracts, cost/scale rationale, security discoveries, "we tried X and retired it" warnings. Mechanics of the old stack don't: build-tooling quirks, runtime workarounds, library-specific fixes. Only the portable ones move.
|
|
123
|
+
4. **Re-record the portable ones in the *target* repo** with `record_decision`, citing provenance in the summary or rationale (e.g. `[transplanted from <source-repo> <decision-id>]`). Merge decisions that form one lineage into a single record.
|
|
124
|
+
5. **Let the transplants shape the port and its tests.** A transplanted durability rationale should become a test that proves the property survived the rewrite; a retired-approach warning should stop the new stack from reintroducing it.
|
|
125
|
+
|
|
126
|
+
The payoff compounds: the port doesn't re-litigate settled arguments or faithfully reproduce old bugs, *negative knowledge* survives even though the code that motivated it was deleted long ago, and at cutover the new repo starts with a curated decision corpus instead of an empty one.
|
|
127
|
+
|
|
128
|
+
The [CLAUDE.md template](./CLAUDE.md.example) ships a compact version of this workflow, so agents set up through the Kawa Code welcome flow follow it automatically.
|
|
129
|
+
|
|
114
130
|
## Development
|
|
115
131
|
|
|
116
132
|
```bash
|
|
@@ -30,9 +30,14 @@
|
|
|
30
30
|
* Opt out with KAWA_PRE_EDIT_CHECK=off.
|
|
31
31
|
*/
|
|
32
32
|
import { readFileSync } from 'node:fs';
|
|
33
|
-
import { connectToMuninn, request, disconnect } from './services/muninn-ipc.js';
|
|
33
|
+
import { connectToMuninn, request, disconnect, setQuiet } from './services/muninn-ipc.js';
|
|
34
34
|
import { resolveOrigin } from './tools/resolve-origin.js';
|
|
35
35
|
import { resolvePaths } from './pre-edit/path-resolve.js';
|
|
36
|
+
import { emitInjection, emitActedOn, estimateTokens } from './telemetry.js';
|
|
37
|
+
// Hook stderr is surfaced to the agent/user on exit-2 blocks — suppress the
|
|
38
|
+
// IPC lifecycle chatter so only the decision-check message comes through.
|
|
39
|
+
// KAWA_DEBUG=1 restores full logging for troubleshooting.
|
|
40
|
+
setQuiet(!process.env.KAWA_DEBUG);
|
|
36
41
|
function readStdin() {
|
|
37
42
|
try {
|
|
38
43
|
return readFileSync(0, 'utf8');
|
|
@@ -199,9 +204,9 @@ async function main() {
|
|
|
199
204
|
}
|
|
200
205
|
if (res?.recommendation === 'investigate-upstream') {
|
|
201
206
|
const force = payload.tool_input?.force === true;
|
|
207
|
+
const ids = (res.decisions ?? []).map(d => d.decisionId).filter(Boolean);
|
|
202
208
|
if (force) {
|
|
203
209
|
// Acknowledge surfaced decisions for this session, then allow.
|
|
204
|
-
const ids = (res.decisions ?? []).map(d => d.decisionId).filter(Boolean);
|
|
205
210
|
if (ids.length > 0) {
|
|
206
211
|
try {
|
|
207
212
|
await request('pre-edit-cache', 'add', {
|
|
@@ -213,22 +218,46 @@ async function main() {
|
|
|
213
218
|
/* best-effort */
|
|
214
219
|
}
|
|
215
220
|
}
|
|
221
|
+
// Track-B acted-on (VALUE_METRICS Phase 2): the agent consciously
|
|
222
|
+
// overrode the surfaced reasoning — it acted on the pre_edit injection.
|
|
223
|
+
// One signal per surfaced decision id (refId), origin in hand here.
|
|
224
|
+
try {
|
|
225
|
+
await Promise.allSettled(ids.map(id => emitActedOn({ type: 'pre_edit', refId: id, repoOrigin })));
|
|
226
|
+
}
|
|
227
|
+
catch { /* fire-and-forget */ }
|
|
216
228
|
disconnect();
|
|
217
229
|
process.exit(0);
|
|
218
230
|
}
|
|
219
231
|
// Block: exit 2 with stderr message. Claude Code surfaces it to the user.
|
|
220
|
-
|
|
232
|
+
const blockMsg = formatBlockMessage(target, res);
|
|
233
|
+
process.stderr.write(blockMsg + '\n');
|
|
234
|
+
// Track-B injection (VALUE_METRICS Phase 2): size the injected block.
|
|
235
|
+
try {
|
|
236
|
+
await emitInjection({ type: 'pre_edit', tokensEst: estimateTokens(blockMsg), itemCount: ids.length, repoOrigin });
|
|
237
|
+
}
|
|
238
|
+
catch { /* fire-and-forget */ }
|
|
221
239
|
disconnect();
|
|
222
240
|
process.exit(2);
|
|
223
241
|
}
|
|
224
242
|
if (res?.recommendation === 'review') {
|
|
243
|
+
const advisory = formatBlockMessage(target, res);
|
|
225
244
|
const out = {
|
|
226
245
|
hookSpecificOutput: {
|
|
227
246
|
hookEventName: 'PreToolUse',
|
|
228
|
-
additionalContext:
|
|
247
|
+
additionalContext: advisory,
|
|
229
248
|
},
|
|
230
249
|
};
|
|
231
250
|
process.stdout.write(JSON.stringify(out) + '\n');
|
|
251
|
+
// Track-B injection (VALUE_METRICS Phase 2): size the injected advisory.
|
|
252
|
+
try {
|
|
253
|
+
await emitInjection({
|
|
254
|
+
type: 'pre_edit',
|
|
255
|
+
tokensEst: estimateTokens(advisory),
|
|
256
|
+
itemCount: (res.decisions ?? []).length,
|
|
257
|
+
repoOrigin,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
catch { /* fire-and-forget */ }
|
|
232
261
|
disconnect();
|
|
233
262
|
process.exit(0);
|
|
234
263
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kawacode-on-pre-edit.js","sourceRoot":"","sources":["../src/kawacode-on-pre-edit.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEtC,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"kawacode-on-pre-edit.js","sourceRoot":"","sources":["../src/kawacode-on-pre-edit.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEtC,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AACzD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE3E,4EAA4E;AAC5E,0EAA0E;AAC1E,0DAA0D;AAC1D,QAAQ,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;AAyCjC,SAAS,SAAS;IAChB,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,QAAgB,EAAE,MAAc;IACvD,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAA;IACxB,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACpC,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IAExB,IAAI,SAAS,GAAG,CAAC,CAAA;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,EAAE;YAAE,SAAS,IAAI,CAAC,CAAA;IACnD,CAAC;IACD,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,IAAI,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,EAAE;YAAE,UAAU,IAAI,CAAC,CAAA;IAClD,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,GAAG,UAAU,EAAE,CAAA;AACvD,CAAC;AAED,SAAS,aAAa,CAAC,OAAoB;IACzC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAA;IACvB,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAA;IAClC,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAA;IAChC,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAA;IAChC,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAA;IAE1B,2EAA2E;IAC3E,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IAC5C,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAA;IAC1B,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,QAAQ,CAAA;IAE/C,IAAI,WAAmB,CAAA;IACvB,IAAI,CAAC;QACH,WAAW,GAAG,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,wEAAwE;QACxE,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAAA;QAClC,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAA;QAC3B,MAAM,KAAK,GAAG,eAAe,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;QACrD,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAA;QACvB,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,CAAA;IAC5D,CAAC;IAED,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAA;QAC5C,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAAA;IAC7F,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED,sFAAsF;AACtF,2EAA2E;AAC3E,0EAA0E;AAC1E,gFAAgF;AAChF,oFAAoF;AACpF,kFAAkF;AAClF,8EAA8E;AAC9E,MAAM,eAAe,GAAG,GAAG,CAAA;AAC3B,MAAM,gBAAgB,GAAG,GAAG,CAAA;AAC5B,MAAM,eAAe,GAAG,CAAC,CAAA,CAAC,mEAAmE;AAC7F,MAAM,eAAe,GAAG,gBAAgB,GAAG,eAAe,CAAA;AAE1D,SAAS,iBAAiB,CAAC,CAAmB;IAC5C,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,IAAI,EAAE,CAAA;IAC3B,IAAI,CAAC,CAAC,MAAM,IAAI,eAAe;QAAE,OAAO,CAAC,CAAA;IACzC,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,OAAO,EAAE,CAAA;IAClD,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;IAClC,OAAO,GAAG,IAAI,OAAO,GAAG,iCAAiC,CAAC,CAAC,UAAU,KAAK,CAAA;AAC5E,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAsB,EAAE,GAAqB;IACvE,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,MAAM,MAAM,GAAG,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;IACnF,KAAK,CAAC,IAAI,CACR,2DAA2D,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,OAAO,GAAG,MAAM,GAAG,CAC7H,CAAA;IAED,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,IAAI,EAAE,CAAA;IACrC,IAAI,SAAS,GAAG,CAAC,CAAA;IACjB,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAa,CAAC,QAAQ,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC,CAAA;QAC9D,MAAM,SAAS,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAA;QACtC,IAAI,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,SAAS,EAAE,CAAC,CAAA;QAC7C,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAA;QAC1C,0EAA0E;QAC1E,IAAI,KAAK,GAAG,CAAC,IAAI,SAAS,GAAG,UAAU,GAAG,eAAe,EAAE,CAAC;YAC1D,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,GAAG,KAAK,CAAA;YAC1C,KAAK,CAAC,IAAI,CACR,OAAO,SAAS,iBAAiB,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,kFAAkF,CAC9I,CAAA;YACD,MAAK;QACP,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAA;QACpB,SAAS,IAAI,UAAU,CAAA;QACvB,KAAK,IAAI,CAAC,CAAA;IACZ,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;IAC/B,KAAK,CAAC,IAAI,CAAC,2IAA2I,CAAC,CAAA;IACvJ,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACjE,KAAK,CAAC,IAAI,CAAC,6CAA6C,MAAM,yDAAyD,CAAC,CAAA;IACxH,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,KAAK,EAAE,CAAC;QAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,GAAG,GAAG,SAAS,EAAE,CAAA;IACvB,IAAI,CAAC,GAAG;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAEzB,IAAI,OAAoB,CAAA;IACxB,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;IACrC,IAAI,CAAC,MAAM;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAE5B,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,IAAI,SAAS,CAAA;IAEpD,mEAAmE;IACnE,qDAAqD;IACrD,IAAI,UAAkB,CAAA;IACtB,IAAI,CAAC;QACH,UAAU,GAAG,aAAa,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,eAAe,EAAE,CAAA;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,IAAI,GAAqB,CAAA;IACzB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,OAAO,CAAC,gBAAgB,EAAE,UAAU,EAAE;YAChD,UAAU;YACV,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,YAAY;SACb,CAAC,CAAA;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,UAAU,EAAE,CAAA;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,IAAI,GAAG,EAAE,cAAc,KAAK,sBAAsB,EAAE,CAAC;QACnD,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,EAAE,KAAK,KAAK,IAAI,CAAA;QAChD,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QACxE,IAAI,KAAK,EAAE,CAAC;YACV,+DAA+D;YAC/D,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACnB,IAAI,CAAC;oBACH,MAAM,OAAO,CAAC,gBAAgB,EAAE,KAAK,EAAE;wBACrC,YAAY;wBACZ,WAAW,EAAE,GAAG;qBACjB,CAAC,CAAA;gBACJ,CAAC;gBAAC,MAAM,CAAC;oBACP,iBAAiB;gBACnB,CAAC;YACH,CAAC;YACD,kEAAkE;YAClE,wEAAwE;YACxE,oEAAoE;YACpE,IAAI,CAAC;gBACH,MAAM,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAA;YACnG,CAAC;YAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC;YACjC,UAAU,EAAE,CAAA;YACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QACD,0EAA0E;QAC1E,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAChD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAA;QACrC,sEAAsE;QACtE,IAAI,CAAC;YACH,MAAM,aAAa,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAA;QACnH,CAAC;QAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC;QACjC,UAAU,EAAE,CAAA;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,IAAI,GAAG,EAAE,cAAc,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAChD,MAAM,GAAG,GAAG;YACV,kBAAkB,EAAE;gBAClB,aAAa,EAAE,YAAY;gBAC3B,iBAAiB,EAAE,QAAQ;aAC5B;SACF,CAAA;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAA;QAChD,yEAAyE;QACzE,IAAI,CAAC;YACH,MAAM,aAAa,CAAC;gBAClB,IAAI,EAAE,UAAU;gBAChB,SAAS,EAAE,cAAc,CAAC,QAAQ,CAAC;gBACnC,SAAS,EAAE,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM;gBACvC,UAAU;aACX,CAAC,CAAA;QACJ,CAAC;QAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC;QACjC,UAAU,EAAE,CAAA;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,oBAAoB;IACpB,UAAU,EAAE,CAAA;IACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA"}
|
|
@@ -42,11 +42,15 @@
|
|
|
42
42
|
* not misread as a commit. Gate only when a commit lands AFTER the most
|
|
43
43
|
* recent complete_intent call (or with none after it) — a failed/attempted
|
|
44
44
|
* complete_intent still counts as "tried", so conflict-resolution turns
|
|
45
|
-
* are not nagged.
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
45
|
+
* are not nagged. The gate attributes the commit to ITS OWN repo (parsed
|
|
46
|
+
* from `git -C`/`cd` in the command, falling back to cwd), confirms via
|
|
47
|
+
* intent:get-active that THIS session has an open current intent THERE,
|
|
48
|
+
* skips entirely when a prior nag for this commit already sits in the
|
|
49
|
+
* transcript (once per commit — never loop), and skips when the repo HEAD
|
|
50
|
+
* is already claimed by a completed intent (intent:claimed-by-commit).
|
|
51
|
+
* Output mirrors job 2: { decision:"block", reason } guarded by
|
|
52
|
+
* !stop_hook_active; once a block has fired it degrades to
|
|
53
|
+
* additionalContext. Takes precedence over the collision report on the
|
|
50
54
|
* turn it fires (finalizing the intent matters more; collisions re-surface
|
|
51
55
|
* next turn).
|
|
52
56
|
*
|
|
@@ -42,11 +42,15 @@
|
|
|
42
42
|
* not misread as a commit. Gate only when a commit lands AFTER the most
|
|
43
43
|
* recent complete_intent call (or with none after it) — a failed/attempted
|
|
44
44
|
* complete_intent still counts as "tried", so conflict-resolution turns
|
|
45
|
-
* are not nagged.
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
45
|
+
* are not nagged. The gate attributes the commit to ITS OWN repo (parsed
|
|
46
|
+
* from `git -C`/`cd` in the command, falling back to cwd), confirms via
|
|
47
|
+
* intent:get-active that THIS session has an open current intent THERE,
|
|
48
|
+
* skips entirely when a prior nag for this commit already sits in the
|
|
49
|
+
* transcript (once per commit — never loop), and skips when the repo HEAD
|
|
50
|
+
* is already claimed by a completed intent (intent:claimed-by-commit).
|
|
51
|
+
* Output mirrors job 2: { decision:"block", reason } guarded by
|
|
52
|
+
* !stop_hook_active; once a block has fired it degrades to
|
|
53
|
+
* additionalContext. Takes precedence over the collision report on the
|
|
50
54
|
* turn it fires (finalizing the intent matters more; collisions re-surface
|
|
51
55
|
* next turn).
|
|
52
56
|
*
|
|
@@ -58,9 +62,14 @@
|
|
|
58
62
|
*/
|
|
59
63
|
import { readFileSync } from 'node:fs';
|
|
60
64
|
import { execSync } from 'node:child_process';
|
|
61
|
-
import {
|
|
65
|
+
import { resolve as resolvePath } from 'node:path';
|
|
66
|
+
import { connectToMuninn, request, disconnect, setQuiet } from './services/muninn-ipc.js';
|
|
62
67
|
import { resolveOrigin } from './tools/resolve-origin.js';
|
|
63
|
-
import {
|
|
68
|
+
import { lastUnfinalizedCommit, nagAlreadyInTranscript, extractCommitPath, detectGateSave } from './stop/uncompleted-commit.js';
|
|
69
|
+
import { emitInjection, emitActedOn, emitTurnEnd, estimateTokens } from './telemetry.js';
|
|
70
|
+
// Same rationale as kawacode-on-pre-edit: hook stderr can surface to the
|
|
71
|
+
// agent/user — suppress IPC lifecycle chatter. KAWA_DEBUG=1 restores it.
|
|
72
|
+
setQuiet(!process.env.KAWA_DEBUG);
|
|
64
73
|
function readStdin() {
|
|
65
74
|
try {
|
|
66
75
|
return readFileSync(0, 'utf8');
|
|
@@ -121,6 +130,13 @@ async function runCollisionCheck(payload) {
|
|
|
121
130
|
if (collisions.length === 0)
|
|
122
131
|
return null;
|
|
123
132
|
const report = formatCollisionReport(collisions);
|
|
133
|
+
// Track-B injection (VALUE_METRICS Phase 2): size the collision report the
|
|
134
|
+
// hook is about to inject (block or advisory both inject `report`).
|
|
135
|
+
// Fire-and-forget; awaited so the socket write flushes before disconnect.
|
|
136
|
+
try {
|
|
137
|
+
await emitInjection({ type: 'stop_collision', tokensEst: estimateTokens(report), itemCount: collisions.length, repoOrigin });
|
|
138
|
+
}
|
|
139
|
+
catch { /* fire-and-forget */ }
|
|
124
140
|
// Block-to-continue only when the per-repo setting is on AND we're not already
|
|
125
141
|
// inside a prior block (else the turn can never end).
|
|
126
142
|
if (res?.mode === 'block' && payload.stop_hook_active !== true) {
|
|
@@ -138,21 +154,10 @@ async function runCollisionCheck(payload) {
|
|
|
138
154
|
});
|
|
139
155
|
}
|
|
140
156
|
// ===== Job 3: complete_intent hard gate =====
|
|
141
|
-
/**
|
|
142
|
-
function
|
|
143
|
-
let raw;
|
|
144
|
-
try {
|
|
145
|
-
raw = readFileSync(transcriptPath, 'utf8');
|
|
146
|
-
}
|
|
147
|
-
catch {
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
return detectUncompletedCommit(raw);
|
|
151
|
-
}
|
|
152
|
-
/** Current HEAD sha for `cwd`, or null if unavailable. */
|
|
153
|
-
function gitHeadSha(cwd) {
|
|
157
|
+
/** Current HEAD sha for `dir`, or null if unavailable. */
|
|
158
|
+
function gitHeadSha(dir) {
|
|
154
159
|
try {
|
|
155
|
-
return execSync('git rev-parse HEAD', { cwd, encoding: 'utf8', timeout: 5000, windowsHide: true }).trim();
|
|
160
|
+
return execSync('git rev-parse HEAD', { cwd: dir, encoding: 'utf8', timeout: 5000, windowsHide: true }).trim();
|
|
156
161
|
}
|
|
157
162
|
catch {
|
|
158
163
|
return null;
|
|
@@ -162,6 +167,17 @@ function gitHeadSha(cwd) {
|
|
|
162
167
|
* The complete_intent hard gate. Returns the hook-protocol JSON to print
|
|
163
168
|
* (a block, or a degraded advisory), or null when there's nothing to gate /
|
|
164
169
|
* on any failure (fail-soft). Mirrors runCollisionCheck's output protocol.
|
|
170
|
+
*
|
|
171
|
+
* Loop-fix (2026-07-03) — three suppressions before any nag:
|
|
172
|
+
* 1. Repo-correct attribution: the gate targets the repo the COMMIT ran in
|
|
173
|
+
* (parsed from `git -C` / `cd` in the command), not the payload cwd. A
|
|
174
|
+
* commit in an intent-less repo (e.g. docs-only) silences naturally via
|
|
175
|
+
* no-active-intent; a cross-repo commit gates against the right intent.
|
|
176
|
+
* 2. Once per commit: a prior nag after the commit in the transcript means
|
|
177
|
+
* we already asked — block once, then silence, never loop.
|
|
178
|
+
* 3. Already claimed: when the target repo's HEAD is claimed by a
|
|
179
|
+
* completed/pushed/done intent (any session), the commit IS finalized —
|
|
180
|
+
* nothing to nag.
|
|
165
181
|
*/
|
|
166
182
|
async function runCompleteGate(payload) {
|
|
167
183
|
if (process.env.KAWA_COMPLETE_GATE === 'off')
|
|
@@ -171,16 +187,32 @@ async function runCompleteGate(payload) {
|
|
|
171
187
|
if (!cwd || !transcriptPath)
|
|
172
188
|
return null;
|
|
173
189
|
// Cheap, IPC-free evidence first: did the agent commit without completing?
|
|
174
|
-
|
|
190
|
+
let transcript;
|
|
191
|
+
try {
|
|
192
|
+
transcript = readFileSync(transcriptPath, 'utf8');
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
const commit = lastUnfinalizedCommit(transcript);
|
|
198
|
+
if (!commit)
|
|
175
199
|
return null;
|
|
200
|
+
// Suppression 2: we already nagged about this commit — block once, then silence.
|
|
201
|
+
if (nagAlreadyInTranscript(transcript, commit.lineIdx))
|
|
202
|
+
return null;
|
|
203
|
+
// Suppression 1: attribute the commit to ITS repo. Fall back to cwd when the
|
|
204
|
+
// command doesn't state a path (the commit ran in the Bash session's cwd).
|
|
205
|
+
const cmdPath = extractCommitPath(commit.cmd);
|
|
206
|
+
const gateDir = cmdPath ? resolvePath(cwd, cmdPath) : cwd;
|
|
176
207
|
let repoOrigin;
|
|
177
208
|
try {
|
|
178
|
-
repoOrigin = resolveOrigin(undefined,
|
|
209
|
+
repoOrigin = resolveOrigin(undefined, gateDir);
|
|
179
210
|
}
|
|
180
211
|
catch {
|
|
181
212
|
return null; // not a git repo / git unavailable — skip
|
|
182
213
|
}
|
|
183
|
-
// Confirm THIS session still has an open current intent
|
|
214
|
+
// Confirm THIS session still has an open current intent IN THE COMMIT'S REPO
|
|
215
|
+
// (supplies its id/title). Intent-less repos (docs) end here.
|
|
184
216
|
let res;
|
|
185
217
|
try {
|
|
186
218
|
res = await request('intent', 'get-active', { repoOrigin });
|
|
@@ -193,13 +225,33 @@ async function runCompleteGate(payload) {
|
|
|
193
225
|
return null; // already finalized (completion clears current) or no intent in play
|
|
194
226
|
if ((intent.status || 'active') !== 'active')
|
|
195
227
|
return null;
|
|
196
|
-
const headSha = gitHeadSha(
|
|
228
|
+
const headSha = gitHeadSha(gateDir);
|
|
229
|
+
// Suppression 3: HEAD already claimed by a completed intent (any session).
|
|
230
|
+
// Failure discipline matches the rest of the gate: any error → no gate.
|
|
231
|
+
if (headSha) {
|
|
232
|
+
try {
|
|
233
|
+
const claim = await request('intent', 'claimed-by-commit', { repoOrigin, sha: headSha });
|
|
234
|
+
if (claim?.claimed === true)
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
197
241
|
const shaShort = headSha ? ` (${headSha.slice(0, 8)})` : '';
|
|
198
242
|
const title = intent.title ? `"${intent.title}"` : 'the active intent';
|
|
243
|
+
// NOTE: this string carries the NAG_MARKER ('Run complete_intent(intentId=')
|
|
244
|
+
// that nagAlreadyInTranscript keys on — keep them in sync.
|
|
199
245
|
const call = `complete_intent(intentId="${intent.id}", status="committed"${headSha ? `, commitSha="${headSha}"` : ''})`;
|
|
200
246
|
const reason = `You committed${shaShort} under ${title} but didn't finalize it. Run ${call} so its ` +
|
|
201
247
|
`decisions distill and code blocks are captured. If this commit isn't meant to finalize the ` +
|
|
202
248
|
`intent, complete it with the correct status or surface it to the user.`;
|
|
249
|
+
// Track-B injection (VALUE_METRICS Phase 2): size the gate reason the hook is
|
|
250
|
+
// about to inject (block or degraded advisory both inject `reason`).
|
|
251
|
+
try {
|
|
252
|
+
await emitInjection({ type: 'stop_gate', tokensEst: estimateTokens(reason), itemCount: 1, repoOrigin });
|
|
253
|
+
}
|
|
254
|
+
catch { /* fire-and-forget */ }
|
|
203
255
|
// Block-to-continue, unless we already blocked once this turn (avoid a loop).
|
|
204
256
|
if (payload.stop_hook_active !== true) {
|
|
205
257
|
return JSON.stringify({ decision: 'block', reason });
|
|
@@ -212,6 +264,44 @@ async function runCompleteGate(payload) {
|
|
|
212
264
|
},
|
|
213
265
|
});
|
|
214
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* Gate-SAVE acted-on signal (VALUE_METRICS V8 / R2). Emits acted_on{stop_gate}
|
|
269
|
+
* when a prior Stop block held the turn open (`stop_hook_active`) AND the
|
|
270
|
+
* transcript now shows a confirmed commit finalized by a complete_intent — i.e.
|
|
271
|
+
* the gate preceded a completion that would otherwise have skipped distillation
|
|
272
|
+
* + block auto-capture. Fire-and-forget; returns its emit promise so main() can
|
|
273
|
+
* flush it before disconnect. Correlation, not causation.
|
|
274
|
+
*/
|
|
275
|
+
async function emitGateSaveSignal(payload) {
|
|
276
|
+
if (process.env.KAWA_COMPLETE_GATE === 'off')
|
|
277
|
+
return;
|
|
278
|
+
if (payload.stop_hook_active !== true)
|
|
279
|
+
return; // only after a block held the turn open
|
|
280
|
+
const cwd = payload.cwd;
|
|
281
|
+
const transcriptPath = payload.transcript_path;
|
|
282
|
+
if (!cwd || !transcriptPath)
|
|
283
|
+
return;
|
|
284
|
+
let raw;
|
|
285
|
+
try {
|
|
286
|
+
raw = readFileSync(transcriptPath, 'utf8');
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (!detectGateSave(raw))
|
|
292
|
+
return;
|
|
293
|
+
let repoOrigin;
|
|
294
|
+
try {
|
|
295
|
+
repoOrigin = resolveOrigin(undefined, cwd);
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
try {
|
|
301
|
+
await emitActedOn({ type: 'stop_gate', repoOrigin });
|
|
302
|
+
}
|
|
303
|
+
catch { /* fire-and-forget */ }
|
|
304
|
+
}
|
|
215
305
|
async function main() {
|
|
216
306
|
const captureOff = process.env.KAWA_THOUGHT_CAPTURE === 'off';
|
|
217
307
|
const collisionOff = process.env.KAWA_STOP_COLLISION_CHECK === 'off';
|
|
@@ -240,8 +330,11 @@ async function main() {
|
|
|
240
330
|
// simply yields no report this turn.
|
|
241
331
|
process.exit(0);
|
|
242
332
|
}
|
|
243
|
-
//
|
|
333
|
+
// Fire-and-forget side tasks awaited before disconnect so their socket writes
|
|
334
|
+
// flush. Includes thought capture (below) and the Track-B gate-save acted-on
|
|
335
|
+
// signal (VALUE_METRICS Phase 2).
|
|
244
336
|
const captureTasks = [];
|
|
337
|
+
captureTasks.push(emitGateSaveSignal(payload));
|
|
245
338
|
if (!captureOff && sessionId && transcriptPath) {
|
|
246
339
|
captureTasks.push(request('capture-thoughts', 'capture', {
|
|
247
340
|
sessionId,
|
|
@@ -274,6 +367,12 @@ async function main() {
|
|
|
274
367
|
}
|
|
275
368
|
if (captureTasks.length > 0)
|
|
276
369
|
await Promise.allSettled(captureTasks);
|
|
370
|
+
// Close the telemetry turn (VALUE_METRICS Phase 2). Sent LAST — after this
|
|
371
|
+
// turn's stop_gate/stop_collision injections above have flushed (each awaited)
|
|
372
|
+
// — so they attribute to the closing turn and the next turn's first injection
|
|
373
|
+
// opens a fresh turnId. Muninn owns turnSeq; this is a thin fire-and-forget
|
|
374
|
+
// signal. Skipped when telemetry is off; harmless if no turn was ever opened.
|
|
375
|
+
await emitTurnEnd();
|
|
277
376
|
disconnect();
|
|
278
377
|
if (output)
|
|
279
378
|
process.stdout.write(output + '\n');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kawacode-on-stop.js","sourceRoot":"","sources":["../src/kawacode-on-stop.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"kawacode-on-stop.js","sourceRoot":"","sources":["../src/kawacode-on-stop.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
* lifts it into `IpcMessage.aid` and keys the per-session current pointer on it.
|
|
30
30
|
*/
|
|
31
31
|
export declare const SESSION_ID: string;
|
|
32
|
+
export declare function setQuiet(value: boolean): void;
|
|
32
33
|
/**
|
|
33
34
|
* Connect to Muninn's Huginn IPC socket.
|
|
34
35
|
*
|
|
@@ -51,13 +52,19 @@ export declare function connectToMuninn(socketPath?: string): Promise<void>;
|
|
|
51
52
|
*/
|
|
52
53
|
export declare function request(domain: string, action: string, data?: any, timeoutMs?: number): Promise<any>;
|
|
53
54
|
/**
|
|
54
|
-
* Ensure a repository path is registered
|
|
55
|
+
* Ensure a repository path is registered as a project.
|
|
55
56
|
*
|
|
56
|
-
* Sends `code:add` with the folder path so
|
|
57
|
-
* sets up git state, and pulls intents/decisions from the API.
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
57
|
+
* Sends `code:add` with the folder path so the app activates the project,
|
|
58
|
+
* sets up git state, and pulls intents/decisions from the API. The handler
|
|
59
|
+
* is idempotent and returns the existing project if already added.
|
|
60
|
+
*
|
|
61
|
+
* A `code:add` failure arrives here as a rejected promise — `routeResponse`
|
|
62
|
+
* already rejects with the handler's real error on `success: false`. We must
|
|
63
|
+
* NOT swallow it: registration is a precondition for every repo-targeting
|
|
64
|
+
* tool, so a hidden failure lets the tool proceed and fail downstream with a
|
|
65
|
+
* misleading message (e.g. "No project open for this repo origin"). Re-throw
|
|
66
|
+
* with repo-path context; the dispatcher (index.ts) surfaces it to the caller
|
|
67
|
+
* as structured tool output so the real reason is visible.
|
|
61
68
|
*/
|
|
62
69
|
export declare function ensureRepo(repoPath: string): Promise<void>;
|
|
63
70
|
/**
|
|
@@ -48,6 +48,21 @@ let connected = false;
|
|
|
48
48
|
let cawId = '';
|
|
49
49
|
let connectionPromise = null;
|
|
50
50
|
const pendingRequests = new Map();
|
|
51
|
+
/**
|
|
52
|
+
* Quiet mode: suppresses connection-lifecycle info logging (connect,
|
|
53
|
+
* handshake, close). Hook dispatchers enable it because Claude Code surfaces
|
|
54
|
+
* hook stderr to the agent/user on exit-2 blocks — the handshake chatter
|
|
55
|
+
* pollutes the actual message. Genuine error logs are never suppressed.
|
|
56
|
+
* The stdio MCP server leaves this off; its stderr feeds the MCP log view.
|
|
57
|
+
*/
|
|
58
|
+
let quiet = false;
|
|
59
|
+
export function setQuiet(value) {
|
|
60
|
+
quiet = value;
|
|
61
|
+
}
|
|
62
|
+
function logInfo(message) {
|
|
63
|
+
if (!quiet)
|
|
64
|
+
console.error(message);
|
|
65
|
+
}
|
|
51
66
|
/**
|
|
52
67
|
* Get the default Muninn socket path for the current platform.
|
|
53
68
|
*/
|
|
@@ -83,7 +98,7 @@ export function connectToMuninn(socketPath) {
|
|
|
83
98
|
function _connectToMuninn(socketPath) {
|
|
84
99
|
const targetPath = socketPath || process.env.MUNINN_SOCKET || getDefaultMuninnSocketPath();
|
|
85
100
|
return new Promise((resolve, reject) => {
|
|
86
|
-
|
|
101
|
+
logInfo(`[MuninnIPC] Connecting to Muninn catalog at ${targetPath}...`);
|
|
87
102
|
const catalogSock = net.createConnection(targetPath, () => {
|
|
88
103
|
// Send extension handshake
|
|
89
104
|
const handshake = JSON.stringify({
|
|
@@ -117,7 +132,7 @@ function _connectToMuninn(socketPath) {
|
|
|
117
132
|
// Windows two-pipe protocol: catalog pipe only handles registration.
|
|
118
133
|
// Muninn sends back a dedicated client pipe path; connect to it for I/O.
|
|
119
134
|
switchedToClientPipe = true;
|
|
120
|
-
|
|
135
|
+
logInfo(`[MuninnIPC] Handshake complete (caw=${cawId}), connecting to ${pipePath}`);
|
|
121
136
|
catalogSock.destroy();
|
|
122
137
|
// Small delay so Muninn's thread has time to start the client pipe server
|
|
123
138
|
setTimeout(() => connectClientPipe(pipePath, resolve, reject), 50);
|
|
@@ -126,7 +141,7 @@ function _connectToMuninn(socketPath) {
|
|
|
126
141
|
// Unix: single persistent connection, keep using catalogSock
|
|
127
142
|
socket = catalogSock;
|
|
128
143
|
connected = true;
|
|
129
|
-
|
|
144
|
+
logInfo(`[MuninnIPC] Handshake complete (caw=${cawId})`);
|
|
130
145
|
resolve();
|
|
131
146
|
}
|
|
132
147
|
continue;
|
|
@@ -152,7 +167,7 @@ function _connectToMuninn(socketPath) {
|
|
|
152
167
|
// On Windows the catalog pipe closes after handshake — expected, skip cleanup.
|
|
153
168
|
// On Unix the catalog socket IS the main socket, so closing means disconnected.
|
|
154
169
|
if (!switchedToClientPipe) {
|
|
155
|
-
|
|
170
|
+
logInfo('[MuninnIPC] Socket closed');
|
|
156
171
|
cleanup();
|
|
157
172
|
}
|
|
158
173
|
});
|
|
@@ -171,11 +186,11 @@ function _connectToMuninn(socketPath) {
|
|
|
171
186
|
* for bidirectional communication after the catalog registration.
|
|
172
187
|
*/
|
|
173
188
|
function connectClientPipe(pipePath, resolve, reject) {
|
|
174
|
-
|
|
189
|
+
logInfo(`[MuninnIPC] Connecting to client pipe: ${pipePath}`);
|
|
175
190
|
const clientSock = net.createConnection(pipePath, () => {
|
|
176
191
|
socket = clientSock;
|
|
177
192
|
connected = true;
|
|
178
|
-
|
|
193
|
+
logInfo('[MuninnIPC] Client pipe connected');
|
|
179
194
|
resolve();
|
|
180
195
|
});
|
|
181
196
|
let buffer = '';
|
|
@@ -200,7 +215,7 @@ function connectClientPipe(pipePath, resolve, reject) {
|
|
|
200
215
|
cleanup();
|
|
201
216
|
});
|
|
202
217
|
clientSock.on('close', () => {
|
|
203
|
-
|
|
218
|
+
logInfo('[MuninnIPC] Client pipe closed');
|
|
204
219
|
cleanup();
|
|
205
220
|
});
|
|
206
221
|
}
|
|
@@ -291,20 +306,26 @@ export async function request(domain, action, data = {}, timeoutMs = DEFAULT_REQ
|
|
|
291
306
|
});
|
|
292
307
|
}
|
|
293
308
|
/**
|
|
294
|
-
* Ensure a repository path is registered
|
|
309
|
+
* Ensure a repository path is registered as a project.
|
|
310
|
+
*
|
|
311
|
+
* Sends `code:add` with the folder path so the app activates the project,
|
|
312
|
+
* sets up git state, and pulls intents/decisions from the API. The handler
|
|
313
|
+
* is idempotent and returns the existing project if already added.
|
|
295
314
|
*
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
315
|
+
* A `code:add` failure arrives here as a rejected promise — `routeResponse`
|
|
316
|
+
* already rejects with the handler's real error on `success: false`. We must
|
|
317
|
+
* NOT swallow it: registration is a precondition for every repo-targeting
|
|
318
|
+
* tool, so a hidden failure lets the tool proceed and fail downstream with a
|
|
319
|
+
* misleading message (e.g. "No project open for this repo origin"). Re-throw
|
|
320
|
+
* with repo-path context; the dispatcher (index.ts) surfaces it to the caller
|
|
321
|
+
* as structured tool output so the real reason is visible.
|
|
301
322
|
*/
|
|
302
323
|
export async function ensureRepo(repoPath) {
|
|
303
324
|
try {
|
|
304
325
|
await request('code', 'add', { folder: repoPath });
|
|
305
326
|
}
|
|
306
327
|
catch (err) {
|
|
307
|
-
|
|
328
|
+
throw new Error(`Could not register repository "${repoPath}" with Kawa Code: ${err.message}`);
|
|
308
329
|
}
|
|
309
330
|
}
|
|
310
331
|
/**
|