@tekmidian/pai 0.61.0 → 0.62.0

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 (67) hide show
  1. package/dist/{async-CLvuY7b-.mjs → async-DNVWtQl2.mjs} +2 -2
  2. package/dist/{async-CLvuY7b-.mjs.map → async-DNVWtQl2.mjs.map} +1 -1
  3. package/dist/{chain-C5oeyUg4.mjs → chain-CuaDawK9.mjs} +2 -2
  4. package/dist/{chain-C5oeyUg4.mjs.map → chain-CuaDawK9.mjs.map} +1 -1
  5. package/dist/cli/index.mjs +11 -11
  6. package/dist/cli/program.mjs +11 -11
  7. package/dist/{context-handover-cache-BdtJZpgv.mjs → context-handover-cache-DFNnlWv2.mjs} +2 -2
  8. package/dist/{context-handover-cache-BdtJZpgv.mjs.map → context-handover-cache-DFNnlWv2.mjs.map} +1 -1
  9. package/dist/daemon/index.mjs +8 -8
  10. package/dist/{daemon-DSsIEqzW.mjs → daemon-Bf7Eock4.mjs} +32 -18
  11. package/dist/{daemon-DSsIEqzW.mjs.map → daemon-Bf7Eock4.mjs.map} +1 -1
  12. package/dist/daemon-bJi1gDkG.mjs +19 -0
  13. package/dist/daemon-mcp/index.mjs +4 -4
  14. package/dist/{factory-EUUhSSoq.mjs → factory-BozZa81q.mjs} +3 -3
  15. package/dist/{factory-EUUhSSoq.mjs.map → factory-BozZa81q.mjs.map} +1 -1
  16. package/dist/{factory-DW7BCJJT.mjs → factory-UO9_DFMN.mjs} +1 -1
  17. package/dist/{fallback-DDbJVaR8.mjs → fallback-F0TWGVM2.mjs} +2 -2
  18. package/dist/{fallback-DDbJVaR8.mjs.map → fallback-F0TWGVM2.mjs.map} +1 -1
  19. package/dist/{helpers-D9WkIf9R.mjs → helpers-Dj-B314s.mjs} +3 -2
  20. package/dist/{helpers-D9WkIf9R.mjs.map → helpers-Dj-B314s.mjs.map} +1 -1
  21. package/dist/hooks/block-sleep-poll.mjs.map +2 -2
  22. package/dist/hooks/load-project-context.mjs +8513 -133
  23. package/dist/hooks/load-project-context.mjs.map +4 -4
  24. package/dist/hooks/security-validator.mjs.map +1 -1
  25. package/dist/hooks/worker-guard.mjs +7859 -0
  26. package/dist/hooks/worker-guard.mjs.map +7 -0
  27. package/dist/hooks/worker-status-line.mjs +101 -8
  28. package/dist/hooks/worker-status-line.mjs.map +4 -4
  29. package/dist/index.mjs +1 -1
  30. package/dist/{indexer-backend-DcDtin1O.mjs → indexer-backend-BN9rpp9O.mjs} +2 -2
  31. package/dist/{main-resolver-DIQ6m_RA.mjs → main-resolver-BIft_FVF.mjs} +3 -3
  32. package/dist/{main-resolver-DIQ6m_RA.mjs.map → main-resolver-BIft_FVF.mjs.map} +1 -1
  33. package/dist/{main-resolver-CxOsxtOr.mjs → main-resolver-C9-poMdi.mjs} +1 -1
  34. package/dist/{planner-D8jAr_sx.mjs → planner-BG9ivPj0.mjs} +4 -4
  35. package/dist/{planner-D8jAr_sx.mjs.map → planner-BG9ivPj0.mjs.map} +1 -1
  36. package/dist/{postgres-nvU5pShF.mjs → postgres-CxD6_Dca.mjs} +3 -3
  37. package/dist/{postgres-nvU5pShF.mjs.map → postgres-CxD6_Dca.mjs.map} +1 -1
  38. package/dist/{program-BTdspOOa.mjs → program-BRvCzhjx.mjs} +157 -40
  39. package/dist/program-BRvCzhjx.mjs.map +1 -0
  40. package/dist/{run-CxxZKEZw.mjs → run-BVQZI79D.mjs} +281 -85
  41. package/dist/run-BVQZI79D.mjs.map +1 -0
  42. package/dist/{session-keepalive-urk--pfa.mjs → session-keepalive-DJA97K2X.mjs} +2 -2
  43. package/dist/{session-keepalive-urk--pfa.mjs.map → session-keepalive-DJA97K2X.mjs.map} +1 -1
  44. package/dist/{sqlite-D9p5a4qe.mjs → sqlite-CfKfuggn.mjs} +2 -2
  45. package/dist/{sqlite-D9p5a4qe.mjs.map → sqlite-CfKfuggn.mjs.map} +1 -1
  46. package/dist/{tools-r-7ZG8B5.mjs → tools-B52IvaU6.mjs} +3 -3
  47. package/dist/{tools-qXyHFwNj.mjs → tools-DFdPbX-X.mjs} +2 -2
  48. package/dist/{tools-qXyHFwNj.mjs.map → tools-DFdPbX-X.mjs.map} +1 -1
  49. package/dist/{vault-indexer-DHYBpRZ5.mjs → vault-indexer-mCFus_AM.mjs} +2 -2
  50. package/dist/{vault-indexer-DHYBpRZ5.mjs.map → vault-indexer-mCFus_AM.mjs.map} +1 -1
  51. package/dist/{wakeup-C48hcN6O.mjs → wakeup-DO1O4udw.mjs} +2 -2
  52. package/dist/{wakeup-C48hcN6O.mjs.map → wakeup-DO1O4udw.mjs.map} +1 -1
  53. package/dist/{work-queue-worker-DUvPiwGO.mjs → work-queue-worker-BbrC3I_R.mjs} +2 -2
  54. package/dist/{work-queue-worker-DUvPiwGO.mjs.map → work-queue-worker-BbrC3I_R.mjs.map} +1 -1
  55. package/dist/{work-queue-worker-1_VBfI_k.mjs → work-queue-worker-z-AATZ2t.mjs} +3 -3
  56. package/docs/commands/README.md +2 -0
  57. package/docs/commands/worker.md +27 -0
  58. package/package.json +2 -2
  59. package/scripts/build-hooks.mjs +6 -5
  60. package/scripts/build-skill-stubs.mjs +6 -5
  61. package/src/hooks/ts/lib/worker-guard.test.ts +188 -0
  62. package/src/hooks/ts/lib/worker-guard.ts +315 -0
  63. package/src/hooks/ts/pre-tool-use/worker-guard.ts +75 -0
  64. package/src/hooks/ts/session-start/load-project-context.ts +14 -0
  65. package/dist/daemon-MoFF4oeg.mjs +0 -19
  66. package/dist/program-BTdspOOa.mjs.map +0 -1
  67. package/dist/run-CxxZKEZw.mjs.map +0 -1
@@ -3,26 +3,26 @@ import { a as slugify$1, i as parseSessionFilename } from "./migrate-BD7D8EEh.mj
3
3
  import { n as ensurePaiMarker } from "./pai-marker-D1MMswkz.mjs";
4
4
  import { t as STOP_WORDS } from "./stop-words-ClCwO8mZ.mjs";
5
5
  import { t as applyRecencyBoost } from "./search-BaTbyWjK.mjs";
6
- import { a as getStorageBackend, i as getRegistryBackend, r as createStorageBackend, s as humanDuration } from "./factory-EUUhSSoq.mjs";
7
- import { a as formatDetectionJson, i as formatDetection, n as migrateIdentityFile, r as detectProject } from "./wakeup-C48hcN6O.mjs";
8
- import { B as claudeProjectsDir, C as findLatestNote, H as scanTranscriptFolders, I as resolveHome, L as saveScanConfig, M as cmdScan, N as loadScanConfig, P as migrateScanConfig, R as upsertProject, S as applyContinue, T as readBodyFile, U as transcriptFiles, V as findMovedProjects, d as migrateWorkQueue, g as migrateSummaryCooldowns, t as readContextHandoverCache, v as extractAndStoreTriples, w as findNotesDir$1, x as appendCheckpointToNote, z as upsertSession } from "./context-handover-cache-BdtJZpgv.mjs";
6
+ import { a as getStorageBackend, i as getRegistryBackend, r as createStorageBackend, s as humanDuration } from "./factory-BozZa81q.mjs";
7
+ import { a as formatDetectionJson, i as formatDetection, n as migrateIdentityFile, r as detectProject } from "./wakeup-DO1O4udw.mjs";
8
+ import { B as claudeProjectsDir, C as findLatestNote, H as scanTranscriptFolders, I as resolveHome, L as saveScanConfig, M as cmdScan, N as loadScanConfig, P as migrateScanConfig, R as upsertProject, S as applyContinue, T as readBodyFile, U as transcriptFiles, V as findMovedProjects, d as migrateWorkQueue, g as migrateSummaryCooldowns, t as readContextHandoverCache, v as extractAndStoreTriples, w as findNotesDir$1, x as appendCheckpointToNote, z as upsertSession } from "./context-handover-cache-DFNnlWv2.mjs";
9
9
  import { a as paiHomePath, i as paiHomeDir, n as migratePaiDir, o as resolvePaiFile, r as migratePaiFile, t as PaiFileMigrationError } from "./pai-home-CeOIYltV.mjs";
10
10
  import { b as OWNER_LABEL_PREFIX, c as migrateConfigFile, d as readMainConfigRaw, f as writeMainConfigRaw, h as resolvedMainConfigPath, l as paiConfigFilePath, m as migrateMainConfigToYaml, n as CONFIG_FILE$2, o as expandHome, p as MainConfigError, s as loadConfig, t as CONFIG_DIR, u as paiConfigYamlFilePath, v as readJsonStrict, x as UNROUTED, y as writeJsonAtomic } from "./config-CQCmH_gV.mjs";
11
11
  import { a as schedulerLogPath, i as paiSocketPath, n as daemonLogPath, r as daemonPidPath } from "./runtime-paths-BRwDeBEg.mjs";
12
12
  import { B as contextWindowFromModelId, C as nativeAnthropicProvider, E as readWorkersSection, F as parseWorkersYamlDocument, I as relocateWorkersYaml, L as workersYamlLegacyNotice, M as inlineWorkersYamlKeys, N as migrateWorkersToYaml, P as needsWorkersYamlRelocation, R as workersYamlPath, S as maskKey, V as stripModelVariant, b as isModelCapability, f as PROVIDER_TAGS, j as initWorkersYaml, m as WorkersConfigError, r as ANTHROPIC_NATIVE, t as buildRunEnv, u as MODEL_CAPABILITIES, v as expandHome$1, y as getProviderOrNative, z as DEFAULT_CONTEXT_WINDOW } from "./run-env-BE5xyCwy.mjs";
13
- import { A as UNLABELED, E as mergeWorker, G as waitForTerminalStatus, H as ownsPid, I as isChatPane, K as longInlinePromptHint, L as isLive, O as appendLedger, R as loadStatus, U as saveStatus, W as setWorkerLabel, X as expandMcpNames, Y as describeMcp, a as projectLaunchConfig, c as handoffFromInside, f as checkPaneForWorker, g as markControlsHeld, h as clickrControlsArgv, i as usageContextTokens, m as openPaneForWorker, n as runWorker, o as parseWorkerReport, p as openFollowPane, q as parseRunnerArgs, r as testProvider, u as sayToWorker, w as discardWorker, z as loadStatuses } from "./run-CxxZKEZw.mjs";
13
+ import { A as appendLedger, B as loadStatus, D as mergeWorker, E as git, G as saveStatus, J as longInlinePromptHint, K as setWorkerLabel, M as UNLABELED, O as uncommittedPaths, Q as expandMcpNames, R as isChatPane, T as gcWorktrees, V as loadStatuses, W as ownsPid, Y as parseRunnerArgs, Z as describeMcp, a as projectLaunchConfig, c as handoffFromInside, f as checkPaneForWorker, g as markControlsHeld, h as clickrControlsArgv, i as usageContextTokens, m as openPaneForWorker, n as runWorker, o as parseWorkerReport, p as openFollowPane, q as waitForTerminalStatus, r as testProvider, u as sayToWorker, w as discardWorker, z as isLive } from "./run-BVQZI79D.mjs";
14
14
  import { t as MergeError } from "./merge-xoyfZQ4W.mjs";
15
15
  import { n as oldFederationPath, t as federationDbPath } from "./federation-db-w8e-sKjp.mjs";
16
16
  import { r as registryDbPath, t as oldRegistryPath } from "./registry-db-Bkpbp7Gf.mjs";
17
- import { i as indexProjectWithBackend } from "./async-CLvuY7b-.mjs";
17
+ import { i as indexProjectWithBackend } from "./async-DNVWtQl2.mjs";
18
18
  import { t as PaiClient } from "./ipc-client-Dasm515c.mjs";
19
- import { A as getConfigValueOp, C as psOutput, D as resolveSpecPath, E as readSpecPrompt, M as setConfigValueOp, N as unsetConfigValueOp, O as MainConfigOpsError, S as followWorkers, T as statusLineOutput, _ as setWorkersEnabled, a as addProvider, b as updateProvider, c as describeModels, d as removeProvider, f as resolveProviderName, g as setProviderModel, h as setProviderEnabled, i as fallbackStatusText, j as listConfigOp, k as formatConfigGetOutput, l as describeProviders, m as setClass, n as fallbackOn, o as classTargetText, p as setCapabilityPreference, r as fallbackStatus, s as describeCapabilities, t as fallbackOff, u as modelPrefsText, v as unsetCapabilityPreference, w as replayOutput, x as useProvider, y as unsetClass } from "./fallback-DDbJVaR8.mjs";
20
- import { _ as resolveSessionByNameOrId, a as buildDeduped, c as hasConversation, d as providerResumePlan, f as restoreTopLevel, g as migrateSessionScanCache, h as fmtAge, l as launchInDir, m as printExitDir, o as normalizeName$2, p as resumeArgvText, s as renderDedupedSessions, t as cmdMain, u as launchPrompt, v as scanCacheFilePath, y as scanSessions } from "./main-resolver-DIQ6m_RA.mjs";
19
+ import { A as getConfigValueOp, C as psOutput, D as resolveSpecPath, E as readSpecPrompt, M as setConfigValueOp, N as unsetConfigValueOp, O as MainConfigOpsError, S as followWorkers, T as statusLineOutput, _ as setWorkersEnabled, a as addProvider, b as updateProvider, c as describeModels, d as removeProvider, f as resolveProviderName, g as setProviderModel, h as setProviderEnabled, i as fallbackStatusText, j as listConfigOp, k as formatConfigGetOutput, l as describeProviders, m as setClass, n as fallbackOn, o as classTargetText, p as setCapabilityPreference, r as fallbackStatus, s as describeCapabilities, t as fallbackOff, u as modelPrefsText, v as unsetCapabilityPreference, w as replayOutput, x as useProvider, y as unsetClass } from "./fallback-F0TWGVM2.mjs";
20
+ import { _ as resolveSessionByNameOrId, a as buildDeduped, c as hasConversation, d as providerResumePlan, f as restoreTopLevel, g as migrateSessionScanCache, h as fmtAge$1, l as launchInDir, m as printExitDir, o as normalizeName$2, p as resumeArgvText, s as renderDedupedSessions, t as cmdMain, u as launchPrompt, v as scanCacheFilePath, y as scanSessions } from "./main-resolver-BIft_FVF.mjs";
21
21
  import { n as queriesDirPath, t as migrateQueriesDir } from "./query-feedback-xz5axTj3.mjs";
22
- import { h as ledgerPath, m as eventsPath, n as ensureProxyRunning, p as ensureNoMcpConfig, r as stopProxy, t as DEFAULT_PROXY_PORT, v as workersLogDir } from "./server-BY6AedmC.mjs";
22
+ import { _ as statusPath, h as ledgerPath, m as eventsPath, n as ensureProxyRunning, p as ensureNoMcpConfig, r as stopProxy, t as DEFAULT_PROXY_PORT, v as workersLogDir } from "./server-BY6AedmC.mjs";
23
23
  import { i as sendToSession, n as fetchLiveSessions, r as revealItermSession, t as callAiBroker } from "./aibroker-client-BK1h--W_.mjs";
24
- import { a as totalUsageTokens, i as parseSessionUsage, r as sessionKeepaliveLedgerSummary, t as loadSessionKeepaliveState } from "./session-keepalive-urk--pfa.mjs";
25
- import { t as runChain } from "./chain-C5oeyUg4.mjs";
24
+ import { a as totalUsageTokens, i as parseSessionUsage, r as sessionKeepaliveLedgerSummary, t as loadSessionKeepaliveState } from "./session-keepalive-DJA97K2X.mjs";
25
+ import { t as runChain } from "./chain-CuaDawK9.mjs";
26
26
  import { appendFileSync, chmodSync, closeSync, copyFileSync, cpSync, createReadStream, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, readlinkSync, realpathSync, renameSync, statSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
27
27
  import { homedir, platform, tmpdir, userInfo } from "node:os";
28
28
  import { basename, dirname, join, relative, resolve, sep } from "node:path";
@@ -161,7 +161,7 @@ async function cmdPromote(opts) {
161
161
  console.error(dim$1(` Pick a durable location for the new project.`));
162
162
  process.exit(1);
163
163
  }
164
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
164
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
165
165
  const registryBackend = await getRegistryBackend();
166
166
  const encodedDir = encodeDir(targetPath);
167
167
  if (await registryBackend.getProjectBySlug(slug) ?? await registryBackend.getProjectByRootPath(targetPath) ?? await registryBackend.getProjectByEncodedDir(encodedDir)) {
@@ -2035,7 +2035,7 @@ async function cmdUnregister(slug, opts = {}) {
2035
2035
  //#region src/cli/commands/project/projects-index.ts
2036
2036
  function registerProjectsCommands(projectsCmd) {
2037
2037
  projectsCmd.command("list", { isDefault: true }).description("Show the unified deduped listing (same as `pai`).\nUse --all to include cold / zero-session / archived projects.").option("--all", "Show all entries including cold / zero-session / archived projects").option("-n, --n <count>", "Max rows to show", "20").action(async (opts) => {
2038
- const { cmdMain } = await import("./main-resolver-CxOsxtOr.mjs");
2038
+ const { cmdMain } = await import("./main-resolver-C9-poMdi.mjs");
2039
2039
  await cmdMain(void 0, void 0, opts);
2040
2040
  });
2041
2041
  projectsCmd.command("list-raw").description("Raw registry listing with slug, path, status, last_active columns").option("--all", "Include archived projects (default: active only)").option("--status <status>", "Filter by status: active | archived").option("--tag <tag>", "Filter by tag").option("--type <type>", "Filter by type").action(async (opts) => {
@@ -3247,7 +3247,7 @@ function registerStatsCommands(memoryCmd) {
3247
3247
  //#region src/cli/commands/memory/sources-cmd.ts
3248
3248
  function registerSourcesCommand(memoryCmd) {
3249
3249
  memoryCmd.command("sources").description("Show what the indexer has taken in: composition by source, which roots\ncontent enters from, the heaviest single files, and how many chunks are\nrewritten per day (which distinguishes a finite backlog from a treadmill).").option("--limit <n>", "Rows per section (default 8)", "8").action(async (opts) => {
3250
- const { createStorageBackend } = await import("./factory-DW7BCJJT.mjs");
3250
+ const { createStorageBackend } = await import("./factory-UO9_DFMN.mjs");
3251
3251
  const { loadConfig } = await import("./config-DjXq_W42.mjs");
3252
3252
  const { cmdMemorySources } = await import("./sources-BBe3AZ-W.mjs");
3253
3253
  let backend;
@@ -7073,7 +7073,7 @@ function cmdLogs(opts) {
7073
7073
  }
7074
7074
  function registerDaemonCommands(daemonCmd) {
7075
7075
  daemonCmd.command("serve").description("Start the PAI daemon in the foreground").action(async () => {
7076
- const { serve } = await import("./daemon-MoFF4oeg.mjs");
7076
+ const { serve } = await import("./daemon-bJi1gDkG.mjs");
7077
7077
  const { loadConfig: lc, ensureConfigDir } = await import("./config-DjXq_W42.mjs");
7078
7078
  ensureConfigDir();
7079
7079
  await serve(lc());
@@ -8408,6 +8408,11 @@ async function stepSettings(rl, daName) {
8408
8408
  matcher: "Bash",
8409
8409
  command: "${ADAPTER_DIR}/Hooks/security-validator.mjs"
8410
8410
  },
8411
+ {
8412
+ hookType: "PreToolUse",
8413
+ matcher: "Bash|Edit|Write|MultiEdit|NotebookEdit",
8414
+ command: "${ADAPTER_DIR}/Hooks/worker-guard.mjs"
8415
+ },
8411
8416
  {
8412
8417
  hookType: "PreToolUse",
8413
8418
  matcher: "*",
@@ -16086,7 +16091,7 @@ async function migrateToPostgres(opts = {}) {
16086
16091
  const dump = pgDump(container, pgConfig, dumpPath);
16087
16092
  if (!dump.ok) return refused(dump.reason, dryRun);
16088
16093
  }
16089
- const { PostgresBackend } = await import("./postgres-nvU5pShF.mjs");
16094
+ const { PostgresBackend } = await import("./postgres-CxD6_Dca.mjs");
16090
16095
  await PostgresBackend.ensureDatabase(pgConfig);
16091
16096
  const sqlite = new BetterSqlite3(sqliteFederationPath, { readonly: true });
16092
16097
  const registrySqlite = sqliteRegistryPath === sqliteFederationPath ? sqlite : new BetterSqlite3(sqliteRegistryPath, { readonly: true });
@@ -16657,7 +16662,7 @@ async function getSessionTags(registryBackend, sessionId) {
16657
16662
  * Session CRUD commands: list, info, rename, slug, tag, route, active, auto-route.
16658
16663
  */
16659
16664
  async function cmdList(projectSlug, opts) {
16660
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
16665
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
16661
16666
  const registryBackend = await getRegistryBackend();
16662
16667
  const limit = parseInt(opts.limit ?? "20", 10);
16663
16668
  let project;
@@ -16722,7 +16727,7 @@ async function cmdList(projectSlug, opts) {
16722
16727
  console.log(dim$1(` ${rows.length} session(s) shown (limit: ${limit})`));
16723
16728
  }
16724
16729
  async function cmdInfo(projectSlug, sessionNumber) {
16725
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
16730
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
16726
16731
  const registryBackend = await getRegistryBackend();
16727
16732
  const project = await getProject$1(registryBackend, projectSlug);
16728
16733
  if (!project) {
@@ -16746,7 +16751,7 @@ async function cmdInfo(projectSlug, sessionNumber) {
16746
16751
  console.log();
16747
16752
  }
16748
16753
  async function cmdRename(projectSlug, numberOrLatest, newSlug) {
16749
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
16754
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
16750
16755
  await cmdRenameWith(await getRegistryBackend(), projectSlug, numberOrLatest, newSlug);
16751
16756
  }
16752
16757
  async function cmdRenameWith(registryBackend, projectSlug, numberOrLatest, newSlug) {
@@ -16809,7 +16814,7 @@ async function cmdRenameWith(registryBackend, projectSlug, numberOrLatest, newSl
16809
16814
  console.log();
16810
16815
  }
16811
16816
  async function cmdSlug(projectSlug, numberOrLatest, opts) {
16812
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
16817
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
16813
16818
  const registryBackend = await getRegistryBackend();
16814
16819
  const project = await getProject$1(registryBackend, projectSlug);
16815
16820
  if (!project) {
@@ -16839,7 +16844,7 @@ async function cmdSlug(projectSlug, numberOrLatest, opts) {
16839
16844
  }
16840
16845
  }
16841
16846
  async function cmdTag(projectSlug, sessionNumber, rawTags) {
16842
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
16847
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
16843
16848
  const registryBackend = await getRegistryBackend();
16844
16849
  const project = await getProject$1(registryBackend, projectSlug);
16845
16850
  if (!project) {
@@ -16879,7 +16884,7 @@ async function cmdTag(projectSlug, sessionNumber, rawTags) {
16879
16884
  console.log();
16880
16885
  }
16881
16886
  async function cmdRoute(projectSlug, sessionNumber, targetProjectSlug, opts) {
16882
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
16887
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
16883
16888
  const registryBackend = await getRegistryBackend();
16884
16889
  const project = await getProject$1(registryBackend, projectSlug);
16885
16890
  if (!project) {
@@ -16921,7 +16926,7 @@ async function cmdRoute(projectSlug, sessionNumber, targetProjectSlug, opts) {
16921
16926
  console.log();
16922
16927
  }
16923
16928
  async function cmdActive(opts) {
16924
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
16929
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
16925
16930
  const registryBackend = await getRegistryBackend();
16926
16931
  const minutes = parseInt(opts.minutes ?? "60", 10);
16927
16932
  const cutoff = Date.now() - minutes * 60 * 1e3;
@@ -17009,7 +17014,7 @@ async function cmdActive(opts) {
17009
17014
  }
17010
17015
  async function cmdAutoRoute(opts) {
17011
17016
  const { autoRoute, formatAutoRouteJson } = await import("./auto-route-CF8WNaoy.mjs");
17012
- const { getRegistryBackend, createStorageBackend } = await import("./factory-DW7BCJJT.mjs");
17017
+ const { getRegistryBackend, createStorageBackend } = await import("./factory-UO9_DFMN.mjs");
17013
17018
  const { loadConfig } = await import("./config-DjXq_W42.mjs");
17014
17019
  const config = loadConfig();
17015
17020
  const registryBackend = await getRegistryBackend();
@@ -17246,7 +17251,7 @@ async function cmdPause(opts) {
17246
17251
  process.exitCode = 1;
17247
17252
  return;
17248
17253
  }
17249
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
17254
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
17250
17255
  const registryBackend = await getRegistryBackend();
17251
17256
  const cwd = process.cwd();
17252
17257
  const project = await resolveProjectByCwd(registryBackend, cwd);
@@ -17641,7 +17646,7 @@ function buildStopBody(project, sessionId) {
17641
17646
  }
17642
17647
  }
17643
17648
  async function cmdHandover(projectSlug, numberOrLatest, sessionId) {
17644
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
17649
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
17645
17650
  const registryBackend = await getRegistryBackend();
17646
17651
  let project;
17647
17652
  if (projectSlug) {
@@ -17937,7 +17942,7 @@ function touchSentinel(rootPath) {
17937
17942
  async function cmdAutosave(opts) {
17938
17943
  const minGap = parseInt(opts.minGap ?? String(DEFAULT_MIN_GAP), 10);
17939
17944
  const cwd = process.cwd();
17940
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
17945
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
17941
17946
  const registryBackend = await getRegistryBackend();
17942
17947
  const project = await resolveProjectByCwd(registryBackend, cwd);
17943
17948
  if (!project) return;
@@ -18062,7 +18067,7 @@ async function cmdRecent(opts) {
18062
18067
  shortId: s.shortId,
18063
18068
  resumable: s.resumable,
18064
18069
  sessionStatus: s.sessionStatus,
18065
- age: fmtAge(s.mtime),
18070
+ age: fmtAge$1(s.mtime),
18066
18071
  mtime: s.mtime,
18067
18072
  name: s.friendlyName,
18068
18073
  lastUserPrompt: s.lastUserPrompt,
@@ -18100,7 +18105,7 @@ async function cmdRecent(opts) {
18100
18105
  return [
18101
18106
  chalk.dim(String(idx + 1)),
18102
18107
  chalk.cyan(s.shortId),
18103
- dim$1(fmtAge(s.mtime)),
18108
+ dim$1(fmtAge$1(s.mtime)),
18104
18109
  name.length > 26 ? name.slice(0, 25) + "…" : name,
18105
18110
  prompt,
18106
18111
  s.userLines > 0 ? String(s.userLines) : dim$1("—"),
@@ -18200,7 +18205,7 @@ async function cmdGoto(query, opts) {
18200
18205
  console.log(` fallback: ${chalk.yellow(argvFresh)}`);
18201
18206
  if (resumableSession) {
18202
18207
  console.log(`\n uuid: ${resumableSession.uuid}`);
18203
- console.log(` age: ${fmtAge(resumableSession.mtime)}`);
18208
+ console.log(` age: ${fmtAge$1(resumableSession.mtime)}`);
18204
18209
  console.log(` status: ${resumableSession.sessionStatus}`);
18205
18210
  console.log(` sys: ${resumableSession.topLevelSystemLines} system lines`);
18206
18211
  }
@@ -19010,6 +19015,89 @@ function registerWorkerConfigCommands(workerCmd) {
19010
19015
  });
19011
19016
  }
19012
19017
 
19018
+ //#endregion
19019
+ //#region src/workers/pending.ts
19020
+ /**
19021
+ * Pending worker results: finished workers whose worktree branch still holds
19022
+ * work that never reached the repo (commits not in HEAD, or uncommitted
19023
+ * files). Surfaced by `pai worker ps/pending`, the SessionStart hook, the
19024
+ * status line and the prepublish gate so an unmerged fix cannot be forgotten.
19025
+ */
19026
+ /** Stale after this long: `pai worker gc` (archive) instead of merge. */
19027
+ const STALE_HOURS = 24;
19028
+ function toplevel(dir) {
19029
+ try {
19030
+ return git(dir, ["rev-parse", "--show-toplevel"]);
19031
+ } catch {
19032
+ return null;
19033
+ }
19034
+ }
19035
+ function fmtAge(ms) {
19036
+ const h = Math.floor(ms / 36e5);
19037
+ return h >= 48 ? `${Math.floor(h / 24)}d` : h >= 1 ? `${h}h` : `${Math.floor(ms / 6e4)}m`;
19038
+ }
19039
+ /** Finished workers with unmerged work; `repoRoot` limits to one repo, else every repo. */
19040
+ function pendingResults(logDir, repoRoot, now = Date.now()) {
19041
+ const want = repoRoot ? toplevel(repoRoot) : null;
19042
+ if (repoRoot && !want) return [];
19043
+ const out = [];
19044
+ for (const st of loadStatuses(logDir)) {
19045
+ if (st.archived || st.merged || isLive(st)) continue;
19046
+ if (!st.worktreeDir || !existsSync(st.worktreeDir)) continue;
19047
+ const repo = toplevel(st.cwd);
19048
+ if (!repo || want && repo !== want) continue;
19049
+ let commits = 0;
19050
+ let dirty = 0;
19051
+ try {
19052
+ if (st.branch) commits = git(repo, [
19053
+ "cherry",
19054
+ "HEAD",
19055
+ `refs/heads/${st.branch}`
19056
+ ]).split("\n").filter((l) => l.startsWith("+")).length;
19057
+ dirty = uncommittedPaths(st.worktreeDir).filter((p) => !/(^|\/)node_modules(\/|$)/.test(p)).length;
19058
+ } catch {
19059
+ continue;
19060
+ }
19061
+ if (!commits && !dirty) continue;
19062
+ let ageMs = 0;
19063
+ try {
19064
+ ageMs = Math.max(0, now - statSync(statusPath(logDir, st.id)).mtimeMs);
19065
+ } catch {}
19066
+ out.push({
19067
+ id: st.id,
19068
+ label: st.label,
19069
+ repo,
19070
+ ageMs,
19071
+ age: fmtAge(ageMs),
19072
+ commits,
19073
+ dirty
19074
+ });
19075
+ }
19076
+ return out;
19077
+ }
19078
+ /** One human line per result, with the exact next command. */
19079
+ function formatPending(results, showRepo = false) {
19080
+ return results.map((r) => {
19081
+ const next = r.ageMs > STALE_HOURS * 36e5 ? "pai worker gc" : `pai worker merge ${r.id}`;
19082
+ const repo = showRepo ? ` ${r.repo}` : "";
19083
+ return `${r.id} ${r.age} ${r.commits} commit(s), ${r.dirty} dirty ${r.label}${repo} -> ${next}`;
19084
+ }).join("\n");
19085
+ }
19086
+ /**
19087
+ * Release gate: exit code and message for `pai worker pending --gate`.
19088
+ * PAI_ALLOW_PENDING=1 overrides.
19089
+ */
19090
+ function pendingGate(results, env = process.env) {
19091
+ if (!results.length || env.PAI_ALLOW_PENDING === "1") return {
19092
+ code: 0,
19093
+ message: ""
19094
+ };
19095
+ return {
19096
+ code: 1,
19097
+ message: `${results.length} unmerged worker result(s) in this repo — merge or discard before publishing:\n${formatPending(results)}\nOverride deliberately with PAI_ALLOW_PENDING=1.`
19098
+ };
19099
+ }
19100
+
19013
19101
  //#endregion
19014
19102
  //#region src/workers/wait.ts
19015
19103
  /**
@@ -19191,7 +19279,24 @@ function registerWorkerCommands(workerCmd) {
19191
19279
  });
19192
19280
  workerCmd.command("ps").description("List workers of this session (RUNNING + FINISHED); --all for every worker").option("--all", "Show workers of all sessions, not just this terminal's").action((opts) => {
19193
19281
  try {
19194
- console.log(psOutput(currentLogDir(), opts.all === true));
19282
+ const logDir = currentLogDir();
19283
+ const pending = pendingResults(logDir, process.cwd()).length;
19284
+ if (pending) console.log(`${pending} unmerged result(s) — pai worker pending`);
19285
+ console.log(psOutput(logDir, opts.all === true));
19286
+ } catch (e) {
19287
+ fail(e);
19288
+ }
19289
+ });
19290
+ workerCmd.command("pending").description("Finished workers whose branch or worktree holds work not yet merged into this repo").option("--all", "Every repo in the log dir, not just the current one").option("--json", "Machine-readable output").option("--gate", "Release gate: exit 1 with the list unless PAI_ALLOW_PENDING=1").action((opts) => {
19291
+ try {
19292
+ const res = pendingResults(currentLogDir(), opts.all ? void 0 : process.cwd());
19293
+ if (opts.gate) {
19294
+ const g = pendingGate(res);
19295
+ if (g.message) console.error(g.message);
19296
+ process.exit(g.code);
19297
+ }
19298
+ if (opts.json) console.log(JSON.stringify(res, null, 2));
19299
+ else console.log(res.length ? formatPending(res, opts.all === true) : "no pending worker results");
19195
19300
  } catch (e) {
19196
19301
  fail(e);
19197
19302
  }
@@ -19340,6 +19445,18 @@ function registerWorkerCommands(workerCmd) {
19340
19445
  fail(e);
19341
19446
  }
19342
19447
  });
19448
+ workerCmd.command("gc").description("Archive leftover worker worktrees (state kept under refs/pai-archive/<id>; gitignored files are not kept)").option("--older-than <hours>", "minimum age of a finished worker", "24").option("--dry-run", "print what would be archived, change nothing").action((opts) => {
19449
+ try {
19450
+ const hours = Number(opts.olderThan);
19451
+ if (!Number.isFinite(hours) || hours < 0) throw new Error(`bad --older-than "${opts.olderThan}"`);
19452
+ const res = gcWorktrees(currentLogDir(), hours, opts.dryRun === true);
19453
+ const verb = opts.dryRun ? "would archive" : "archived";
19454
+ for (const r of res) console.log(r.skipped ? `skipped ${r.id}: ${r.skipped}` : `${verb} ${r.id} -> ${r.archive}`);
19455
+ console.log(`${res.filter((r) => r.archive).length} ${opts.dryRun ? "would be archived" : "archived"}`);
19456
+ } catch (e) {
19457
+ fail(e);
19458
+ }
19459
+ });
19343
19460
  workerCmd.command("kill <id>").description("Send SIGTERM to a running worker process").action(async (id) => {
19344
19461
  try {
19345
19462
  const logDir = currentLogDir();
@@ -20220,7 +20337,7 @@ async function countVectorDbPaths(oldPaths) {
20220
20337
  if (oldPaths.length === 0) return 0;
20221
20338
  try {
20222
20339
  const { loadConfig } = await import("./config-DjXq_W42.mjs");
20223
- const { createStorageBackend } = await import("./factory-DW7BCJJT.mjs");
20340
+ const { createStorageBackend } = await import("./factory-UO9_DFMN.mjs");
20224
20341
  const config = loadConfig();
20225
20342
  if (config.storageBackend !== "postgres") return 0;
20226
20343
  const backend = await createStorageBackend(config);
@@ -20238,7 +20355,7 @@ async function updateVectorDbPaths(moves) {
20238
20355
  if (moves.length === 0) return 0;
20239
20356
  try {
20240
20357
  const { loadConfig } = await import("./config-DjXq_W42.mjs");
20241
- const { createStorageBackend } = await import("./factory-DW7BCJJT.mjs");
20358
+ const { createStorageBackend } = await import("./factory-UO9_DFMN.mjs");
20242
20359
  const config = loadConfig();
20243
20360
  if (config.storageBackend !== "postgres") return 0;
20244
20361
  const backend = await createStorageBackend(config);
@@ -20325,7 +20442,7 @@ async function displayDryRun(plans) {
20325
20442
  console.log();
20326
20443
  }
20327
20444
  async function executeCleanup(plans, skipReindex) {
20328
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
20445
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
20329
20446
  const registryBackend = await getRegistryBackend();
20330
20447
  let deleted = 0;
20331
20448
  let renamed = 0;
@@ -20522,7 +20639,7 @@ async function executeCleanup(plans, skipReindex) {
20522
20639
  //#region src/cli/commands/session-cleanup/index.ts
20523
20640
  function registerSessionCleanupCommand(sessionCmd) {
20524
20641
  sessionCmd.command("cleanup [project-slug]").description("Clean up session notes: delete empties, auto-name unnamed, move into YYYY/MM/ hierarchy, renumber").option("--execute", "Actually perform the cleanup (default is dry-run)").option("--no-renumber", "Skip renumbering sessions after deletions").option("--no-reindex", "Skip triggering memory re-index after moves").action(async (projectSlug, opts) => {
20525
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
20642
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
20526
20643
  const registryBackend = await getRegistryBackend();
20527
20644
  const dryRun = !opts.execute;
20528
20645
  const skipReindex = opts.reindex === false;
@@ -20592,7 +20709,7 @@ function finalizeNote(notePath) {
20592
20709
  }
20593
20710
  async function cmdEnd(opts) {
20594
20711
  await cmdPause(opts);
20595
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
20712
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
20596
20713
  const registryBackend = await getRegistryBackend();
20597
20714
  const cwd = process.cwd();
20598
20715
  const project = await registryBackend.findProjectByCwdPrefix(cwd);
@@ -21040,7 +21157,7 @@ async function cmdFind(query, opts) {
21040
21157
  */
21041
21158
  async function getProjects(includeArchived) {
21042
21159
  try {
21043
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
21160
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
21044
21161
  const rows = await (await getRegistryBackend()).listProjectsWithSessionStats();
21045
21162
  return includeArchived ? rows : rows.filter((p) => p.status === "active");
21046
21163
  } catch {
@@ -21181,7 +21298,7 @@ function buildFeedFrom(allSessions, projects, liveSessions, allProjects) {
21181
21298
  const tag = tagFor(e.status);
21182
21299
  const name = chalk.white(pad(e.name, 22));
21183
21300
  const where = dir ? dim$1(shorten(dir, 40)) : chalk.green("(running in another tab)");
21184
- const age = e.status === "live" ? chalk.green("now") : e.lastActivity > 0 ? dim$1(fmtAge(e.lastActivity)) : dim$1("—");
21301
+ const age = e.status === "live" ? chalk.green("now") : e.lastActivity > 0 ? dim$1(fmtAge$1(e.lastActivity)) : dim$1("—");
21185
21302
  const kwDisp = kw ? dim$1(" " + kw) : "";
21186
21303
  const display = `${tag} ${name} ${pad(age, 5)} ${where}${kwDisp}`;
21187
21304
  const search = `${e.name} ${dir ?? ""} ${kw}`.toLowerCase();
@@ -21247,7 +21364,7 @@ function contextFor(rec) {
21247
21364
  const notes = recentMarkdown(rec.dir, 4);
21248
21365
  if (notes.length) {
21249
21366
  lines.push(dim$1("recent notes:"));
21250
- for (const n of notes) lines.push(" " + dim$1(n.rel.slice(0, 60)) + " " + dim$1(fmtAge(n.mtime)));
21367
+ for (const n of notes) lines.push(" " + dim$1(n.rel.slice(0, 60)) + " " + dim$1(fmtAge$1(n.mtime)));
21251
21368
  } else lines.push(dim$1("(no notes here yet)"));
21252
21369
  ctxCache.set(rec.dir, lines);
21253
21370
  return lines;
@@ -21514,7 +21631,7 @@ async function cmdPick(opts = {}) {
21514
21631
  const onRemove = async (rec) => {
21515
21632
  if (!rec.slug) return false;
21516
21633
  try {
21517
- const { getRegistryBackend } = await import("./factory-DW7BCJJT.mjs");
21634
+ const { getRegistryBackend } = await import("./factory-UO9_DFMN.mjs");
21518
21635
  const registryBackend = await getRegistryBackend();
21519
21636
  const project = await registryBackend.getProjectBySlug(rec.slug);
21520
21637
  if (!project || project.status !== "active") return false;
@@ -21799,4 +21916,4 @@ claude() {
21799
21916
 
21800
21917
  //#endregion
21801
21918
  export { drainStdio as n, buildProgram as t };
21802
- //# sourceMappingURL=program-BTdspOOa.mjs.map
21919
+ //# sourceMappingURL=program-BRvCzhjx.mjs.map