@basou/core 0.27.0 → 0.29.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.
- package/dist/index.d.ts +184 -17
- package/dist/index.js +151 -6
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/schemas/manifest.schema.json +7 -0
package/dist/index.js
CHANGED
|
@@ -21,6 +21,118 @@ function summarizeAdapterOutput(_stream, _raw) {
|
|
|
21
21
|
throw new Error("adapter_output summary is not implemented in this release");
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
// src/adapters/claude-code/settings-hook.ts
|
|
25
|
+
var STOP_HOOK_TIMEOUT_SECONDS = 20;
|
|
26
|
+
var BASOU_STOP_HOOK = /(?:\bbasou|(?:@basou|packages)\/cli\/dist\/index\.js['"]?)\s+hook\s+stop\b/;
|
|
27
|
+
function isBasouStopHookCommand(command) {
|
|
28
|
+
return BASOU_STOP_HOOK.test(command);
|
|
29
|
+
}
|
|
30
|
+
function shellQuote(value) {
|
|
31
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
32
|
+
}
|
|
33
|
+
function buildStopHookCommand(options) {
|
|
34
|
+
const flags = [];
|
|
35
|
+
if (options.block === true) flags.push("--block");
|
|
36
|
+
if (options.minEdits !== void 0) flags.push(`--min-edits ${options.minEdits}`);
|
|
37
|
+
const suffix = flags.length > 0 ? ` ${flags.join(" ")}` : "";
|
|
38
|
+
return `node ${shellQuote(options.cliEntry)} hook stop${suffix} 2>/dev/null || true`;
|
|
39
|
+
}
|
|
40
|
+
function isRecord(value) {
|
|
41
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
42
|
+
}
|
|
43
|
+
function cloneSettings(settings) {
|
|
44
|
+
if (settings === void 0 || settings === null) return {};
|
|
45
|
+
if (!isRecord(settings)) {
|
|
46
|
+
throw new Error("Claude settings is not a JSON object.");
|
|
47
|
+
}
|
|
48
|
+
return structuredClone(settings);
|
|
49
|
+
}
|
|
50
|
+
function upsertStopHook(settings, command) {
|
|
51
|
+
const root = cloneSettings(settings);
|
|
52
|
+
if (root.hooks === void 0) {
|
|
53
|
+
root.hooks = {};
|
|
54
|
+
} else if (!isRecord(root.hooks)) {
|
|
55
|
+
throw new Error("The 'hooks' key in Claude settings is not an object.");
|
|
56
|
+
}
|
|
57
|
+
const hooks = root.hooks;
|
|
58
|
+
if (hooks.Stop === void 0) {
|
|
59
|
+
hooks.Stop = [];
|
|
60
|
+
} else if (!Array.isArray(hooks.Stop)) {
|
|
61
|
+
throw new Error("The 'hooks.Stop' key in Claude settings is not an array.");
|
|
62
|
+
}
|
|
63
|
+
const stop = hooks.Stop;
|
|
64
|
+
for (const group of stop) {
|
|
65
|
+
if (!isRecord(group) || !Array.isArray(group.hooks)) continue;
|
|
66
|
+
for (const entry of group.hooks) {
|
|
67
|
+
if (!isRecord(entry)) continue;
|
|
68
|
+
if (typeof entry.command === "string" && isBasouStopHookCommand(entry.command)) {
|
|
69
|
+
const unchanged = entry.type === "command" && entry.command === command && entry.timeout === STOP_HOOK_TIMEOUT_SECONDS;
|
|
70
|
+
entry.type = "command";
|
|
71
|
+
entry.command = command;
|
|
72
|
+
entry.timeout = STOP_HOOK_TIMEOUT_SECONDS;
|
|
73
|
+
return { settings: root, action: unchanged ? "unchanged" : "updated" };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
stop.push({ hooks: [{ type: "command", command, timeout: STOP_HOOK_TIMEOUT_SECONDS }] });
|
|
78
|
+
return { settings: root, action: "installed" };
|
|
79
|
+
}
|
|
80
|
+
function removeStopHook(settings) {
|
|
81
|
+
const root = cloneSettings(settings);
|
|
82
|
+
if (!isRecord(root.hooks) || !Array.isArray(root.hooks.Stop)) {
|
|
83
|
+
return { settings: root, action: "absent" };
|
|
84
|
+
}
|
|
85
|
+
const hooks = root.hooks;
|
|
86
|
+
const stop = hooks.Stop;
|
|
87
|
+
let removed = false;
|
|
88
|
+
const newStop = [];
|
|
89
|
+
for (const group of stop) {
|
|
90
|
+
if (!isRecord(group) || !Array.isArray(group.hooks)) {
|
|
91
|
+
newStop.push(group);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const keptHooks = group.hooks.filter((entry) => {
|
|
95
|
+
if (isRecord(entry) && typeof entry.command === "string" && isBasouStopHookCommand(entry.command)) {
|
|
96
|
+
removed = true;
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
return true;
|
|
100
|
+
});
|
|
101
|
+
if (keptHooks.length === group.hooks.length) {
|
|
102
|
+
newStop.push(group);
|
|
103
|
+
} else if (keptHooks.length > 0) {
|
|
104
|
+
group.hooks = keptHooks;
|
|
105
|
+
newStop.push(group);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (!removed) {
|
|
109
|
+
return { settings: root, action: "absent" };
|
|
110
|
+
}
|
|
111
|
+
if (newStop.length === 0) {
|
|
112
|
+
delete hooks.Stop;
|
|
113
|
+
} else {
|
|
114
|
+
hooks.Stop = newStop;
|
|
115
|
+
}
|
|
116
|
+
if (Object.keys(hooks).length === 0) {
|
|
117
|
+
delete root.hooks;
|
|
118
|
+
}
|
|
119
|
+
return { settings: root, action: "removed" };
|
|
120
|
+
}
|
|
121
|
+
function findBasouStopHookCommand(settings) {
|
|
122
|
+
if (!isRecord(settings) || !isRecord(settings.hooks) || !Array.isArray(settings.hooks.Stop)) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
for (const group of settings.hooks.Stop) {
|
|
126
|
+
if (!isRecord(group) || !Array.isArray(group.hooks)) continue;
|
|
127
|
+
for (const entry of group.hooks) {
|
|
128
|
+
if (isRecord(entry) && typeof entry.command === "string" && isBasouStopHookCommand(entry.command)) {
|
|
129
|
+
return entry.command;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
|
|
24
136
|
// src/adapters/claude-code/ask-user-question.ts
|
|
25
137
|
function readString(value) {
|
|
26
138
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
@@ -4582,6 +4694,7 @@ var ImportConfigSchema = z9.looseObject({
|
|
|
4582
4694
|
var RepoVisibilitySchema = z9.enum(["public", "private", "future-public"]);
|
|
4583
4695
|
var RepoLanguageSchema = z9.enum(["en", "ja", "en+ja"]);
|
|
4584
4696
|
var PublishKindSchema = z9.enum(["web", "npm"]);
|
|
4697
|
+
var RepoInstructionsSchema = z9.enum(["hub", "self"]);
|
|
4585
4698
|
var PublishTargetSchema = z9.looseObject({
|
|
4586
4699
|
kind: PublishKindSchema,
|
|
4587
4700
|
visibility: RepoVisibilitySchema.optional(),
|
|
@@ -4591,7 +4704,8 @@ var RepoEntrySchema = z9.looseObject({
|
|
|
4591
4704
|
path: SourceRootSchema,
|
|
4592
4705
|
visibility: RepoVisibilitySchema.optional(),
|
|
4593
4706
|
language: RepoLanguageSchema.optional(),
|
|
4594
|
-
publishes: z9.array(PublishTargetSchema).optional()
|
|
4707
|
+
publishes: z9.array(PublishTargetSchema).optional(),
|
|
4708
|
+
instructions: RepoInstructionsSchema.optional()
|
|
4595
4709
|
});
|
|
4596
4710
|
var WorkspaceMetaSchema = z9.looseObject({
|
|
4597
4711
|
id: WorkspaceIdSchema,
|
|
@@ -5365,12 +5479,17 @@ function isPublicFacing(v) {
|
|
|
5365
5479
|
function planGitignore(input) {
|
|
5366
5480
|
const plans = [];
|
|
5367
5481
|
const unknown = [];
|
|
5482
|
+
const self = [];
|
|
5368
5483
|
const unreachable = [];
|
|
5369
5484
|
for (const repo of input.repos) {
|
|
5370
5485
|
if (!repo.reachable) {
|
|
5371
5486
|
unreachable.push(repo.path);
|
|
5372
5487
|
continue;
|
|
5373
5488
|
}
|
|
5489
|
+
if (repo.self === true) {
|
|
5490
|
+
self.push(repo.path);
|
|
5491
|
+
continue;
|
|
5492
|
+
}
|
|
5374
5493
|
if (repo.visibility === void 0) {
|
|
5375
5494
|
unknown.push(repo.path);
|
|
5376
5495
|
continue;
|
|
@@ -5388,6 +5507,7 @@ function planGitignore(input) {
|
|
|
5388
5507
|
return {
|
|
5389
5508
|
plans,
|
|
5390
5509
|
unknown,
|
|
5510
|
+
self,
|
|
5391
5511
|
unreachable,
|
|
5392
5512
|
ok: plans.length === 0 && unknown.length === 0 && unreachable.length === 0
|
|
5393
5513
|
};
|
|
@@ -5476,7 +5596,8 @@ function summarizePresetPlan(facts) {
|
|
|
5476
5596
|
}
|
|
5477
5597
|
const byCanonical = /* @__PURE__ */ new Map();
|
|
5478
5598
|
for (const f of deduped) {
|
|
5479
|
-
if (f.isAnchor || !f.reachable || f.canonicalName === void 0 || !isRenderable(f))
|
|
5599
|
+
if (f.isAnchor || f.self === true || !f.reachable || f.canonicalName === void 0 || !isRenderable(f))
|
|
5600
|
+
continue;
|
|
5480
5601
|
const repos = byCanonical.get(f.canonicalName) ?? [];
|
|
5481
5602
|
repos.push(f.path);
|
|
5482
5603
|
byCanonical.set(f.canonicalName, repos);
|
|
@@ -5495,12 +5616,17 @@ function summarizePresetPlan(facts) {
|
|
|
5495
5616
|
const markerConflicts = [];
|
|
5496
5617
|
const unreadable = [];
|
|
5497
5618
|
const anchors = [];
|
|
5619
|
+
const self = [];
|
|
5498
5620
|
const unreachable = [];
|
|
5499
5621
|
for (const f of deduped) {
|
|
5500
5622
|
if (f.isAnchor) {
|
|
5501
5623
|
anchors.push(f.path);
|
|
5502
5624
|
continue;
|
|
5503
5625
|
}
|
|
5626
|
+
if (f.self === true) {
|
|
5627
|
+
self.push(f.path);
|
|
5628
|
+
continue;
|
|
5629
|
+
}
|
|
5504
5630
|
if (!f.reachable) {
|
|
5505
5631
|
unreachable.push(f.path);
|
|
5506
5632
|
continue;
|
|
@@ -5546,6 +5672,7 @@ function summarizePresetPlan(facts) {
|
|
|
5546
5672
|
unreadable,
|
|
5547
5673
|
collisions,
|
|
5548
5674
|
anchors,
|
|
5675
|
+
self,
|
|
5549
5676
|
unreachable,
|
|
5550
5677
|
ok: plans.length === 0 && markerConflicts.length === 0 && unreadable.length === 0 && collisions.length === 0 && unreachable.length === 0 && undeclared.length === 0
|
|
5551
5678
|
};
|
|
@@ -5638,6 +5765,7 @@ function classifyRetrofit(facts) {
|
|
|
5638
5765
|
};
|
|
5639
5766
|
if (!facts.declared) return { ...base, action: "refuse", reason: "not-declared" };
|
|
5640
5767
|
if (facts.isAnchor) return { ...base, action: "refuse", reason: "anchor" };
|
|
5768
|
+
if (facts.self === true) return { ...base, action: "refuse", reason: "self" };
|
|
5641
5769
|
if (!facts.reachable) return { ...base, action: "refuse", reason: "unreachable" };
|
|
5642
5770
|
if (facts.agentsState === "blocked") return { ...base, action: "refuse", reason: "blocked" };
|
|
5643
5771
|
if (facts.agentsState === "symlink")
|
|
@@ -5653,6 +5781,9 @@ function classifyRetrofit(facts) {
|
|
|
5653
5781
|
}
|
|
5654
5782
|
|
|
5655
5783
|
// src/project/roster.ts
|
|
5784
|
+
function instructionMode(entry) {
|
|
5785
|
+
return entry.instructions ?? "hub";
|
|
5786
|
+
}
|
|
5656
5787
|
function summarizeRosterDrift(input) {
|
|
5657
5788
|
const captured = new Set((input.sourceRoots ?? []).map(normalizeRelativePath));
|
|
5658
5789
|
const declared = /* @__PURE__ */ new Map();
|
|
@@ -5715,7 +5846,7 @@ function summarizeSymlinkPlan(facts) {
|
|
|
5715
5846
|
}
|
|
5716
5847
|
const byCanonical = /* @__PURE__ */ new Map();
|
|
5717
5848
|
for (const f of deduped) {
|
|
5718
|
-
if (f.isAnchor || !f.reachable || !f.canonicalPresent || f.canonicalName === void 0) {
|
|
5849
|
+
if (f.isAnchor || f.self === true || !f.reachable || !f.canonicalPresent || f.canonicalName === void 0) {
|
|
5719
5850
|
continue;
|
|
5720
5851
|
}
|
|
5721
5852
|
const repos = byCanonical.get(f.canonicalName) ?? [];
|
|
@@ -5733,6 +5864,7 @@ function summarizeSymlinkPlan(facts) {
|
|
|
5733
5864
|
const plans = [];
|
|
5734
5865
|
const conflicts = [];
|
|
5735
5866
|
const missingCanonical = [];
|
|
5867
|
+
const selfAgentsMissing = [];
|
|
5736
5868
|
const unreachable = [];
|
|
5737
5869
|
for (const f of deduped) {
|
|
5738
5870
|
if (f.isAnchor) continue;
|
|
@@ -5741,7 +5873,8 @@ function summarizeSymlinkPlan(facts) {
|
|
|
5741
5873
|
continue;
|
|
5742
5874
|
}
|
|
5743
5875
|
if (!f.canonicalPresent) {
|
|
5744
|
-
|
|
5876
|
+
if (f.self === true) selfAgentsMissing.push(f.path);
|
|
5877
|
+
else missingCanonical.push(f.path);
|
|
5745
5878
|
continue;
|
|
5746
5879
|
}
|
|
5747
5880
|
if (collidingPaths.has(f.path)) continue;
|
|
@@ -5768,9 +5901,10 @@ function summarizeSymlinkPlan(facts) {
|
|
|
5768
5901
|
plans,
|
|
5769
5902
|
conflicts,
|
|
5770
5903
|
missingCanonical,
|
|
5904
|
+
selfAgentsMissing,
|
|
5771
5905
|
unreachable,
|
|
5772
5906
|
collisions,
|
|
5773
|
-
ok: plans.length === 0 && conflicts.length === 0 && missingCanonical.length === 0 && unreachable.length === 0 && collisions.length === 0
|
|
5907
|
+
ok: plans.length === 0 && conflicts.length === 0 && missingCanonical.length === 0 && selfAgentsMissing.length === 0 && unreachable.length === 0 && collisions.length === 0
|
|
5774
5908
|
};
|
|
5775
5909
|
}
|
|
5776
5910
|
|
|
@@ -5781,6 +5915,7 @@ function isPublicFacing2(v) {
|
|
|
5781
5915
|
function summarizeWiring(facts) {
|
|
5782
5916
|
const risks = [];
|
|
5783
5917
|
const unknown = [];
|
|
5918
|
+
const self = [];
|
|
5784
5919
|
const incomplete = [];
|
|
5785
5920
|
const unreachable = [];
|
|
5786
5921
|
for (const f of facts) {
|
|
@@ -5788,7 +5923,9 @@ function summarizeWiring(facts) {
|
|
|
5788
5923
|
unreachable.push(f.path);
|
|
5789
5924
|
continue;
|
|
5790
5925
|
}
|
|
5791
|
-
if (
|
|
5926
|
+
if (f.self === true) {
|
|
5927
|
+
self.push(f.path);
|
|
5928
|
+
} else if (isPublicFacing2(f.visibility)) {
|
|
5792
5929
|
for (const file of f.instructionFiles) {
|
|
5793
5930
|
if (file.tracked) risks.push({ repo: f.path, visibility: f.visibility, file: file.name });
|
|
5794
5931
|
}
|
|
@@ -5802,6 +5939,7 @@ function summarizeWiring(facts) {
|
|
|
5802
5939
|
repos: facts,
|
|
5803
5940
|
risks,
|
|
5804
5941
|
unknown,
|
|
5942
|
+
self,
|
|
5805
5943
|
incomplete,
|
|
5806
5944
|
unreachable,
|
|
5807
5945
|
ok: risks.length === 0 && unknown.length === 0 && unreachable.length === 0
|
|
@@ -7638,6 +7776,7 @@ export {
|
|
|
7638
7776
|
PROTOCOL_END,
|
|
7639
7777
|
PROTOCOL_START,
|
|
7640
7778
|
RiskLevelSchema,
|
|
7779
|
+
STOP_HOOK_TIMEOUT_SECONDS,
|
|
7641
7780
|
STUCK_THRESHOLD_MS,
|
|
7642
7781
|
SchemaVersionSchema,
|
|
7643
7782
|
SessionIdSchema,
|
|
@@ -7665,6 +7804,7 @@ export {
|
|
|
7665
7804
|
basouPaths,
|
|
7666
7805
|
buildJsonSchemas,
|
|
7667
7806
|
buildStatusSnapshot,
|
|
7807
|
+
buildStopHookCommand,
|
|
7668
7808
|
chainEvents,
|
|
7669
7809
|
chainRawJsonLines,
|
|
7670
7810
|
classifyFilesBySourceRoot,
|
|
@@ -7686,6 +7826,7 @@ export {
|
|
|
7686
7826
|
enumerateTaskIds,
|
|
7687
7827
|
evaluateStopHook,
|
|
7688
7828
|
finalizeSessionYaml,
|
|
7829
|
+
findBasouStopHookCommand,
|
|
7689
7830
|
findErrorCode,
|
|
7690
7831
|
findReviewGaps,
|
|
7691
7832
|
formatDurationMs,
|
|
@@ -7694,6 +7835,8 @@ export {
|
|
|
7694
7835
|
getSnapshot,
|
|
7695
7836
|
importSessionFromJson,
|
|
7696
7837
|
inspectChainTail,
|
|
7838
|
+
instructionMode,
|
|
7839
|
+
isBasouStopHookCommand,
|
|
7697
7840
|
isGitNotFound,
|
|
7698
7841
|
isImportDerivedSource,
|
|
7699
7842
|
isLazyExpired,
|
|
@@ -7732,6 +7875,7 @@ export {
|
|
|
7732
7875
|
refreshTaskLinkedSessions,
|
|
7733
7876
|
reimportPreservingId,
|
|
7734
7877
|
removeMarkerSection,
|
|
7878
|
+
removeStopHook,
|
|
7735
7879
|
renderDecisions,
|
|
7736
7880
|
renderHandoff,
|
|
7737
7881
|
renderOrientation,
|
|
@@ -7761,6 +7905,7 @@ export {
|
|
|
7761
7905
|
ulid,
|
|
7762
7906
|
unknownManifestKeys,
|
|
7763
7907
|
updateTaskStatusWithEvent,
|
|
7908
|
+
upsertStopHook,
|
|
7764
7909
|
verifyEventsChain,
|
|
7765
7910
|
writeEventsBulk,
|
|
7766
7911
|
writeManifest,
|