@mmnto/cli 1.114.0 → 1.115.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 (82) hide show
  1. package/dist/commands/doctor-seat-identity.d.ts +71 -0
  2. package/dist/commands/doctor-seat-identity.d.ts.map +1 -0
  3. package/dist/commands/doctor-seat-identity.js +352 -0
  4. package/dist/commands/doctor-seat-identity.js.map +1 -0
  5. package/dist/commands/doctor-seat-identity.test.d.ts +13 -0
  6. package/dist/commands/doctor-seat-identity.test.d.ts.map +1 -0
  7. package/dist/commands/doctor-seat-identity.test.js +230 -0
  8. package/dist/commands/doctor-seat-identity.test.js.map +1 -0
  9. package/dist/commands/doctor.d.ts.map +1 -1
  10. package/dist/commands/doctor.js +3 -0
  11. package/dist/commands/doctor.js.map +1 -1
  12. package/dist/commands/doctor.test.js +1 -0
  13. package/dist/commands/doctor.test.js.map +1 -1
  14. package/dist/commands/ecl-gc.d.ts.map +1 -1
  15. package/dist/commands/ecl-gc.js +18 -7
  16. package/dist/commands/ecl-gc.js.map +1 -1
  17. package/dist/commands/ecl-gc.test.js +63 -1
  18. package/dist/commands/ecl-gc.test.js.map +1 -1
  19. package/dist/commands/eject.d.ts +62 -3
  20. package/dist/commands/eject.d.ts.map +1 -1
  21. package/dist/commands/eject.js +382 -47
  22. package/dist/commands/eject.js.map +1 -1
  23. package/dist/commands/eject.test.js +557 -7
  24. package/dist/commands/eject.test.js.map +1 -1
  25. package/dist/commands/gemini-beforetool-contract.test.d.ts +2 -0
  26. package/dist/commands/gemini-beforetool-contract.test.d.ts.map +1 -0
  27. package/dist/commands/gemini-beforetool-contract.test.js +106 -0
  28. package/dist/commands/gemini-beforetool-contract.test.js.map +1 -0
  29. package/dist/commands/gemini-sessionstart-contract.test.d.ts +2 -0
  30. package/dist/commands/gemini-sessionstart-contract.test.d.ts.map +1 -0
  31. package/dist/commands/gemini-sessionstart-contract.test.js +184 -0
  32. package/dist/commands/gemini-sessionstart-contract.test.js.map +1 -0
  33. package/dist/commands/init-templates.d.ts +2 -2
  34. package/dist/commands/init-templates.d.ts.map +1 -1
  35. package/dist/commands/init-templates.js +267 -15
  36. package/dist/commands/init-templates.js.map +1 -1
  37. package/dist/commands/init.test.js +25 -7
  38. package/dist/commands/init.test.js.map +1 -1
  39. package/dist/commands/install-hooks-exit-contract.test.js +5 -0
  40. package/dist/commands/install-hooks-exit-contract.test.js.map +1 -1
  41. package/dist/commands/mail-degraded-e4.test.js +126 -0
  42. package/dist/commands/mail-degraded-e4.test.js.map +1 -1
  43. package/dist/commands/mail.d.ts +19 -1
  44. package/dist/commands/mail.d.ts.map +1 -1
  45. package/dist/commands/mail.js +195 -30
  46. package/dist/commands/mail.js.map +1 -1
  47. package/dist/commands/mail.test.js +291 -3
  48. package/dist/commands/mail.test.js.map +1 -1
  49. package/dist/commands/orient.d.ts.map +1 -1
  50. package/dist/commands/orient.js +82 -0
  51. package/dist/commands/orient.js.map +1 -1
  52. package/dist/commands/orient.test.js +144 -1
  53. package/dist/commands/orient.test.js.map +1 -1
  54. package/dist/commands/seat-cli-wiring.test.d.ts +20 -0
  55. package/dist/commands/seat-cli-wiring.test.d.ts.map +1 -0
  56. package/dist/commands/seat-cli-wiring.test.js +147 -0
  57. package/dist/commands/seat-cli-wiring.test.js.map +1 -0
  58. package/dist/commands/seat-poll-chain.test.d.ts +13 -0
  59. package/dist/commands/seat-poll-chain.test.d.ts.map +1 -0
  60. package/dist/commands/seat-poll-chain.test.js +103 -0
  61. package/dist/commands/seat-poll-chain.test.js.map +1 -0
  62. package/dist/commands/seat.d.ts +92 -0
  63. package/dist/commands/seat.d.ts.map +1 -0
  64. package/dist/commands/seat.js +649 -0
  65. package/dist/commands/seat.js.map +1 -0
  66. package/dist/commands/seat.test.d.ts +19 -0
  67. package/dist/commands/seat.test.d.ts.map +1 -0
  68. package/dist/commands/seat.test.js +532 -0
  69. package/dist/commands/seat.test.js.map +1 -0
  70. package/dist/commands/sessionstart-manifest-contract.test.d.ts +2 -0
  71. package/dist/commands/sessionstart-manifest-contract.test.d.ts.map +1 -0
  72. package/dist/commands/sessionstart-manifest-contract.test.js +176 -0
  73. package/dist/commands/sessionstart-manifest-contract.test.js.map +1 -0
  74. package/dist/hooks/__tests__/auto-context.test.js +20 -0
  75. package/dist/hooks/__tests__/auto-context.test.js.map +1 -1
  76. package/dist/hooks/auto-context.d.ts +19 -0
  77. package/dist/hooks/auto-context.d.ts.map +1 -1
  78. package/dist/hooks/auto-context.js +22 -4
  79. package/dist/hooks/auto-context.js.map +1 -1
  80. package/dist/index.js +71 -0
  81. package/dist/index.js.map +1 -1
  82. package/package.json +2 -2
@@ -54,7 +54,7 @@ export declare const BARE_REF_REGEX_SOURCE = "(?<!\\b[\\w-]+/[\\w-]+)#(\\d+)(?![
54
54
  * both templates start with it, so the constant stays the single source of truth.
55
55
  */
56
56
  export declare const SESSION_START_MARKER = "// [totem] auto-generated";
57
- export declare const GEMINI_SESSION_START = "// [totem] auto-generated \u2014 Gemini CLI SessionStart hook\n// Runs `totem describe` at the start of every Gemini CLI session to emit\n// the project-orientation banner (\"[Describe] Project: ... Lessons: N\n// Targets: N Hooks: ...\"). Matches the family-canonical pattern used by\n// totem-strategy, totem-substrate, arhgap11, and totem-status, and\n// matches the Claude-side SessionStart hook scaffolded by this same init\n// pass (mmnto-ai/totem#1884).\nconst { execSync } = require('child_process');\n\n// totem-status refresh-gh \u2014 GH-federation snapshot refresh (mmnto-ai/totem-status#127\n// C3 residual; tracking mmnto-ai/totem#2556). Spawn-and-forget, detached+unref, and\n// fired BEFORE the synchronous describe/orient briefings so it overlaps them: session\n// start must never block on it (mmnto-ai/totem#2059 measured ~3s of synchronous gh\n// calls here). The verb's exit-0-or-nothing contract (single-flight, atomic rename,\n// no-clobber when gh is missing) makes blind firing safe. ENOENT = the sidecar is not\n// adopted in this repo (the common non-cohort case) \u2014 zero noise; any other spawn\n// failure keeps a non-fatal stderr breadcrumb.\n// PRIMARY checkout only (.git must be a DIRECTORY): in a linked worktree .git is a\n// pointer FILE, and a detached child inheriting the worktree cwd holds a Windows\n// directory lock that breaks worktree removal; the primary's hooks + the daemon\n// cover the workspace-level snapshot (single-flight makes extra fires redundant).\n// A non-git cwd has no refresh moment at all. The stat is cwd-anchored, not a\n// walk-up: both host runtimes launch session hooks with cwd = project root, so a\n// subdirectory cwd (which would skip) does not occur in practice \u2014 and adding a\n// git walk would cost a synchronous process on the very path this block keeps free.\ntry {\n const nodePath = require('path');\n const { statSync } = require('fs');\n let primaryCheckout = false;\n try {\n primaryCheckout = statSync(nodePath.join(process.cwd(), '.git')).isDirectory();\n } catch {\n // not a git checkout (or .git unreadable) \u2014 no refresh moment here\n }\n if (primaryCheckout) {\n const { spawn } = require('child_process');\n // Observability leg (mmnto-ai/totem#2570, routed from the status seat's\n // 2026-08-03 silent no-write): under stdio:'ignore' plus the verb's\n // exit-0-or-nothing contract, a reaped or dying child leaves NO trace\n // (Windows detached is not job-object breakaway \u2014 a hook-harness\n // tree-kill takes the child mid-run). Each firing stamps a workspace-root\n // log and hands the child the same fd, so the verb's own success line\n // lands after the stamp; a stamp with nothing after it means the child\n // never finished. Log failures degrade to the previous blind firing \u2014\n // the stamp must never block or break the spawn.\n const { openSync, closeSync, appendFileSync, existsSync, writeFileSync } = require('fs');\n // REPO-LOCAL log, inside .git (falsification round: the primary-checkout\n // gate just proved .git is a directory; never tracked, dies with the\n // clone, writable wherever git itself writes, and per-repo so concurrent\n // firings from sibling repos never interleave). A workspace-parent path\n // would grow an un-gitignorable file OUTSIDE the repo tree for every\n // consumer of these published templates \u2014 including non-adopters, whose\n // ENOENT firing still stamps.\n const logPath = nodePath.join(process.cwd(), '.git', 'totem-status-refresh-hook.log');\n // Control characters are scrubbed from path-derived fields before they\n // reach the log (terminal-injection guideline: a crafted checkout path\n // must not forge stamp lines or inject terminal controls).\n const scrub = (v) => String(v).replace(/[\\x00-\\x1f\\x7f]/g, '?');\n let stdio = 'ignore';\n let logFd = null;\n try {\n try {\n // 1 MiB self-cap: the log truncates rather than growing forever.\n if (statSync(logPath).size > 1048576) writeFileSync(logPath, '');\n } catch {\n // no log yet \u2014 nothing to cap\n }\n appendFileSync(logPath, '[' + new Date().toISOString() + '] gemini spawn cwd=' + scrub(process.cwd()) + ' path-has-go-bin=' + /go[\\\\/]bin/i.test(process.env.PATH || '') + ' cwd-shadow-exe=' + existsSync(nodePath.join(process.cwd(), 'totem-status.exe')) + '\\n');\n logFd = openSync(logPath, 'a');\n stdio = ['ignore', logFd, logFd];\n } catch {\n // log unavailable \u2014 refresh still fires blind, as before\n }\n const refresh = spawn('totem-status', ['refresh-gh'], {\n detached: true,\n stdio,\n });\n refresh.on('error', (err) => {\n try {\n appendFileSync(logPath, '[' + new Date().toISOString() + '] gemini spawn-error code=' + ((err && err.code) || 'unknown') + '\\n');\n } catch {\n // log write failed \u2014 fall through to the stderr breadcrumb\n }\n if (err && err.code === 'ENOENT') return;\n process.stderr.write('[SessionStart] totem-status refresh-gh spawn failed (non-fatal): ' + (err instanceof Error ? err.message : String(err)) + '\\n');\n });\n refresh.unref();\n // The child holds its own copy of the fd from spawn time; release the parent's.\n if (logFd !== null) {\n try {\n closeSync(logFd);\n } catch {\n // nothing to release\n }\n }\n }\n} catch (err) {\n process.stderr.write('[SessionStart] totem-status refresh-gh unavailable (non-fatal): ' + (err instanceof Error ? err.message : String(err)) + '\\n');\n}\n\ntry {\n execSync('totem describe', {\n timeout: 30000,\n stdio: ['ignore', 'inherit', 'inherit'],\n });\n} catch (err) {\n process.stdout.write('[Totem] Briefing unavailable: ' + (err instanceof Error ? err.message : String(err)) + '\\n');\n}\n\n// totem orient --session \u2014 live derived in-flight state, ADDITIVE to describe\n// (mmnto-ai/totem#2044 PR-3). Own try/catch; orient --session is itself boot-safe.\ntry {\n execSync('totem orient --session', {\n timeout: 30000,\n stdio: ['ignore', 'inherit', 'inherit'],\n });\n} catch (err) {\n // Boot-safe: orient is additive to describe; a failure never blocks session start \u2014\n // surface a NON-fatal breadcrumb (matches the Claude-side hook) rather than swallow.\n process.stderr.write('[SessionStart] orient briefing unavailable (non-fatal): ' + (err instanceof Error ? err.message : String(err)) + '\\n');\n}\n// [totem] end auto-generated\n";
57
+ export declare const GEMINI_SESSION_START = "// [totem] auto-generated \u2014 Gemini CLI SessionStart hook\n// Runs `totem describe` at the start of every Gemini CLI session to emit\n// the project-orientation banner (\"[Describe] Project: ... Lessons: N\n// Targets: N Hooks: ...\"). Matches the family-canonical pattern used by\n// totem-strategy, totem-substrate, arhgap11, and totem-status, and\n// matches the Claude-side SessionStart hook scaffolded by this same init\n// pass (mmnto-ai/totem#1884).\nconst { spawnSync } = require('child_process');\n\n// totem-status refresh-gh \u2014 GH-federation snapshot refresh (mmnto-ai/totem-status#127\n// C3 residual; tracking mmnto-ai/totem#2556). Spawn-and-forget, detached+unref, and\n// fired BEFORE the synchronous describe/orient briefings so it overlaps them: session\n// start must never block on it (mmnto-ai/totem#2059 measured ~3s of synchronous gh\n// calls here). The verb's exit-0-or-nothing contract (single-flight, atomic rename,\n// no-clobber when gh is missing) makes blind firing safe. ENOENT = the sidecar is not\n// adopted in this repo (the common non-cohort case) \u2014 zero noise; any other spawn\n// failure keeps a non-fatal stderr breadcrumb.\n// PRIMARY checkout only (.git must be a DIRECTORY): in a linked worktree .git is a\n// pointer FILE, and a detached child inheriting the worktree cwd holds a Windows\n// directory lock that breaks worktree removal; the primary's hooks + the daemon\n// cover the workspace-level snapshot (single-flight makes extra fires redundant).\n// A non-git cwd has no refresh moment at all. The stat is cwd-anchored, not a\n// walk-up: both host runtimes launch session hooks with cwd = project root, so a\n// subdirectory cwd (which would skip) does not occur in practice \u2014 and adding a\n// git walk would cost a synchronous process on the very path this block keeps free.\ntry {\n const nodePath = require('path');\n const { statSync } = require('fs');\n let primaryCheckout = false;\n try {\n primaryCheckout = statSync(nodePath.join(process.cwd(), '.git')).isDirectory();\n } catch {\n // not a git checkout (or .git unreadable) \u2014 no refresh moment here\n }\n if (primaryCheckout) {\n const { spawn } = require('child_process');\n // Observability leg (mmnto-ai/totem#2570, routed from the status seat's\n // 2026-08-03 silent no-write): under stdio:'ignore' plus the verb's\n // exit-0-or-nothing contract, a reaped or dying child leaves NO trace\n // (Windows detached is not job-object breakaway \u2014 a hook-harness\n // tree-kill takes the child mid-run). Each firing stamps a workspace-root\n // log and hands the child the same fd, so the verb's own success line\n // lands after the stamp; a stamp with nothing after it means the child\n // never finished. Log failures degrade to the previous blind firing \u2014\n // the stamp must never block or break the spawn.\n const { openSync, closeSync, appendFileSync, existsSync, writeFileSync } = require('fs');\n // REPO-LOCAL log, inside .git (falsification round: the primary-checkout\n // gate just proved .git is a directory; never tracked, dies with the\n // clone, writable wherever git itself writes, and per-repo so concurrent\n // firings from sibling repos never interleave). A workspace-parent path\n // would grow an un-gitignorable file OUTSIDE the repo tree for every\n // consumer of these published templates \u2014 including non-adopters, whose\n // ENOENT firing still stamps.\n const logPath = nodePath.join(process.cwd(), '.git', 'totem-status-refresh-hook.log');\n // Control characters are scrubbed from path-derived fields before they\n // reach the log (terminal-injection guideline: a crafted checkout path\n // must not forge stamp lines or inject terminal controls).\n const scrub = (v) => String(v).replace(/[\\x00-\\x1f\\x7f]/g, '?');\n let stdio = 'ignore';\n let logFd = null;\n try {\n try {\n // 1 MiB self-cap: the log truncates rather than growing forever.\n if (statSync(logPath).size > 1048576) writeFileSync(logPath, '');\n } catch {\n // no log yet \u2014 nothing to cap\n }\n appendFileSync(logPath, '[' + new Date().toISOString() + '] gemini spawn cwd=' + scrub(process.cwd()) + ' path-has-go-bin=' + /go[\\\\/]bin/i.test(process.env.PATH || '') + ' cwd-shadow-exe=' + existsSync(nodePath.join(process.cwd(), 'totem-status.exe')) + '\\n');\n logFd = openSync(logPath, 'a');\n stdio = ['ignore', logFd, logFd];\n } catch {\n // log unavailable \u2014 refresh still fires blind, as before\n }\n const refresh = spawn('totem-status', ['refresh-gh'], {\n detached: true,\n stdio,\n });\n refresh.on('error', (err) => {\n try {\n appendFileSync(logPath, '[' + new Date().toISOString() + '] gemini spawn-error code=' + ((err && err.code) || 'unknown') + '\\n');\n } catch {\n // log write failed \u2014 fall through to the stderr breadcrumb\n }\n if (err && err.code === 'ENOENT') return;\n process.stderr.write('[SessionStart] totem-status refresh-gh spawn failed (non-fatal): ' + (err instanceof Error ? err.message : String(err)) + '\\n');\n });\n refresh.unref();\n // The child holds its own copy of the fd from spawn time; release the parent's.\n if (logFd !== null) {\n try {\n closeSync(logFd);\n } catch {\n // nothing to release\n }\n }\n }\n} catch (err) {\n process.stderr.write('[SessionStart] totem-status refresh-gh unavailable (non-fatal): ' + (err instanceof Error ? err.message : String(err)) + '\\n');\n}\n\n// \u2500\u2500\u2500 A.3.a: mint session ID + log session_start event \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// New with mmnto-ai/totem#2468: this template never took over the A.3.a duty\n// its Claude sibling carries, so Gemini-seat sessions had no session UUID and\n// no session_start denominator row \u2014 the selection-manifest join key and the\n// recorded-absence contract both need them. Same shape as the Claude template.\n// Fire-and-forget: a ledger failure must NOT block the briefing.\nlet mintedSessionId = null;\ntry {\n const nodePath = require('path');\n const { mkdirSync, writeFileSync, appendFileSync } = require('fs');\n const { randomUUID } = require('crypto');\n const ledgerDir = nodePath.join(process.cwd(), '.totem', 'ledger');\n mkdirSync(ledgerDir, { recursive: true });\n mintedSessionId = randomUUID();\n writeFileSync(nodePath.join(ledgerDir, '.session-id'), mintedSessionId, 'utf-8');\n const selfAgentEntry = (process.env.TOTEM_SELF_AGENT || '')\n .split(',')\n .map((s) => s.trim())\n .find((s) => s.length > 0);\n const event = {\n timestamp: new Date().toISOString(),\n type: 'session_start',\n activity_name: 'SessionStart',\n source: 'bot',\n ...(selfAgentEntry ? { agent_source: selfAgentEntry } : {}),\n justification: '',\n session_id: mintedSessionId,\n };\n appendFileSync(nodePath.join(ledgerDir, 'events.ndjson'), JSON.stringify(event) + '\\n', 'utf-8');\n} catch (err) {\n process.stderr.write(\n '[SessionStart] session-start telemetry unavailable (non-fatal): ' +\n (err instanceof Error ? err.message : String(err)) +\n '\\n',\n );\n}\n\n// Interactive Gemini ingests SessionStart CONTEXT only from the\n// hookSpecificOutput.additionalContext envelope \u2014 plain exit-0 stdout wraps as\n// systemMessage, which the interactive startup consumer never injects, so the\n// briefing was absent from model context in the primary dev flow even once\n// registered (mmnto-ai/totem#2613; leg-verified against @google/gemini-cli\n// 0.54.4). systemMessage rides alongside the envelope for the human surfaces:\n// interactive startup and /clear render it as a UI info item and -p echoes it\n// to stderr \u2014 so the briefing is VISIBLE to the human on those surfaces and\n// injected as context for the model (one payload, both audiences).\n// The Totem CLI writes its banner and diagnostics to STDERR, so capture takes\n// BOTH streams \u2014 the same seam the Claude-side template documents; a\n// stdout-only capture silently drops the describe leg (mmnto-ai/totem#2613\n// falsification round). A leg failure carries any partial stdout plus the\n// fail-soft note; exit is ALWAYS 0 (never blocks boot).\n// Per-leg 20s budgets cut the measured worst-case process exit from 60s to\n// 40s against Gemini's 60s DEFAULT_HOOK_TIMEOUT (which tree-kills at expiry;\n// no descendant inherits this hook's own streams).\nlet briefing = '';\ntry {\n const describeRun = spawnSync('totem describe', {\n shell: true,\n timeout: 20000,\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n // spawnSync sets .error (it does NOT throw) on spawn-level failure/timeout.\n briefing += describeRun.stdout || '';\n if (describeRun.error || describeRun.status !== 0) {\n const reason = describeRun.error\n ? (describeRun.error.message || String(describeRun.error))\n : ((describeRun.stderr || '').trim() || 'totem describe exited ' + describeRun.status);\n briefing += '[Totem] Briefing unavailable: ' + reason + '\\n';\n } else {\n briefing += describeRun.stderr || '';\n }\n} catch (err) {\n // Belt for a genuinely throwing spawnSync: same fail-soft note.\n briefing += '[Totem] Briefing unavailable: ' + (err instanceof Error ? err.message : String(err)) + '\\n';\n}\n\n// Selection-manifest block boundary (mmnto-ai/totem#2468): everything in\n// `briefing` up to here is the describe leg \u2014 including its fail-soft note,\n// which IS injected payload when it fires.\nconst describeBriefingEnd = briefing.length;\n\n// totem orient --session \u2014 live derived in-flight state, ADDITIVE to describe\n// (mmnto-ai/totem#2044 PR-3). Own try/catch; orient --session is itself boot-safe.\ntry {\n const orientRun = spawnSync('totem orient --session', {\n shell: true,\n timeout: 20000,\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n briefing += orientRun.stdout || '';\n if (orientRun.error || orientRun.status !== 0) {\n const orientReason = orientRun.error\n ? (orientRun.error.message || String(orientRun.error))\n : ((orientRun.stderr || '').trim() || 'totem orient exited ' + orientRun.status);\n // Boot-safe: orient is additive to describe; a failure never blocks session\n // start. The note rides the briefing (both keys) so the model and the human\n // both see the orient gap \u2014 a stderr-only note is invisible to the model\n // (CR round on this PR); the parent-stderr breadcrumb stays for hook\n // diagnostics.\n briefing += '[Totem] Orient briefing unavailable: ' + orientReason + '\\n';\n process.stderr.write('[SessionStart] orient briefing unavailable (non-fatal): ' + orientReason + '\\n');\n } else {\n briefing += orientRun.stderr || '';\n }\n} catch (err) {\n const orientMsg = err instanceof Error ? err.message : String(err);\n briefing += '[Totem] Orient briefing unavailable: ' + orientMsg + '\\n';\n process.stderr.write('[SessionStart] orient briefing unavailable (non-fatal): ' + orientMsg + '\\n');\n}\n\n// \u2500\u2500\u2500 selection manifest (mmnto-ai/totem#2468 M1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Inline append mirroring the A.3.a write above \u2014 this rendered hook runs\n// standalone in consumer repos with no access to @mmnto/totem's writer. The\n// row shape is BOUND to SelectionManifestRowSchema (strict): change both in\n// the same PR; the template contract test parses this row with the real\n// schema. A zero-byte block never becomes a candidate (nothing was injected).\ntry {\n const nodePath = require('path');\n const { appendFileSync } = require('fs');\n const { createHash } = require('crypto');\n const measure = (id, content, reason) => {\n const bytes = Buffer.byteLength(content, 'utf-8');\n return {\n id,\n disposition: 'selected',\n reason,\n bytes,\n approxTokens: Math.ceil(bytes / 4),\n fingerprint: createHash('sha256').update(content, 'utf-8').digest('hex').slice(0, 16),\n };\n };\n const selfAgent = (process.env.TOTEM_SELF_AGENT || '')\n .split(',')\n .map((s) => s.trim())\n .find((s) => s.length > 0);\n const row = {\n schemaVersion: 1,\n timestamp: new Date().toISOString(),\n emitter: 'session-start',\n ...(mintedSessionId ? { session_id: mintedSessionId } : {}),\n ...(selfAgent ? { agent_source: selfAgent } : {}),\n context: { template: 'gemini-managed' },\n universe: 'managed-template blocks: describe + orient --session',\n costBasis: { bytes: 'utf8-length', approxTokens: 'ceil(bytes/4) approximation' },\n candidates: [\n measure('describe', briefing.slice(0, describeBriefingEnd), 'always-injected briefing'),\n measure('orient:session-block', briefing.slice(describeBriefingEnd), 'always-injected briefing'),\n ].filter((c) => c.bytes > 0),\n warnings: [],\n };\n appendFileSync(\n nodePath.join(process.cwd(), '.totem', 'ledger', 'selection-manifests.ndjson'),\n JSON.stringify(row) + '\\n',\n 'utf-8',\n );\n} catch (err) {\n process.stderr.write(\n '[SessionStart] selection manifest unavailable (non-fatal): ' +\n (err instanceof Error ? err.message : String(err)) +\n '\\n',\n );\n}\n\nprocess.stdout.write(JSON.stringify({\n systemMessage: briefing,\n hookSpecificOutput: { hookEventName: 'SessionStart', additionalContext: briefing },\n}) + '\\n');\n// [totem] end auto-generated\n";
58
58
  export declare const GEMINI_BEFORE_TOOL: string;
59
59
  export declare const GEMINI_SKILL = "<!-- [totem] auto-generated \u2014 Totem Architect skill -->\n# Totem Architect\n\nBefore designing, planning, or implementing features, query the project's memory index for relevant context:\n\n1. Use the `search_knowledge` MCP tool with a query describing what you're about to build.\n2. Review returned lessons, specs, and code patterns before writing any code.\n3. If you discover a trap or architectural constraint, factor it into your design.\n\nThis ensures you build on existing knowledge rather than repeating past mistakes.\n";
60
60
  export declare const CLAUDE_SHIELD_GATE = "// [totem] auto-generated \u2014 Claude Code review gate hook\n// Intercepts git push/commit to run `totem review` before proceeding.\nconst { execSync } = require('child_process');\n\nconst input = process.env.TOOL_INPUT || '';\nif (/\bgits+(push|commit)\b/.test(input)) {\n try {\n execSync('totem lint', { encoding: 'utf-8', timeout: 60000, stdio: 'inherit' });\n } catch (err) {\n process.exit(1);\n }\n}\n";
@@ -73,7 +73,7 @@ export declare const CLAUDE_PREWRITESHIELD_ENTRY: {
73
73
  command: string;
74
74
  }[];
75
75
  };
76
- export declare const CLAUDE_SESSION_START = "// [totem] auto-generated \u2014 Claude Code SessionStart hook\n// Runs `@mmnto/cli describe` at the start of every Claude Code session.\n// Mirrors `.gemini/hooks/SessionStart.cjs`. `.cjs` extension because\n// package.json may have \"type\": \"module\" \u2014 Claude Code execs hooks via\n// plain `node`, which would otherwise treat `.js` as ESM.\n//\n// A.3.a: mints a session UUID, persists to .totem/ledger/.session-id,\n// and appends a `session_start` event to .totem/ledger/events.ndjson\n// BEFORE running `totem describe`. Subsequent MCP calls within the\n// session correlate via session_id (ADR-029 \u00A7 Session Heuristic).\n// Fire-and-forget: any ledger failure must NOT block the briefing.\nconst { spawnSync } = require('child_process');\nconst { existsSync, mkdirSync, writeFileSync, appendFileSync } = require('fs');\nconst { randomUUID } = require('crypto');\nconst { join } = require('path');\n\n// \u2500\u2500\u2500 A.3.a: mint session ID + log session_start event \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ntry {\n const ledgerDir = join(process.cwd(), '.totem', 'ledger');\n mkdirSync(ledgerDir, { recursive: true });\n const sessionId = randomUUID();\n writeFileSync(join(ledgerDir, '.session-id'), sessionId, 'utf-8');\n // Amended ADR-078 (2026-07-15): agent_source is the env-carried seat-id\n // (TOTEM_SELF_AGENT, first non-empty comma entry), never a vendor class\n // ('claude' has no reverse projection to a seat). Omitted entirely when\n // the env var is absent: stamp absence, never guess (Tenet 4). The parse\n // deliberately mirrors deriveSearchLogAttribution (packages/mcp/src/\n // search-log.ts) and parseEnvAgentList (packages/core/src/\n // orchestration-resolver.ts) \u2014 inlined because this rendered .cjs hook\n // runs standalone in consumer repos with no access to those modules; if\n // the shared parse semantics change, change this template in the same PR.\n const selfAgent = (process.env.TOTEM_SELF_AGENT || '')\n .split(',')\n .map((s) => s.trim())\n .find((s) => s.length > 0);\n const event = {\n timestamp: new Date().toISOString(),\n type: 'session_start',\n activity_name: 'SessionStart',\n source: 'bot',\n ...(selfAgent ? { agent_source: selfAgent } : {}),\n justification: '',\n session_id: sessionId,\n };\n appendFileSync(join(ledgerDir, 'events.ndjson'), JSON.stringify(event) + '\\n', 'utf-8');\n} catch (err) {\n // Fire-and-forget; ledger failures must not block the briefing. A lightweight\n // stderr breadcrumb makes hook misconfigurations diagnosable in consumer repos\n // (CR R1 catch \u2014 empty catch suppresses all signal). stderr (not stdout) so\n // the briefing path remains clean for Claude's prompt context.\n process.stderr.write(\n '[SessionStart] Session-start telemetry unavailable (non-fatal): ' +\n (err instanceof Error ? err.message : String(err)) +\n '\\n',\n );\n}\n\n// \u2500\u2500\u2500 totem-status refresh-gh \u2014 GH-federation snapshot refresh \u2500\u2500\u2500\n// (mmnto-ai/totem-status#127 C3 residual; tracking mmnto-ai/totem#2556.)\n// Spawn-and-forget, detached+unref, fired BEFORE the synchronous describe/orient\n// briefings so it overlaps them: session start must never block on it\n// (mmnto-ai/totem#2059 measured ~3s of synchronous gh calls here). The verb's\n// exit-0-or-nothing contract (single-flight, atomic rename, no-clobber when gh\n// is missing) makes blind firing safe. ENOENT = the sidecar is not adopted in\n// this repo (the common non-cohort case) \u2014 zero noise; any other spawn failure\n// keeps a non-fatal stderr breadcrumb.\n// PRIMARY checkout only (.git must be a DIRECTORY): in a linked worktree .git is a\n// pointer FILE, and a detached child inheriting the worktree cwd holds a Windows\n// directory lock that breaks worktree removal; the primary's hooks + the daemon\n// cover the workspace-level snapshot (single-flight makes extra fires redundant).\n// A non-git cwd has no refresh moment at all. The stat is cwd-anchored, not a\n// walk-up: both host runtimes launch session hooks with cwd = project root, so a\n// subdirectory cwd (which would skip) does not occur in practice \u2014 and adding a\n// git walk would cost a synchronous process on the very path this block keeps free.\ntry {\n const nodePath = require('path');\n const { statSync } = require('fs');\n let primaryCheckout = false;\n try {\n primaryCheckout = statSync(nodePath.join(process.cwd(), '.git')).isDirectory();\n } catch {\n // not a git checkout (or .git unreadable) \u2014 no refresh moment here\n }\n if (primaryCheckout) {\n const { spawn } = require('child_process');\n // Observability leg (mmnto-ai/totem#2570, routed from the status seat's\n // 2026-08-03 silent no-write): under stdio:'ignore' plus the verb's\n // exit-0-or-nothing contract, a reaped or dying child leaves NO trace\n // (Windows detached is not job-object breakaway \u2014 a hook-harness\n // tree-kill takes the child mid-run). Each firing stamps a workspace-root\n // log and hands the child the same fd, so the verb's own success line\n // lands after the stamp; a stamp with nothing after it means the child\n // never finished. Log failures degrade to the previous blind firing \u2014\n // the stamp must never block or break the spawn.\n const { openSync, closeSync, appendFileSync, existsSync, writeFileSync } = require('fs');\n // REPO-LOCAL log, inside .git (falsification round: the primary-checkout\n // gate just proved .git is a directory; never tracked, dies with the\n // clone, writable wherever git itself writes, and per-repo so concurrent\n // firings from sibling repos never interleave). A workspace-parent path\n // would grow an un-gitignorable file OUTSIDE the repo tree for every\n // consumer of these published templates \u2014 including non-adopters, whose\n // ENOENT firing still stamps.\n const logPath = nodePath.join(process.cwd(), '.git', 'totem-status-refresh-hook.log');\n // Control characters are scrubbed from path-derived fields before they\n // reach the log (terminal-injection guideline: a crafted checkout path\n // must not forge stamp lines or inject terminal controls).\n const scrub = (v) => String(v).replace(/[\\x00-\\x1f\\x7f]/g, '?');\n let stdio = 'ignore';\n let logFd = null;\n try {\n try {\n // 1 MiB self-cap: the log truncates rather than growing forever.\n if (statSync(logPath).size > 1048576) writeFileSync(logPath, '');\n } catch {\n // no log yet \u2014 nothing to cap\n }\n appendFileSync(logPath, '[' + new Date().toISOString() + '] claude spawn cwd=' + scrub(process.cwd()) + ' path-has-go-bin=' + /go[\\\\/]bin/i.test(process.env.PATH || '') + ' cwd-shadow-exe=' + existsSync(nodePath.join(process.cwd(), 'totem-status.exe')) + '\\n');\n logFd = openSync(logPath, 'a');\n stdio = ['ignore', logFd, logFd];\n } catch {\n // log unavailable \u2014 refresh still fires blind, as before\n }\n const refresh = spawn('totem-status', ['refresh-gh'], {\n detached: true,\n stdio,\n });\n refresh.on('error', (err) => {\n try {\n appendFileSync(logPath, '[' + new Date().toISOString() + '] claude spawn-error code=' + ((err && err.code) || 'unknown') + '\\n');\n } catch {\n // log write failed \u2014 fall through to the stderr breadcrumb\n }\n if (err && err.code === 'ENOENT') return;\n process.stderr.write('[SessionStart] totem-status refresh-gh spawn failed (non-fatal): ' + (err instanceof Error ? err.message : String(err)) + '\\n');\n });\n refresh.unref();\n // The child holds its own copy of the fd from spawn time; release the parent's.\n if (logFd !== null) {\n try {\n closeSync(logFd);\n } catch {\n // nothing to release\n }\n }\n }\n} catch (err) {\n process.stderr.write('[SessionStart] totem-status refresh-gh unavailable (non-fatal): ' + (err instanceof Error ? err.message : String(err)) + '\\n');\n}\n\n// \u2500\u2500\u2500 totem describe briefing (existing behavior) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ntry {\n const cliPath = join(process.cwd(), 'node_modules', '@mmnto', 'cli', 'dist', 'index.js');\n if (existsSync(cliPath)) {\n const result = spawnSync(process.execPath, [cliPath, 'describe'], {\n encoding: 'utf-8',\n timeout: 30000,\n });\n if (result.error) {\n throw result.error;\n }\n // Totem CLI writes diagnostic output to stderr; route to stdout so the\n // session-start context lands in Claude's prompt rather than user-visible noise.\n process.stdout.write((result.stdout || '') + (result.stderr || ''));\n } else {\n process.stdout.write(\n '[Totem] @mmnto/cli not installed. Run `pnpm install` (or your package manager equivalent) to enable session-start orientation.\\n',\n );\n }\n} catch (err) {\n process.stdout.write(\n '[Totem] Briefing unavailable: ' +\n (err instanceof Error ? err.message : String(err)) +\n '\\n',\n );\n}\n\n// \u2500\u2500\u2500 totem orient --session \u2014 live derived in-flight state (mmnto-ai/totem#2044 PR-3) \u2500\u2500\n// ADDITIVE to describe (Tenet 13: describe = static identity sensor \u2014 scope/tier/\n// counts; orient = live in-flight sensor \u2014 open PRs/issues/board/freeze). Append,\n// never replace. Its OWN try/catch so an orient failure never disturbs the describe\n// briefing or the boot; `orient --session` is itself boot-safe (emits nothing when\n// nothing is high-signal, never exits non-zero, degrades to honest \"could not derive\").\ntry {\n const orientCliPath = join(process.cwd(), 'node_modules', '@mmnto', 'cli', 'dist', 'index.js');\n if (existsSync(orientCliPath)) {\n const orientResult = spawnSync(process.execPath, [orientCliPath, 'orient', '--session'], {\n encoding: 'utf-8',\n timeout: 30000,\n });\n // spawnSync sets .error (it does NOT throw) on a spawn-level failure; re-throw so\n // it surfaces through the catch breadcrumb below rather than writing '' silently.\n if (orientResult.error) {\n throw orientResult.error;\n }\n process.stdout.write((orientResult.stdout || '') + (orientResult.stderr || ''));\n }\n} catch (err) {\n // Boot-safe: orient is additive to describe (already emitted), so a failure never\n // blocks session start \u2014 but surface a NON-fatal breadcrumb to stderr (not stdout,\n // to keep the prompt clean) for debuggability rather than swallowing silently.\n process.stderr.write(\n '[SessionStart] orient briefing unavailable (non-fatal): ' +\n (err instanceof Error ? err.message : String(err)) +\n '\\n',\n );\n}\n// [totem] end auto-generated\n";
76
+ export declare const CLAUDE_SESSION_START = "// [totem] auto-generated \u2014 Claude Code SessionStart hook\n// Runs `@mmnto/cli describe` at the start of every Claude Code session.\n// Mirrors `.gemini/hooks/SessionStart.cjs`. `.cjs` extension because\n// package.json may have \"type\": \"module\" \u2014 Claude Code execs hooks via\n// plain `node`, which would otherwise treat `.js` as ESM.\n//\n// A.3.a: mints a session UUID, persists to .totem/ledger/.session-id,\n// and appends a `session_start` event to .totem/ledger/events.ndjson\n// BEFORE running `totem describe`. Subsequent MCP calls within the\n// session correlate via session_id (ADR-029 \u00A7 Session Heuristic).\n// Fire-and-forget: any ledger failure must NOT block the briefing.\nconst { spawnSync } = require('child_process');\nconst { existsSync, mkdirSync, writeFileSync, appendFileSync } = require('fs');\nconst { randomUUID } = require('crypto');\nconst { join } = require('path');\n\n// \u2500\u2500\u2500 A.3.a: mint session ID + log session_start event \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Hoisted so the selection-manifest row below (mmnto-ai/totem#2468) can carry\n// the same session UUID as its join key.\nlet mintedSessionId = null;\ntry {\n const ledgerDir = join(process.cwd(), '.totem', 'ledger');\n mkdirSync(ledgerDir, { recursive: true });\n const sessionId = randomUUID();\n mintedSessionId = sessionId;\n writeFileSync(join(ledgerDir, '.session-id'), sessionId, 'utf-8');\n // Amended ADR-078 (2026-07-15): agent_source is the env-carried seat-id\n // (TOTEM_SELF_AGENT, first non-empty comma entry), never a vendor class\n // ('claude' has no reverse projection to a seat). Omitted entirely when\n // the env var is absent: stamp absence, never guess (Tenet 4). The parse\n // deliberately mirrors deriveSearchLogAttribution (packages/mcp/src/\n // search-log.ts) and parseEnvAgentList (packages/core/src/\n // orchestration-resolver.ts) \u2014 inlined because this rendered .cjs hook\n // runs standalone in consumer repos with no access to those modules; if\n // the shared parse semantics change, change this template in the same PR.\n const selfAgent = (process.env.TOTEM_SELF_AGENT || '')\n .split(',')\n .map((s) => s.trim())\n .find((s) => s.length > 0);\n const event = {\n timestamp: new Date().toISOString(),\n type: 'session_start',\n activity_name: 'SessionStart',\n source: 'bot',\n ...(selfAgent ? { agent_source: selfAgent } : {}),\n justification: '',\n session_id: sessionId,\n };\n appendFileSync(join(ledgerDir, 'events.ndjson'), JSON.stringify(event) + '\\n', 'utf-8');\n} catch (err) {\n // Fire-and-forget; ledger failures must not block the briefing. A lightweight\n // stderr breadcrumb makes hook misconfigurations diagnosable in consumer repos\n // (CR R1 catch \u2014 empty catch suppresses all signal). stderr (not stdout) so\n // the briefing path remains clean for Claude's prompt context.\n process.stderr.write(\n '[SessionStart] Session-start telemetry unavailable (non-fatal): ' +\n (err instanceof Error ? err.message : String(err)) +\n '\\n',\n );\n}\n\n// \u2500\u2500\u2500 totem-status refresh-gh \u2014 GH-federation snapshot refresh \u2500\u2500\u2500\n// (mmnto-ai/totem-status#127 C3 residual; tracking mmnto-ai/totem#2556.)\n// Spawn-and-forget, detached+unref, fired BEFORE the synchronous describe/orient\n// briefings so it overlaps them: session start must never block on it\n// (mmnto-ai/totem#2059 measured ~3s of synchronous gh calls here). The verb's\n// exit-0-or-nothing contract (single-flight, atomic rename, no-clobber when gh\n// is missing) makes blind firing safe. ENOENT = the sidecar is not adopted in\n// this repo (the common non-cohort case) \u2014 zero noise; any other spawn failure\n// keeps a non-fatal stderr breadcrumb.\n// PRIMARY checkout only (.git must be a DIRECTORY): in a linked worktree .git is a\n// pointer FILE, and a detached child inheriting the worktree cwd holds a Windows\n// directory lock that breaks worktree removal; the primary's hooks + the daemon\n// cover the workspace-level snapshot (single-flight makes extra fires redundant).\n// A non-git cwd has no refresh moment at all. The stat is cwd-anchored, not a\n// walk-up: both host runtimes launch session hooks with cwd = project root, so a\n// subdirectory cwd (which would skip) does not occur in practice \u2014 and adding a\n// git walk would cost a synchronous process on the very path this block keeps free.\ntry {\n const nodePath = require('path');\n const { statSync } = require('fs');\n let primaryCheckout = false;\n try {\n primaryCheckout = statSync(nodePath.join(process.cwd(), '.git')).isDirectory();\n } catch {\n // not a git checkout (or .git unreadable) \u2014 no refresh moment here\n }\n if (primaryCheckout) {\n const { spawn } = require('child_process');\n // Observability leg (mmnto-ai/totem#2570, routed from the status seat's\n // 2026-08-03 silent no-write): under stdio:'ignore' plus the verb's\n // exit-0-or-nothing contract, a reaped or dying child leaves NO trace\n // (Windows detached is not job-object breakaway \u2014 a hook-harness\n // tree-kill takes the child mid-run). Each firing stamps a workspace-root\n // log and hands the child the same fd, so the verb's own success line\n // lands after the stamp; a stamp with nothing after it means the child\n // never finished. Log failures degrade to the previous blind firing \u2014\n // the stamp must never block or break the spawn.\n const { openSync, closeSync, appendFileSync, existsSync, writeFileSync } = require('fs');\n // REPO-LOCAL log, inside .git (falsification round: the primary-checkout\n // gate just proved .git is a directory; never tracked, dies with the\n // clone, writable wherever git itself writes, and per-repo so concurrent\n // firings from sibling repos never interleave). A workspace-parent path\n // would grow an un-gitignorable file OUTSIDE the repo tree for every\n // consumer of these published templates \u2014 including non-adopters, whose\n // ENOENT firing still stamps.\n const logPath = nodePath.join(process.cwd(), '.git', 'totem-status-refresh-hook.log');\n // Control characters are scrubbed from path-derived fields before they\n // reach the log (terminal-injection guideline: a crafted checkout path\n // must not forge stamp lines or inject terminal controls).\n const scrub = (v) => String(v).replace(/[\\x00-\\x1f\\x7f]/g, '?');\n let stdio = 'ignore';\n let logFd = null;\n try {\n try {\n // 1 MiB self-cap: the log truncates rather than growing forever.\n if (statSync(logPath).size > 1048576) writeFileSync(logPath, '');\n } catch {\n // no log yet \u2014 nothing to cap\n }\n appendFileSync(logPath, '[' + new Date().toISOString() + '] claude spawn cwd=' + scrub(process.cwd()) + ' path-has-go-bin=' + /go[\\\\/]bin/i.test(process.env.PATH || '') + ' cwd-shadow-exe=' + existsSync(nodePath.join(process.cwd(), 'totem-status.exe')) + '\\n');\n logFd = openSync(logPath, 'a');\n stdio = ['ignore', logFd, logFd];\n } catch {\n // log unavailable \u2014 refresh still fires blind, as before\n }\n const refresh = spawn('totem-status', ['refresh-gh'], {\n detached: true,\n stdio,\n });\n refresh.on('error', (err) => {\n try {\n appendFileSync(logPath, '[' + new Date().toISOString() + '] claude spawn-error code=' + ((err && err.code) || 'unknown') + '\\n');\n } catch {\n // log write failed \u2014 fall through to the stderr breadcrumb\n }\n if (err && err.code === 'ENOENT') return;\n process.stderr.write('[SessionStart] totem-status refresh-gh spawn failed (non-fatal): ' + (err instanceof Error ? err.message : String(err)) + '\\n');\n });\n refresh.unref();\n // The child holds its own copy of the fd from spawn time; release the parent's.\n if (logFd !== null) {\n try {\n closeSync(logFd);\n } catch {\n // nothing to release\n }\n }\n }\n} catch (err) {\n process.stderr.write('[SessionStart] totem-status refresh-gh unavailable (non-fatal): ' + (err instanceof Error ? err.message : String(err)) + '\\n');\n}\n\n// \u2500\u2500\u2500 totem describe briefing (existing behavior) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Captured (mmnto-ai/totem#2468): the injected block is the selection-manifest\n// candidate below \u2014 the not-installed notice is a notice, not a briefing.\nlet describeText = '';\ntry {\n const cliPath = join(process.cwd(), 'node_modules', '@mmnto', 'cli', 'dist', 'index.js');\n if (existsSync(cliPath)) {\n const result = spawnSync(process.execPath, [cliPath, 'describe'], {\n encoding: 'utf-8',\n timeout: 30000,\n });\n if (result.error) {\n throw result.error;\n }\n // Totem CLI writes diagnostic output to stderr; route to stdout so the\n // session-start context lands in Claude's prompt rather than user-visible noise.\n describeText = (result.stdout || '') + (result.stderr || '');\n process.stdout.write(describeText);\n } else {\n process.stdout.write(\n '[Totem] @mmnto/cli not installed. Run `pnpm install` (or your package manager equivalent) to enable session-start orientation.\\n',\n );\n }\n} catch (err) {\n process.stdout.write(\n '[Totem] Briefing unavailable: ' +\n (err instanceof Error ? err.message : String(err)) +\n '\\n',\n );\n}\n\n// \u2500\u2500\u2500 totem orient --session \u2014 live derived in-flight state (mmnto-ai/totem#2044 PR-3) \u2500\u2500\n// ADDITIVE to describe (Tenet 13: describe = static identity sensor \u2014 scope/tier/\n// counts; orient = live in-flight sensor \u2014 open PRs/issues/board/freeze). Append,\n// never replace. Its OWN try/catch so an orient failure never disturbs the describe\n// briefing or the boot; `orient --session` is itself boot-safe (emits nothing when\n// nothing is high-signal, never exits non-zero, degrades to honest \"could not derive\").\nlet orientText = '';\ntry {\n const orientCliPath = join(process.cwd(), 'node_modules', '@mmnto', 'cli', 'dist', 'index.js');\n if (existsSync(orientCliPath)) {\n const orientResult = spawnSync(process.execPath, [orientCliPath, 'orient', '--session'], {\n encoding: 'utf-8',\n timeout: 30000,\n });\n // spawnSync sets .error (it does NOT throw) on a spawn-level failure; re-throw so\n // it surfaces through the catch breadcrumb below rather than writing '' silently.\n if (orientResult.error) {\n throw orientResult.error;\n }\n orientText = (orientResult.stdout || '') + (orientResult.stderr || '');\n process.stdout.write(orientText);\n }\n} catch (err) {\n // Boot-safe: orient is additive to describe (already emitted), so a failure never\n // blocks session start \u2014 but surface a NON-fatal breadcrumb to stderr (not stdout,\n // to keep the prompt clean) for debuggability rather than swallowing silently.\n process.stderr.write(\n '[SessionStart] orient briefing unavailable (non-fatal): ' +\n (err instanceof Error ? err.message : String(err)) +\n '\\n',\n );\n}\n\n// \u2500\u2500\u2500 selection manifest (mmnto-ai/totem#2468 M1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Inline append mirroring the session_start write above \u2014 this rendered hook\n// runs standalone in consumer repos with no access to @mmnto/totem's writer.\n// The row shape is BOUND to SelectionManifestRowSchema (strict): change both\n// in the same PR; the template contract test parses this row with the real\n// schema. A zero-byte block never becomes a candidate (nothing was injected).\ntry {\n const { createHash } = require('crypto');\n const measure = (id, content, reason) => {\n const bytes = Buffer.byteLength(content, 'utf-8');\n return {\n id,\n disposition: 'selected',\n reason,\n bytes,\n approxTokens: Math.ceil(bytes / 4),\n fingerprint: createHash('sha256').update(content, 'utf-8').digest('hex').slice(0, 16),\n };\n };\n const selfAgent = (process.env.TOTEM_SELF_AGENT || '')\n .split(',')\n .map((s) => s.trim())\n .find((s) => s.length > 0);\n const row = {\n schemaVersion: 1,\n timestamp: new Date().toISOString(),\n emitter: 'session-start',\n ...(mintedSessionId ? { session_id: mintedSessionId } : {}),\n ...(selfAgent ? { agent_source: selfAgent } : {}),\n context: { template: 'claude-managed' },\n universe: 'managed-template blocks: describe + orient --session',\n costBasis: { bytes: 'utf8-length', approxTokens: 'ceil(bytes/4) approximation' },\n candidates: [\n measure('describe', describeText, 'always-injected briefing'),\n measure('orient:session-block', orientText, 'always-injected briefing'),\n ].filter((c) => c.bytes > 0),\n warnings: [],\n };\n appendFileSync(\n join(process.cwd(), '.totem', 'ledger', 'selection-manifests.ndjson'),\n JSON.stringify(row) + '\\n',\n 'utf-8',\n );\n} catch (err) {\n process.stderr.write(\n '[SessionStart] selection manifest unavailable (non-fatal): ' +\n (err instanceof Error ? err.message : String(err)) +\n '\\n',\n );\n}\n// [totem] end auto-generated\n";
77
77
  export declare const CLAUDE_SESSION_START_ENTRY: {
78
78
  hooks: {
79
79
  type: string;
@@ -1 +1 @@
1
- {"version":3,"file":"init-templates.d.ts","sourceRoot":"","sources":["../../src/commands/init-templates.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init-templates.d.ts","sourceRoot":"","sources":["../../src/commands/init-templates.ts"],"names":[],"mappings":"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"}
@@ -158,7 +158,7 @@ export const GEMINI_SESSION_START = `// [totem] auto-generated — Gemini CLI Se
158
158
  // totem-strategy, totem-substrate, arhgap11, and totem-status, and
159
159
  // matches the Claude-side SessionStart hook scaffolded by this same init
160
160
  // pass (mmnto-ai/totem#1884).
161
- const { execSync } = require('child_process');
161
+ const { spawnSync } = require('child_process');
162
162
 
163
163
  // totem-status refresh-gh — GH-federation snapshot refresh (mmnto-ai/totem-status#127
164
164
  // C3 residual; tracking mmnto-ai/totem#2556). Spawn-and-forget, detached+unref, and
@@ -251,27 +251,175 @@ try {
251
251
  process.stderr.write('[SessionStart] totem-status refresh-gh unavailable (non-fatal): ' + (err instanceof Error ? err.message : String(err)) + '\\n');
252
252
  }
253
253
 
254
+ // ─── A.3.a: mint session ID + log session_start event ──────────
255
+ // New with mmnto-ai/totem#2468: this template never took over the A.3.a duty
256
+ // its Claude sibling carries, so Gemini-seat sessions had no session UUID and
257
+ // no session_start denominator row — the selection-manifest join key and the
258
+ // recorded-absence contract both need them. Same shape as the Claude template.
259
+ // Fire-and-forget: a ledger failure must NOT block the briefing.
260
+ let mintedSessionId = null;
254
261
  try {
255
- execSync('totem describe', {
256
- timeout: 30000,
257
- stdio: ['ignore', 'inherit', 'inherit'],
262
+ const nodePath = require('path');
263
+ const { mkdirSync, writeFileSync, appendFileSync } = require('fs');
264
+ const { randomUUID } = require('crypto');
265
+ const ledgerDir = nodePath.join(process.cwd(), '.totem', 'ledger');
266
+ mkdirSync(ledgerDir, { recursive: true });
267
+ mintedSessionId = randomUUID();
268
+ writeFileSync(nodePath.join(ledgerDir, '.session-id'), mintedSessionId, 'utf-8');
269
+ const selfAgentEntry = (process.env.TOTEM_SELF_AGENT || '')
270
+ .split(',')
271
+ .map((s) => s.trim())
272
+ .find((s) => s.length > 0);
273
+ const event = {
274
+ timestamp: new Date().toISOString(),
275
+ type: 'session_start',
276
+ activity_name: 'SessionStart',
277
+ source: 'bot',
278
+ ...(selfAgentEntry ? { agent_source: selfAgentEntry } : {}),
279
+ justification: '',
280
+ session_id: mintedSessionId,
281
+ };
282
+ appendFileSync(nodePath.join(ledgerDir, 'events.ndjson'), JSON.stringify(event) + '\\n', 'utf-8');
283
+ } catch (err) {
284
+ process.stderr.write(
285
+ '[SessionStart] session-start telemetry unavailable (non-fatal): ' +
286
+ (err instanceof Error ? err.message : String(err)) +
287
+ '\\n',
288
+ );
289
+ }
290
+
291
+ // Interactive Gemini ingests SessionStart CONTEXT only from the
292
+ // hookSpecificOutput.additionalContext envelope — plain exit-0 stdout wraps as
293
+ // systemMessage, which the interactive startup consumer never injects, so the
294
+ // briefing was absent from model context in the primary dev flow even once
295
+ // registered (mmnto-ai/totem#2613; leg-verified against @google/gemini-cli
296
+ // 0.54.4). systemMessage rides alongside the envelope for the human surfaces:
297
+ // interactive startup and /clear render it as a UI info item and -p echoes it
298
+ // to stderr — so the briefing is VISIBLE to the human on those surfaces and
299
+ // injected as context for the model (one payload, both audiences).
300
+ // The Totem CLI writes its banner and diagnostics to STDERR, so capture takes
301
+ // BOTH streams — the same seam the Claude-side template documents; a
302
+ // stdout-only capture silently drops the describe leg (mmnto-ai/totem#2613
303
+ // falsification round). A leg failure carries any partial stdout plus the
304
+ // fail-soft note; exit is ALWAYS 0 (never blocks boot).
305
+ // Per-leg 20s budgets cut the measured worst-case process exit from 60s to
306
+ // 40s against Gemini's 60s DEFAULT_HOOK_TIMEOUT (which tree-kills at expiry;
307
+ // no descendant inherits this hook's own streams).
308
+ let briefing = '';
309
+ try {
310
+ const describeRun = spawnSync('totem describe', {
311
+ shell: true,
312
+ timeout: 20000,
313
+ encoding: 'utf-8',
314
+ stdio: ['ignore', 'pipe', 'pipe'],
258
315
  });
316
+ // spawnSync sets .error (it does NOT throw) on spawn-level failure/timeout.
317
+ briefing += describeRun.stdout || '';
318
+ if (describeRun.error || describeRun.status !== 0) {
319
+ const reason = describeRun.error
320
+ ? (describeRun.error.message || String(describeRun.error))
321
+ : ((describeRun.stderr || '').trim() || 'totem describe exited ' + describeRun.status);
322
+ briefing += '[Totem] Briefing unavailable: ' + reason + '\\n';
323
+ } else {
324
+ briefing += describeRun.stderr || '';
325
+ }
259
326
  } catch (err) {
260
- process.stdout.write('[Totem] Briefing unavailable: ' + (err instanceof Error ? err.message : String(err)) + '\\n');
327
+ // Belt for a genuinely throwing spawnSync: same fail-soft note.
328
+ briefing += '[Totem] Briefing unavailable: ' + (err instanceof Error ? err.message : String(err)) + '\\n';
261
329
  }
262
330
 
331
+ // Selection-manifest block boundary (mmnto-ai/totem#2468): everything in
332
+ // \`briefing\` up to here is the describe leg — including its fail-soft note,
333
+ // which IS injected payload when it fires.
334
+ const describeBriefingEnd = briefing.length;
335
+
263
336
  // totem orient --session — live derived in-flight state, ADDITIVE to describe
264
337
  // (mmnto-ai/totem#2044 PR-3). Own try/catch; orient --session is itself boot-safe.
265
338
  try {
266
- execSync('totem orient --session', {
267
- timeout: 30000,
268
- stdio: ['ignore', 'inherit', 'inherit'],
339
+ const orientRun = spawnSync('totem orient --session', {
340
+ shell: true,
341
+ timeout: 20000,
342
+ encoding: 'utf-8',
343
+ stdio: ['ignore', 'pipe', 'pipe'],
269
344
  });
345
+ briefing += orientRun.stdout || '';
346
+ if (orientRun.error || orientRun.status !== 0) {
347
+ const orientReason = orientRun.error
348
+ ? (orientRun.error.message || String(orientRun.error))
349
+ : ((orientRun.stderr || '').trim() || 'totem orient exited ' + orientRun.status);
350
+ // Boot-safe: orient is additive to describe; a failure never blocks session
351
+ // start. The note rides the briefing (both keys) so the model and the human
352
+ // both see the orient gap — a stderr-only note is invisible to the model
353
+ // (CR round on this PR); the parent-stderr breadcrumb stays for hook
354
+ // diagnostics.
355
+ briefing += '[Totem] Orient briefing unavailable: ' + orientReason + '\\n';
356
+ process.stderr.write('[SessionStart] orient briefing unavailable (non-fatal): ' + orientReason + '\\n');
357
+ } else {
358
+ briefing += orientRun.stderr || '';
359
+ }
270
360
  } catch (err) {
271
- // Boot-safe: orient is additive to describe; a failure never blocks session start —
272
- // surface a NON-fatal breadcrumb (matches the Claude-side hook) rather than swallow.
273
- process.stderr.write('[SessionStart] orient briefing unavailable (non-fatal): ' + (err instanceof Error ? err.message : String(err)) + '\\n');
361
+ const orientMsg = err instanceof Error ? err.message : String(err);
362
+ briefing += '[Totem] Orient briefing unavailable: ' + orientMsg + '\\n';
363
+ process.stderr.write('[SessionStart] orient briefing unavailable (non-fatal): ' + orientMsg + '\\n');
274
364
  }
365
+
366
+ // ─── selection manifest (mmnto-ai/totem#2468 M1) ────────────────
367
+ // Inline append mirroring the A.3.a write above — this rendered hook runs
368
+ // standalone in consumer repos with no access to @mmnto/totem's writer. The
369
+ // row shape is BOUND to SelectionManifestRowSchema (strict): change both in
370
+ // the same PR; the template contract test parses this row with the real
371
+ // schema. A zero-byte block never becomes a candidate (nothing was injected).
372
+ try {
373
+ const nodePath = require('path');
374
+ const { appendFileSync } = require('fs');
375
+ const { createHash } = require('crypto');
376
+ const measure = (id, content, reason) => {
377
+ const bytes = Buffer.byteLength(content, 'utf-8');
378
+ return {
379
+ id,
380
+ disposition: 'selected',
381
+ reason,
382
+ bytes,
383
+ approxTokens: Math.ceil(bytes / 4),
384
+ fingerprint: createHash('sha256').update(content, 'utf-8').digest('hex').slice(0, 16),
385
+ };
386
+ };
387
+ const selfAgent = (process.env.TOTEM_SELF_AGENT || '')
388
+ .split(',')
389
+ .map((s) => s.trim())
390
+ .find((s) => s.length > 0);
391
+ const row = {
392
+ schemaVersion: 1,
393
+ timestamp: new Date().toISOString(),
394
+ emitter: 'session-start',
395
+ ...(mintedSessionId ? { session_id: mintedSessionId } : {}),
396
+ ...(selfAgent ? { agent_source: selfAgent } : {}),
397
+ context: { template: 'gemini-managed' },
398
+ universe: 'managed-template blocks: describe + orient --session',
399
+ costBasis: { bytes: 'utf8-length', approxTokens: 'ceil(bytes/4) approximation' },
400
+ candidates: [
401
+ measure('describe', briefing.slice(0, describeBriefingEnd), 'always-injected briefing'),
402
+ measure('orient:session-block', briefing.slice(describeBriefingEnd), 'always-injected briefing'),
403
+ ].filter((c) => c.bytes > 0),
404
+ warnings: [],
405
+ };
406
+ appendFileSync(
407
+ nodePath.join(process.cwd(), '.totem', 'ledger', 'selection-manifests.ndjson'),
408
+ JSON.stringify(row) + '\\n',
409
+ 'utf-8',
410
+ );
411
+ } catch (err) {
412
+ process.stderr.write(
413
+ '[SessionStart] selection manifest unavailable (non-fatal): ' +
414
+ (err instanceof Error ? err.message : String(err)) +
415
+ '\\n',
416
+ );
417
+ }
418
+
419
+ process.stdout.write(JSON.stringify({
420
+ systemMessage: briefing,
421
+ hookSpecificOutput: { hookEventName: 'SessionStart', additionalContext: briefing },
422
+ }) + '\\n');
275
423
  ${TOTEM_FILE_END}
276
424
  `;
277
425
  export const GEMINI_BEFORE_TOOL = `// [totem] auto-generated — Gemini CLI BeforeTool hook
@@ -443,7 +591,7 @@ function checkXrepoQualifyRefs(toolName, toolInput) {
443
591
  );
444
592
  }
445
593
 
446
- module.exports = function beforeTool(toolName, toolInput) {
594
+ function beforeTool(toolName, toolInput) {
447
595
  checkOutboxSubjectQuoting(toolName, toolInput);
448
596
  checkAutoCloseKeywords(toolName, toolInput);
449
597
  checkXrepoQualifyRefs(toolName, toolInput);
@@ -457,7 +605,50 @@ module.exports = function beforeTool(toolName, toolInput) {
457
605
  } catch (err) {
458
606
  throw new Error('[Totem Error] Shield check failed. Fix violations before pushing.\\n' + err.message);
459
607
  }
460
- };
608
+ }
609
+ module.exports = beforeTool;
610
+
611
+ // Entry point — Gemini runs this file as a COMMAND hook (\`node BeforeTool.cjs\`)
612
+ // with the hook-input JSON on stdin; without this block the file defines a
613
+ // function and exits 0 = allow, leaving every guard above inert
614
+ // (mmnto-ai/totem#2611). Exit contract (leg-verified against
615
+ // @google/gemini-cli 0.54.4): exit 0 allow · exit 1 ALLOW with warning (an
616
+ // uncaught throw exits 1 — throwing can never deny) · exit >= 2 deny ·
617
+ // structured stdout {"decision":"deny","reason"} deny. A violation emits the
618
+ // structured deny AND exits 2 so either channel suffices. Gemini reads stderr
619
+ // only when stdout is EMPTY, so the stderr copy on the deny path never enters
620
+ // the hook pipeline — it serves hand-run invocations; on the exit-1 paths the
621
+ // stderr breadcrumb IS the payload that surfaces as the warning. Input the
622
+ // guard cannot evaluate (unparseable JSON, missing tool_name) is
623
+ // allow-with-warning (exit 1): denying every call on a vendor shape change
624
+ // would brick the seat, and exiting 0 would hide the outage.
625
+ if (require.main === module) {
626
+ let raw = '';
627
+ process.stdin.setEncoding('utf-8');
628
+ process.stdin.on('data', function (chunk) { raw += chunk; });
629
+ process.stdin.on('end', function () {
630
+ let input;
631
+ try {
632
+ input = JSON.parse(raw);
633
+ } catch (err) {
634
+ process.stderr.write('[totem BeforeTool] hook input is not parseable JSON — guard did not evaluate this call: ' + (err instanceof Error ? err.message : String(err)) + '\\n');
635
+ process.exit(1);
636
+ }
637
+ if (typeof input !== 'object' || input === null || typeof input.tool_name !== 'string') {
638
+ process.stderr.write('[totem BeforeTool] hook input carries no tool_name — guard did not evaluate this call\\n');
639
+ process.exit(1);
640
+ }
641
+ try {
642
+ beforeTool(input.tool_name, input.tool_input);
643
+ } catch (err) {
644
+ const reason = err instanceof Error ? err.message : String(err);
645
+ process.stdout.write(JSON.stringify({ decision: 'deny', reason: reason }) + '\\n');
646
+ process.stderr.write(reason + '\\n');
647
+ process.exit(2);
648
+ }
649
+ process.exit(0);
650
+ });
651
+ }
461
652
  ${TOTEM_FILE_END}
462
653
  `;
463
654
  export const GEMINI_SKILL = `<!-- [totem] auto-generated — Totem Architect skill -->
@@ -758,10 +949,14 @@ const { randomUUID } = require('crypto');
758
949
  const { join } = require('path');
759
950
 
760
951
  // ─── A.3.a: mint session ID + log session_start event ──────────
952
+ // Hoisted so the selection-manifest row below (mmnto-ai/totem#2468) can carry
953
+ // the same session UUID as its join key.
954
+ let mintedSessionId = null;
761
955
  try {
762
956
  const ledgerDir = join(process.cwd(), '.totem', 'ledger');
763
957
  mkdirSync(ledgerDir, { recursive: true });
764
958
  const sessionId = randomUUID();
959
+ mintedSessionId = sessionId;
765
960
  writeFileSync(join(ledgerDir, '.session-id'), sessionId, 'utf-8');
766
961
  // Amended ADR-078 (2026-07-15): agent_source is the env-carried seat-id
767
962
  // (TOTEM_SELF_AGENT, first non-empty comma entry), never a vendor class
@@ -891,6 +1086,9 @@ try {
891
1086
  }
892
1087
 
893
1088
  // ─── totem describe briefing (existing behavior) ────────────────
1089
+ // Captured (mmnto-ai/totem#2468): the injected block is the selection-manifest
1090
+ // candidate below — the not-installed notice is a notice, not a briefing.
1091
+ let describeText = '';
894
1092
  try {
895
1093
  const cliPath = join(process.cwd(), 'node_modules', '@mmnto', 'cli', 'dist', 'index.js');
896
1094
  if (existsSync(cliPath)) {
@@ -903,7 +1101,8 @@ try {
903
1101
  }
904
1102
  // Totem CLI writes diagnostic output to stderr; route to stdout so the
905
1103
  // session-start context lands in Claude's prompt rather than user-visible noise.
906
- process.stdout.write((result.stdout || '') + (result.stderr || ''));
1104
+ describeText = (result.stdout || '') + (result.stderr || '');
1105
+ process.stdout.write(describeText);
907
1106
  } else {
908
1107
  process.stdout.write(
909
1108
  '[Totem] @mmnto/cli not installed. Run \`pnpm install\` (or your package manager equivalent) to enable session-start orientation.\\n',
@@ -923,6 +1122,7 @@ try {
923
1122
  // never replace. Its OWN try/catch so an orient failure never disturbs the describe
924
1123
  // briefing or the boot; \`orient --session\` is itself boot-safe (emits nothing when
925
1124
  // nothing is high-signal, never exits non-zero, degrades to honest "could not derive").
1125
+ let orientText = '';
926
1126
  try {
927
1127
  const orientCliPath = join(process.cwd(), 'node_modules', '@mmnto', 'cli', 'dist', 'index.js');
928
1128
  if (existsSync(orientCliPath)) {
@@ -935,7 +1135,8 @@ try {
935
1135
  if (orientResult.error) {
936
1136
  throw orientResult.error;
937
1137
  }
938
- process.stdout.write((orientResult.stdout || '') + (orientResult.stderr || ''));
1138
+ orientText = (orientResult.stdout || '') + (orientResult.stderr || '');
1139
+ process.stdout.write(orientText);
939
1140
  }
940
1141
  } catch (err) {
941
1142
  // Boot-safe: orient is additive to describe (already emitted), so a failure never
@@ -947,6 +1148,57 @@ try {
947
1148
  '\\n',
948
1149
  );
949
1150
  }
1151
+
1152
+ // ─── selection manifest (mmnto-ai/totem#2468 M1) ────────────────
1153
+ // Inline append mirroring the session_start write above — this rendered hook
1154
+ // runs standalone in consumer repos with no access to @mmnto/totem's writer.
1155
+ // The row shape is BOUND to SelectionManifestRowSchema (strict): change both
1156
+ // in the same PR; the template contract test parses this row with the real
1157
+ // schema. A zero-byte block never becomes a candidate (nothing was injected).
1158
+ try {
1159
+ const { createHash } = require('crypto');
1160
+ const measure = (id, content, reason) => {
1161
+ const bytes = Buffer.byteLength(content, 'utf-8');
1162
+ return {
1163
+ id,
1164
+ disposition: 'selected',
1165
+ reason,
1166
+ bytes,
1167
+ approxTokens: Math.ceil(bytes / 4),
1168
+ fingerprint: createHash('sha256').update(content, 'utf-8').digest('hex').slice(0, 16),
1169
+ };
1170
+ };
1171
+ const selfAgent = (process.env.TOTEM_SELF_AGENT || '')
1172
+ .split(',')
1173
+ .map((s) => s.trim())
1174
+ .find((s) => s.length > 0);
1175
+ const row = {
1176
+ schemaVersion: 1,
1177
+ timestamp: new Date().toISOString(),
1178
+ emitter: 'session-start',
1179
+ ...(mintedSessionId ? { session_id: mintedSessionId } : {}),
1180
+ ...(selfAgent ? { agent_source: selfAgent } : {}),
1181
+ context: { template: 'claude-managed' },
1182
+ universe: 'managed-template blocks: describe + orient --session',
1183
+ costBasis: { bytes: 'utf8-length', approxTokens: 'ceil(bytes/4) approximation' },
1184
+ candidates: [
1185
+ measure('describe', describeText, 'always-injected briefing'),
1186
+ measure('orient:session-block', orientText, 'always-injected briefing'),
1187
+ ].filter((c) => c.bytes > 0),
1188
+ warnings: [],
1189
+ };
1190
+ appendFileSync(
1191
+ join(process.cwd(), '.totem', 'ledger', 'selection-manifests.ndjson'),
1192
+ JSON.stringify(row) + '\\n',
1193
+ 'utf-8',
1194
+ );
1195
+ } catch (err) {
1196
+ process.stderr.write(
1197
+ '[SessionStart] selection manifest unavailable (non-fatal): ' +
1198
+ (err instanceof Error ? err.message : String(err)) +
1199
+ '\\n',
1200
+ );
1201
+ }
950
1202
  ${TOTEM_FILE_END}
951
1203
  `;
952
1204
  export const CLAUDE_SESSION_START_ENTRY = {
@@ -1 +1 @@
1
- {"version":3,"file":"init-templates.js","sourceRoot":"","sources":["../../src/commands/init-templates.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init-templates.js","sourceRoot":"","sources":["../../src/commands/init-templates.ts"],"names":[],"mappings":"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"}
@@ -1705,13 +1705,31 @@ describe('GEMINI_SESSION_START template', () => {
1705
1705
  it('does NOT call `totem status` (the prior drifted shape)', () => {
1706
1706
  expect(GEMINI_SESSION_START).not.toContain("'totem status'");
1707
1707
  });
1708
- it('uses a 30-second timeout matching the Claude-side hook contract', () => {
1709
- expect(GEMINI_SESSION_START).toContain('timeout: 30000');
1710
- });
1711
- it('routes diagnostic stdio so the banner lands in the session prompt', () => {
1712
- // Gemini SessionStart hooks inherit stdio; the third entry must be
1713
- // 'inherit' for the orientation output to reach the agent.
1714
- expect(GEMINI_SESSION_START).toContain("stdio: ['ignore', 'inherit', 'inherit']");
1708
+ it('uses 20-second per-leg timeouts measured worst-case exit drops 60s to 40s', () => {
1709
+ // Two sequential legs at the old 30s each could consume Gemini's entire
1710
+ // 60s DEFAULT_HOOK_TIMEOUT on one pathological hang. Post-fix no
1711
+ // descendant inherits the hook's own streams, so the inner budgets are
1712
+ // honored even under a hung grandchild, and the vendor tree-kills at its
1713
+ // own 60s expiry regardless (mmnto-ai/totem#2613 falsification rounds).
1714
+ expect(GEMINI_SESSION_START).toContain('timeout: 20000');
1715
+ expect(GEMINI_SESSION_START).not.toContain('timeout: 30000');
1716
+ });
1717
+ it('captures BOTH streams of the briefing legs and emits envelope + systemMessage', () => {
1718
+ // Interactive Gemini ingests SessionStart output ONLY from
1719
+ // hookSpecificOutput.additionalContext — an 'inherit' stdout wraps as
1720
+ // systemMessage, which the interactive startup consumer never reads
1721
+ // (mmnto-ai/totem#2613; the pre-fix pin here asserted exactly that
1722
+ // dropped channel). The Totem CLI writes its banner to STDERR, so capture
1723
+ // must take both streams — a stdout-only capture silently drops the
1724
+ // describe leg. systemMessage rides alongside for the /clear and -p
1725
+ // surfaces, which read only that key. The runtime contract is pinned
1726
+ // end-to-end by gemini-sessionstart-contract.test.ts; this guards
1727
+ // template drift.
1728
+ expect(GEMINI_SESSION_START).toContain("stdio: ['ignore', 'pipe', 'pipe']");
1729
+ expect(GEMINI_SESSION_START).not.toContain("stdio: ['ignore', 'inherit', 'inherit']");
1730
+ expect(GEMINI_SESSION_START).toContain("hookEventName: 'SessionStart'");
1731
+ expect(GEMINI_SESSION_START).toContain('additionalContext: briefing');
1732
+ expect(GEMINI_SESSION_START).toContain('systemMessage: briefing');
1715
1733
  });
1716
1734
  it('emits a generic fallback breadcrumb when describe fails', () => {
1717
1735
  // No strategy-repo-specific pointers leak; matches the Claude-side