cleargate 0.11.3 → 0.11.5
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/{chunk-Q3BTSXCK.js → chunk-WFNLCTY5.js} +90 -2
- package/dist/chunk-WFNLCTY5.js.map +1 -0
- package/dist/cli.cjs +288 -96
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +116 -11
- 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/dist/{whoami-W4U6DPVG.js → whoami-GQTFZHFQ.js} +2 -2
- 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/chunk-Q3BTSXCK.js.map +0 -1
- /package/dist/{whoami-W4U6DPVG.js.map → whoami-GQTFZHFQ.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -9,8 +9,9 @@ import {
|
|
|
9
9
|
AcquireError,
|
|
10
10
|
acquireAccessToken,
|
|
11
11
|
getMembershipState,
|
|
12
|
-
loadConfig
|
|
13
|
-
|
|
12
|
+
loadConfig,
|
|
13
|
+
saveConfig
|
|
14
|
+
} from "./chunk-WFNLCTY5.js";
|
|
14
15
|
import {
|
|
15
16
|
createTokenStore
|
|
16
17
|
} from "./chunk-4V4QABOJ.js";
|
|
@@ -21,7 +22,7 @@ import { Command } from "commander";
|
|
|
21
22
|
// package.json
|
|
22
23
|
var package_default = {
|
|
23
24
|
name: "cleargate",
|
|
24
|
-
version: "0.11.
|
|
25
|
+
version: "0.11.5",
|
|
25
26
|
private: false,
|
|
26
27
|
type: "module",
|
|
27
28
|
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.",
|
|
@@ -633,7 +634,8 @@ async function joinHandler(opts) {
|
|
|
633
634
|
if (UUID_V4_RE.test(opts.inviteUrl)) {
|
|
634
635
|
token = opts.inviteUrl;
|
|
635
636
|
const cfg = loadConfig({
|
|
636
|
-
flags: { profile: opts.profile, mcpUrl: opts.mcpUrlFlag }
|
|
637
|
+
flags: { profile: opts.profile, mcpUrl: opts.mcpUrlFlag },
|
|
638
|
+
...opts.configPath !== void 0 ? { configPath: opts.configPath } : {}
|
|
637
639
|
});
|
|
638
640
|
if (!cfg.mcpUrl) {
|
|
639
641
|
stderr(
|
|
@@ -970,9 +972,15 @@ async function joinHandler(opts) {
|
|
|
970
972
|
try {
|
|
971
973
|
const store = await (opts.createStore ?? createTokenStore)();
|
|
972
974
|
await store.save(opts.profile, refreshToken);
|
|
975
|
+
saveConfig(
|
|
976
|
+
{ mcpUrl: baseUrl },
|
|
977
|
+
opts.configPath !== void 0 ? { configPath: opts.configPath } : {}
|
|
978
|
+
);
|
|
973
979
|
stdout(`joined project '${projectName}' as '${hostname3()}'
|
|
974
980
|
`);
|
|
975
981
|
stdout(`refresh token saved to ${store.backend}.
|
|
982
|
+
`);
|
|
983
|
+
stdout(`mcp_url ${baseUrl} saved to ~/.cleargate/config.json.
|
|
976
984
|
`);
|
|
977
985
|
} catch (err) {
|
|
978
986
|
stderr(
|
|
@@ -2430,6 +2438,61 @@ function resolveScaffoldRoot(opts) {
|
|
|
2430
2438
|
};
|
|
2431
2439
|
}
|
|
2432
2440
|
|
|
2441
|
+
// src/lib/session-load-delta.ts
|
|
2442
|
+
function canonicalize(value) {
|
|
2443
|
+
if (value === null || typeof value !== "object") {
|
|
2444
|
+
return JSON.stringify(value);
|
|
2445
|
+
}
|
|
2446
|
+
if (Array.isArray(value)) {
|
|
2447
|
+
return "[" + value.map(canonicalize).join(",") + "]";
|
|
2448
|
+
}
|
|
2449
|
+
const obj = value;
|
|
2450
|
+
const sortedKeys = Object.keys(obj).sort();
|
|
2451
|
+
const pairs = sortedKeys.map((k) => JSON.stringify(k) + ":" + canonicalize(obj[k]));
|
|
2452
|
+
return "{" + pairs.join(",") + "}";
|
|
2453
|
+
}
|
|
2454
|
+
var HOOK_EVENTS = ["PreToolUse", "PostToolUse", "SessionStart", "SubagentStop"];
|
|
2455
|
+
function extractSettingsHooksBlock(settings) {
|
|
2456
|
+
const hooks = settings["hooks"] ?? {};
|
|
2457
|
+
const extracted = {};
|
|
2458
|
+
for (const event of HOOK_EVENTS) {
|
|
2459
|
+
if (Object.prototype.hasOwnProperty.call(hooks, event)) {
|
|
2460
|
+
extracted[event] = hooks[event];
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
return extracted;
|
|
2464
|
+
}
|
|
2465
|
+
function extractMcpCleargateEntry(mcp2) {
|
|
2466
|
+
const servers = mcp2["mcpServers"] ?? {};
|
|
2467
|
+
return servers["cleargate"] ?? null;
|
|
2468
|
+
}
|
|
2469
|
+
function extractSessionLoadDelta(filePath, oldContent, newContent) {
|
|
2470
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
2471
|
+
if (normalized === ".claude/settings.json") {
|
|
2472
|
+
try {
|
|
2473
|
+
const oldSettings = JSON.parse(oldContent);
|
|
2474
|
+
const newSettings = JSON.parse(newContent);
|
|
2475
|
+
const oldHooks = extractSettingsHooksBlock(oldSettings);
|
|
2476
|
+
const newHooks = extractSettingsHooksBlock(newSettings);
|
|
2477
|
+
return canonicalize(oldHooks) !== canonicalize(newHooks);
|
|
2478
|
+
} catch {
|
|
2479
|
+
return true;
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
if (normalized === ".mcp.json") {
|
|
2483
|
+
try {
|
|
2484
|
+
const oldMcp = JSON.parse(oldContent);
|
|
2485
|
+
const newMcp = JSON.parse(newContent);
|
|
2486
|
+
const oldEntry = extractMcpCleargateEntry(oldMcp);
|
|
2487
|
+
const newEntry = extractMcpCleargateEntry(newMcp);
|
|
2488
|
+
return canonicalize(oldEntry) !== canonicalize(newEntry);
|
|
2489
|
+
} catch {
|
|
2490
|
+
return true;
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2493
|
+
return true;
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2433
2496
|
// src/commands/init.ts
|
|
2434
2497
|
var HOOK_ADDITION = {
|
|
2435
2498
|
hooks: {
|
|
@@ -2605,10 +2668,17 @@ async function initHandler(opts = {}) {
|
|
|
2605
2668
|
}
|
|
2606
2669
|
}
|
|
2607
2670
|
const mergedSettings = mergeSettings(existingSettings, HOOK_ADDITION);
|
|
2671
|
+
const mergedSettingsContent = JSON.stringify(mergedSettings, null, 2) + "\n";
|
|
2672
|
+
const existingSettingsContent = existingSettings !== null ? JSON.stringify(existingSettings, null, 2) + "\n" : "{}";
|
|
2608
2673
|
fs15.mkdirSync(path15.dirname(settingsPath), { recursive: true });
|
|
2609
|
-
writeAtomic(settingsPath,
|
|
2610
|
-
|
|
2674
|
+
writeAtomic(settingsPath, mergedSettingsContent);
|
|
2675
|
+
if (extractSessionLoadDelta(".claude/settings.json", existingSettingsContent, mergedSettingsContent)) {
|
|
2676
|
+
stdout(`[cleargate init] Updated .claude/settings.json: merged PostToolUse hook \u2014 restart Claude Code if already open.
|
|
2677
|
+
`);
|
|
2678
|
+
} else {
|
|
2679
|
+
stdout(`[cleargate init] .claude/settings.json unchanged (hooks block already current)
|
|
2611
2680
|
`);
|
|
2681
|
+
}
|
|
2612
2682
|
const claudeMdPath = path15.join(cwd, "CLAUDE.md");
|
|
2613
2683
|
const claudeMdSrcPath = path15.join(payloadDir, "CLAUDE.md");
|
|
2614
2684
|
let claudeMdBlock;
|
|
@@ -7775,7 +7845,16 @@ function removeClearGateHooks(settings) {
|
|
|
7775
7845
|
// src/lib/merge-ui.ts
|
|
7776
7846
|
import { createPatch } from "diff";
|
|
7777
7847
|
function renderInlineDiff(ours, theirs, filePath) {
|
|
7778
|
-
|
|
7848
|
+
const patch = createPatch(filePath, ours, theirs, "installed", "upstream");
|
|
7849
|
+
const hasHunkLines = patch.split("\n").filter((l) => l.startsWith("+") || l.startsWith("-")).filter((l) => !l.startsWith("+++") && !l.startsWith("---")).length > 0;
|
|
7850
|
+
if (!hasHunkLines) {
|
|
7851
|
+
const ourBytes = Buffer.byteLength(ours, "utf-8");
|
|
7852
|
+
const theirBytes = Buffer.byteLength(theirs, "utf-8");
|
|
7853
|
+
const byteNote = ourBytes !== theirBytes ? `${Math.abs(theirBytes - ourBytes)} bytes changed` : "same byte count";
|
|
7854
|
+
return patch + `(whitespace/EOL-only differences \u2014 ${byteNote})
|
|
7855
|
+
`;
|
|
7856
|
+
}
|
|
7857
|
+
return patch;
|
|
7779
7858
|
}
|
|
7780
7859
|
async function promptMergeChoice(opts) {
|
|
7781
7860
|
const { path: filePath, state: state2, ours, theirs } = opts;
|
|
@@ -8070,7 +8149,15 @@ async function upgradeHandler(flags, cli) {
|
|
|
8070
8149
|
let count = 0;
|
|
8071
8150
|
for (const item of workItems) {
|
|
8072
8151
|
const state2 = classify(item.entry.sha256, item.installSha, item.currentSha, item.entry.tier);
|
|
8073
|
-
|
|
8152
|
+
const projectedPostSha = item.entry.sha256;
|
|
8153
|
+
const projectedPostState = classify(
|
|
8154
|
+
item.entry.sha256,
|
|
8155
|
+
item.entry.sha256,
|
|
8156
|
+
projectedPostSha,
|
|
8157
|
+
item.entry.tier
|
|
8158
|
+
);
|
|
8159
|
+
const stateLabel = state2 !== projectedPostState ? `state=${state2} \u2192 ${projectedPostState}` : `state=${state2}`;
|
|
8160
|
+
stdout(`[dry-run] ${item.entry.path} action=${item.action} ${stateLabel}`);
|
|
8074
8161
|
count++;
|
|
8075
8162
|
}
|
|
8076
8163
|
stdout(`[dry-run] ${count} files planned. No changes made.`);
|
|
@@ -8082,6 +8169,15 @@ async function upgradeHandler(flags, cli) {
|
|
|
8082
8169
|
const sessionRestartFiles = [];
|
|
8083
8170
|
for (const item of workItems) {
|
|
8084
8171
|
const { entry, currentSha, installSha, action } = item;
|
|
8172
|
+
let preMutationContent = null;
|
|
8173
|
+
if (SESSION_LOAD_PATHS.has(entry.path)) {
|
|
8174
|
+
const targetPath = path36.join(cwd, entry.path);
|
|
8175
|
+
try {
|
|
8176
|
+
preMutationContent = await fsp.readFile(targetPath, "utf-8");
|
|
8177
|
+
} catch {
|
|
8178
|
+
preMutationContent = "";
|
|
8179
|
+
}
|
|
8180
|
+
}
|
|
8085
8181
|
switch (action) {
|
|
8086
8182
|
case "skip": {
|
|
8087
8183
|
stdout(`[skip] ${entry.path} policy=${entry.overwrite_policy}`);
|
|
@@ -8112,8 +8208,17 @@ async function upgradeHandler(flags, cli) {
|
|
|
8112
8208
|
current_sha: postSha,
|
|
8113
8209
|
package_sha: entry.sha256
|
|
8114
8210
|
};
|
|
8115
|
-
if (SESSION_LOAD_PATHS.has(entry.path) &&
|
|
8116
|
-
|
|
8211
|
+
if (SESSION_LOAD_PATHS.has(entry.path) && preMutationContent !== null) {
|
|
8212
|
+
const targetPath = path36.join(cwd, entry.path);
|
|
8213
|
+
let postMutationContent;
|
|
8214
|
+
try {
|
|
8215
|
+
postMutationContent = await fsp.readFile(targetPath, "utf-8");
|
|
8216
|
+
} catch {
|
|
8217
|
+
postMutationContent = "";
|
|
8218
|
+
}
|
|
8219
|
+
if (extractSessionLoadDelta(entry.path, preMutationContent, postMutationContent)) {
|
|
8220
|
+
sessionRestartFiles.push(entry.path);
|
|
8221
|
+
}
|
|
8117
8222
|
}
|
|
8118
8223
|
}
|
|
8119
8224
|
await writeDriftState(cwd, driftMap, { lastRefreshed: now.toISOString() });
|
|
@@ -11022,7 +11127,7 @@ program.command("init").description("initialise a repo with ClearGate scaffold (
|
|
|
11022
11127
|
await initHandler({ force: opts.force ?? false, yes: opts.yes ?? false, pin: opts.pin, fromSource: opts.fromSource });
|
|
11023
11128
|
});
|
|
11024
11129
|
program.command("whoami").description("print the currently authenticated agent identity").option("--json", "CR-011: emit membership state as JSON (no network call)").action(async (opts) => {
|
|
11025
|
-
const { whoamiHandler } = await import("./whoami-
|
|
11130
|
+
const { whoamiHandler } = await import("./whoami-GQTFZHFQ.js");
|
|
11026
11131
|
const parentOpts = program.opts();
|
|
11027
11132
|
await whoamiHandler({
|
|
11028
11133
|
profile: parentOpts.profile,
|