halfcycle 0.11.1 → 0.12.0-rc.2
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/README.md +1 -1
- package/bin/bin.bundle.mjs +964 -351
- package/bin/pre-tool-use-filter.sh +4 -0
- package/commands/agent-teams-orchestration.md +1 -1
- package/commands/consistency-check.md +1 -1
- package/commands/context-update.md +1 -1
- package/commands/halfcycle-design.md +1 -1
- package/commands/halfcycle-setup.md +1 -1
- package/commands/stack-assembly-worker.md +1 -1
- package/commands/task-execution.md +1 -1
- package/commands/task-graph.md +1 -1
- package/commands/write-spec.md +1 -1
- package/dist/banner-facts.d.ts +7 -2
- package/dist/banner-facts.d.ts.map +1 -1
- package/dist/build-record/obtain.d.ts.map +1 -1
- package/dist/change.d.ts.map +1 -1
- package/dist/check-criteria.d.ts +1 -1
- package/dist/check-criteria.d.ts.map +1 -1
- package/dist/check-report.d.ts +1 -1
- package/dist/check-report.d.ts.map +1 -1
- package/dist/check-tasks.d.ts +10 -1
- package/dist/check-tasks.d.ts.map +1 -1
- package/dist/cli-contract.d.ts +1 -1
- package/dist/cli-contract.d.ts.map +1 -1
- package/dist/cli.js +1412 -873
- package/dist/cli.js.map +3 -3
- package/dist/close-phase.d.ts +5 -3
- package/dist/close-phase.d.ts.map +1 -1
- package/dist/confirm-identity.d.ts +3 -0
- package/dist/confirm-identity.d.ts.map +1 -1
- package/dist/crew.d.ts +37 -0
- package/dist/crew.d.ts.map +1 -0
- package/dist/draw/index.d.ts +1 -1
- package/dist/draw/index.d.ts.map +1 -1
- package/dist/engagement-credential.d.ts +4 -0
- package/dist/engagement-credential.d.ts.map +1 -1
- package/dist/failure-line.d.ts +3 -2
- package/dist/failure-line.d.ts.map +1 -1
- package/dist/folder-refusals.d.ts.map +1 -1
- package/dist/index.js +330 -224
- package/dist/index.js.map +3 -3
- package/dist/install-manifest.d.ts +5 -1
- package/dist/install-manifest.d.ts.map +1 -1
- package/dist/install-plan.d.ts.map +1 -1
- package/dist/install.d.ts +45 -11
- package/dist/install.d.ts.map +1 -1
- package/dist/local-allow.d.ts +72 -3
- package/dist/local-allow.d.ts.map +1 -1
- package/dist/loopback-signin.d.ts +6 -5
- package/dist/loopback-signin.d.ts.map +1 -1
- package/dist/merge-settings.d.ts +16 -1
- package/dist/merge-settings.d.ts.map +1 -1
- package/dist/open-phase.d.ts +1 -1
- package/dist/open-phase.d.ts.map +1 -1
- package/dist/own-version.d.ts +42 -0
- package/dist/own-version.d.ts.map +1 -0
- package/dist/pace.d.ts +2 -2
- package/dist/pace.d.ts.map +1 -1
- package/dist/plan.d.ts +4 -3
- package/dist/plan.d.ts.map +1 -1
- package/dist/pre-create-checks.d.ts.map +1 -1
- package/dist/preview.d.ts +7 -2
- package/dist/preview.d.ts.map +1 -1
- package/dist/ready.d.ts +1 -1
- package/dist/ready.d.ts.map +1 -1
- package/dist/regression.d.ts +48 -0
- package/dist/regression.d.ts.map +1 -0
- package/dist/request-shapes-verb.d.ts +1 -1
- package/dist/request-shapes-verb.d.ts.map +1 -1
- package/dist/restore.d.ts +1 -1
- package/dist/restore.d.ts.map +1 -1
- package/dist/review.d.ts +2 -2
- package/dist/review.d.ts.map +1 -1
- package/dist/route.d.ts +1 -1
- package/dist/route.d.ts.map +1 -1
- package/dist/size.d.ts.map +1 -1
- package/dist/uninstall.d.ts.map +1 -1
- package/package.json +1 -1
package/bin/bin.bundle.mjs
CHANGED
|
@@ -14804,12 +14804,34 @@ function looksLikeSecret(text) {
|
|
|
14804
14804
|
var MCP_REGISTRATION_REL = ".mcp.json";
|
|
14805
14805
|
var MCP_SERVER_KEY = "halfcycle";
|
|
14806
14806
|
|
|
14807
|
+
// ../core/dist/release-version.js
|
|
14808
|
+
var RELEASE_VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
|
|
14809
|
+
|
|
14810
|
+
// ../core/dist/release-tag.js
|
|
14811
|
+
var PRE_RELEASE_VERSION_PATTERN = /^(\d+\.\d+\.\d+)-rc\.\d+$/;
|
|
14812
|
+
var PACKAGE_COMMAND = "npx halfcycle";
|
|
14813
|
+
function isPreReleaseVersion(value) {
|
|
14814
|
+
return typeof value === "string" && PRE_RELEASE_VERSION_PATTERN.test(value);
|
|
14815
|
+
}
|
|
14816
|
+
function releaseTagOfVersion(version2) {
|
|
14817
|
+
return isPreReleaseVersion(version2) ? "next" : "latest";
|
|
14818
|
+
}
|
|
14819
|
+
function halfcycleCommand(version2) {
|
|
14820
|
+
return `${PACKAGE_COMMAND}@${releaseTagOfVersion(version2)}`;
|
|
14821
|
+
}
|
|
14822
|
+
function bareHalfcycleCommand(version2) {
|
|
14823
|
+
return releaseTagOfVersion(version2) === "next" ? `${PACKAGE_COMMAND}@next` : PACKAGE_COMMAND;
|
|
14824
|
+
}
|
|
14825
|
+
|
|
14807
14826
|
// ../core/dist/shell-quote.js
|
|
14808
14827
|
function quoteForShell(value) {
|
|
14809
14828
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
14810
14829
|
}
|
|
14811
|
-
var HALFCYCLE_COMMAND =
|
|
14812
|
-
|
|
14830
|
+
var HALFCYCLE_COMMAND = halfcycleCommand();
|
|
14831
|
+
function doctorLine(version2) {
|
|
14832
|
+
return `Run \`${bareHalfcycleCommand(version2)} doctor\` to check set up, sign-in, connection, checks and version.`;
|
|
14833
|
+
}
|
|
14834
|
+
var DOCTOR_LINE = doctorLine();
|
|
14813
14835
|
|
|
14814
14836
|
// ../core/dist/folder-trust.js
|
|
14815
14837
|
var CLAUDE_STATE_FILENAME = ".claude.json";
|
|
@@ -15107,9 +15129,6 @@ function typedPhaseReference(phase, number4) {
|
|
|
15107
15129
|
return phase.includes(":") && number4 !== null ? String(number4) : phase;
|
|
15108
15130
|
}
|
|
15109
15131
|
|
|
15110
|
-
// ../core/dist/release-version.js
|
|
15111
|
-
var RELEASE_VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
|
|
15112
|
-
|
|
15113
15132
|
// ../core/dist/github-address.js
|
|
15114
15133
|
var GITHUB_REPOSITORY_ADDRESS = /^https:\/\/github\.com\/[A-Za-z0-9][A-Za-z0-9-]{0,38}\/(?!\.{1,2}$)[A-Za-z0-9._-]{1,100}$/;
|
|
15115
15134
|
var HOST = "[Gg][Ii][Tt][Hh][Uu][Bb]\\.[Cc][Oo][Mm]";
|
|
@@ -15148,8 +15167,14 @@ function githubRepositoryAddress(remote) {
|
|
|
15148
15167
|
}
|
|
15149
15168
|
|
|
15150
15169
|
// ../core/dist/sign-in.js
|
|
15151
|
-
|
|
15152
|
-
|
|
15170
|
+
function signInCommand(version2) {
|
|
15171
|
+
return `"${bareHalfcycleCommand(version2)}"`;
|
|
15172
|
+
}
|
|
15173
|
+
var SIGN_IN_COMMAND = signInCommand();
|
|
15174
|
+
function hookRemedy(version2) {
|
|
15175
|
+
return `Run ${signInCommand(version2)} in the project folder to sign in.`;
|
|
15176
|
+
}
|
|
15177
|
+
var HOOK_REMEDY = hookRemedy();
|
|
15153
15178
|
|
|
15154
15179
|
// ../core/dist/task-plan.js
|
|
15155
15180
|
var TASK_PLAN_FILE = "docs/build-records/task-plan.json";
|
|
@@ -15261,7 +15286,7 @@ function codexHookCommand(script, args2) {
|
|
|
15261
15286
|
const invocation = `cd "$(git rev-parse --show-toplevel)" && bash ./${script}`;
|
|
15262
15287
|
return args2 === void 0 ? invocation : `${invocation} ${args2}`;
|
|
15263
15288
|
}
|
|
15264
|
-
var CODEX_WINDOWS_NOT_SET_UP =
|
|
15289
|
+
var CODEX_WINDOWS_NOT_SET_UP = `Halfcycle checks did not run because Halfcycle is not set up in this folder or any folder above it; run ${bareHalfcycleCommand()} in the project folder.`;
|
|
15265
15290
|
var CODEX_WINDOWS_NO_GIT_BASH = "Halfcycle checks did not run because Git for Windows was not found; install Git for Windows, then open a new session.";
|
|
15266
15291
|
function codexHookCommandWindows(script, args2) {
|
|
15267
15292
|
const tick = (text) => "`" + text + "`";
|
|
@@ -18925,6 +18950,10 @@ function paceClockOf(at, now) {
|
|
|
18925
18950
|
return `${day} ${clock}`;
|
|
18926
18951
|
}
|
|
18927
18952
|
var PACE_P5 = "This build may use all of your allowance. It will not slow down to leave room for you.";
|
|
18953
|
+
function paceP8Of(version2) {
|
|
18954
|
+
return `For these to work, run "${bareHalfcycleCommand(version2)}" once more in this project.`;
|
|
18955
|
+
}
|
|
18956
|
+
var PACE_P8 = paceP8Of();
|
|
18928
18957
|
function paceS1Of(window, k, until, now, keepFreePercent) {
|
|
18929
18958
|
return `Halfcycle is slowing this build so you keep about ${paceShareWordsOf(keepFreePercent)} of this ${paceWindowWordsOf(window)} for your own work. It will run at most ${paceAgentsOf(k)} at once until ${paceClockOf(until, now)}.`;
|
|
18930
18959
|
}
|
|
@@ -19170,7 +19199,10 @@ var CLIENT_VERSION_HEADER = "x-halfcycle-client";
|
|
|
19170
19199
|
var TYPED_APPROVAL_OFF_SENTENCE = "Approving by typing is switched off for now.";
|
|
19171
19200
|
var HEADLESS_CANNOT_APPROVE = "(a headless session cannot approve, by design)";
|
|
19172
19201
|
var TYPED_REVIEW_OFF_SENTENCE = "Reviewing by typing is switched off for now.";
|
|
19173
|
-
|
|
19202
|
+
function clientUpdateSentence(version2) {
|
|
19203
|
+
return `To approve by typing in a session, Halfcycle needs updating: run \`${halfcycleCommand(version2)}\` in this project's folder, then reopen your session and ask again.`;
|
|
19204
|
+
}
|
|
19205
|
+
var CLIENT_UPDATE_SENTENCE = clientUpdateSentence();
|
|
19174
19206
|
|
|
19175
19207
|
// ../events/dist/device-auth.js
|
|
19176
19208
|
var utcIso86012 = external_exports.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/, "must be a UTC ISO-8601 timestamp ending in Z");
|
|
@@ -19268,17 +19300,31 @@ var deviceConfirmResponseSchema = external_exports.union([
|
|
|
19268
19300
|
var DASHBOARD_URL = "https://app.halfcycle.ai";
|
|
19269
19301
|
|
|
19270
19302
|
// ../events/dist/project-page.js
|
|
19271
|
-
|
|
19272
|
-
|
|
19303
|
+
var SERVICE_HOST = /^(?:control|delivery)(-[a-z0-9]+)?\.halfcycle\.ai$/;
|
|
19304
|
+
function consoleOrigin(serviceAddress) {
|
|
19305
|
+
const trimmed = serviceAddress?.trim();
|
|
19306
|
+
if (!trimmed)
|
|
19307
|
+
return DASHBOARD_URL;
|
|
19308
|
+
let host;
|
|
19309
|
+
try {
|
|
19310
|
+
host = new URL(trimmed.includes("://") ? trimmed : `https://${trimmed}`).hostname.toLowerCase();
|
|
19311
|
+
} catch {
|
|
19312
|
+
return DASHBOARD_URL;
|
|
19313
|
+
}
|
|
19314
|
+
const suffix = SERVICE_HOST.exec(host)?.[1];
|
|
19315
|
+
return suffix === void 0 ? DASHBOARD_URL : `https://app${suffix}.halfcycle.ai`;
|
|
19316
|
+
}
|
|
19317
|
+
function projectPageUrl(engagementId, serviceAddress) {
|
|
19318
|
+
return isEngagementId(engagementId) ? `${consoleOrigin(serviceAddress)}/${encodeURIComponent(engagementId)}` : void 0;
|
|
19273
19319
|
}
|
|
19274
|
-
function systemViewUrl(engagementId, phase) {
|
|
19275
|
-
const page = projectPageUrl(engagementId);
|
|
19320
|
+
function systemViewUrl(engagementId, phase, serviceAddress) {
|
|
19321
|
+
const page = projectPageUrl(engagementId, serviceAddress);
|
|
19276
19322
|
if (page === void 0)
|
|
19277
19323
|
return void 0;
|
|
19278
19324
|
return `${page}/console/system-view?${new URLSearchParams({ phase }).toString()}`;
|
|
19279
19325
|
}
|
|
19280
|
-
function requestAccessSentence(engagementId) {
|
|
19281
|
-
const page = projectPageUrl(engagementId) ?? "this project's page on Halfcycle";
|
|
19326
|
+
function requestAccessSentence(engagementId, serviceAddress) {
|
|
19327
|
+
const page = projectPageUrl(engagementId, serviceAddress) ?? "this project's page on Halfcycle";
|
|
19282
19328
|
return `To ask for access, open ${page} signed in as this account and choose "Request access". Then let the project's owner know, so they can approve it.`;
|
|
19283
19329
|
}
|
|
19284
19330
|
|
|
@@ -19345,19 +19391,19 @@ function systemViewSentence(offerTyping, address) {
|
|
|
19345
19391
|
return [];
|
|
19346
19392
|
return [offerTyping === "yes" ? `Or they approve it in the System view: ${address}` : `They approve it in the System view: ${address}`];
|
|
19347
19393
|
}
|
|
19348
|
-
function waitingNotice(entry, offerTyping, engagementId) {
|
|
19394
|
+
function waitingNotice(entry, offerTyping, engagementId, serviceAddress) {
|
|
19349
19395
|
return [
|
|
19350
19396
|
...entry.changedParts.length > 0 ? [`These parts changed since the owner last decided on this phase, and wait for their approval: ${quotedParts(entry.changedParts)}.`] : [],
|
|
19351
19397
|
`The scope of ${phaseWords(entry.phase)} is waiting for the project's owner to approve it.`,
|
|
19352
19398
|
approvalSentence(entry.phase, offerTyping),
|
|
19353
|
-
...systemViewSentence(offerTyping, systemViewUrl(engagementId, entry.phase))
|
|
19399
|
+
...systemViewSentence(offerTyping, systemViewUrl(engagementId, entry.phase, serviceAddress))
|
|
19354
19400
|
].join(" ");
|
|
19355
19401
|
}
|
|
19356
19402
|
function scopeNoticeText(scope, options) {
|
|
19357
19403
|
const omit2 = options.omitActivePhase === true ? options.activePhase : void 0;
|
|
19358
19404
|
return {
|
|
19359
19405
|
sentBack: scope.sentBack.map(sentBackNotice),
|
|
19360
|
-
waiting: scope.waiting.filter((w) => omit2 === void 0 || w.phase !== omit2).map((w) => waitingNotice(w, options.offerTyping, options.engagementId))
|
|
19406
|
+
waiting: scope.waiting.filter((w) => omit2 === void 0 || w.phase !== omit2).map((w) => waitingNotice(w, options.offerTyping, options.engagementId, options.serviceAddress))
|
|
19361
19407
|
};
|
|
19362
19408
|
}
|
|
19363
19409
|
|
|
@@ -19385,15 +19431,15 @@ var reviewNoticesSchema = external_exports.object({
|
|
|
19385
19431
|
function phaseCalled(phase) {
|
|
19386
19432
|
return `phase "${phase}"`;
|
|
19387
19433
|
}
|
|
19388
|
-
function questionNotice(entry) {
|
|
19389
|
-
const answer = `${
|
|
19434
|
+
function questionNotice(entry, version2) {
|
|
19435
|
+
const answer = `${halfcycleCommand(version2)} review ${quoteForShell(entry.phase)} --answer ${quoteForShell(entry.part)} "<your answer>"`;
|
|
19390
19436
|
return `Before anything else: the project's owner asked about "${entry.partName}" in the review of ${phaseCalled(entry.phase)}: ${entry.question} Answer it with ${answer}.`;
|
|
19391
19437
|
}
|
|
19392
19438
|
function sentBackNotice2(entry) {
|
|
19393
19439
|
return `Before anything else: the project's owner sent "${entry.partName}" in ${phaseCalled(entry.phase)} back to building: ${entry.note} Rebuild it: add or reopen the tasks that build it. For each task that rebuilds it, add a task that reviews the rebuild, held by a different agent from the one that built it. When each review has passed, report the build with the time each task finished, then run the close step again.`;
|
|
19394
19440
|
}
|
|
19395
|
-
function reviewNoticeText(review) {
|
|
19396
|
-
return [...review.questions.map(questionNotice), ...review.sentBack.map(sentBackNotice2)];
|
|
19441
|
+
function reviewNoticeText(review, version2) {
|
|
19442
|
+
return [...review.questions.map((entry) => questionNotice(entry, version2)), ...review.sentBack.map(sentBackNotice2)];
|
|
19397
19443
|
}
|
|
19398
19444
|
|
|
19399
19445
|
// ../events/dist/credential-wire.js
|
|
@@ -19420,8 +19466,14 @@ var CREDENTIAL_PLACEHOLDERS = [
|
|
|
19420
19466
|
UPDATE_CLAUDE_CODE_PLACEHOLDER
|
|
19421
19467
|
];
|
|
19422
19468
|
var SWITCH_ACCOUNT_ANSWER = 'answer "s" when asked';
|
|
19423
|
-
|
|
19424
|
-
|
|
19469
|
+
function noCredentialSentence(version2) {
|
|
19470
|
+
return `Halfcycle is not connected: this machine has no working Halfcycle credential for this project. Run "${bareHalfcycleCommand(version2)}" in the project folder to sign in again.`;
|
|
19471
|
+
}
|
|
19472
|
+
var NO_CREDENTIAL_SENTENCE = noCredentialSentence();
|
|
19473
|
+
function notThisAccountSentence(version2) {
|
|
19474
|
+
return `Halfcycle is not connected: this project belongs to another Halfcycle account. To switch, run "${bareHalfcycleCommand(version2)}" in this project and ${SWITCH_ACCOUNT_ANSWER}.`;
|
|
19475
|
+
}
|
|
19476
|
+
var NOT_THIS_ACCOUNT_SENTENCE = notThisAccountSentence();
|
|
19425
19477
|
var UPDATE_CLAUDE_CODE_SENTENCE = "Halfcycle is not connected: this Claude Code version does not name the server it connects to, so no credential was sent. Update Claude Code, then reopen.";
|
|
19426
19478
|
var CANNOT_REACH_SENTENCE = "Halfcycle is not connected: its server could not be reached, so its tools are unavailable in this session. Check your network, then reopen the project.";
|
|
19427
19479
|
var SERVICE_PROBLEM_SENTENCE = "Halfcycle is not connected: its service had a problem just now, so nothing in this session is being checked. Reopen the project to try again.";
|
|
@@ -19432,6 +19484,13 @@ var PLACEHOLDER_SENTENCES = Object.freeze({
|
|
|
19432
19484
|
[NOT_THIS_ACCOUNT_PLACEHOLDER]: NOT_THIS_ACCOUNT_SENTENCE,
|
|
19433
19485
|
[UPDATE_CLAUDE_CODE_PLACEHOLDER]: UPDATE_CLAUDE_CODE_SENTENCE
|
|
19434
19486
|
});
|
|
19487
|
+
function placeholderSentencesOf(version2) {
|
|
19488
|
+
return Object.freeze({
|
|
19489
|
+
[NO_CREDENTIAL_PLACEHOLDER]: noCredentialSentence(version2),
|
|
19490
|
+
[NOT_THIS_ACCOUNT_PLACEHOLDER]: notThisAccountSentence(version2),
|
|
19491
|
+
[UPDATE_CLAUDE_CODE_PLACEHOLDER]: UPDATE_CLAUDE_CODE_SENTENCE
|
|
19492
|
+
});
|
|
19493
|
+
}
|
|
19435
19494
|
|
|
19436
19495
|
// ../events/dist/scope-chat.js
|
|
19437
19496
|
var chatScopeApproveRequestSchema = external_exports.object({
|
|
@@ -19862,8 +19921,8 @@ var AUTONOMY_A5 = "Builds in this project wait for you again.";
|
|
|
19862
19921
|
function withoutFinalStop(text) {
|
|
19863
19922
|
return text.endsWith(".") ? text.slice(0, -1) : text;
|
|
19864
19923
|
}
|
|
19865
|
-
function autonomyA9(what, id) {
|
|
19866
|
-
return `Halfcycle saved a copy before this: ${withoutFinalStop(what)}. To bring it back, run: ${
|
|
19924
|
+
function autonomyA9(what, id, version2) {
|
|
19925
|
+
return `Halfcycle saved a copy before this: ${withoutFinalStop(what)}. To bring it back, run: ${halfcycleCommand(version2)} restore ${id} (kept for 7 days).`;
|
|
19867
19926
|
}
|
|
19868
19927
|
function autonomyA10(typeSentence, item) {
|
|
19869
19928
|
return `${typeSentence} Builds run on their own here, but this still waits for the owner. Declare it with halfcycle_declare_owner_wait, item ${String(item)}, and carry on with other work.`;
|
|
@@ -19929,6 +19988,53 @@ function checksReportOfInstructions(text) {
|
|
|
19929
19988
|
// dist/hook-protocol.js
|
|
19930
19989
|
import { writeSync } from "node:fs";
|
|
19931
19990
|
|
|
19991
|
+
// dist/pinned-engagement.js
|
|
19992
|
+
import { readFileSync } from "node:fs";
|
|
19993
|
+
import { resolve } from "node:path";
|
|
19994
|
+
function readPinnedId(root) {
|
|
19995
|
+
let raw;
|
|
19996
|
+
try {
|
|
19997
|
+
raw = readFileSync(resolve(root, BUNDLE_PIN_REL), "utf-8");
|
|
19998
|
+
} catch {
|
|
19999
|
+
return { problem: "no-pin" };
|
|
20000
|
+
}
|
|
20001
|
+
let pin;
|
|
20002
|
+
try {
|
|
20003
|
+
pin = JSON.parse(raw);
|
|
20004
|
+
} catch {
|
|
20005
|
+
return { problem: "no-id" };
|
|
20006
|
+
}
|
|
20007
|
+
const id = typeof pin === "object" && pin !== null ? pin[PIN_ENGAGEMENT_ID_FIELD] : void 0;
|
|
20008
|
+
return typeof id === "string" && id !== "" ? { id } : { problem: "no-id" };
|
|
20009
|
+
}
|
|
20010
|
+
function pinnedEngagementId(root) {
|
|
20011
|
+
const pinned = readPinnedId(root);
|
|
20012
|
+
return "id" in pinned && isEngagementId(pinned.id) ? pinned.id : void 0;
|
|
20013
|
+
}
|
|
20014
|
+
function projectFolder(env = process.env) {
|
|
20015
|
+
const dir = env["CLAUDE_PROJECT_DIR"];
|
|
20016
|
+
return dir !== void 0 && dir !== "" ? dir : process.cwd();
|
|
20017
|
+
}
|
|
20018
|
+
function readPinnedVersion(root) {
|
|
20019
|
+
let raw;
|
|
20020
|
+
try {
|
|
20021
|
+
raw = readFileSync(resolve(root, BUNDLE_PIN_REL), "utf-8");
|
|
20022
|
+
} catch {
|
|
20023
|
+
return void 0;
|
|
20024
|
+
}
|
|
20025
|
+
let pin;
|
|
20026
|
+
try {
|
|
20027
|
+
pin = JSON.parse(raw);
|
|
20028
|
+
} catch {
|
|
20029
|
+
return void 0;
|
|
20030
|
+
}
|
|
20031
|
+
const version2 = typeof pin === "object" && pin !== null ? pin["version"] : void 0;
|
|
20032
|
+
return typeof version2 === "string" && version2 !== "" ? version2 : void 0;
|
|
20033
|
+
}
|
|
20034
|
+
function installedVersion(env = process.env) {
|
|
20035
|
+
return readPinnedVersion(projectFolder(env));
|
|
20036
|
+
}
|
|
20037
|
+
|
|
19932
20038
|
// dist/agent-argument.js
|
|
19933
20039
|
var AGENT_FLAG = "--agent";
|
|
19934
20040
|
function agentFromArguments(rest) {
|
|
@@ -19996,9 +20102,10 @@ function hookReply(event, profile = AGENT_PROFILES["claude-code"]) {
|
|
|
19996
20102
|
if (!owesDoctorLine || doctorLineSaid)
|
|
19997
20103
|
return;
|
|
19998
20104
|
doctorLineSaid = true;
|
|
19999
|
-
|
|
20105
|
+
const doctor = doctorLine(installedVersion());
|
|
20106
|
+
queued.push(doctor);
|
|
20000
20107
|
if (personOwedDoctorLine)
|
|
20001
|
-
forPerson.push(
|
|
20108
|
+
forPerson.push(doctor);
|
|
20002
20109
|
};
|
|
20003
20110
|
return {
|
|
20004
20111
|
notice(text) {
|
|
@@ -20020,7 +20127,7 @@ function hookReply(event, profile = AGENT_PROFILES["claude-code"]) {
|
|
|
20020
20127
|
},
|
|
20021
20128
|
loud(text, exitCode, notAFailure) {
|
|
20022
20129
|
const said = notAFailure !== void 0 || doctorLineSaid ? text : `${text.trimEnd()}
|
|
20023
|
-
${
|
|
20130
|
+
${doctorLine(installedVersion())}
|
|
20024
20131
|
`;
|
|
20025
20132
|
if (notAFailure === void 0)
|
|
20026
20133
|
doctorLineSaid = true;
|
|
@@ -20112,7 +20219,7 @@ function lastResortReply(argv, text) {
|
|
|
20112
20219
|
function answerUnexpectedError(argv, err, out) {
|
|
20113
20220
|
const text = `halfcycle-runner: unexpected error: ${err instanceof Error ? err.message : String(err)}
|
|
20114
20221
|
Contact hello@halfcycle.ai if this keeps happening.
|
|
20115
|
-
${
|
|
20222
|
+
${doctorLine(installedVersion())}
|
|
20116
20223
|
`;
|
|
20117
20224
|
const reply = lastResortReply(argv, text);
|
|
20118
20225
|
if (reply !== null) {
|
|
@@ -20150,7 +20257,7 @@ function noRepositoryText(failure) {
|
|
|
20150
20257
|
}
|
|
20151
20258
|
function contractFaultText(message) {
|
|
20152
20259
|
return `[Halfcycle] WARNING: Guard response could not be understood \u2014 ${message}
|
|
20153
|
-
This is not a service outage: the guard service answered. The suspect is this repository's own installed halfcycle runner, which is out of date with what the service now sends. Update it: run
|
|
20260
|
+
This is not a service outage: the guard service answered. The suspect is this repository's own installed halfcycle runner, which is out of date with what the service now sends. Update it: run ${signInCommand(installedVersion())} in this repository, then retry. Session continues (fail-open).`;
|
|
20154
20261
|
}
|
|
20155
20262
|
var UNCONFIGURED_EXIT_TOOL_USE = 2;
|
|
20156
20263
|
var UNCONFIGURED_EXIT_STOP_FAMILY = 1;
|
|
@@ -20166,8 +20273,8 @@ function emitNeverConfigured(exitCode, reason, engagementId, reply) {
|
|
|
20166
20273
|
writeSync(2, text);
|
|
20167
20274
|
process.exitCode = exitCode;
|
|
20168
20275
|
}
|
|
20169
|
-
function namesTheSignInCommand(text) {
|
|
20170
|
-
return text.includes(
|
|
20276
|
+
function namesTheSignInCommand(text, version2) {
|
|
20277
|
+
return text.includes(signInCommand(version2 ?? installedVersion()));
|
|
20171
20278
|
}
|
|
20172
20279
|
var PERMISSIONS_BLOCK = "\n permissions:\n contents: read\n id-token: write\n\n";
|
|
20173
20280
|
var BOTH_LINES_SENTENCE = "BOTH LINES. Declaring any permission replaces the defaults rather than adding to them, so a block naming only the identity token takes read access away from the checkout step and a private repository stops checking out before this check is reached.";
|
|
@@ -20192,13 +20299,13 @@ ${CI_OLDER_SETUP}
|
|
|
20192
20299
|
`;
|
|
20193
20300
|
}
|
|
20194
20301
|
function notThisAccountReport(label, engagementId) {
|
|
20195
|
-
return `${label} This project belongs to another Halfcycle account. Halfcycle is Solo today \u2014 one person works on a project at a time \u2014 so no credential exists for this machine and none will be issued. Nothing here needs fixing; this copy simply is not checked. ${requestAccessSentence(engagementId)} If this account is wrong, sign in as the one that owns the project and run
|
|
20302
|
+
return `${label} This project belongs to another Halfcycle account. Halfcycle is Solo today \u2014 one person works on a project at a time \u2014 so no credential exists for this machine and none will be issued. Nothing here needs fixing; this copy simply is not checked. ${requestAccessSentence(engagementId, readControlOrigin().origin)} If this account is wrong, sign in as the one that owns the project and run ${signInCommand(installedVersion())} again.
|
|
20196
20303
|
`;
|
|
20197
20304
|
}
|
|
20198
20305
|
function neverConfiguredReport(reason, label = "[Halfcycle]", engagementId) {
|
|
20199
20306
|
switch (reason) {
|
|
20200
20307
|
case "no-credential-yet":
|
|
20201
|
-
return neverConfiguredMessage(
|
|
20308
|
+
return neverConfiguredMessage(hookRemedy(installedVersion()), label);
|
|
20202
20309
|
case "not-this-account":
|
|
20203
20310
|
return notThisAccountReport(label, engagementId);
|
|
20204
20311
|
}
|
|
@@ -20242,7 +20349,7 @@ This is not a service outage. The guard service is up and replying; ${cause}, so
|
|
|
20242
20349
|
${remedy}
|
|
20243
20350
|
`;
|
|
20244
20351
|
}
|
|
20245
|
-
function emitCredentialRejected(statusCode, serviceMessage, exitCode, remedy =
|
|
20352
|
+
function emitCredentialRejected(statusCode, serviceMessage, exitCode, remedy = hookRemedy(installedVersion()), reply) {
|
|
20246
20353
|
const text = credentialRejectedMessage(statusCode, serviceMessage, remedy);
|
|
20247
20354
|
if (reply !== void 0) {
|
|
20248
20355
|
reply.loud(text, exitCode);
|
|
@@ -20256,20 +20363,20 @@ function credentialRenewalFailedMessage(remedy, label = "[Halfcycle]") {
|
|
|
20256
20363
|
${remedy}
|
|
20257
20364
|
`;
|
|
20258
20365
|
}
|
|
20259
|
-
function noCoverageStatement(reason, remedySaid = false, engagementId) {
|
|
20366
|
+
function noCoverageStatement(reason, remedySaid = false, engagementId, version2 = installedVersion()) {
|
|
20260
20367
|
if (reason === "not-this-account") {
|
|
20261
20368
|
return [
|
|
20262
20369
|
"[halfcycle] This project belongs to another Halfcycle account, so nothing here is checked.",
|
|
20263
20370
|
"[halfcycle] Your work carries on exactly as it would without Halfcycle \u2014 no edit is",
|
|
20264
20371
|
"[halfcycle] evaluated, and nothing you do is reported as having passed.",
|
|
20265
20372
|
"[halfcycle] Halfcycle is Solo today \u2014 one developer per project \u2014 with Team plans coming.",
|
|
20266
|
-
`[halfcycle] ${requestAccessSentence(engagementId)}`,
|
|
20373
|
+
`[halfcycle] ${requestAccessSentence(engagementId, readControlOrigin().origin)}`,
|
|
20267
20374
|
"[halfcycle] If this account is wrong, sign in as the one that owns the project and run",
|
|
20268
|
-
|
|
20375
|
+
`[halfcycle] ${signInCommand(version2)} again.`
|
|
20269
20376
|
].join("\n");
|
|
20270
20377
|
}
|
|
20271
20378
|
const statement = `${NO_SIGN_IN_HERE}, so edits made in this session won't be checked.`;
|
|
20272
|
-
return remedySaid ? statement : `${statement} ${
|
|
20379
|
+
return remedySaid ? statement : `${statement} ${hookRemedy(version2)}`;
|
|
20273
20380
|
}
|
|
20274
20381
|
function notRunReport(notRun, label = "[Halfcycle]") {
|
|
20275
20382
|
if (!notRun || notRun.length === 0)
|
|
@@ -20494,7 +20601,7 @@ async function attempt2(url2, token, request, fetchFn, retry) {
|
|
|
20494
20601
|
|
|
20495
20602
|
// dist/git.js
|
|
20496
20603
|
import { spawnSync } from "node:child_process";
|
|
20497
|
-
import { existsSync as existsSync2, readFileSync } from "node:fs";
|
|
20604
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
20498
20605
|
import { relative } from "node:path";
|
|
20499
20606
|
var COLOR_AWARE_SUBCOMMANDS = /* @__PURE__ */ new Set(["diff", "show", "log"]);
|
|
20500
20607
|
function spawnGit(args2, cwd, timeoutMs, extra) {
|
|
@@ -20527,7 +20634,7 @@ function getSingleFileDiff(absFilePath, repoRoot) {
|
|
|
20527
20634
|
return diffResult.value;
|
|
20528
20635
|
}
|
|
20529
20636
|
try {
|
|
20530
|
-
const content =
|
|
20637
|
+
const content = readFileSync2(absFilePath, "utf-8");
|
|
20531
20638
|
if (!content.trim())
|
|
20532
20639
|
return "";
|
|
20533
20640
|
const lines2 = content.split("\n");
|
|
@@ -21354,7 +21461,7 @@ function detectBlastRadiusMarkers(filePath, diffContent) {
|
|
|
21354
21461
|
}
|
|
21355
21462
|
|
|
21356
21463
|
// dist/extract/numeric-columns.js
|
|
21357
|
-
import { readFileSync as
|
|
21464
|
+
import { readFileSync as readFileSync3, readdirSync } from "node:fs";
|
|
21358
21465
|
import { join as join2 } from "node:path";
|
|
21359
21466
|
function extractNumericColumns(diffContent, context = {}) {
|
|
21360
21467
|
const addedLines = [];
|
|
@@ -21432,7 +21539,7 @@ function walkForRegistrations(dir, repoRoot, acc) {
|
|
|
21432
21539
|
continue;
|
|
21433
21540
|
let content;
|
|
21434
21541
|
try {
|
|
21435
|
-
content =
|
|
21542
|
+
content = readFileSync3(absPath, "utf-8");
|
|
21436
21543
|
} catch {
|
|
21437
21544
|
continue;
|
|
21438
21545
|
}
|
|
@@ -21569,7 +21676,7 @@ function resolveWireFields(lines2, decls) {
|
|
|
21569
21676
|
}
|
|
21570
21677
|
|
|
21571
21678
|
// dist/fixtures-manifest.js
|
|
21572
|
-
import { existsSync as existsSync3, mkdirSync, readFileSync as
|
|
21679
|
+
import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync4, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
21573
21680
|
import { dirname, join as join3 } from "node:path";
|
|
21574
21681
|
function manifestPath(repoRoot) {
|
|
21575
21682
|
return join3(repoRoot, "test", "fixtures", "captured", "manifest.json");
|
|
@@ -21582,7 +21689,7 @@ function loadManifest(repoRoot) {
|
|
|
21582
21689
|
return [];
|
|
21583
21690
|
let raw;
|
|
21584
21691
|
try {
|
|
21585
|
-
raw =
|
|
21692
|
+
raw = readFileSync4(manifestPath(repoRoot), "utf-8");
|
|
21586
21693
|
} catch {
|
|
21587
21694
|
return [];
|
|
21588
21695
|
}
|
|
@@ -21855,7 +21962,7 @@ function toAstShapes(markers) {
|
|
|
21855
21962
|
}
|
|
21856
21963
|
|
|
21857
21964
|
// dist/extract/context.js
|
|
21858
|
-
import { readFileSync as
|
|
21965
|
+
import { readFileSync as readFileSync5, readdirSync as readdirSync2 } from "node:fs";
|
|
21859
21966
|
import { join as join4, relative as relative2, sep } from "node:path";
|
|
21860
21967
|
|
|
21861
21968
|
// dist/extract/repo-facts.js
|
|
@@ -22005,7 +22112,7 @@ function walk(dir, repoRoot, acc, facts, underDocs = false) {
|
|
|
22005
22112
|
noteFileName(facts, entry.name, underDocs);
|
|
22006
22113
|
if (!underDocs && isFactManifest(entry.name)) {
|
|
22007
22114
|
try {
|
|
22008
|
-
noteManifest(facts, entry.name,
|
|
22115
|
+
noteManifest(facts, entry.name, readFileSync5(join4(dir, entry.name), "utf-8"));
|
|
22009
22116
|
} catch {
|
|
22010
22117
|
continue;
|
|
22011
22118
|
}
|
|
@@ -22016,7 +22123,7 @@ function walk(dir, repoRoot, acc, facts, underDocs = false) {
|
|
|
22016
22123
|
const absPath = join4(dir, entry.name);
|
|
22017
22124
|
let content;
|
|
22018
22125
|
try {
|
|
22019
|
-
content =
|
|
22126
|
+
content = readFileSync5(absPath, "utf-8");
|
|
22020
22127
|
} catch {
|
|
22021
22128
|
continue;
|
|
22022
22129
|
}
|
|
@@ -22088,11 +22195,8 @@ async function postTelemetry(run, baseUrl, token, logger, fetchFn) {
|
|
|
22088
22195
|
if (!response.ok) {
|
|
22089
22196
|
logger.warn(`[Halfcycle telemetry] Control-plane POST returned ${response.status} (dropped \u2014 best-effort)`);
|
|
22090
22197
|
}
|
|
22091
|
-
} catch
|
|
22198
|
+
} catch {
|
|
22092
22199
|
clearTimeout(timer);
|
|
22093
|
-
const isTimeout = err instanceof Error && err.name === "AbortError";
|
|
22094
|
-
const msg = isTimeout ? `Control-plane timed out after ${TELEMETRY_TIMEOUT_MS}ms (dropped \u2014 best-effort)` : err instanceof Error ? `Control-plane unreachable: ${err.message} (dropped \u2014 best-effort)` : `Control-plane error: ${String(err)} (dropped \u2014 best-effort)`;
|
|
22095
|
-
logger.warn(`[Halfcycle telemetry] ${msg}`);
|
|
22096
22200
|
}
|
|
22097
22201
|
}
|
|
22098
22202
|
function changeSetDescriptorCount(changeSet) {
|
|
@@ -22350,34 +22454,6 @@ function cleanRunSummary(verdict, scope) {
|
|
|
22350
22454
|
return `[Halfcycle CI] ${verdict} ${files}, ${scope.signals} signal(s) checked.`;
|
|
22351
22455
|
}
|
|
22352
22456
|
|
|
22353
|
-
// dist/pinned-engagement.js
|
|
22354
|
-
import { readFileSync as readFileSync5 } from "node:fs";
|
|
22355
|
-
import { resolve } from "node:path";
|
|
22356
|
-
function readPinnedId(root) {
|
|
22357
|
-
let raw;
|
|
22358
|
-
try {
|
|
22359
|
-
raw = readFileSync5(resolve(root, BUNDLE_PIN_REL), "utf-8");
|
|
22360
|
-
} catch {
|
|
22361
|
-
return { problem: "no-pin" };
|
|
22362
|
-
}
|
|
22363
|
-
let pin;
|
|
22364
|
-
try {
|
|
22365
|
-
pin = JSON.parse(raw);
|
|
22366
|
-
} catch {
|
|
22367
|
-
return { problem: "no-id" };
|
|
22368
|
-
}
|
|
22369
|
-
const id = typeof pin === "object" && pin !== null ? pin[PIN_ENGAGEMENT_ID_FIELD] : void 0;
|
|
22370
|
-
return typeof id === "string" && id !== "" ? { id } : { problem: "no-id" };
|
|
22371
|
-
}
|
|
22372
|
-
function pinnedEngagementId(root) {
|
|
22373
|
-
const pinned = readPinnedId(root);
|
|
22374
|
-
return "id" in pinned && isEngagementId(pinned.id) ? pinned.id : void 0;
|
|
22375
|
-
}
|
|
22376
|
-
function projectFolder(env = process.env) {
|
|
22377
|
-
const dir = env["CLAUDE_PROJECT_DIR"];
|
|
22378
|
-
return dir !== void 0 && dir !== "" ? dir : process.cwd();
|
|
22379
|
-
}
|
|
22380
|
-
|
|
22381
22457
|
// dist/credential-store.js
|
|
22382
22458
|
import { chmodSync, existsSync as existsSync4, readFileSync as readFileSync6, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2, realpathSync } from "node:fs";
|
|
22383
22459
|
import { homedir as homedir3, platform } from "node:os";
|
|
@@ -22514,12 +22590,12 @@ async function mintThroughJoin(controlOrigin, engagementId, accountCredential, f
|
|
|
22514
22590
|
}
|
|
22515
22591
|
if (!response.ok) {
|
|
22516
22592
|
if (response.status === UNAUTHORIZED)
|
|
22517
|
-
return { ok: false, remedy:
|
|
22593
|
+
return { ok: false, remedy: hookRemedy(installedVersion()) };
|
|
22518
22594
|
return { ok: false, remedy: planeSentence(body) ?? UNREADABLE_REFUSAL_REMEDY };
|
|
22519
22595
|
}
|
|
22520
22596
|
const parsed = engagementCredentialResponseSchema.safeParse(body);
|
|
22521
22597
|
if (!parsed.success)
|
|
22522
|
-
return { ok: false, remedy:
|
|
22598
|
+
return { ok: false, remedy: unreadableMintRemedy() };
|
|
22523
22599
|
return { ok: true, token: parsed.data.sessionToken, source: "mint" };
|
|
22524
22600
|
}
|
|
22525
22601
|
function planeSentence(body) {
|
|
@@ -22530,11 +22606,13 @@ function planeSentence(body) {
|
|
|
22530
22606
|
}
|
|
22531
22607
|
var UNREACHABLE_REMEDY = "The Halfcycle service could not be reached to renew this credential. Nothing is wrong with this repository; the next change will try again.";
|
|
22532
22608
|
var UNREADABLE_REFUSAL_REMEDY = "The Halfcycle service declined to renew this credential and gave no reason this version could read.";
|
|
22533
|
-
|
|
22609
|
+
function unreadableMintRemedy() {
|
|
22610
|
+
return `The Halfcycle service answered with a credential this version could not read. Update the installed Halfcycle runner: run ${signInCommand(installedVersion())} in this repository.`;
|
|
22611
|
+
}
|
|
22534
22612
|
async function refreshEngagementCredential(opts) {
|
|
22535
22613
|
const envFilePath = readEnvFilePath(opts.source);
|
|
22536
22614
|
if (!envFilePath)
|
|
22537
|
-
return { ok: false, remedy:
|
|
22615
|
+
return { ok: false, remedy: hookRemedy(installedVersion()) };
|
|
22538
22616
|
const stored = readStoredEngagementToken(envFilePath);
|
|
22539
22617
|
if (stored !== void 0 && stored !== opts.refusedToken) {
|
|
22540
22618
|
return { ok: true, token: stored, source: "disk" };
|
|
@@ -22542,7 +22620,7 @@ async function refreshEngagementCredential(opts) {
|
|
|
22542
22620
|
const controlOrigin = readControlOrigin(opts.source).origin;
|
|
22543
22621
|
const accountCredential = readAccountCredential(controlOrigin, opts.home);
|
|
22544
22622
|
if (!accountCredential)
|
|
22545
|
-
return { ok: false, remedy:
|
|
22623
|
+
return { ok: false, remedy: hookRemedy(installedVersion()) };
|
|
22546
22624
|
const minted = await mintThroughJoin(controlOrigin, opts.engagementId, accountCredential, opts.fetchFn ?? globalThis.fetch);
|
|
22547
22625
|
if (!minted.ok)
|
|
22548
22626
|
return minted;
|
|
@@ -22563,10 +22641,10 @@ async function evaluateWithRefresh(opts) {
|
|
|
22563
22641
|
const fetchFn = opts.fetchFn ?? globalThis.fetch;
|
|
22564
22642
|
const first = await evaluate(opts.guardServiceUrl, opts.token, opts.request, fetchFn);
|
|
22565
22643
|
if (first.ok)
|
|
22566
|
-
return { result: first, token: opts.token, remedy:
|
|
22644
|
+
return { result: first, token: opts.token, remedy: hookRemedy(installedVersion()) };
|
|
22567
22645
|
const failure = classifyFailure(first);
|
|
22568
22646
|
if (failure.kind !== "credential" || failure.statusCode !== UNAUTHORIZED) {
|
|
22569
|
-
return { result: first, token: opts.token, remedy:
|
|
22647
|
+
return { result: first, token: opts.token, remedy: hookRemedy(installedVersion()) };
|
|
22570
22648
|
}
|
|
22571
22649
|
const refreshed = await refreshEngagementCredential({
|
|
22572
22650
|
engagementId: opts.engagementId,
|
|
@@ -22578,7 +22656,7 @@ async function evaluateWithRefresh(opts) {
|
|
|
22578
22656
|
if (!refreshed.ok)
|
|
22579
22657
|
return { result: first, token: opts.token, remedy: refreshed.remedy };
|
|
22580
22658
|
const retry = await evaluate(opts.guardServiceUrl, refreshed.token, opts.request, fetchFn);
|
|
22581
|
-
return { result: retry, token: refreshed.token, remedy:
|
|
22659
|
+
return { result: retry, token: refreshed.token, remedy: hookRemedy(installedVersion()) };
|
|
22582
22660
|
}
|
|
22583
22661
|
|
|
22584
22662
|
// dist/hooks/marker.js
|
|
@@ -23708,7 +23786,7 @@ async function observeChanges(sessionId, reply, deps = {}) {
|
|
|
23708
23786
|
var R1_START_NOT_HERE = "Halfcycle cannot count what this phase has changed on this computer yet, because the commit the phase started from is not here. Get the project's latest history, and it counts again at the end of the next reply.";
|
|
23709
23787
|
var R2_START_NOT_ON_BRANCH = "Halfcycle cannot count what this phase has changed on this branch, because the branch does not contain the commit the phase started from. Switch to the branch the phase is built on, and it counts again at the end of the next reply.";
|
|
23710
23788
|
function r3NoStartRecorded(phase) {
|
|
23711
|
-
return `Halfcycle cannot count what phase "${phase}" changes, because no starting commit was recorded when it opened. To count from where the project is now, run: ${
|
|
23789
|
+
return `Halfcycle cannot count what phase "${phase}" changes, because no starting commit was recorded when it opened. To count from where the project is now, run: ${halfcycleCommand(installedVersion())} open-phase ${quoteForShell(phase)} --actor "you" --evidence "<what shows this phase is ready to start>"`;
|
|
23712
23790
|
}
|
|
23713
23791
|
function r4OutsideThePlan(parts) {
|
|
23714
23792
|
const first = parts.length === 1 ? "Halfcycle saw changes to a part this phase's plan does not include:" : "Halfcycle saw changes to parts this phase's plan does not include:";
|
|
@@ -27197,12 +27275,12 @@ function runsBesideOtherWork(toolInput, record2) {
|
|
|
27197
27275
|
}
|
|
27198
27276
|
|
|
27199
27277
|
// dist/pace-hook.js
|
|
27200
|
-
import { mkdirSync as
|
|
27278
|
+
import { mkdirSync as mkdirSync10, readFileSync as readFileSync22, renameSync as renameSync12, unlinkSync as unlinkSync8, writeFileSync as writeFileSync14 } from "node:fs";
|
|
27201
27279
|
import nodePath6 from "node:path";
|
|
27202
27280
|
|
|
27203
27281
|
// dist/pace-verb.js
|
|
27204
|
-
import { mkdirSync as
|
|
27205
|
-
import { homedir as
|
|
27282
|
+
import { mkdirSync as mkdirSync9, readdirSync as readdirSync8, readFileSync as readFileSync21, renameSync as renameSync11, statSync as statSync6, writeFileSync as writeFileSync13 } from "node:fs";
|
|
27283
|
+
import { homedir as homedir10 } from "node:os";
|
|
27206
27284
|
import nodePath5 from "node:path";
|
|
27207
27285
|
|
|
27208
27286
|
// dist/plan-report.js
|
|
@@ -27356,12 +27434,72 @@ async function planUsageReport(input, deps = {}) {
|
|
|
27356
27434
|
}
|
|
27357
27435
|
}
|
|
27358
27436
|
|
|
27437
|
+
// dist/relayed-choices.js
|
|
27438
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync20, renameSync as renameSync10, rmSync as rmSync3, writeFileSync as writeFileSync12 } from "node:fs";
|
|
27439
|
+
import { homedir as homedir9 } from "node:os";
|
|
27440
|
+
import { dirname as dirname6, join as join15 } from "node:path";
|
|
27441
|
+
function relayedChoicesFilePath(engagementId, home) {
|
|
27442
|
+
if (!isEngagementId(engagementId))
|
|
27443
|
+
return null;
|
|
27444
|
+
return join15(home ?? homedir9(), HALFCYCLE_DIR_NAME, ENGAGEMENTS_DIR_NAME, engagementId, PACING_DIR_NAME, RELAYED_CHOICES_FILENAME);
|
|
27445
|
+
}
|
|
27446
|
+
function readRelayedChoices(engagementId, phase, home) {
|
|
27447
|
+
const path = relayedChoicesFilePath(engagementId, home);
|
|
27448
|
+
if (path === null)
|
|
27449
|
+
return null;
|
|
27450
|
+
try {
|
|
27451
|
+
const parsed = relayedChoicesFileSchema.safeParse(JSON.parse(readFileSync20(path, "utf-8")));
|
|
27452
|
+
return parsed.success && parsed.data.phase === phase ? parsed.data : null;
|
|
27453
|
+
} catch {
|
|
27454
|
+
return null;
|
|
27455
|
+
}
|
|
27456
|
+
}
|
|
27457
|
+
function keptSaid(said) {
|
|
27458
|
+
const cut = said.trim().slice(0, RELAYED_SAID_MAX);
|
|
27459
|
+
const last = cut.charCodeAt(cut.length - 1);
|
|
27460
|
+
return (last >= 55296 && last <= 56319 ? cut.slice(0, -1) : cut).trim();
|
|
27461
|
+
}
|
|
27462
|
+
function recordRelayedChoice(opts) {
|
|
27463
|
+
const target = relayedChoicesFilePath(opts.engagementId, opts.home);
|
|
27464
|
+
if (target === null || !phaseNameSchema.safeParse(opts.phase).success)
|
|
27465
|
+
return false;
|
|
27466
|
+
const said = keptSaid(opts.said);
|
|
27467
|
+
if (said === "")
|
|
27468
|
+
return false;
|
|
27469
|
+
const when = opts.now ?? /* @__PURE__ */ new Date();
|
|
27470
|
+
if (Number.isNaN(when.getTime()))
|
|
27471
|
+
return false;
|
|
27472
|
+
const entry = { at: when.toISOString(), said };
|
|
27473
|
+
const before = readRelayedChoices(opts.engagementId, opts.phase, opts.home);
|
|
27474
|
+
const file2 = relayedChoicesFileSchema.safeParse({
|
|
27475
|
+
phase: opts.phase,
|
|
27476
|
+
entries: [...before?.entries ?? [], entry]
|
|
27477
|
+
});
|
|
27478
|
+
if (!file2.success)
|
|
27479
|
+
return false;
|
|
27480
|
+
const temp = join15(dirname6(target), `.${RELAYED_CHOICES_FILENAME}.${process.pid}.tmp`);
|
|
27481
|
+
try {
|
|
27482
|
+
mkdirSync8(dirname6(target), { recursive: true, mode: 448 });
|
|
27483
|
+
writeFileSync12(temp, `${JSON.stringify(file2.data)}
|
|
27484
|
+
`, { mode: 384 });
|
|
27485
|
+
renameSync10(temp, target);
|
|
27486
|
+
return true;
|
|
27487
|
+
} catch {
|
|
27488
|
+
try {
|
|
27489
|
+
rmSync3(temp, { force: true });
|
|
27490
|
+
} catch {
|
|
27491
|
+
}
|
|
27492
|
+
return false;
|
|
27493
|
+
}
|
|
27494
|
+
}
|
|
27495
|
+
|
|
27359
27496
|
// dist/pace-verb.js
|
|
27360
27497
|
var PACE_WINDOW_MINUTES = 300;
|
|
27361
27498
|
var PACE_BASIS_DEADLINE_MS = 5e3;
|
|
27362
27499
|
var PACE_FIRST_READ_WAIT_MS = 10 * 60 * 1e3;
|
|
27363
27500
|
var PACE_LATER_READ_WAIT_MS = 5e3;
|
|
27364
27501
|
var BUILD_NUMBER_FILENAME = "build.json";
|
|
27502
|
+
var PROJECT_PACE_FILENAME = "project-pace.json";
|
|
27365
27503
|
function layoutGraph(tasks, agents, medianTaskMinutes) {
|
|
27366
27504
|
const index = /* @__PURE__ */ new Map();
|
|
27367
27505
|
tasks.forEach((t2, i) => {
|
|
@@ -27479,14 +27617,14 @@ function weekCeilingFor(key, home) {
|
|
|
27479
27617
|
function enginePacingDir(engagementId, home) {
|
|
27480
27618
|
if (!isEngagementId(engagementId))
|
|
27481
27619
|
return null;
|
|
27482
|
-
return nodePath5.join(home ??
|
|
27620
|
+
return nodePath5.join(home ?? homedir10(), HALFCYCLE_DIR_NAME, ENGAGEMENTS_DIR_NAME, engagementId, PACING_DIR_NAME);
|
|
27483
27621
|
}
|
|
27484
27622
|
function readBuildNumber(engagementId, home) {
|
|
27485
27623
|
const dir = enginePacingDir(engagementId, home);
|
|
27486
27624
|
if (dir === null)
|
|
27487
27625
|
return null;
|
|
27488
27626
|
try {
|
|
27489
|
-
const v = JSON.parse(
|
|
27627
|
+
const v = JSON.parse(readFileSync21(nodePath5.join(dir, BUILD_NUMBER_FILENAME), "utf-8"));
|
|
27490
27628
|
const n = v["number"];
|
|
27491
27629
|
if (typeof v["phase"] === "string" && typeof n === "number" && Number.isInteger(n) && n >= 1 && n <= PACE_AGENTS_MAX && typeof v["namedByOwner"] === "boolean") {
|
|
27492
27630
|
return { phase: v["phase"], number: n, namedByOwner: v["namedByOwner"] };
|
|
@@ -27503,11 +27641,54 @@ function writeBuildNumber(engagementId, value, home) {
|
|
|
27503
27641
|
const dir = enginePacingDir(engagementId, home);
|
|
27504
27642
|
if (dir === null)
|
|
27505
27643
|
throw new Error("not an engagement id");
|
|
27506
|
-
|
|
27644
|
+
mkdirSync9(dir, { recursive: true, mode: 448 });
|
|
27507
27645
|
const path = nodePath5.join(dir, BUILD_NUMBER_FILENAME);
|
|
27508
27646
|
const tmp = `${path}.${String(process.pid)}.tmp`;
|
|
27509
|
-
|
|
27510
|
-
|
|
27647
|
+
writeFileSync13(tmp, JSON.stringify(value), { mode: 384 });
|
|
27648
|
+
renameSync11(tmp, path);
|
|
27649
|
+
}
|
|
27650
|
+
var NO_PROJECT_PACE = { number: null, relayed: [] };
|
|
27651
|
+
function readProjectPace(engagementId, home) {
|
|
27652
|
+
const dir = enginePacingDir(engagementId, home);
|
|
27653
|
+
if (dir === null)
|
|
27654
|
+
return NO_PROJECT_PACE;
|
|
27655
|
+
try {
|
|
27656
|
+
const v = JSON.parse(readFileSync21(nodePath5.join(dir, PROJECT_PACE_FILENAME), "utf-8"));
|
|
27657
|
+
const n = v["number"];
|
|
27658
|
+
const number4 = typeof n === "number" && Number.isInteger(n) && n >= 1 && n <= PACE_AGENTS_MAX ? n : null;
|
|
27659
|
+
const list = Array.isArray(v["relayed"]) ? v["relayed"] : [];
|
|
27660
|
+
const relayed = list.flatMap((e) => {
|
|
27661
|
+
if (typeof e !== "object" || e === null)
|
|
27662
|
+
return [];
|
|
27663
|
+
const { at, said } = e;
|
|
27664
|
+
return typeof at === "string" && typeof said === "string" ? [{ at, said }] : [];
|
|
27665
|
+
});
|
|
27666
|
+
return { number: number4, relayed };
|
|
27667
|
+
} catch {
|
|
27668
|
+
return NO_PROJECT_PACE;
|
|
27669
|
+
}
|
|
27670
|
+
}
|
|
27671
|
+
function writeProjectPace(engagementId, value, home) {
|
|
27672
|
+
const dir = enginePacingDir(engagementId, home);
|
|
27673
|
+
if (dir === null)
|
|
27674
|
+
throw new Error("not an engagement id");
|
|
27675
|
+
mkdirSync9(dir, { recursive: true, mode: 448 });
|
|
27676
|
+
const path = nodePath5.join(dir, PROJECT_PACE_FILENAME);
|
|
27677
|
+
const tmp = `${path}.${String(process.pid)}.tmp`;
|
|
27678
|
+
writeFileSync13(tmp, JSON.stringify(value), { mode: 384 });
|
|
27679
|
+
renameSync11(tmp, path);
|
|
27680
|
+
}
|
|
27681
|
+
function moveRelayedToPhase(engagementId, phase, project, home) {
|
|
27682
|
+
if (project.relayed.length === 0)
|
|
27683
|
+
return;
|
|
27684
|
+
try {
|
|
27685
|
+
for (const e of project.relayed) {
|
|
27686
|
+
const at = new Date(e.at);
|
|
27687
|
+
recordRelayedChoice({ engagementId, phase, said: e.said, now: Number.isNaN(at.getTime()) ? void 0 : at, home });
|
|
27688
|
+
}
|
|
27689
|
+
writeProjectPace(engagementId, { number: project.number, relayed: [] }, home);
|
|
27690
|
+
} catch {
|
|
27691
|
+
}
|
|
27511
27692
|
}
|
|
27512
27693
|
function liveSubAgentsIn(cwd, deps = {}) {
|
|
27513
27694
|
try {
|
|
@@ -27681,7 +27862,8 @@ async function runPaceVerb(args2, deps = {}) {
|
|
|
27681
27862
|
let limitFile = null;
|
|
27682
27863
|
if (parsed.kind === "start") {
|
|
27683
27864
|
const stored = buildNumberFor(engagementId, parsed.phase, deps.home);
|
|
27684
|
-
const
|
|
27865
|
+
const project = readProjectPace(engagementId, deps.home);
|
|
27866
|
+
const kept = stored !== null && stored.namedByOwner ? stored.number : project.number;
|
|
27685
27867
|
const sameGraph = basis !== null && basis.phase === parsed.phase;
|
|
27686
27868
|
const suggestFor = (named2) => suggestPace({
|
|
27687
27869
|
keepFreePercent,
|
|
@@ -27701,6 +27883,7 @@ async function runPaceVerb(args2, deps = {}) {
|
|
|
27701
27883
|
suggestion = { ...named === null ? suggested : suggestFor(named), ...ceiling };
|
|
27702
27884
|
number4 = suggestion.number;
|
|
27703
27885
|
writeBuildNumber(engagementId, { phase: parsed.phase, number: number4, namedByOwner: named !== null }, deps.home);
|
|
27886
|
+
moveRelayedToPhase(engagementId, parsed.phase, project, deps.home);
|
|
27704
27887
|
const limitBasis = basis === null ? null : { tasks: sameGraph ? basis.tasks : [], medianTaskTokens: basis.medianTaskTokens };
|
|
27705
27888
|
limitFile = limitAtStart(pacingDir2, parsed.phase, limitBasis, suggestion.minutes, readPhaseUsage(pacingDir2, parsed.phase));
|
|
27706
27889
|
if (limitFile !== null) {
|
|
@@ -27715,7 +27898,7 @@ async function runPaceVerb(args2, deps = {}) {
|
|
|
27715
27898
|
}
|
|
27716
27899
|
} else {
|
|
27717
27900
|
const stored = basis === null ? readBuildNumber(engagementId, deps.home) : basis.phase === null ? null : buildNumberFor(engagementId, basis.phase, deps.home);
|
|
27718
|
-
number4 = stored?.number ?? CAREFUL_START_AGENTS;
|
|
27901
|
+
number4 = stored?.number ?? readProjectPace(engagementId, deps.home).number ?? CAREFUL_START_AGENTS;
|
|
27719
27902
|
if (basis !== null) {
|
|
27720
27903
|
limitFile = basis.phase === null ? null : limitInForce(pacingDir2, basis.phase, { tasks: basis.tasks, medianTaskTokens: basis.medianTaskTokens }, readPhaseUsage(pacingDir2, basis.phase));
|
|
27721
27904
|
} else {
|
|
@@ -27785,17 +27968,17 @@ function objectOf2(v) {
|
|
|
27785
27968
|
}
|
|
27786
27969
|
function readJson(path) {
|
|
27787
27970
|
try {
|
|
27788
|
-
return objectOf2(JSON.parse(
|
|
27971
|
+
return objectOf2(JSON.parse(readFileSync22(path, "utf-8")));
|
|
27789
27972
|
} catch {
|
|
27790
27973
|
return null;
|
|
27791
27974
|
}
|
|
27792
27975
|
}
|
|
27793
27976
|
function writeJsonWhole2(path, value) {
|
|
27794
|
-
|
|
27977
|
+
mkdirSync10(nodePath6.dirname(path), { recursive: true, mode: 448 });
|
|
27795
27978
|
const tmp = `${path}.${String(process.pid)}.${Math.random().toString(36).slice(2, 10)}.tmp`;
|
|
27796
27979
|
try {
|
|
27797
|
-
|
|
27798
|
-
|
|
27980
|
+
writeFileSync14(tmp, JSON.stringify(value), { mode: 384 });
|
|
27981
|
+
renameSync12(tmp, path);
|
|
27799
27982
|
} catch (err) {
|
|
27800
27983
|
try {
|
|
27801
27984
|
unlinkSync8(tmp);
|
|
@@ -27932,7 +28115,7 @@ async function paceAtTurnEnd(input, reply, deps = {}) {
|
|
|
27932
28115
|
}
|
|
27933
28116
|
const reported = readReportedAccount(key, { home: deps.home });
|
|
27934
28117
|
const build = buildNumberFor(engagementId, basis.phase, deps.home);
|
|
27935
|
-
const number4 = build?.number ?? CAREFUL_START_AGENTS;
|
|
28118
|
+
const number4 = build?.number ?? readProjectPace(engagementId, deps.home).number ?? CAREFUL_START_AGENTS;
|
|
27936
28119
|
const decision = paceOf({ number: number4, keepFreePercent: basis.keepFreePercent, learned, reported, now });
|
|
27937
28120
|
const settled2 = {
|
|
27938
28121
|
pace: decision.pace,
|
|
@@ -28104,14 +28287,14 @@ function paceHoldText(input, toolInput, deps = {}) {
|
|
|
28104
28287
|
|
|
28105
28288
|
// dist/risky/account-names.js
|
|
28106
28289
|
import { randomBytes } from "node:crypto";
|
|
28107
|
-
import { mkdirSync as
|
|
28108
|
-
import { homedir as
|
|
28109
|
-
import { isAbsolute as isAbsolute5, join as
|
|
28290
|
+
import { mkdirSync as mkdirSync11, readFileSync as readFileSync24, renameSync as renameSync13, rmSync as rmSync4, statSync as statSync8, writeFileSync as writeFileSync15 } from "node:fs";
|
|
28291
|
+
import { homedir as homedir12 } from "node:os";
|
|
28292
|
+
import { isAbsolute as isAbsolute5, join as join17, posix as posix2, resolve as resolve7, sep as sep6 } from "node:path";
|
|
28110
28293
|
|
|
28111
28294
|
// dist/risky/facts.js
|
|
28112
|
-
import { existsSync as existsSync8, lstatSync as lstatSync3, readdirSync as readdirSync9, readFileSync as
|
|
28113
|
-
import { homedir as
|
|
28114
|
-
import { basename as pathBasename, dirname as
|
|
28295
|
+
import { existsSync as existsSync8, lstatSync as lstatSync3, readdirSync as readdirSync9, readFileSync as readFileSync23, realpathSync as realpathSync7, statSync as statSync7 } from "node:fs";
|
|
28296
|
+
import { homedir as homedir11, tmpdir as tmpdir2 } from "node:os";
|
|
28297
|
+
import { basename as pathBasename, dirname as dirname7, isAbsolute as isAbsolute4, join as join16, relative as relative7, resolve as resolve6, sep as sep5 } from "node:path";
|
|
28115
28298
|
|
|
28116
28299
|
// dist/risky/shell.js
|
|
28117
28300
|
var MAX_DEPTH = 8;
|
|
@@ -29412,21 +29595,281 @@ function recogniseSimple(cmd) {
|
|
|
29412
29595
|
function programForms(words) {
|
|
29413
29596
|
const forms = [words];
|
|
29414
29597
|
const prog = basename3(words[0].text);
|
|
29598
|
+
const args2 = words.slice(1);
|
|
29415
29599
|
let rest;
|
|
29416
29600
|
if (prog === "npx" || prog === "bunx" || prog === "pnpx") {
|
|
29417
|
-
rest = skipRunnerOptions(
|
|
29601
|
+
rest = skipRunnerOptions(args2);
|
|
29418
29602
|
} else if (prog === "npm" || prog === PNPM || prog === "yarn" || prog === "bun") {
|
|
29419
|
-
const lead = skipLeading(
|
|
29603
|
+
const lead = skipLeading(args2, MANAGER_VALUE_OPTIONS);
|
|
29420
29604
|
const sub = lead[0]?.text;
|
|
29421
29605
|
if (sub === "exec" || sub === "dlx" || sub === "x")
|
|
29422
29606
|
rest = skipRunnerOptions(lead.slice(1));
|
|
29423
29607
|
else if (sub !== void 0 && prog !== "npm")
|
|
29424
29608
|
rest = lead;
|
|
29609
|
+
} else {
|
|
29610
|
+
const started = PYTHON_PROGRAM.test(prog) ? pythonStarts(args2) : prog === "ruby" ? rubyStarts(args2) : prog === "bundle" ? bundleExecStarts(args2) : prog === "go" ? goRunStarts(args2) : prog === "cargo" ? cargoRunStarts(args2) : prog === "uv" ? uvRunStarts(args2) : prog === DENO ? denoRunStarts(args2) : void 0;
|
|
29611
|
+
if (started !== void 0 && started.length > 0 && startsPublisher(started[0]))
|
|
29612
|
+
rest = started;
|
|
29613
|
+
else if (prog === "uv" && started !== void 0 && started.length > 0) {
|
|
29614
|
+
for (const inner of programForms(started).slice(1))
|
|
29615
|
+
if (startsPublisher(inner[0]))
|
|
29616
|
+
forms.push(inner);
|
|
29617
|
+
}
|
|
29425
29618
|
}
|
|
29426
29619
|
if (rest !== void 0 && rest.length > 0)
|
|
29427
29620
|
forms.push(rest);
|
|
29428
29621
|
return forms;
|
|
29429
29622
|
}
|
|
29623
|
+
var DENO = "deno";
|
|
29624
|
+
var UV_VALUE_OPTIONS = /* @__PURE__ */ new Set([
|
|
29625
|
+
"--directory",
|
|
29626
|
+
"--project",
|
|
29627
|
+
"--config-file",
|
|
29628
|
+
"--cache-dir",
|
|
29629
|
+
"--python",
|
|
29630
|
+
"-p",
|
|
29631
|
+
"--with",
|
|
29632
|
+
"--with-editable",
|
|
29633
|
+
"--with-requirements",
|
|
29634
|
+
"--env-file",
|
|
29635
|
+
"--package",
|
|
29636
|
+
"--extra",
|
|
29637
|
+
"--group",
|
|
29638
|
+
"--no-group",
|
|
29639
|
+
"--only-group",
|
|
29640
|
+
"--index",
|
|
29641
|
+
"--default-index",
|
|
29642
|
+
"--index-url",
|
|
29643
|
+
"-i",
|
|
29644
|
+
"--extra-index-url",
|
|
29645
|
+
"--find-links",
|
|
29646
|
+
"-f",
|
|
29647
|
+
"--index-strategy",
|
|
29648
|
+
"--keyring-provider",
|
|
29649
|
+
"--resolution",
|
|
29650
|
+
"--prerelease",
|
|
29651
|
+
"--exclude-newer",
|
|
29652
|
+
"--link-mode",
|
|
29653
|
+
"--color",
|
|
29654
|
+
"--refresh-package",
|
|
29655
|
+
"--reinstall-package",
|
|
29656
|
+
"--upgrade-package",
|
|
29657
|
+
"-P",
|
|
29658
|
+
"--python-preference"
|
|
29659
|
+
]);
|
|
29660
|
+
function uvRunStarts(args2) {
|
|
29661
|
+
const lead = skipLeading(args2, UV_VALUE_OPTIONS);
|
|
29662
|
+
if (lead[0]?.text !== "run")
|
|
29663
|
+
return void 0;
|
|
29664
|
+
const rest = lead.slice(1);
|
|
29665
|
+
let j = 0;
|
|
29666
|
+
while (j < rest.length) {
|
|
29667
|
+
const t = rest[j].text;
|
|
29668
|
+
if (t === "--")
|
|
29669
|
+
return rest.slice(j + 1);
|
|
29670
|
+
if (t === "-m" || t === "--module")
|
|
29671
|
+
return rest.slice(j + 1);
|
|
29672
|
+
if (!t.startsWith("-"))
|
|
29673
|
+
return rest.slice(j);
|
|
29674
|
+
j += UV_VALUE_OPTIONS.has(t) ? 2 : 1;
|
|
29675
|
+
}
|
|
29676
|
+
return void 0;
|
|
29677
|
+
}
|
|
29678
|
+
var DENO_VALUE_OPTIONS = /* @__PURE__ */ new Set([
|
|
29679
|
+
"-c",
|
|
29680
|
+
"--config",
|
|
29681
|
+
"--import-map",
|
|
29682
|
+
"--lock",
|
|
29683
|
+
"--cert",
|
|
29684
|
+
"--location",
|
|
29685
|
+
"--seed",
|
|
29686
|
+
"--v8-flags"
|
|
29687
|
+
]);
|
|
29688
|
+
function denoRunStarts(args2) {
|
|
29689
|
+
if (args2[0]?.text !== "run")
|
|
29690
|
+
return void 0;
|
|
29691
|
+
const rest = args2.slice(1);
|
|
29692
|
+
let j = 0;
|
|
29693
|
+
while (j < rest.length) {
|
|
29694
|
+
const t = rest[j].text;
|
|
29695
|
+
if (t === "--") {
|
|
29696
|
+
j++;
|
|
29697
|
+
break;
|
|
29698
|
+
}
|
|
29699
|
+
if (!t.startsWith("-"))
|
|
29700
|
+
break;
|
|
29701
|
+
j += DENO_VALUE_OPTIONS.has(t) ? 2 : 1;
|
|
29702
|
+
}
|
|
29703
|
+
const spec = rest[j];
|
|
29704
|
+
const m = spec === void 0 ? null : /^(?:npm|jsr):(.+)$/.exec(spec.text);
|
|
29705
|
+
if (spec === void 0 || m === null)
|
|
29706
|
+
return void 0;
|
|
29707
|
+
const parts = m[1].split("/").filter((p) => p !== "");
|
|
29708
|
+
const name = parts[0]?.startsWith("@") ? parts[1] : parts[0];
|
|
29709
|
+
const bare = name?.replace(/@.*$/, "");
|
|
29710
|
+
return bare === void 0 || bare === "" ? void 0 : [{ text: bare, literal: spec.literal }, ...rest.slice(j + 1)];
|
|
29711
|
+
}
|
|
29712
|
+
var PYTHON_PROGRAM = /^python(\d+(\.\d+)*)?$/;
|
|
29713
|
+
function startsPublisher(word) {
|
|
29714
|
+
const prog = basename3(word.text);
|
|
29715
|
+
return Object.hasOwn(PUBLISH_SEQUENCES, prog) || Object.hasOwn(DEPLOY_SEQUENCES, prog) || prog === VERCEL;
|
|
29716
|
+
}
|
|
29717
|
+
function readCluster(args2, i, letters) {
|
|
29718
|
+
const word = args2[i];
|
|
29719
|
+
const t = word.text;
|
|
29720
|
+
for (let k = 1; k < t.length; k++) {
|
|
29721
|
+
const c = t[k];
|
|
29722
|
+
if (letters.stop.includes(c))
|
|
29723
|
+
return null;
|
|
29724
|
+
const tail = t.slice(k + 1);
|
|
29725
|
+
if (letters.start.includes(c))
|
|
29726
|
+
return tail !== "" ? [{ text: tail, literal: word.literal }, ...args2.slice(i + 1)] : args2.slice(i + 1);
|
|
29727
|
+
if (letters.value.includes(c))
|
|
29728
|
+
return tail !== "" ? i + 1 : i + 2;
|
|
29729
|
+
if (letters.attached.includes(c))
|
|
29730
|
+
return i + 1;
|
|
29731
|
+
}
|
|
29732
|
+
return i + 1;
|
|
29733
|
+
}
|
|
29734
|
+
function interpreterStarts(args2, letters) {
|
|
29735
|
+
let i = 0;
|
|
29736
|
+
while (i < args2.length) {
|
|
29737
|
+
const t = args2[i].text;
|
|
29738
|
+
if (t === "--")
|
|
29739
|
+
return args2.slice(i + 1);
|
|
29740
|
+
if (t === "-")
|
|
29741
|
+
return void 0;
|
|
29742
|
+
if (!t.startsWith("-"))
|
|
29743
|
+
return args2.slice(i);
|
|
29744
|
+
if (t.startsWith("--")) {
|
|
29745
|
+
i++;
|
|
29746
|
+
continue;
|
|
29747
|
+
}
|
|
29748
|
+
const next = readCluster(args2, i, letters);
|
|
29749
|
+
if (next === null)
|
|
29750
|
+
return void 0;
|
|
29751
|
+
if (typeof next !== "number")
|
|
29752
|
+
return next;
|
|
29753
|
+
i = next;
|
|
29754
|
+
}
|
|
29755
|
+
return void 0;
|
|
29756
|
+
}
|
|
29757
|
+
function pythonStarts(args2) {
|
|
29758
|
+
return interpreterStarts(args2, { stop: "c", start: "m", value: "WX", attached: "" });
|
|
29759
|
+
}
|
|
29760
|
+
function rubyStarts(args2) {
|
|
29761
|
+
return interpreterStarts(args2, { stop: "e", start: "S", value: "IrCE", attached: "0FiKTWx" });
|
|
29762
|
+
}
|
|
29763
|
+
function bundleExecStarts(args2) {
|
|
29764
|
+
const lead = skipLeading(args2, EMPTY);
|
|
29765
|
+
return lead[0]?.text === "exec" ? skipLeading(lead.slice(1), EMPTY) : void 0;
|
|
29766
|
+
}
|
|
29767
|
+
var GO_BUILD_VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
29768
|
+
"C",
|
|
29769
|
+
"p",
|
|
29770
|
+
"asmflags",
|
|
29771
|
+
"buildmode",
|
|
29772
|
+
"compiler",
|
|
29773
|
+
"coverpkg",
|
|
29774
|
+
"covermode",
|
|
29775
|
+
"exec",
|
|
29776
|
+
"gccgoflags",
|
|
29777
|
+
"gcflags",
|
|
29778
|
+
"installsuffix",
|
|
29779
|
+
"ldflags",
|
|
29780
|
+
"mod",
|
|
29781
|
+
"modfile",
|
|
29782
|
+
"overlay",
|
|
29783
|
+
"pgo",
|
|
29784
|
+
"pkgdir",
|
|
29785
|
+
"tags",
|
|
29786
|
+
"toolexec"
|
|
29787
|
+
]);
|
|
29788
|
+
function goRunStarts(args2) {
|
|
29789
|
+
if (args2[0]?.text !== "run")
|
|
29790
|
+
return void 0;
|
|
29791
|
+
const rest = args2.slice(1);
|
|
29792
|
+
let i = 0;
|
|
29793
|
+
while (i < rest.length) {
|
|
29794
|
+
const t = rest[i].text;
|
|
29795
|
+
if (t === "--") {
|
|
29796
|
+
i++;
|
|
29797
|
+
break;
|
|
29798
|
+
}
|
|
29799
|
+
if (!t.startsWith("-"))
|
|
29800
|
+
break;
|
|
29801
|
+
const name = t.replace(/^--?/, "");
|
|
29802
|
+
i += !name.includes("=") && GO_BUILD_VALUE_FLAGS.has(name) ? 2 : 1;
|
|
29803
|
+
}
|
|
29804
|
+
const pkg = rest[i];
|
|
29805
|
+
if (pkg === void 0 || pkg.text.startsWith(".") || pkg.text.startsWith("/") || pkg.text.endsWith(".go"))
|
|
29806
|
+
return void 0;
|
|
29807
|
+
const parts = pkg.text.split("@")[0].split("/").filter((p) => p !== "");
|
|
29808
|
+
let last = parts.pop();
|
|
29809
|
+
if (last !== void 0 && /^v\d+$/.test(last) && parts.length > 0)
|
|
29810
|
+
last = parts.pop();
|
|
29811
|
+
return last === void 0 ? void 0 : [{ text: last, literal: pkg.literal }, ...rest.slice(i + 1)];
|
|
29812
|
+
}
|
|
29813
|
+
var CARGO_VALUE_OPTIONS = /* @__PURE__ */ new Set(["-C", "-Z", "--config", "--color"]);
|
|
29814
|
+
var CARGO_RUN_VALUE_OPTIONS = /* @__PURE__ */ new Set([
|
|
29815
|
+
"-F",
|
|
29816
|
+
"--features",
|
|
29817
|
+
"--target",
|
|
29818
|
+
"--target-dir",
|
|
29819
|
+
"--manifest-path",
|
|
29820
|
+
"-j",
|
|
29821
|
+
"--jobs",
|
|
29822
|
+
"--profile",
|
|
29823
|
+
"--color",
|
|
29824
|
+
"--config",
|
|
29825
|
+
"-Z",
|
|
29826
|
+
"--message-format",
|
|
29827
|
+
"--lockfile-path"
|
|
29828
|
+
]);
|
|
29829
|
+
var CARGO_PROGRAM_OPTIONS = ["--bin", "--example", "-p", "--package"];
|
|
29830
|
+
function cargoRunStarts(args2) {
|
|
29831
|
+
let i = 0;
|
|
29832
|
+
while (i < args2.length) {
|
|
29833
|
+
const t = args2[i].text;
|
|
29834
|
+
if (t === "--" || !(t.startsWith("-") || t.startsWith("+")))
|
|
29835
|
+
break;
|
|
29836
|
+
i += CARGO_VALUE_OPTIONS.has(t) ? 2 : 1;
|
|
29837
|
+
}
|
|
29838
|
+
const sub = args2[i]?.text;
|
|
29839
|
+
if (sub !== "run" && sub !== "r")
|
|
29840
|
+
return void 0;
|
|
29841
|
+
const rest = args2.slice(i + 1);
|
|
29842
|
+
let named;
|
|
29843
|
+
let namedByPackage = false;
|
|
29844
|
+
const passed = [];
|
|
29845
|
+
for (let j = 0; j < rest.length; j++) {
|
|
29846
|
+
const word = rest[j];
|
|
29847
|
+
const t = word.text;
|
|
29848
|
+
if (t === "--") {
|
|
29849
|
+
passed.push(...rest.slice(j + 1));
|
|
29850
|
+
break;
|
|
29851
|
+
}
|
|
29852
|
+
if (!t.startsWith("-")) {
|
|
29853
|
+
passed.push(word);
|
|
29854
|
+
continue;
|
|
29855
|
+
}
|
|
29856
|
+
const eq = t.indexOf("=");
|
|
29857
|
+
const attachedP = /^-p[^=]/.test(t);
|
|
29858
|
+
const name = attachedP ? "-p" : eq < 0 ? t : t.slice(0, eq);
|
|
29859
|
+
if (CARGO_PROGRAM_OPTIONS.includes(name)) {
|
|
29860
|
+
const value = attachedP ? { text: t.slice(2), literal: word.literal } : eq < 0 ? rest[++j] : { text: t.slice(eq + 1), literal: word.literal };
|
|
29861
|
+
const byPackage = name === "-p" || name === "--package";
|
|
29862
|
+
if (value !== void 0 && (named === void 0 || namedByPackage && !byPackage)) {
|
|
29863
|
+
named = value;
|
|
29864
|
+
namedByPackage = byPackage;
|
|
29865
|
+
}
|
|
29866
|
+
continue;
|
|
29867
|
+
}
|
|
29868
|
+
if (eq < 0 && CARGO_RUN_VALUE_OPTIONS.has(name))
|
|
29869
|
+
j++;
|
|
29870
|
+
}
|
|
29871
|
+
return named === void 0 ? void 0 : [named, ...passed];
|
|
29872
|
+
}
|
|
29430
29873
|
var MANAGER_VALUE_OPTIONS = /* @__PURE__ */ new Set(["--filter", "-F", "-C", "--dir", "--prefix", "--cwd", "--workspace"]);
|
|
29431
29874
|
function skipLeading(words, valueOptions) {
|
|
29432
29875
|
let j = 0;
|
|
@@ -30065,7 +30508,12 @@ var PUBLISH_SEQUENCES = {
|
|
|
30065
30508
|
docker: [["push"]],
|
|
30066
30509
|
podman: [["push"]],
|
|
30067
30510
|
vsce: [["publish"]],
|
|
30068
|
-
dotnet: [["nuget", "push"]]
|
|
30511
|
+
dotnet: [["nuget", "push"]],
|
|
30512
|
+
rake: [["release"]],
|
|
30513
|
+
flit: [["publish"]],
|
|
30514
|
+
hatch: [["publish"]],
|
|
30515
|
+
pdm: [["publish"]],
|
|
30516
|
+
uv: [["publish"]]
|
|
30069
30517
|
};
|
|
30070
30518
|
var DEPLOY_SEQUENCES = {
|
|
30071
30519
|
netlify: [["deploy"]],
|
|
@@ -30075,7 +30523,9 @@ var DEPLOY_SEQUENCES = {
|
|
|
30075
30523
|
wrangler: [["deploy"]],
|
|
30076
30524
|
terraform: [["apply"], ["destroy"]],
|
|
30077
30525
|
tofu: [["apply"], ["destroy"]],
|
|
30078
|
-
kubectl: [["apply"], ["delete"]]
|
|
30526
|
+
kubectl: [["apply"], ["delete"]],
|
|
30527
|
+
cap: [["deploy"]],
|
|
30528
|
+
mkdocs: [["gh-deploy"]]
|
|
30079
30529
|
};
|
|
30080
30530
|
function publishMatch(cmd, prog, args2) {
|
|
30081
30531
|
const seqs = PUBLISH_SEQUENCES[prog];
|
|
@@ -30083,11 +30533,13 @@ function publishMatch(cmd, prog, args2) {
|
|
|
30083
30533
|
return [];
|
|
30084
30534
|
if (hasLong(args2, "--dry-run"))
|
|
30085
30535
|
return [];
|
|
30086
|
-
|
|
30536
|
+
const words = prog === "uv" ? operandTexts(skipLeading(args2, UV_VALUE_OPTIONS)).slice(0, 1) : operandTexts(args2);
|
|
30537
|
+
return containsSequence(words, seqs) ? [{ type: "publish", program: prog, command: cmd }] : [];
|
|
30087
30538
|
}
|
|
30539
|
+
var VERCEL = "vercel";
|
|
30088
30540
|
var PRODUCTION_DEPLOY_OPTIONS = ["--prod", "--production"];
|
|
30089
30541
|
function deployMatch(cmd, prog, args2) {
|
|
30090
|
-
if (prog ===
|
|
30542
|
+
if (prog === VERCEL) {
|
|
30091
30543
|
return hasLong(args2, ...PRODUCTION_DEPLOY_OPTIONS) ? [{ type: "deploy", program: prog, command: cmd }] : [];
|
|
30092
30544
|
}
|
|
30093
30545
|
const seqs = DEPLOY_SEQUENCES[prog];
|
|
@@ -30323,7 +30775,7 @@ var Env = class {
|
|
|
30323
30775
|
constructor(ctx) {
|
|
30324
30776
|
this.projectDir = realOrSelf(resolve6(ctx.projectDir));
|
|
30325
30777
|
this.cwd = realOrSelf(resolve6(this.projectDir, ctx.cwd));
|
|
30326
|
-
this.home = realOrSelf(resolve6(ctx.home ??
|
|
30778
|
+
this.home = realOrSelf(resolve6(ctx.home ?? homedir11()));
|
|
30327
30779
|
this.timeoutMs = ctx.gitTimeoutMs ?? FACTS_GIT_TIMEOUT_MS;
|
|
30328
30780
|
this.tempDir = realOrSelf(resolve6(ctx.tempDir ?? tmpdir2()));
|
|
30329
30781
|
const roots = ctx.tempRoots ?? [this.tempDir, tmpdir2(), ...TEMP_ROOTS];
|
|
@@ -30347,7 +30799,7 @@ var Env = class {
|
|
|
30347
30799
|
return this.description;
|
|
30348
30800
|
this.description = null;
|
|
30349
30801
|
try {
|
|
30350
|
-
const raw = JSON.parse(
|
|
30802
|
+
const raw = JSON.parse(readFileSync23(join16(repoRoot, SYSTEM_DESCRIPTION_REL), "utf-8"));
|
|
30351
30803
|
const checked = checkSystemDescription(raw);
|
|
30352
30804
|
if (checked.ok)
|
|
30353
30805
|
this.description = checked.description;
|
|
@@ -30378,7 +30830,7 @@ var Env = class {
|
|
|
30378
30830
|
return false;
|
|
30379
30831
|
let dir = abs;
|
|
30380
30832
|
while (!isDirectory(dir)) {
|
|
30381
|
-
const up =
|
|
30833
|
+
const up = dirname7(dir);
|
|
30382
30834
|
if (up === dir)
|
|
30383
30835
|
return false;
|
|
30384
30836
|
dir = up;
|
|
@@ -30411,18 +30863,18 @@ function resolveHome(text, home, base) {
|
|
|
30411
30863
|
if (text === "~")
|
|
30412
30864
|
return home;
|
|
30413
30865
|
if (text.startsWith("~/"))
|
|
30414
|
-
return
|
|
30866
|
+
return join16(home, text.slice(2));
|
|
30415
30867
|
return resolve6(base, text);
|
|
30416
30868
|
}
|
|
30417
30869
|
function realTarget(abs) {
|
|
30418
|
-
const parent =
|
|
30870
|
+
const parent = dirname7(abs);
|
|
30419
30871
|
if (parent === abs)
|
|
30420
30872
|
return abs;
|
|
30421
|
-
return
|
|
30873
|
+
return join16(realOrSelf(parent), pathBasename(abs));
|
|
30422
30874
|
}
|
|
30423
30875
|
function wordPath(word, base, env) {
|
|
30424
30876
|
if (word.temp !== void 0) {
|
|
30425
|
-
const root = word.temp.base === "mktemp" ?
|
|
30877
|
+
const root = word.temp.base === "mktemp" ? join16(env.tempDir, ".halfcycle-mktemp-new") : env.tempDir;
|
|
30426
30878
|
return resolve6(`${root}${word.temp.suffix}`);
|
|
30427
30879
|
}
|
|
30428
30880
|
return word.literal ? resolveHome(word.text, env.home, base) : null;
|
|
@@ -30568,7 +31020,7 @@ function globPath(abs) {
|
|
|
30568
31020
|
const next = [];
|
|
30569
31021
|
if (!/[*?[]/.test(segment)) {
|
|
30570
31022
|
for (const c of current)
|
|
30571
|
-
next.push(
|
|
31023
|
+
next.push(join16(c, segment));
|
|
30572
31024
|
} else {
|
|
30573
31025
|
const re = segmentPattern(segment);
|
|
30574
31026
|
for (const c of current) {
|
|
@@ -30582,7 +31034,7 @@ function globPath(abs) {
|
|
|
30582
31034
|
if (n.startsWith(".") && !segment.startsWith("."))
|
|
30583
31035
|
continue;
|
|
30584
31036
|
if (re.test(n))
|
|
30585
|
-
next.push(
|
|
31037
|
+
next.push(join16(c, n));
|
|
30586
31038
|
}
|
|
30587
31039
|
}
|
|
30588
31040
|
}
|
|
@@ -30710,7 +31162,7 @@ function findKeeps(filter, roots, repoRoot) {
|
|
|
30710
31162
|
const names = filter.names.map((n) => findPattern(n.pattern, n.fold, false));
|
|
30711
31163
|
const excluded = filter.excluded.map((p) => findPattern(p, false, true));
|
|
30712
31164
|
const steps = (rel) => {
|
|
30713
|
-
const abs =
|
|
31165
|
+
const abs = join16(repoRoot, rel);
|
|
30714
31166
|
const out = [];
|
|
30715
31167
|
for (const r of roots) {
|
|
30716
31168
|
if (!isInside(abs, r.abs))
|
|
@@ -30782,9 +31234,9 @@ function credentialFilesIn(folders, repoRoot, deadline, skip) {
|
|
|
30782
31234
|
const out = [];
|
|
30783
31235
|
const stack = [];
|
|
30784
31236
|
for (const f of folders) {
|
|
30785
|
-
if (isDirectory(
|
|
31237
|
+
if (isDirectory(join16(repoRoot, f)))
|
|
30786
31238
|
stack.push(f);
|
|
30787
|
-
else if (pathExists(
|
|
31239
|
+
else if (pathExists(join16(repoRoot, f)) && isCredentialPath(f))
|
|
30788
31240
|
out.push(f);
|
|
30789
31241
|
}
|
|
30790
31242
|
let seen = 0;
|
|
@@ -30792,7 +31244,7 @@ function credentialFilesIn(folders, repoRoot, deadline, skip) {
|
|
|
30792
31244
|
const rel = stack.pop();
|
|
30793
31245
|
let entries;
|
|
30794
31246
|
try {
|
|
30795
|
-
entries = readdirSync9(
|
|
31247
|
+
entries = readdirSync9(join16(repoRoot, rel), { withFileTypes: true });
|
|
30796
31248
|
} catch {
|
|
30797
31249
|
continue;
|
|
30798
31250
|
}
|
|
@@ -30905,7 +31357,7 @@ function deleteFilesFacts(m, env) {
|
|
|
30905
31357
|
const targets = plainFolderRefused ? inside2.filter((t) => !isDirectory(t)) : inside2;
|
|
30906
31358
|
if (targets.length === 0)
|
|
30907
31359
|
return silentDelete(m);
|
|
30908
|
-
const repoRoot = env.repoRoot(
|
|
31360
|
+
const repoRoot = env.repoRoot(dirname7(targets[0])) ?? env.repoRoot(env.projectDir);
|
|
30909
31361
|
if (repoRoot === null || !targets.every((t) => isInside(t, repoRoot)))
|
|
30910
31362
|
return cannot(thingFor([], targets, null, env));
|
|
30911
31363
|
const keep = m.findFilter === void 0 ? void 0 : findKeeps(m.findFilter, targets.map((t) => ({ abs: t, text: written.get(t) ?? null })), repoRoot);
|
|
@@ -30950,7 +31402,7 @@ function closeFoldsAll(targets, env) {
|
|
|
30950
31402
|
return false;
|
|
30951
31403
|
let at = root;
|
|
30952
31404
|
for (const seg of rel.split("/")) {
|
|
30953
|
-
at =
|
|
31405
|
+
at = join16(at, seg);
|
|
30954
31406
|
try {
|
|
30955
31407
|
if (lstatSync3(at).isSymbolicLink())
|
|
30956
31408
|
return false;
|
|
@@ -31533,7 +31985,7 @@ function publishFacts(m, env) {
|
|
|
31533
31985
|
const start = startFolder(m, env);
|
|
31534
31986
|
if (start !== null && PACKAGE_JSON_PROGRAMS.has(m.program)) {
|
|
31535
31987
|
try {
|
|
31536
|
-
const pkg = JSON.parse(
|
|
31988
|
+
const pkg = JSON.parse(readFileSync23(join16(start, "package.json"), "utf-8"));
|
|
31537
31989
|
if (typeof pkg["name"] === "string" && typeof pkg["version"] === "string" && pkg["name"] !== "" && pkg["version"] !== "") {
|
|
31538
31990
|
name = pkg["name"];
|
|
31539
31991
|
version2 = pkg["version"];
|
|
@@ -31583,7 +32035,7 @@ function shrinkRecordFacts(m, env) {
|
|
|
31583
32035
|
try {
|
|
31584
32036
|
if (!lstatSync3(file2.abs).isFile())
|
|
31585
32037
|
continue;
|
|
31586
|
-
before =
|
|
32038
|
+
before = readFileSync23(file2.abs, "utf-8");
|
|
31587
32039
|
} catch {
|
|
31588
32040
|
continue;
|
|
31589
32041
|
}
|
|
@@ -31635,7 +32087,7 @@ function recordRoot(abs, env) {
|
|
|
31635
32087
|
return null;
|
|
31636
32088
|
let dir = abs;
|
|
31637
32089
|
while (!isDirectory(dir)) {
|
|
31638
|
-
const up =
|
|
32090
|
+
const up = dirname7(dir);
|
|
31639
32091
|
if (up === dir)
|
|
31640
32092
|
return null;
|
|
31641
32093
|
dir = up;
|
|
@@ -31660,7 +32112,7 @@ function recordFilesUnder(folder2, env) {
|
|
|
31660
32112
|
const starts = /* @__PURE__ */ new Set();
|
|
31661
32113
|
for (const { pattern } of PROJECT_RECORD_PATTERNS) {
|
|
31662
32114
|
if (relFolder === "" || patternOwns(relFolder, pattern))
|
|
31663
|
-
starts.add(
|
|
32115
|
+
starts.add(join16(root, pattern));
|
|
31664
32116
|
else if (patternOwns(pattern, relFolder))
|
|
31665
32117
|
starts.add(folder2);
|
|
31666
32118
|
}
|
|
@@ -31686,7 +32138,7 @@ function recordFilesUnder(folder2, env) {
|
|
|
31686
32138
|
continue;
|
|
31687
32139
|
}
|
|
31688
32140
|
for (const n of names)
|
|
31689
|
-
stack.push(
|
|
32141
|
+
stack.push(join16(p, n));
|
|
31690
32142
|
} else if (st.isFile()) {
|
|
31691
32143
|
const r = recordFileAt(p, env);
|
|
31692
32144
|
if (r !== null)
|
|
@@ -31699,7 +32151,7 @@ function recordHistory(files, env) {
|
|
|
31699
32151
|
const out = /* @__PURE__ */ new Map();
|
|
31700
32152
|
const byTree = /* @__PURE__ */ new Map();
|
|
31701
32153
|
for (const abs of files) {
|
|
31702
|
-
const top = env.repoRoot(
|
|
32154
|
+
const top = env.repoRoot(dirname7(abs));
|
|
31703
32155
|
if (top === null || !isInside(abs, top))
|
|
31704
32156
|
continue;
|
|
31705
32157
|
const list = byTree.get(top) ?? [];
|
|
@@ -31776,9 +32228,9 @@ function isRecord2(v) {
|
|
|
31776
32228
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
31777
32229
|
}
|
|
31778
32230
|
function placesFor(home, env) {
|
|
31779
|
-
const claude =
|
|
31780
|
-
const codex =
|
|
31781
|
-
return { claude, codex, home, list:
|
|
32231
|
+
const claude = join17(readClaudeConfigFolder(env) ?? home, CLAUDE_SETTINGS_FILENAME);
|
|
32232
|
+
const codex = join17(codexHomeOf(env, home), CODEX_SETTINGS_FILENAME);
|
|
32233
|
+
return { claude, codex, home, list: join17(home, HALFCYCLE_DIR_NAME, ACCOUNT_NAMES_FILENAME), firstLine: `${claude} ${codex}` };
|
|
31782
32234
|
}
|
|
31783
32235
|
function claudeNames(text) {
|
|
31784
32236
|
const root = JSON.parse(text);
|
|
@@ -31818,7 +32270,7 @@ function canonical(stored) {
|
|
|
31818
32270
|
function readSource(path, parse3) {
|
|
31819
32271
|
let text;
|
|
31820
32272
|
try {
|
|
31821
|
-
text =
|
|
32273
|
+
text = readFileSync24(path, "utf-8");
|
|
31822
32274
|
} catch (e) {
|
|
31823
32275
|
const code = e.code;
|
|
31824
32276
|
return { names: [], broken: code !== "ENOENT" && code !== "ENOTDIR" };
|
|
@@ -31847,7 +32299,7 @@ function namesFromList(p) {
|
|
|
31847
32299
|
}
|
|
31848
32300
|
let lines2;
|
|
31849
32301
|
try {
|
|
31850
|
-
lines2 =
|
|
32302
|
+
lines2 = readFileSync24(p.list, "utf-8").split("\n");
|
|
31851
32303
|
} catch {
|
|
31852
32304
|
return null;
|
|
31853
32305
|
}
|
|
@@ -31863,13 +32315,13 @@ function writeList(p, names) {
|
|
|
31863
32315
|
const lines2 = [p.firstLine, ...comparable.length === names.length ? [] : [ACCOUNT_NAMES_ANY], ...comparable];
|
|
31864
32316
|
const temp = `${p.list}.${String(process.pid)}.${randomBytes(4).toString("hex")}`;
|
|
31865
32317
|
try {
|
|
31866
|
-
|
|
31867
|
-
|
|
32318
|
+
mkdirSync11(join17(p.home, HALFCYCLE_DIR_NAME), { recursive: true, mode: 448 });
|
|
32319
|
+
writeFileSync15(temp, `${lines2.join("\n")}
|
|
31868
32320
|
`, { mode: 384, flag: "wx" });
|
|
31869
|
-
|
|
32321
|
+
renameSync13(temp, p.list);
|
|
31870
32322
|
} catch {
|
|
31871
32323
|
try {
|
|
31872
|
-
|
|
32324
|
+
rmSync4(temp, { force: true });
|
|
31873
32325
|
} catch {
|
|
31874
32326
|
return;
|
|
31875
32327
|
}
|
|
@@ -31925,7 +32377,7 @@ function sumOf(texts, name) {
|
|
|
31925
32377
|
}
|
|
31926
32378
|
function textOf(path) {
|
|
31927
32379
|
try {
|
|
31928
|
-
return
|
|
32380
|
+
return readFileSync24(path, "utf-8");
|
|
31929
32381
|
} catch {
|
|
31930
32382
|
return "";
|
|
31931
32383
|
}
|
|
@@ -32020,7 +32472,7 @@ function accountNamesFacts(calls, context) {
|
|
|
32020
32472
|
const writes = calls.filter(readsAccountNames);
|
|
32021
32473
|
if (writes.length === 0)
|
|
32022
32474
|
return [];
|
|
32023
|
-
const names = readNames(placesFor(context.home ??
|
|
32475
|
+
const names = readNames(placesFor(context.home ?? homedir12(), context.env ?? process.env));
|
|
32024
32476
|
if (names.length === 0)
|
|
32025
32477
|
return [];
|
|
32026
32478
|
const perCall = context.gitTimeoutMs ?? FACTS_GIT_TIMEOUT_MS;
|
|
@@ -32548,7 +33000,7 @@ function isOneCall(call) {
|
|
|
32548
33000
|
|
|
32549
33001
|
// dist/risky/allow-once.js
|
|
32550
33002
|
import { createHash as createHash5 } from "node:crypto";
|
|
32551
|
-
import { appendFileSync as appendFileSync5, readFileSync as
|
|
33003
|
+
import { appendFileSync as appendFileSync5, readFileSync as readFileSync25, realpathSync as realpathSync8, renameSync as renameSync14, statSync as statSync9, unlinkSync as unlinkSync9, writeFileSync as writeFileSync16 } from "node:fs";
|
|
32552
33004
|
import { isAbsolute as isAbsolute6, relative as relative8, resolve as resolve8, sep as sep7 } from "node:path";
|
|
32553
33005
|
var ALLOW_ONCE_MS = 5 * 60 * 1e3;
|
|
32554
33006
|
var HELD_STEP_MAX_AGE_MS = 60 * 60 * 1e3;
|
|
@@ -32709,7 +33161,7 @@ function numberKept(path, key) {
|
|
|
32709
33161
|
function readNumbers(path) {
|
|
32710
33162
|
let text;
|
|
32711
33163
|
try {
|
|
32712
|
-
text =
|
|
33164
|
+
text = readFileSync25(path, "utf8");
|
|
32713
33165
|
} catch (err) {
|
|
32714
33166
|
return err.code === "ENOENT" ? { next: 1, steps: /* @__PURE__ */ new Map() } : null;
|
|
32715
33167
|
}
|
|
@@ -32821,13 +33273,13 @@ function distinctSteps(held, numbersPath) {
|
|
|
32821
33273
|
function claimHeld(path, session, now) {
|
|
32822
33274
|
const claimed = `${path}.${process.pid}.${now}.claim`;
|
|
32823
33275
|
try {
|
|
32824
|
-
|
|
33276
|
+
renameSync14(path, claimed);
|
|
32825
33277
|
} catch {
|
|
32826
33278
|
return [];
|
|
32827
33279
|
}
|
|
32828
33280
|
let text = "";
|
|
32829
33281
|
try {
|
|
32830
|
-
text =
|
|
33282
|
+
text = readFileSync25(claimed, "utf8");
|
|
32831
33283
|
} catch {
|
|
32832
33284
|
text = "";
|
|
32833
33285
|
}
|
|
@@ -32882,7 +33334,7 @@ function nowOf(deps) {
|
|
|
32882
33334
|
}
|
|
32883
33335
|
function readRecord2(path, session) {
|
|
32884
33336
|
try {
|
|
32885
|
-
return parseRecord(
|
|
33337
|
+
return parseRecord(readFileSync25(path, "utf8"), session);
|
|
32886
33338
|
} catch {
|
|
32887
33339
|
return null;
|
|
32888
33340
|
}
|
|
@@ -32920,8 +33372,8 @@ function writeRecord(path, record2) {
|
|
|
32920
33372
|
function writeWhole2(path, body) {
|
|
32921
33373
|
const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
32922
33374
|
try {
|
|
32923
|
-
|
|
32924
|
-
|
|
33375
|
+
writeFileSync16(tmp, body, { mode: 384 });
|
|
33376
|
+
renameSync14(tmp, path);
|
|
32925
33377
|
return true;
|
|
32926
33378
|
} catch {
|
|
32927
33379
|
removeQuietly(tmp);
|
|
@@ -33021,8 +33473,8 @@ function decideAutonomous(facts, mayPublishNow) {
|
|
|
33021
33473
|
}
|
|
33022
33474
|
|
|
33023
33475
|
// dist/risky/own-copy.js
|
|
33024
|
-
import { readFileSync as
|
|
33025
|
-
import { join as
|
|
33476
|
+
import { readFileSync as readFileSync26 } from "node:fs";
|
|
33477
|
+
import { join as join18, posix as posix3, win32 as win322 } from "node:path";
|
|
33026
33478
|
var OWN_COPY_START_TOOL = "Agent";
|
|
33027
33479
|
var OWN_COPY_WRITE_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit", "MultiEdit", "NotebookEdit"]);
|
|
33028
33480
|
var OWN_COPY_ISOLATION = "worktree";
|
|
@@ -33043,7 +33495,7 @@ function stringField2(o, key) {
|
|
|
33043
33495
|
}
|
|
33044
33496
|
function readOr(deps, path) {
|
|
33045
33497
|
try {
|
|
33046
|
-
return (deps.readFile ?? ((p) =>
|
|
33498
|
+
return (deps.readFile ?? ((p) => readFileSync26(p, "utf-8")))(path);
|
|
33047
33499
|
} catch {
|
|
33048
33500
|
return null;
|
|
33049
33501
|
}
|
|
@@ -33083,7 +33535,7 @@ function typeCanChangeFiles(subagentType, deps) {
|
|
|
33083
33535
|
return true;
|
|
33084
33536
|
if (AGENT_FILE_NAME.test(type)) {
|
|
33085
33537
|
for (const base of [deps.projectDir, deps.home]) {
|
|
33086
|
-
const text = readOr(deps,
|
|
33538
|
+
const text = readOr(deps, join18(base, ".claude", "agents", `${type}.md`));
|
|
33087
33539
|
if (text === null)
|
|
33088
33540
|
continue;
|
|
33089
33541
|
const tools = frontmatterTools(text);
|
|
@@ -33187,20 +33639,111 @@ function judgeChange(input, call, deps) {
|
|
|
33187
33639
|
};
|
|
33188
33640
|
}
|
|
33189
33641
|
|
|
33642
|
+
// dist/risky/skip-checks.js
|
|
33643
|
+
var SKIP_CHECKS_GIT_SUBCOMMANDS = ["commit", "push"];
|
|
33644
|
+
var GIT_PROGRAM = "git";
|
|
33645
|
+
var NO_VERIFY = "--no-verify";
|
|
33646
|
+
var COMMIT_LONG_VALUE = /* @__PURE__ */ new Set([
|
|
33647
|
+
"--message",
|
|
33648
|
+
"--file",
|
|
33649
|
+
"--template",
|
|
33650
|
+
"--reuse-message",
|
|
33651
|
+
"--reedit-message",
|
|
33652
|
+
"--author",
|
|
33653
|
+
"--date",
|
|
33654
|
+
"--cleanup",
|
|
33655
|
+
"--fixup",
|
|
33656
|
+
"--squash",
|
|
33657
|
+
"--trailer",
|
|
33658
|
+
"--pathspec-from-file"
|
|
33659
|
+
]);
|
|
33660
|
+
var COMMIT_GRAMMAR = {
|
|
33661
|
+
shortSkip: "n",
|
|
33662
|
+
shortValue: /* @__PURE__ */ new Set(["m", "F", "c", "C", "t", "u", "S"]),
|
|
33663
|
+
shortSeparateValue: /* @__PURE__ */ new Set(["m", "F", "c", "C", "t"]),
|
|
33664
|
+
longValue: COMMIT_LONG_VALUE
|
|
33665
|
+
};
|
|
33666
|
+
var PUSH_LONG_VALUE = /* @__PURE__ */ new Set(["--push-option", "--repo", "--receive-pack", "--exec"]);
|
|
33667
|
+
var PUSH_GRAMMAR = {
|
|
33668
|
+
shortSkip: null,
|
|
33669
|
+
shortValue: /* @__PURE__ */ new Set(["o"]),
|
|
33670
|
+
shortSeparateValue: /* @__PURE__ */ new Set(["o"]),
|
|
33671
|
+
longValue: PUSH_LONG_VALUE
|
|
33672
|
+
};
|
|
33673
|
+
var GRAMMARS = {
|
|
33674
|
+
commit: COMMIT_GRAMMAR,
|
|
33675
|
+
push: PUSH_GRAMMAR
|
|
33676
|
+
};
|
|
33677
|
+
function skipsChecks(command) {
|
|
33678
|
+
const out = [];
|
|
33679
|
+
for (const cmd of splitCommand(command)) {
|
|
33680
|
+
if (cmd.words.length === 0 || basename3(cmd.words[0].text) !== GIT_PROGRAM)
|
|
33681
|
+
continue;
|
|
33682
|
+
const args2 = cmd.words.slice(1);
|
|
33683
|
+
const { at } = gitArgsOf(args2);
|
|
33684
|
+
const sub = args2[at]?.text;
|
|
33685
|
+
const verb = SKIP_CHECKS_GIT_SUBCOMMANDS.find((v) => v === sub);
|
|
33686
|
+
if (verb === void 0)
|
|
33687
|
+
continue;
|
|
33688
|
+
if (carriesSkip(args2.slice(at + 1), GRAMMARS[verb]))
|
|
33689
|
+
out.push({ verb, command: cmd });
|
|
33690
|
+
}
|
|
33691
|
+
return out;
|
|
33692
|
+
}
|
|
33693
|
+
function carriesSkip(rest, grammar) {
|
|
33694
|
+
for (let i = 0; i < rest.length; i++) {
|
|
33695
|
+
const word = rest[i];
|
|
33696
|
+
const t = word.text;
|
|
33697
|
+
if (t === "--")
|
|
33698
|
+
return false;
|
|
33699
|
+
if (t.startsWith("--")) {
|
|
33700
|
+
if (!t.includes("=") && grammar.longValue.has(t)) {
|
|
33701
|
+
i++;
|
|
33702
|
+
continue;
|
|
33703
|
+
}
|
|
33704
|
+
if (hasLongAsGitReads([word], NO_VERIFY))
|
|
33705
|
+
return true;
|
|
33706
|
+
continue;
|
|
33707
|
+
}
|
|
33708
|
+
if (t.length < 2 || !t.startsWith("-"))
|
|
33709
|
+
continue;
|
|
33710
|
+
for (let k = 1; k < t.length; k++) {
|
|
33711
|
+
const letter = t[k];
|
|
33712
|
+
if (letter === grammar.shortSkip)
|
|
33713
|
+
return true;
|
|
33714
|
+
if (grammar.shortValue.has(letter)) {
|
|
33715
|
+
if (k === t.length - 1 && grammar.shortSeparateValue.has(letter))
|
|
33716
|
+
i++;
|
|
33717
|
+
break;
|
|
33718
|
+
}
|
|
33719
|
+
}
|
|
33720
|
+
}
|
|
33721
|
+
return false;
|
|
33722
|
+
}
|
|
33723
|
+
var SKIP_CHECKS_COMMIT_FIX = "Run it again without --no-verify or -n. If a check fails, fix what it found.";
|
|
33724
|
+
var SKIP_CHECKS_PUSH_FIX = "Run it again without --no-verify. If a check fails, fix what it found.";
|
|
33725
|
+
function skipChecksRefusal(match, description) {
|
|
33726
|
+
const what = match.verb === "commit" ? "A commit" : "A push";
|
|
33727
|
+
return {
|
|
33728
|
+
person: `Halfcycle: ${what} was stopped. It would skip this project's own checks, and those always run here. ${reasonSentence(description)} ${NOTHING_WAS_CHANGED}`,
|
|
33729
|
+
agent: match.verb === "commit" ? SKIP_CHECKS_COMMIT_FIX : SKIP_CHECKS_PUSH_FIX
|
|
33730
|
+
};
|
|
33731
|
+
}
|
|
33732
|
+
|
|
33190
33733
|
// dist/risky/save.js
|
|
33191
33734
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
33192
|
-
import { chmodSync as chmodSync2, constants as fsConstants, copyFileSync, lstatSync as lstatSync4, mkdirSync as
|
|
33193
|
-
import { homedir as
|
|
33194
|
-
import { dirname as
|
|
33735
|
+
import { chmodSync as chmodSync2, constants as fsConstants, copyFileSync, lstatSync as lstatSync4, mkdirSync as mkdirSync12, readdirSync as readdirSync10, readFileSync as readFileSync27, readlinkSync, realpathSync as realpathSync9, renameSync as renameSync15, rmSync as rmSync5, statSync as statSync10, symlinkSync, writeFileSync as writeFileSync17 } from "node:fs";
|
|
33736
|
+
import { homedir as homedir13 } from "node:os";
|
|
33737
|
+
import { dirname as dirname8, isAbsolute as isAbsolute7, join as join19, resolve as resolve9 } from "node:path";
|
|
33195
33738
|
var SAVE_LIMIT_BYTES = 2e8;
|
|
33196
33739
|
var SAVE_BUDGET_MS = 5e3;
|
|
33197
33740
|
function notSaved(reason) {
|
|
33198
33741
|
return { saved: false, reason };
|
|
33199
33742
|
}
|
|
33200
|
-
function savedFolderOf(engagementId, home =
|
|
33743
|
+
function savedFolderOf(engagementId, home = homedir13()) {
|
|
33201
33744
|
if (!isEngagementId(engagementId))
|
|
33202
33745
|
return null;
|
|
33203
|
-
return
|
|
33746
|
+
return join19(home, HALFCYCLE_DIR_NAME, ENGAGEMENTS_DIR_NAME, engagementId, SAVED_DIR_NAME);
|
|
33204
33747
|
}
|
|
33205
33748
|
function saveFirst(staked, ctx) {
|
|
33206
33749
|
const now = ctx.now ?? Date.now;
|
|
@@ -33231,20 +33774,20 @@ function saveFirst(staked, ctx) {
|
|
|
33231
33774
|
const id = freshId(folder2, ctx.newId);
|
|
33232
33775
|
if (id === null)
|
|
33233
33776
|
return notSaved(AUTONOMY_SAVE_FAILED_REASON);
|
|
33234
|
-
saveDir =
|
|
33777
|
+
saveDir = join19(folder2, id);
|
|
33235
33778
|
const repository = repositoryOf(g);
|
|
33236
33779
|
if (repository === null)
|
|
33237
33780
|
return failed(saveDir);
|
|
33238
|
-
|
|
33781
|
+
writeFileSync17(join19(saveDir, SAVED_REPOSITORY_FILE_NAME), `${repository}
|
|
33239
33782
|
`, { mode: 384 });
|
|
33240
|
-
const privateIndex =
|
|
33783
|
+
const privateIndex = join19(saveDir, PRIVATE_INDEX_NAME);
|
|
33241
33784
|
const commit = saveCommit(id, headCommit2, found2.tracked, plan.lines, privateIndex, g, now());
|
|
33242
|
-
|
|
33785
|
+
rmSync5(privateIndex, { force: true });
|
|
33243
33786
|
if (commit === null)
|
|
33244
33787
|
return failed(saveDir);
|
|
33245
|
-
const copiesDir =
|
|
33788
|
+
const copiesDir = join19(saveDir, SAVED_COPIES_DIR_NAME);
|
|
33246
33789
|
for (const rel of found2.copies) {
|
|
33247
|
-
if (now() > deadline || !copyOne(
|
|
33790
|
+
if (now() > deadline || !copyOne(join19(plan.root, rel), join19(copiesDir, rel)))
|
|
33248
33791
|
return failed(saveDir);
|
|
33249
33792
|
}
|
|
33250
33793
|
const description = savedSchema.safeParse({
|
|
@@ -33260,10 +33803,10 @@ function saveFirst(staked, ctx) {
|
|
|
33260
33803
|
});
|
|
33261
33804
|
if (!description.success)
|
|
33262
33805
|
return failed(saveDir);
|
|
33263
|
-
const file2 =
|
|
33264
|
-
|
|
33806
|
+
const file2 = join19(saveDir, SAVED_FILE_NAME);
|
|
33807
|
+
writeFileSync17(`${file2}.part`, `${JSON.stringify(description.data, null, 2)}
|
|
33265
33808
|
`, { mode: 384 });
|
|
33266
|
-
|
|
33809
|
+
renameSync15(`${file2}.part`, file2);
|
|
33267
33810
|
ctx.beforeRef?.();
|
|
33268
33811
|
const ref = g.run(["update-ref", "--no-deref", savedRefOf(id), commit, ""]);
|
|
33269
33812
|
if (!ref.ok)
|
|
@@ -33276,7 +33819,7 @@ function saveFirst(staked, ctx) {
|
|
|
33276
33819
|
var PRIVATE_INDEX_NAME = "index.part";
|
|
33277
33820
|
function failed(saveDir) {
|
|
33278
33821
|
try {
|
|
33279
|
-
|
|
33822
|
+
rmSync5(saveDir, { recursive: true, force: true });
|
|
33280
33823
|
} catch {
|
|
33281
33824
|
}
|
|
33282
33825
|
return notSaved(AUTONOMY_SAVE_FAILED_REASON);
|
|
@@ -33340,7 +33883,7 @@ function filesOf(plan, g, deadline) {
|
|
|
33340
33883
|
trackedAll.add(path);
|
|
33341
33884
|
if (!reached(path, plan.specs))
|
|
33342
33885
|
continue;
|
|
33343
|
-
const st = lstatOrNull(
|
|
33886
|
+
const st = lstatOrNull(join19(plan.root, path));
|
|
33344
33887
|
if (st !== null && (st.isFile() || st.isSymbolicLink()))
|
|
33345
33888
|
tracked.add(path);
|
|
33346
33889
|
}
|
|
@@ -33352,7 +33895,7 @@ function filesOf(plan, g, deadline) {
|
|
|
33352
33895
|
const rel = stack.pop();
|
|
33353
33896
|
if (rel === ".git")
|
|
33354
33897
|
continue;
|
|
33355
|
-
const abs = rel === "." ? plan.root :
|
|
33898
|
+
const abs = rel === "." ? plan.root : join19(plan.root, rel);
|
|
33356
33899
|
const st = lstatOrNull(abs);
|
|
33357
33900
|
if (st === null)
|
|
33358
33901
|
continue;
|
|
@@ -33383,7 +33926,7 @@ function copyOne(src, dst) {
|
|
|
33383
33926
|
const st = lstatOrNull(src);
|
|
33384
33927
|
if (st === null)
|
|
33385
33928
|
return false;
|
|
33386
|
-
|
|
33929
|
+
mkdirSync12(dirname8(dst), { recursive: true, mode: 448 });
|
|
33387
33930
|
if (st.isSymbolicLink()) {
|
|
33388
33931
|
symlinkSync(readlinkSync(src), dst);
|
|
33389
33932
|
return true;
|
|
@@ -33459,13 +34002,13 @@ var SaveGit = class {
|
|
|
33459
34002
|
}
|
|
33460
34003
|
};
|
|
33461
34004
|
function freshId(folder2, newId) {
|
|
33462
|
-
|
|
34005
|
+
mkdirSync12(folder2, { recursive: true, mode: 448 });
|
|
33463
34006
|
for (let i = 0; i < 5; i++) {
|
|
33464
34007
|
const id = newId?.() ?? defaultId();
|
|
33465
34008
|
if (!savedIdSchema.safeParse(id).success)
|
|
33466
34009
|
return null;
|
|
33467
34010
|
try {
|
|
33468
|
-
|
|
34011
|
+
mkdirSync12(join19(folder2, id), { mode: 448 });
|
|
33469
34012
|
return id;
|
|
33470
34013
|
} catch (e) {
|
|
33471
34014
|
if (e.code !== "EEXIST")
|
|
@@ -33490,7 +34033,7 @@ function repositoryOf(g) {
|
|
|
33490
34033
|
}
|
|
33491
34034
|
function markedRepository(dir) {
|
|
33492
34035
|
try {
|
|
33493
|
-
const text =
|
|
34036
|
+
const text = readFileSync27(join19(dir, SAVED_REPOSITORY_FILE_NAME), "utf-8").trim();
|
|
33494
34037
|
return text === "" ? null : text;
|
|
33495
34038
|
} catch {
|
|
33496
34039
|
return null;
|
|
@@ -33524,7 +34067,7 @@ function pruneSaves(root, engagementId, ctx = {}) {
|
|
|
33524
34067
|
if (!savedIdSchema.safeParse(id).success)
|
|
33525
34068
|
continue;
|
|
33526
34069
|
here.add(id);
|
|
33527
|
-
const dir =
|
|
34070
|
+
const dir = join19(folder2, id);
|
|
33528
34071
|
const st = lstatOrNull(dir);
|
|
33529
34072
|
const answer = savedPruneAnswer({
|
|
33530
34073
|
refMadeAt: refs.get(id) ?? null,
|
|
@@ -33532,9 +34075,9 @@ function pruneSaves(root, engagementId, ctx = {}) {
|
|
|
33532
34075
|
folderRepository: markedRepository(dir)
|
|
33533
34076
|
}, { repository, now: now() });
|
|
33534
34077
|
if (answer === "remove-folder")
|
|
33535
|
-
|
|
34078
|
+
rmSync5(dir, { recursive: true, force: true });
|
|
33536
34079
|
else if (answer === "remove-ref-then-folder" && g.run(["update-ref", "-d", savedRefOf(id)]).ok) {
|
|
33537
|
-
|
|
34080
|
+
rmSync5(dir, { recursive: true, force: true });
|
|
33538
34081
|
} else if (answer === "remove-ref")
|
|
33539
34082
|
g.run(["update-ref", "-d", savedRefOf(id)]);
|
|
33540
34083
|
}
|
|
@@ -33563,19 +34106,19 @@ function realOrSelf3(p) {
|
|
|
33563
34106
|
|
|
33564
34107
|
// dist/autonomy-state.js
|
|
33565
34108
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
33566
|
-
import { chmodSync as chmodSync3, mkdirSync as
|
|
33567
|
-
import { homedir as
|
|
33568
|
-
import { dirname as
|
|
34109
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync13, readFileSync as readFileSync28, renameSync as renameSync16, rmSync as rmSync6, writeFileSync as writeFileSync18 } from "node:fs";
|
|
34110
|
+
import { homedir as homedir14, platform as platform2 } from "node:os";
|
|
34111
|
+
import { dirname as dirname9, join as join20 } from "node:path";
|
|
33569
34112
|
var AUTONOMY_STATE_FILENAME = "autonomy.json";
|
|
33570
34113
|
var AUTONOMY_STATE_DEADLINE_MS = 1500;
|
|
33571
34114
|
function autonomyStateFilePath(engagementId, home) {
|
|
33572
|
-
return
|
|
34115
|
+
return join20(home ?? homedir14(), HALFCYCLE_DIR_NAME, ENGAGEMENTS_DIR_NAME, engagementId, AUTONOMY_STATE_FILENAME);
|
|
33573
34116
|
}
|
|
33574
34117
|
function readCachedAutonomy(engagementId, nowMs, home) {
|
|
33575
34118
|
if (!isEngagementId(engagementId))
|
|
33576
34119
|
return null;
|
|
33577
34120
|
try {
|
|
33578
|
-
const parsed = autonomyStateFileSchema.safeParse(JSON.parse(
|
|
34121
|
+
const parsed = autonomyStateFileSchema.safeParse(JSON.parse(readFileSync28(autonomyStateFilePath(engagementId, home), "utf-8")));
|
|
33579
34122
|
if (!parsed.success || !parsed.data.on)
|
|
33580
34123
|
return null;
|
|
33581
34124
|
const age = nowMs - Date.parse(parsed.data.readAt);
|
|
@@ -33616,24 +34159,24 @@ var LIVE_READ_PROGRAM = [
|
|
|
33616
34159
|
].join("");
|
|
33617
34160
|
function deleteAutonomyStateFile(engagementId, home) {
|
|
33618
34161
|
try {
|
|
33619
|
-
|
|
34162
|
+
rmSync6(autonomyStateFilePath(engagementId, home), { force: true });
|
|
33620
34163
|
} catch {
|
|
33621
34164
|
}
|
|
33622
34165
|
}
|
|
33623
34166
|
function writeAutonomyStateFile(engagementId, file2, home) {
|
|
33624
34167
|
const target = autonomyStateFilePath(engagementId, home);
|
|
33625
|
-
const temp =
|
|
34168
|
+
const temp = join20(dirname9(target), `.${AUTONOMY_STATE_FILENAME}.${process.pid}.tmp`);
|
|
33626
34169
|
try {
|
|
33627
|
-
|
|
33628
|
-
|
|
34170
|
+
mkdirSync13(dirname9(target), { recursive: true, mode: 448 });
|
|
34171
|
+
writeFileSync18(temp, `${JSON.stringify(file2)}
|
|
33629
34172
|
`, { mode: 384 });
|
|
33630
34173
|
if (platform2() !== "win32")
|
|
33631
34174
|
chmodSync3(temp, 384);
|
|
33632
|
-
|
|
34175
|
+
renameSync16(temp, target);
|
|
33633
34176
|
return true;
|
|
33634
34177
|
} catch {
|
|
33635
34178
|
try {
|
|
33636
|
-
|
|
34179
|
+
rmSync6(temp, { force: true });
|
|
33637
34180
|
} catch {
|
|
33638
34181
|
}
|
|
33639
34182
|
return false;
|
|
@@ -33756,7 +34299,7 @@ function shellWord(text) {
|
|
|
33756
34299
|
|
|
33757
34300
|
// dist/hooks/pre-tool-use.js
|
|
33758
34301
|
import { performance } from "node:perf_hooks";
|
|
33759
|
-
import { homedir as
|
|
34302
|
+
import { homedir as homedir15 } from "node:os";
|
|
33760
34303
|
var UNREADABLE_INPUT_NOTICE = "Halfcycle could not read what the coding agent was about to do, so that step went ahead without being checked for anything that cannot be undone. If this keeps happening, update Halfcycle.";
|
|
33761
34304
|
var PRE_TOOL_USE_LIMIT_MS = (HALFCYCLE_HOOK_WIRING.find((e) => e.event === "PreToolUse")?.timeout ?? 10) * 1e3;
|
|
33762
34305
|
var AUTONOMY_REPLY_MARGIN_MS = 1e3;
|
|
@@ -33789,6 +34332,9 @@ function runPreToolUse(deps) {
|
|
|
33789
34332
|
if (calls === null || !calls.every((c) => CHECKED.has(c.toolName)))
|
|
33790
34333
|
return unreadable(deps, input);
|
|
33791
34334
|
const call = calls[0] ?? { toolName: stringOf(input, "tool_name") ?? "", toolInput: {} };
|
|
34335
|
+
const skipped = skippedChecksReply(calls);
|
|
34336
|
+
if (skipped !== null)
|
|
34337
|
+
return skipped;
|
|
33792
34338
|
let answer;
|
|
33793
34339
|
try {
|
|
33794
34340
|
answer = riskyAnswer(calls, () => {
|
|
@@ -33859,6 +34405,24 @@ function runPreToolUse(deps) {
|
|
|
33859
34405
|
return "";
|
|
33860
34406
|
}
|
|
33861
34407
|
}
|
|
34408
|
+
function skippedChecksReply(calls) {
|
|
34409
|
+
try {
|
|
34410
|
+
for (const c of calls) {
|
|
34411
|
+
const command = c.toolName === "Bash" ? c.toolInput["command"] : void 0;
|
|
34412
|
+
if (typeof command !== "string")
|
|
34413
|
+
continue;
|
|
34414
|
+
const match = skipsChecks(command)[0];
|
|
34415
|
+
if (match === void 0)
|
|
34416
|
+
continue;
|
|
34417
|
+
const text = skipChecksRefusal(match, reasonOf(c));
|
|
34418
|
+
return `${preToolUseReplyText("refuse", text.person, text.agent)}
|
|
34419
|
+
`;
|
|
34420
|
+
}
|
|
34421
|
+
} catch {
|
|
34422
|
+
return null;
|
|
34423
|
+
}
|
|
34424
|
+
return null;
|
|
34425
|
+
}
|
|
33862
34426
|
function clockOf(deps) {
|
|
33863
34427
|
return deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
33864
34428
|
}
|
|
@@ -33926,7 +34490,7 @@ function autonomousAnswer(call, staked, sendsSaves, mode, autonomy, deps) {
|
|
|
33926
34490
|
});
|
|
33927
34491
|
if (!saved.saved)
|
|
33928
34492
|
return refuse(autonomyA12(typeSentenceFor(saved.reason === AUTONOMY_COULD_NOT_TELL_REASON ? [] : staked), saved.reason));
|
|
33929
|
-
return `${preToolUseSavedText(autonomyA9(what, saved.id))}
|
|
34493
|
+
return `${preToolUseSavedText(autonomyA9(what, saved.id, installedVersion(deps.env ?? process.env)))}
|
|
33930
34494
|
`;
|
|
33931
34495
|
}
|
|
33932
34496
|
default: {
|
|
@@ -33983,7 +34547,7 @@ function ownCopyOf(input, call, deps) {
|
|
|
33983
34547
|
const walk2 = deps.walk ?? deps.liveness?.walk;
|
|
33984
34548
|
return judgeOwnCopy(input, call, {
|
|
33985
34549
|
projectDir: projectDirOf(deps),
|
|
33986
|
-
home: deps.home ??
|
|
34550
|
+
home: deps.home ?? homedir15(),
|
|
33987
34551
|
...walk2 === void 0 ? {} : { walk: walk2 },
|
|
33988
34552
|
...deps.liveness === void 0 ? {} : { liveness: deps.liveness }
|
|
33989
34553
|
});
|
|
@@ -34017,7 +34581,7 @@ function unreadable(deps, input) {
|
|
|
34017
34581
|
|
|
34018
34582
|
// dist/hooks/session-diff.js
|
|
34019
34583
|
import { unlinkSync as unlinkSync10 } from "node:fs";
|
|
34020
|
-
import { join as
|
|
34584
|
+
import { join as join21 } from "node:path";
|
|
34021
34585
|
var STOP_HOOK_EVENT = {
|
|
34022
34586
|
stop: "Stop",
|
|
34023
34587
|
"subagent-stop": "SubagentStop"
|
|
@@ -34082,7 +34646,7 @@ async function evaluateSession(input, kind, reply, readSeat, profile) {
|
|
|
34082
34646
|
const candidates = ownEditedFiles(repoRoot, sessionId).filter((relPath) => !tracked.has(relPath));
|
|
34083
34647
|
const untracked = getUntrackedFiles(repoRoot, candidates);
|
|
34084
34648
|
const created = untracked.ok ? untracked.value.filter((relPath) => !tracked.has(relPath)) : [];
|
|
34085
|
-
const getDiff = (relPath) => tracked.has(relPath) ? collected.getDiff(relPath) : getSingleFileDiff(
|
|
34649
|
+
const getDiff = (relPath) => tracked.has(relPath) ? collected.getDiff(relPath) : getSingleFileDiff(join21(repoRoot, relPath), repoRoot);
|
|
34086
34650
|
const { evaluated } = partitionInstallerOutput(collected.files);
|
|
34087
34651
|
const { evaluated: createdEvaluated } = partitionInstallerOutput(created);
|
|
34088
34652
|
const changedFiles2 = [...ownChangedFiles(repoRoot, evaluated, sessionId), ...createdEvaluated];
|
|
@@ -34293,65 +34857,6 @@ async function runStop(observeDeps = {}, timeDeps = {}, paceDeps = {}, profile =
|
|
|
34293
34857
|
}, profile);
|
|
34294
34858
|
}
|
|
34295
34859
|
|
|
34296
|
-
// dist/relayed-choices.js
|
|
34297
|
-
import { mkdirSync as mkdirSync13, readFileSync as readFileSync28, renameSync as renameSync16, rmSync as rmSync6, writeFileSync as writeFileSync18 } from "node:fs";
|
|
34298
|
-
import { homedir as homedir15 } from "node:os";
|
|
34299
|
-
import { dirname as dirname9, join as join21 } from "node:path";
|
|
34300
|
-
function relayedChoicesFilePath(engagementId, home) {
|
|
34301
|
-
if (!isEngagementId(engagementId))
|
|
34302
|
-
return null;
|
|
34303
|
-
return join21(home ?? homedir15(), HALFCYCLE_DIR_NAME, ENGAGEMENTS_DIR_NAME, engagementId, PACING_DIR_NAME, RELAYED_CHOICES_FILENAME);
|
|
34304
|
-
}
|
|
34305
|
-
function readRelayedChoices(engagementId, phase, home) {
|
|
34306
|
-
const path = relayedChoicesFilePath(engagementId, home);
|
|
34307
|
-
if (path === null)
|
|
34308
|
-
return null;
|
|
34309
|
-
try {
|
|
34310
|
-
const parsed = relayedChoicesFileSchema.safeParse(JSON.parse(readFileSync28(path, "utf-8")));
|
|
34311
|
-
return parsed.success && parsed.data.phase === phase ? parsed.data : null;
|
|
34312
|
-
} catch {
|
|
34313
|
-
return null;
|
|
34314
|
-
}
|
|
34315
|
-
}
|
|
34316
|
-
function keptSaid(said) {
|
|
34317
|
-
const cut = said.trim().slice(0, RELAYED_SAID_MAX);
|
|
34318
|
-
const last = cut.charCodeAt(cut.length - 1);
|
|
34319
|
-
return (last >= 55296 && last <= 56319 ? cut.slice(0, -1) : cut).trim();
|
|
34320
|
-
}
|
|
34321
|
-
function recordRelayedChoice(opts) {
|
|
34322
|
-
const target = relayedChoicesFilePath(opts.engagementId, opts.home);
|
|
34323
|
-
if (target === null || !phaseNameSchema.safeParse(opts.phase).success)
|
|
34324
|
-
return false;
|
|
34325
|
-
const said = keptSaid(opts.said);
|
|
34326
|
-
if (said === "")
|
|
34327
|
-
return false;
|
|
34328
|
-
const when = opts.now ?? /* @__PURE__ */ new Date();
|
|
34329
|
-
if (Number.isNaN(when.getTime()))
|
|
34330
|
-
return false;
|
|
34331
|
-
const entry = { at: when.toISOString(), said };
|
|
34332
|
-
const before = readRelayedChoices(opts.engagementId, opts.phase, opts.home);
|
|
34333
|
-
const file2 = relayedChoicesFileSchema.safeParse({
|
|
34334
|
-
phase: opts.phase,
|
|
34335
|
-
entries: [...before?.entries ?? [], entry]
|
|
34336
|
-
});
|
|
34337
|
-
if (!file2.success)
|
|
34338
|
-
return false;
|
|
34339
|
-
const temp = join21(dirname9(target), `.${RELAYED_CHOICES_FILENAME}.${process.pid}.tmp`);
|
|
34340
|
-
try {
|
|
34341
|
-
mkdirSync13(dirname9(target), { recursive: true, mode: 448 });
|
|
34342
|
-
writeFileSync18(temp, `${JSON.stringify(file2.data)}
|
|
34343
|
-
`, { mode: 384 });
|
|
34344
|
-
renameSync16(temp, target);
|
|
34345
|
-
return true;
|
|
34346
|
-
} catch {
|
|
34347
|
-
try {
|
|
34348
|
-
rmSync6(temp, { force: true });
|
|
34349
|
-
} catch {
|
|
34350
|
-
}
|
|
34351
|
-
return false;
|
|
34352
|
-
}
|
|
34353
|
-
}
|
|
34354
|
-
|
|
34355
34860
|
// dist/hooks/scope-phrase.js
|
|
34356
34861
|
var APPROVE_PREFIX = /^approve /i;
|
|
34357
34862
|
var SEND_BACK_PREFIX = /^send back /i;
|
|
@@ -34449,21 +34954,61 @@ function autonomyPhraseShape(prompt) {
|
|
|
34449
34954
|
}
|
|
34450
34955
|
|
|
34451
34956
|
// dist/hooks/pace-phrase.js
|
|
34452
|
-
var
|
|
34453
|
-
|
|
34957
|
+
var NUMBER_WORDS = [
|
|
34958
|
+
"one",
|
|
34959
|
+
"two",
|
|
34960
|
+
"three",
|
|
34961
|
+
"four",
|
|
34962
|
+
"five",
|
|
34963
|
+
"six",
|
|
34964
|
+
"seven",
|
|
34965
|
+
"eight",
|
|
34966
|
+
"nine",
|
|
34967
|
+
"ten",
|
|
34968
|
+
"eleven",
|
|
34969
|
+
"twelve",
|
|
34970
|
+
"thirteen",
|
|
34971
|
+
"fourteen",
|
|
34972
|
+
"fifteen",
|
|
34973
|
+
"sixteen",
|
|
34974
|
+
"seventeen",
|
|
34975
|
+
"eighteen",
|
|
34976
|
+
"nineteen",
|
|
34977
|
+
"twenty"
|
|
34978
|
+
];
|
|
34979
|
+
var POLITE = /^(?:please,? )?(.*?)(?:,? please)?[.!]*$/i;
|
|
34980
|
+
var VERB = "(?:(?:run|use|start)(?: with)? )?";
|
|
34981
|
+
var QUALIFIER = "(?: (?:at once|at a time|in parallel|concurrently|simultaneously|together))?";
|
|
34982
|
+
var FASTER = /^(?:(?:go )?faster|(?:run )?more agents)$/i;
|
|
34983
|
+
var AGENTS = new RegExp(`^${VERB}(?:up to )?(-?[0-9]+(?:\\.[0-9]+)?|${NUMBER_WORDS.join("|")}) agents?${QUALIFIER}$`, "i");
|
|
34984
|
+
var MAX_PACE = /^(?:(?:go|run)(?: at)? )?(?:max|maximum|full|top) (?:pace|speed)$/i;
|
|
34985
|
+
var MAX_AGENTS = new RegExp(`^${VERB}(?:the )?(?:max|maximum)(?: possible)?(?: number of)? agents${QUALIFIER}$`, "i");
|
|
34986
|
+
var AS_MANY = new RegExp(`^${VERB}as many agents as (?:possible|you can)${QUALIFIER}$`, "i");
|
|
34987
|
+
var VAGUE = new RegExp(`^${VERB}(?:lots of|a lot of|loads of|plenty of|many|some|several|a few|a bunch of) agents${QUALIFIER}$`, "i");
|
|
34454
34988
|
var KEEP_FREE = /^keep ([0-9]{1,3})% free$/i;
|
|
34455
34989
|
var USE_UP_TO = /^use up to ([0-9]{1,3})%$/i;
|
|
34990
|
+
function countOf(said) {
|
|
34991
|
+
const word = NUMBER_WORDS.indexOf(said.toLowerCase());
|
|
34992
|
+
return word >= 0 ? word + 1 : Number(said);
|
|
34993
|
+
}
|
|
34456
34994
|
function pacePhraseShape(prompt) {
|
|
34457
34995
|
if (typeof prompt !== "string")
|
|
34458
34996
|
return null;
|
|
34459
|
-
const
|
|
34460
|
-
if (LINE_BREAK.test(
|
|
34997
|
+
const trimmed = prompt.trim();
|
|
34998
|
+
if (trimmed === "" || LINE_BREAK.test(trimmed))
|
|
34999
|
+
return null;
|
|
35000
|
+
const line2 = POLITE.exec(trimmed.replace(/ +/g, " "))?.[1] ?? "";
|
|
35001
|
+
if (line2 === "")
|
|
34461
35002
|
return null;
|
|
34462
35003
|
if (FASTER.test(line2))
|
|
34463
35004
|
return { kind: "faster" };
|
|
34464
35005
|
const agents = AGENTS.exec(line2);
|
|
34465
35006
|
if (agents !== null)
|
|
34466
|
-
return { kind: "agents", count:
|
|
35007
|
+
return { kind: "agents", count: countOf(agents[1]) };
|
|
35008
|
+
if (MAX_PACE.test(line2) || MAX_AGENTS.test(line2) || AS_MANY.test(line2))
|
|
35009
|
+
return { kind: "max" };
|
|
35010
|
+
if (VAGUE.test(line2))
|
|
35011
|
+
return { kind: "vague" };
|
|
34467
35012
|
const keep = KEEP_FREE.exec(line2);
|
|
34468
35013
|
if (keep !== null)
|
|
34469
35014
|
return { kind: "keep-free", percent: Number(keep[1]) };
|
|
@@ -34661,7 +35206,7 @@ function nothingDone(act) {
|
|
|
34661
35206
|
return act === "approve" ? "Nothing was approved" : "Nothing was sent back";
|
|
34662
35207
|
}
|
|
34663
35208
|
function showCommand(phase) {
|
|
34664
|
-
return `\`${
|
|
35209
|
+
return `\`${halfcycleCommand(installedVersion())} plan ${quoteForShell(phase)} --show\``;
|
|
34665
35210
|
}
|
|
34666
35211
|
function recordedLine(act, phase, planVersion) {
|
|
34667
35212
|
return act === "approve" ? line(`Approved "${phase}", plan version ${planVersion}, in your session.`) : line(`Sent "${phase}" back with your note, plan version ${planVersion}, in your session. The note is given first to the next session that asks what to do.`);
|
|
@@ -34670,13 +35215,13 @@ function notAttendedLine(act) {
|
|
|
34670
35215
|
return line(`${nothingDone(act)}: approving or sending back by typing counts only when a person types it into an open session.`);
|
|
34671
35216
|
}
|
|
34672
35217
|
function notSignedInLine(act) {
|
|
34673
|
-
return line(`${nothingDone(act)}: this project is not signed in on this computer. ${
|
|
35218
|
+
return line(`${nothingDone(act)}: this project is not signed in on this computer. ${hookRemedy(installedVersion())}`);
|
|
34674
35219
|
}
|
|
34675
35220
|
function notOwnerLine(act) {
|
|
34676
35221
|
return line(`${nothingDone(act)}: only the project's owner can approve or send back this scope.`);
|
|
34677
35222
|
}
|
|
34678
35223
|
function showFirstLine(act) {
|
|
34679
|
-
return line(`${nothingDone(act)}: that phase has not been listed here. List its parts first with \`${
|
|
35224
|
+
return line(`${nothingDone(act)}: that phase has not been listed here. List its parts first with \`${halfcycleCommand(installedVersion())} plan <phase> --show\`, then type the line again.`);
|
|
34680
35225
|
}
|
|
34681
35226
|
function namedPhases(phases) {
|
|
34682
35227
|
const quoted2 = phases.map((phase) => `"${phase}"`);
|
|
@@ -34701,7 +35246,7 @@ function noteRefusedLine() {
|
|
|
34701
35246
|
return line("Nothing was sent back: the note was not accepted. Reword it in plain words and type the send-back again.");
|
|
34702
35247
|
}
|
|
34703
35248
|
function approveRefusedLine() {
|
|
34704
|
-
return line(`${nothingDone("approve")}: Halfcycle did not accept the request. ${
|
|
35249
|
+
return line(`${nothingDone("approve")}: Halfcycle did not accept the request. ${clientUpdateSentence(installedVersion())}`);
|
|
34705
35250
|
}
|
|
34706
35251
|
function cannotReachLine(act) {
|
|
34707
35252
|
return line(`${nothingDone(act)}: Halfcycle could not be reached just now. Type the line again in a minute.`);
|
|
@@ -34742,7 +35287,7 @@ function reviewNotAttendedLine() {
|
|
|
34742
35287
|
return line(`${NOTHING_RECORDED}: reviewing by typing counts only when a person types it into an open session.`);
|
|
34743
35288
|
}
|
|
34744
35289
|
function reviewNotSignedInLine() {
|
|
34745
|
-
return line(`${NOTHING_RECORDED}: this project is not signed in on this computer. ${
|
|
35290
|
+
return line(`${NOTHING_RECORDED}: this project is not signed in on this computer. ${hookRemedy(installedVersion())}`);
|
|
34746
35291
|
}
|
|
34747
35292
|
function reviewCannotReachLine() {
|
|
34748
35293
|
return line(`${NOTHING_RECORDED}: Halfcycle could not be reached just now. Type the line again in a minute.`);
|
|
@@ -34838,7 +35383,7 @@ function reviewCloseRefusedLine(phase, steps) {
|
|
|
34838
35383
|
return line([head, ...steps.map(unfinishedStepLine), "Then type the line again."].join(" "));
|
|
34839
35384
|
}
|
|
34840
35385
|
function reviewRefusedLine(act) {
|
|
34841
|
-
return act === "accept" ? line(`${NOTHING_RECORDED}: Halfcycle did not accept the request. Update Halfcycle by running \`${
|
|
35386
|
+
return act === "accept" ? line(`${NOTHING_RECORDED}: Halfcycle did not accept the request. Update Halfcycle by running \`${halfcycleCommand(installedVersion())}\` in this project's folder, then type the line again.`) : line(`${NOTHING_RECORDED}: the words were not accepted. Reword them in plain words and type the line again.`);
|
|
34842
35387
|
}
|
|
34843
35388
|
function stillWaitingOf(phase, waiting) {
|
|
34844
35389
|
const named = namedPhase(phase);
|
|
@@ -34955,7 +35500,7 @@ function autonomyNotAttendedLine() {
|
|
|
34955
35500
|
return line(`${AUTONOMY_NOTHING_CHANGED}: turning this on or off by typing counts only when a person types it into an open session.`);
|
|
34956
35501
|
}
|
|
34957
35502
|
function autonomyNotSignedInLine() {
|
|
34958
|
-
return line(`${AUTONOMY_NOTHING_CHANGED}: this project is not signed in on this computer. ${
|
|
35503
|
+
return line(`${AUTONOMY_NOTHING_CHANGED}: this project is not signed in on this computer. ${hookRemedy(installedVersion())}`);
|
|
34959
35504
|
}
|
|
34960
35505
|
function autonomyNotOwnerLine() {
|
|
34961
35506
|
return line(`${AUTONOMY_NOTHING_CHANGED}: only the project's owner can turn this on or off.`);
|
|
@@ -35037,7 +35582,7 @@ function waitNotAttendedLine() {
|
|
|
35037
35582
|
return line(`${NOTHING_RECORDED}: an answer counts only when a person types it into an open session.`);
|
|
35038
35583
|
}
|
|
35039
35584
|
function waitNotSignedInLine() {
|
|
35040
|
-
return line(`${NOTHING_RECORDED}: this project is not signed in on this computer. ${
|
|
35585
|
+
return line(`${NOTHING_RECORDED}: this project is not signed in on this computer. ${hookRemedy(installedVersion())}`);
|
|
35041
35586
|
}
|
|
35042
35587
|
function waitNotOwnerLine() {
|
|
35043
35588
|
return line(`${NOTHING_RECORDED}: only the project's owner can answer a decision that waits for them.`);
|
|
@@ -35094,10 +35639,15 @@ var PACE_NOTHING_CHANGED_OPENING = "Nothing changed";
|
|
|
35094
35639
|
function paceAnswerLine(text, _agent) {
|
|
35095
35640
|
return codexLine(text);
|
|
35096
35641
|
}
|
|
35097
|
-
function paceNumberDoneText(n, more) {
|
|
35098
|
-
const
|
|
35642
|
+
function paceNumberDoneText(n, more, running) {
|
|
35643
|
+
const when = running ? "starting now and in every later build" : "from the next build on";
|
|
35644
|
+
const most = n >= PACE_AGENTS_MAX ? " That is the most Halfcycle runs." : "";
|
|
35645
|
+
const head = `Done. This project now runs up to ${paceAgentsOf(n)} at once, ${when}.${most}`;
|
|
35099
35646
|
return more ? `${head} This uses your allowance faster.` : head;
|
|
35100
35647
|
}
|
|
35648
|
+
function paceVagueText() {
|
|
35649
|
+
return `${PACE_NOTHING_CHANGED_OPENING}: say how many agents to run at once, from 1 to ${String(PACE_AGENTS_MAX)}, like "run 5 agents", or say "max pace".`;
|
|
35650
|
+
}
|
|
35101
35651
|
function paceKeepFreeDoneText(percent) {
|
|
35102
35652
|
if (percent === 0)
|
|
35103
35653
|
return PACE_P5;
|
|
@@ -35109,7 +35659,7 @@ function paceUseUpToDoneText(percent) {
|
|
|
35109
35659
|
return `Done. This build may use up to ${String(percent)}% of each usage window.`;
|
|
35110
35660
|
}
|
|
35111
35661
|
function paceNoBuildText() {
|
|
35112
|
-
return `${PACE_NOTHING_CHANGED_OPENING}: no build is running in this project yet.
|
|
35662
|
+
return `${PACE_NOTHING_CHANGED_OPENING}: no build is running in this project yet, so there is no pace to raise. Say a number instead, like "run 5 agents", or say "max pace".`;
|
|
35113
35663
|
}
|
|
35114
35664
|
function paceAgentsRangeText() {
|
|
35115
35665
|
return `${PACE_NOTHING_CHANGED_OPENING}: run between 1 and ${String(PACE_AGENTS_MAX)} agents at once.`;
|
|
@@ -35124,7 +35674,7 @@ function paceNotAttendedText() {
|
|
|
35124
35674
|
return `${PACE_NOTHING_CHANGED_OPENING}: a choice that uses more of your allowance counts only when a person types it into an open session.`;
|
|
35125
35675
|
}
|
|
35126
35676
|
function paceNotSignedInText() {
|
|
35127
|
-
return `${PACE_NOTHING_CHANGED_OPENING}: this project is not signed in on this computer. ${
|
|
35677
|
+
return `${PACE_NOTHING_CHANGED_OPENING}: this project is not signed in on this computer. ${hookRemedy(installedVersion())}`;
|
|
35128
35678
|
}
|
|
35129
35679
|
function paceNotOwnerText() {
|
|
35130
35680
|
return `${PACE_NOTHING_CHANGED_OPENING}: only the project's owner can change this.`;
|
|
@@ -35350,30 +35900,51 @@ async function decidePace(shape, opts) {
|
|
|
35350
35900
|
const say = (text) => paceAnswerLine(text, agent);
|
|
35351
35901
|
const env = opts.env ?? process.env;
|
|
35352
35902
|
const typed = whoTyped(opts);
|
|
35903
|
+
if (shape.kind === "vague")
|
|
35904
|
+
return say(paceVagueText());
|
|
35353
35905
|
const read = readConfig(env);
|
|
35354
35906
|
if (read.config === null) {
|
|
35355
35907
|
return say(readNeverConfiguredReason(env) === "not-this-account" ? paceNotOwnerText() : paceNotSignedInText());
|
|
35356
35908
|
}
|
|
35357
35909
|
const { guardServiceToken, guardEngagementId } = read.config;
|
|
35358
35910
|
const dir = enginePacingDir(guardEngagementId, opts.home);
|
|
35911
|
+
if (dir === null)
|
|
35912
|
+
return say(paceNotSignedInText());
|
|
35359
35913
|
const build = readBuildNumber(guardEngagementId, opts.home);
|
|
35360
|
-
const phase =
|
|
35361
|
-
|
|
35362
|
-
|
|
35914
|
+
const phase = readPaceStateFile(dir).basis?.phase ?? null;
|
|
35915
|
+
const running = build !== null && phase !== null && build.phase === phase ? { build, phase } : null;
|
|
35916
|
+
const project = readProjectPace(guardEngagementId, opts.home);
|
|
35917
|
+
const at = new Date((opts.now ?? Date.now)());
|
|
35363
35918
|
const said = String(promptOf(opts.input)).trim();
|
|
35364
|
-
|
|
35365
|
-
|
|
35366
|
-
|
|
35919
|
+
const relay = () => {
|
|
35920
|
+
if (running !== null) {
|
|
35921
|
+
recordRelayedChoice({ engagementId: guardEngagementId, phase: running.phase, said, now: at, home: opts.home });
|
|
35922
|
+
return;
|
|
35923
|
+
}
|
|
35924
|
+
try {
|
|
35925
|
+
const held = readProjectPace(guardEngagementId, opts.home);
|
|
35926
|
+
writeProjectPace(guardEngagementId, { ...held, relayed: [...held.relayed, { at: at.toISOString(), said }] }, opts.home);
|
|
35927
|
+
} catch {
|
|
35928
|
+
}
|
|
35929
|
+
};
|
|
35930
|
+
if (shape.kind === "faster" || shape.kind === "agents" || shape.kind === "max") {
|
|
35931
|
+
if (shape.kind === "faster" && running === null)
|
|
35932
|
+
return say(paceNoBuildText());
|
|
35933
|
+
const number4 = shape.kind === "faster" ? running.build.number + 1 : shape.kind === "max" ? PACE_AGENTS_MAX : shape.count;
|
|
35934
|
+
if (!Number.isInteger(number4) || number4 < 1 || number4 > PACE_AGENTS_MAX)
|
|
35367
35935
|
return say(paceAgentsRangeText());
|
|
35368
|
-
const
|
|
35936
|
+
const before = running !== null ? running.build.number : project.number ?? CAREFUL_START_AGENTS;
|
|
35937
|
+
const more = number4 > before;
|
|
35369
35938
|
if (more && typed === "not-attended")
|
|
35370
35939
|
return say(paceNotAttendedText());
|
|
35371
|
-
|
|
35372
|
-
|
|
35373
|
-
|
|
35374
|
-
recordRelayedChoice({ engagementId: guardEngagementId, phase, said, now: new Date((opts.now ?? Date.now)()), home: opts.home });
|
|
35940
|
+
if (running !== null) {
|
|
35941
|
+
writeBuildNumber(guardEngagementId, { phase: running.phase, number: number4, namedByOwner: true }, opts.home);
|
|
35942
|
+
adjustPaceState(dir, opts, number4);
|
|
35375
35943
|
}
|
|
35376
|
-
|
|
35944
|
+
writeProjectPace(guardEngagementId, { ...project, number: number4 }, opts.home);
|
|
35945
|
+
if (more && typed === "cannot-tell")
|
|
35946
|
+
relay();
|
|
35947
|
+
return say(paceNumberDoneText(number4, more, running !== null));
|
|
35377
35948
|
}
|
|
35378
35949
|
if (shape.kind === "keep-free" && shape.percent > KEEP_FREE_MAX)
|
|
35379
35950
|
return say(paceKeepFreeRangeText());
|
|
@@ -35401,9 +35972,8 @@ async function decidePace(shape, opts) {
|
|
|
35401
35972
|
case "recorded":
|
|
35402
35973
|
if (response.status !== 200)
|
|
35403
35974
|
return say(paceCannotReachText());
|
|
35404
|
-
if (givenIn === "relayed" && parsed.data.moreAllowance === true)
|
|
35405
|
-
|
|
35406
|
-
}
|
|
35975
|
+
if (givenIn === "relayed" && parsed.data.moreAllowance === true)
|
|
35976
|
+
relay();
|
|
35407
35977
|
return say(done);
|
|
35408
35978
|
case "needs-the-person":
|
|
35409
35979
|
return say(paceNotAttendedText());
|
|
@@ -35884,12 +36454,11 @@ function runResolveEngagement(cwd, registryPath) {
|
|
|
35884
36454
|
}
|
|
35885
36455
|
|
|
35886
36456
|
// dist/refresh-credential.js
|
|
35887
|
-
import { lstatSync as lstatSync5, readFileSync as
|
|
36457
|
+
import { lstatSync as lstatSync5, readFileSync as readFileSync31, realpathSync as realpathSync11 } from "node:fs";
|
|
35888
36458
|
import { homedir as homedir19 } from "node:os";
|
|
35889
36459
|
import { join as join24, resolve as resolve12 } from "node:path";
|
|
35890
36460
|
|
|
35891
36461
|
// dist/mcp-headers.js
|
|
35892
|
-
import { readFileSync as readFileSync31 } from "node:fs";
|
|
35893
36462
|
import { homedir as homedir18 } from "node:os";
|
|
35894
36463
|
import { dirname as dirname10, resolve as resolve11 } from "node:path";
|
|
35895
36464
|
var URL_FLAG = "--url";
|
|
@@ -35920,22 +36489,6 @@ function projectRootFromBinary(binaryPath) {
|
|
|
35920
36489
|
const depth = VENDORED_BIN_REL.split("/").length - 1;
|
|
35921
36490
|
return resolve11(dirname10(binaryPath), ...Array(depth).fill(".."));
|
|
35922
36491
|
}
|
|
35923
|
-
function readPinnedVersion(root) {
|
|
35924
|
-
let raw;
|
|
35925
|
-
try {
|
|
35926
|
-
raw = readFileSync31(resolve11(root, BUNDLE_PIN_REL), "utf-8");
|
|
35927
|
-
} catch {
|
|
35928
|
-
return void 0;
|
|
35929
|
-
}
|
|
35930
|
-
let pin;
|
|
35931
|
-
try {
|
|
35932
|
-
pin = JSON.parse(raw);
|
|
35933
|
-
} catch {
|
|
35934
|
-
return void 0;
|
|
35935
|
-
}
|
|
35936
|
-
const version2 = typeof pin === "object" && pin !== null ? pin["version"] : void 0;
|
|
35937
|
-
return typeof version2 === "string" && version2 !== "" ? version2 : void 0;
|
|
35938
|
-
}
|
|
35939
36492
|
function resolveStore(root, home) {
|
|
35940
36493
|
const pinned = readPinnedId(root);
|
|
35941
36494
|
if ("problem" in pinned)
|
|
@@ -35964,23 +36517,25 @@ function sentences(lines2) {
|
|
|
35964
36517
|
`).join("");
|
|
35965
36518
|
}
|
|
35966
36519
|
function badIdSentence(root) {
|
|
36520
|
+
const signIn = signInCommand(readPinnedVersion(root));
|
|
35967
36521
|
return sentences([
|
|
35968
36522
|
`${resolve11(root, BUNDLE_PIN_REL)} names an engagement id that is not a Halfcycle project id,`,
|
|
35969
|
-
|
|
36523
|
+
`so no credential was read. Delete that file and run ${signIn} again: this repository`,
|
|
35970
36524
|
"is then set up as a new Halfcycle project."
|
|
35971
36525
|
]);
|
|
35972
36526
|
}
|
|
35973
36527
|
function storeProblemSentence(problem, root, home, engagementId) {
|
|
36528
|
+
const signIn = signInCommand(readPinnedVersion(root));
|
|
35974
36529
|
switch (problem) {
|
|
35975
36530
|
case "no-pin":
|
|
35976
36531
|
return sentences([
|
|
35977
36532
|
`no ${BUNDLE_PIN_REL} in ${root}, so this repository has no Halfcycle engagement.`,
|
|
35978
|
-
|
|
36533
|
+
`run ${signIn} here to install one.`
|
|
35979
36534
|
]);
|
|
35980
36535
|
case "no-id":
|
|
35981
36536
|
return sentences([
|
|
35982
36537
|
`${resolve11(root, BUNDLE_PIN_REL)} names no engagement id.`,
|
|
35983
|
-
|
|
36538
|
+
`run ${signIn} here to rewrite it.`
|
|
35984
36539
|
]);
|
|
35985
36540
|
case "bad-id":
|
|
35986
36541
|
return badIdSentence(root);
|
|
@@ -35989,14 +36544,14 @@ function storeProblemSentence(problem, root, home, engagementId) {
|
|
|
35989
36544
|
"this project belongs to another Halfcycle account, so this machine has no",
|
|
35990
36545
|
"credential for it and the Halfcycle tools are not available here. Nothing is",
|
|
35991
36546
|
"broken.",
|
|
35992
|
-
requestAccessSentence(engagementId),
|
|
36547
|
+
requestAccessSentence(engagementId, readControlOrigin().origin),
|
|
35993
36548
|
"If this account is wrong, sign in as the account that owns it and run",
|
|
35994
|
-
|
|
36549
|
+
`${signIn} again.`
|
|
35995
36550
|
]);
|
|
35996
36551
|
case "no-credential":
|
|
35997
36552
|
return sentences([
|
|
35998
36553
|
`this machine holds no credential for engagement ${engagementId ?? ""}.`,
|
|
35999
|
-
`run
|
|
36554
|
+
`run ${signIn} in this repository \u2014 it will sign you in through your browser if needed, and write the credential to ${resolve11(home, HALFCYCLE_DIR_NAME)}, outside this repository.`
|
|
36000
36555
|
]);
|
|
36001
36556
|
}
|
|
36002
36557
|
}
|
|
@@ -36021,6 +36576,7 @@ async function chooseBearer(opts) {
|
|
|
36021
36576
|
const writeErr = opts.writeErr ?? defaultWriteErr;
|
|
36022
36577
|
const home = opts.home ?? homedir18();
|
|
36023
36578
|
const root = projectRootFromBinary(opts.binaryPath);
|
|
36579
|
+
const signIn = signInCommand(readPinnedVersion(root));
|
|
36024
36580
|
const environmentToken = opts.environmentTokenFirst ? readEnvironmentToken() : void 0;
|
|
36025
36581
|
const store = resolveStore(root, home);
|
|
36026
36582
|
let storedToken;
|
|
@@ -36033,7 +36589,7 @@ async function chooseBearer(opts) {
|
|
|
36033
36589
|
if (storedToken === void 0) {
|
|
36034
36590
|
writeErr(sentences([
|
|
36035
36591
|
`GUARD_SERVICE_TOKEN is absent or empty in ${store.path}.`,
|
|
36036
|
-
`run
|
|
36592
|
+
`run ${signIn} in this repository to rewrite this machine's credential.`
|
|
36037
36593
|
]));
|
|
36038
36594
|
return NO_CREDENTIAL_PLACEHOLDER;
|
|
36039
36595
|
}
|
|
@@ -36053,7 +36609,7 @@ async function chooseBearer(opts) {
|
|
|
36053
36609
|
} else {
|
|
36054
36610
|
writeErr(sentences([
|
|
36055
36611
|
"this machine has no Halfcycle server address recorded for this repository, so the credential was not sent.",
|
|
36056
|
-
|
|
36612
|
+
`run ${signIn} in this repository on this machine to record it.`
|
|
36057
36613
|
]));
|
|
36058
36614
|
}
|
|
36059
36615
|
return NO_CREDENTIAL_PLACEHOLDER;
|
|
@@ -36065,7 +36621,7 @@ async function chooseBearer(opts) {
|
|
|
36065
36621
|
writeErr(sentences([
|
|
36066
36622
|
`${registrationFile} asks for this repository's Halfcycle credential to be sent to ${shownUrl(requested ?? "")},`,
|
|
36067
36623
|
`which is not this machine's Halfcycle server (${want ?? "none recorded"}). The credential was NOT sent.`,
|
|
36068
|
-
`if nobody meant to change ${registrationFile}, treat that change as suspect;
|
|
36624
|
+
`if nobody meant to change ${registrationFile}, treat that change as suspect; ${signIn} restores the entry.`
|
|
36069
36625
|
]));
|
|
36070
36626
|
return NO_CREDENTIAL_PLACEHOLDER;
|
|
36071
36627
|
}
|
|
@@ -36085,6 +36641,7 @@ async function chooseBearer(opts) {
|
|
|
36085
36641
|
async function mcpHeaders(opts) {
|
|
36086
36642
|
const writeErr = opts.writeErr ?? defaultWriteErr;
|
|
36087
36643
|
const root = projectRootFromBinary(opts.binaryPath);
|
|
36644
|
+
const signIn = signInCommand(readPinnedVersion(root));
|
|
36088
36645
|
const variableUrl = readMcpServerUrl();
|
|
36089
36646
|
try {
|
|
36090
36647
|
return headerLine(await chooseBearer({
|
|
@@ -36102,7 +36659,7 @@ async function mcpHeaders(opts) {
|
|
|
36102
36659
|
try {
|
|
36103
36660
|
writeErr(sentences([
|
|
36104
36661
|
`the credential could not be read: ${err instanceof Error ? err.message : String(err)}`,
|
|
36105
|
-
`run
|
|
36662
|
+
`run ${signIn} in this repository to rewrite this machine's credential.`
|
|
36106
36663
|
]));
|
|
36107
36664
|
} catch {
|
|
36108
36665
|
return headerLine(NO_CREDENTIAL_PLACEHOLDER, readPinnedVersion(root));
|
|
@@ -36117,11 +36674,13 @@ async function headersVerbLine(binaryPath, rest, run = mcpHeaders, writeErr = de
|
|
|
36117
36674
|
} catch (err) {
|
|
36118
36675
|
if (url2 === void 0)
|
|
36119
36676
|
throw err;
|
|
36120
|
-
const
|
|
36677
|
+
const version2 = readPinnedVersion(projectRootFromBinary(binaryPath));
|
|
36678
|
+
const signIn = signInCommand(version2);
|
|
36679
|
+
const fallback = headerLine(NO_CREDENTIAL_PLACEHOLDER, version2);
|
|
36121
36680
|
try {
|
|
36122
36681
|
writeErr(sentences([
|
|
36123
36682
|
`the credential could not be read: ${err instanceof Error ? err.message : String(err)}`,
|
|
36124
|
-
`run
|
|
36683
|
+
`run ${signIn} in this repository to rewrite this machine's credential.`
|
|
36125
36684
|
]));
|
|
36126
36685
|
} catch {
|
|
36127
36686
|
return fallback;
|
|
@@ -36185,7 +36744,7 @@ var SESSION_START_PROBE_ATTEMPTS = 2;
|
|
|
36185
36744
|
function registeredMcpUrl(projectRoot) {
|
|
36186
36745
|
let parsed;
|
|
36187
36746
|
try {
|
|
36188
|
-
parsed = JSON.parse(
|
|
36747
|
+
parsed = JSON.parse(readFileSync31(resolve12(projectRoot, MCP_REGISTRATION_REL), "utf-8"));
|
|
36189
36748
|
} catch {
|
|
36190
36749
|
return void 0;
|
|
36191
36750
|
}
|
|
@@ -36220,7 +36779,7 @@ function reportOf(body) {
|
|
|
36220
36779
|
const instructions = body["result"]["instructions"];
|
|
36221
36780
|
return typeof instructions === "string" ? checksReportOfInstructions(instructions) : "none";
|
|
36222
36781
|
}
|
|
36223
|
-
async function postInitialize(url2, bearer, fetchFn, signal) {
|
|
36782
|
+
async function postInitialize(url2, bearer, fetchFn, signal, version2) {
|
|
36224
36783
|
let res;
|
|
36225
36784
|
try {
|
|
36226
36785
|
res = await fetchFn(url2, {
|
|
@@ -36235,7 +36794,7 @@ async function postInitialize(url2, bearer, fetchFn, signal) {
|
|
|
36235
36794
|
}
|
|
36236
36795
|
if (res.status === 401) {
|
|
36237
36796
|
discardBody(res);
|
|
36238
|
-
return
|
|
36797
|
+
return noCredentialSentence(version2);
|
|
36239
36798
|
}
|
|
36240
36799
|
if (res.status < 200 || res.status > 299) {
|
|
36241
36800
|
discardBody(res);
|
|
@@ -36255,12 +36814,12 @@ async function postInitialize(url2, bearer, fetchFn, signal) {
|
|
|
36255
36814
|
}
|
|
36256
36815
|
return namesItsServer(body) ? { report: reportOf(body) } : SERVICE_PROBLEM_SENTENCE;
|
|
36257
36816
|
}
|
|
36258
|
-
async function probeDelivery(url2, bearer, fetchFn, deadlineMs, maxAttempts) {
|
|
36817
|
+
async function probeDelivery(url2, bearer, fetchFn, deadlineMs, maxAttempts, version2) {
|
|
36259
36818
|
const controller = new AbortController();
|
|
36260
36819
|
const timer = setTimeout(() => controller.abort(), deadlineMs);
|
|
36261
36820
|
try {
|
|
36262
36821
|
for (let attempt3 = 0; attempt3 < maxAttempts; attempt3++) {
|
|
36263
|
-
const outcome = await postInitialize(url2, bearer, fetchFn, controller.signal);
|
|
36822
|
+
const outcome = await postInitialize(url2, bearer, fetchFn, controller.signal, version2);
|
|
36264
36823
|
if (outcome !== CUT_OFF)
|
|
36265
36824
|
return outcome;
|
|
36266
36825
|
}
|
|
@@ -36271,9 +36830,11 @@ async function probeDelivery(url2, bearer, fetchFn, deadlineMs, maxAttempts) {
|
|
|
36271
36830
|
}
|
|
36272
36831
|
async function checkConnection(renewedToken, opts) {
|
|
36273
36832
|
const profile = opts.profile ?? AGENT_PROFILES["claude-code"];
|
|
36274
|
-
const
|
|
36833
|
+
const root = projectRootFromBinary(opts.binaryPath);
|
|
36834
|
+
const url2 = registeredMcpUrl(root);
|
|
36275
36835
|
if (url2 === void 0)
|
|
36276
36836
|
return void 0;
|
|
36837
|
+
const version2 = readPinnedVersion(root);
|
|
36277
36838
|
const bearer = await chooseBearer({
|
|
36278
36839
|
binaryPath: opts.binaryPath,
|
|
36279
36840
|
home: opts.home,
|
|
@@ -36284,9 +36845,9 @@ async function checkConnection(renewedToken, opts) {
|
|
|
36284
36845
|
environmentTokenFirst: false
|
|
36285
36846
|
});
|
|
36286
36847
|
if (CREDENTIAL_PLACEHOLDERS.includes(bearer)) {
|
|
36287
|
-
return { sentence:
|
|
36848
|
+
return { sentence: placeholderSentencesOf(version2)[bearer], url: url2, bearer, connected: false };
|
|
36288
36849
|
}
|
|
36289
|
-
const outcome = await probeDelivery(url2, bearer, opts.fetchFn ?? globalThis.fetch, opts.checkDeadlineMs ?? CONNECTION_CHECK_DEADLINE_MS, opts.maxAttempts ?? SESSION_START_PROBE_ATTEMPTS);
|
|
36850
|
+
const outcome = await probeDelivery(url2, bearer, opts.fetchFn ?? globalThis.fetch, opts.checkDeadlineMs ?? CONNECTION_CHECK_DEADLINE_MS, opts.maxAttempts ?? SESSION_START_PROBE_ATTEMPTS, version2);
|
|
36290
36851
|
if (typeof outcome === "string")
|
|
36291
36852
|
return { sentence: outcome, url: url2, bearer, connected: false };
|
|
36292
36853
|
return { sentence: connectedSentenceFor(profile), url: url2, bearer, connected: true, report: outcome.report };
|
|
@@ -36361,7 +36922,11 @@ async function fetchPositionNotices(url2, bearer, engagementId, fetchFn, deadlin
|
|
|
36361
36922
|
}
|
|
36362
36923
|
}
|
|
36363
36924
|
function scopeNoticeLines(scope, engagementId) {
|
|
36364
|
-
const text = scopeNoticeText(scope, {
|
|
36925
|
+
const text = scopeNoticeText(scope, {
|
|
36926
|
+
engagementId,
|
|
36927
|
+
serviceAddress: readControlOrigin().origin,
|
|
36928
|
+
offerTyping: scope.typedApprovalOffered ? "yes" : "off"
|
|
36929
|
+
});
|
|
36365
36930
|
return [...text.sentBack, ...text.waiting];
|
|
36366
36931
|
}
|
|
36367
36932
|
function defaultWriteErr2(text) {
|
|
@@ -36374,12 +36939,13 @@ function headlessInUntrustedFolder(input, profile, opts) {
|
|
|
36374
36939
|
const cwd = input["cwd"];
|
|
36375
36940
|
const folder2 = typeof cwd === "string" && cwd !== "" ? cwd : projectRootFromBinary(opts.binaryPath);
|
|
36376
36941
|
const stateFile = join24(readClaudeConfigFolder() ?? opts.home ?? homedir19(), CLAUDE_STATE_FILENAME);
|
|
36377
|
-
return trustOfWorkingFolder(folder2, stateFile, process.platform, { lstatSync: lstatSync5, readFileSync:
|
|
36942
|
+
return trustOfWorkingFolder(folder2, stateFile, process.platform, { lstatSync: lstatSync5, readFileSync: readFileSync31, realpathSync: realpathSync11 }) === "not-trusted";
|
|
36378
36943
|
}
|
|
36379
36944
|
async function runRefreshCredential(opts) {
|
|
36380
36945
|
const writeErr = opts.writeErr ?? defaultWriteErr2;
|
|
36381
36946
|
const profile = opts.profile ?? AGENT_PROFILES["claude-code"];
|
|
36382
36947
|
const startedAt = Date.now();
|
|
36948
|
+
const startVersion = readPinnedVersion(projectRootFromBinary(opts.binaryPath));
|
|
36383
36949
|
try {
|
|
36384
36950
|
const renewalSaid = [];
|
|
36385
36951
|
let renewalOpen = true;
|
|
@@ -36410,7 +36976,7 @@ async function runRefreshCredential(opts) {
|
|
|
36410
36976
|
if (notices?.scope !== void 0)
|
|
36411
36977
|
parts.push(...scopeNoticeLines(notices.scope, engagementId));
|
|
36412
36978
|
if (notices?.review !== void 0)
|
|
36413
|
-
parts.push(...reviewNoticeText(notices.review));
|
|
36979
|
+
parts.push(...reviewNoticeText(notices.review, startVersion));
|
|
36414
36980
|
for (const entry of notices?.approvedInConsole ?? [])
|
|
36415
36981
|
parts.push(approvedInConsoleSentence(entry.phase));
|
|
36416
36982
|
}
|
|
@@ -36438,18 +37004,18 @@ async function runRefreshCredential(opts) {
|
|
|
36438
37004
|
return `${nonBlockingReply("SessionStart", FOLDER_NOT_TRUSTED_NOTICE)}
|
|
36439
37005
|
`;
|
|
36440
37006
|
if (readConfig().config === null) {
|
|
36441
|
-
const remedySaid = parts.some(namesTheSignInCommand);
|
|
37007
|
+
const remedySaid = parts.some((part) => namesTheSignInCommand(part, startVersion));
|
|
36442
37008
|
aFailureOfOurs = true;
|
|
36443
|
-
parts.push(noCoverageStatement(readNeverConfiguredReason(), remedySaid, pinnedEngagementId(projectRootFromBinary(opts.binaryPath))));
|
|
37009
|
+
parts.push(noCoverageStatement(readNeverConfiguredReason(), remedySaid, pinnedEngagementId(projectRootFromBinary(opts.binaryPath)), startVersion));
|
|
36444
37010
|
}
|
|
36445
37011
|
for (const said of renewalSaid) {
|
|
36446
37012
|
aFailureOfOurs = true;
|
|
36447
|
-
if (namesTheSignInCommand(said) && parts.some(namesTheSignInCommand))
|
|
37013
|
+
if (namesTheSignInCommand(said, startVersion) && parts.some((part) => namesTheSignInCommand(part, startVersion)))
|
|
36448
37014
|
continue;
|
|
36449
37015
|
parts.push(said.trimEnd());
|
|
36450
37016
|
}
|
|
36451
37017
|
if (aFailureOfOurs)
|
|
36452
|
-
parts.push(
|
|
37018
|
+
parts.push(doctorLine(startVersion));
|
|
36453
37019
|
return parts.length === 0 ? "" : `${nonBlockingReply("SessionStart", parts.join("\n"))}
|
|
36454
37020
|
`;
|
|
36455
37021
|
} catch (err) {
|
|
@@ -36467,7 +37033,7 @@ async function runRefreshCredential(opts) {
|
|
|
36467
37033
|
import { fileURLToPath } from "node:url";
|
|
36468
37034
|
|
|
36469
37035
|
// dist/capture.js
|
|
36470
|
-
import { readFileSync as
|
|
37036
|
+
import { readFileSync as readFileSync32, writeFileSync as writeFileSync20, mkdirSync as mkdirSync14, existsSync as existsSync10 } from "node:fs";
|
|
36471
37037
|
import { dirname as dirname11 } from "node:path";
|
|
36472
37038
|
function runCapture(provider, endpoint, opts = {}) {
|
|
36473
37039
|
const repoRoot = opts.repoRoot ?? process.cwd();
|
|
@@ -36535,7 +37101,7 @@ function readInputFile(fromFile) {
|
|
|
36535
37101
|
if (!fromFile)
|
|
36536
37102
|
return void 0;
|
|
36537
37103
|
try {
|
|
36538
|
-
return
|
|
37104
|
+
return readFileSync32(fromFile, "utf-8");
|
|
36539
37105
|
} catch {
|
|
36540
37106
|
return void 0;
|
|
36541
37107
|
}
|
|
@@ -36548,7 +37114,7 @@ function relativeFixturePath(repoRoot, fixture) {
|
|
|
36548
37114
|
// dist/prove.js
|
|
36549
37115
|
import { spawn as spawn2, spawnSync as spawnSync3 } from "node:child_process";
|
|
36550
37116
|
import { createHash as createHash6, randomUUID as randomUUID3 } from "node:crypto";
|
|
36551
|
-
import { createWriteStream, mkdirSync as mkdirSync15, readdirSync as readdirSync11, readFileSync as
|
|
37117
|
+
import { createWriteStream, mkdirSync as mkdirSync15, readdirSync as readdirSync11, readFileSync as readFileSync33, renameSync as renameSync18, unlinkSync as unlinkSync12, writeFileSync as writeFileSync21 } from "node:fs";
|
|
36552
37118
|
import { homedir as homedir20 } from "node:os";
|
|
36553
37119
|
import { dirname as dirname12, join as join25 } from "node:path";
|
|
36554
37120
|
|
|
@@ -36560,11 +37126,15 @@ function firstNumber(line2, pattern) {
|
|
|
36560
37126
|
const match = line2.match(pattern);
|
|
36561
37127
|
return match ? Number(match[1]) : void 0;
|
|
36562
37128
|
}
|
|
36563
|
-
|
|
36564
|
-
|
|
37129
|
+
var NODE_PASS_LINE = /^(?:# |ℹ️? )pass (\d+)[ \t\r]*$/gm;
|
|
37130
|
+
var NODE_FAIL_LINE = /^(?:# |ℹ️? )fail (\d+)[ \t\r]*$/gm;
|
|
37131
|
+
var NODE_COLOUR_CODE = /\u001b\[[0-9;]*m/g;
|
|
37132
|
+
function nodeTestRunnerCounts(rawOutput) {
|
|
37133
|
+
const output = rawOutput.replace(NODE_COLOUR_CODE, "");
|
|
37134
|
+
const passedLines = [...output.matchAll(NODE_PASS_LINE)];
|
|
36565
37135
|
if (passedLines.length === 0)
|
|
36566
37136
|
return null;
|
|
36567
|
-
const failedLines = [...output.matchAll(
|
|
37137
|
+
const failedLines = [...output.matchAll(NODE_FAIL_LINE)];
|
|
36568
37138
|
return {
|
|
36569
37139
|
passed: sum(passedLines.map((m) => Number(m[1]))),
|
|
36570
37140
|
failed: sum(failedLines.map((m) => Number(m[1])))
|
|
@@ -36625,13 +37195,56 @@ function cargoTestCounts(output) {
|
|
|
36625
37195
|
failed: sum(lines2.map((m) => Number(m[2])))
|
|
36626
37196
|
};
|
|
36627
37197
|
}
|
|
37198
|
+
var UNITTEST_COLOUR_CODE = /\u001b\[[0-9;]*m/g;
|
|
37199
|
+
var UNITTEST_RAN_LINE = /^Ran (\d+) tests? in \d+(?:\.\d+)?s\s*$/;
|
|
37200
|
+
var UNITTEST_STATUS_LINE = /^(?:OK|FAILED|NO TESTS RAN)(?: \((.*)\))?$/;
|
|
37201
|
+
var UNITTEST_PAIR = /^(failures|errors|skipped|expected failures|unexpected successes)=(\d+)$/;
|
|
37202
|
+
function unittestPairs(list) {
|
|
37203
|
+
const pairs = /* @__PURE__ */ new Map();
|
|
37204
|
+
if (list === void 0)
|
|
37205
|
+
return pairs;
|
|
37206
|
+
for (const part of list.split(",")) {
|
|
37207
|
+
const match = part.trim().match(UNITTEST_PAIR);
|
|
37208
|
+
if (!match)
|
|
37209
|
+
return null;
|
|
37210
|
+
pairs.set(match[1], (pairs.get(match[1]) ?? 0) + Number(match[2]));
|
|
37211
|
+
}
|
|
37212
|
+
return pairs;
|
|
37213
|
+
}
|
|
37214
|
+
function unittestCounts(output) {
|
|
37215
|
+
const lines2 = output.split("\n").map((line2) => line2.endsWith("\r") ? line2.slice(0, -1) : line2);
|
|
37216
|
+
let total = null;
|
|
37217
|
+
for (let i = 0; i < lines2.length; i++) {
|
|
37218
|
+
const ran = lines2[i].match(UNITTEST_RAN_LINE);
|
|
37219
|
+
if (!ran)
|
|
37220
|
+
continue;
|
|
37221
|
+
let next = i + 1;
|
|
37222
|
+
while (next < lines2.length && lines2[next].trim() === "")
|
|
37223
|
+
next++;
|
|
37224
|
+
if (next >= lines2.length)
|
|
37225
|
+
continue;
|
|
37226
|
+
const status = lines2[next].replace(UNITTEST_COLOUR_CODE, "").trim().match(UNITTEST_STATUS_LINE);
|
|
37227
|
+
if (!status)
|
|
37228
|
+
continue;
|
|
37229
|
+
const pairs = unittestPairs(status[1]);
|
|
37230
|
+
if (!pairs)
|
|
37231
|
+
continue;
|
|
37232
|
+
const count = (key) => pairs.get(key) ?? 0;
|
|
37233
|
+
const failed2 = count("failures") + count("errors") + count("unexpected successes");
|
|
37234
|
+
const accounted = failed2 + count("skipped") + count("expected failures");
|
|
37235
|
+
const passed = Math.max(0, Number(ran[1]) - accounted);
|
|
37236
|
+
total = total ? { passed: total.passed + passed, failed: total.failed + failed2 } : { passed, failed: failed2 };
|
|
37237
|
+
}
|
|
37238
|
+
return total;
|
|
37239
|
+
}
|
|
36628
37240
|
var FORMAT_PARSERS = [
|
|
36629
37241
|
nodeTestRunnerCounts,
|
|
36630
37242
|
mochaCounts,
|
|
36631
37243
|
jestCounts,
|
|
36632
37244
|
vitestCounts,
|
|
36633
37245
|
pytestCounts,
|
|
36634
|
-
cargoTestCounts
|
|
37246
|
+
cargoTestCounts,
|
|
37247
|
+
unittestCounts
|
|
36635
37248
|
];
|
|
36636
37249
|
function parseTestCounts(output) {
|
|
36637
37250
|
let total = null;
|
|
@@ -36759,7 +37372,7 @@ function keptCheckPath(dir, subject, label) {
|
|
|
36759
37372
|
}
|
|
36760
37373
|
function readKeptCheck(dir, subject, label) {
|
|
36761
37374
|
try {
|
|
36762
|
-
const raw = JSON.parse(
|
|
37375
|
+
const raw = JSON.parse(readFileSync33(keptCheckPath(dir, subject, label), "utf-8"));
|
|
36763
37376
|
if (typeof raw.command !== "string" || raw.command === "" || typeof raw.commandId !== "string")
|
|
36764
37377
|
return null;
|
|
36765
37378
|
const b = raw.before;
|
|
@@ -36784,7 +37397,7 @@ function readQueue(dir) {
|
|
|
36784
37397
|
const path = join25(dir, QUEUE_DIR_NAME, name);
|
|
36785
37398
|
let parsed = null;
|
|
36786
37399
|
try {
|
|
36787
|
-
parsed = testRunReportSchema.safeParse(JSON.parse(
|
|
37400
|
+
parsed = testRunReportSchema.safeParse(JSON.parse(readFileSync33(path, "utf-8")));
|
|
36788
37401
|
} catch {
|
|
36789
37402
|
parsed = null;
|
|
36790
37403
|
}
|
|
@@ -37027,7 +37640,7 @@ ${PROVE_USAGE}`);
|
|
|
37027
37640
|
const end = await runCommand(command, repoRoot, logPath2, env, deps);
|
|
37028
37641
|
let output = "";
|
|
37029
37642
|
try {
|
|
37030
|
-
output =
|
|
37643
|
+
output = readFileSync33(logPath2, "utf-8");
|
|
37031
37644
|
} catch {
|
|
37032
37645
|
output = "";
|
|
37033
37646
|
}
|
|
@@ -37077,7 +37690,7 @@ ${PROVE_USAGE}`);
|
|
|
37077
37690
|
|
|
37078
37691
|
// dist/statusline.js
|
|
37079
37692
|
import { spawn as spawn3 } from "node:child_process";
|
|
37080
|
-
import { readFileSync as
|
|
37693
|
+
import { readFileSync as readFileSync34 } from "node:fs";
|
|
37081
37694
|
import nodePath7 from "node:path";
|
|
37082
37695
|
var OWN_STATUS_LINE_DEADLINE_MS = 5e3;
|
|
37083
37696
|
var PERSON_SETTINGS_FILENAME = "settings.json";
|
|
@@ -37115,7 +37728,7 @@ function halfcycleStatusLineOf(figures) {
|
|
|
37115
37728
|
}
|
|
37116
37729
|
function personStatusLineCommand(configFolder) {
|
|
37117
37730
|
try {
|
|
37118
|
-
const v = JSON.parse(
|
|
37731
|
+
const v = JSON.parse(readFileSync34(nodePath7.join(configFolder, PERSON_SETTINGS_FILENAME), "utf-8"));
|
|
37119
37732
|
const line2 = v["statusLine"];
|
|
37120
37733
|
if (typeof line2 !== "object" || line2 === null)
|
|
37121
37734
|
return null;
|
|
@@ -37233,7 +37846,7 @@ function usageFigures2(env, deps = {}) {
|
|
|
37233
37846
|
}
|
|
37234
37847
|
return figures;
|
|
37235
37848
|
}
|
|
37236
|
-
function connectionKind(bearer, sentence) {
|
|
37849
|
+
function connectionKind(bearer, sentence, version2) {
|
|
37237
37850
|
if (bearer === NOT_THIS_ACCOUNT_PLACEHOLDER)
|
|
37238
37851
|
return "other-account";
|
|
37239
37852
|
if (bearer === UPDATE_CLAUDE_CODE_PLACEHOLDER)
|
|
@@ -37246,7 +37859,7 @@ function connectionKind(bearer, sentence) {
|
|
|
37246
37859
|
return "cannot-reach";
|
|
37247
37860
|
if (sentence === SERVICE_PROBLEM_SENTENCE)
|
|
37248
37861
|
return "service-problem";
|
|
37249
|
-
if (sentence ===
|
|
37862
|
+
if (sentence === noCredentialSentence(version2))
|
|
37250
37863
|
return "signed-out";
|
|
37251
37864
|
throw new Error("the connection check gave an outcome with no kind");
|
|
37252
37865
|
}
|
|
@@ -37260,7 +37873,7 @@ async function checkConnectionLine(opts) {
|
|
|
37260
37873
|
const withUsage = usage.length === 0 ? {} : { usage };
|
|
37261
37874
|
if (result === void 0)
|
|
37262
37875
|
return { kind: "not-registered", sentence: null, ...withUsage };
|
|
37263
|
-
const line2 = { kind: connectionKind(result.bearer, result.sentence), sentence: result.sentence };
|
|
37876
|
+
const line2 = { kind: connectionKind(result.bearer, result.sentence, readPinnedVersion(projectRootFromBinary(opts.binaryPath))), sentence: result.sentence };
|
|
37264
37877
|
const report = result.report === void 0 || result.report === "none" ? {} : { report: result.report };
|
|
37265
37878
|
return { ...line2, ...report, ...withUsage };
|
|
37266
37879
|
}
|