cleargate 0.11.3 → 0.11.4
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/CHANGELOG.md +15 -0
- package/dist/MANIFEST.json +5 -5
- package/dist/cli.cjs +105 -7
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +104 -7
- package/dist/cli.js.map +1 -1
- package/dist/templates/cleargate-planning/.claude/hooks/pending-task-sentinel.sh +6 -1
- package/dist/templates/cleargate-planning/.claude/hooks/token-ledger.sh +162 -45
- package/dist/templates/cleargate-planning/.cleargate/scripts/write_dispatch.sh +7 -1
- package/dist/templates/cleargate-planning/MANIFEST.json +5 -5
- package/package.json +1 -1
- package/templates/cleargate-planning/.claude/hooks/pending-task-sentinel.sh +6 -1
- package/templates/cleargate-planning/.claude/hooks/token-ledger.sh +162 -45
- package/templates/cleargate-planning/.cleargate/scripts/write_dispatch.sh +7 -1
- package/templates/cleargate-planning/MANIFEST.json +5 -5
package/dist/cli.js
CHANGED
|
@@ -21,7 +21,7 @@ import { Command } from "commander";
|
|
|
21
21
|
// package.json
|
|
22
22
|
var package_default = {
|
|
23
23
|
name: "cleargate",
|
|
24
|
-
version: "0.11.
|
|
24
|
+
version: "0.11.4",
|
|
25
25
|
private: false,
|
|
26
26
|
type: "module",
|
|
27
27
|
description: "Planning framework for Claude Code agents \u2014 sprint/epic/story protocol, five-role agent team (architect/developer/qa/devops/reporter), Karpathy-style awareness wiki.",
|
|
@@ -2430,6 +2430,61 @@ function resolveScaffoldRoot(opts) {
|
|
|
2430
2430
|
};
|
|
2431
2431
|
}
|
|
2432
2432
|
|
|
2433
|
+
// src/lib/session-load-delta.ts
|
|
2434
|
+
function canonicalize(value) {
|
|
2435
|
+
if (value === null || typeof value !== "object") {
|
|
2436
|
+
return JSON.stringify(value);
|
|
2437
|
+
}
|
|
2438
|
+
if (Array.isArray(value)) {
|
|
2439
|
+
return "[" + value.map(canonicalize).join(",") + "]";
|
|
2440
|
+
}
|
|
2441
|
+
const obj = value;
|
|
2442
|
+
const sortedKeys = Object.keys(obj).sort();
|
|
2443
|
+
const pairs = sortedKeys.map((k) => JSON.stringify(k) + ":" + canonicalize(obj[k]));
|
|
2444
|
+
return "{" + pairs.join(",") + "}";
|
|
2445
|
+
}
|
|
2446
|
+
var HOOK_EVENTS = ["PreToolUse", "PostToolUse", "SessionStart", "SubagentStop"];
|
|
2447
|
+
function extractSettingsHooksBlock(settings) {
|
|
2448
|
+
const hooks = settings["hooks"] ?? {};
|
|
2449
|
+
const extracted = {};
|
|
2450
|
+
for (const event of HOOK_EVENTS) {
|
|
2451
|
+
if (Object.prototype.hasOwnProperty.call(hooks, event)) {
|
|
2452
|
+
extracted[event] = hooks[event];
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
return extracted;
|
|
2456
|
+
}
|
|
2457
|
+
function extractMcpCleargateEntry(mcp2) {
|
|
2458
|
+
const servers = mcp2["mcpServers"] ?? {};
|
|
2459
|
+
return servers["cleargate"] ?? null;
|
|
2460
|
+
}
|
|
2461
|
+
function extractSessionLoadDelta(filePath, oldContent, newContent) {
|
|
2462
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
2463
|
+
if (normalized === ".claude/settings.json") {
|
|
2464
|
+
try {
|
|
2465
|
+
const oldSettings = JSON.parse(oldContent);
|
|
2466
|
+
const newSettings = JSON.parse(newContent);
|
|
2467
|
+
const oldHooks = extractSettingsHooksBlock(oldSettings);
|
|
2468
|
+
const newHooks = extractSettingsHooksBlock(newSettings);
|
|
2469
|
+
return canonicalize(oldHooks) !== canonicalize(newHooks);
|
|
2470
|
+
} catch {
|
|
2471
|
+
return true;
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
if (normalized === ".mcp.json") {
|
|
2475
|
+
try {
|
|
2476
|
+
const oldMcp = JSON.parse(oldContent);
|
|
2477
|
+
const newMcp = JSON.parse(newContent);
|
|
2478
|
+
const oldEntry = extractMcpCleargateEntry(oldMcp);
|
|
2479
|
+
const newEntry = extractMcpCleargateEntry(newMcp);
|
|
2480
|
+
return canonicalize(oldEntry) !== canonicalize(newEntry);
|
|
2481
|
+
} catch {
|
|
2482
|
+
return true;
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
return true;
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2433
2488
|
// src/commands/init.ts
|
|
2434
2489
|
var HOOK_ADDITION = {
|
|
2435
2490
|
hooks: {
|
|
@@ -2605,10 +2660,17 @@ async function initHandler(opts = {}) {
|
|
|
2605
2660
|
}
|
|
2606
2661
|
}
|
|
2607
2662
|
const mergedSettings = mergeSettings(existingSettings, HOOK_ADDITION);
|
|
2663
|
+
const mergedSettingsContent = JSON.stringify(mergedSettings, null, 2) + "\n";
|
|
2664
|
+
const existingSettingsContent = existingSettings !== null ? JSON.stringify(existingSettings, null, 2) + "\n" : "{}";
|
|
2608
2665
|
fs15.mkdirSync(path15.dirname(settingsPath), { recursive: true });
|
|
2609
|
-
writeAtomic(settingsPath,
|
|
2610
|
-
|
|
2666
|
+
writeAtomic(settingsPath, mergedSettingsContent);
|
|
2667
|
+
if (extractSessionLoadDelta(".claude/settings.json", existingSettingsContent, mergedSettingsContent)) {
|
|
2668
|
+
stdout(`[cleargate init] Updated .claude/settings.json: merged PostToolUse hook \u2014 restart Claude Code if already open.
|
|
2669
|
+
`);
|
|
2670
|
+
} else {
|
|
2671
|
+
stdout(`[cleargate init] .claude/settings.json unchanged (hooks block already current)
|
|
2611
2672
|
`);
|
|
2673
|
+
}
|
|
2612
2674
|
const claudeMdPath = path15.join(cwd, "CLAUDE.md");
|
|
2613
2675
|
const claudeMdSrcPath = path15.join(payloadDir, "CLAUDE.md");
|
|
2614
2676
|
let claudeMdBlock;
|
|
@@ -7775,7 +7837,16 @@ function removeClearGateHooks(settings) {
|
|
|
7775
7837
|
// src/lib/merge-ui.ts
|
|
7776
7838
|
import { createPatch } from "diff";
|
|
7777
7839
|
function renderInlineDiff(ours, theirs, filePath) {
|
|
7778
|
-
|
|
7840
|
+
const patch = createPatch(filePath, ours, theirs, "installed", "upstream");
|
|
7841
|
+
const hasHunkLines = patch.split("\n").filter((l) => l.startsWith("+") || l.startsWith("-")).filter((l) => !l.startsWith("+++") && !l.startsWith("---")).length > 0;
|
|
7842
|
+
if (!hasHunkLines) {
|
|
7843
|
+
const ourBytes = Buffer.byteLength(ours, "utf-8");
|
|
7844
|
+
const theirBytes = Buffer.byteLength(theirs, "utf-8");
|
|
7845
|
+
const byteNote = ourBytes !== theirBytes ? `${Math.abs(theirBytes - ourBytes)} bytes changed` : "same byte count";
|
|
7846
|
+
return patch + `(whitespace/EOL-only differences \u2014 ${byteNote})
|
|
7847
|
+
`;
|
|
7848
|
+
}
|
|
7849
|
+
return patch;
|
|
7779
7850
|
}
|
|
7780
7851
|
async function promptMergeChoice(opts) {
|
|
7781
7852
|
const { path: filePath, state: state2, ours, theirs } = opts;
|
|
@@ -8070,7 +8141,15 @@ async function upgradeHandler(flags, cli) {
|
|
|
8070
8141
|
let count = 0;
|
|
8071
8142
|
for (const item of workItems) {
|
|
8072
8143
|
const state2 = classify(item.entry.sha256, item.installSha, item.currentSha, item.entry.tier);
|
|
8073
|
-
|
|
8144
|
+
const projectedPostSha = item.entry.sha256;
|
|
8145
|
+
const projectedPostState = classify(
|
|
8146
|
+
item.entry.sha256,
|
|
8147
|
+
item.entry.sha256,
|
|
8148
|
+
projectedPostSha,
|
|
8149
|
+
item.entry.tier
|
|
8150
|
+
);
|
|
8151
|
+
const stateLabel = state2 !== projectedPostState ? `state=${state2} \u2192 ${projectedPostState}` : `state=${state2}`;
|
|
8152
|
+
stdout(`[dry-run] ${item.entry.path} action=${item.action} ${stateLabel}`);
|
|
8074
8153
|
count++;
|
|
8075
8154
|
}
|
|
8076
8155
|
stdout(`[dry-run] ${count} files planned. No changes made.`);
|
|
@@ -8082,6 +8161,15 @@ async function upgradeHandler(flags, cli) {
|
|
|
8082
8161
|
const sessionRestartFiles = [];
|
|
8083
8162
|
for (const item of workItems) {
|
|
8084
8163
|
const { entry, currentSha, installSha, action } = item;
|
|
8164
|
+
let preMutationContent = null;
|
|
8165
|
+
if (SESSION_LOAD_PATHS.has(entry.path)) {
|
|
8166
|
+
const targetPath = path36.join(cwd, entry.path);
|
|
8167
|
+
try {
|
|
8168
|
+
preMutationContent = await fsp.readFile(targetPath, "utf-8");
|
|
8169
|
+
} catch {
|
|
8170
|
+
preMutationContent = "";
|
|
8171
|
+
}
|
|
8172
|
+
}
|
|
8085
8173
|
switch (action) {
|
|
8086
8174
|
case "skip": {
|
|
8087
8175
|
stdout(`[skip] ${entry.path} policy=${entry.overwrite_policy}`);
|
|
@@ -8112,8 +8200,17 @@ async function upgradeHandler(flags, cli) {
|
|
|
8112
8200
|
current_sha: postSha,
|
|
8113
8201
|
package_sha: entry.sha256
|
|
8114
8202
|
};
|
|
8115
|
-
if (SESSION_LOAD_PATHS.has(entry.path) &&
|
|
8116
|
-
|
|
8203
|
+
if (SESSION_LOAD_PATHS.has(entry.path) && preMutationContent !== null) {
|
|
8204
|
+
const targetPath = path36.join(cwd, entry.path);
|
|
8205
|
+
let postMutationContent;
|
|
8206
|
+
try {
|
|
8207
|
+
postMutationContent = await fsp.readFile(targetPath, "utf-8");
|
|
8208
|
+
} catch {
|
|
8209
|
+
postMutationContent = "";
|
|
8210
|
+
}
|
|
8211
|
+
if (extractSessionLoadDelta(entry.path, preMutationContent, postMutationContent)) {
|
|
8212
|
+
sessionRestartFiles.push(entry.path);
|
|
8213
|
+
}
|
|
8117
8214
|
}
|
|
8118
8215
|
}
|
|
8119
8216
|
await writeDriftState(cwd, driftMap, { lastRefreshed: now.toISOString() });
|