@sunasteriskrnd/takumi 1.0.0-dev.39 → 1.0.0-dev.40

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.
Files changed (2) hide show
  1. package/dist/index.js +614 -446
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -19815,7 +19815,7 @@ var package_default;
19815
19815
  var init_package = __esm(() => {
19816
19816
  package_default = {
19817
19817
  name: "@sunasteriskrnd/takumi",
19818
- version: "1.0.0-dev.39",
19818
+ version: "1.0.0-dev.40",
19819
19819
  description: "CLI tool for bootstrapping and managing Takumi projects",
19820
19820
  type: "module",
19821
19821
  repository: {
@@ -49135,7 +49135,7 @@ __export(exports_monorepo_resolver, {
49135
49135
  resolveMonorepoRoot: () => resolveMonorepoRoot
49136
49136
  });
49137
49137
  import { existsSync as existsSync56, readFileSync as readFileSync22 } from "node:fs";
49138
- import { dirname as dirname33, join as join116, resolve as resolve26 } from "node:path";
49138
+ import { dirname as dirname33, join as join117, resolve as resolve26 } from "node:path";
49139
49139
  import { fileURLToPath as fileURLToPath3 } from "node:url";
49140
49140
  function parseMetadataAt(metadataPath) {
49141
49141
  if (!existsSync56(metadataPath))
@@ -49152,7 +49152,7 @@ function parseMetadataAt(metadataPath) {
49152
49152
  }
49153
49153
  }
49154
49154
  function readSourceDirFromPackageJson(candidateRoot) {
49155
- const packageJsonPath = join116(candidateRoot, "package.json");
49155
+ const packageJsonPath = join117(candidateRoot, "package.json");
49156
49156
  if (!existsSync56(packageJsonPath))
49157
49157
  return null;
49158
49158
  try {
@@ -49175,7 +49175,7 @@ function tryReadAtCandidate(candidateRoot) {
49175
49175
  };
49176
49176
  }
49177
49177
  const sourceDir = readSourceDirFromPackageJson(candidateRoot) ?? "claude";
49178
- const sourceRoot = join116(candidateRoot, sourceDir);
49178
+ const sourceRoot = join117(candidateRoot, sourceDir);
49179
49179
  const nestedMetadata = parseMetadataAt(getManifestPath(sourceRoot)) ?? parseMetadataAt(getLegacyManifestPath(sourceRoot));
49180
49180
  if (nestedMetadata) {
49181
49181
  return {
@@ -70229,6 +70229,9 @@ async function readStdinJson() {
70229
70229
  }
70230
70230
  }
70231
70231
 
70232
+ // src/domains/hooks/telemetry/lib/claude-transcript-apply.ts
70233
+ import { stat as stat8 } from "node:fs/promises";
70234
+
70232
70235
  // src/domains/hooks/telemetry/lib/claude-transcript-reader.ts
70233
70236
  function num2(v2) {
70234
70237
  return typeof v2 === "number" && Number.isFinite(v2) ? v2 : 0;
@@ -70290,6 +70293,240 @@ function bucketTokens(records) {
70290
70293
  return { mainLoopDelta, subagentDeltas, tokenUsageDeltas };
70291
70294
  }
70292
70295
 
70296
+ // src/domains/hooks/telemetry/lib/session-lock.ts
70297
+ var import_proper_lockfile8 = __toESM(require_proper_lockfile(), 1);
70298
+ import { promises as fs21 } from "node:fs";
70299
+ import { join as join95 } from "node:path";
70300
+ var LOCK_RESOURCE = "summary.json";
70301
+ var DEFAULT_TIMEOUT_MS3 = 2000;
70302
+ var RETRY_INTERVAL_MS = 100;
70303
+ var DEFAULT_STALE_AFTER_MS = 1e4;
70304
+ async function withSummaryLock(sessionDir, fn, options2 = {}) {
70305
+ const timeoutMs = options2.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
70306
+ const staleAfterMs = options2.staleAfterMs ?? DEFAULT_STALE_AFTER_MS;
70307
+ const resource = join95(sessionDir, LOCK_RESOURCE);
70308
+ try {
70309
+ await fs21.mkdir(sessionDir, { recursive: true });
70310
+ } catch {
70311
+ return fn();
70312
+ }
70313
+ let release = null;
70314
+ try {
70315
+ release = await import_proper_lockfile8.default.lock(resource, {
70316
+ realpath: false,
70317
+ stale: staleAfterMs,
70318
+ retries: {
70319
+ retries: Math.max(0, Math.ceil(timeoutMs / RETRY_INTERVAL_MS)),
70320
+ factor: 1,
70321
+ minTimeout: RETRY_INTERVAL_MS,
70322
+ maxTimeout: RETRY_INTERVAL_MS
70323
+ },
70324
+ onCompromised: (err) => hookLog("summary_lock_compromised", { sessionDir, error: err?.message })
70325
+ });
70326
+ } catch (e2) {
70327
+ hookLog("summary_lock_timeout", { sessionDir, timeoutMs, error: e2?.message });
70328
+ }
70329
+ try {
70330
+ return await fn();
70331
+ } finally {
70332
+ if (release) {
70333
+ await release().catch(() => {});
70334
+ }
70335
+ }
70336
+ }
70337
+
70338
+ // src/domains/hooks/telemetry/lib/summary.ts
70339
+ import { promises as fs22 } from "node:fs";
70340
+
70341
+ // src/domains/hooks/telemetry/lib/session-paths.ts
70342
+ init_paths2();
70343
+ import { join as join97 } from "node:path";
70344
+
70345
+ // src/shared/project-paths.ts
70346
+ init_paths2();
70347
+ import { createHash as createHash10 } from "node:crypto";
70348
+ import { realpathSync as realpathSync2 } from "node:fs";
70349
+ import { basename as basename17, join as join96 } from "node:path";
70350
+ function encodeCwd(cwd2) {
70351
+ const stripped = cwd2.replace(/^\/+/, "");
70352
+ const sanitized = stripped.replace(/[^a-zA-Z0-9-]/g, "-");
70353
+ return `-${sanitized}`;
70354
+ }
70355
+ function computeProjectHash(cwd2) {
70356
+ let canonical = cwd2;
70357
+ try {
70358
+ canonical = realpathSync2(cwd2);
70359
+ } catch {
70360
+ hookLog("project-hash", { fallback: "realpath_failed", cwd: cwd2 });
70361
+ }
70362
+ return createHash10("sha256").update(canonical).digest("hex").slice(0, 16);
70363
+ }
70364
+ function getProjectLabel(cwd2) {
70365
+ return basename17(cwd2) || "";
70366
+ }
70367
+ function getProjectsRoot() {
70368
+ return join96(getConfigDir(), "projects");
70369
+ }
70370
+ function getProjectDir(args) {
70371
+ return join96(getProjectsRoot(), encodeCwd(args.cwd), args.agent);
70372
+ }
70373
+
70374
+ // src/domains/hooks/telemetry/lib/session-paths.ts
70375
+ var MAX_SESSION_ID_LEN = 128;
70376
+ function safeSessionSegment(sessionId) {
70377
+ if (typeof sessionId !== "string" || sessionId.length === 0)
70378
+ return null;
70379
+ const cleaned = sessionId.replace(/[^a-zA-Z0-9._-]/g, "");
70380
+ return cleaned.length > 0 ? cleaned.slice(0, MAX_SESSION_ID_LEN) : null;
70381
+ }
70382
+ function getSessionsRoot() {
70383
+ return join97(getConfigDir(), "sessions");
70384
+ }
70385
+ function getSessionDirV2(args) {
70386
+ const segment = safeSessionSegment(args.sessionId);
70387
+ if (!segment)
70388
+ return null;
70389
+ return join97(getProjectDir({ agent: args.agent, cwd: args.cwd }), "sessions", segment);
70390
+ }
70391
+ function getEventsFile(sessionDir) {
70392
+ return join97(sessionDir, "events.jsonl");
70393
+ }
70394
+ function getSummaryFile(sessionDir) {
70395
+ return join97(sessionDir, "summary.json");
70396
+ }
70397
+ function getLastPushFile(sessionDir) {
70398
+ return join97(sessionDir, "last_push.txt");
70399
+ }
70400
+ var OBSERVATIONS_FILENAME = "observations.jsonl";
70401
+ function getObservationsFile(sessionDir) {
70402
+ return join97(sessionDir, OBSERVATIONS_FILENAME);
70403
+ }
70404
+ function getObservationsFlushingFile(sessionDir) {
70405
+ return join97(sessionDir, `${OBSERVATIONS_FILENAME}.flushing`);
70406
+ }
70407
+ function getObservationsPushedFile(sessionDir) {
70408
+ return join97(sessionDir, "obs_pushed.txt");
70409
+ }
70410
+ function getMetaFile(sessionDir) {
70411
+ return join97(sessionDir, "meta.json");
70412
+ }
70413
+
70414
+ // src/domains/hooks/telemetry/lib/summary.ts
70415
+ function zeroTokens3() {
70416
+ return { input: 0, output: 0, cache_read: 0, cache_write: 0 };
70417
+ }
70418
+ function initialSummary(args) {
70419
+ return {
70420
+ schema_version: 1,
70421
+ session_id: args.sessionId,
70422
+ agent: args.agent,
70423
+ cli_version: args.cliVersion ?? null,
70424
+ kit_versions: args.kitVersions ?? {},
70425
+ project: args.project,
70426
+ timing: { started_at: args.startedAt, ended_at: null, duration_s: null },
70427
+ main_loop_tokens: zeroTokens3(),
70428
+ token_usage: {},
70429
+ subagents: [],
70430
+ skills: [],
70431
+ tool_stats: {
70432
+ schema_version: 1,
70433
+ total_events: 0,
70434
+ total_tool_calls: 0,
70435
+ by_type: {},
70436
+ by_name: {},
70437
+ subagents: { by_type: {} },
70438
+ skills: { by_name: {} }
70439
+ },
70440
+ totals: zeroTokens3(),
70441
+ pending_user_triggers: [],
70442
+ skills_in_flight: {},
70443
+ transcript_offset: 0,
70444
+ remote: { last_pushed_at: null, last_status: null }
70445
+ };
70446
+ }
70447
+ async function readSummary(sessionDir) {
70448
+ let raw;
70449
+ try {
70450
+ raw = await fs22.readFile(getSummaryFile(sessionDir), "utf8");
70451
+ } catch {
70452
+ return null;
70453
+ }
70454
+ try {
70455
+ return JSON.parse(raw);
70456
+ } catch {
70457
+ return null;
70458
+ }
70459
+ }
70460
+ async function writeSummary(sessionDir, summary) {
70461
+ await fs22.mkdir(sessionDir, { recursive: true });
70462
+ const target = getSummaryFile(sessionDir);
70463
+ const tmp = `${target}.tmp`;
70464
+ await fs22.writeFile(tmp, JSON.stringify(summary), "utf8");
70465
+ await fs22.rename(tmp, target);
70466
+ }
70467
+ function isPlainObject2(value) {
70468
+ return typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
70469
+ }
70470
+ function mergeDeep(existing, delta) {
70471
+ if (delta === undefined)
70472
+ return existing;
70473
+ if (typeof existing === "number" && typeof delta === "number")
70474
+ return existing + delta;
70475
+ if (Array.isArray(existing) && Array.isArray(delta))
70476
+ return [...existing, ...delta];
70477
+ if (isPlainObject2(existing) && isPlainObject2(delta)) {
70478
+ const out = { ...existing };
70479
+ for (const key of Object.keys(delta)) {
70480
+ out[key] = key in existing ? mergeDeep(existing[key], delta[key]) : delta[key];
70481
+ }
70482
+ return out;
70483
+ }
70484
+ return delta;
70485
+ }
70486
+ function mergeSummary(existing, delta) {
70487
+ const merged = mergeDeep(existing, delta);
70488
+ merged.schema_version = 1;
70489
+ merged.tool_stats.schema_version = 1;
70490
+ return merged;
70491
+ }
70492
+
70493
+ // src/domains/hooks/telemetry/lib/transcript-fingerprint.ts
70494
+ import { createHash as createHash11 } from "node:crypto";
70495
+ import { open as open2 } from "node:fs/promises";
70496
+ var HEAD_BYTES = 4096;
70497
+ async function headFingerprint(transcriptPath) {
70498
+ let handle;
70499
+ try {
70500
+ handle = await open2(transcriptPath, "r");
70501
+ const buf = Buffer.alloc(HEAD_BYTES);
70502
+ const { bytesRead } = await handle.read(buf, 0, HEAD_BYTES, 0);
70503
+ if (bytesRead < HEAD_BYTES)
70504
+ return null;
70505
+ return createHash11("sha256").update(buf.subarray(0, bytesRead)).digest("hex");
70506
+ } catch {
70507
+ return null;
70508
+ } finally {
70509
+ await handle?.close().catch(() => {});
70510
+ }
70511
+ }
70512
+ function compactionBoundary(records) {
70513
+ const idx = records.findIndex((r2) => r2.isCompactSummary === true);
70514
+ return idx === -1 ? 0 : idx + 1;
70515
+ }
70516
+
70517
+ // src/domains/hooks/telemetry/lib/transcript-metrics.ts
70518
+ function deriveTranscriptMetrics(records) {
70519
+ let turnCount = 0;
70520
+ let apiErrorCount = 0;
70521
+ for (const record of records) {
70522
+ if (record.isApiErrorMessage === true)
70523
+ apiErrorCount += 1;
70524
+ if (record.type === "system" && record.subtype === "turn_duration")
70525
+ turnCount += 1;
70526
+ }
70527
+ return { turnCount, apiErrorCount };
70528
+ }
70529
+
70293
70530
  // src/domains/hooks/telemetry/lib/claude-transcript-apply.ts
70294
70531
  function ensureTokens(t) {
70295
70532
  return t ?? { input: 0, output: 0, cache_read: 0, cache_write: 0 };
@@ -70309,43 +70546,85 @@ function mergeTokenUsageDeltas(existing, deltas) {
70309
70546
  }
70310
70547
  return out;
70311
70548
  }
70312
- async function applyClaudeTranscriptDelta(args) {
70313
- if (!args.transcriptPath) {
70314
- return { summary: args.summary, read: false };
70549
+ function foldRecordsIntoSummary(summary, records, nextOffset, newFingerprint, compactionDetected) {
70550
+ const { mainLoopDelta, subagentDeltas, tokenUsageDeltas } = bucketTokens(records);
70551
+ const metrics = deriveTranscriptMetrics(records);
70552
+ const merged = mergeSummary(summary, {
70553
+ turn_count: metrics.turnCount,
70554
+ api_error_count: metrics.apiErrorCount
70555
+ });
70556
+ merged.main_loop_tokens = addTokens3(summary.main_loop_tokens, mainLoopDelta);
70557
+ merged.subagents = summary.subagents.map((rec) => {
70558
+ const delta = subagentDeltas.get(rec.id);
70559
+ if (!delta)
70560
+ return rec;
70561
+ return { ...rec, tokens: addTokens3(ensureTokens(rec.tokens), delta) };
70562
+ });
70563
+ merged.token_usage = mergeTokenUsageDeltas(summary.token_usage, tokenUsageDeltas);
70564
+ merged.transcript_offset = nextOffset;
70565
+ if (newFingerprint) {
70566
+ merged.transcript_fingerprint = newFingerprint;
70567
+ } else if (compactionDetected) {
70568
+ merged.transcript_fingerprint = undefined;
70315
70569
  }
70316
- try {
70317
- const { records, nextOffset } = await tailRead({
70318
- transcriptPath: args.transcriptPath,
70319
- offset: args.summary.transcript_offset
70320
- });
70321
- if (records.length === 0 && nextOffset === args.summary.transcript_offset) {
70322
- return { summary: args.summary, read: true };
70570
+ return merged;
70571
+ }
70572
+ async function applyClaudeTranscriptDelta(args) {
70573
+ if (!args.transcriptPath)
70574
+ return { summary: null, read: false };
70575
+ const transcriptPath = args.transcriptPath;
70576
+ return withSummaryLock(args.sessionDir, async () => {
70577
+ try {
70578
+ const summary = await readSummary(args.sessionDir);
70579
+ if (!summary)
70580
+ return { summary: null, read: false };
70581
+ const newFingerprint = await headFingerprint(transcriptPath);
70582
+ const priorFingerprint = summary.transcript_fingerprint;
70583
+ const fingerprintMismatch = newFingerprint !== null && priorFingerprint !== undefined && newFingerprint !== priorFingerprint;
70584
+ let currentSize = null;
70585
+ try {
70586
+ currentSize = (await stat8(transcriptPath)).size;
70587
+ } catch {
70588
+ currentSize = null;
70589
+ }
70590
+ const sizeShrank = currentSize !== null && currentSize < summary.transcript_offset;
70591
+ const compactionDetected = fingerprintMismatch || sizeShrank;
70592
+ let recordsToFold;
70593
+ let nextOffset;
70594
+ if (compactionDetected) {
70595
+ const full = await tailRead({ transcriptPath, offset: 0 });
70596
+ const fullRecords = full.records;
70597
+ const boundary = compactionBoundary(fullRecords);
70598
+ if (boundary === 0) {
70599
+ hookLog("transcript_drift", { compaction_marker_unconfirmed: true });
70600
+ recordsToFold = [];
70601
+ } else {
70602
+ recordsToFold = fullRecords.slice(boundary);
70603
+ }
70604
+ nextOffset = full.nextOffset;
70605
+ } else {
70606
+ const tail = await tailRead({ transcriptPath, offset: summary.transcript_offset });
70607
+ recordsToFold = tail.records;
70608
+ nextOffset = tail.nextOffset;
70609
+ }
70610
+ if (!compactionDetected && recordsToFold.length === 0 && nextOffset === summary.transcript_offset) {
70611
+ return { summary, read: true };
70612
+ }
70613
+ const updated = foldRecordsIntoSummary(summary, recordsToFold, nextOffset, newFingerprint, compactionDetected);
70614
+ await writeSummary(args.sessionDir, updated);
70615
+ return { summary: updated, read: true };
70616
+ } catch (e2) {
70617
+ const error = e2?.message ?? String(e2);
70618
+ hookLog("transcript_apply", { error });
70619
+ return { summary: null, read: false, error };
70323
70620
  }
70324
- const { mainLoopDelta, subagentDeltas, tokenUsageDeltas } = bucketTokens(records);
70325
- const updated = {
70326
- ...args.summary,
70327
- main_loop_tokens: addTokens3(args.summary.main_loop_tokens, mainLoopDelta),
70328
- subagents: args.summary.subagents.map((rec) => {
70329
- const delta = subagentDeltas.get(rec.id);
70330
- if (!delta)
70331
- return rec;
70332
- return { ...rec, tokens: addTokens3(ensureTokens(rec.tokens), delta) };
70333
- }),
70334
- token_usage: mergeTokenUsageDeltas(args.summary.token_usage, tokenUsageDeltas),
70335
- transcript_offset: nextOffset
70336
- };
70337
- return { summary: updated, read: true };
70338
- } catch (e2) {
70339
- const error = e2?.message ?? String(e2);
70340
- hookLog("transcript_apply", { error });
70341
- return { summary: args.summary, read: false, error };
70342
- }
70621
+ });
70343
70622
  }
70344
70623
 
70345
70624
  // src/domains/hooks/telemetry/lib/detached-put.ts
70346
70625
  import { spawn as spawn2 } from "node:child_process";
70347
70626
  import { openSync as openSync5 } from "node:fs";
70348
- import { dirname as dirname26, join as join95 } from "node:path";
70627
+ import { dirname as dirname26, join as join98 } from "node:path";
70349
70628
  var ALLOWED_ENV_PREFIXES = ["TKM_", "TAKUMI_"];
70350
70629
  var ALLOWED_ENV_KEYS = new Set(["HOME", "USERPROFILE", "PATH", "NODE_ENV"]);
70351
70630
  var DETACH_DEBUG_LOG_NAME = "detach-debug.log";
@@ -70353,7 +70632,7 @@ function effectiveDetachMode(flags) {
70353
70632
  return flags.noDetach ? "inline" : "detached";
70354
70633
  }
70355
70634
  function sessionDebugLogPath(sessionDir) {
70356
- return join95(sessionDir, DETACH_DEBUG_LOG_NAME);
70635
+ return join98(sessionDir, DETACH_DEBUG_LOG_NAME);
70357
70636
  }
70358
70637
  var BUNFS_PREFIX = "/$bunfs/";
70359
70638
  function resolveInvocationPrefix() {
@@ -70383,7 +70662,7 @@ function resolvePreloadScript(entryPath) {
70383
70662
  try {
70384
70663
  const srcDir = dirname26(entryPath);
70385
70664
  const repoRoot = dirname26(srcDir);
70386
- return join95(repoRoot, "scripts", "preload-config-override.ts");
70665
+ return join98(repoRoot, "scripts", "preload-config-override.ts");
70387
70666
  } catch {
70388
70667
  return null;
70389
70668
  }
@@ -70450,87 +70729,32 @@ function decodeJobArgv(argv) {
70450
70729
  }
70451
70730
  }
70452
70731
 
70453
- // src/domains/hooks/telemetry/lib/session-meta.ts
70454
- import { promises as fs21 } from "node:fs";
70455
-
70456
- // src/domains/hooks/telemetry/lib/session-paths.ts
70457
- init_paths2();
70458
- import { join as join97 } from "node:path";
70459
-
70460
- // src/shared/project-paths.ts
70461
- init_paths2();
70462
- import { createHash as createHash10 } from "node:crypto";
70463
- import { realpathSync as realpathSync2 } from "node:fs";
70464
- import { basename as basename17, join as join96 } from "node:path";
70465
- function encodeCwd(cwd2) {
70466
- const stripped = cwd2.replace(/^\/+/, "");
70467
- const sanitized = stripped.replace(/[^a-zA-Z0-9-]/g, "-");
70468
- return `-${sanitized}`;
70469
- }
70470
- function computeProjectHash(cwd2) {
70471
- let canonical = cwd2;
70472
- try {
70473
- canonical = realpathSync2(cwd2);
70474
- } catch {
70475
- hookLog("project-hash", { fallback: "realpath_failed", cwd: cwd2 });
70476
- }
70477
- return createHash10("sha256").update(canonical).digest("hex").slice(0, 16);
70478
- }
70479
- function getProjectLabel(cwd2) {
70480
- return basename17(cwd2) || "";
70481
- }
70482
- function getProjectsRoot() {
70483
- return join96(getConfigDir(), "projects");
70484
- }
70485
- function getProjectDir(args) {
70486
- return join96(getProjectsRoot(), encodeCwd(args.cwd), args.agent);
70487
- }
70488
-
70489
- // src/domains/hooks/telemetry/lib/session-paths.ts
70490
- var MAX_SESSION_ID_LEN = 128;
70491
- function safeSessionSegment(sessionId) {
70492
- if (typeof sessionId !== "string" || sessionId.length === 0)
70493
- return null;
70494
- const cleaned = sessionId.replace(/[^a-zA-Z0-9._-]/g, "");
70495
- return cleaned.length > 0 ? cleaned.slice(0, MAX_SESSION_ID_LEN) : null;
70496
- }
70497
- function getSessionsRoot() {
70498
- return join97(getConfigDir(), "sessions");
70499
- }
70500
- function getSessionDirV2(args) {
70501
- const segment = safeSessionSegment(args.sessionId);
70502
- if (!segment)
70503
- return null;
70504
- return join97(getProjectDir({ agent: args.agent, cwd: args.cwd }), "sessions", segment);
70505
- }
70506
- function getEventsFile(sessionDir) {
70507
- return join97(sessionDir, "events.jsonl");
70508
- }
70509
- function getSummaryFile(sessionDir) {
70510
- return join97(sessionDir, "summary.json");
70511
- }
70512
- function getLastPushFile(sessionDir) {
70513
- return join97(sessionDir, "last_push.txt");
70514
- }
70515
- var OBSERVATIONS_FILENAME = "observations.jsonl";
70516
- function getObservationsFile(sessionDir) {
70517
- return join97(sessionDir, OBSERVATIONS_FILENAME);
70518
- }
70519
- function getObservationsFlushingFile(sessionDir) {
70520
- return join97(sessionDir, `${OBSERVATIONS_FILENAME}.flushing`);
70732
+ // src/domains/hooks/telemetry/lib/session-lifecycle.ts
70733
+ function elapsedSeconds(sinceIso, nowIso) {
70734
+ if (!sinceIso)
70735
+ return 0;
70736
+ const ms = Date.parse(nowIso) - Date.parse(sinceIso);
70737
+ return ms > 0 ? ms / 1000 : 0;
70521
70738
  }
70522
- function getObservationsPushedFile(sessionDir) {
70523
- return join97(sessionDir, "obs_pushed.txt");
70739
+ function openBusyInterval(summary, nowIso) {
70740
+ return { ...summary, active_since: nowIso };
70524
70741
  }
70525
- function getMetaFile(sessionDir) {
70526
- return join97(sessionDir, "meta.json");
70742
+ function closeBusyInterval(summary, nowIso) {
70743
+ if (!summary.active_since)
70744
+ return summary;
70745
+ return {
70746
+ ...summary,
70747
+ agent_busy_time_s: (summary.agent_busy_time_s ?? 0) + elapsedSeconds(summary.active_since, nowIso),
70748
+ active_since: undefined
70749
+ };
70527
70750
  }
70528
70751
 
70529
70752
  // src/domains/hooks/telemetry/lib/session-meta.ts
70753
+ import { promises as fs23 } from "node:fs";
70530
70754
  async function readMeta(sessionDir) {
70531
70755
  let raw;
70532
70756
  try {
70533
- raw = await fs21.readFile(getMetaFile(sessionDir), "utf8");
70757
+ raw = await fs23.readFile(getMetaFile(sessionDir), "utf8");
70534
70758
  } catch {
70535
70759
  return null;
70536
70760
  }
@@ -70543,13 +70767,13 @@ async function readMeta(sessionDir) {
70543
70767
  async function writeMetaIfAbsent(sessionDir, meta) {
70544
70768
  const target = getMetaFile(sessionDir);
70545
70769
  try {
70546
- await fs21.access(target);
70770
+ await fs23.access(target);
70547
70771
  return;
70548
70772
  } catch {}
70549
- await fs21.mkdir(sessionDir, { recursive: true });
70773
+ await fs23.mkdir(sessionDir, { recursive: true });
70550
70774
  const tmp = `${target}.tmp`;
70551
- await fs21.writeFile(tmp, JSON.stringify(meta), "utf8");
70552
- await fs21.rename(tmp, target);
70775
+ await fs23.writeFile(tmp, JSON.stringify(meta), "utf8");
70776
+ await fs23.rename(tmp, target);
70553
70777
  }
70554
70778
 
70555
70779
  // src/domains/hooks/telemetry/lib/session-payload.ts
@@ -70577,98 +70801,22 @@ function buildSessionPayload(args) {
70577
70801
  milestone_completed: args.milestone,
70578
70802
  error_count: args.errorCount,
70579
70803
  tool_stats: summary.tool_stats,
70580
- ...hasTokenUsage ? { token_usage: summary.token_usage } : {}
70804
+ ...hasTokenUsage ? { token_usage: summary.token_usage } : {},
70805
+ ...summary.turn_count !== undefined ? { turn_count: summary.turn_count } : {},
70806
+ ...summary.api_error_count !== undefined ? { api_error_count: summary.api_error_count } : {},
70807
+ ...summary.agent_busy_time_s !== undefined ? { agent_busy_time_s: Math.round(summary.agent_busy_time_s) } : {},
70808
+ summary_generated_at: new Date().toISOString()
70581
70809
  }
70582
70810
  };
70583
70811
  }
70584
70812
 
70585
- // src/domains/hooks/telemetry/lib/summary.ts
70586
- import { promises as fs22 } from "node:fs";
70587
- function zeroTokens3() {
70588
- return { input: 0, output: 0, cache_read: 0, cache_write: 0 };
70589
- }
70590
- function initialSummary(args) {
70591
- return {
70592
- schema_version: 1,
70593
- session_id: args.sessionId,
70594
- agent: args.agent,
70595
- cli_version: args.cliVersion ?? null,
70596
- kit_versions: args.kitVersions ?? {},
70597
- project: args.project,
70598
- timing: { started_at: args.startedAt, ended_at: null, duration_s: null },
70599
- main_loop_tokens: zeroTokens3(),
70600
- token_usage: {},
70601
- subagents: [],
70602
- skills: [],
70603
- tool_stats: {
70604
- schema_version: 1,
70605
- total_events: 0,
70606
- total_tool_calls: 0,
70607
- by_type: {},
70608
- by_name: {},
70609
- subagents: { by_type: {} },
70610
- skills: { by_name: {} }
70611
- },
70612
- totals: zeroTokens3(),
70613
- pending_user_triggers: [],
70614
- skills_in_flight: {},
70615
- transcript_offset: 0,
70616
- remote: { last_pushed_at: null, last_status: null }
70617
- };
70618
- }
70619
- async function readSummary(sessionDir) {
70620
- let raw;
70621
- try {
70622
- raw = await fs22.readFile(getSummaryFile(sessionDir), "utf8");
70623
- } catch {
70624
- return null;
70625
- }
70626
- try {
70627
- return JSON.parse(raw);
70628
- } catch {
70629
- return null;
70630
- }
70631
- }
70632
- async function writeSummary(sessionDir, summary) {
70633
- await fs22.mkdir(sessionDir, { recursive: true });
70634
- const target = getSummaryFile(sessionDir);
70635
- const tmp = `${target}.tmp`;
70636
- await fs22.writeFile(tmp, JSON.stringify(summary), "utf8");
70637
- await fs22.rename(tmp, target);
70638
- }
70639
- function isPlainObject2(value) {
70640
- return typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
70641
- }
70642
- function mergeDeep(existing, delta) {
70643
- if (delta === undefined)
70644
- return existing;
70645
- if (typeof existing === "number" && typeof delta === "number")
70646
- return existing + delta;
70647
- if (Array.isArray(existing) && Array.isArray(delta))
70648
- return [...existing, ...delta];
70649
- if (isPlainObject2(existing) && isPlainObject2(delta)) {
70650
- const out = { ...existing };
70651
- for (const key of Object.keys(delta)) {
70652
- out[key] = key in existing ? mergeDeep(existing[key], delta[key]) : delta[key];
70653
- }
70654
- return out;
70655
- }
70656
- return delta;
70657
- }
70658
- function mergeSummary(existing, delta) {
70659
- const merged = mergeDeep(existing, delta);
70660
- merged.schema_version = 1;
70661
- merged.tool_stats.schema_version = 1;
70662
- return merged;
70663
- }
70664
-
70665
70813
  // src/domains/hooks/telemetry/lib/throttle.ts
70666
- import { promises as fs23 } from "node:fs";
70814
+ import { promises as fs24 } from "node:fs";
70667
70815
  var defaultNow = () => Date.now();
70668
70816
  async function readLastPush(sessionDir) {
70669
70817
  let raw;
70670
70818
  try {
70671
- raw = await fs23.readFile(getLastPushFile(sessionDir), "utf8");
70819
+ raw = await fs24.readFile(getLastPushFile(sessionDir), "utf8");
70672
70820
  } catch {
70673
70821
  return null;
70674
70822
  }
@@ -70676,11 +70824,11 @@ async function readLastPush(sessionDir) {
70676
70824
  return Number.isFinite(parsed) ? parsed : null;
70677
70825
  }
70678
70826
  async function writeLastPush(sessionDir, ts) {
70679
- await fs23.mkdir(sessionDir, { recursive: true });
70827
+ await fs24.mkdir(sessionDir, { recursive: true });
70680
70828
  const target = getLastPushFile(sessionDir);
70681
70829
  const tmp = `${target}.tmp`;
70682
- await fs23.writeFile(tmp, String(ts), "utf8");
70683
- await fs23.rename(tmp, target);
70830
+ await fs24.writeFile(tmp, String(ts), "utf8");
70831
+ await fs24.rename(tmp, target);
70684
70832
  }
70685
70833
  async function shouldFlush(args) {
70686
70834
  const now = args.now ?? defaultNow;
@@ -70690,8 +70838,8 @@ async function shouldFlush(args) {
70690
70838
  if (now() - last >= args.intervalMs)
70691
70839
  return true;
70692
70840
  try {
70693
- const stat8 = await fs23.stat(getEventsFile(args.sessionDir));
70694
- if (stat8.size >= args.sizeBytes)
70841
+ const stat9 = await fs24.stat(getEventsFile(args.sessionDir));
70842
+ if (stat9.size >= args.sizeBytes)
70695
70843
  return true;
70696
70844
  } catch {}
70697
70845
  return false;
@@ -70737,16 +70885,21 @@ async function runSessionEndFlush(data, ctx) {
70737
70885
  return;
70738
70886
  }
70739
70887
  const endedAtIso = new Date().toISOString();
70740
- summary.timing.ended_at = endedAtIso;
70741
- summary.timing.duration_s = Math.max(0, Math.round((Date.parse(endedAtIso) - Date.parse(summary.timing.started_at)) / 1000));
70888
+ const closedSummary = await withSummaryLock(sessionDir, async () => {
70889
+ const latest = await readSummary(sessionDir) ?? summary;
70890
+ latest.timing.ended_at = endedAtIso;
70891
+ latest.timing.duration_s = Math.max(0, Math.round((Date.parse(endedAtIso) - Date.parse(latest.timing.started_at)) / 1000));
70892
+ const closed = closeBusyInterval(latest, endedAtIso);
70893
+ await writeSummary(sessionDir, closed);
70894
+ return closed;
70895
+ });
70742
70896
  const transcriptPath = typeof data.transcript_path === "string" ? data.transcript_path : (await readMeta(sessionDir))?.transcript_path ?? null;
70743
- let finalSummary = summary;
70897
+ let finalSummary = closedSummary;
70744
70898
  if (transcriptPath) {
70745
- const applied = await applyClaudeTranscriptDelta({ summary, transcriptPath });
70746
- if (applied.read)
70899
+ const applied = await applyClaudeTranscriptDelta({ sessionDir, transcriptPath });
70900
+ if (applied.read && applied.summary)
70747
70901
  finalSummary = applied.summary;
70748
70902
  }
70749
- await writeSummary(sessionDir, finalSummary);
70750
70903
  const reason = pickReason(data);
70751
70904
  const existingMeta = await readMeta(sessionDir);
70752
70905
  if (existingMeta && (reason || Object.keys(data).length > 0)) {
@@ -70755,12 +70908,12 @@ async function runSessionEndFlush(data, ctx) {
70755
70908
  ...reason ? { session_end_reason: reason } : {},
70756
70909
  session_end_raw: data
70757
70910
  };
70758
- const { promises: fs24 } = await import("node:fs");
70759
- const { join: join98 } = await import("node:path");
70760
- const target = join98(sessionDir, "meta.json");
70911
+ const { promises: fs25 } = await import("node:fs");
70912
+ const { join: join99 } = await import("node:path");
70913
+ const target = join99(sessionDir, "meta.json");
70761
70914
  const tmp = `${target}.tmp`;
70762
- await fs24.writeFile(tmp, JSON.stringify(updated), "utf8");
70763
- await fs24.rename(tmp, target);
70915
+ await fs25.writeFile(tmp, JSON.stringify(updated), "utf8");
70916
+ await fs25.rename(tmp, target);
70764
70917
  } else if (!existingMeta) {
70765
70918
  await writeMetaIfAbsent(sessionDir, {
70766
70919
  agent,
@@ -70831,7 +70984,7 @@ async function handleSessionEnd(agent, flags = {}) {
70831
70984
  init_takumi_constants();
70832
70985
 
70833
70986
  // src/domains/hooks/telemetry/lib/codex-tokens.ts
70834
- import * as fs24 from "node:fs";
70987
+ import * as fs25 from "node:fs";
70835
70988
  function n(v2) {
70836
70989
  return typeof v2 === "number" && Number.isFinite(v2) ? v2 : 0;
70837
70990
  }
@@ -70855,7 +71008,7 @@ function codexTokensOf(rec) {
70855
71008
  }
70856
71009
  function sumCodexChildTokens(jsonlPath) {
70857
71010
  const acc = { input: 0, output: 0, cache_read: 0, cache_write: 0 };
70858
- if (!jsonlPath || !fs24.existsSync(jsonlPath))
71011
+ if (!jsonlPath || !fs25.existsSync(jsonlPath))
70859
71012
  return acc;
70860
71013
  const { records } = readNew(jsonlPath, 0);
70861
71014
  for (const rec of records) {
@@ -70941,12 +71094,12 @@ async function applyCodexTranscriptDelta(args) {
70941
71094
  }
70942
71095
 
70943
71096
  // src/domains/hooks/lib/jsonl-append.ts
70944
- import { promises as fs25, appendFileSync as appendFileSync2, mkdirSync as mkdirSync4 } from "node:fs";
71097
+ import { promises as fs26, appendFileSync as appendFileSync2, mkdirSync as mkdirSync4 } from "node:fs";
70945
71098
  import { dirname as dirname27 } from "node:path";
70946
71099
  async function appendJsonl(filePath, record) {
70947
71100
  try {
70948
- await fs25.mkdir(dirname27(filePath), { recursive: true });
70949
- await fs25.appendFile(filePath, `${JSON.stringify(record)}
71101
+ await fs26.mkdir(dirname27(filePath), { recursive: true });
71102
+ await fs26.appendFile(filePath, `${JSON.stringify(record)}
70950
71103
  `, "utf8");
70951
71104
  } catch {}
70952
71105
  }
@@ -71001,10 +71154,13 @@ async function recordEvent(args) {
71001
71154
  const meta = buildMeta(args);
71002
71155
  await writeMetaIfAbsent(sessionDir, meta);
71003
71156
  const onDiskMeta = await readMeta(sessionDir) ?? meta;
71004
- const existing = await readSummary(sessionDir);
71005
- const base = existing ?? buildInitialSummary(args, onDiskMeta);
71006
- const next = args.mutate ? args.mutate(base) : base;
71007
- await writeSummary(sessionDir, next);
71157
+ const next = await withSummaryLock(sessionDir, async () => {
71158
+ const existing = await readSummary(sessionDir);
71159
+ const base = existing ?? buildInitialSummary(args, onDiskMeta);
71160
+ const mutated = args.mutate ? args.mutate(base) : base;
71161
+ await writeSummary(sessionDir, mutated);
71162
+ return mutated;
71163
+ });
71008
71164
  if (args.bufferEvent) {
71009
71165
  await appendEvent(sessionDir, args.bufferEvent);
71010
71166
  }
@@ -71084,7 +71240,7 @@ function recordStop(s, args) {
71084
71240
  merged.timing.duration_s = Math.max(0, Math.round((Date.parse(args.endedAtIso) - Date.parse(merged.timing.started_at)) / 1000));
71085
71241
  if (args.cliVersion)
71086
71242
  merged.cli_version = args.cliVersion;
71087
- return merged;
71243
+ return closeBusyInterval(merged, args.endedAtIso);
71088
71244
  }
71089
71245
  async function runStopFlush(data, ctx) {
71090
71246
  const { agent, cwd: cwd2, flags } = ctx;
@@ -71133,17 +71289,32 @@ async function runStopFlush(data, ctx) {
71133
71289
  setHookDebugLog(sessionDebugLogPath(result.sessionDir));
71134
71290
  let payloadSummary = result.summary;
71135
71291
  if (hasTranscript && transcriptPath) {
71136
- const applied = agent === "codex" ? await applyCodexTranscriptDelta({
71137
- summary: result.summary,
71138
- transcriptPath,
71139
- stdinModel
71140
- }) : await applyClaudeTranscriptDelta({
71141
- summary: result.summary,
71142
- transcriptPath
71143
- });
71144
- if (applied.read) {
71145
- payloadSummary = recomputeTotals(applied.summary);
71146
- await writeSummary(result.sessionDir, payloadSummary);
71292
+ if (agent === "codex") {
71293
+ payloadSummary = await withSummaryLock(result.sessionDir, async () => {
71294
+ const latest = await readSummary(result.sessionDir) ?? result.summary;
71295
+ const applied = await applyCodexTranscriptDelta({
71296
+ summary: latest,
71297
+ transcriptPath,
71298
+ stdinModel
71299
+ });
71300
+ const recomputed = recomputeTotals(applied.read ? applied.summary : latest);
71301
+ await writeSummary(result.sessionDir, recomputed);
71302
+ return recomputed;
71303
+ });
71304
+ } else {
71305
+ const applied = await applyClaudeTranscriptDelta({
71306
+ sessionDir: result.sessionDir,
71307
+ transcriptPath
71308
+ });
71309
+ if (applied.read && applied.summary) {
71310
+ const appliedSummary = applied.summary;
71311
+ payloadSummary = await withSummaryLock(result.sessionDir, async () => {
71312
+ const latest = await readSummary(result.sessionDir) ?? appliedSummary;
71313
+ const recomputed = recomputeTotals(latest);
71314
+ await writeSummary(result.sessionDir, recomputed);
71315
+ return recomputed;
71316
+ });
71317
+ }
71147
71318
  }
71148
71319
  }
71149
71320
  const endpoint = resolveEndpoint();
@@ -71205,11 +71376,13 @@ async function runStopFlush(data, ctx) {
71205
71376
  last_pushed_at: new Date().toISOString(),
71206
71377
  last_status: put2.status ?? null
71207
71378
  };
71208
- const refreshed = await readSummary(result.sessionDir);
71209
- if (refreshed) {
71210
- refreshed.remote = remote;
71211
- await writeSummary(result.sessionDir, refreshed);
71212
- }
71379
+ await withSummaryLock(result.sessionDir, async () => {
71380
+ const refreshed = await readSummary(result.sessionDir);
71381
+ if (refreshed) {
71382
+ refreshed.remote = remote;
71383
+ await writeSummary(result.sessionDir, refreshed);
71384
+ }
71385
+ });
71213
71386
  }
71214
71387
  } catch (e2) {
71215
71388
  hookLog("stop", { error: e2?.message ?? String(e2) });
@@ -71222,15 +71395,15 @@ async function handleStop(agent, flags = {}) {
71222
71395
 
71223
71396
  // src/domains/hooks/telemetry/otlp/observations-export.ts
71224
71397
  init_paths2();
71225
- import { promises as fs29, openSync as openSync7 } from "node:fs";
71226
- import { join as join99 } from "node:path";
71398
+ import { promises as fs30, openSync as openSync7 } from "node:fs";
71399
+ import { join as join100 } from "node:path";
71227
71400
 
71228
71401
  // src/domains/hooks/telemetry/lib/retention.ts
71229
- import { promises as fs26 } from "node:fs";
71230
- import { join as join98 } from "node:path";
71402
+ import { promises as fs27 } from "node:fs";
71403
+ import { join as join99 } from "node:path";
71231
71404
  async function pathExists24(path10) {
71232
71405
  try {
71233
- await fs26.access(path10);
71406
+ await fs27.access(path10);
71234
71407
  return true;
71235
71408
  } catch {
71236
71409
  return false;
@@ -71242,10 +71415,10 @@ async function hasUnexportedObservations(dir) {
71242
71415
  async function decideDelete(dir, args) {
71243
71416
  let mtimeMs = 0;
71244
71417
  try {
71245
- const stat8 = await fs26.stat(dir);
71246
- if (!stat8.isDirectory())
71418
+ const stat9 = await fs27.stat(dir);
71419
+ if (!stat9.isDirectory())
71247
71420
  return false;
71248
- mtimeMs = stat8.mtimeMs;
71421
+ mtimeMs = stat9.mtimeMs;
71249
71422
  } catch {
71250
71423
  return false;
71251
71424
  }
@@ -71261,8 +71434,8 @@ async function decideDelete(dir, args) {
71261
71434
  }
71262
71435
  async function listChildren(dir) {
71263
71436
  try {
71264
- const names = await fs26.readdir(dir);
71265
- return names.map((n2) => join98(dir, n2));
71437
+ const names = await fs27.readdir(dir);
71438
+ return names.map((n2) => join99(dir, n2));
71266
71439
  } catch {
71267
71440
  return [];
71268
71441
  }
@@ -71273,7 +71446,7 @@ async function collectV2Sessions() {
71273
71446
  const sessions = [];
71274
71447
  for (const projectDir of projects) {
71275
71448
  for (const agentDir of await listChildren(projectDir)) {
71276
- for (const sessionDir of await listChildren(join98(agentDir, "sessions"))) {
71449
+ for (const sessionDir of await listChildren(join99(agentDir, "sessions"))) {
71277
71450
  sessions.push(sessionDir);
71278
71451
  }
71279
71452
  }
@@ -71297,7 +71470,7 @@ async function sweepRetention(args) {
71297
71470
  continue;
71298
71471
  }
71299
71472
  try {
71300
- await fs26.rm(dir, { recursive: true, force: true });
71473
+ await fs27.rm(dir, { recursive: true, force: true });
71301
71474
  deleted.push(dir);
71302
71475
  } catch {}
71303
71476
  }
@@ -71305,10 +71478,10 @@ async function sweepRetention(args) {
71305
71478
  }
71306
71479
 
71307
71480
  // src/domains/hooks/telemetry/otlp/observations-export-state.ts
71308
- import { promises as fs27 } from "node:fs";
71481
+ import { promises as fs28 } from "node:fs";
71309
71482
  async function exists(path10) {
71310
71483
  try {
71311
- await fs27.access(path10);
71484
+ await fs28.access(path10);
71312
71485
  return true;
71313
71486
  } catch {
71314
71487
  return false;
@@ -71320,7 +71493,7 @@ async function stageObservationsForFlush(sessionDir) {
71320
71493
  return flushing;
71321
71494
  const live = getObservationsFile(sessionDir);
71322
71495
  try {
71323
- await fs27.rename(live, flushing);
71496
+ await fs28.rename(live, flushing);
71324
71497
  return flushing;
71325
71498
  } catch {
71326
71499
  return null;
@@ -71328,15 +71501,15 @@ async function stageObservationsForFlush(sessionDir) {
71328
71501
  }
71329
71502
  async function completeObservationsFlush(sessionDir, flushingPath, now) {
71330
71503
  try {
71331
- await fs27.writeFile(getObservationsPushedFile(sessionDir), String(now), "utf8");
71504
+ await fs28.writeFile(getObservationsPushedFile(sessionDir), String(now), "utf8");
71332
71505
  } catch {}
71333
71506
  try {
71334
- await fs27.rm(flushingPath, { force: true });
71507
+ await fs28.rm(flushingPath, { force: true });
71335
71508
  } catch {}
71336
71509
  }
71337
71510
  async function readObsPushed(sessionDir) {
71338
71511
  try {
71339
- const raw = await fs27.readFile(getObservationsPushedFile(sessionDir), "utf8");
71512
+ const raw = await fs28.readFile(getObservationsPushedFile(sessionDir), "utf8");
71340
71513
  const parsed = Number.parseInt(raw.trim(), 10);
71341
71514
  return Number.isFinite(parsed) ? parsed : null;
71342
71515
  } catch {
@@ -71351,7 +71524,7 @@ async function shouldFlushObservations(sessionDir, gate) {
71351
71524
  return true;
71352
71525
  let size = 0;
71353
71526
  try {
71354
- size = (await fs27.stat(getObservationsFile(sessionDir))).size;
71527
+ size = (await fs28.stat(getObservationsFile(sessionDir))).size;
71355
71528
  } catch {
71356
71529
  return false;
71357
71530
  }
@@ -71378,10 +71551,10 @@ async function resolveOtlpConfig() {
71378
71551
 
71379
71552
  // src/domains/hooks/telemetry/otlp/otlp-post.ts
71380
71553
  import { spawn as spawn3 } from "node:child_process";
71381
- import { promises as fs28, openSync as openSync6 } from "node:fs";
71554
+ import { promises as fs29, openSync as openSync6 } from "node:fs";
71382
71555
 
71383
71556
  // src/domains/hooks/telemetry/otlp/otlp-payload-builder.ts
71384
- import { createHash as createHash11 } from "node:crypto";
71557
+ import { createHash as createHash12 } from "node:crypto";
71385
71558
  var SERVICE_NAME = "tkm-hooks";
71386
71559
  var SCOPE_NAME = "takumi-cli.hooks";
71387
71560
  var MAX_RECORDS = 500;
@@ -71500,7 +71673,7 @@ function resourceAttributes(args) {
71500
71673
  }
71501
71674
  function batchKey(kept) {
71502
71675
  const sessionId = str2(kept[0]?.session_id) ?? "unknown";
71503
- const hash = createHash11("sha256").update(kept.map((r2) => JSON.stringify(r2)).join(`
71676
+ const hash = createHash12("sha256").update(kept.map((r2) => JSON.stringify(r2)).join(`
71504
71677
  `)).digest("hex").slice(0, 16);
71505
71678
  return `${sessionId}:${hash}`;
71506
71679
  }
@@ -71528,7 +71701,7 @@ function buildOtlpLogsPayload(content) {
71528
71701
  }
71529
71702
 
71530
71703
  // src/domains/hooks/telemetry/otlp/otlp-post.ts
71531
- var DEFAULT_TIMEOUT_MS3 = 5000;
71704
+ var DEFAULT_TIMEOUT_MS4 = 5000;
71532
71705
  var LOGS_PATH = "/v1/logs";
71533
71706
  var ALLOWED_HOST_SUFFIXES = [".sun-asterisk.ai"];
71534
71707
  var ALLOWED_EXACT_HOSTS = new Set(["localhost", "127.0.0.1", "::1", "[::1]"]);
@@ -71563,7 +71736,7 @@ async function runOtlpPost(job, deps = {}) {
71563
71736
  const now = deps.now ?? Date.now;
71564
71737
  let content;
71565
71738
  try {
71566
- content = await fs28.readFile(job.flushingPath, "utf8");
71739
+ content = await fs29.readFile(job.flushingPath, "utf8");
71567
71740
  } catch {
71568
71741
  return { ok: false, skipped: true, error: "no_flushing_file" };
71569
71742
  }
@@ -71583,7 +71756,7 @@ async function runOtlpPost(job, deps = {}) {
71583
71756
  headers.Authorization = `Bearer ${config.bearer}`;
71584
71757
  }
71585
71758
  const controller = new AbortController;
71586
- const timer = setTimeout(() => controller.abort(), job.timeoutMs > 0 ? job.timeoutMs : DEFAULT_TIMEOUT_MS3);
71759
+ const timer = setTimeout(() => controller.abort(), job.timeoutMs > 0 ? job.timeoutMs : DEFAULT_TIMEOUT_MS4);
71587
71760
  try {
71588
71761
  const res = await doFetch(url, {
71589
71762
  method: "POST",
@@ -71702,12 +71875,12 @@ async function exportSessionObservations(sessionDir, opts = {}, deps = {}) {
71702
71875
  }
71703
71876
  }
71704
71877
  function lockPath() {
71705
- return join99(getConfigDir(), "obs-flush.lock");
71878
+ return join100(getConfigDir(), "obs-flush.lock");
71706
71879
  }
71707
71880
  async function acquireSweepLock(now) {
71708
71881
  const path10 = lockPath();
71709
71882
  try {
71710
- await fs29.mkdir(getConfigDir(), { recursive: true });
71883
+ await fs30.mkdir(getConfigDir(), { recursive: true });
71711
71884
  } catch {
71712
71885
  return false;
71713
71886
  }
@@ -71716,9 +71889,9 @@ async function acquireSweepLock(now) {
71716
71889
  return true;
71717
71890
  } catch {
71718
71891
  try {
71719
- const stat8 = await fs29.stat(path10);
71720
- if (now - stat8.mtimeMs > STALE_LOCK_MS) {
71721
- await fs29.rm(path10, { force: true });
71892
+ const stat9 = await fs30.stat(path10);
71893
+ if (now - stat9.mtimeMs > STALE_LOCK_MS) {
71894
+ await fs30.rm(path10, { force: true });
71722
71895
  openSync7(path10, "wx");
71723
71896
  return true;
71724
71897
  }
@@ -71728,7 +71901,7 @@ async function acquireSweepLock(now) {
71728
71901
  }
71729
71902
  async function releaseSweepLock() {
71730
71903
  try {
71731
- await fs29.rm(lockPath(), { force: true });
71904
+ await fs30.rm(lockPath(), { force: true });
71732
71905
  } catch {}
71733
71906
  }
71734
71907
  async function flushOrphanObservations(deps = {}) {
@@ -71857,7 +72030,7 @@ function diffTokens(post2, base) {
71857
72030
  cache_write: Math.max(0, post2.cache_write - base.cache_write)
71858
72031
  };
71859
72032
  }
71860
- function applyMutation(s, classified, tsIso, toolUseId, description, skillTokens) {
72033
+ function applyMutation(s, classified, tsIso, toolUseId, skillTokens) {
71861
72034
  const merged = mergeSummary(s, {
71862
72035
  tool_stats: {
71863
72036
  total_events: 1,
@@ -71898,8 +72071,6 @@ function applyMutation(s, classified, tsIso, toolUseId, description, skillTokens
71898
72071
  started_at: tsIso,
71899
72072
  triggered_by: triggeredBy
71900
72073
  };
71901
- if (description)
71902
- record.description = description.slice(0, MAX_EVENT_NAME_LEN);
71903
72074
  merged.subagents.push(record);
71904
72075
  }
71905
72076
  return merged;
@@ -71925,8 +72096,6 @@ async function runPostToolUseCapture(data, ctx) {
71925
72096
  const tsIso = new Date().toISOString();
71926
72097
  const transcriptPath = typeof data.transcript_path === "string" ? data.transcript_path : null;
71927
72098
  const toolUseId = typeof data.tool_use_id === "string" ? data.tool_use_id : null;
71928
- const input = data.tool_input && typeof data.tool_input === "object" ? data.tool_input : {};
71929
- const description = typeof input.description === "string" ? input.description : null;
71930
72099
  let skillTokens = null;
71931
72100
  if (classified.kind === "skill" && agent === "claude" && transcriptPath) {
71932
72101
  const sessionDir = getSessionDirV2({ agent, cwd: cwd2, sessionId });
@@ -71934,9 +72103,8 @@ async function runPostToolUseCapture(data, ctx) {
71934
72103
  const before = await readSummary(sessionDir);
71935
72104
  const baseline = before?.skills_in_flight[classified.name]?.baseline;
71936
72105
  if (before && baseline) {
71937
- const applied = await applyClaudeTranscriptDelta({ summary: before, transcriptPath });
71938
- if (applied.read) {
71939
- await writeSummary(sessionDir, applied.summary);
72106
+ const applied = await applyClaudeTranscriptDelta({ sessionDir, transcriptPath });
72107
+ if (applied.read && applied.summary) {
71940
72108
  skillTokens = diffTokens(applied.summary.main_loop_tokens, baseline);
71941
72109
  }
71942
72110
  }
@@ -71949,7 +72117,7 @@ async function runPostToolUseCapture(data, ctx) {
71949
72117
  startedAt: tsIso,
71950
72118
  transcriptPath,
71951
72119
  bufferEvent: { event_type: classified.kind, event_name: classified.name, ts: tsIso },
71952
- mutate: (s) => applyMutation(s, classified, tsIso, toolUseId, description, skillTokens)
72120
+ mutate: (s) => applyMutation(s, classified, tsIso, toolUseId, skillTokens)
71953
72121
  });
71954
72122
  if (!result) {
71955
72123
  hookLog("post-tool-use", { agent, session_id: sessionId, skipped: "bad_session_dir" });
@@ -72289,7 +72457,7 @@ async function runUserPromptSubmitCapture(data, ctx) {
72289
72457
  by_name: { [tkmCommand]: 1 }
72290
72458
  };
72291
72459
  }
72292
- return mergeSummary(s, delta);
72460
+ return openBusyInterval(mergeSummary(s, delta), tsIso);
72293
72461
  }
72294
72462
  });
72295
72463
  if (!result) {
@@ -72346,11 +72514,11 @@ var metricsRecord = {
72346
72514
 
72347
72515
  // src/domains/hooks/handlers/session-init/handler.ts
72348
72516
  import { mkdirSync as mkdirSync5 } from "node:fs";
72349
- import { dirname as dirname28, join as join103 } from "node:path";
72517
+ import { dirname as dirname28, join as join104 } from "node:path";
72350
72518
 
72351
72519
  // src/domains/hooks/handlers/_shared/project-detector.ts
72352
72520
  import { existsSync as existsSync48, readFileSync as readFileSync15 } from "node:fs";
72353
- import { join as join100 } from "node:path";
72521
+ import { join as join101 } from "node:path";
72354
72522
  var LOCKFILE_PRIORITY = [
72355
72523
  { manager: "bun", files: ["bun.lockb", "bun.lock"] },
72356
72524
  { manager: "pnpm", files: ["pnpm-lock.yaml"] },
@@ -72385,14 +72553,14 @@ var APP_FRAMEWORKS = new Set([
72385
72553
  var WORKSPACE_MARKER_FILES = ["pnpm-workspace.yaml", "turbo.json", "lerna.json"];
72386
72554
  function fileExists(cwd2, name2) {
72387
72555
  try {
72388
- return existsSync48(join100(cwd2, name2));
72556
+ return existsSync48(join101(cwd2, name2));
72389
72557
  } catch {
72390
72558
  return false;
72391
72559
  }
72392
72560
  }
72393
72561
  function readPackageJson(cwd2) {
72394
72562
  try {
72395
- const raw = readFileSync15(join100(cwd2, "package.json"), "utf8");
72563
+ const raw = readFileSync15(join101(cwd2, "package.json"), "utf8");
72396
72564
  const parsed = JSON.parse(raw);
72397
72565
  if (parsed && typeof parsed === "object")
72398
72566
  return parsed;
@@ -72474,13 +72642,13 @@ function detectProject(cwd2) {
72474
72642
  }
72475
72643
 
72476
72644
  // src/domains/hooks/handlers/session-init/env-entries.ts
72477
- import { createHash as createHash12 } from "node:crypto";
72645
+ import { createHash as createHash13 } from "node:crypto";
72478
72646
  import { platform as platform8, userInfo } from "node:os";
72479
- import { join as join102 } from "node:path";
72647
+ import { join as join103 } from "node:path";
72480
72648
 
72481
72649
  // src/domains/hooks/handlers/session-init/plan-resolver.ts
72482
72650
  import { existsSync as existsSync49, readFileSync as readFileSync16, readdirSync as readdirSync7 } from "node:fs";
72483
- import { join as join101 } from "node:path";
72651
+ import { join as join102 } from "node:path";
72484
72652
  var MAX_PLAN_DIRS = 100;
72485
72653
  var MAX_PLAN_FILE_BYTES = 64 * 1024;
72486
72654
  function listPlanDirs(plansPath) {
@@ -72494,7 +72662,7 @@ function listPlanDirs(plansPath) {
72494
72662
  }
72495
72663
  function planFileMentionsSession(planDir, sessionId) {
72496
72664
  try {
72497
- const planFile = join101(planDir, "plan.md");
72665
+ const planFile = join102(planDir, "plan.md");
72498
72666
  if (!existsSync49(planFile))
72499
72667
  return false;
72500
72668
  const body = readFileSync16(planFile, { encoding: "utf8" });
@@ -72509,7 +72677,7 @@ function resolveActivePlan(plansPath, sessionId) {
72509
72677
  if (!sessionId)
72510
72678
  return "";
72511
72679
  for (const name2 of listPlanDirs(plansPath)) {
72512
- const dir = join101(plansPath, name2);
72680
+ const dir = join102(plansPath, name2);
72513
72681
  if (name2.includes(sessionId) || planFileMentionsSession(dir, sessionId)) {
72514
72682
  return dir;
72515
72683
  }
@@ -72530,7 +72698,7 @@ function resolveSuggestedPlan(plansPath, branch, branchPattern) {
72530
72698
  return "";
72531
72699
  for (const name2 of listPlanDirs(plansPath)) {
72532
72700
  if (name2.includes(slug))
72533
- return join101(plansPath, name2);
72701
+ return join102(plansPath, name2);
72534
72702
  }
72535
72703
  return "";
72536
72704
  }
@@ -72562,7 +72730,7 @@ function resolveTimezone() {
72562
72730
  function deriveTaskListId(sessionId) {
72563
72731
  if (!sessionId)
72564
72732
  return "";
72565
- const digest = createHash12("sha256").update(sessionId).digest("hex").slice(0, 16);
72733
+ const digest = createHash13("sha256").update(sessionId).digest("hex").slice(0, 16);
72566
72734
  return `tkm-tasks-${digest}`;
72567
72735
  }
72568
72736
  function codingLevelString(level) {
@@ -72584,11 +72752,11 @@ function buildEnvEntries(params) {
72584
72752
  const plan = config.plan ?? {};
72585
72753
  const locale = config.locale ?? {};
72586
72754
  const validation = plan.validation ?? {};
72587
- const settingsDir = join102(projectRoot, ".claude");
72588
- const docsPath = join102(projectRoot, paths.docs ?? "docs");
72589
- const plansPath = join102(projectRoot, paths.plans ?? "plans");
72755
+ const settingsDir = join103(projectRoot, ".claude");
72756
+ const docsPath = join103(projectRoot, paths.docs ?? "docs");
72757
+ const plansPath = join103(projectRoot, paths.plans ?? "plans");
72590
72758
  const reportsDir = plan.reportsDir ?? "reports";
72591
- const reportsPath = join102(plansPath, reportsDir);
72759
+ const reportsPath = join103(plansPath, reportsDir);
72592
72760
  const namingFormat = plan.namingFormat ?? "";
72593
72761
  const activePlan = resolveActivePlan(plansPath, ctx.sessionId);
72594
72762
  const suggestedPlan = resolveSuggestedPlan(plansPath, branch, plan.resolution?.branchPattern ?? "");
@@ -72669,7 +72837,7 @@ function resolveEnvFilePath(settingsDir) {
72669
72837
  const override = process.env.CLAUDE_ENV_FILE;
72670
72838
  if (override && override.trim().length > 0)
72671
72839
  return override;
72672
- return join103(settingsDir, DEFAULT_ENV_FILE);
72840
+ return join104(settingsDir, DEFAULT_ENV_FILE);
72673
72841
  }
72674
72842
  function persistEntries(envFilePath, entries) {
72675
72843
  try {
@@ -72723,10 +72891,10 @@ var sessionInit = {
72723
72891
 
72724
72892
  // src/domains/hooks/handlers/_shared/context-assembler.ts
72725
72893
  import { execFileSync as execFileSync3 } from "node:child_process";
72726
- import { createHash as createHash13 } from "node:crypto";
72894
+ import { createHash as createHash14 } from "node:crypto";
72727
72895
  import { existsSync as existsSync50, mkdirSync as mkdirSync6, readFileSync as readFileSync17, rmSync as rmSync3, statSync as statSync8, writeFileSync as writeFileSync9 } from "node:fs";
72728
72896
  import { homedir as homedir27, platform as platform9, tmpdir as tmpdir4 } from "node:os";
72729
- import { basename as basename18, join as join104, resolve as resolve21 } from "node:path";
72897
+ import { basename as basename18, join as join105, resolve as resolve21 } from "node:path";
72730
72898
  var INJECTED_TTL_MS = 12 * 60 * 60 * 1000;
72731
72899
  var RESERVATION_TTL_MS = 60 * 1000;
72732
72900
  function gitBranch(dir) {
@@ -72798,17 +72966,17 @@ function buildPromptContext(args) {
72798
72966
  }
72799
72967
  function scopeKey(baseDir) {
72800
72968
  const abs = resolve21(baseDir || ".");
72801
- const hash = createHash13("sha256").update(abs).digest("hex").slice(0, 16);
72969
+ const hash = createHash14("sha256").update(abs).digest("hex").slice(0, 16);
72802
72970
  const slug = basename18(abs).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 24) || "root";
72803
72971
  return `${slug}-${hash}`;
72804
72972
  }
72805
72973
  function stateDir() {
72806
- return join104(tmpdir4(), "takumi-context-throttle");
72974
+ return join105(tmpdir4(), "takumi-context-throttle");
72807
72975
  }
72808
72976
  function stateFile(sessionId, scope, transcriptPath) {
72809
72977
  const key = `${sessionId}\x00${scope}\x00${transcriptPath ?? ""}`;
72810
- const hash = createHash13("sha256").update(key).digest("hex").slice(0, 32);
72811
- return join104(stateDir(), `${hash}.json`);
72978
+ const hash = createHash14("sha256").update(key).digest("hex").slice(0, 32);
72979
+ return join105(stateDir(), `${hash}.json`);
72812
72980
  }
72813
72981
  function readState(file) {
72814
72982
  try {
@@ -72877,8 +73045,8 @@ function clearPending(sessionId, scope, transcriptPath) {
72877
73045
  } catch {}
72878
73046
  }
72879
73047
  function resolveSkillsVenv(_cwd) {
72880
- const base = join104(homedir27(), ".claude", "skills", ".venv");
72881
- const interpreter = platform9() === "win32" ? join104(base, "Scripts", "python.exe") : join104(base, "bin", "python3");
73048
+ const base = join105(homedir27(), ".claude", "skills", ".venv");
73049
+ const interpreter = platform9() === "win32" ? join105(base, "Scripts", "python.exe") : join105(base, "bin", "python3");
72882
73050
  return existsSync50(interpreter) ? interpreter : null;
72883
73051
  }
72884
73052
 
@@ -72917,12 +73085,12 @@ var sessionPromptContext = {
72917
73085
  };
72918
73086
 
72919
73087
  // src/domains/hooks/handlers/session-subagent-init/context-block.ts
72920
- import { join as join106 } from "node:path";
73088
+ import { join as join107 } from "node:path";
72921
73089
 
72922
73090
  // src/domains/hooks/handlers/session-subagent-init/context-sources.ts
72923
73091
  import { execFileSync as execFileSync4 } from "node:child_process";
72924
73092
  import { readdirSync as readdirSync8, statSync as statSync9 } from "node:fs";
72925
- import { isAbsolute as isAbsolute4, join as join105, resolve as resolve22 } from "node:path";
73093
+ import { isAbsolute as isAbsolute4, join as join106, resolve as resolve22 } from "node:path";
72926
73094
  var MAX_DOCS_FILES = 15;
72927
73095
  var MAX_DOCS_SUBDIRS = 5;
72928
73096
  function gitFacts(dir) {
@@ -72959,11 +73127,11 @@ function detectPlan(plansAbs) {
72959
73127
  for (const e2 of entries) {
72960
73128
  if (!e2.isDirectory())
72961
73129
  continue;
72962
- const dir = join105(plansAbs, e2.name);
73130
+ const dir = join106(plansAbs, e2.name);
72963
73131
  try {
72964
73132
  if (!readdirSync8(dir).includes("plan.md"))
72965
73133
  continue;
72966
- const mtime = statSync9(join105(dir, "plan.md")).mtimeMs;
73134
+ const mtime = statSync9(join106(dir, "plan.md")).mtimeMs;
72967
73135
  if (!best || mtime > best.mtime)
72968
73136
  best = { name: e2.name, mtime };
72969
73137
  } catch {}
@@ -72986,7 +73154,7 @@ function docsCatalogue(docsAbs) {
72986
73154
  for (const d3 of subdirs.slice(0, MAX_DOCS_SUBDIRS)) {
72987
73155
  let count = 0;
72988
73156
  try {
72989
- count = readdirSync8(join105(docsAbs, d3)).length;
73157
+ count = readdirSync8(join106(docsAbs, d3)).length;
72990
73158
  } catch {}
72991
73159
  lines.push(`- ${d3}/ (${count} entries)`);
72992
73160
  }
@@ -73030,11 +73198,11 @@ function buildSubagentContext(input, ctx) {
73030
73198
  const agentId = strField(input, "agent_id") || "unknown";
73031
73199
  const plansAbs = abs(base, cfg.paths?.plans?.trim() || "plans");
73032
73200
  const docsAbs = abs(base, cfg.paths?.docs?.trim() || "docs");
73033
- const reportsAbs = join106(plansAbs, cfg.plan?.reportsDir?.trim() || "reports");
73201
+ const reportsAbs = join107(plansAbs, cfg.plan?.reportsDir?.trim() || "reports");
73034
73202
  const dateStr = stamp(cfg.plan?.dateFormat?.trim() || "YYMMDD-HHmm", new Date);
73035
73203
  const namingFormat = cfg.plan?.namingFormat?.trim() || "{date}-{slug}";
73036
- const planDir = join106(plansAbs, planDirTemplate(namingFormat, dateStr));
73037
- const reportFile = join106(reportsAbs, `${agentKey}-${dateStr}-{slug}-report.md`);
73204
+ const planDir = join107(plansAbs, planDirTemplate(namingFormat, dateStr));
73205
+ const reportFile = join107(reportsAbs, `${agentKey}-${dateStr}-{slug}-report.md`);
73038
73206
  const activePlan = detectPlan(plansAbs);
73039
73207
  const venv = resolveSkillsVenv(effectiveCwd);
73040
73208
  const respLang = cfg.locale?.responseLanguage?.trim() || null;
@@ -73496,7 +73664,7 @@ function buildObservation(args) {
73496
73664
  }
73497
73665
 
73498
73666
  // src/commands/hooks/lib/hook-exec-dispatch.ts
73499
- var DEFAULT_TIMEOUT_MS4 = 2000;
73667
+ var DEFAULT_TIMEOUT_MS5 = 2000;
73500
73668
  var RECORD_TIMEOUT_MS = 1e4;
73501
73669
  async function defaultLoadConfig(cwd2) {
73502
73670
  try {
@@ -73560,7 +73728,7 @@ async function runHookExec(args, deps = {}) {
73560
73728
  };
73561
73729
  const sessionDir = sessionId ? getSessionDirV2({ agent: args.agent, cwd: cwd2, sessionId }) : null;
73562
73730
  const result = await runHooks(handlers3, input, ctx, {
73563
- timeoutMs: args.timeoutMs ?? DEFAULT_TIMEOUT_MS4,
73731
+ timeoutMs: args.timeoutMs ?? DEFAULT_TIMEOUT_MS5,
73564
73732
  timeoutMsByPolicy: { record: args.recordTimeoutMs ?? RECORD_TIMEOUT_MS },
73565
73733
  onHandlerComplete: (handlerName, handlerResult) => {
73566
73734
  if (!sessionDir)
@@ -73602,7 +73770,7 @@ async function hookExecCommand(options2) {
73602
73770
  init_logger();
73603
73771
 
73604
73772
  // src/commands/hooks/event-handlers/_do-put.ts
73605
- var DEFAULT_TIMEOUT_MS5 = 5000;
73773
+ var DEFAULT_TIMEOUT_MS6 = 5000;
73606
73774
  async function handleDoPut() {
73607
73775
  let job = null;
73608
73776
  try {
@@ -73617,7 +73785,7 @@ async function handleDoPut() {
73617
73785
  const result = await authedFetch(job.url, {
73618
73786
  method: "PUT",
73619
73787
  body: job.payload,
73620
- timeoutMs: job.timeoutMs > 0 ? job.timeoutMs : DEFAULT_TIMEOUT_MS5
73788
+ timeoutMs: job.timeoutMs > 0 ? job.timeoutMs : DEFAULT_TIMEOUT_MS6
73621
73789
  });
73622
73790
  hookLog("stop_detached", {
73623
73791
  ok: result.ok,
@@ -74935,21 +75103,21 @@ import { existsSync as existsSync52 } from "node:fs";
74935
75103
  // src/commands/hooks/lib/settings-path-resolver.ts
74936
75104
  import { lstatSync as lstatSync3, realpathSync as realpathSync3 } from "node:fs";
74937
75105
  import { homedir as homedir28 } from "node:os";
74938
- import { join as join107 } from "node:path";
75106
+ import { join as join108 } from "node:path";
74939
75107
  function rawPath(agent, global3) {
74940
75108
  const root = global3 ? homedir28() : process.cwd();
74941
75109
  if (agent === "claude") {
74942
- return join107(root, ".claude", "settings.json");
75110
+ return join108(root, ".claude", "settings.json");
74943
75111
  }
74944
- return join107(root, ".codex", "hooks.json");
75112
+ return join108(root, ".codex", "hooks.json");
74945
75113
  }
74946
75114
  function resolveSettingsPath(agent, options2 = {}) {
74947
75115
  const originalPath = rawPath(agent, Boolean(options2.global));
74948
75116
  let wasSymlink = false;
74949
75117
  let realPath = originalPath;
74950
75118
  try {
74951
- const stat8 = lstatSync3(originalPath);
74952
- if (stat8.isSymbolicLink()) {
75119
+ const stat9 = lstatSync3(originalPath);
75120
+ if (stat9.isSymbolicLink()) {
74953
75121
  wasSymlink = true;
74954
75122
  realPath = realpathSync3(originalPath);
74955
75123
  }
@@ -76642,7 +76810,7 @@ init_logger();
76642
76810
  init_takumi_constants();
76643
76811
  var import_fs_extra31 = __toESM(require_lib(), 1);
76644
76812
  var import_semver5 = __toESM(require_semver2(), 1);
76645
- import { join as join108 } from "node:path";
76813
+ import { join as join109 } from "node:path";
76646
76814
  function evaluateCliVersionGate(input) {
76647
76815
  const min = typeof input.minCliVersion === "string" ? input.minCliVersion.trim() : undefined;
76648
76816
  if (!min)
@@ -76663,7 +76831,7 @@ function evaluateCliVersionGate(input) {
76663
76831
  }
76664
76832
  async function readKitMinCliVersion(extractDir) {
76665
76833
  try {
76666
- const resolved = await findManifestPath(join108(extractDir, ".claude"));
76834
+ const resolved = await findManifestPath(join109(extractDir, ".claude"));
76667
76835
  if (!resolved)
76668
76836
  return;
76669
76837
  const raw = await import_fs_extra31.readFile(resolved.path, "utf-8");
@@ -76773,7 +76941,7 @@ async function dispatchInstallers(ctx, targetAgents2, lifecycle) {
76773
76941
  init_logger();
76774
76942
  // src/domains/installation/download-extractor.ts
76775
76943
  init_auth_client();
76776
- import * as fs31 from "node:fs";
76944
+ import * as fs32 from "node:fs";
76777
76945
  import * as path10 from "node:path";
76778
76946
 
76779
76947
  // src/domains/github/auth-prompt.ts
@@ -76853,9 +77021,9 @@ init_github_client();
76853
77021
  init_environment();
76854
77022
  init_logger();
76855
77023
  init_safe_spinner();
76856
- import { mkdir as mkdir25, stat as stat10 } from "node:fs/promises";
77024
+ import { mkdir as mkdir25, stat as stat11 } from "node:fs/promises";
76857
77025
  import { tmpdir as tmpdir5 } from "node:os";
76858
- import { join as join114 } from "node:path";
77026
+ import { join as join115 } from "node:path";
76859
77027
 
76860
77028
  // src/shared/temp-cleanup.ts
76861
77029
  init_logger();
@@ -76874,7 +77042,7 @@ init_logger();
76874
77042
  init_output_manager();
76875
77043
  import { createWriteStream as createWriteStream2, rmSync as rmSync6 } from "node:fs";
76876
77044
  import { mkdir as mkdir21 } from "node:fs/promises";
76877
- import { join as join109 } from "node:path";
77045
+ import { join as join110 } from "node:path";
76878
77046
 
76879
77047
  // src/shared/progress-bar.ts
76880
77048
  init_output_manager();
@@ -77044,8 +77212,8 @@ var MAX_EXTRACTION_SIZE = 500 * 1024 * 1024;
77044
77212
  function isPathSafe(basePath, targetPath) {
77045
77213
  const resolvedBase = resolve23(basePath);
77046
77214
  try {
77047
- const stat8 = lstatSync4(targetPath);
77048
- if (stat8.isSymbolicLink()) {
77215
+ const stat9 = lstatSync4(targetPath);
77216
+ if (stat9.isSymbolicLink()) {
77049
77217
  const realTarget = realpathSync4(targetPath);
77050
77218
  if (!realTarget.startsWith(resolvedBase)) {
77051
77219
  return false;
@@ -77084,7 +77252,7 @@ var MAX_DOWNLOAD_SIZE = 500 * 1024 * 1024;
77084
77252
  class FileDownloader {
77085
77253
  async downloadAsset(asset, destDir) {
77086
77254
  try {
77087
- const destPath = join109(destDir, asset.name);
77255
+ const destPath = join110(destDir, asset.name);
77088
77256
  await mkdir21(destDir, { recursive: true });
77089
77257
  output.info(`Downloading ${asset.name} (${formatBytes(asset.size)})...`);
77090
77258
  logger.verbose("Download details", {
@@ -77169,7 +77337,7 @@ class FileDownloader {
77169
77337
  }
77170
77338
  async downloadFile(params) {
77171
77339
  const { url, name: name2, size, destDir, token } = params;
77172
- const destPath = join109(destDir, name2);
77340
+ const destPath = join110(destDir, name2);
77173
77341
  await mkdir21(destDir, { recursive: true });
77174
77342
  output.info(`Downloading ${name2}${size ? ` (${formatBytes(size)})` : ""}...`);
77175
77343
  const headers = {};
@@ -77272,7 +77440,7 @@ init_logger();
77272
77440
  init_types2();
77273
77441
  import { constants as constants3 } from "node:fs";
77274
77442
  import { access as access3, readdir as readdir25 } from "node:fs/promises";
77275
- import { join as join110 } from "node:path";
77443
+ import { join as join111 } from "node:path";
77276
77444
  async function validateExtraction(extractDir) {
77277
77445
  try {
77278
77446
  const entries = await readdir25(extractDir, { encoding: "utf8" });
@@ -77284,7 +77452,7 @@ async function validateExtraction(extractDir) {
77284
77452
  const missingPaths = [];
77285
77453
  for (const path10 of criticalPaths) {
77286
77454
  try {
77287
- await access3(join110(extractDir, path10), constants3.F_OK);
77455
+ await access3(join111(extractDir, path10), constants3.F_OK);
77288
77456
  logger.debug(`Found: ${path10}`);
77289
77457
  } catch {
77290
77458
  logger.warning(`Expected path not found: ${path10}`);
@@ -77305,8 +77473,8 @@ async function validateExtraction(extractDir) {
77305
77473
 
77306
77474
  // src/domains/installation/extraction/tar-extractor.ts
77307
77475
  init_logger();
77308
- import { copyFile as copyFile5, mkdir as mkdir23, readdir as readdir27, rm as rm7, stat as stat8 } from "node:fs/promises";
77309
- import { join as join112 } from "node:path";
77476
+ import { copyFile as copyFile5, mkdir as mkdir23, readdir as readdir27, rm as rm7, stat as stat9 } from "node:fs/promises";
77477
+ import { join as join113 } from "node:path";
77310
77478
 
77311
77479
  // node_modules/tar/dist/esm/index.min.js
77312
77480
  import Kr from "events";
@@ -79578,7 +79746,7 @@ var Vn = 512 * 1024;
79578
79746
  var $n = pr | ur | dr | mr;
79579
79747
  var lr = !fr && typeof ar == "number" ? ar | ur | dr | mr : null;
79580
79748
  var cs = lr !== null ? () => lr : Kn ? (s3) => s3 < Vn ? $n : "w" : () => "w";
79581
- var fs30 = (s3, t, e2) => {
79749
+ var fs31 = (s3, t, e2) => {
79582
79750
  try {
79583
79751
  return mi.lchownSync(s3, t, e2);
79584
79752
  } catch (i) {
@@ -79627,7 +79795,7 @@ var ds = (s3, t, e2, i) => {
79627
79795
  });
79628
79796
  };
79629
79797
  var qn = (s3, t, e2, i) => {
79630
- t.isDirectory() && us(Ee.resolve(s3, t.name), e2, i), fs30(Ee.resolve(s3, t.name), e2, i);
79798
+ t.isDirectory() && us(Ee.resolve(s3, t.name), e2, i), fs31(Ee.resolve(s3, t.name), e2, i);
79631
79799
  };
79632
79800
  var us = (s3, t, e2) => {
79633
79801
  let i;
@@ -79638,12 +79806,12 @@ var us = (s3, t, e2) => {
79638
79806
  if (n2?.code === "ENOENT")
79639
79807
  return;
79640
79808
  if (n2?.code === "ENOTDIR" || n2?.code === "ENOTSUP")
79641
- return fs30(s3, t, e2);
79809
+ return fs31(s3, t, e2);
79642
79810
  throw n2;
79643
79811
  }
79644
79812
  for (let r2 of i)
79645
79813
  qn(s3, r2, t, e2);
79646
- return fs30(s3, t, e2);
79814
+ return fs31(s3, t, e2);
79647
79815
  };
79648
79816
  var we = class extends Error {
79649
79817
  path;
@@ -80519,7 +80687,7 @@ function decodeFilePath(path10) {
80519
80687
  init_logger();
80520
80688
  init_types2();
80521
80689
  import { copyFile as copyFile4, lstat as lstat6, mkdir as mkdir22, readdir as readdir26 } from "node:fs/promises";
80522
- import { join as join111, relative as relative16 } from "node:path";
80690
+ import { join as join112, relative as relative16 } from "node:path";
80523
80691
  async function withRetry2(fn2, retries = 3) {
80524
80692
  for (let i = 0;i < retries; i++) {
80525
80693
  try {
@@ -80541,8 +80709,8 @@ async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTrac
80541
80709
  await mkdir22(destDir, { recursive: true });
80542
80710
  const entries = await readdir26(sourceDir, { encoding: "utf8" });
80543
80711
  for (const entry of entries) {
80544
- const sourcePath = join111(sourceDir, entry);
80545
- const destPath = join111(destDir, entry);
80712
+ const sourcePath = join112(sourceDir, entry);
80713
+ const destPath = join112(destDir, entry);
80546
80714
  const relativePath = relative16(sourceDir, sourcePath);
80547
80715
  if (!isPathSafe(destDir, destPath)) {
80548
80716
  logger.warning(`Skipping unsafe path: ${relativePath}`);
@@ -80569,8 +80737,8 @@ async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
80569
80737
  await mkdir22(destDir, { recursive: true });
80570
80738
  const entries = await readdir26(sourceDir, { encoding: "utf8" });
80571
80739
  for (const entry of entries) {
80572
- const sourcePath = join111(sourceDir, entry);
80573
- const destPath = join111(destDir, entry);
80740
+ const sourcePath = join112(sourceDir, entry);
80741
+ const destPath = join112(destDir, entry);
80574
80742
  const relativePath = relative16(sourceDir, sourcePath);
80575
80743
  if (!isPathSafe(destDir, destPath)) {
80576
80744
  logger.warning(`Skipping unsafe path: ${relativePath}`);
@@ -80625,8 +80793,8 @@ class TarExtractor {
80625
80793
  logger.debug(`Root entries: ${entries.join(", ")}`);
80626
80794
  if (entries.length === 1) {
80627
80795
  const rootEntry = entries[0];
80628
- const rootPath = join112(tempExtractDir, rootEntry);
80629
- const rootStat = await stat8(rootPath);
80796
+ const rootPath = join113(tempExtractDir, rootEntry);
80797
+ const rootStat = await stat9(rootPath);
80630
80798
  if (rootStat.isDirectory()) {
80631
80799
  const rootContents = await readdir27(rootPath, { encoding: "utf8" });
80632
80800
  logger.debug(`Root directory '${rootEntry}' contains: ${rootContents.join(", ")}`);
@@ -80641,7 +80809,7 @@ class TarExtractor {
80641
80809
  }
80642
80810
  } else {
80643
80811
  await mkdir23(destDir, { recursive: true });
80644
- await copyFile5(rootPath, join112(destDir, rootEntry));
80812
+ await copyFile5(rootPath, join113(destDir, rootEntry));
80645
80813
  }
80646
80814
  } else {
80647
80815
  logger.debug("Multiple root entries - moving all");
@@ -80661,8 +80829,8 @@ class TarExtractor {
80661
80829
  // src/domains/installation/extraction/zip-extractor.ts
80662
80830
  init_logger();
80663
80831
  import { createWriteStream as createWriteStream3 } from "node:fs";
80664
- import { chmod as chmod3, copyFile as copyFile6, mkdir as mkdir24, readdir as readdir28, rm as rm8, stat as stat9 } from "node:fs/promises";
80665
- import { dirname as dirname31, join as join113, resolve as resolve24 } from "node:path";
80832
+ import { chmod as chmod3, copyFile as copyFile6, mkdir as mkdir24, readdir as readdir28, rm as rm8, stat as stat10 } from "node:fs/promises";
80833
+ import { dirname as dirname31, join as join114, resolve as resolve24 } from "node:path";
80666
80834
  import { pipeline } from "node:stream/promises";
80667
80835
  import yauzl from "yauzl-promise";
80668
80836
  class ZipExtractor {
@@ -80676,8 +80844,8 @@ class ZipExtractor {
80676
80844
  logger.debug(`Root entries: ${entries.join(", ")}`);
80677
80845
  if (entries.length === 1) {
80678
80846
  const rootEntry = entries[0];
80679
- const rootPath = join113(tempExtractDir, rootEntry);
80680
- const rootStat = await stat9(rootPath);
80847
+ const rootPath = join114(tempExtractDir, rootEntry);
80848
+ const rootStat = await stat10(rootPath);
80681
80849
  if (rootStat.isDirectory()) {
80682
80850
  const rootContents = await readdir28(rootPath, { encoding: "utf8" });
80683
80851
  logger.debug(`Root directory '${rootEntry}' contains: ${rootContents.join(", ")}`);
@@ -80692,7 +80860,7 @@ class ZipExtractor {
80692
80860
  }
80693
80861
  } else {
80694
80862
  await mkdir24(destDir, { recursive: true });
80695
- await copyFile6(rootPath, join113(destDir, rootEntry));
80863
+ await copyFile6(rootPath, join114(destDir, rootEntry));
80696
80864
  }
80697
80865
  } else {
80698
80866
  logger.debug("Multiple root entries - moving all");
@@ -80782,7 +80950,7 @@ class DownloadManager {
80782
80950
  return this.fileDownloader.downloadFile(params);
80783
80951
  }
80784
80952
  async extractArchive(archivePath, destDir, archiveType) {
80785
- const archiveStats = await stat10(archivePath);
80953
+ const archiveStats = await stat11(archivePath);
80786
80954
  if (archiveStats.size > MAX_ARCHIVE_SIZE) {
80787
80955
  throw new ExtractionError(`Archive exceeds ${formatBytes(MAX_ARCHIVE_SIZE)} limit: ${formatBytes(archiveStats.size)}`);
80788
80956
  }
@@ -80821,7 +80989,7 @@ class DownloadManager {
80821
80989
  async createTempDir() {
80822
80990
  const timestamp = Date.now();
80823
80991
  const counter = DownloadManager.tempDirCounter++;
80824
- const primaryTempDir = join114(tmpdir5(), `takumi-${timestamp}-${counter}`);
80992
+ const primaryTempDir = join115(tmpdir5(), `takumi-${timestamp}-${counter}`);
80825
80993
  try {
80826
80994
  await mkdir25(primaryTempDir, { recursive: true });
80827
80995
  logger.debug(`Created temp directory: ${primaryTempDir}`);
@@ -80838,7 +81006,7 @@ Solutions:
80838
81006
  2. Set HOME environment variable
80839
81007
  3. Try running from a different directory`);
80840
81008
  }
80841
- const fallbackTempDir = join114(homeDir, ".sunagentkit", "tmp", `takumi-${timestamp}-${counter}`);
81009
+ const fallbackTempDir = join115(homeDir, ".sunagentkit", "tmp", `takumi-${timestamp}-${counter}`);
80842
81010
  try {
80843
81011
  await mkdir25(fallbackTempDir, { recursive: true });
80844
81012
  logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
@@ -80883,8 +81051,8 @@ function buildReleaseAllowlist(layout) {
80883
81051
  async function ensureLayoutSourceDir(projectRoot, layout, strict) {
80884
81052
  const sourceDir = path10.join(projectRoot, layout.sourceDir);
80885
81053
  try {
80886
- const stat11 = await fs31.promises.stat(sourceDir);
80887
- if (!stat11.isDirectory()) {
81054
+ const stat12 = await fs32.promises.stat(sourceDir);
81055
+ if (!stat12.isDirectory()) {
80888
81056
  throw new Error(`Expected source directory "${layout.sourceDir}" exists but is not a directory.`);
80889
81057
  }
80890
81058
  return sourceDir;
@@ -80908,8 +81076,8 @@ async function materializeRuntimeLayoutInPlace(projectRoot, layout) {
80908
81076
  }
80909
81077
  const sourceDir = path10.join(projectRoot, layout.sourceDir);
80910
81078
  const runtimeDir = path10.join(projectRoot, layout.runtimeDir);
80911
- await fs31.promises.rm(runtimeDir, { recursive: true, force: true });
80912
- await fs31.promises.rename(sourceDir, runtimeDir);
81079
+ await fs32.promises.rm(runtimeDir, { recursive: true, force: true });
81080
+ await fs32.promises.rename(sourceDir, runtimeDir);
80913
81081
  }
80914
81082
  async function stageLocalKitPathForRuntimeLayout(kitRoot, layout) {
80915
81083
  const sourceDir = await ensureLayoutSourceDir(kitRoot, layout, false);
@@ -80919,20 +81087,20 @@ async function stageLocalKitPathForRuntimeLayout(kitRoot, layout) {
80919
81087
  const downloadManager = new DownloadManager;
80920
81088
  const tempDir = await downloadManager.createTempDir();
80921
81089
  const extractDir = `${tempDir}/extracted`;
80922
- await fs31.promises.mkdir(extractDir, { recursive: true });
80923
- const entries = await fs31.promises.readdir(kitRoot);
81090
+ await fs32.promises.mkdir(extractDir, { recursive: true });
81091
+ const entries = await fs32.promises.readdir(kitRoot);
80924
81092
  const allowlist = buildReleaseAllowlist(layout);
80925
81093
  for (const entry of entries) {
80926
81094
  if (!allowlist.includes(entry) || entry === layout.sourceDir) {
80927
81095
  continue;
80928
81096
  }
80929
- await fs31.promises.cp(path10.join(kitRoot, entry), path10.join(extractDir, entry), {
81097
+ await fs32.promises.cp(path10.join(kitRoot, entry), path10.join(extractDir, entry), {
80930
81098
  recursive: true
80931
81099
  });
80932
81100
  }
80933
81101
  const runtimeDir = path10.join(extractDir, layout.runtimeDir);
80934
- await fs31.promises.mkdir(path10.dirname(runtimeDir), { recursive: true });
80935
- await fs31.promises.cp(sourceDir, runtimeDir, { recursive: true });
81102
+ await fs32.promises.mkdir(path10.dirname(runtimeDir), { recursive: true });
81103
+ await fs32.promises.cp(sourceDir, runtimeDir, { recursive: true });
80936
81104
  logger.verbose("Staged local kit path with runtime layout", {
80937
81105
  kitRoot,
80938
81106
  extractDir,
@@ -80961,9 +81129,9 @@ function resolveRepoRootForKit(kitRoot) {
80961
81129
  try {
80962
81130
  const parent = path10.dirname(kitRoot);
80963
81131
  const parentPackageJson = path10.join(parent, "package.json");
80964
- if (!fs31.existsSync(parentPackageJson))
81132
+ if (!fs32.existsSync(parentPackageJson))
80965
81133
  return kitRoot;
80966
- const pkg = JSON.parse(fs31.readFileSync(parentPackageJson, "utf-8"));
81134
+ const pkg = JSON.parse(fs32.readFileSync(parentPackageJson, "utf-8"));
80967
81135
  const kitCfg = pkg.takumi;
80968
81136
  const sourceDir = kitCfg?.sourceDir;
80969
81137
  if (typeof sourceDir === "string" && path10.resolve(parent, sourceDir) === path10.resolve(kitRoot)) {
@@ -80977,9 +81145,9 @@ async function stageMonorepoForInstallation(kitRoot) {
80977
81145
  const tempDir = await downloadManager.createTempDir();
80978
81146
  const extractDir = `${tempDir}/extracted`;
80979
81147
  const claudeDir = path10.join(extractDir, ".claude");
80980
- await fs31.promises.mkdir(claudeDir, { recursive: true });
81148
+ await fs32.promises.mkdir(claudeDir, { recursive: true });
80981
81149
  const repoRoot = resolveRepoRootForKit(kitRoot);
80982
- const kitEntries = await fs31.promises.readdir(kitRoot);
81150
+ const kitEntries = await fs32.promises.readdir(kitRoot);
80983
81151
  const skipLegacyManifest = kitEntries.includes(MANIFEST_FILENAME) && kitEntries.includes(LEGACY_MANIFEST_FILENAME);
80984
81152
  for (const entry of kitEntries) {
80985
81153
  if (!MONOREPO_KIT_CONTENT.includes(entry))
@@ -80987,14 +81155,14 @@ async function stageMonorepoForInstallation(kitRoot) {
80987
81155
  if (skipLegacyManifest && entry === LEGACY_MANIFEST_FILENAME)
80988
81156
  continue;
80989
81157
  const srcPath = path10.join(kitRoot, entry);
80990
- await fs31.promises.cp(srcPath, path10.join(claudeDir, entry), { recursive: true });
81158
+ await fs32.promises.cp(srcPath, path10.join(claudeDir, entry), { recursive: true });
80991
81159
  }
80992
- const repoEntries = repoRoot === kitRoot ? kitEntries : await fs31.promises.readdir(repoRoot);
81160
+ const repoEntries = repoRoot === kitRoot ? kitEntries : await fs32.promises.readdir(repoRoot);
80993
81161
  for (const entry of repoEntries) {
80994
81162
  if (!RELEASE_ROOT_ALLOWLIST.includes(entry))
80995
81163
  continue;
80996
81164
  const srcPath = path10.join(repoRoot, entry);
80997
- await fs31.promises.cp(srcPath, path10.join(extractDir, entry), { recursive: true });
81165
+ await fs32.promises.cp(srcPath, path10.join(extractDir, entry), { recursive: true });
80998
81166
  }
80999
81167
  logger.verbose("Staged monorepo for installation", {
81000
81168
  kitRoot,
@@ -81008,13 +81176,13 @@ async function stageMonorepoForInstallation(kitRoot) {
81008
81176
  async function normalizeFullRepoExtract(dir, strict) {
81009
81177
  const layout = resolveKitLayout(dir);
81010
81178
  await ensureLayoutSourceDir(dir, layout, strict);
81011
- const entries = await fs31.promises.readdir(dir);
81179
+ const entries = await fs32.promises.readdir(dir);
81012
81180
  const releaseAllowlist = buildReleaseAllowlist(layout);
81013
81181
  let removedCount = 0;
81014
81182
  for (const entry of entries) {
81015
81183
  if (!releaseAllowlist.includes(entry)) {
81016
81184
  const fullPath = path10.join(dir, entry);
81017
- await fs31.promises.rm(fullPath, { recursive: true, force: true });
81185
+ await fs32.promises.rm(fullPath, { recursive: true, force: true });
81018
81186
  removedCount++;
81019
81187
  }
81020
81188
  }
@@ -81129,8 +81297,8 @@ async function useLocalKitPath(kitPath, isMonorepo) {
81129
81297
  output.section("Using local kit");
81130
81298
  const absolutePath = path10.resolve(kitPath);
81131
81299
  try {
81132
- const stat11 = await fs31.promises.stat(absolutePath);
81133
- if (!stat11.isDirectory()) {
81300
+ const stat12 = await fs32.promises.stat(absolutePath);
81301
+ if (!stat12.isDirectory()) {
81134
81302
  throw new Error(`--kit-path must point to a directory, not a file.
81135
81303
 
81136
81304
  Provided path: ${absolutePath}
@@ -81168,8 +81336,8 @@ Please verify the path exists and is accessible.`);
81168
81336
  }
81169
81337
  const claudeDir = path10.join(absolutePath, DEFAULT_KIT_LAYOUT.runtimeDir);
81170
81338
  try {
81171
- const stat11 = await fs31.promises.stat(claudeDir);
81172
- if (!stat11.isDirectory()) {
81339
+ const stat12 = await fs32.promises.stat(claudeDir);
81340
+ if (!stat12.isDirectory()) {
81173
81341
  logger.warning(`Warning: ${claudeDir} exists but is not a directory.
81174
81342
  This may not be a valid Takumi installation.`);
81175
81343
  }
@@ -81203,15 +81371,15 @@ async function extractLocalArchive(archivePath, exclude) {
81203
81371
  const absolutePath = path10.resolve(archivePath);
81204
81372
  validateArchiveFormat(absolutePath);
81205
81373
  try {
81206
- const stat11 = await fs31.promises.stat(absolutePath);
81207
- if (!stat11.isFile()) {
81374
+ const stat12 = await fs32.promises.stat(absolutePath);
81375
+ if (!stat12.isFile()) {
81208
81376
  throw new Error(`--archive must point to a file, not a directory.
81209
81377
 
81210
81378
  Provided path: ${absolutePath}
81211
81379
 
81212
81380
  If you meant to use an extracted kit directory, use --kit-path instead.`);
81213
81381
  }
81214
- if (stat11.size === 0) {
81382
+ if (stat12.size === 0) {
81215
81383
  throw new Error(`Archive file is empty: ${absolutePath}
81216
81384
 
81217
81385
  The file exists but contains no data. Please verify the archive is not corrupted.`);
@@ -81336,7 +81504,7 @@ async function downloadViaWorker(release, kit, isNonInteractive2) {
81336
81504
  const tempDir = await downloadManager.createTempDir();
81337
81505
  const archivePath = path10.join(tempDir, assetName);
81338
81506
  const buf = Buffer.from(await res.arrayBuffer());
81339
- await fs31.promises.writeFile(archivePath, buf);
81507
+ await fs32.promises.writeFile(archivePath, buf);
81340
81508
  const extractDir = `${tempDir}/extracted`;
81341
81509
  logger.verbose("Extraction", { archivePath, extractDir });
81342
81510
  await downloadManager.extractArchive(archivePath, extractDir);
@@ -81545,7 +81713,7 @@ Re-run with explicit base kit, e.g. --kit ${BASE_KIT} --kit ${parsed2.join(" --k
81545
81713
  }
81546
81714
  // src/commands/init/phases/selection-handler.ts
81547
81715
  import { mkdir as mkdir26 } from "node:fs/promises";
81548
- import { join as join118, resolve as resolve28 } from "node:path";
81716
+ import { join as join119, resolve as resolve28 } from "node:path";
81549
81717
 
81550
81718
  // src/commands/shared/agent-selector.ts
81551
81719
  init_registry();
@@ -81699,7 +81867,7 @@ init_safe_spinner();
81699
81867
  init_takumi_constants();
81700
81868
  var import_fs_extra32 = __toESM(require_lib(), 1);
81701
81869
  import { existsSync as existsSync57, readdirSync as readdirSync9, rmSync as rmSync7, rmdirSync as rmdirSync2, unlinkSync as unlinkSync6 } from "node:fs";
81702
- import { dirname as dirname34, join as join117, resolve as resolve27 } from "node:path";
81870
+ import { dirname as dirname34, join as join118, resolve as resolve27 } from "node:path";
81703
81871
  var TAKUMI_SUBDIRECTORIES = ["commands", "agents", "skills", "rules", "hooks"];
81704
81872
  async function analyzeFreshInstallation(claudeDir) {
81705
81873
  const metadata = await readManifest(claudeDir);
@@ -81769,7 +81937,7 @@ async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
81769
81937
  const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
81770
81938
  const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
81771
81939
  for (const file of filesToRemove) {
81772
- const fullPath = join117(claudeDir, file.path);
81940
+ const fullPath = join118(claudeDir, file.path);
81773
81941
  try {
81774
81942
  if (existsSync57(fullPath)) {
81775
81943
  unlinkSync6(fullPath);
@@ -81843,7 +82011,7 @@ async function removeSubdirectoriesFallback(claudeDir) {
81843
82011
  const removedFiles = [];
81844
82012
  let removedDirCount = 0;
81845
82013
  for (const subdir of TAKUMI_SUBDIRECTORIES) {
81846
- const subdirPath = join117(claudeDir, subdir);
82014
+ const subdirPath = join118(claudeDir, subdir);
81847
82015
  if (await import_fs_extra32.pathExists(subdirPath)) {
81848
82016
  rmSync7(subdirPath, { recursive: true, force: true });
81849
82017
  removedDirCount++;
@@ -82068,7 +82236,7 @@ async function handleSelection(ctx) {
82068
82236
  }
82069
82237
  if (!ctx.options.fresh) {
82070
82238
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
82071
- const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
82239
+ const claudeDir = prefix ? join119(resolvedDir, prefix) : resolvedDir;
82072
82240
  try {
82073
82241
  const existingMetadata = await readManifest(claudeDir);
82074
82242
  if (existingMetadata?.kits) {
@@ -82101,7 +82269,7 @@ async function handleSelection(ctx) {
82101
82269
  }
82102
82270
  if (ctx.options.fresh) {
82103
82271
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
82104
- const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
82272
+ const claudeDir = prefix ? join119(resolvedDir, prefix) : resolvedDir;
82105
82273
  const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
82106
82274
  if (!canProceed) {
82107
82275
  return { ...ctx, cancelled: true };
@@ -82121,7 +82289,7 @@ async function handleSelection(ctx) {
82121
82289
  let currentVersion = null;
82122
82290
  try {
82123
82291
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
82124
- const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
82292
+ const claudeDir = prefix ? join119(resolvedDir, prefix) : resolvedDir;
82125
82293
  const existingMetadata = await readManifest(claudeDir);
82126
82294
  currentVersion = existingMetadata?.kits?.[kitType]?.version || null;
82127
82295
  if (currentVersion) {
@@ -82209,7 +82377,7 @@ async function handleSelection(ctx) {
82209
82377
  if (ctx.options.yes && !ctx.options.fresh && !ctx.options.force && releaseTag && !isOfflineMode) {
82210
82378
  try {
82211
82379
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
82212
- const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
82380
+ const claudeDir = prefix ? join119(resolvedDir, prefix) : resolvedDir;
82213
82381
  const existingMetadata = await readManifest(claudeDir);
82214
82382
  const installedKitVersion = existingMetadata?.kits?.[kitType]?.version;
82215
82383
  if (installedKitVersion && versionsMatch(installedKitVersion, releaseTag)) {
@@ -82232,7 +82400,7 @@ async function handleSelection(ctx) {
82232
82400
  let currentSecondaryVersion = null;
82233
82401
  try {
82234
82402
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
82235
- const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
82403
+ const claudeDir = prefix ? join119(resolvedDir, prefix) : resolvedDir;
82236
82404
  const existingMetadata = await readManifest(claudeDir);
82237
82405
  currentSecondaryVersion = existingMetadata?.kits?.[secondaryKit]?.version || null;
82238
82406
  } catch {}
@@ -82315,13 +82483,13 @@ function resolveGlobalTargetDir(targetAgents2) {
82315
82483
  }
82316
82484
  // src/commands/init/phases/sync-handler.ts
82317
82485
  init_paths();
82318
- import { copyFile as copyFile7, mkdir as mkdir28, open as open2, readFile as readFile41, rename as rename7, stat as stat12, unlink as unlink11, writeFile as writeFile28 } from "node:fs/promises";
82319
- import { dirname as dirname35, join as join121, resolve as resolve29 } from "node:path";
82486
+ import { copyFile as copyFile7, mkdir as mkdir28, open as open3, readFile as readFile41, rename as rename7, stat as stat13, unlink as unlink11, writeFile as writeFile28 } from "node:fs/promises";
82487
+ import { dirname as dirname35, join as join122, resolve as resolve29 } from "node:path";
82320
82488
 
82321
82489
  // src/domains/sync/config-version-checker.ts
82322
82490
  init_auth_client();
82323
82491
  import { mkdir as mkdir27, readFile as readFile39, unlink as unlink10, writeFile as writeFile27 } from "node:fs/promises";
82324
- import { join as join119 } from "node:path";
82492
+ import { join as join120 } from "node:path";
82325
82493
  init_version_utils();
82326
82494
  init_logger();
82327
82495
  init_path_resolver();
@@ -82357,7 +82525,7 @@ var CACHE_FILENAME = "config-update-cache.json";
82357
82525
  class ConfigVersionChecker {
82358
82526
  static getCacheFilePath(kitType, global3) {
82359
82527
  const cacheDir = PathResolver.getCacheDir(global3);
82360
- return join119(cacheDir, `${kitType}-${CACHE_FILENAME}`);
82528
+ return join120(cacheDir, `${kitType}-${CACHE_FILENAME}`);
82361
82529
  }
82362
82530
  static async loadCache(kitType, global3) {
82363
82531
  try {
@@ -82476,8 +82644,8 @@ class ConfigVersionChecker {
82476
82644
  // src/domains/sync/sync-engine.ts
82477
82645
  init_ownership_checker();
82478
82646
  init_logger();
82479
- import { lstat as lstat7, readFile as readFile40, readlink, realpath as realpath3, stat as stat11 } from "node:fs/promises";
82480
- import { isAbsolute as isAbsolute5, join as join120, normalize as normalize9, relative as relative17 } from "node:path";
82647
+ import { lstat as lstat7, readFile as readFile40, readlink, realpath as realpath3, stat as stat12 } from "node:fs/promises";
82648
+ import { isAbsolute as isAbsolute5, join as join121, normalize as normalize9, relative as relative17 } from "node:path";
82481
82649
  var MAX_SYNC_FILE_SIZE = 10 * 1024 * 1024;
82482
82650
  var MAX_SYMLINK_DEPTH = 20;
82483
82651
  async function validateSymlinkChain(path11, basePath, maxDepth = MAX_SYMLINK_DEPTH) {
@@ -82489,7 +82657,7 @@ async function validateSymlinkChain(path11, basePath, maxDepth = MAX_SYMLINK_DEP
82489
82657
  if (!stats.isSymbolicLink())
82490
82658
  break;
82491
82659
  const target = await readlink(current);
82492
- const resolvedTarget = isAbsolute5(target) ? target : join120(current, "..", target);
82660
+ const resolvedTarget = isAbsolute5(target) ? target : join121(current, "..", target);
82493
82661
  const normalizedTarget = normalize9(resolvedTarget);
82494
82662
  const rel = relative17(basePath, normalizedTarget);
82495
82663
  if (rel.startsWith("..") || isAbsolute5(rel)) {
@@ -82525,7 +82693,7 @@ async function validateSyncPath(basePath, filePath) {
82525
82693
  if (normalized.startsWith("..") || normalized.includes("/../")) {
82526
82694
  throw new Error(`Path traversal not allowed: ${filePath}`);
82527
82695
  }
82528
- const fullPath = join120(basePath, normalized);
82696
+ const fullPath = join121(basePath, normalized);
82529
82697
  const rel = relative17(basePath, fullPath);
82530
82698
  if (rel.startsWith("..") || isAbsolute5(rel)) {
82531
82699
  throw new Error(`Path escapes base directory: ${filePath}`);
@@ -82540,7 +82708,7 @@ async function validateSyncPath(basePath, filePath) {
82540
82708
  }
82541
82709
  } catch (error) {
82542
82710
  if (error.code === "ENOENT") {
82543
- const parentPath = join120(fullPath, "..");
82711
+ const parentPath = join121(fullPath, "..");
82544
82712
  try {
82545
82713
  const resolvedBase = await realpath3(basePath);
82546
82714
  const resolvedParent = await realpath3(parentPath);
@@ -82577,7 +82745,7 @@ class SyncEngine {
82577
82745
  continue;
82578
82746
  }
82579
82747
  try {
82580
- await stat11(upstreamPath);
82748
+ await stat12(upstreamPath);
82581
82749
  } catch {
82582
82750
  plan.skipped.push(file);
82583
82751
  continue;
@@ -82591,7 +82759,7 @@ class SyncEngine {
82591
82759
  continue;
82592
82760
  }
82593
82761
  try {
82594
- await stat11(localPath);
82762
+ await stat12(localPath);
82595
82763
  } catch {
82596
82764
  plan.autoUpdate.push(file);
82597
82765
  continue;
@@ -83031,13 +83199,13 @@ function getLockTimeout() {
83031
83199
  var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
83032
83200
  async function acquireSyncLock(global3) {
83033
83201
  const cacheDir = PathResolver.getCacheDir(global3);
83034
- const lockPath2 = join121(cacheDir, ".sync-lock");
83202
+ const lockPath2 = join122(cacheDir, ".sync-lock");
83035
83203
  const startTime = Date.now();
83036
83204
  const lockTimeout = getLockTimeout();
83037
83205
  await mkdir28(dirname35(lockPath2), { recursive: true });
83038
83206
  while (Date.now() - startTime < lockTimeout) {
83039
83207
  try {
83040
- const handle = await open2(lockPath2, "wx");
83208
+ const handle = await open3(lockPath2, "wx");
83041
83209
  return async () => {
83042
83210
  await handle.close();
83043
83211
  await unlink11(lockPath2).catch(() => {});
@@ -83045,7 +83213,7 @@ async function acquireSyncLock(global3) {
83045
83213
  } catch (err) {
83046
83214
  if (err.code === "EEXIST") {
83047
83215
  try {
83048
- const lockStat = await stat12(lockPath2);
83216
+ const lockStat = await stat13(lockPath2);
83049
83217
  const lockAge = Math.abs(Date.now() - lockStat.mtimeMs);
83050
83218
  if (lockAge > STALE_LOCK_THRESHOLD_MS) {
83051
83219
  logger.warning(`Removing stale sync lock (age: ${Math.round(lockAge / 1000)}s)`);
@@ -83112,7 +83280,7 @@ async function executeSyncMerge(ctx) {
83112
83280
  try {
83113
83281
  const sourcePath = await validateSyncPath(upstreamDir, file.path);
83114
83282
  const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
83115
- const targetDir = join121(targetPath, "..");
83283
+ const targetDir = join122(targetPath, "..");
83116
83284
  try {
83117
83285
  await mkdir28(targetDir, { recursive: true });
83118
83286
  } catch (mkdirError) {
@@ -83283,7 +83451,7 @@ async function createBackup(claudeDir, files, backupDir) {
83283
83451
  const sourcePath = await validateSyncPath(claudeDir, file.path);
83284
83452
  if (await import_fs_extra34.pathExists(sourcePath)) {
83285
83453
  const targetPath = await validateSyncPath(backupDir, file.path);
83286
- const targetDir = join121(targetPath, "..");
83454
+ const targetDir = join122(targetPath, "..");
83287
83455
  await mkdir28(targetDir, { recursive: true });
83288
83456
  await copyFile7(sourcePath, targetPath);
83289
83457
  }
@@ -83309,38 +83477,38 @@ init_logger();
83309
83477
  init_types2();
83310
83478
  var import_fs_extra35 = __toESM(require_lib(), 1);
83311
83479
  import { rename as rename8, rm as rm9 } from "node:fs/promises";
83312
- import { join as join122, relative as relative18 } from "node:path";
83480
+ import { join as join123, relative as relative18 } from "node:path";
83313
83481
  async function collectDirsToRename(extractDir, folders) {
83314
83482
  const dirsToRename = [];
83315
83483
  if (folders.docs !== DEFAULT_FOLDERS.docs) {
83316
- const docsPath = join122(extractDir, DEFAULT_FOLDERS.docs);
83484
+ const docsPath = join123(extractDir, DEFAULT_FOLDERS.docs);
83317
83485
  if (await import_fs_extra35.pathExists(docsPath)) {
83318
83486
  dirsToRename.push({
83319
83487
  from: docsPath,
83320
- to: join122(extractDir, folders.docs)
83488
+ to: join123(extractDir, folders.docs)
83321
83489
  });
83322
83490
  }
83323
- const claudeDocsPath = join122(extractDir, ".claude", DEFAULT_FOLDERS.docs);
83491
+ const claudeDocsPath = join123(extractDir, ".claude", DEFAULT_FOLDERS.docs);
83324
83492
  if (await import_fs_extra35.pathExists(claudeDocsPath)) {
83325
83493
  dirsToRename.push({
83326
83494
  from: claudeDocsPath,
83327
- to: join122(extractDir, ".claude", folders.docs)
83495
+ to: join123(extractDir, ".claude", folders.docs)
83328
83496
  });
83329
83497
  }
83330
83498
  }
83331
83499
  if (folders.plans !== DEFAULT_FOLDERS.plans) {
83332
- const plansPath = join122(extractDir, DEFAULT_FOLDERS.plans);
83500
+ const plansPath = join123(extractDir, DEFAULT_FOLDERS.plans);
83333
83501
  if (await import_fs_extra35.pathExists(plansPath)) {
83334
83502
  dirsToRename.push({
83335
83503
  from: plansPath,
83336
- to: join122(extractDir, folders.plans)
83504
+ to: join123(extractDir, folders.plans)
83337
83505
  });
83338
83506
  }
83339
- const claudePlansPath = join122(extractDir, ".claude", DEFAULT_FOLDERS.plans);
83507
+ const claudePlansPath = join123(extractDir, ".claude", DEFAULT_FOLDERS.plans);
83340
83508
  if (await import_fs_extra35.pathExists(claudePlansPath)) {
83341
83509
  dirsToRename.push({
83342
83510
  from: claudePlansPath,
83343
- to: join122(extractDir, ".claude", folders.plans)
83511
+ to: join123(extractDir, ".claude", folders.plans)
83344
83512
  });
83345
83513
  }
83346
83514
  }
@@ -83381,7 +83549,7 @@ async function renameFolders(dirsToRename, extractDir, options2) {
83381
83549
  init_logger();
83382
83550
  init_types2();
83383
83551
  import { readFile as readFile42, readdir as readdir29, writeFile as writeFile29 } from "node:fs/promises";
83384
- import { join as join123, relative as relative19 } from "node:path";
83552
+ import { join as join124, relative as relative19 } from "node:path";
83385
83553
  var TRANSFORMABLE_FILE_PATTERNS = [
83386
83554
  ".md",
83387
83555
  ".txt",
@@ -83434,7 +83602,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
83434
83602
  let replacementsCount = 0;
83435
83603
  const entries = await readdir29(dir, { withFileTypes: true });
83436
83604
  for (const entry of entries) {
83437
- const fullPath = join123(dir, entry.name);
83605
+ const fullPath = join124(dir, entry.name);
83438
83606
  if (entry.isDirectory()) {
83439
83607
  if (entry.name === "node_modules" || entry.name === ".git") {
83440
83608
  continue;
@@ -83571,7 +83739,7 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
83571
83739
  init_logger();
83572
83740
  import { readFile as readFile43, readdir as readdir30, writeFile as writeFile30 } from "node:fs/promises";
83573
83741
  import { platform as platform11 } from "node:os";
83574
- import { extname as extname7, join as join124 } from "node:path";
83742
+ import { extname as extname7, join as join125 } from "node:path";
83575
83743
  var IS_WINDOWS3 = platform11() === "win32";
83576
83744
  var HOME_PREFIX = "$HOME";
83577
83745
  function getHomeDirPrefix() {
@@ -83671,7 +83839,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
83671
83839
  async function processDirectory2(dir) {
83672
83840
  const entries = await readdir30(dir, { withFileTypes: true });
83673
83841
  for (const entry of entries) {
83674
- const fullPath = join124(dir, entry.name);
83842
+ const fullPath = join125(dir, entry.name);
83675
83843
  if (entry.isDirectory()) {
83676
83844
  if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
83677
83845
  continue;
@@ -83957,11 +84125,11 @@ async function initCommand(options2) {
83957
84125
  // src/commands/plan/plan-command.ts
83958
84126
  init_output_manager();
83959
84127
  import { existsSync as existsSync62, statSync as statSync11 } from "node:fs";
83960
- import { dirname as dirname41, join as join128, parse as parse4, resolve as resolve33 } from "node:path";
84128
+ import { dirname as dirname41, join as join129, parse as parse4, resolve as resolve33 } from "node:path";
83961
84129
 
83962
84130
  // src/commands/plan/plan-read-handlers.ts
83963
84131
  import { existsSync as existsSync61, statSync as statSync10 } from "node:fs";
83964
- import { basename as basename21, dirname as dirname40, join as join127, relative as relative20, resolve as resolve31 } from "node:path";
84132
+ import { basename as basename21, dirname as dirname40, join as join128, relative as relative20, resolve as resolve31 } from "node:path";
83965
84133
 
83966
84134
  // src/domains/plan-parser/index.ts
83967
84135
  import { dirname as dirname39 } from "node:path";
@@ -84342,12 +84510,12 @@ function parsePlanFile(planFilePath, options2) {
84342
84510
  }
84343
84511
  // src/domains/plan-parser/plan-scanner.ts
84344
84512
  import { existsSync as existsSync58, readdirSync as readdirSync10 } from "node:fs";
84345
- import { join as join125 } from "node:path";
84513
+ import { join as join126 } from "node:path";
84346
84514
  function scanPlanDir(dir) {
84347
84515
  if (!existsSync58(dir))
84348
84516
  return [];
84349
84517
  try {
84350
- return readdirSync10(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join125(dir, entry.name, "plan.md")).filter(existsSync58);
84518
+ return readdirSync10(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join126(dir, entry.name, "plan.md")).filter(existsSync58);
84351
84519
  } catch {
84352
84520
  return [];
84353
84521
  }
@@ -84416,7 +84584,7 @@ function validatePlanFile(filePath, strict = false) {
84416
84584
  var import_gray_matter7 = __toESM(require_gray_matter(), 1);
84417
84585
  import { mkdirSync as mkdirSync9, readFileSync as readFileSync25, writeFileSync as writeFileSync12 } from "node:fs";
84418
84586
  import { existsSync as existsSync60 } from "node:fs";
84419
- import { basename as basename20, dirname as dirname38, join as join126 } from "node:path";
84587
+ import { basename as basename20, dirname as dirname38, join as join127 } from "node:path";
84420
84588
  function phaseNameToFilename(id, name2) {
84421
84589
  const numMatch = /^(\d+)([a-z]*)$/i.exec(id);
84422
84590
  const num4 = numMatch ? numMatch[1] : id;
@@ -84524,12 +84692,12 @@ function scaffoldPlan(options2) {
84524
84692
  mkdirSync9(dir, { recursive: true });
84525
84693
  const resolvedPhases = resolvePhaseIds(options2.phases);
84526
84694
  const optionsWithResolved = { ...options2, phases: resolvedPhases };
84527
- const planFile = join126(dir, "plan.md");
84695
+ const planFile = join127(dir, "plan.md");
84528
84696
  writeFileSync12(planFile, generatePlanMd(optionsWithResolved), "utf8");
84529
84697
  const phaseFiles = [];
84530
84698
  for (const phase of resolvedPhases) {
84531
84699
  const filename = phaseNameToFilename(phase.id, phase.name);
84532
- const phaseFile = join126(dir, filename);
84700
+ const phaseFile = join127(dir, filename);
84533
84701
  writeFileSync12(phaseFile, generatePhaseTemplate(phase), "utf8");
84534
84702
  phaseFiles.push(phaseFile);
84535
84703
  }
@@ -84609,7 +84777,7 @@ function phaseNameFilenameFromTableRow(body, phaseId, planDir) {
84609
84777
  continue;
84610
84778
  const linkMatch = /\[([^\]]+)\]\(\.\/([^)]+)\)/.exec(row);
84611
84779
  if (linkMatch)
84612
- return join126(planDir, linkMatch[2]);
84780
+ return join127(planDir, linkMatch[2]);
84613
84781
  }
84614
84782
  return null;
84615
84783
  }
@@ -84690,7 +84858,7 @@ function addPhase(planFile, name2, afterId) {
84690
84858
  `);
84691
84859
  }
84692
84860
  writeFileSync12(planFile, import_gray_matter7.default.stringify(updatedBody, frontmatter), "utf8");
84693
- const phaseFilePath = join126(planDir, filename);
84861
+ const phaseFilePath = join127(planDir, filename);
84694
84862
  writeFileSync12(phaseFilePath, generatePhaseTemplate({ id: phaseId, name: name2 }), "utf8");
84695
84863
  return { phaseId, phaseFile: phaseFilePath };
84696
84864
  }
@@ -84794,7 +84962,7 @@ async function handleValidate(target, options2) {
84794
84962
  }
84795
84963
  async function handleStatus(target, options2) {
84796
84964
  const t = target ? resolve31(target) : null;
84797
- const plansDir = t && existsSync61(t) && statSync10(t).isDirectory() && !existsSync61(join127(t, "plan.md")) ? t : null;
84965
+ const plansDir = t && existsSync61(t) && statSync10(t).isDirectory() && !existsSync61(join128(t, "plan.md")) ? t : null;
84798
84966
  if (plansDir) {
84799
84967
  const planFiles = scanPlanDir(plansDir);
84800
84968
  if (planFiles.length === 0) {
@@ -85026,10 +85194,10 @@ async function handleAddPhase(target, options2) {
85026
85194
  function resolvePlanFile(target) {
85027
85195
  const t = target ? resolve33(target) : process.cwd();
85028
85196
  if (existsSync62(t)) {
85029
- const stat13 = statSync11(t);
85030
- if (stat13.isFile())
85197
+ const stat14 = statSync11(t);
85198
+ if (stat14.isFile())
85031
85199
  return t;
85032
- const candidate = join128(t, "plan.md");
85200
+ const candidate = join129(t, "plan.md");
85033
85201
  if (existsSync62(candidate))
85034
85202
  return candidate;
85035
85203
  }
@@ -85037,7 +85205,7 @@ function resolvePlanFile(target) {
85037
85205
  let dir = process.cwd();
85038
85206
  const root = parse4(dir).root;
85039
85207
  while (dir !== root) {
85040
- const candidate = join128(dir, "plan.md");
85208
+ const candidate = join129(dir, "plan.md");
85041
85209
  if (existsSync62(candidate))
85042
85210
  return candidate;
85043
85211
  dir = dirname41(dir);
@@ -85134,15 +85302,15 @@ init_logger();
85134
85302
  // src/commands/telemetry/shared.ts
85135
85303
  import { existsSync as existsSync63, readFileSync as readFileSync26, readdirSync as readdirSync11 } from "node:fs";
85136
85304
  import { homedir as homedir29 } from "node:os";
85137
- import { join as join129 } from "node:path";
85305
+ import { join as join130 } from "node:path";
85138
85306
  init_token_store();
85139
85307
  init_manifest_path_resolver();
85140
85308
  init_takumi_constants();
85141
- var USER_CACHE_PATH = join129(homedir29(), ".claude", "sk-user.json");
85142
- var EVENT_BUFFER_DIR = join129(homedir29(), ".claude", "sk-events");
85143
- var RATE_STATE_PATH = join129(homedir29(), ".claude", "sk-rate-state.json");
85144
- var TAKUMI_MANIFEST_PATH = join129(homedir29(), ".claude", MANIFEST_FILENAME);
85145
- var LEGACY_METADATA_PATH = join129(homedir29(), ".claude", LEGACY_MANIFEST_FILENAME);
85309
+ var USER_CACHE_PATH = join130(homedir29(), ".claude", "sk-user.json");
85310
+ var EVENT_BUFFER_DIR = join130(homedir29(), ".claude", "sk-events");
85311
+ var RATE_STATE_PATH = join130(homedir29(), ".claude", "sk-rate-state.json");
85312
+ var TAKUMI_MANIFEST_PATH = join130(homedir29(), ".claude", MANIFEST_FILENAME);
85313
+ var LEGACY_METADATA_PATH = join130(homedir29(), ".claude", LEGACY_MANIFEST_FILENAME);
85146
85314
  var TELEMETRY_HOOK_FIELD = "hooks.telemetry";
85147
85315
  var TOKEN_PLACEHOLDER = "__INJECT_AT_RELEASE__";
85148
85316
  function readUserCache() {
@@ -85171,7 +85339,7 @@ function readTelemetryConfig() {
85171
85339
  const envToken = process.env.TAKUMI_TELEMETRY_TOKEN;
85172
85340
  let metadata = null;
85173
85341
  try {
85174
- const resolved = findManifestPathSync(join129(homedir29(), ".claude"));
85342
+ const resolved = findManifestPathSync(join130(homedir29(), ".claude"));
85175
85343
  if (resolved) {
85176
85344
  metadata = JSON.parse(readFileSync26(resolved.path, "utf8"));
85177
85345
  }
@@ -85349,7 +85517,7 @@ init_safe_prompts();
85349
85517
  init_safe_spinner();
85350
85518
  var import_fs_extra37 = __toESM(require_lib(), 1);
85351
85519
  import { readdirSync as readdirSync13, rmSync as rmSync9 } from "node:fs";
85352
- import { join as join131, resolve as resolve34, sep as sep9 } from "node:path";
85520
+ import { join as join132, resolve as resolve34, sep as sep9 } from "node:path";
85353
85521
 
85354
85522
  // src/commands/uninstall/analysis-handler.ts
85355
85523
  init_metadata_migration();
@@ -85360,7 +85528,7 @@ init_safe_prompts();
85360
85528
  init_takumi_constants();
85361
85529
  var import_picocolors27 = __toESM(require_picocolors(), 1);
85362
85530
  import { existsSync as existsSync64, readdirSync as readdirSync12, rmSync as rmSync8 } from "node:fs";
85363
- import { dirname as dirname42, join as join130 } from "node:path";
85531
+ import { dirname as dirname42, join as join131 } from "node:path";
85364
85532
  function listPresentManifestNames(installPath) {
85365
85533
  const present = [];
85366
85534
  if (existsSync64(getManifestPath(installPath)))
@@ -85413,7 +85581,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
85413
85581
  if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
85414
85582
  const kitFiles = metadata.kits[kit].files || [];
85415
85583
  for (const trackedFile of kitFiles) {
85416
- const filePath = join130(installation.path, trackedFile.path);
85584
+ const filePath = join131(installation.path, trackedFile.path);
85417
85585
  if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
85418
85586
  result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
85419
85587
  continue;
@@ -85445,7 +85613,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
85445
85613
  return result;
85446
85614
  }
85447
85615
  for (const trackedFile of allTrackedFiles) {
85448
- const filePath = join130(installation.path, trackedFile.path);
85616
+ const filePath = join131(installation.path, trackedFile.path);
85449
85617
  const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
85450
85618
  if (!ownershipResult.exists)
85451
85619
  continue;
@@ -85544,7 +85712,7 @@ async function removeInstallations(installations, options2) {
85544
85712
  let removedCount = 0;
85545
85713
  let cleanedDirs = 0;
85546
85714
  for (const item of analysis.toDelete) {
85547
- const filePath = join131(installation.path, item.path);
85715
+ const filePath = join132(installation.path, item.path);
85548
85716
  if (!await import_fs_extra37.pathExists(filePath))
85549
85717
  continue;
85550
85718
  if (!await isPathSafeToRemove(filePath, installation.path)) {
@@ -86413,7 +86581,7 @@ init_manifest_path_resolver();
86413
86581
  init_logger();
86414
86582
  init_types2();
86415
86583
  import { readFileSync as readFileSync27 } from "node:fs";
86416
- import { join as join132 } from "node:path";
86584
+ import { join as join133 } from "node:path";
86417
86585
  var PROVIDER_LOCAL_SUBDIRS = {
86418
86586
  "claude-code": ".claude",
86419
86587
  codex: ".codex"
@@ -86468,7 +86636,7 @@ async function displayVersion() {
86468
86636
  const localSubdir = PROVIDER_LOCAL_SUBDIRS[provider];
86469
86637
  if (!localSubdir)
86470
86638
  continue;
86471
- const localRoot = join132(process.cwd(), localSubdir);
86639
+ const localRoot = join133(process.cwd(), localSubdir);
86472
86640
  if (localRoot === inst.globalRoot())
86473
86641
  continue;
86474
86642
  const resolved = findManifestPathSync(localRoot);