@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.
- package/CHANGELOG.md +23 -0
- package/dist/command-catalog.generated.d.ts +4 -1
- package/dist/command-catalog.generated.js +5 -1
- package/dist/commands/agents.js +6 -0
- package/dist/commands/core-checkpoint-gate-setting.d.ts +0 -10
- package/dist/commands/core-checkpoint-gate-setting.js +3 -3
- package/dist/commands/core-ontology.d.ts +1 -9
- package/dist/commands/core-ontology.js +4 -4
- package/dist/commands/core-policy.d.ts +0 -3
- package/dist/commands/core-policy.js +3 -3
- package/dist/commands/files.js +1 -1
- package/dist/commands/index-cmd.js +1 -1
- package/dist/commands/integrations-api.d.ts +9 -4
- package/dist/commands/integrations-api.js +9 -6
- package/dist/commands/integrations-manage.js +11 -3
- package/dist/commands/integrations.d.ts +8 -0
- package/dist/commands/integrations.js +83 -0
- package/dist/commands/lanes-checks.d.ts +6 -2
- package/dist/commands/lanes-checks.js +69 -19
- package/dist/commands/lanes-report.js +5 -2
- package/dist/commands/lanes.d.ts +0 -11
- package/dist/commands/lanes.js +6 -6
- package/dist/commands/mcp-registration.d.ts +5 -11
- package/dist/commands/mcp-registration.js +2 -6
- package/dist/lib/core-utils/sentry-report.d.ts +5 -11
- package/dist/lib/core-utils/sentry-report.js +2 -2
- package/dist/lib/db/local.d.ts +0 -5
- package/dist/lib/db/local.js +1 -1
- package/dist/lib/db/migrate.d.ts +0 -12
- package/dist/lib/db/migrate.js +5 -5
- package/dist/lib/db/sql.d.ts +0 -10
- package/dist/lib/db/sql.js +4 -8
- package/dist/lib/doctor/checks/codex-wiring.d.ts +0 -4
- package/dist/lib/doctor/checks/codex-wiring.js +3 -35
- package/dist/lib/doctor/checks/grok-wiring.js +1 -34
- package/dist/lib/doctor/checks/runtime-health.d.ts +0 -17
- package/dist/lib/doctor/checks/runtime-health.js +4 -4
- package/dist/lib/doctor/checks/scaffold-cli-floor.d.ts +0 -1
- package/dist/lib/doctor/checks/scaffold-cli-floor.js +1 -1
- package/dist/lib/doctor/compat.d.ts +0 -16
- package/dist/lib/doctor/compat.js +3 -3
- package/dist/lib/doctor/deep/effects.js +1 -3
- package/dist/lib/doctor/deep/sandbox.js +1 -3
- package/dist/lib/doctor/fixtures/schema.js +1 -3
- package/dist/lib/doctor/platform.d.ts +0 -26
- package/dist/lib/doctor/platform.js +5 -5
- package/dist/lib/doctor/shared.d.ts +8 -0
- package/dist/lib/doctor/shared.js +38 -0
- package/dist/lib/lanes/autopilot.js +125 -103
- package/dist/lib/monitor.d.ts +2 -6
- package/dist/lib/monitor.js +5 -5
- package/dist/lib/onboarding/errors.d.ts +2 -1
- package/dist/lib/onboarding/errors.js +1 -1
- package/dist/lib/onboarding/index.d.ts +2 -6
- package/dist/lib/onboarding/index.js +2 -5
- package/dist/lib/report-publish.d.ts +1 -10
- package/dist/lib/report-publish.js +3 -9
- package/dist/lib/search-index/embed-lock.d.ts +0 -7
- package/dist/lib/search-index/embed-lock.js +1 -1
- package/dist/lib/search-index/index.d.ts +7 -0
- package/dist/lib/search-index/index.js +21 -2
- package/dist/lib/search-index/load-gate.d.ts +0 -8
- package/dist/lib/search-index/load-gate.js +3 -3
- package/dist/lib/search-index/max-doc-bytes.d.ts +2 -3
- package/dist/lib/search-index/max-doc-bytes.js +1 -1
- package/dist/lib/search-index/qmd-exit-diagnostics.d.ts +5 -0
- package/dist/lib/search-index/qmd-exit-diagnostics.js +40 -0
- package/dist/lib/service-manager/launchd.d.ts +0 -7
- package/dist/lib/service-manager/launchd.js +2 -2
- package/dist/main.js +7 -2
- package/dist/startup-registration.js +9 -1
- package/dist/utils/client-health.d.ts +0 -4
- package/dist/utils/client-health.js +2 -2
- package/dist/utils/feedback-diagnostics.d.ts +2 -1
- package/dist/utils/feedback-log-bundle.d.ts +0 -25
- package/dist/utils/feedback-log-bundle.js +5 -5
- package/dist/utils/feedback-logs.d.ts +4 -38
- package/dist/utils/feedback-logs.js +7 -7
- package/dist/utils/feedback-screenshots.d.ts +0 -1
- package/dist/utils/feedback-screenshots.js +1 -1
- package/dist/utils/install-tree-torn.d.ts +19 -13
- package/dist/utils/install-tree-torn.js +77 -2
- package/dist/utils/local-files-overview.d.ts +0 -6
- package/dist/utils/local-files-overview.js +1 -1
- package/dist/utils/qmd-model-download-error.d.ts +0 -8
- package/dist/utils/qmd-model-download-error.js +1 -1
- package/dist/utils/qmd-query-document-error.d.ts +0 -6
- package/dist/utils/qmd-query-document-error.js +1 -1
- package/dist/utils/scaffold-fast-import-guard.d.ts +0 -1
- package/dist/utils/scaffold-fast-import-guard.js +1 -1
- package/dist/utils/scaffold-sibling-references.d.ts +3 -2
- package/dist/utils/sentry-fingerprint.js +17 -0
- package/dist/utils/version-gate.d.ts +4 -0
- package/dist/utils/version-gate.js +13 -0
- 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
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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.
|
|
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.
|
|
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(([
|
|
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
|
-
|
|
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
|
|
859
|
-
const
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
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);
|
package/dist/commands/lanes.d.ts
CHANGED
|
@@ -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
|
package/dist/commands/lanes.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
78
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
367
|
+
const DEFAULT_LOCK_STALE_MS = 30_000;
|
|
372
368
|
/** Default total time to wait for a held lock before giving up. */
|
|
373
|
-
|
|
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
|
-
|
|
36
|
+
type HookTimeoutDebugPhaseTiming = {
|
|
38
37
|
phase: string;
|
|
39
38
|
elapsed_ms: number;
|
|
40
39
|
};
|
|
41
|
-
|
|
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
|
-
|
|
54
|
+
type SentryReportMetadataValue = string | number | boolean | HookSequenceEntry[] | HookTimeoutDebugContext;
|
|
56
55
|
export type SentryReportMetadata = Record<string, SentryReportMetadataValue>;
|
|
57
|
-
|
|
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
|
-
|
|
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
|
-
|
|
352
|
+
function parseSentryReportEvent(stdin) {
|
|
353
353
|
if (byteLength(stdin) > MAX_SENTRY_REPORT_PAYLOAD_BYTES)
|
|
354
354
|
return invalidInput();
|
|
355
355
|
let parsed;
|
package/dist/lib/db/local.d.ts
CHANGED
|
@@ -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.
|
package/dist/lib/db/local.js
CHANGED
|
@@ -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
|
-
|
|
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);
|
package/dist/lib/db/migrate.d.ts
CHANGED
|
@@ -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
|
*/
|
package/dist/lib/db/migrate.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
44
|
+
function listAppliedVersions(db) {
|
|
45
45
|
ensureMigrationsLedger(db);
|
|
46
46
|
const rows = db
|
|
47
47
|
.prepare(`SELECT version FROM ${MIGRATIONS_TABLE} ORDER BY version`)
|
package/dist/lib/db/sql.d.ts
CHANGED
|
@@ -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
|
package/dist/lib/db/sql.js
CHANGED
|
@@ -7,17 +7,17 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import Database from "better-sqlite3";
|
|
9
9
|
import { openLocalDb } from "./local.js";
|
|
10
|
-
import { normalizeCompanySlugForLocalDb,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|