gossipcat 0.4.30 → 0.4.31
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/README.md +13 -8
- package/dist-mcp/mcp-server.js +51 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
|
-
<a href="https://www.npmjs.com/package/gossipcat"><img src="https://img.shields.io/npm/v/gossipcat?color=0ea5e9" alt="npm version" /></a>
|
|
10
|
+
<a href="https://www.npmjs.com/package/gossipcat"><img src="https://img.shields.io/npm/v/gossipcat?color=0ea5e9&v=0430" alt="npm version" /></a>
|
|
11
11
|
<a href="https://www.npmjs.com/package/gossipcat"><img src="https://img.shields.io/npm/dw/gossipcat?color=0ea5e9" alt="npm weekly downloads" /></a>
|
|
12
12
|
<a href="https://github.com/gossipcat-ai/gossipcat-ai/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT License" /></a>
|
|
13
13
|
<a href="#quickstart"><img src="https://img.shields.io/badge/node-22%2B-green" alt="Node 22+" /></a>
|
|
@@ -85,15 +85,14 @@ The core difference: gossipcat verifies findings against actual `file:line` cita
|
|
|
85
85
|
|
|
86
86
|
## Real-world session
|
|
87
87
|
|
|
88
|
-
What a typical gossipcat session looks like in practice (2026-
|
|
88
|
+
What a typical gossipcat session looks like in practice (2026-05-22, v0.4.30 ship):
|
|
89
89
|
|
|
90
|
-
- **
|
|
91
|
-
- **
|
|
92
|
-
- **1
|
|
93
|
-
- **
|
|
94
|
-
- **1 hallucination caught** on haiku-researcher — extrapolated from a 50-row sample when the full dataset was needed; `hallucination_caught` signal recorded, accuracy score updated, no fix shipped on bad data
|
|
90
|
+
- **1 feature shipped end-to-end** — consensus auto-verify (PR #448, master commit `4b28a1c`, 1255+ LOC, 50/50 new tests, zero regressions). Full design ↔ ship arc through gossipcat itself: 6 consensus rounds on the spec before any code was written.
|
|
91
|
+
- **6 consensus rounds on the spec** caught **21+ HIGH-severity defects** across rev-1 → rev-6 — including a double-dispatch bug on the `run()` path (rev-3, opus-implementer), a phantom `AgentTeam` type the implementer would have invented if shipped (rev-5, sonnet-reviewer grep-grounded against live `AgentConfig`), and a `metadata` field that didn't exist on `ConsensusSignal` at all (rev-4, sonnet — `metadata` lives only on `MetaSignal` / `PipelineSignal`). Each round produced a measurable rev: rev-1 had 4 HIGHs, rev-6 had 0.
|
|
92
|
+
- **1 post-merge bug caught by a pre-existing drift test** — `signal-allowlist-drift.test.ts:108` (which exists precisely to catch this — same failure mode as PR #329's silent-drop of `transport_failure`) flagged that the implementer added the 2 new signals to `KNOWN_SIGNALS` + the type union + `OPERATIONAL_SIGNAL_NAMES` but missed `VALID_CONSENSUS_SIGNALS` in `performance-writer.ts`. 7-line fix landed in the same PR before merge.
|
|
93
|
+
- **Methodology lesson recorded** — sonnet-reviewer's habit of grepping cited file:line against live code (rather than trusting prose claims) is what ultimately closed the spec. Recorded as a `citation_grounding` agreement signal so the agent's pattern compounds across sessions.
|
|
95
94
|
|
|
96
|
-
|
|
95
|
+
Nothing landed without cross-review. Two agents got `+/-` score adjustments based on what they caught vs. what they missed. The spec is now usable as a worked example of what 6 rounds of multi-agent design review looks like — `docs/superpowers/specs/2026-05-21-consensus-auto-verify-design.md`.
|
|
97
96
|
|
|
98
97
|
<br/>
|
|
99
98
|
|
|
@@ -149,6 +148,12 @@ Real-time view of tasks, consensus reports, agent scores, and activity feed. Ter
|
|
|
149
148
|
Per-agent cognitive memory persists across sessions. Agents remember past findings, patterns, and project context.
|
|
150
149
|
</td>
|
|
151
150
|
</tr>
|
|
151
|
+
<tr>
|
|
152
|
+
<td align="center" colspan="3">
|
|
153
|
+
<h3>Auto-Verify (v0.4.30)</h3>
|
|
154
|
+
Opt-in. Every UNVERIFIED finding gets <code>file_read</code>-checked by a verifier agent before the report is returned. <code>tag</code> stays <code>'unverified'</code> — auto-verify is metadata, not state transition. Flag: <code>GOSSIP_CONSENSUS_AUTO_VERIFY_UNVERIFIED=1</code>.
|
|
155
|
+
</td>
|
|
156
|
+
</tr>
|
|
152
157
|
</table>
|
|
153
158
|
|
|
154
159
|
<br/>
|
package/dist-mcp/mcp-server.js
CHANGED
|
@@ -50040,10 +50040,16 @@ function stampConcurrencyTaint(map2) {
|
|
|
50040
50040
|
}
|
|
50041
50041
|
return true;
|
|
50042
50042
|
}
|
|
50043
|
-
function elidePromptIfRequested(projectRoot, taskId, agentPrompt, promptFormat, warmCached = false) {
|
|
50043
|
+
function elidePromptIfRequested(projectRoot, taskId, agentPrompt, promptFormat, warmCached = false, writeMode) {
|
|
50044
50044
|
if (promptFormat !== "elided") return { elided: false };
|
|
50045
|
-
const
|
|
50046
|
-
|
|
50045
|
+
const body = writeMode === "worktree" ? `// GOSSIP_ISOLATION: worktree
|
|
50046
|
+
// This task was dispatched with write_mode: "worktree".
|
|
50047
|
+
// The orchestrator MUST invoke Agent() with isolation: "worktree".
|
|
50048
|
+
// Do not paraphrase this requirement.
|
|
50049
|
+
|
|
50050
|
+
` + agentPrompt : agentPrompt;
|
|
50051
|
+
const bytes = Buffer.byteLength(body, "utf8");
|
|
50052
|
+
const promptPath = writeDispatchPrompt(projectRoot, taskId, body);
|
|
50047
50053
|
const warmSuffix = warmCached ? " \u2014 warm-cached (skills) + live task" : "";
|
|
50048
50054
|
const marker = `[skills section elided: see ${promptPath}, ${bytes} bytes${warmSuffix} \u2014 READ this file and pass its CONTENTS verbatim as the Agent(prompt: ...) value. Do NOT pass the path string.]`;
|
|
50049
50055
|
return { elided: true, promptPath, marker, bytes };
|
|
@@ -50415,17 +50421,31 @@ Task: ${task}`;
|
|
|
50415
50421
|
worktreePath: void 0,
|
|
50416
50422
|
timestamp: Date.now()
|
|
50417
50423
|
});
|
|
50418
|
-
const elision = elidePromptIfRequested(
|
|
50424
|
+
const elision = elidePromptIfRequested(
|
|
50425
|
+
process.cwd(),
|
|
50426
|
+
taskId,
|
|
50427
|
+
agentPrompt,
|
|
50428
|
+
prompt_format,
|
|
50429
|
+
singleWarm,
|
|
50430
|
+
useWorktree ? "worktree" : void 0
|
|
50431
|
+
);
|
|
50419
50432
|
if (elision.elided) {
|
|
50420
50433
|
const info = ctx.nativeTaskMap.get(taskId);
|
|
50421
50434
|
if (info) info.promptPath = elision.promptPath;
|
|
50422
50435
|
}
|
|
50423
50436
|
persistNativeTaskMap();
|
|
50437
|
+
const promptRef = elision.elided ? "<file contents>" : `<AGENT_PROMPT:${taskId} below>`;
|
|
50438
|
+
const agentCall = useWorktree ? `Agent(
|
|
50439
|
+
model: "${nativeConfig.model}",
|
|
50440
|
+
prompt: ${promptRef},
|
|
50441
|
+
isolation: "worktree", // REQUIRED \u2014 do not omit
|
|
50442
|
+
run_in_background: true
|
|
50443
|
+
)` : `Agent(model: "${nativeConfig.model}", prompt: ${promptRef}, run_in_background: true)`;
|
|
50424
50444
|
const promptInstruction = elision.elided ? `Step 1 \u2014 ${elision.marker}
|
|
50425
|
-
|
|
50445
|
+
${agentCall}
|
|
50426
50446
|
|
|
50427
50447
|
` : `Step 1 \u2014 Pass the AGENT_PROMPT:${taskId} content item below verbatim to Agent(prompt: ...):
|
|
50428
|
-
|
|
50448
|
+
${agentCall}
|
|
50429
50449
|
|
|
50430
50450
|
`;
|
|
50431
50451
|
return { content: [
|
|
@@ -50437,8 +50457,10 @@ NATIVE_DISPATCH: Execute this via Claude Code Agent tool, then relay the result.
|
|
|
50437
50457
|
Task ID: ${taskId}
|
|
50438
50458
|
Agent: ${agent_id}
|
|
50439
50459
|
Model: ${nativeConfig.model}
|
|
50460
|
+
` + (useWorktree ? `Worktree isolation: REQUIRED \u2014 Agent() MUST be invoked with isolation: "worktree"
|
|
50440
50461
|
|
|
50441
|
-
`
|
|
50462
|
+
` : `
|
|
50463
|
+
`) + promptInstruction + `Step 2 \u2014 REQUIRED after agent completes:
|
|
50442
50464
|
gossip_relay(task_id: "${taskId}", relay_token: "${relayToken}", result: "<agent output>")
|
|
50443
50465
|
(VERBATIM \u2014 pass the agent's raw output; do NOT paraphrase or summarize, or <agent_finding> tags will be lost)
|
|
50444
50466
|
|
|
@@ -50680,15 +50702,24 @@ Task: ${def.task}`;
|
|
|
50680
50702
|
worktreePath: void 0,
|
|
50681
50703
|
timestamp: Date.now()
|
|
50682
50704
|
});
|
|
50683
|
-
const parallelElision = elidePromptIfRequested(process.cwd(), taskId, agentPrompt, prompt_format, parallelWarm);
|
|
50705
|
+
const parallelElision = elidePromptIfRequested(process.cwd(), taskId, agentPrompt, prompt_format, parallelWarm, def.write_mode);
|
|
50684
50706
|
if (parallelElision.elided) {
|
|
50685
50707
|
const info = ctx.nativeTaskMap.get(taskId);
|
|
50686
50708
|
if (info) info.promptPath = parallelElision.promptPath;
|
|
50687
50709
|
}
|
|
50688
50710
|
const parallelPromptRef = parallelElision.elided ? parallelElision.marker : `<AGENT_PROMPT:${taskId} below>`;
|
|
50711
|
+
const parallelUseWorktree = def.write_mode === "worktree";
|
|
50712
|
+
const parallelWorktreeBanner = parallelUseWorktree ? `
|
|
50713
|
+
Worktree isolation: REQUIRED \u2014 Agent() MUST be invoked with isolation: "worktree"` : "";
|
|
50714
|
+
const parallelAgentCall = parallelUseWorktree ? `Agent(
|
|
50715
|
+
model: "${nativeConfig.model}",
|
|
50716
|
+
prompt: ${parallelPromptRef},
|
|
50717
|
+
isolation: "worktree", // REQUIRED \u2014 do not omit
|
|
50718
|
+
run_in_background: true
|
|
50719
|
+
)` : `Agent(model: "${nativeConfig.model}", prompt: ${parallelPromptRef}, run_in_background: true)`;
|
|
50689
50720
|
lines.push(` ${taskId} \u2192 ${def.agent_id} (native \u2014 dispatch via Agent tool)`);
|
|
50690
50721
|
nativeInstructions.push(
|
|
50691
|
-
`[${taskId}]
|
|
50722
|
+
`[${taskId}] ${parallelAgentCall}${parallelWorktreeBanner}
|
|
50692
50723
|
\u2192 then: gossip_relay(task_id: "${taskId}", relay_token: "${relayToken}", result: "<output>")`
|
|
50693
50724
|
);
|
|
50694
50725
|
if (!parallelElision.elided) {
|
|
@@ -50898,16 +50929,25 @@ Task: ${def.task}`;
|
|
|
50898
50929
|
}
|
|
50899
50930
|
}
|
|
50900
50931
|
agentPrompt = maybeApplyUnverifiedNote(agentPrompt, def.task, def.agent_id);
|
|
50901
|
-
const consensusElision = elidePromptIfRequested(process.cwd(), taskId, agentPrompt, prompt_format, consensusWarm);
|
|
50932
|
+
const consensusElision = elidePromptIfRequested(process.cwd(), taskId, agentPrompt, prompt_format, consensusWarm, def.write_mode);
|
|
50902
50933
|
if (consensusElision.elided) {
|
|
50903
50934
|
const info = ctx.nativeTaskMap.get(taskId);
|
|
50904
50935
|
if (info) info.promptPath = consensusElision.promptPath;
|
|
50905
50936
|
persistNativeTaskMap();
|
|
50906
50937
|
}
|
|
50907
50938
|
const consensusPromptRef = consensusElision.elided ? consensusElision.marker : `<AGENT_PROMPT:${taskId} below>`;
|
|
50939
|
+
const consensusUseWorktree = def.write_mode === "worktree";
|
|
50940
|
+
const consensusWorktreeBanner = consensusUseWorktree ? `
|
|
50941
|
+
Worktree isolation: REQUIRED \u2014 Agent() MUST be invoked with isolation: "worktree"` : "";
|
|
50942
|
+
const consensusAgentCall = consensusUseWorktree ? `Agent(
|
|
50943
|
+
model: "${nativeConfig.model}",
|
|
50944
|
+
prompt: ${consensusPromptRef},
|
|
50945
|
+
isolation: "worktree", // REQUIRED \u2014 do not omit
|
|
50946
|
+
run_in_background: true
|
|
50947
|
+
)` : `Agent(model: "${nativeConfig.model}", prompt: ${consensusPromptRef}, run_in_background: true)`;
|
|
50908
50948
|
lines.push(` ${taskId} \u2192 ${def.agent_id} (native \u2014 dispatch via Agent tool)`);
|
|
50909
50949
|
nativeInstructions.push(
|
|
50910
|
-
`[${taskId}]
|
|
50950
|
+
`[${taskId}] ${consensusAgentCall}${consensusWorktreeBanner}
|
|
50911
50951
|
\u2192 then: gossip_relay(task_id: "${taskId}", relay_token: "${relayToken}", result: "<output>")`
|
|
50912
50952
|
);
|
|
50913
50953
|
if (!consensusElision.elided) {
|
package/package.json
CHANGED