@indigoai-us/hq-cli 5.308.0 → 5.309.1

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 (95) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/command-catalog.generated.d.ts +4 -1
  3. package/dist/command-catalog.generated.js +5 -1
  4. package/dist/commands/agents.js +6 -0
  5. package/dist/commands/core-checkpoint-gate-setting.d.ts +0 -10
  6. package/dist/commands/core-checkpoint-gate-setting.js +3 -3
  7. package/dist/commands/core-ontology.d.ts +1 -9
  8. package/dist/commands/core-ontology.js +4 -4
  9. package/dist/commands/core-policy.d.ts +0 -3
  10. package/dist/commands/core-policy.js +3 -3
  11. package/dist/commands/files.js +1 -1
  12. package/dist/commands/index-cmd.js +1 -1
  13. package/dist/commands/integrations-api.d.ts +9 -4
  14. package/dist/commands/integrations-api.js +9 -6
  15. package/dist/commands/integrations-manage.js +11 -3
  16. package/dist/commands/integrations.d.ts +8 -0
  17. package/dist/commands/integrations.js +83 -0
  18. package/dist/commands/lanes-checks.d.ts +6 -2
  19. package/dist/commands/lanes-checks.js +69 -19
  20. package/dist/commands/lanes-report.js +5 -2
  21. package/dist/commands/lanes.d.ts +0 -11
  22. package/dist/commands/lanes.js +6 -6
  23. package/dist/commands/mcp-registration.d.ts +5 -11
  24. package/dist/commands/mcp-registration.js +2 -6
  25. package/dist/lib/core-utils/sentry-report.d.ts +5 -11
  26. package/dist/lib/core-utils/sentry-report.js +2 -2
  27. package/dist/lib/db/local.d.ts +0 -5
  28. package/dist/lib/db/local.js +1 -1
  29. package/dist/lib/db/migrate.d.ts +0 -12
  30. package/dist/lib/db/migrate.js +5 -5
  31. package/dist/lib/db/sql.d.ts +0 -10
  32. package/dist/lib/db/sql.js +4 -8
  33. package/dist/lib/doctor/checks/codex-wiring.d.ts +0 -4
  34. package/dist/lib/doctor/checks/codex-wiring.js +3 -35
  35. package/dist/lib/doctor/checks/grok-wiring.js +1 -34
  36. package/dist/lib/doctor/checks/runtime-health.d.ts +0 -17
  37. package/dist/lib/doctor/checks/runtime-health.js +4 -4
  38. package/dist/lib/doctor/checks/scaffold-cli-floor.d.ts +0 -1
  39. package/dist/lib/doctor/checks/scaffold-cli-floor.js +1 -1
  40. package/dist/lib/doctor/compat.d.ts +0 -16
  41. package/dist/lib/doctor/compat.js +3 -3
  42. package/dist/lib/doctor/deep/effects.js +1 -3
  43. package/dist/lib/doctor/deep/sandbox.js +1 -3
  44. package/dist/lib/doctor/fixtures/schema.js +1 -3
  45. package/dist/lib/doctor/platform.d.ts +0 -26
  46. package/dist/lib/doctor/platform.js +5 -5
  47. package/dist/lib/doctor/shared.d.ts +8 -0
  48. package/dist/lib/doctor/shared.js +38 -0
  49. package/dist/lib/lanes/autopilot.js +125 -103
  50. package/dist/lib/monitor.d.ts +2 -6
  51. package/dist/lib/monitor.js +5 -5
  52. package/dist/lib/onboarding/errors.d.ts +2 -1
  53. package/dist/lib/onboarding/errors.js +1 -1
  54. package/dist/lib/onboarding/index.d.ts +2 -6
  55. package/dist/lib/onboarding/index.js +2 -5
  56. package/dist/lib/report-publish.d.ts +1 -10
  57. package/dist/lib/report-publish.js +3 -9
  58. package/dist/lib/search-index/embed-lock.d.ts +0 -7
  59. package/dist/lib/search-index/embed-lock.js +1 -1
  60. package/dist/lib/search-index/index.d.ts +7 -0
  61. package/dist/lib/search-index/index.js +21 -2
  62. package/dist/lib/search-index/load-gate.d.ts +0 -8
  63. package/dist/lib/search-index/load-gate.js +3 -3
  64. package/dist/lib/search-index/max-doc-bytes.d.ts +2 -3
  65. package/dist/lib/search-index/max-doc-bytes.js +1 -1
  66. package/dist/lib/search-index/qmd-exit-diagnostics.d.ts +5 -0
  67. package/dist/lib/search-index/qmd-exit-diagnostics.js +40 -0
  68. package/dist/lib/service-manager/launchd.d.ts +0 -7
  69. package/dist/lib/service-manager/launchd.js +2 -2
  70. package/dist/main.js +7 -2
  71. package/dist/startup-registration.js +9 -1
  72. package/dist/utils/client-health.d.ts +0 -4
  73. package/dist/utils/client-health.js +2 -2
  74. package/dist/utils/feedback-diagnostics.d.ts +2 -1
  75. package/dist/utils/feedback-log-bundle.d.ts +0 -25
  76. package/dist/utils/feedback-log-bundle.js +5 -5
  77. package/dist/utils/feedback-logs.d.ts +4 -38
  78. package/dist/utils/feedback-logs.js +7 -7
  79. package/dist/utils/feedback-screenshots.d.ts +0 -1
  80. package/dist/utils/feedback-screenshots.js +1 -1
  81. package/dist/utils/install-tree-torn.d.ts +19 -13
  82. package/dist/utils/install-tree-torn.js +77 -2
  83. package/dist/utils/local-files-overview.d.ts +0 -6
  84. package/dist/utils/local-files-overview.js +1 -1
  85. package/dist/utils/qmd-model-download-error.d.ts +0 -8
  86. package/dist/utils/qmd-model-download-error.js +1 -1
  87. package/dist/utils/qmd-query-document-error.d.ts +0 -6
  88. package/dist/utils/qmd-query-document-error.js +1 -1
  89. package/dist/utils/scaffold-fast-import-guard.d.ts +0 -1
  90. package/dist/utils/scaffold-fast-import-guard.js +1 -1
  91. package/dist/utils/scaffold-sibling-references.d.ts +3 -2
  92. package/dist/utils/sentry-fingerprint.js +17 -0
  93. package/dist/utils/version-gate.d.ts +4 -0
  94. package/dist/utils/version-gate.js +13 -0
  95. package/package.json +1 -1
@@ -12,6 +12,37 @@ import { DEFAULT_ORPHAN_USER_IDLE_HOURS, findOrphanLanes, parseOrphanMinAge, par
12
12
  import { LANES_RUNS_REL } from "../lib/lanes/spawn.js";
13
13
  import { assertNoSecretText } from "../lib/lanes/text-scan.js";
14
14
  import { checkCompanyPath } from "../lib/lanes/checked-company-path.js";
15
+ export function mappingIncludesStory(mapping, storyId) {
16
+ return (mapping.storyPrefix === undefined || storyId.startsWith(mapping.storyPrefix))
17
+ && (mapping.excludePrefix === undefined || !storyId.startsWith(mapping.excludePrefix));
18
+ }
19
+ function mappingsOverlap(left, right) {
20
+ const includes = [left.storyPrefix, right.storyPrefix].filter((value) => value !== undefined);
21
+ if (includes.length === 2 && !includes[0].startsWith(includes[1]) && !includes[1].startsWith(includes[0]))
22
+ return false;
23
+ const commonPrefix = includes.sort((a, b) => b.length - a.length)[0] ?? "";
24
+ return ![left.excludePrefix, right.excludePrefix].some((excluded) => excluded !== undefined && commonPrefix.startsWith(excluded));
25
+ }
26
+ function ambiguousProjectMappings(mappings) {
27
+ const byProject = new Map();
28
+ for (const mapping of mappings)
29
+ byProject.set(mapping.projectId, [...(byProject.get(mapping.projectId) ?? []), mapping]);
30
+ const ambiguous = new Map();
31
+ for (const [projectId, rows] of byProject) {
32
+ const conflicts = new Set();
33
+ for (let i = 0; i < rows.length; i++) {
34
+ for (let j = i + 1; j < rows.length; j++) {
35
+ if (mappingsOverlap(rows[i], rows[j])) {
36
+ conflicts.add(rows[i].team);
37
+ conflicts.add(rows[j].team);
38
+ }
39
+ }
40
+ }
41
+ if (conflicts.size > 0)
42
+ ambiguous.set(projectId, [...conflicts].sort());
43
+ }
44
+ return ambiguous;
45
+ }
15
46
  function fail(error, message, details = {}) {
16
47
  throw new LanesError(error, message, details);
17
48
  }
@@ -165,16 +196,26 @@ export function loadProjectMappings(root, company, requestedProject) {
165
196
  const team = validSegment(entry.team, "team");
166
197
  const leadLaneId = validSegment(entry.lane, "lead lane id");
167
198
  const statusPath = checkCompanyPath(root, company, entry.status, registryPath);
168
- if (mappings.has(projectId))
169
- return fail("tracker_checks_mapping_ambiguous", "More than one active team maps to a project", { path: registryPath, project_id: projectId });
170
- mappings.set(projectId, { projectId, team, leadLaneId, statusPath });
199
+ const parsePrefix = (field) => {
200
+ const value = entry[field];
201
+ if (value === undefined)
202
+ return undefined;
203
+ if (typeof value !== "string" || value.trim() === "") {
204
+ return fail("tracker_checks_mapping_invalid", `${field} must be a non-empty string`, { path: registryPath, index, field });
205
+ }
206
+ return value.trim();
207
+ };
208
+ const storyPrefix = parsePrefix("story_prefix");
209
+ const excludePrefix = parsePrefix("exclude_prefix");
210
+ const key = `${projectId}:${team}:${index}`;
211
+ mappings.set(key, { projectId, team, leadLaneId, statusPath, ...(storyPrefix === undefined ? {} : { storyPrefix }), ...(excludePrefix === undefined ? {} : { excludePrefix }) });
171
212
  }
172
213
  }
173
214
  const projectsRoot = path.join(root, "companies", company, "projects");
174
215
  const knownProjectIds = new Set(projectDirectories(root, company));
175
216
  for (const projectId of knownProjectIds) {
176
- if (projectHasTrackerRecords(root, company, projectId) && !mappings.has(projectId)) {
177
- mappings.set(projectId, {
217
+ if (projectHasTrackerRecords(root, company, projectId) && ![...mappings.values()].some((mapping) => mapping.projectId === projectId)) {
218
+ mappings.set(`${projectId}:tracker`, {
178
219
  projectId,
179
220
  team: projectId,
180
221
  statusPath: path.join(projectsRoot, projectId, "manager-status.json"),
@@ -183,10 +224,10 @@ export function loadProjectMappings(root, company, requestedProject) {
183
224
  }
184
225
  if (requestedProject !== undefined) {
185
226
  const projectId = validSegment(requestedProject, "project");
186
- if (!knownProjectIds.has(projectId) && !mappings.has(projectId)) {
227
+ if (!knownProjectIds.has(projectId) && ![...mappings.values()].some((mapping) => mapping.projectId === projectId)) {
187
228
  return fail("tracker_project_not_found", "Project directory was not found for this company", { project_id: projectId, path: path.join(projectsRoot, projectId) });
188
229
  }
189
- return new Map([...mappings].filter(([mappedProjectId]) => mappedProjectId === projectId));
230
+ return new Map([...mappings].filter(([, mapping]) => mapping.projectId === projectId));
190
231
  }
191
232
  return mappings;
192
233
  }
@@ -539,17 +580,18 @@ function readCompanyQuestions(root, company, projectId) {
539
580
  surfaced_at: surfacedAt.get(question.question_id) ?? null,
540
581
  }));
541
582
  }
542
- function readTeamInputs(root, company, projects, lanes) {
583
+ export function readTeamInputs(root, company, projects, lanes) {
543
584
  const inputs = [];
544
585
  for (const project of projects) {
545
586
  const projectPath = path.join(root, "companies", company.slug, "projects", project.projectId);
546
587
  const prdPath = path.join(projectPath, "prd.json");
547
588
  const { stories, mtime } = readProject(root, company.slug, prdPath);
548
- const teamLanes = lanes.filter((lane) => sameCompanyLane(lane, company) && laneMatchesProject(lane, project.projectId));
589
+ const teamLanes = lanes.filter((lane) => sameCompanyLane(lane, company) && laneMatchesProject(lane, project.projectId)
590
+ && (lane.lane_id === project.leadLaneId || mappingIncludesStory(project, lane.story_id)));
549
591
  const lead = project.leadLaneId === undefined
550
592
  ? undefined
551
593
  : teamLanes.find((lane) => lane.lane_id === project.leadLaneId);
552
- const openStories = stories.filter((story) => !storyIsDone(story));
594
+ const openStories = stories.filter((story) => mappingIncludesStory(project, String(story.id)) && !storyIsDone(story));
553
595
  const openPrRefs = new Set();
554
596
  for (const story of openStories) {
555
597
  for (const ref of pullRequestReferences(story.prs ?? []))
@@ -599,7 +641,7 @@ function requiredRecordTimestamp(kind, record, projectDirectory, field, value) {
599
641
  return parseTimestamp(value, field, pathForTrackerRecord(projectDirectory, kind, record.id));
600
642
  return value;
601
643
  }
602
- export function listTrackerRecords(projectDirectory, kind) {
644
+ function listTrackerRecords(projectDirectory, kind) {
603
645
  try {
604
646
  return createLocalTrackerStore(projectDirectory).list(kind);
605
647
  }
@@ -658,7 +700,7 @@ async function readTrackerCheckRecords(root, company, projects) {
658
700
  const blockers = [];
659
701
  const kpis = [];
660
702
  const directives = [];
661
- for (const project of projects) {
703
+ for (const project of [...new Map(projects.map((project) => [project.projectId, project])).values()]) {
662
704
  const absoluteDirectory = path.join(root, "companies", company.slug, "projects", project.projectId);
663
705
  const store = createLocalTrackerStore(absoluteDirectory);
664
706
  const records = {
@@ -715,7 +757,7 @@ export async function resolveTrackerCompany(deps, requested) {
715
757
  fail("tracker_company_unresolved", "The active HQ company could not be resolved", {});
716
758
  return company;
717
759
  }
718
- async function checkReport(root, company, projects, directiveProjects, projectFilter, minAgeMinutes, now, deps) {
760
+ async function checkReport(root, company, projects, directiveProjects, projectFilter, minAgeMinutes, now, deps, projectErrors) {
719
761
  const selectedProjects = [...projects.values()];
720
762
  const laneRecords = readScopedLanes(root, company, selectedProjects);
721
763
  const warnings = laneRecords.flatMap((lane) => {
@@ -773,6 +815,7 @@ async function checkReport(root, company, projects, directiveProjects, projectFi
773
815
  company: company.slug,
774
816
  generated_at: now.toISOString(),
775
817
  ...(warnings.length === 0 ? {} : { warnings }),
818
+ ...(projectErrors.length === 0 ? {} : { project_errors: projectErrors }),
776
819
  checks,
777
820
  };
778
821
  }
@@ -855,13 +898,20 @@ export function registerLaneChecksCommand(parent, deps, wrap) {
855
898
  const root = deps.hqRoot();
856
899
  const projectFilter = options.project === undefined ? undefined : validSegment(options.project, "project");
857
900
  const minAgeMinutes = parseOrphanMinAge(options.minAge);
858
- const projects = loadProjectMappings(root, company.slug, projectFilter);
859
- const directiveProjects = projectFilter === undefined
860
- ? projects
861
- : loadProjectMappings(root, company.slug);
862
- const report = await checkReport(root, company, projects, directiveProjects, projectFilter, minAgeMinutes, deps.now(), deps);
901
+ const allProjects = loadProjectMappings(root, company.slug);
902
+ const ambiguous = ambiguousProjectMappings([...allProjects.values()]);
903
+ const selectedAll = projectFilter === undefined ? [...allProjects.values()] : [...allProjects.values()].filter((mapping) => mapping.projectId === projectFilter);
904
+ const projectErrors = [...ambiguous].filter(([projectId]) => projectFilter === undefined || projectId === projectFilter).map(([project_id, teams]) => ({
905
+ project_id,
906
+ code: "tracker_checks_mapping_ambiguous",
907
+ teams,
908
+ message: "Team story prefixes overlap for this project",
909
+ }));
910
+ const projects = new Map(selectedAll.filter((mapping) => !ambiguous.has(mapping.projectId)).map((mapping, index) => [`${mapping.projectId}:${mapping.team}:${index}`, mapping]));
911
+ const directiveProjects = new Map([...allProjects.values()].filter((mapping) => !ambiguous.has(mapping.projectId)).map((mapping, index) => [`${mapping.projectId}:${mapping.team}:${index}`, mapping]));
912
+ const report = await checkReport(root, company, projects, directiveProjects, projectFilter, minAgeMinutes, deps.now(), deps, projectErrors);
863
913
  console.log(JSON.stringify(report, null, 2));
864
- if (report.checks.some((item) => item.result === "failing"))
914
+ if (report.checks.some((item) => item.result === "failing") || projectErrors.length > 0)
865
915
  process.exitCode = 2;
866
916
  }));
867
917
  parent.command("orphans")
@@ -6,7 +6,7 @@ import { normalizeIsoTimestamp } from "../lib/lanes/timestamp.js";
6
6
  import { mapSourceStoryStatus } from "../lib/mesh/story-status.js";
7
7
  import { buildTrackerOwnerReport, buildTrackerTeamPage, renderTrackerOwnerReportText, renderTrackerTeamPageText, } from "../lib/lanes/tracker-report.js";
8
8
  import { FIRST_TRACKER_REPORT_SINCE, readTrackerReportState, writeTrackerReportState, } from "../lib/lanes/tracker-report-state.js";
9
- import { listTrackerRecordsTolerant, loadCompanyQuestionRecords, loadProjectMappings, pathForTrackerRecord, readProject, resolveTrackerCompany, } from "./lanes-checks.js";
9
+ import { listTrackerRecordsTolerant, loadCompanyQuestionRecords, loadProjectMappings, mappingIncludesStory, pathForTrackerRecord, readProject, resolveTrackerCompany, } from "./lanes-checks.js";
10
10
  function fail(error, message, details = {}) {
11
11
  throw new LanesError(error, message, details);
12
12
  }
@@ -184,6 +184,8 @@ async function teamInput(root, company, project, questions, deps, errors = []) {
184
184
  errors.push({ path: prdPath, field: "id", message: "Story id must be a non-empty string" });
185
185
  continue;
186
186
  }
187
+ if (!mappingIncludesStory(project, id))
188
+ continue;
187
189
  const title = typeof story.title === "string" ? story.title : "";
188
190
  if (!title.trim()) {
189
191
  errors.push({ path: prdPath, field: "title", story_id: id, message: "Story title must be a non-empty string" });
@@ -217,7 +219,8 @@ async function teamInput(root, company, project, questions, deps, errors = []) {
217
219
  stories.push({ id, title, status, references: refs.references, ...(normalizedUpdatedAt ? { updated_at: normalizedUpdatedAt } : {}), source_path: prdPath });
218
220
  }
219
221
  const teamQuestions = [];
220
- for (const record of questions.filter((question) => question.project_id === project.projectId)) {
222
+ for (const record of questions.filter((question) => question.project_id === project.projectId
223
+ && (typeof question.story_id !== "string" || mappingIncludesStory(project, question.story_id)))) {
221
224
  const sourcePath = questionRecordPath(root, record.question_id);
222
225
  try {
223
226
  const body = deps.readQuestionBody(root, record);
@@ -112,8 +112,6 @@ export declare function parseQuestionBody(raw: unknown): QuestionBody | null;
112
112
  */
113
113
  export declare const ASK_BACKOFF_MS: readonly [5000, 15000];
114
114
  export declare const ASK_ATTEMPTS: number;
115
- /** Flip to true in the next release to make --priority mandatory. */
116
- export declare const ASK_PRIORITY_REQUIRED = false;
117
115
  export declare function casUpdateQuestion(hqRoot: string, questionId: string, updater: (current: QuestionRecord) => QuestionRecord): QuestionRecord;
118
116
  export declare function casUpdateLane(hqRoot: string, laneId: string, updater: (current: LaneRecord) => LaneRecord): LaneRecord;
119
117
  /**
@@ -128,12 +126,7 @@ export declare function composeWorkerBrief(worker: ResolvedLaneWorker, taskBrief
128
126
  * and the foreground-only rule.
129
127
  */
130
128
  export declare function composeGeneralBrief(taskBrief: string): string;
131
- export declare function parseMaxRuntimeSeconds(raw: unknown, workerId: string): number | undefined;
132
- export declare const PICKUP_TERMINAL_REASONS: readonly ["account_not_logged_in", "unknown_account", "account_disabled", "model_unsupported"];
133
129
  export declare const DISPATCH_TERMINAL_REASON: "outpost_dispatch_failed";
134
- export type PickupTerminalReason = (typeof PICKUP_TERMINAL_REASONS)[number];
135
- /** Only explicit non-persistence evidence can prove a failed dispatch has no owner snapshot. */
136
- export declare function isUndispatchedOutpostMirror(lane: LaneRecord): boolean;
137
130
  /**
138
131
  * The CAS updater a pickup failure applies. A lane that is already terminal
139
132
  * for any reason (a cancel that landed after the caller's last read, an
@@ -149,9 +142,5 @@ export declare function pickupFailureUpdater(reasonRaw: string, details: Record<
149
142
  export declare function applyOutpostAccountPickup(hqRoot: string, laneId: string, modelDeps?: KnownModelsDeps): LaneRecord;
150
143
  export declare function cancelPendingQuestionsForLane(hqRoot: string, laneId: string, nowIso: string, operatorReason?: string): QuestionRecord[];
151
144
  export declare function stopCommittedState(state: LaneRecord["state"]): "cancelled" | "killed";
152
- /** Stderr notice that `stop` ends a lane for good, naming the resumable path. */
153
- export declare function stopTerminalWarning(laneId: string): string;
154
- /** Stderr notice when an interrupted lane has no session to resume from. */
155
- export declare function interruptNotResumableWarning(laneId: string): string;
156
145
  export declare function registerLanesCommand(parent: Command, deps?: LanesCommandDeps): Command;
157
146
  //# sourceMappingURL=lanes.d.ts.map
@@ -2253,7 +2253,7 @@ function assertKnownOutpost(requested, known) {
2253
2253
  export const ASK_BACKOFF_MS = [5_000, 15_000];
2254
2254
  export const ASK_ATTEMPTS = ASK_BACKOFF_MS.length + 1;
2255
2255
  /** Flip to true in the next release to make --priority mandatory. */
2256
- export const ASK_PRIORITY_REQUIRED = false;
2256
+ const ASK_PRIORITY_REQUIRED = false;
2257
2257
  const ASK_PRIORITY_WARNING = "--priority will be required in the next release.";
2258
2258
  const QUESTION_PRIORITIES = ["P0", "P1", "P2"];
2259
2259
  function withCasRetry(fn, attempts = 5) {
@@ -2390,7 +2390,7 @@ export function composeGeneralBrief(taskBrief) {
2390
2390
  "",
2391
2391
  ].join("\n");
2392
2392
  }
2393
- export function parseMaxRuntimeSeconds(raw, workerId) {
2393
+ function parseMaxRuntimeSeconds(raw, workerId) {
2394
2394
  if (raw === undefined || raw === null || raw === "")
2395
2395
  return undefined;
2396
2396
  if (typeof raw === "number") {
@@ -2540,7 +2540,7 @@ async function storyBoardCheck(ctx, company, projectId, storyIds) {
2540
2540
  throw err;
2541
2541
  }
2542
2542
  }
2543
- export const PICKUP_TERMINAL_REASONS = [
2543
+ const PICKUP_TERMINAL_REASONS = [
2544
2544
  "account_not_logged_in",
2545
2545
  "unknown_account",
2546
2546
  "account_disabled",
@@ -2548,7 +2548,7 @@ export const PICKUP_TERMINAL_REASONS = [
2548
2548
  ];
2549
2549
  export const DISPATCH_TERMINAL_REASON = "outpost_dispatch_failed";
2550
2550
  /** Only explicit non-persistence evidence can prove a failed dispatch has no owner snapshot. */
2551
- export function isUndispatchedOutpostMirror(lane) {
2551
+ function isUndispatchedOutpostMirror(lane) {
2552
2552
  return lane.host.kind === "outpost" &&
2553
2553
  isTerminalLaneState(lane.state) &&
2554
2554
  lane.terminal_reason === DISPATCH_TERMINAL_REASON &&
@@ -7302,7 +7302,7 @@ async function runStop(ctx, laneId, reason, quiet = false) {
7302
7302
  });
7303
7303
  }
7304
7304
  /** Stderr notice that `stop` ends a lane for good, naming the resumable path. */
7305
- export function stopTerminalWarning(laneId) {
7305
+ function stopTerminalWarning(laneId) {
7306
7306
  return `hq lanes: warning: stop kills lane ${laneId} and it cannot be resumed. ` +
7307
7307
  `To pause it and keep it resumable, use hq lanes interrupt ${laneId}.\n`;
7308
7308
  }
@@ -7395,7 +7395,7 @@ function persistInterruptedSession(hqRoot, lane) {
7395
7395
  : { ...current, provider_session_id: sessionId, provider_session_id_absent: undefined });
7396
7396
  }
7397
7397
  /** Stderr notice when an interrupted lane has no session to resume from. */
7398
- export function interruptNotResumableWarning(laneId) {
7398
+ function interruptNotResumableWarning(laneId) {
7399
7399
  return `hq lanes: warning: lane ${laneId} was interrupted before its provider reported a session id, ` +
7400
7400
  `so hq lanes resume cannot continue it. Start a new lane for the remaining work.\n`;
7401
7401
  }
@@ -74,8 +74,8 @@ export declare class ConfigParseError extends McpRegistrationError {
74
74
  export declare class ConfigPermissionError extends McpRegistrationError {
75
75
  readonly code: "ConfigPermissionError";
76
76
  }
77
- export type CodexMcpCollisionOwner = 'hq' | 'foreign' | 'unknown';
78
- export type CodexMcpCollisionField = 'command' | 'args' | 'env' | 'url' | 'other';
77
+ type CodexMcpCollisionOwner = 'hq' | 'foreign' | 'unknown';
78
+ type CodexMcpCollisionField = 'command' | 'args' | 'env' | 'url' | 'other';
79
79
  /** Safe, value-free context for a Codex name collision reported to Sentry. */
80
80
  export interface CodexMcpCollisionDiagnostics {
81
81
  client: 'codex';
@@ -146,7 +146,7 @@ export declare function backupRoot(env: SafeWriteEnv): string;
146
146
  /** `~/.hq/logs/mcp-registry.log` — the append-only JSONL audit log (mirrors backupRoot style). */
147
147
  export declare function mcpRegistryLogPath(env: SafeWriteEnv): string;
148
148
  /** The action recorded on an audit line. */
149
- export type AuditAction = 'register' | 'unregister';
149
+ type AuditAction = 'register' | 'unregister';
150
150
  /**
151
151
  * The result recorded on an audit line:
152
152
  * - `registered` — a register write that changed the file.
@@ -156,7 +156,7 @@ export type AuditAction = 'register' | 'unregister';
156
156
  * foreign/unstamped entry left in place). PARTIAL is auditable.
157
157
  * - `error` — the surface emit threw (the operation failed for this surface).
158
158
  */
159
- export type AuditResult = 'registered' | 'unregistered' | 'noop' | 'skipped' | 'error';
159
+ type AuditResult = 'registered' | 'unregistered' | 'noop' | 'skipped' | 'error';
160
160
  /**
161
161
  * One append-only audit-log entry. EXACT shape (field order is the JSON key order):
162
162
  * `{ ts, action, pack, server, transport, target, file, prevHash, newHash, result }`.
@@ -213,8 +213,6 @@ export declare function codexConfigPath(env: SafeWriteEnv): string;
213
213
  export declare function isCodexInstalled(env: SafeWriteEnv): boolean;
214
214
  /** `~/.claude.json` — the PINNED single Claude surface (top-level mcpServers). */
215
215
  export declare function claudeConfigPath(env: SafeWriteEnv): string;
216
- /** `~/.mcp.json` — the project-pinned Claude surface (a symlink on this host). */
217
- export declare function mcpJsonPath(env: SafeWriteEnv): string;
218
216
  /** Outcome of {@link readConfigDoc}: a parsed doc plus whether the file pre-existed. */
219
217
  export interface ReadConfigResult<T> {
220
218
  /** The parsed doc, or the `emptyDoc` when the file is absent/empty. */
@@ -284,10 +282,6 @@ export declare function readConfigDoc<T>(target: string, format: ConfigFormat<T>
284
282
  * separate snippet block) cannot leak. The result never contains raw file content.
285
283
  */
286
284
  export declare function sanitizeParserMessage(message: string): string;
287
- /** Default stale-lock timeout — a lock older than this whose PID is dead is broken. */
288
- export declare const DEFAULT_LOCK_STALE_MS = 30000;
289
- /** Default total time to wait for a held lock before giving up. */
290
- export declare const DEFAULT_LOCK_WAIT_MS = 10000;
291
285
  /** A held advisory lock; release with {@link releaseLock} (idempotent). */
292
286
  export interface ConfigLock {
293
287
  /** The lockfile path (`~/.<basename>.hqlock`). */
@@ -752,7 +746,7 @@ export declare function mergeCodexServer(name: string, def: TomlTable): (doc: Co
752
746
  */
753
747
  export declare function registerCodexServer(opts: RegisterServerOptions): RegisterSurfaceResult | RegisterSurfaceSkip;
754
748
  /** Discriminates an un-registration outcome on one surface. */
755
- export type UnregisterOutcome =
749
+ type UnregisterOutcome =
756
750
  /** The provenance-stamped entry was found and removed (file changed). */
757
751
  'removed'
758
752
  /** The entry was already absent / never installed — a clean idempotent no-op. */
@@ -242,10 +242,6 @@ export function isCodexInstalled(env) {
242
242
  export function claudeConfigPath(env) {
243
243
  return path.join(env.home, '.claude.json');
244
244
  }
245
- /** `~/.mcp.json` — the project-pinned Claude surface (a symlink on this host). */
246
- export function mcpJsonPath(env) {
247
- return path.join(env.home, '.mcp.json');
248
- }
249
245
  /**
250
246
  * Built-in JSON {@link ConfigFormat} for the Claude surfaces. Pretty-prints with
251
247
  * a trailing newline; an empty doc is `{}`. Parsing the empty string is the
@@ -368,9 +364,9 @@ export function sanitizeParserMessage(message) {
368
364
  // Advisory O_EXCL lock (held across read->merge->write).
369
365
  // ---------------------------------------------------------------------------
370
366
  /** Default stale-lock timeout — a lock older than this whose PID is dead is broken. */
371
- export const DEFAULT_LOCK_STALE_MS = 30_000;
367
+ const DEFAULT_LOCK_STALE_MS = 30_000;
372
368
  /** Default total time to wait for a held lock before giving up. */
373
- export const DEFAULT_LOCK_WAIT_MS = 10_000;
369
+ const DEFAULT_LOCK_WAIT_MS = 10_000;
374
370
  /** The lockfile path for a target: `~/.<basename>.hqlock` (a sibling, hidden). */
375
371
  export function lockPathFor(target) {
376
372
  const dir = path.dirname(target);
@@ -18,7 +18,6 @@
18
18
  import * as Sentry from "@sentry/node";
19
19
  import type { CaptureContext, SeverityLevel } from "@sentry/node";
20
20
  export declare const DEFAULT_SENTRY_REPORT_TIMEOUT_MS = 750;
21
- export declare const MAX_SENTRY_REPORT_TIMEOUT_MS = 5000;
22
21
  export declare const MAX_SENTRY_REPORT_PAYLOAD_BYTES = 2048;
23
22
  export declare const MAX_SENTRY_REPORT_METADATA_VALUE_BYTES = 256;
24
23
  /**
@@ -34,11 +33,11 @@ export type HookSequenceEntry = {
34
33
  event: string;
35
34
  ms: number;
36
35
  };
37
- export type HookTimeoutDebugPhaseTiming = {
36
+ type HookTimeoutDebugPhaseTiming = {
38
37
  phase: string;
39
38
  elapsed_ms: number;
40
39
  };
41
- export type HookTimeoutDebugContext = {
40
+ type HookTimeoutDebugContext = {
42
41
  hook_name: string;
43
42
  hook_event: string;
44
43
  budget_ms: number;
@@ -52,9 +51,9 @@ export type HookTimeoutDebugContext = {
52
51
  spawn_ms?: number | "unavailable";
53
52
  process_count?: number | "unavailable";
54
53
  };
55
- export type SentryReportMetadataValue = string | number | boolean | HookSequenceEntry[] | HookTimeoutDebugContext;
54
+ type SentryReportMetadataValue = string | number | boolean | HookSequenceEntry[] | HookTimeoutDebugContext;
56
55
  export type SentryReportMetadata = Record<string, SentryReportMetadataValue>;
57
- export type SentryReportEvent = {
56
+ type SentryReportEvent = {
58
57
  type: string;
59
58
  message: string;
60
59
  fingerprint: string;
@@ -102,12 +101,6 @@ export type SentryReportResult = {
102
101
  export declare function readSentryReportStdin(stdin: AsyncIterable<Buffer | string>): Promise<string | null>;
103
102
  /** Unknown metadata is ignored before this cap is evaluated. */
104
103
  export declare function exceedsSentryReportMetadataKeyCap(keys: Iterable<string>): boolean;
105
- /**
106
- * Parse and validate the closed report schema without touching Sentry. The
107
- * function intentionally returns an ordinary result instead of throwing so a
108
- * hook can ignore the CLI exit code without creating an unhandled rejection.
109
- */
110
- export declare function parseSentryReportEvent(stdin: string): SentryReportResult;
111
104
  /**
112
105
  * Capture one validated Sentry message and wait only for the supplied bounded
113
106
  * flush budget. A zero result means the event entered the local transport and
@@ -117,4 +110,5 @@ export declare function parseSentryReportEvent(stdin: string): SentryReportResul
117
110
  * transport errors cannot echo event data back to a hook.
118
111
  */
119
112
  export declare function reportSentryEvent(stdin: string, options?: SentryReportOptions, dependencies?: SentryReportDependencies): Promise<SentryReportResult>;
113
+ export {};
120
114
  //# sourceMappingURL=sentry-report.d.ts.map
@@ -25,7 +25,7 @@ import { beforeSend } from "../../sentry-before-send.js";
25
25
  import { resolveLiveRoot } from "../../utils/hq-roots.js";
26
26
  import { hookTimeoutDebugContextEnabled } from "./hook-timeout-debug-context-flag.js";
27
27
  export const DEFAULT_SENTRY_REPORT_TIMEOUT_MS = 750;
28
- export const MAX_SENTRY_REPORT_TIMEOUT_MS = 5_000;
28
+ const MAX_SENTRY_REPORT_TIMEOUT_MS = 5_000;
29
29
  export const MAX_SENTRY_REPORT_PAYLOAD_BYTES = 2_048;
30
30
  export const MAX_SENTRY_REPORT_METADATA_VALUE_BYTES = 256;
31
31
  const MAX_SENTRY_REPORT_TYPE_BYTES = 64;
@@ -349,7 +349,7 @@ function invalidInput() {
349
349
  * function intentionally returns an ordinary result instead of throwing so a
350
350
  * hook can ignore the CLI exit code without creating an unhandled rejection.
351
351
  */
352
- export function parseSentryReportEvent(stdin) {
352
+ function parseSentryReportEvent(stdin) {
353
353
  if (byteLength(stdin) > MAX_SENTRY_REPORT_PAYLOAD_BYTES)
354
354
  return invalidInput();
355
355
  let parsed;
@@ -23,11 +23,6 @@ export interface LocalDbStatus {
23
23
  /** Fingerprint of path for logs that prefer not to echo full home paths. */
24
24
  pathFingerprint: string;
25
25
  }
26
- /**
27
- * Short non-reversible fingerprint of a path (for status display).
28
- * Not a secret — just avoids dumping full home paths when preferred.
29
- */
30
- export declare function fingerprintPath(filePath: string): string;
31
26
  /**
32
27
  * Open (and create if missing) the company local vault DB with WAL mode.
33
28
  * Idempotent: reopening an existing file does not recreate or wipe it.
@@ -12,7 +12,7 @@ const MIGRATIONS_TABLE = "hq_schema_migrations";
12
12
  * Short non-reversible fingerprint of a path (for status display).
13
13
  * Not a secret — just avoids dumping full home paths when preferred.
14
14
  */
15
- export function fingerprintPath(filePath) {
15
+ function fingerprintPath(filePath) {
16
16
  let h = 2166136261;
17
17
  for (let i = 0; i < filePath.length; i++) {
18
18
  h ^= filePath.charCodeAt(i);
@@ -5,9 +5,7 @@
5
5
  * companies/{company}/db/migrations/*.sql
6
6
  * Applied versions are recorded in hq_schema_migrations inside the local DB.
7
7
  */
8
- import type { LocalDb } from "./local.js";
9
8
  import type { LocalDbPathEnv } from "./paths.js";
10
- export declare const MIGRATIONS_TABLE = "hq_schema_migrations";
11
9
  export interface MigrateOptions extends LocalDbPathEnv {
12
10
  company: string;
13
11
  /**
@@ -24,16 +22,6 @@ export interface MigrateResult {
24
22
  head: string | null;
25
23
  }
26
24
  export declare function resolveMigrationsDir(hqRoot: string, companySlug: string): string;
27
- /**
28
- * Ensure migrations directory exists (creates empty dir on first migrate).
29
- */
30
- export declare function ensureMigrationsDir(hqRoot: string, companySlug: string): string;
31
- /**
32
- * List pending migration files in lexical/version order (filename sort).
33
- */
34
- export declare function listMigrationFiles(migrationsDir: string): string[];
35
- export declare function ensureMigrationsLedger(db: LocalDb): void;
36
- export declare function listAppliedVersions(db: LocalDb): Set<string>;
37
25
  /**
38
26
  * Apply pending migrations. On failure, does not mark the failed file applied.
39
27
  */
@@ -9,7 +9,7 @@ import fs from "node:fs";
9
9
  import path from "node:path";
10
10
  import { openLocalDb, readMigrationHead } from "./local.js";
11
11
  import { normalizeCompanySlugForLocalDb } from "./paths.js";
12
- export const MIGRATIONS_TABLE = "hq_schema_migrations";
12
+ const MIGRATIONS_TABLE = "hq_schema_migrations";
13
13
  export function resolveMigrationsDir(hqRoot, companySlug) {
14
14
  const slug = normalizeCompanySlugForLocalDb(companySlug);
15
15
  return path.join(hqRoot, "companies", slug, "db", "migrations");
@@ -17,7 +17,7 @@ export function resolveMigrationsDir(hqRoot, companySlug) {
17
17
  /**
18
18
  * Ensure migrations directory exists (creates empty dir on first migrate).
19
19
  */
20
- export function ensureMigrationsDir(hqRoot, companySlug) {
20
+ function ensureMigrationsDir(hqRoot, companySlug) {
21
21
  const dir = resolveMigrationsDir(hqRoot, companySlug);
22
22
  fs.mkdirSync(dir, { recursive: true });
23
23
  return dir;
@@ -25,7 +25,7 @@ export function ensureMigrationsDir(hqRoot, companySlug) {
25
25
  /**
26
26
  * List pending migration files in lexical/version order (filename sort).
27
27
  */
28
- export function listMigrationFiles(migrationsDir) {
28
+ function listMigrationFiles(migrationsDir) {
29
29
  if (!fs.existsSync(migrationsDir))
30
30
  return [];
31
31
  return fs
@@ -33,7 +33,7 @@ export function listMigrationFiles(migrationsDir) {
33
33
  .filter((f) => f.endsWith(".sql"))
34
34
  .sort((a, b) => a.localeCompare(b, "en"));
35
35
  }
36
- export function ensureMigrationsLedger(db) {
36
+ function ensureMigrationsLedger(db) {
37
37
  db.exec(`
38
38
  CREATE TABLE IF NOT EXISTS ${MIGRATIONS_TABLE} (
39
39
  version TEXT PRIMARY KEY NOT NULL,
@@ -41,7 +41,7 @@ export function ensureMigrationsLedger(db) {
41
41
  );
42
42
  `);
43
43
  }
44
- export function listAppliedVersions(db) {
44
+ function listAppliedVersions(db) {
45
45
  ensureMigrationsLedger(db);
46
46
  const rows = db
47
47
  .prepare(`SELECT version FROM ${MIGRATIONS_TABLE} ORDER BY version`)
@@ -27,14 +27,6 @@ export interface SqlRunResult {
27
27
  changes: number;
28
28
  readonly: boolean;
29
29
  }
30
- export declare function stripSqlNoise(sql: string): string;
31
- export declare function isWriteSql(sql: string): boolean;
32
- /**
33
- * Statements that must never run via `hq db sql`, even with --write.
34
- * ATTACH/DETACH would let a company-scoped session open another company's
35
- * vault.db by absolute path (category-1 isolation).
36
- */
37
- export declare function assertSqlAllowed(sql: string): void;
38
30
  /**
39
31
  * Resolve which file path to open, enforcing company isolation by default.
40
32
  */
@@ -44,6 +36,4 @@ export declare function resolveSqlDbPath(opts: SqlRunOptions): string;
44
36
  */
45
37
  export declare function runLocalSql(opts: SqlRunOptions): SqlRunResult;
46
38
  export declare function formatSqlResult(result: SqlRunResult, format?: "jsonl" | "table"): string;
47
- /** Test helper: company dir for isolation assertions. */
48
- export declare function companyLocalDbDir(company: string, env?: LocalDbPathEnv): string;
49
39
  //# sourceMappingURL=sql.d.ts.map
@@ -7,17 +7,17 @@
7
7
  */
8
8
  import Database from "better-sqlite3";
9
9
  import { openLocalDb } from "./local.js";
10
- import { normalizeCompanySlugForLocalDb, resolveLocalDbDir, resolveLocalDbPath, } from "./paths.js";
10
+ import { normalizeCompanySlugForLocalDb, resolveLocalDbPath, } from "./paths.js";
11
11
  const WRITE_PATTERN = /^\s*(INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|ALTER|TRUNCATE|REINDEX|VACUUM|BEGIN|COMMIT|ROLLBACK)\b/i;
12
12
  /** Always forbidden — opens other files/DBs and breaks company path isolation. */
13
13
  const FORBIDDEN_SQL_PATTERN = /\b(ATTACH|DETACH|LOAD_EXTENSION)\b/i;
14
- export function stripSqlNoise(sql) {
14
+ function stripSqlNoise(sql) {
15
15
  return sql
16
16
  .replace(/^\s*--[^\n]*\n/gm, "")
17
17
  .replace(/^\s*\/\*[\s\S]*?\*\//gm, "")
18
18
  .trim();
19
19
  }
20
- export function isWriteSql(sql) {
20
+ function isWriteSql(sql) {
21
21
  return WRITE_PATTERN.test(stripSqlNoise(sql));
22
22
  }
23
23
  /**
@@ -25,7 +25,7 @@ export function isWriteSql(sql) {
25
25
  * ATTACH/DETACH would let a company-scoped session open another company's
26
26
  * vault.db by absolute path (category-1 isolation).
27
27
  */
28
- export function assertSqlAllowed(sql) {
28
+ function assertSqlAllowed(sql) {
29
29
  const stripped = stripSqlNoise(sql);
30
30
  if (FORBIDDEN_SQL_PATTERN.test(stripped)) {
31
31
  throw new Error("ATTACH/DETACH/LOAD_EXTENSION are not allowed via hq db sql (tenant isolation); use the company-canonical local path only");
@@ -122,8 +122,4 @@ export function formatSqlResult(result, format = "jsonl") {
122
122
  .join("\n");
123
123
  return body ? `${header}\n${body}` : header;
124
124
  }
125
- /** Test helper: company dir for isolation assertions. */
126
- export function companyLocalDbDir(company, env) {
127
- return resolveLocalDbDir(company, env);
128
- }
129
125
  //# sourceMappingURL=sql.js.map
@@ -41,10 +41,6 @@
41
41
  */
42
42
  import { type AllowedDivergenceLoad } from "../allowed-divergence.js";
43
43
  import type { CheckContext, CheckResult } from "../types.js";
44
- /** Basename of the single-adapter script the current architecture routes to. */
45
- export declare const CODEX_ADAPTER_BASENAME = "hq-codex-hook-adapter.sh";
46
- /** Library the adapter sources to dispatch `.claude/settings.json` live. */
47
- export declare const CODEX_DISPATCH_LIB_RELPATH: string;
48
44
  /**
49
45
  * Lifecycle events the shipped `.codex/config.toml` routes through the adapter.
50
46
  * A missing event means the Claude hooks for that event never run under Codex.