halfcycle 0.3.31 → 0.3.32
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/.claude-plugin/plugin.json +1 -1
- package/bin/bin.bundle.mjs +310 -40
- package/dist/bin.js +212 -108
- package/dist/bin.js.map +3 -3
- package/dist/identity.d.ts +39 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/index.js +196 -102
- package/dist/index.js.map +3 -3
- package/dist/install.d.ts +60 -40
- package/dist/install.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "halfcycle",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.32",
|
|
4
4
|
"description": "Halfcycle Method bundle — resolution-stub slash commands, remote method-delivery registration, and governance-hook wiring for a Halfcycle engagement repo. It ships NO worker role files: a project's roles are authored from that project's own recorded decisions at orchestration kickoff (FX-2, W3-F-27).",
|
|
5
5
|
"commands": [
|
|
6
6
|
{
|
package/bin/bin.bundle.mjs
CHANGED
|
@@ -14652,6 +14652,75 @@ function parseAccountStoreText(raw) {
|
|
|
14652
14652
|
// ../core/dist/ci-audience.js
|
|
14653
14653
|
var HALFCYCLE_OIDC_AUDIENCE = "https://halfcycle.ai";
|
|
14654
14654
|
|
|
14655
|
+
// ../core/dist/hook-wiring.js
|
|
14656
|
+
var SETTINGS_REL = ".claude/settings.json";
|
|
14657
|
+
var LOCAL_SETTINGS_REL = ".claude/settings.local.json";
|
|
14658
|
+
var VENDORED_BIN_REL = ".halfcycle/bin/bin.bundle.mjs";
|
|
14659
|
+
var SESSION_START_MARKER_REL = ".claude/hooks/session-start-marker.sh";
|
|
14660
|
+
var GUARD_RUNNER_REL = ".claude/hooks/guard-runner.sh";
|
|
14661
|
+
var USER_PROMPT_REMINDER_REL = ".claude/hooks/user-prompt-reminder.sh";
|
|
14662
|
+
var SESSION_END_MARKER_REL = ".claude/hooks/session-end-marker.sh";
|
|
14663
|
+
var WRITE_CAPABLE_TOOLS = ["Edit", "MultiEdit", "NotebookEdit", "Write"];
|
|
14664
|
+
var HALFCYCLE_HOOK_WIRING = [
|
|
14665
|
+
{
|
|
14666
|
+
event: "SessionStart",
|
|
14667
|
+
matcher: null,
|
|
14668
|
+
timeout: 5,
|
|
14669
|
+
command: `bash ./${SESSION_START_MARKER_REL}`,
|
|
14670
|
+
script: SESSION_START_MARKER_REL
|
|
14671
|
+
},
|
|
14672
|
+
{
|
|
14673
|
+
event: "SessionStart",
|
|
14674
|
+
matcher: null,
|
|
14675
|
+
timeout: 10,
|
|
14676
|
+
command: `bash ./${GUARD_RUNNER_REL} refresh-credential`,
|
|
14677
|
+
script: GUARD_RUNNER_REL
|
|
14678
|
+
},
|
|
14679
|
+
{
|
|
14680
|
+
event: "UserPromptSubmit",
|
|
14681
|
+
matcher: null,
|
|
14682
|
+
timeout: 5,
|
|
14683
|
+
command: `bash ./${USER_PROMPT_REMINDER_REL}`,
|
|
14684
|
+
script: USER_PROMPT_REMINDER_REL
|
|
14685
|
+
},
|
|
14686
|
+
{
|
|
14687
|
+
event: "PostToolUse",
|
|
14688
|
+
matcher: WRITE_CAPABLE_TOOLS.join("|"),
|
|
14689
|
+
timeout: 60,
|
|
14690
|
+
command: `bash ./${GUARD_RUNNER_REL} hook post-tool-use`,
|
|
14691
|
+
script: GUARD_RUNNER_REL
|
|
14692
|
+
},
|
|
14693
|
+
{
|
|
14694
|
+
event: "Stop",
|
|
14695
|
+
matcher: null,
|
|
14696
|
+
timeout: 60,
|
|
14697
|
+
command: `bash ./${GUARD_RUNNER_REL} hook stop`,
|
|
14698
|
+
script: GUARD_RUNNER_REL
|
|
14699
|
+
},
|
|
14700
|
+
{
|
|
14701
|
+
event: "SubagentStop",
|
|
14702
|
+
matcher: null,
|
|
14703
|
+
timeout: 60,
|
|
14704
|
+
command: `bash ./${GUARD_RUNNER_REL} hook subagent-stop`,
|
|
14705
|
+
script: GUARD_RUNNER_REL
|
|
14706
|
+
},
|
|
14707
|
+
{
|
|
14708
|
+
event: "SessionEnd",
|
|
14709
|
+
matcher: null,
|
|
14710
|
+
timeout: 5,
|
|
14711
|
+
command: `bash ./${SESSION_END_MARKER_REL}`,
|
|
14712
|
+
script: SESSION_END_MARKER_REL
|
|
14713
|
+
}
|
|
14714
|
+
];
|
|
14715
|
+
var RETIRED_HOOK_COMMANDS = [];
|
|
14716
|
+
var HALFCYCLE_HOOK_COMMANDS = /* @__PURE__ */ new Set([
|
|
14717
|
+
...HALFCYCLE_HOOK_WIRING.map((entry) => entry.command),
|
|
14718
|
+
...RETIRED_HOOK_COMMANDS
|
|
14719
|
+
]);
|
|
14720
|
+
var HALFCYCLE_HOOK_WIRING_PATHS = [
|
|
14721
|
+
.../* @__PURE__ */ new Set([SETTINGS_REL, ...HALFCYCLE_HOOK_WIRING.map((entry) => entry.script), VENDORED_BIN_REL])
|
|
14722
|
+
];
|
|
14723
|
+
|
|
14655
14724
|
// dist/control-origin.js
|
|
14656
14725
|
var DEFAULT_CONTROL_ORIGIN = "https://control.halfcycle.ai";
|
|
14657
14726
|
function resolveControlOrigin(env) {
|
|
@@ -14809,6 +14878,25 @@ var CLIENT_CAPABILITY_VOCABULARY = Object.keys(diffMetadataSchema.shape).filter(
|
|
|
14809
14878
|
function isClientCapability(value) {
|
|
14810
14879
|
return CLIENT_CAPABILITY_VOCABULARY.includes(value);
|
|
14811
14880
|
}
|
|
14881
|
+
var seatHookSchema = external_exports.object({
|
|
14882
|
+
event: external_exports.string(),
|
|
14883
|
+
matcher: external_exports.string().nullable(),
|
|
14884
|
+
command: external_exports.string(),
|
|
14885
|
+
timeout: external_exports.number().nullable()
|
|
14886
|
+
}).strict();
|
|
14887
|
+
var seatSettingsFileSchema = external_exports.object({
|
|
14888
|
+
path: external_exports.string(),
|
|
14889
|
+
state: external_exports.enum(["read", "absent", "unreadable"]),
|
|
14890
|
+
hooks: external_exports.array(seatHookSchema)
|
|
14891
|
+
}).strict();
|
|
14892
|
+
var seatPathSchema = external_exports.object({
|
|
14893
|
+
path: external_exports.string(),
|
|
14894
|
+
state: external_exports.enum(["clean", "modified", "added", "deleted", "untracked", "ignored", "absent", "unknown"])
|
|
14895
|
+
}).strict();
|
|
14896
|
+
var seatConfigurationSchema = external_exports.object({
|
|
14897
|
+
settingsFiles: external_exports.array(seatSettingsFileSchema),
|
|
14898
|
+
paths: external_exports.array(seatPathSchema)
|
|
14899
|
+
}).strict();
|
|
14812
14900
|
var evaluationRequestSchema = external_exports.object({
|
|
14813
14901
|
engagementId: external_exports.string(),
|
|
14814
14902
|
changeSet: changeSetSchema,
|
|
@@ -14829,7 +14917,17 @@ var evaluationRequestSchema = external_exports.object({
|
|
|
14829
14917
|
*
|
|
14830
14918
|
* Omitting the field means "unknown": every check runs as it always has.
|
|
14831
14919
|
*/
|
|
14832
|
-
repoHasDeployFiles: external_exports.boolean().optional()
|
|
14920
|
+
repoHasDeployFiles: external_exports.boolean().optional(),
|
|
14921
|
+
/**
|
|
14922
|
+
* The hooks this tool installed that this project's own settings files
|
|
14923
|
+
* register, each with the event, matcher and timeout it is registered
|
|
14924
|
+
* under, and whether each file those hooks rely on is committed and
|
|
14925
|
+
* unchanged. Sent as found: the service decides what it means, and
|
|
14926
|
+
* nothing about it is sent back.
|
|
14927
|
+
*
|
|
14928
|
+
* Omitting the field means "not observed", never "set up".
|
|
14929
|
+
*/
|
|
14930
|
+
seatConfiguration: seatConfigurationSchema.optional()
|
|
14833
14931
|
}).strict();
|
|
14834
14932
|
|
|
14835
14933
|
// ../events/dist/result.js
|
|
@@ -15508,8 +15606,12 @@ async function attempt(url2, token, request, fetchFn, retry) {
|
|
|
15508
15606
|
import { spawnSync } from "node:child_process";
|
|
15509
15607
|
import { readFileSync } from "node:fs";
|
|
15510
15608
|
import { relative } from "node:path";
|
|
15511
|
-
function git(args2, cwd) {
|
|
15512
|
-
const result = spawnSync("git", args2, {
|
|
15609
|
+
function git(args2, cwd, timeoutMs) {
|
|
15610
|
+
const result = spawnSync("git", args2, {
|
|
15611
|
+
cwd,
|
|
15612
|
+
encoding: "utf-8",
|
|
15613
|
+
...timeoutMs === void 0 ? {} : { timeout: timeoutMs }
|
|
15614
|
+
});
|
|
15513
15615
|
if (result.error) {
|
|
15514
15616
|
return { ok: false, message: `git error: ${result.error.message}` };
|
|
15515
15617
|
}
|
|
@@ -15653,6 +15755,20 @@ function refExists(ref, repoRoot) {
|
|
|
15653
15755
|
const result = git(["rev-parse", "--verify", "--quiet", `${ref}^{commit}`], repoRoot);
|
|
15654
15756
|
return result.ok && result.value.trim().length > 0;
|
|
15655
15757
|
}
|
|
15758
|
+
var WIRING_STATUS_TIMEOUT_MS = 2e3;
|
|
15759
|
+
function getWiringStatus(pathspecs, cwd) {
|
|
15760
|
+
return git([
|
|
15761
|
+
"--no-optional-locks",
|
|
15762
|
+
"status",
|
|
15763
|
+
"--porcelain=v1",
|
|
15764
|
+
"-z",
|
|
15765
|
+
"--no-renames",
|
|
15766
|
+
"--ignored=traditional",
|
|
15767
|
+
"--untracked-files=all",
|
|
15768
|
+
"--",
|
|
15769
|
+
...pathspecs
|
|
15770
|
+
], cwd, WIRING_STATUS_TIMEOUT_MS);
|
|
15771
|
+
}
|
|
15656
15772
|
|
|
15657
15773
|
// dist/screen/secret-shape.js
|
|
15658
15774
|
var SECRET_SHAPE_PATTERNS = [
|
|
@@ -16614,13 +16730,14 @@ function deriveClientCapabilities(changeSet) {
|
|
|
16614
16730
|
}
|
|
16615
16731
|
return [...seen];
|
|
16616
16732
|
}
|
|
16617
|
-
function buildEvaluationRequest(engagementId, changeSet, context) {
|
|
16733
|
+
function buildEvaluationRequest(engagementId, changeSet, context, seatConfiguration) {
|
|
16618
16734
|
const hasDeployFiles = repoHasDeployFiles(context);
|
|
16619
16735
|
return {
|
|
16620
16736
|
engagementId,
|
|
16621
16737
|
changeSet,
|
|
16622
16738
|
clientCapabilities: deriveClientCapabilities(changeSet),
|
|
16623
|
-
...hasDeployFiles === void 0 ? {} : { repoHasDeployFiles: hasDeployFiles }
|
|
16739
|
+
...hasDeployFiles === void 0 ? {} : { repoHasDeployFiles: hasDeployFiles },
|
|
16740
|
+
...seatConfiguration === void 0 ? {} : { seatConfiguration }
|
|
16624
16741
|
};
|
|
16625
16742
|
}
|
|
16626
16743
|
function produceExcerpts(diffContent, descriptors, caps) {
|
|
@@ -17237,14 +17354,165 @@ async function evaluateWithRefresh(opts) {
|
|
|
17237
17354
|
return { result: retry, token: refreshed.token, remedy: HOOK_REMEDY };
|
|
17238
17355
|
}
|
|
17239
17356
|
|
|
17357
|
+
// dist/seat-configuration.js
|
|
17358
|
+
import { existsSync as existsSync2, readFileSync as readFileSync6, realpathSync as realpathSync2 } from "node:fs";
|
|
17359
|
+
import { homedir as homedir3 } from "node:os";
|
|
17360
|
+
import { join as join6, relative as relative3, resolve } from "node:path";
|
|
17361
|
+
function gatherSeatConfiguration(repoRoot, read = readSeatConfiguration) {
|
|
17362
|
+
try {
|
|
17363
|
+
const facts = read(repoRoot);
|
|
17364
|
+
if (facts === void 0)
|
|
17365
|
+
return void 0;
|
|
17366
|
+
const parsed = seatConfigurationSchema.safeParse(facts);
|
|
17367
|
+
return parsed.success ? parsed.data : void 0;
|
|
17368
|
+
} catch {
|
|
17369
|
+
return void 0;
|
|
17370
|
+
}
|
|
17371
|
+
}
|
|
17372
|
+
function readSeatConfiguration(repoRoot) {
|
|
17373
|
+
const given = resolve(process.env["CLAUDE_PROJECT_DIR"] || process.cwd());
|
|
17374
|
+
const projectDir = realpathSync2.native(given);
|
|
17375
|
+
const home = homedir3();
|
|
17376
|
+
let realHome = home;
|
|
17377
|
+
try {
|
|
17378
|
+
realHome = realpathSync2.native(home);
|
|
17379
|
+
} catch {
|
|
17380
|
+
realHome = home;
|
|
17381
|
+
}
|
|
17382
|
+
if (projectDir === home || given === home || projectDir === realHome)
|
|
17383
|
+
return void 0;
|
|
17384
|
+
return {
|
|
17385
|
+
settingsFiles: [readSettingsFile(projectDir, SETTINGS_REL), readSettingsFile(projectDir, LOCAL_SETTINGS_REL)],
|
|
17386
|
+
paths: readPathStates(projectDir, repoRoot)
|
|
17387
|
+
};
|
|
17388
|
+
}
|
|
17389
|
+
function isPlainObject2(value) {
|
|
17390
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17391
|
+
}
|
|
17392
|
+
function readSettingsFile(projectDir, rel) {
|
|
17393
|
+
let raw;
|
|
17394
|
+
try {
|
|
17395
|
+
raw = readFileSync6(join6(projectDir, rel), "utf-8");
|
|
17396
|
+
} catch (err) {
|
|
17397
|
+
const code = err.code;
|
|
17398
|
+
const state = code === "ENOENT" || code === "ENOTDIR" ? "absent" : "unreadable";
|
|
17399
|
+
return { path: rel, state, hooks: [] };
|
|
17400
|
+
}
|
|
17401
|
+
let parsed;
|
|
17402
|
+
try {
|
|
17403
|
+
parsed = JSON.parse(raw);
|
|
17404
|
+
} catch {
|
|
17405
|
+
return { path: rel, state: "unreadable", hooks: [] };
|
|
17406
|
+
}
|
|
17407
|
+
if (!isPlainObject2(parsed))
|
|
17408
|
+
return { path: rel, state: "unreadable", hooks: [] };
|
|
17409
|
+
return { path: rel, state: "read", hooks: ourHooks(parsed["hooks"]) };
|
|
17410
|
+
}
|
|
17411
|
+
function ourHooks(hooks) {
|
|
17412
|
+
if (!isPlainObject2(hooks))
|
|
17413
|
+
return [];
|
|
17414
|
+
const rows = [];
|
|
17415
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17416
|
+
for (const [event, entries] of Object.entries(hooks)) {
|
|
17417
|
+
if (!Array.isArray(entries))
|
|
17418
|
+
continue;
|
|
17419
|
+
for (const entry of entries) {
|
|
17420
|
+
if (!isPlainObject2(entry))
|
|
17421
|
+
continue;
|
|
17422
|
+
let matcher = null;
|
|
17423
|
+
if (Object.hasOwn(entry, "matcher")) {
|
|
17424
|
+
if (typeof entry["matcher"] !== "string")
|
|
17425
|
+
continue;
|
|
17426
|
+
matcher = entry["matcher"];
|
|
17427
|
+
}
|
|
17428
|
+
const commands = entry["hooks"];
|
|
17429
|
+
if (!Array.isArray(commands))
|
|
17430
|
+
continue;
|
|
17431
|
+
for (const hook of commands) {
|
|
17432
|
+
if (!isPlainObject2(hook))
|
|
17433
|
+
continue;
|
|
17434
|
+
const command = hook["command"];
|
|
17435
|
+
if (typeof command !== "string" || !HALFCYCLE_HOOK_COMMANDS.has(command))
|
|
17436
|
+
continue;
|
|
17437
|
+
let timeout = null;
|
|
17438
|
+
if (Object.hasOwn(hook, "timeout")) {
|
|
17439
|
+
const value = hook["timeout"];
|
|
17440
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
17441
|
+
continue;
|
|
17442
|
+
timeout = value;
|
|
17443
|
+
}
|
|
17444
|
+
const key = JSON.stringify([event, matcher, command, timeout]);
|
|
17445
|
+
if (seen.has(key))
|
|
17446
|
+
continue;
|
|
17447
|
+
seen.add(key);
|
|
17448
|
+
rows.push({ event, matcher, command, timeout });
|
|
17449
|
+
}
|
|
17450
|
+
}
|
|
17451
|
+
}
|
|
17452
|
+
return rows;
|
|
17453
|
+
}
|
|
17454
|
+
function readPathStates(projectDir, repoRoot) {
|
|
17455
|
+
const unknown2 = () => HALFCYCLE_HOOK_WIRING_PATHS.map((path) => ({ path, state: "unknown" }));
|
|
17456
|
+
let projectTop = projectDir;
|
|
17457
|
+
if (repoRoot !== projectDir) {
|
|
17458
|
+
const top = getRepoRoot(projectDir);
|
|
17459
|
+
if (!top.ok)
|
|
17460
|
+
return unknown2();
|
|
17461
|
+
projectTop = top.value;
|
|
17462
|
+
}
|
|
17463
|
+
const prefix = relative3(projectTop, projectDir);
|
|
17464
|
+
const status = getWiringStatus(HALFCYCLE_HOOK_WIRING_PATHS, projectDir);
|
|
17465
|
+
if (!status.ok)
|
|
17466
|
+
return unknown2();
|
|
17467
|
+
const mapped = mapWiringStatus(status.value, prefix, HALFCYCLE_HOOK_WIRING_PATHS, (rel) => existsSync2(join6(projectDir, rel)));
|
|
17468
|
+
return mapped ?? unknown2();
|
|
17469
|
+
}
|
|
17470
|
+
function mapWiringStatus(output, prefix, paths, onDisk) {
|
|
17471
|
+
const byGitPath = /* @__PURE__ */ new Map();
|
|
17472
|
+
for (const rel of paths)
|
|
17473
|
+
byGitPath.set(prefix === "" ? rel : `${prefix}/${rel}`, rel);
|
|
17474
|
+
const codes = /* @__PURE__ */ new Map();
|
|
17475
|
+
if (output !== "") {
|
|
17476
|
+
if (!output.endsWith("\0"))
|
|
17477
|
+
return null;
|
|
17478
|
+
for (const record2 of output.slice(0, -1).split("\0")) {
|
|
17479
|
+
if (record2.length < 4 || record2[2] !== " ")
|
|
17480
|
+
return null;
|
|
17481
|
+
const rel = byGitPath.get(record2.slice(3));
|
|
17482
|
+
if (rel === void 0)
|
|
17483
|
+
return null;
|
|
17484
|
+
const xy = record2.slice(0, 2);
|
|
17485
|
+
const existing = codes.get(rel);
|
|
17486
|
+
if (existing)
|
|
17487
|
+
existing.push(xy);
|
|
17488
|
+
else
|
|
17489
|
+
codes.set(rel, [xy]);
|
|
17490
|
+
}
|
|
17491
|
+
}
|
|
17492
|
+
return paths.map((path) => {
|
|
17493
|
+
const xys = codes.get(path);
|
|
17494
|
+
if (!xys)
|
|
17495
|
+
return { path, state: onDisk(path) ? "clean" : "absent" };
|
|
17496
|
+
if (xys.some((xy) => xy.includes("D")))
|
|
17497
|
+
return { path, state: "deleted" };
|
|
17498
|
+
if (xys.includes("??"))
|
|
17499
|
+
return { path, state: "untracked" };
|
|
17500
|
+
if (xys.includes("!!"))
|
|
17501
|
+
return { path, state: "ignored" };
|
|
17502
|
+
if (xys.some((xy) => xy[0] === "A"))
|
|
17503
|
+
return { path, state: "added" };
|
|
17504
|
+
return { path, state: "modified" };
|
|
17505
|
+
});
|
|
17506
|
+
}
|
|
17507
|
+
|
|
17240
17508
|
// dist/hooks/post-tool-use.js
|
|
17241
17509
|
var HANDLED_EDIT_TOOLS = /* @__PURE__ */ new Set(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
|
|
17242
|
-
async function runPostToolUse() {
|
|
17510
|
+
async function runPostToolUse(readSeat = readSeatConfiguration) {
|
|
17243
17511
|
const reply = hookReply("PostToolUse");
|
|
17244
|
-
await evaluateEdit(reply);
|
|
17512
|
+
await evaluateEdit(reply, readSeat);
|
|
17245
17513
|
reply.flush();
|
|
17246
17514
|
}
|
|
17247
|
-
async function evaluateEdit(reply) {
|
|
17515
|
+
async function evaluateEdit(reply, readSeat) {
|
|
17248
17516
|
let input;
|
|
17249
17517
|
try {
|
|
17250
17518
|
const raw = await readStdin();
|
|
@@ -17282,11 +17550,12 @@ async function evaluateEdit(reply) {
|
|
|
17282
17550
|
return;
|
|
17283
17551
|
}
|
|
17284
17552
|
const { guardServiceUrl, guardServiceToken, guardEngagementId } = configResult.config;
|
|
17553
|
+
const seatConfiguration = gatherSeatConfiguration(repoRoot, readSeat);
|
|
17285
17554
|
const evaluation = await evaluateWithRefresh({
|
|
17286
17555
|
guardServiceUrl,
|
|
17287
17556
|
token: guardServiceToken,
|
|
17288
17557
|
engagementId: guardEngagementId,
|
|
17289
|
-
request: buildEvaluationRequest(guardEngagementId, changeSet, context)
|
|
17558
|
+
request: buildEvaluationRequest(guardEngagementId, changeSet, context, seatConfiguration)
|
|
17290
17559
|
});
|
|
17291
17560
|
const clientResult = evaluation.result;
|
|
17292
17561
|
if (!clientResult.ok) {
|
|
@@ -17367,19 +17636,19 @@ ${guardLines}${notRunBlock}`);
|
|
|
17367
17636
|
}
|
|
17368
17637
|
}
|
|
17369
17638
|
function readStdin() {
|
|
17370
|
-
return new Promise((
|
|
17639
|
+
return new Promise((resolve2, reject) => {
|
|
17371
17640
|
const chunks = [];
|
|
17372
17641
|
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
17373
|
-
process.stdin.on("end", () =>
|
|
17642
|
+
process.stdin.on("end", () => resolve2(Buffer.concat(chunks).toString("utf-8")));
|
|
17374
17643
|
process.stdin.on("error", reject);
|
|
17375
17644
|
});
|
|
17376
17645
|
}
|
|
17377
17646
|
|
|
17378
17647
|
// dist/hooks/marker.js
|
|
17379
17648
|
import { createHash } from "node:crypto";
|
|
17380
|
-
import { existsSync as
|
|
17649
|
+
import { existsSync as existsSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync3, unlinkSync as unlinkSync3, readdirSync as readdirSync3, statSync } from "node:fs";
|
|
17381
17650
|
import { tmpdir } from "node:os";
|
|
17382
|
-
import { join as
|
|
17651
|
+
import { join as join7 } from "node:path";
|
|
17383
17652
|
var MARKER_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
17384
17653
|
var MARKER_PREFIX = "halfcycle-session-";
|
|
17385
17654
|
var MARKER_SUFFIX = ".ref";
|
|
@@ -17397,19 +17666,19 @@ function markerFileName(repoRoot, sessionId) {
|
|
|
17397
17666
|
return `${MARKER_PREFIX}${key}${MARKER_SUFFIX}`;
|
|
17398
17667
|
}
|
|
17399
17668
|
function markerPath(repoRoot, sessionId) {
|
|
17400
|
-
return
|
|
17669
|
+
return join7(markerDir(), markerFileName(repoRoot, sessionId));
|
|
17401
17670
|
}
|
|
17402
17671
|
function dedupePath(repoRoot, sessionId) {
|
|
17403
17672
|
const hash2 = repoHash(repoRoot);
|
|
17404
17673
|
const key = sessionId && sessionId.length > 0 ? `${hash2}-${sessionId}` : hash2;
|
|
17405
|
-
return
|
|
17674
|
+
return join7(markerDir(), `${MARKER_PREFIX}${key}${DEDUPE_SUFFIX}`);
|
|
17406
17675
|
}
|
|
17407
17676
|
function readMarker(repoRoot, sessionId) {
|
|
17408
17677
|
const path = markerPath(repoRoot, sessionId);
|
|
17409
|
-
if (!
|
|
17678
|
+
if (!existsSync3(path))
|
|
17410
17679
|
return null;
|
|
17411
17680
|
try {
|
|
17412
|
-
return
|
|
17681
|
+
return readFileSync7(path, "utf-8").trim() || null;
|
|
17413
17682
|
} catch {
|
|
17414
17683
|
return null;
|
|
17415
17684
|
}
|
|
@@ -17417,7 +17686,7 @@ function readMarker(repoRoot, sessionId) {
|
|
|
17417
17686
|
function deleteMarker(repoRoot, sessionId) {
|
|
17418
17687
|
for (const path of [markerPath(repoRoot, sessionId), dedupePath(repoRoot, sessionId)]) {
|
|
17419
17688
|
try {
|
|
17420
|
-
if (
|
|
17689
|
+
if (existsSync3(path))
|
|
17421
17690
|
unlinkSync3(path);
|
|
17422
17691
|
} catch {
|
|
17423
17692
|
}
|
|
@@ -17425,10 +17694,10 @@ function deleteMarker(repoRoot, sessionId) {
|
|
|
17425
17694
|
}
|
|
17426
17695
|
function readDedupe(repoRoot, sessionId) {
|
|
17427
17696
|
const path = dedupePath(repoRoot, sessionId);
|
|
17428
|
-
if (!
|
|
17697
|
+
if (!existsSync3(path))
|
|
17429
17698
|
return null;
|
|
17430
17699
|
try {
|
|
17431
|
-
const parsed = JSON.parse(
|
|
17700
|
+
const parsed = JSON.parse(readFileSync7(path, "utf-8"));
|
|
17432
17701
|
if (typeof parsed === "object" && parsed !== null && typeof parsed.base === "string" && typeof parsed.digest === "string") {
|
|
17433
17702
|
return parsed;
|
|
17434
17703
|
}
|
|
@@ -17470,10 +17739,10 @@ function orphanSweep(repoRoot, refKnown, keepSessionId, now = Date.now()) {
|
|
|
17470
17739
|
continue;
|
|
17471
17740
|
if (name === keepName)
|
|
17472
17741
|
continue;
|
|
17473
|
-
const full =
|
|
17742
|
+
const full = join7(dir, name);
|
|
17474
17743
|
let unusable = false;
|
|
17475
17744
|
try {
|
|
17476
|
-
const ref =
|
|
17745
|
+
const ref = readFileSync7(full, "utf-8").trim();
|
|
17477
17746
|
if (!ref || !refKnown(ref))
|
|
17478
17747
|
unusable = true;
|
|
17479
17748
|
} catch {
|
|
@@ -17531,12 +17800,12 @@ function collectDiff(repoRoot, base) {
|
|
|
17531
17800
|
getDiff: (relPath) => getWorkingTreeFileDiff(relPath, repoRoot)
|
|
17532
17801
|
};
|
|
17533
17802
|
}
|
|
17534
|
-
async function runSessionDiff(input, kind) {
|
|
17803
|
+
async function runSessionDiff(input, kind, readSeat = readSeatConfiguration) {
|
|
17535
17804
|
const reply = hookReply(STOP_HOOK_EVENT[kind]);
|
|
17536
|
-
await evaluateSession(input, kind, reply);
|
|
17805
|
+
await evaluateSession(input, kind, reply, readSeat);
|
|
17537
17806
|
reply.flush();
|
|
17538
17807
|
}
|
|
17539
|
-
async function evaluateSession(input, kind, reply) {
|
|
17808
|
+
async function evaluateSession(input, kind, reply, readSeat) {
|
|
17540
17809
|
const repoRootResult = getRepoRoot(process.cwd());
|
|
17541
17810
|
if (!repoRootResult.ok) {
|
|
17542
17811
|
reply.notice(localFaultText(`Could not find git repo root: ${repoRootResult.message}`));
|
|
@@ -17576,11 +17845,12 @@ async function evaluateSession(input, kind, reply) {
|
|
|
17576
17845
|
return;
|
|
17577
17846
|
}
|
|
17578
17847
|
const { guardServiceUrl, guardServiceToken, guardEngagementId } = configResult.config;
|
|
17848
|
+
const seatConfiguration = gatherSeatConfiguration(repoRoot, readSeat);
|
|
17579
17849
|
const evaluation = await evaluateWithRefresh({
|
|
17580
17850
|
guardServiceUrl,
|
|
17581
17851
|
token: guardServiceToken,
|
|
17582
17852
|
engagementId: guardEngagementId,
|
|
17583
|
-
request: buildEvaluationRequest(guardEngagementId, changeSet, context)
|
|
17853
|
+
request: buildEvaluationRequest(guardEngagementId, changeSet, context, seatConfiguration)
|
|
17584
17854
|
});
|
|
17585
17855
|
const clientResult = evaluation.result;
|
|
17586
17856
|
if (!clientResult.ok) {
|
|
@@ -17678,9 +17948,9 @@ async function readHookStdin() {
|
|
|
17678
17948
|
}
|
|
17679
17949
|
}
|
|
17680
17950
|
function readStdin2() {
|
|
17681
|
-
return new Promise((
|
|
17951
|
+
return new Promise((resolve2) => {
|
|
17682
17952
|
if (process.stdin.isTTY) {
|
|
17683
|
-
|
|
17953
|
+
resolve2("");
|
|
17684
17954
|
return;
|
|
17685
17955
|
}
|
|
17686
17956
|
const chunks = [];
|
|
@@ -17690,7 +17960,7 @@ function readStdin2() {
|
|
|
17690
17960
|
return;
|
|
17691
17961
|
settled = true;
|
|
17692
17962
|
clearTimeout(timer);
|
|
17693
|
-
|
|
17963
|
+
resolve2(Buffer.concat(chunks).toString("utf-8"));
|
|
17694
17964
|
};
|
|
17695
17965
|
const timer = setTimeout(done, 2e3);
|
|
17696
17966
|
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
@@ -17712,17 +17982,17 @@ async function runStop() {
|
|
|
17712
17982
|
}
|
|
17713
17983
|
|
|
17714
17984
|
// dist/resolve-engagement.js
|
|
17715
|
-
import { existsSync as
|
|
17716
|
-
import { join as
|
|
17717
|
-
import { homedir as
|
|
17985
|
+
import { existsSync as existsSync4, readFileSync as readFileSync8, realpathSync as realpathSync3 } from "node:fs";
|
|
17986
|
+
import { join as join8, sep as sep2 } from "node:path";
|
|
17987
|
+
import { homedir as homedir4 } from "node:os";
|
|
17718
17988
|
function defaultRegistryPath() {
|
|
17719
|
-
return
|
|
17989
|
+
return join8(homedir4(), ".halfcycle", "registry.json");
|
|
17720
17990
|
}
|
|
17721
17991
|
function readRegistry(registryPath = defaultRegistryPath()) {
|
|
17722
|
-
if (!
|
|
17992
|
+
if (!existsSync4(registryPath))
|
|
17723
17993
|
return {};
|
|
17724
17994
|
try {
|
|
17725
|
-
const parsed = JSON.parse(
|
|
17995
|
+
const parsed = JSON.parse(readFileSync8(registryPath, "utf-8"));
|
|
17726
17996
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
17727
17997
|
return {};
|
|
17728
17998
|
const out = {};
|
|
@@ -17737,7 +18007,7 @@ function readRegistry(registryPath = defaultRegistryPath()) {
|
|
|
17737
18007
|
}
|
|
17738
18008
|
function canonicalise(p) {
|
|
17739
18009
|
try {
|
|
17740
|
-
return
|
|
18010
|
+
return realpathSync3(p);
|
|
17741
18011
|
} catch {
|
|
17742
18012
|
return p;
|
|
17743
18013
|
}
|
|
@@ -17802,7 +18072,7 @@ async function runRefreshCredential(opts) {
|
|
|
17802
18072
|
}
|
|
17803
18073
|
|
|
17804
18074
|
// dist/capture.js
|
|
17805
|
-
import { readFileSync as
|
|
18075
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3, existsSync as existsSync5 } from "node:fs";
|
|
17806
18076
|
import { dirname as dirname4 } from "node:path";
|
|
17807
18077
|
function runCapture(provider, endpoint, opts = {}) {
|
|
17808
18078
|
const repoRoot = opts.repoRoot ?? process.cwd();
|
|
@@ -17870,7 +18140,7 @@ function readInputFile(fromFile) {
|
|
|
17870
18140
|
if (!fromFile)
|
|
17871
18141
|
return void 0;
|
|
17872
18142
|
try {
|
|
17873
|
-
return
|
|
18143
|
+
return readFileSync9(fromFile, "utf-8");
|
|
17874
18144
|
} catch {
|
|
17875
18145
|
return void 0;
|
|
17876
18146
|
}
|
|
@@ -17965,10 +18235,10 @@ Commit the fixture; the next guard evaluation of this endpoint will pass.
|
|
|
17965
18235
|
process.exit(1);
|
|
17966
18236
|
}
|
|
17967
18237
|
function readStdin3() {
|
|
17968
|
-
return new Promise((
|
|
18238
|
+
return new Promise((resolve2, reject) => {
|
|
17969
18239
|
const chunks = [];
|
|
17970
18240
|
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
17971
|
-
process.stdin.on("end", () =>
|
|
18241
|
+
process.stdin.on("end", () => resolve2(Buffer.concat(chunks).toString("utf-8")));
|
|
17972
18242
|
process.stdin.on("error", reject);
|
|
17973
18243
|
});
|
|
17974
18244
|
}
|