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.cjs
CHANGED
|
@@ -114,6 +114,40 @@ function requireMcpUrl(cfg) {
|
|
|
114
114
|
}
|
|
115
115
|
return cfg.mcpUrl;
|
|
116
116
|
}
|
|
117
|
+
function saveConfig(updates, opts = {}) {
|
|
118
|
+
const home = os.homedir();
|
|
119
|
+
if (!home) {
|
|
120
|
+
throw new Error("Cannot determine home directory.");
|
|
121
|
+
}
|
|
122
|
+
const configPath = opts.configPath ?? path2.join(home, ".cleargate", "config.json");
|
|
123
|
+
const dir = path2.dirname(configPath);
|
|
124
|
+
let existing = {};
|
|
125
|
+
try {
|
|
126
|
+
const raw = fs2.readFileSync(configPath, "utf8");
|
|
127
|
+
const parsed = JSON.parse(raw);
|
|
128
|
+
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
129
|
+
existing = parsed;
|
|
130
|
+
}
|
|
131
|
+
} catch (err) {
|
|
132
|
+
if (!(err instanceof Error && "code" in err && err.code === "ENOENT")) {
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const merged = { ...existing };
|
|
136
|
+
for (const [k, v] of Object.entries(updates)) {
|
|
137
|
+
if (v !== void 0) merged[k] = v;
|
|
138
|
+
}
|
|
139
|
+
fs2.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
140
|
+
try {
|
|
141
|
+
fs2.chmodSync(dir, 448);
|
|
142
|
+
} catch {
|
|
143
|
+
}
|
|
144
|
+
const tmpPath = path2.join(dir, ".config.json.tmp");
|
|
145
|
+
const json = JSON.stringify(merged, null, 2) + "\n";
|
|
146
|
+
fs2.writeFileSync(tmpPath, json, { mode: 384 });
|
|
147
|
+
fs2.chmodSync(tmpPath, 384);
|
|
148
|
+
fs2.renameSync(tmpPath, configPath);
|
|
149
|
+
fs2.chmodSync(configPath, 384);
|
|
150
|
+
}
|
|
117
151
|
var fs2, os, path2, import_zod, ConfigSchema;
|
|
118
152
|
var init_config = __esm({
|
|
119
153
|
"src/config.ts"() {
|
|
@@ -383,6 +417,41 @@ var init_membership = __esm({
|
|
|
383
417
|
});
|
|
384
418
|
|
|
385
419
|
// src/auth/acquire.ts
|
|
420
|
+
function defaultDiskCachePath(env = process.env) {
|
|
421
|
+
const override = env["CLEARGATE_DISK_CACHE_PATH"];
|
|
422
|
+
if (override === "off") return null;
|
|
423
|
+
if (typeof override === "string" && override.length > 0) return override;
|
|
424
|
+
const home = os9.homedir();
|
|
425
|
+
if (!home) return null;
|
|
426
|
+
return path45.join(home, ".cleargate", "access-token.json");
|
|
427
|
+
}
|
|
428
|
+
function readDiskCache(filePath) {
|
|
429
|
+
try {
|
|
430
|
+
const raw = fs42.readFileSync(filePath, "utf8");
|
|
431
|
+
const parsed = JSON.parse(raw);
|
|
432
|
+
if (parsed !== null && typeof parsed === "object" && parsed.version === 1 && typeof parsed.entries === "object" && parsed.entries !== null) {
|
|
433
|
+
return parsed;
|
|
434
|
+
}
|
|
435
|
+
} catch {
|
|
436
|
+
}
|
|
437
|
+
return { version: 1, entries: {} };
|
|
438
|
+
}
|
|
439
|
+
function writeDiskCache(filePath, data) {
|
|
440
|
+
const dir = path45.dirname(filePath);
|
|
441
|
+
try {
|
|
442
|
+
fs42.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
443
|
+
try {
|
|
444
|
+
fs42.chmodSync(dir, 448);
|
|
445
|
+
} catch {
|
|
446
|
+
}
|
|
447
|
+
const tmpPath = path45.join(dir, ".access-token.json.tmp");
|
|
448
|
+
fs42.writeFileSync(tmpPath, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
|
|
449
|
+
fs42.chmodSync(tmpPath, 384);
|
|
450
|
+
fs42.renameSync(tmpPath, filePath);
|
|
451
|
+
fs42.chmodSync(filePath, 384);
|
|
452
|
+
} catch {
|
|
453
|
+
}
|
|
454
|
+
}
|
|
386
455
|
function decodeJwtPayload2(token) {
|
|
387
456
|
try {
|
|
388
457
|
const parts = token.split(".");
|
|
@@ -408,6 +477,15 @@ async function acquireAccessToken(opts) {
|
|
|
408
477
|
return cached.accessToken;
|
|
409
478
|
}
|
|
410
479
|
}
|
|
480
|
+
const diskCachePath = opts.diskCachePath === void 0 ? defaultDiskCachePath() : opts.diskCachePath;
|
|
481
|
+
if (!opts.forceRefresh && diskCachePath) {
|
|
482
|
+
const file = readDiskCache(diskCachePath);
|
|
483
|
+
const entry = file.entries[cacheKey];
|
|
484
|
+
if (entry && nowFn() < entry.expiresAtMs) {
|
|
485
|
+
CACHE.set(cacheKey, entry);
|
|
486
|
+
return entry.accessToken;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
411
489
|
const store = await (opts.createStore ?? createTokenStore)();
|
|
412
490
|
const stored = await store.load(opts.profile);
|
|
413
491
|
if (!stored) {
|
|
@@ -456,15 +534,24 @@ async function acquireAccessToken(opts) {
|
|
|
456
534
|
const exp = payload?.exp;
|
|
457
535
|
if (typeof exp === "number" && Number.isFinite(exp)) {
|
|
458
536
|
const expiresAtMs = (exp - 60) * 1e3;
|
|
459
|
-
|
|
537
|
+
const entry = { accessToken, expiresAtMs };
|
|
538
|
+
CACHE.set(cacheKey, entry);
|
|
539
|
+
if (diskCachePath) {
|
|
540
|
+
const file = readDiskCache(diskCachePath);
|
|
541
|
+
file.entries[cacheKey] = entry;
|
|
542
|
+
writeDiskCache(diskCachePath, file);
|
|
543
|
+
}
|
|
460
544
|
}
|
|
461
545
|
return accessToken;
|
|
462
546
|
}
|
|
463
|
-
var CACHE, AcquireError;
|
|
547
|
+
var fs42, os9, path45, CACHE, AcquireError;
|
|
464
548
|
var init_acquire = __esm({
|
|
465
549
|
"src/auth/acquire.ts"() {
|
|
466
550
|
"use strict";
|
|
467
551
|
init_cjs_shims();
|
|
552
|
+
fs42 = __toESM(require("fs"), 1);
|
|
553
|
+
os9 = __toESM(require("os"), 1);
|
|
554
|
+
path45 = __toESM(require("path"), 1);
|
|
468
555
|
init_factory();
|
|
469
556
|
CACHE = /* @__PURE__ */ new Map();
|
|
470
557
|
AcquireError = class extends Error {
|
|
@@ -696,7 +783,7 @@ var import_commander = require("commander");
|
|
|
696
783
|
// package.json
|
|
697
784
|
var package_default = {
|
|
698
785
|
name: "cleargate",
|
|
699
|
-
version: "0.11.
|
|
786
|
+
version: "0.11.5",
|
|
700
787
|
private: false,
|
|
701
788
|
type: "module",
|
|
702
789
|
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.",
|
|
@@ -1314,7 +1401,8 @@ async function joinHandler(opts) {
|
|
|
1314
1401
|
if (UUID_V4_RE.test(opts.inviteUrl)) {
|
|
1315
1402
|
token = opts.inviteUrl;
|
|
1316
1403
|
const cfg = loadConfig({
|
|
1317
|
-
flags: { profile: opts.profile, mcpUrl: opts.mcpUrlFlag }
|
|
1404
|
+
flags: { profile: opts.profile, mcpUrl: opts.mcpUrlFlag },
|
|
1405
|
+
...opts.configPath !== void 0 ? { configPath: opts.configPath } : {}
|
|
1318
1406
|
});
|
|
1319
1407
|
if (!cfg.mcpUrl) {
|
|
1320
1408
|
stderr(
|
|
@@ -1651,9 +1739,15 @@ async function joinHandler(opts) {
|
|
|
1651
1739
|
try {
|
|
1652
1740
|
const store = await (opts.createStore ?? createTokenStore)();
|
|
1653
1741
|
await store.save(opts.profile, refreshToken);
|
|
1742
|
+
saveConfig(
|
|
1743
|
+
{ mcpUrl: baseUrl },
|
|
1744
|
+
opts.configPath !== void 0 ? { configPath: opts.configPath } : {}
|
|
1745
|
+
);
|
|
1654
1746
|
stdout(`joined project '${projectName}' as '${hostname3()}'
|
|
1655
1747
|
`);
|
|
1656
1748
|
stdout(`refresh token saved to ${store.backend}.
|
|
1749
|
+
`);
|
|
1750
|
+
stdout(`mcp_url ${baseUrl} saved to ~/.cleargate/config.json.
|
|
1657
1751
|
`);
|
|
1658
1752
|
} catch (err) {
|
|
1659
1753
|
stderr(
|
|
@@ -3176,6 +3270,62 @@ function resolveScaffoldRoot(opts) {
|
|
|
3176
3270
|
};
|
|
3177
3271
|
}
|
|
3178
3272
|
|
|
3273
|
+
// src/lib/session-load-delta.ts
|
|
3274
|
+
init_cjs_shims();
|
|
3275
|
+
function canonicalize(value) {
|
|
3276
|
+
if (value === null || typeof value !== "object") {
|
|
3277
|
+
return JSON.stringify(value);
|
|
3278
|
+
}
|
|
3279
|
+
if (Array.isArray(value)) {
|
|
3280
|
+
return "[" + value.map(canonicalize).join(",") + "]";
|
|
3281
|
+
}
|
|
3282
|
+
const obj = value;
|
|
3283
|
+
const sortedKeys = Object.keys(obj).sort();
|
|
3284
|
+
const pairs = sortedKeys.map((k) => JSON.stringify(k) + ":" + canonicalize(obj[k]));
|
|
3285
|
+
return "{" + pairs.join(",") + "}";
|
|
3286
|
+
}
|
|
3287
|
+
var HOOK_EVENTS = ["PreToolUse", "PostToolUse", "SessionStart", "SubagentStop"];
|
|
3288
|
+
function extractSettingsHooksBlock(settings) {
|
|
3289
|
+
const hooks = settings["hooks"] ?? {};
|
|
3290
|
+
const extracted = {};
|
|
3291
|
+
for (const event of HOOK_EVENTS) {
|
|
3292
|
+
if (Object.prototype.hasOwnProperty.call(hooks, event)) {
|
|
3293
|
+
extracted[event] = hooks[event];
|
|
3294
|
+
}
|
|
3295
|
+
}
|
|
3296
|
+
return extracted;
|
|
3297
|
+
}
|
|
3298
|
+
function extractMcpCleargateEntry(mcp2) {
|
|
3299
|
+
const servers = mcp2["mcpServers"] ?? {};
|
|
3300
|
+
return servers["cleargate"] ?? null;
|
|
3301
|
+
}
|
|
3302
|
+
function extractSessionLoadDelta(filePath, oldContent, newContent) {
|
|
3303
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
3304
|
+
if (normalized === ".claude/settings.json") {
|
|
3305
|
+
try {
|
|
3306
|
+
const oldSettings = JSON.parse(oldContent);
|
|
3307
|
+
const newSettings = JSON.parse(newContent);
|
|
3308
|
+
const oldHooks = extractSettingsHooksBlock(oldSettings);
|
|
3309
|
+
const newHooks = extractSettingsHooksBlock(newSettings);
|
|
3310
|
+
return canonicalize(oldHooks) !== canonicalize(newHooks);
|
|
3311
|
+
} catch {
|
|
3312
|
+
return true;
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
if (normalized === ".mcp.json") {
|
|
3316
|
+
try {
|
|
3317
|
+
const oldMcp = JSON.parse(oldContent);
|
|
3318
|
+
const newMcp = JSON.parse(newContent);
|
|
3319
|
+
const oldEntry = extractMcpCleargateEntry(oldMcp);
|
|
3320
|
+
const newEntry = extractMcpCleargateEntry(newMcp);
|
|
3321
|
+
return canonicalize(oldEntry) !== canonicalize(newEntry);
|
|
3322
|
+
} catch {
|
|
3323
|
+
return true;
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
3326
|
+
return true;
|
|
3327
|
+
}
|
|
3328
|
+
|
|
3179
3329
|
// src/commands/init.ts
|
|
3180
3330
|
var HOOK_ADDITION = {
|
|
3181
3331
|
hooks: {
|
|
@@ -3351,10 +3501,17 @@ async function initHandler(opts = {}) {
|
|
|
3351
3501
|
}
|
|
3352
3502
|
}
|
|
3353
3503
|
const mergedSettings = mergeSettings(existingSettings, HOOK_ADDITION);
|
|
3504
|
+
const mergedSettingsContent = JSON.stringify(mergedSettings, null, 2) + "\n";
|
|
3505
|
+
const existingSettingsContent = existingSettings !== null ? JSON.stringify(existingSettings, null, 2) + "\n" : "{}";
|
|
3354
3506
|
fs17.mkdirSync(path18.dirname(settingsPath), { recursive: true });
|
|
3355
|
-
writeAtomic(settingsPath,
|
|
3356
|
-
|
|
3507
|
+
writeAtomic(settingsPath, mergedSettingsContent);
|
|
3508
|
+
if (extractSessionLoadDelta(".claude/settings.json", existingSettingsContent, mergedSettingsContent)) {
|
|
3509
|
+
stdout(`[cleargate init] Updated .claude/settings.json: merged PostToolUse hook \u2014 restart Claude Code if already open.
|
|
3510
|
+
`);
|
|
3511
|
+
} else {
|
|
3512
|
+
stdout(`[cleargate init] .claude/settings.json unchanged (hooks block already current)
|
|
3357
3513
|
`);
|
|
3514
|
+
}
|
|
3358
3515
|
const claudeMdPath = path18.join(cwd, "CLAUDE.md");
|
|
3359
3516
|
const claudeMdSrcPath = path18.join(payloadDir, "CLAUDE.md");
|
|
3360
3517
|
let claudeMdBlock;
|
|
@@ -8863,7 +9020,16 @@ function removeClearGateHooks(settings) {
|
|
|
8863
9020
|
init_cjs_shims();
|
|
8864
9021
|
var import_diff = require("diff");
|
|
8865
9022
|
function renderInlineDiff(ours, theirs, filePath) {
|
|
8866
|
-
|
|
9023
|
+
const patch = (0, import_diff.createPatch)(filePath, ours, theirs, "installed", "upstream");
|
|
9024
|
+
const hasHunkLines = patch.split("\n").filter((l) => l.startsWith("+") || l.startsWith("-")).filter((l) => !l.startsWith("+++") && !l.startsWith("---")).length > 0;
|
|
9025
|
+
if (!hasHunkLines) {
|
|
9026
|
+
const ourBytes = Buffer.byteLength(ours, "utf-8");
|
|
9027
|
+
const theirBytes = Buffer.byteLength(theirs, "utf-8");
|
|
9028
|
+
const byteNote = ourBytes !== theirBytes ? `${Math.abs(theirBytes - ourBytes)} bytes changed` : "same byte count";
|
|
9029
|
+
return patch + `(whitespace/EOL-only differences \u2014 ${byteNote})
|
|
9030
|
+
`;
|
|
9031
|
+
}
|
|
9032
|
+
return patch;
|
|
8867
9033
|
}
|
|
8868
9034
|
async function promptMergeChoice(opts) {
|
|
8869
9035
|
const { path: filePath, state: state2, ours, theirs } = opts;
|
|
@@ -9159,7 +9325,15 @@ async function upgradeHandler(flags, cli) {
|
|
|
9159
9325
|
let count = 0;
|
|
9160
9326
|
for (const item of workItems) {
|
|
9161
9327
|
const state2 = classify(item.entry.sha256, item.installSha, item.currentSha, item.entry.tier);
|
|
9162
|
-
|
|
9328
|
+
const projectedPostSha = item.entry.sha256;
|
|
9329
|
+
const projectedPostState = classify(
|
|
9330
|
+
item.entry.sha256,
|
|
9331
|
+
item.entry.sha256,
|
|
9332
|
+
projectedPostSha,
|
|
9333
|
+
item.entry.tier
|
|
9334
|
+
);
|
|
9335
|
+
const stateLabel = state2 !== projectedPostState ? `state=${state2} \u2192 ${projectedPostState}` : `state=${state2}`;
|
|
9336
|
+
stdout(`[dry-run] ${item.entry.path} action=${item.action} ${stateLabel}`);
|
|
9163
9337
|
count++;
|
|
9164
9338
|
}
|
|
9165
9339
|
stdout(`[dry-run] ${count} files planned. No changes made.`);
|
|
@@ -9171,6 +9345,15 @@ async function upgradeHandler(flags, cli) {
|
|
|
9171
9345
|
const sessionRestartFiles = [];
|
|
9172
9346
|
for (const item of workItems) {
|
|
9173
9347
|
const { entry, currentSha, installSha, action } = item;
|
|
9348
|
+
let preMutationContent = null;
|
|
9349
|
+
if (SESSION_LOAD_PATHS.has(entry.path)) {
|
|
9350
|
+
const targetPath = path41.join(cwd, entry.path);
|
|
9351
|
+
try {
|
|
9352
|
+
preMutationContent = await fsp.readFile(targetPath, "utf-8");
|
|
9353
|
+
} catch {
|
|
9354
|
+
preMutationContent = "";
|
|
9355
|
+
}
|
|
9356
|
+
}
|
|
9174
9357
|
switch (action) {
|
|
9175
9358
|
case "skip": {
|
|
9176
9359
|
stdout(`[skip] ${entry.path} policy=${entry.overwrite_policy}`);
|
|
@@ -9201,8 +9384,17 @@ async function upgradeHandler(flags, cli) {
|
|
|
9201
9384
|
current_sha: postSha,
|
|
9202
9385
|
package_sha: entry.sha256
|
|
9203
9386
|
};
|
|
9204
|
-
if (SESSION_LOAD_PATHS.has(entry.path) &&
|
|
9205
|
-
|
|
9387
|
+
if (SESSION_LOAD_PATHS.has(entry.path) && preMutationContent !== null) {
|
|
9388
|
+
const targetPath = path41.join(cwd, entry.path);
|
|
9389
|
+
let postMutationContent;
|
|
9390
|
+
try {
|
|
9391
|
+
postMutationContent = await fsp.readFile(targetPath, "utf-8");
|
|
9392
|
+
} catch {
|
|
9393
|
+
postMutationContent = "";
|
|
9394
|
+
}
|
|
9395
|
+
if (extractSessionLoadDelta(entry.path, preMutationContent, postMutationContent)) {
|
|
9396
|
+
sessionRestartFiles.push(entry.path);
|
|
9397
|
+
}
|
|
9206
9398
|
}
|
|
9207
9399
|
}
|
|
9208
9400
|
await writeDriftState(cwd, driftMap, { lastRefreshed: now.toISOString() });
|
|
@@ -9520,7 +9712,7 @@ async function uninstallHandler(opts) {
|
|
|
9520
9712
|
// src/commands/sync.ts
|
|
9521
9713
|
init_cjs_shims();
|
|
9522
9714
|
var fsPromises8 = __toESM(require("fs/promises"), 1);
|
|
9523
|
-
var
|
|
9715
|
+
var path51 = __toESM(require("path"), 1);
|
|
9524
9716
|
|
|
9525
9717
|
// src/lib/sync-log.ts
|
|
9526
9718
|
init_cjs_shims();
|
|
@@ -9840,12 +10032,12 @@ init_config();
|
|
|
9840
10032
|
// src/lib/intake.ts
|
|
9841
10033
|
init_cjs_shims();
|
|
9842
10034
|
var fsPromises4 = __toESM(require("fs/promises"), 1);
|
|
9843
|
-
var
|
|
10035
|
+
var path47 = __toESM(require("path"), 1);
|
|
9844
10036
|
|
|
9845
10037
|
// src/lib/slug.ts
|
|
9846
10038
|
init_cjs_shims();
|
|
9847
10039
|
var fsPromises3 = __toESM(require("fs/promises"), 1);
|
|
9848
|
-
var
|
|
10040
|
+
var path46 = __toESM(require("path"), 1);
|
|
9849
10041
|
function slugify(title, max = 40) {
|
|
9850
10042
|
const normalized = title.normalize("NFKD").replace(new RegExp("\\p{M}", "gu"), "");
|
|
9851
10043
|
const lowered = normalized.toLowerCase();
|
|
@@ -9860,8 +10052,8 @@ function slugify(title, max = 40) {
|
|
|
9860
10052
|
var PROPOSAL_ID_RE = /^proposal_id:\s*"?PROP-(\d+)"?/m;
|
|
9861
10053
|
async function nextProposalId(projectRoot) {
|
|
9862
10054
|
const dirs = [
|
|
9863
|
-
|
|
9864
|
-
|
|
10055
|
+
path46.join(projectRoot, ".cleargate", "delivery", "pending-sync"),
|
|
10056
|
+
path46.join(projectRoot, ".cleargate", "delivery", "archive")
|
|
9865
10057
|
];
|
|
9866
10058
|
let maxN = 0;
|
|
9867
10059
|
for (const dir of dirs) {
|
|
@@ -9873,7 +10065,7 @@ async function nextProposalId(projectRoot) {
|
|
|
9873
10065
|
}
|
|
9874
10066
|
for (const entry of entries) {
|
|
9875
10067
|
if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
|
|
9876
|
-
const fullPath =
|
|
10068
|
+
const fullPath = path46.join(dir, entry.name);
|
|
9877
10069
|
try {
|
|
9878
10070
|
const raw = await fsPromises3.readFile(fullPath, "utf8");
|
|
9879
10071
|
const fmEnd = extractFrontmatterBlock(raw);
|
|
@@ -9891,8 +10083,8 @@ async function nextProposalId(projectRoot) {
|
|
|
9891
10083
|
}
|
|
9892
10084
|
async function findByRemoteId(projectRoot, remoteId) {
|
|
9893
10085
|
const dirs = [
|
|
9894
|
-
|
|
9895
|
-
|
|
10086
|
+
path46.join(projectRoot, ".cleargate", "delivery", "pending-sync"),
|
|
10087
|
+
path46.join(projectRoot, ".cleargate", "delivery", "archive")
|
|
9896
10088
|
];
|
|
9897
10089
|
const escaped = remoteId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9898
10090
|
const re = new RegExp(`^remote_id:\\s*"?${escaped}"?\\s*$`, "m");
|
|
@@ -9905,7 +10097,7 @@ async function findByRemoteId(projectRoot, remoteId) {
|
|
|
9905
10097
|
}
|
|
9906
10098
|
for (const entry of entries) {
|
|
9907
10099
|
if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
|
|
9908
|
-
const fullPath =
|
|
10100
|
+
const fullPath = path46.join(dir, entry.name);
|
|
9909
10101
|
try {
|
|
9910
10102
|
const raw = await fsPromises3.readFile(fullPath, "utf8");
|
|
9911
10103
|
const fm = extractFrontmatterBlock(raw);
|
|
@@ -9942,7 +10134,7 @@ async function runIntakeBranch(opts) {
|
|
|
9942
10134
|
labelFilter = "cleargate:proposal",
|
|
9943
10135
|
now = () => (/* @__PURE__ */ new Date()).toISOString()
|
|
9944
10136
|
} = opts;
|
|
9945
|
-
const pendingSyncDir =
|
|
10137
|
+
const pendingSyncDir = path47.join(projectRoot, ".cleargate", "delivery", "pending-sync");
|
|
9946
10138
|
let remoteItems = [];
|
|
9947
10139
|
try {
|
|
9948
10140
|
remoteItems = await mcp2.call(
|
|
@@ -9973,7 +10165,7 @@ async function runIntakeBranch(opts) {
|
|
|
9973
10165
|
const slug2 = slugify(item.title ?? "untitled");
|
|
9974
10166
|
const num2 = proposalId2.replace("PROP-", "");
|
|
9975
10167
|
const filename2 = `PROPOSAL-${num2}-remote-${slug2}.md`;
|
|
9976
|
-
const targetPath2 =
|
|
10168
|
+
const targetPath2 = path47.join(pendingSyncDir, filename2);
|
|
9977
10169
|
createdItems.push({
|
|
9978
10170
|
proposalId: proposalId2,
|
|
9979
10171
|
remoteId: item.remote_id,
|
|
@@ -9986,7 +10178,7 @@ async function runIntakeBranch(opts) {
|
|
|
9986
10178
|
const num = proposalId.replace("PROP-", "");
|
|
9987
10179
|
const slug = slugify(item.title ?? "untitled");
|
|
9988
10180
|
const filename = `PROPOSAL-${num}-remote-${slug}.md`;
|
|
9989
|
-
const targetPath =
|
|
10181
|
+
const targetPath = path47.join(pendingSyncDir, filename);
|
|
9990
10182
|
const nowTs = now();
|
|
9991
10183
|
const fm = {
|
|
9992
10184
|
proposal_id: proposalId,
|
|
@@ -10078,8 +10270,8 @@ path/to/new/file.ext - {Explanation of purpose}
|
|
|
10078
10270
|
}
|
|
10079
10271
|
async function hasAnyRemoteAuthored(projectRoot) {
|
|
10080
10272
|
const dirs = [
|
|
10081
|
-
|
|
10082
|
-
|
|
10273
|
+
path47.join(projectRoot, ".cleargate", "delivery", "pending-sync"),
|
|
10274
|
+
path47.join(projectRoot, ".cleargate", "delivery", "archive")
|
|
10083
10275
|
];
|
|
10084
10276
|
for (const dir of dirs) {
|
|
10085
10277
|
let entries;
|
|
@@ -10090,7 +10282,7 @@ async function hasAnyRemoteAuthored(projectRoot) {
|
|
|
10090
10282
|
}
|
|
10091
10283
|
for (const entry of entries) {
|
|
10092
10284
|
if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
|
|
10093
|
-
const fullPath =
|
|
10285
|
+
const fullPath = path47.join(dir, entry.name);
|
|
10094
10286
|
try {
|
|
10095
10287
|
const raw = await fsPromises4.readFile(fullPath, "utf8");
|
|
10096
10288
|
const fmEnd = raw.indexOf("\n---", 4);
|
|
@@ -10108,9 +10300,9 @@ async function hasAnyRemoteAuthored(projectRoot) {
|
|
|
10108
10300
|
|
|
10109
10301
|
// src/lib/active-criteria.ts
|
|
10110
10302
|
init_cjs_shims();
|
|
10111
|
-
var
|
|
10303
|
+
var fs43 = __toESM(require("fs"), 1);
|
|
10112
10304
|
var fsPromises5 = __toESM(require("fs/promises"), 1);
|
|
10113
|
-
var
|
|
10305
|
+
var path48 = __toESM(require("path"), 1);
|
|
10114
10306
|
async function resolveActiveItems(projectRoot, localItems, nowFn = () => (/* @__PURE__ */ new Date()).toISOString()) {
|
|
10115
10307
|
const active = /* @__PURE__ */ new Set();
|
|
10116
10308
|
const now = Date.parse(nowFn());
|
|
@@ -10135,7 +10327,7 @@ async function resolveInSprintIds(projectRoot) {
|
|
|
10135
10327
|
const ids = /* @__PURE__ */ new Set();
|
|
10136
10328
|
try {
|
|
10137
10329
|
const sprintDir = resolveActiveSprintDir(projectRoot);
|
|
10138
|
-
const sprintId =
|
|
10330
|
+
const sprintId = path48.basename(sprintDir);
|
|
10139
10331
|
if (sprintId === "_off-sprint") return ids;
|
|
10140
10332
|
const sprintFile = await findSprintFile2(projectRoot, sprintId);
|
|
10141
10333
|
if (!sprintFile) return ids;
|
|
@@ -10150,14 +10342,14 @@ async function resolveInSprintIds(projectRoot) {
|
|
|
10150
10342
|
return ids;
|
|
10151
10343
|
}
|
|
10152
10344
|
async function findSprintFile2(projectRoot, sprintId) {
|
|
10153
|
-
const pendingSync =
|
|
10154
|
-
const archive =
|
|
10345
|
+
const pendingSync = path48.join(projectRoot, ".cleargate", "delivery", "pending-sync");
|
|
10346
|
+
const archive = path48.join(projectRoot, ".cleargate", "delivery", "archive");
|
|
10155
10347
|
for (const dir of [pendingSync, archive]) {
|
|
10156
10348
|
try {
|
|
10157
|
-
const entries =
|
|
10349
|
+
const entries = fs43.readdirSync(dir, { withFileTypes: true });
|
|
10158
10350
|
for (const entry of entries) {
|
|
10159
10351
|
if (entry.isFile() && entry.name.startsWith(sprintId) && entry.name.endsWith(".md")) {
|
|
10160
|
-
return
|
|
10352
|
+
return path48.join(dir, entry.name);
|
|
10161
10353
|
}
|
|
10162
10354
|
}
|
|
10163
10355
|
} catch {
|
|
@@ -10169,12 +10361,12 @@ async function findSprintFile2(projectRoot, sprintId) {
|
|
|
10169
10361
|
// src/lib/comments-cache.ts
|
|
10170
10362
|
init_cjs_shims();
|
|
10171
10363
|
var fsPromises6 = __toESM(require("fs/promises"), 1);
|
|
10172
|
-
var
|
|
10364
|
+
var path49 = __toESM(require("path"), 1);
|
|
10173
10365
|
function cacheDir(projectRoot) {
|
|
10174
|
-
return
|
|
10366
|
+
return path49.join(projectRoot, ".cleargate", ".comments-cache");
|
|
10175
10367
|
}
|
|
10176
10368
|
function cachePath(projectRoot, remoteId) {
|
|
10177
|
-
return
|
|
10369
|
+
return path49.join(cacheDir(projectRoot), `${remoteId}.json`);
|
|
10178
10370
|
}
|
|
10179
10371
|
async function writeCommentCache(projectRoot, remoteId, comments) {
|
|
10180
10372
|
const dir = cacheDir(projectRoot);
|
|
@@ -10189,7 +10381,7 @@ async function writeCommentCache(projectRoot, remoteId, comments) {
|
|
|
10189
10381
|
// src/lib/wiki-comments-render.ts
|
|
10190
10382
|
init_cjs_shims();
|
|
10191
10383
|
var fsPromises7 = __toESM(require("fs/promises"), 1);
|
|
10192
|
-
var
|
|
10384
|
+
var path50 = __toESM(require("path"), 1);
|
|
10193
10385
|
var START = "<!-- cleargate:comments:start -->";
|
|
10194
10386
|
var END = "<!-- cleargate:comments:end -->";
|
|
10195
10387
|
function resolveBucket(fm) {
|
|
@@ -10234,7 +10426,7 @@ async function renderCommentsSection(opts) {
|
|
|
10234
10426
|
const bucket = resolveBucket(localItem.fm);
|
|
10235
10427
|
const primaryId = getPrimaryId(localItem.fm);
|
|
10236
10428
|
if (!bucket || !primaryId) return;
|
|
10237
|
-
const wikiPath =
|
|
10429
|
+
const wikiPath = path50.join(
|
|
10238
10430
|
projectRoot,
|
|
10239
10431
|
".cleargate",
|
|
10240
10432
|
"wiki",
|
|
@@ -10270,7 +10462,7 @@ async function renderCommentsSection(opts) {
|
|
|
10270
10462
|
await writeAtomic4(wikiPath, updated);
|
|
10271
10463
|
}
|
|
10272
10464
|
async function writeAtomic4(filePath, content) {
|
|
10273
|
-
await fsPromises7.mkdir(
|
|
10465
|
+
await fsPromises7.mkdir(path50.dirname(filePath), { recursive: true });
|
|
10274
10466
|
const tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
10275
10467
|
await fsPromises7.writeFile(tmpPath, content, "utf8");
|
|
10276
10468
|
await fsPromises7.rename(tmpPath, filePath);
|
|
@@ -10282,11 +10474,11 @@ async function syncCheckHandler(opts = {}) {
|
|
|
10282
10474
|
const env = opts.env ?? process.env;
|
|
10283
10475
|
const stdout = opts.stdout ?? ((s) => process.stdout.write(s));
|
|
10284
10476
|
const nowFn = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
10285
|
-
const markerPath =
|
|
10477
|
+
const markerPath = path51.join(projectRoot, ".cleargate", ".sync-marker.json");
|
|
10286
10478
|
const updateMarker = async (nowIso2) => {
|
|
10287
10479
|
try {
|
|
10288
10480
|
const content = JSON.stringify({ last_check: nowIso2 });
|
|
10289
|
-
await fsPromises8.mkdir(
|
|
10481
|
+
await fsPromises8.mkdir(path51.dirname(markerPath), { recursive: true });
|
|
10290
10482
|
const tmpPath = `${markerPath}.tmp.${Date.now()}`;
|
|
10291
10483
|
await fsPromises8.writeFile(tmpPath, content, "utf8");
|
|
10292
10484
|
await fsPromises8.rename(tmpPath, markerPath);
|
|
@@ -10369,7 +10561,7 @@ async function syncHandler(opts = {}) {
|
|
|
10369
10561
|
const nowFn = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
10370
10562
|
const identity = resolveIdentity(projectRoot);
|
|
10371
10563
|
const sprintRoot = resolveActiveSprintDir(projectRoot);
|
|
10372
|
-
const sprintId =
|
|
10564
|
+
const sprintId = path51.basename(sprintRoot);
|
|
10373
10565
|
let mcp2;
|
|
10374
10566
|
if (opts.mcp) {
|
|
10375
10567
|
mcp2 = opts.mcp;
|
|
@@ -10430,7 +10622,7 @@ async function syncHandler(opts = {}) {
|
|
|
10430
10622
|
exit(2);
|
|
10431
10623
|
return;
|
|
10432
10624
|
}
|
|
10433
|
-
const wikiMetaPath =
|
|
10625
|
+
const wikiMetaPath = path51.join(projectRoot, ".cleargate", "wiki", "meta.json");
|
|
10434
10626
|
let lastRemoteSync = "1970-01-01T00:00:00.000Z";
|
|
10435
10627
|
try {
|
|
10436
10628
|
const metaRaw = await fsPromises8.readFile(wikiMetaPath, "utf8");
|
|
@@ -10671,7 +10863,7 @@ async function syncHandler(opts = {}) {
|
|
|
10671
10863
|
};
|
|
10672
10864
|
await appendSyncLog(sprintRoot, entry);
|
|
10673
10865
|
}
|
|
10674
|
-
const conflictsFile =
|
|
10866
|
+
const conflictsFile = path51.join(projectRoot, ".cleargate", ".conflicts.json");
|
|
10675
10867
|
const conflictsContent = {
|
|
10676
10868
|
generated_at: nowFn(),
|
|
10677
10869
|
sprint_id: sprintId,
|
|
@@ -10679,7 +10871,7 @@ async function syncHandler(opts = {}) {
|
|
|
10679
10871
|
};
|
|
10680
10872
|
await writeAtomic5(conflictsFile, JSON.stringify(conflictsContent, null, 2) + "\n");
|
|
10681
10873
|
try {
|
|
10682
|
-
await fsPromises8.mkdir(
|
|
10874
|
+
await fsPromises8.mkdir(path51.dirname(wikiMetaPath), { recursive: true });
|
|
10683
10875
|
let meta = {};
|
|
10684
10876
|
try {
|
|
10685
10877
|
const raw = await fsPromises8.readFile(wikiMetaPath, "utf8");
|
|
@@ -10720,13 +10912,13 @@ async function applyPull(item, localPath, fm, actorEmail, nowFn) {
|
|
|
10720
10912
|
await writeAtomic5(localPath, newContent);
|
|
10721
10913
|
}
|
|
10722
10914
|
async function writeAtomic5(filePath, content) {
|
|
10723
|
-
await fsPromises8.mkdir(
|
|
10915
|
+
await fsPromises8.mkdir(path51.dirname(filePath), { recursive: true });
|
|
10724
10916
|
const tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
10725
10917
|
await fsPromises8.writeFile(tmpPath, content, "utf8");
|
|
10726
10918
|
await fsPromises8.rename(tmpPath, filePath);
|
|
10727
10919
|
}
|
|
10728
10920
|
async function scanLocalItems(projectRoot) {
|
|
10729
|
-
const pendingSync =
|
|
10921
|
+
const pendingSync = path51.join(projectRoot, ".cleargate", "delivery", "pending-sync");
|
|
10730
10922
|
const results = [];
|
|
10731
10923
|
let entries;
|
|
10732
10924
|
try {
|
|
@@ -10736,7 +10928,7 @@ async function scanLocalItems(projectRoot) {
|
|
|
10736
10928
|
}
|
|
10737
10929
|
for (const entry of entries) {
|
|
10738
10930
|
if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
|
|
10739
|
-
const fullPath =
|
|
10931
|
+
const fullPath = path51.join(pendingSync, entry.name);
|
|
10740
10932
|
try {
|
|
10741
10933
|
const raw = await fsPromises8.readFile(fullPath, "utf8");
|
|
10742
10934
|
const { fm, body } = parseFrontmatter(raw);
|
|
@@ -10764,7 +10956,7 @@ init_config();
|
|
|
10764
10956
|
// src/lib/sync/work-items.ts
|
|
10765
10957
|
init_cjs_shims();
|
|
10766
10958
|
var fsPromises9 = __toESM(require("fs/promises"), 1);
|
|
10767
|
-
var
|
|
10959
|
+
var path52 = __toESM(require("path"), 1);
|
|
10768
10960
|
var import_node_crypto2 = require("crypto");
|
|
10769
10961
|
var BATCH_SIZE = 100;
|
|
10770
10962
|
var ATTRIBUTION_FIELDS = /* @__PURE__ */ new Set([
|
|
@@ -10812,8 +11004,8 @@ function getItemId2(fm) {
|
|
|
10812
11004
|
}
|
|
10813
11005
|
async function walkDeliveryDirs(projectRoot) {
|
|
10814
11006
|
const dirs = [
|
|
10815
|
-
|
|
10816
|
-
|
|
11007
|
+
path52.join(projectRoot, ".cleargate", "delivery", "pending-sync"),
|
|
11008
|
+
path52.join(projectRoot, ".cleargate", "delivery", "archive")
|
|
10817
11009
|
];
|
|
10818
11010
|
const results = [];
|
|
10819
11011
|
for (const dir of dirs) {
|
|
@@ -10825,7 +11017,7 @@ async function walkDeliveryDirs(projectRoot) {
|
|
|
10825
11017
|
}
|
|
10826
11018
|
for (const entry of entries) {
|
|
10827
11019
|
if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
|
|
10828
|
-
const fullPath =
|
|
11020
|
+
const fullPath = path52.join(dir, entry.name);
|
|
10829
11021
|
try {
|
|
10830
11022
|
const raw = await fsPromises9.readFile(fullPath, "utf8");
|
|
10831
11023
|
const { fm, body } = parseFrontmatter(raw);
|
|
@@ -10850,7 +11042,7 @@ async function walkDeliveryDirs(projectRoot) {
|
|
|
10850
11042
|
return results;
|
|
10851
11043
|
}
|
|
10852
11044
|
async function writeAtomic6(filePath, content) {
|
|
10853
|
-
await fsPromises9.mkdir(
|
|
11045
|
+
await fsPromises9.mkdir(path52.dirname(filePath), { recursive: true });
|
|
10854
11046
|
const tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
10855
11047
|
await fsPromises9.writeFile(tmpPath, content, "utf8");
|
|
10856
11048
|
await fsPromises9.rename(tmpPath, filePath);
|
|
@@ -10917,9 +11109,9 @@ async function syncWorkItems(opts) {
|
|
|
10917
11109
|
|
|
10918
11110
|
// src/lib/admin-url.ts
|
|
10919
11111
|
init_cjs_shims();
|
|
10920
|
-
var
|
|
10921
|
-
var
|
|
10922
|
-
var
|
|
11112
|
+
var fs44 = __toESM(require("fs"), 1);
|
|
11113
|
+
var os10 = __toESM(require("os"), 1);
|
|
11114
|
+
var path53 = __toESM(require("path"), 1);
|
|
10923
11115
|
var DEFAULT_BASE = "https://admin.cleargate.soula.ge/";
|
|
10924
11116
|
function adminUrl(urlPath, opts) {
|
|
10925
11117
|
const env = opts?.env ?? process.env;
|
|
@@ -10940,10 +11132,10 @@ function adminUrl(urlPath, opts) {
|
|
|
10940
11132
|
return base;
|
|
10941
11133
|
}
|
|
10942
11134
|
function readLocalConfig() {
|
|
10943
|
-
const home =
|
|
11135
|
+
const home = os10.homedir();
|
|
10944
11136
|
if (!home) return null;
|
|
10945
|
-
const configPath =
|
|
10946
|
-
const raw =
|
|
11137
|
+
const configPath = path53.join(home, ".cleargate", "config.json");
|
|
11138
|
+
const raw = fs44.readFileSync(configPath, "utf8");
|
|
10947
11139
|
return JSON.parse(raw);
|
|
10948
11140
|
}
|
|
10949
11141
|
|
|
@@ -11058,7 +11250,7 @@ async function syncWorkItemsHandler(opts = {}) {
|
|
|
11058
11250
|
// src/commands/pull.ts
|
|
11059
11251
|
init_cjs_shims();
|
|
11060
11252
|
var fsPromises10 = __toESM(require("fs/promises"), 1);
|
|
11061
|
-
var
|
|
11253
|
+
var path54 = __toESM(require("path"), 1);
|
|
11062
11254
|
init_acquire();
|
|
11063
11255
|
init_config();
|
|
11064
11256
|
async function pullHandler(idOrRemoteId, opts = {}) {
|
|
@@ -11173,7 +11365,7 @@ async function pullHandler(idOrRemoteId, opts = {}) {
|
|
|
11173
11365
|
result: "ok"
|
|
11174
11366
|
};
|
|
11175
11367
|
await appendSyncLog(sprintRoot, entry);
|
|
11176
|
-
stdout(`pull: ${remoteId} applied to ${
|
|
11368
|
+
stdout(`pull: ${remoteId} applied to ${path54.relative(projectRoot, localPath)}
|
|
11177
11369
|
`);
|
|
11178
11370
|
if (opts.comments) {
|
|
11179
11371
|
const comments = await mcp2.call(
|
|
@@ -11196,7 +11388,7 @@ async function resolveRemoteId(idOrRemoteId, projectRoot) {
|
|
|
11196
11388
|
if (/^[A-Z]+-\d+/.test(idOrRemoteId)) {
|
|
11197
11389
|
return idOrRemoteId;
|
|
11198
11390
|
}
|
|
11199
|
-
const pendingSync =
|
|
11391
|
+
const pendingSync = path54.join(projectRoot, ".cleargate", "delivery", "pending-sync");
|
|
11200
11392
|
let entries;
|
|
11201
11393
|
try {
|
|
11202
11394
|
entries = await fsPromises10.readdir(pendingSync, { withFileTypes: true });
|
|
@@ -11206,7 +11398,7 @@ async function resolveRemoteId(idOrRemoteId, projectRoot) {
|
|
|
11206
11398
|
for (const entry of entries) {
|
|
11207
11399
|
if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
|
|
11208
11400
|
try {
|
|
11209
|
-
const raw = await fsPromises10.readFile(
|
|
11401
|
+
const raw = await fsPromises10.readFile(path54.join(pendingSync, entry.name), "utf8");
|
|
11210
11402
|
const { fm } = parseFrontmatter(raw);
|
|
11211
11403
|
for (const key of ["story_id", "epic_id", "proposal_id", "cr_id", "bug_id"]) {
|
|
11212
11404
|
if (fm[key] === idOrRemoteId && typeof fm["remote_id"] === "string") {
|
|
@@ -11219,7 +11411,7 @@ async function resolveRemoteId(idOrRemoteId, projectRoot) {
|
|
|
11219
11411
|
return null;
|
|
11220
11412
|
}
|
|
11221
11413
|
async function findLocalFile(remoteId, projectRoot) {
|
|
11222
|
-
const pendingSync =
|
|
11414
|
+
const pendingSync = path54.join(projectRoot, ".cleargate", "delivery", "pending-sync");
|
|
11223
11415
|
let entries;
|
|
11224
11416
|
try {
|
|
11225
11417
|
entries = await fsPromises10.readdir(pendingSync, { withFileTypes: true });
|
|
@@ -11228,7 +11420,7 @@ async function findLocalFile(remoteId, projectRoot) {
|
|
|
11228
11420
|
}
|
|
11229
11421
|
for (const entry of entries) {
|
|
11230
11422
|
if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
|
|
11231
|
-
const fullPath =
|
|
11423
|
+
const fullPath = path54.join(pendingSync, entry.name);
|
|
11232
11424
|
try {
|
|
11233
11425
|
const raw = await fsPromises10.readFile(fullPath, "utf8");
|
|
11234
11426
|
const { fm } = parseFrontmatter(raw);
|
|
@@ -11239,7 +11431,7 @@ async function findLocalFile(remoteId, projectRoot) {
|
|
|
11239
11431
|
return null;
|
|
11240
11432
|
}
|
|
11241
11433
|
async function writeAtomic7(filePath, content) {
|
|
11242
|
-
await fsPromises10.mkdir(
|
|
11434
|
+
await fsPromises10.mkdir(path54.dirname(filePath), { recursive: true });
|
|
11243
11435
|
const tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
11244
11436
|
await fsPromises10.writeFile(tmpPath, content, "utf8");
|
|
11245
11437
|
await fsPromises10.rename(tmpPath, filePath);
|
|
@@ -11255,7 +11447,7 @@ function getItemId3(fm) {
|
|
|
11255
11447
|
// src/commands/push.ts
|
|
11256
11448
|
init_cjs_shims();
|
|
11257
11449
|
var fsPromises11 = __toESM(require("fs/promises"), 1);
|
|
11258
|
-
var
|
|
11450
|
+
var path55 = __toESM(require("path"), 1);
|
|
11259
11451
|
init_acquire();
|
|
11260
11452
|
init_config();
|
|
11261
11453
|
async function pushHandler(fileOrId, opts = {}) {
|
|
@@ -11331,7 +11523,7 @@ async function pushHandler(fileOrId, opts = {}) {
|
|
|
11331
11523
|
}
|
|
11332
11524
|
async function handlePush(filePath, ctx) {
|
|
11333
11525
|
const { projectRoot, identity, sprintRoot, nowFn, resolveMcp, stdout, stderr, exit } = ctx;
|
|
11334
|
-
const resolvedPath =
|
|
11526
|
+
const resolvedPath = path55.isAbsolute(filePath) ? filePath : path55.resolve(projectRoot, filePath);
|
|
11335
11527
|
let rawContent;
|
|
11336
11528
|
try {
|
|
11337
11529
|
rawContent = await fsPromises11.readFile(resolvedPath, "utf8");
|
|
@@ -11457,8 +11649,8 @@ async function handleRevert(idOrRemoteId, ctx) {
|
|
|
11457
11649
|
void localPath;
|
|
11458
11650
|
}
|
|
11459
11651
|
async function resolveLocalItem(idOrRemoteId, projectRoot) {
|
|
11460
|
-
const pendingSync =
|
|
11461
|
-
const archive =
|
|
11652
|
+
const pendingSync = path55.join(projectRoot, ".cleargate", "delivery", "pending-sync");
|
|
11653
|
+
const archive = path55.join(projectRoot, ".cleargate", "delivery", "archive");
|
|
11462
11654
|
for (const dir of [pendingSync, archive]) {
|
|
11463
11655
|
let entries;
|
|
11464
11656
|
try {
|
|
@@ -11468,7 +11660,7 @@ async function resolveLocalItem(idOrRemoteId, projectRoot) {
|
|
|
11468
11660
|
}
|
|
11469
11661
|
for (const entry of entries) {
|
|
11470
11662
|
if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
|
|
11471
|
-
const fullPath =
|
|
11663
|
+
const fullPath = path55.join(dir, entry.name);
|
|
11472
11664
|
try {
|
|
11473
11665
|
const raw = await fsPromises11.readFile(fullPath, "utf8");
|
|
11474
11666
|
const { fm } = parseFrontmatter(raw);
|
|
@@ -11487,7 +11679,7 @@ async function resolveLocalItem(idOrRemoteId, projectRoot) {
|
|
|
11487
11679
|
return null;
|
|
11488
11680
|
}
|
|
11489
11681
|
async function writeAtomic8(filePath, content) {
|
|
11490
|
-
await fsPromises11.mkdir(
|
|
11682
|
+
await fsPromises11.mkdir(path55.dirname(filePath), { recursive: true });
|
|
11491
11683
|
const tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
11492
11684
|
await fsPromises11.writeFile(tmpPath, content, "utf8");
|
|
11493
11685
|
await fsPromises11.rename(tmpPath, filePath);
|
|
@@ -11516,7 +11708,7 @@ function getItemType2(fm) {
|
|
|
11516
11708
|
// src/commands/conflicts.ts
|
|
11517
11709
|
init_cjs_shims();
|
|
11518
11710
|
var fsPromises12 = __toESM(require("fs/promises"), 1);
|
|
11519
|
-
var
|
|
11711
|
+
var path56 = __toESM(require("path"), 1);
|
|
11520
11712
|
init_acquire();
|
|
11521
11713
|
init_config();
|
|
11522
11714
|
var RESOLUTION_HINTS = {
|
|
@@ -11554,7 +11746,7 @@ async function conflictsHandler(opts = {}) {
|
|
|
11554
11746
|
}
|
|
11555
11747
|
}
|
|
11556
11748
|
}
|
|
11557
|
-
const conflictsFile =
|
|
11749
|
+
const conflictsFile = path56.join(projectRoot, ".cleargate", ".conflicts.json");
|
|
11558
11750
|
let data;
|
|
11559
11751
|
try {
|
|
11560
11752
|
const raw = await fsPromises12.readFile(conflictsFile, "utf8");
|
|
@@ -11642,24 +11834,24 @@ function formatEntry(entry) {
|
|
|
11642
11834
|
|
|
11643
11835
|
// src/commands/admin-login.ts
|
|
11644
11836
|
init_cjs_shims();
|
|
11645
|
-
var
|
|
11646
|
-
var
|
|
11647
|
-
var
|
|
11837
|
+
var fs45 = __toESM(require("fs"), 1);
|
|
11838
|
+
var path57 = __toESM(require("path"), 1);
|
|
11839
|
+
var os11 = __toESM(require("os"), 1);
|
|
11648
11840
|
var DEFAULT_MCP_URL = "http://localhost:3000";
|
|
11649
11841
|
function resolveMcpUrl(mcpUrlFlag, env) {
|
|
11650
11842
|
return (mcpUrlFlag ?? (env ?? process.env)["CLEARGATE_MCP_URL"] ?? DEFAULT_MCP_URL).replace(/\/$/, "");
|
|
11651
11843
|
}
|
|
11652
11844
|
function resolveAuthFilePath(opts) {
|
|
11653
11845
|
if (opts.authFilePath) return opts.authFilePath;
|
|
11654
|
-
const homedirFn = opts.homedir ??
|
|
11655
|
-
return
|
|
11846
|
+
const homedirFn = opts.homedir ?? os11.homedir;
|
|
11847
|
+
return path57.join(homedirFn(), ".cleargate", "admin-auth.json");
|
|
11656
11848
|
}
|
|
11657
11849
|
function writeAdminAuth(filePath, token) {
|
|
11658
|
-
const dir =
|
|
11659
|
-
|
|
11850
|
+
const dir = path57.dirname(filePath);
|
|
11851
|
+
fs45.mkdirSync(dir, { recursive: true });
|
|
11660
11852
|
const payload = JSON.stringify({ version: 1, token }, null, 2);
|
|
11661
|
-
|
|
11662
|
-
|
|
11853
|
+
fs45.writeFileSync(filePath, payload, { encoding: "utf8", mode: 384 });
|
|
11854
|
+
fs45.chmodSync(filePath, 384);
|
|
11663
11855
|
}
|
|
11664
11856
|
async function adminLoginHandler(opts = {}) {
|
|
11665
11857
|
const fetchFn = opts.fetch ?? globalThis.fetch;
|
|
@@ -11769,8 +11961,8 @@ async function adminLoginHandler(opts = {}) {
|
|
|
11769
11961
|
|
|
11770
11962
|
// src/commands/hotfix.ts
|
|
11771
11963
|
init_cjs_shims();
|
|
11772
|
-
var
|
|
11773
|
-
var
|
|
11964
|
+
var fs46 = __toESM(require("fs"), 1);
|
|
11965
|
+
var path58 = __toESM(require("path"), 1);
|
|
11774
11966
|
function defaultExit4(code) {
|
|
11775
11967
|
return process.exit(code);
|
|
11776
11968
|
}
|
|
@@ -11780,7 +11972,7 @@ function maxHotfixId(pendingDir) {
|
|
|
11780
11972
|
let max = 0;
|
|
11781
11973
|
let entries;
|
|
11782
11974
|
try {
|
|
11783
|
-
entries =
|
|
11975
|
+
entries = fs46.readdirSync(pendingDir);
|
|
11784
11976
|
} catch {
|
|
11785
11977
|
return 0;
|
|
11786
11978
|
}
|
|
@@ -11794,13 +11986,13 @@ function maxHotfixId(pendingDir) {
|
|
|
11794
11986
|
return max;
|
|
11795
11987
|
}
|
|
11796
11988
|
function countActiveHotfixes(repoRoot) {
|
|
11797
|
-
const pendingDir =
|
|
11798
|
-
const archiveDir =
|
|
11989
|
+
const pendingDir = path58.join(repoRoot, ".cleargate", "delivery", "pending-sync");
|
|
11990
|
+
const archiveDir = path58.join(repoRoot, ".cleargate", "delivery", "archive");
|
|
11799
11991
|
const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1e3;
|
|
11800
11992
|
let count = 0;
|
|
11801
11993
|
let pendingEntries = [];
|
|
11802
11994
|
try {
|
|
11803
|
-
pendingEntries =
|
|
11995
|
+
pendingEntries = fs46.readdirSync(pendingDir);
|
|
11804
11996
|
} catch {
|
|
11805
11997
|
}
|
|
11806
11998
|
for (const entry of pendingEntries) {
|
|
@@ -11808,13 +12000,13 @@ function countActiveHotfixes(repoRoot) {
|
|
|
11808
12000
|
}
|
|
11809
12001
|
let archiveEntries = [];
|
|
11810
12002
|
try {
|
|
11811
|
-
archiveEntries =
|
|
12003
|
+
archiveEntries = fs46.readdirSync(archiveDir);
|
|
11812
12004
|
} catch {
|
|
11813
12005
|
}
|
|
11814
12006
|
for (const entry of archiveEntries) {
|
|
11815
12007
|
if (entry.startsWith("HOTFIX-") && entry.endsWith(".md")) {
|
|
11816
12008
|
try {
|
|
11817
|
-
const stat =
|
|
12009
|
+
const stat = fs46.statSync(path58.join(archiveDir, entry));
|
|
11818
12010
|
if (stat.mtimeMs >= sevenDaysAgo) count++;
|
|
11819
12011
|
} catch {
|
|
11820
12012
|
}
|
|
@@ -11823,7 +12015,7 @@ function countActiveHotfixes(repoRoot) {
|
|
|
11823
12015
|
return count;
|
|
11824
12016
|
}
|
|
11825
12017
|
function resolveTemplatePath(repoRoot) {
|
|
11826
|
-
return
|
|
12018
|
+
return path58.join(repoRoot, ".cleargate", "templates", "hotfix.md");
|
|
11827
12019
|
}
|
|
11828
12020
|
function hotfixNewHandler(opts, cli) {
|
|
11829
12021
|
const stdoutFn = cli?.stdout ?? ((s) => process.stdout.write(s + "\n"));
|
|
@@ -11842,14 +12034,14 @@ function hotfixNewHandler(opts, cli) {
|
|
|
11842
12034
|
);
|
|
11843
12035
|
return exitFn(1);
|
|
11844
12036
|
}
|
|
11845
|
-
const pendingDir =
|
|
12037
|
+
const pendingDir = path58.join(repoRoot, ".cleargate", "delivery", "pending-sync");
|
|
11846
12038
|
const maxId = maxHotfixId(pendingDir);
|
|
11847
12039
|
const nextId = maxId + 1;
|
|
11848
12040
|
const idStr = `HOTFIX-${String(nextId).padStart(3, "0")}`;
|
|
11849
12041
|
const templatePath = resolveTemplatePath(repoRoot);
|
|
11850
12042
|
let templateContent;
|
|
11851
12043
|
try {
|
|
11852
|
-
templateContent =
|
|
12044
|
+
templateContent = fs46.readFileSync(templatePath, "utf8");
|
|
11853
12045
|
} catch {
|
|
11854
12046
|
stderrFn(`[cleargate hotfix new] template not found: ${templatePath}`);
|
|
11855
12047
|
return exitFn(2);
|
|
@@ -11857,10 +12049,10 @@ function hotfixNewHandler(opts, cli) {
|
|
|
11857
12049
|
const content = templateContent.replace(/\{ID\}/g, idStr).replace(/\{SLUG\}/g, opts.slug).replace(/\{ISO\}/g, now);
|
|
11858
12050
|
const fileSlug = opts.slug.replace(/-/g, "_");
|
|
11859
12051
|
const fileName = `${idStr}_${fileSlug}.md`;
|
|
11860
|
-
const outPath =
|
|
12052
|
+
const outPath = path58.join(pendingDir, fileName);
|
|
11861
12053
|
try {
|
|
11862
|
-
|
|
11863
|
-
|
|
12054
|
+
fs46.mkdirSync(pendingDir, { recursive: true });
|
|
12055
|
+
fs46.writeFileSync(outPath, content, "utf8");
|
|
11864
12056
|
} catch (err) {
|
|
11865
12057
|
const msg = err instanceof Error ? err.message : String(err);
|
|
11866
12058
|
stderrFn(`[cleargate hotfix new] write failed: ${msg}`);
|