@drisp/cli 0.7.6 → 0.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{WorkflowInstallWizard-YANLNMTP.js → WorkflowInstallWizard-IOJD3YOA.js} +2 -2
- package/dist/{chunk-2N7IBKJF.js → chunk-HGMJ3YL2.js} +188 -34
- package/dist/{chunk-W57EQYCM.js → chunk-OYUBT6RS.js} +138 -18
- package/dist/{chunk-Y6XJPUR2.js → chunk-TBUUNMC6.js} +2 -2
- package/dist/cli.js +376 -64
- package/dist/dashboard-daemon.js +3 -3
- package/dist/runner.js +3 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
cursorToVisualPosition,
|
|
38
38
|
defaultWorktreesRoot,
|
|
39
39
|
detectClaudeVersion,
|
|
40
|
+
eligibilityReason,
|
|
40
41
|
ensureBuildWorktree,
|
|
41
42
|
ensureChildWorktree,
|
|
42
43
|
expandHome,
|
|
@@ -126,6 +127,7 @@ import {
|
|
|
126
127
|
runnerServiceUnit,
|
|
127
128
|
runnerSoftwareVersion,
|
|
128
129
|
runnerUpdateRequestSchema,
|
|
130
|
+
scopeFingerprint,
|
|
129
131
|
serviceInstallationId,
|
|
130
132
|
sessionsDir,
|
|
131
133
|
sliceAnsi,
|
|
@@ -140,7 +142,7 @@ import {
|
|
|
140
142
|
visualPositionToOffset,
|
|
141
143
|
wrapText,
|
|
142
144
|
writeIdentityOnce
|
|
143
|
-
} from "./chunk-
|
|
145
|
+
} from "./chunk-HGMJ3YL2.js";
|
|
144
146
|
import {
|
|
145
147
|
generateId as generateId2
|
|
146
148
|
} from "./chunk-PQIB66SG.js";
|
|
@@ -159,6 +161,7 @@ import {
|
|
|
159
161
|
DESCRIPTION_TEMPLATE,
|
|
160
162
|
GATES,
|
|
161
163
|
LAYOUT_MARKERS,
|
|
164
|
+
MERGE_SIGN_OFF,
|
|
162
165
|
NO_GATE_TEXT_TEMPLATE,
|
|
163
166
|
ORCHESTRATOR_LIMITS,
|
|
164
167
|
QA_SECTIONS,
|
|
@@ -198,7 +201,7 @@ import {
|
|
|
198
201
|
workflowRegistryDir,
|
|
199
202
|
writeGlobalConfig,
|
|
200
203
|
writeProjectConfig
|
|
201
|
-
} from "./chunk-
|
|
204
|
+
} from "./chunk-OYUBT6RS.js";
|
|
202
205
|
import {
|
|
203
206
|
__toESM
|
|
204
207
|
} from "./chunk-G3PMV62Z.js";
|
|
@@ -206,10 +209,10 @@ import {
|
|
|
206
209
|
// src/app/entry/cli.tsx
|
|
207
210
|
import { render } from "ink";
|
|
208
211
|
import meow from "meow";
|
|
209
|
-
import
|
|
212
|
+
import fs12 from "fs";
|
|
210
213
|
import { createRequire } from "module";
|
|
211
214
|
import os5 from "os";
|
|
212
|
-
import
|
|
215
|
+
import path12 from "path";
|
|
213
216
|
import { fileURLToPath } from "url";
|
|
214
217
|
|
|
215
218
|
// src/app/shell/sessionUiState.ts
|
|
@@ -5328,14 +5331,14 @@ function extractWebSearch(_input, response) {
|
|
|
5328
5331
|
return { type: "text", content: extractTextContent(response), maxLines: 10 };
|
|
5329
5332
|
}
|
|
5330
5333
|
function extractNotebookEdit(input, _response) {
|
|
5331
|
-
const
|
|
5334
|
+
const path13 = typeof input["notebook_path"] === "string" ? input["notebook_path"] : "";
|
|
5332
5335
|
const mode = typeof input["edit_mode"] === "string" ? input["edit_mode"] : "replace";
|
|
5333
5336
|
const source = typeof input["new_source"] === "string" ? input["new_source"] : "";
|
|
5334
|
-
if (!source) return { type: "text", content: `${mode} cell in ${
|
|
5337
|
+
if (!source) return { type: "text", content: `${mode} cell in ${path13}` };
|
|
5335
5338
|
return {
|
|
5336
5339
|
type: "code",
|
|
5337
5340
|
content: source,
|
|
5338
|
-
language: detectLanguage(
|
|
5341
|
+
language: detectLanguage(path13),
|
|
5339
5342
|
maxLines: 10
|
|
5340
5343
|
};
|
|
5341
5344
|
}
|
|
@@ -5861,10 +5864,10 @@ function extractToolSubject(toolName, toolInput) {
|
|
|
5861
5864
|
const parts = [];
|
|
5862
5865
|
const pattern = str(input, "pattern");
|
|
5863
5866
|
const glob = str(input, "glob");
|
|
5864
|
-
const
|
|
5867
|
+
const path13 = str(input, "path");
|
|
5865
5868
|
if (pattern) parts.push(`"${pattern}"`);
|
|
5866
5869
|
if (glob) parts.push(glob);
|
|
5867
|
-
if (
|
|
5870
|
+
if (path13) parts.push(`in ${path13}`);
|
|
5868
5871
|
return parts.length > 0 ? parts.join(" ") : void 0;
|
|
5869
5872
|
}
|
|
5870
5873
|
case "Skill":
|
|
@@ -13095,7 +13098,7 @@ var thisMachine = (installationId) => ({
|
|
|
13095
13098
|
os: `${platform()} ${release()}`.slice(0, 64),
|
|
13096
13099
|
softwareVersion: runnerSoftwareVersion
|
|
13097
13100
|
});
|
|
13098
|
-
var post = (origin,
|
|
13101
|
+
var post = (origin, path13, body) => fetch(new URL(path13, origin), {
|
|
13099
13102
|
method: "POST",
|
|
13100
13103
|
headers: { "Content-Type": "application/json" },
|
|
13101
13104
|
body: JSON.stringify(body)
|
|
@@ -13114,8 +13117,8 @@ async function alreadyConnected(existing, { forTeam, ownIdentity }) {
|
|
|
13114
13117
|
const problem = own ? await credentialAccepted(own.config) ? void 0 : "lapsed" : forTeam(existing.orgId).length ? "other_runner" : "missing";
|
|
13115
13118
|
const runner = { orgId: existing.orgId, runnerId: existing.runnerId, name: existing.name };
|
|
13116
13119
|
if (own && problem === void 0) return { status: "already_connected", ...runner, path: own.path };
|
|
13117
|
-
const
|
|
13118
|
-
return { status: "identity_unusable", ...runner, problem, ...
|
|
13120
|
+
const path13 = (own ?? forTeam(existing.orgId)[0])?.path;
|
|
13121
|
+
return { status: "identity_unusable", ...runner, problem, ...path13 ? { path: path13 } : {} };
|
|
13119
13122
|
}
|
|
13120
13123
|
async function connectWithCode({
|
|
13121
13124
|
code,
|
|
@@ -13187,20 +13190,20 @@ async function saveIdentity(origin, credential, { single, forTeam }, directory)
|
|
|
13187
13190
|
name: credential.name
|
|
13188
13191
|
});
|
|
13189
13192
|
const replaced = [];
|
|
13190
|
-
for (const { path:
|
|
13191
|
-
const aside = `${
|
|
13192
|
-
await rename(
|
|
13193
|
+
for (const { path: path14 } of forTeam(credential.orgId)) {
|
|
13194
|
+
const aside = `${path14}.replaced-${Date.now()}`;
|
|
13195
|
+
await rename(path14, aside);
|
|
13193
13196
|
replaced.push(aside);
|
|
13194
13197
|
}
|
|
13195
|
-
const
|
|
13198
|
+
const path13 = single ?? teamIdentityPath(origin, credential.orgId, directory);
|
|
13196
13199
|
try {
|
|
13197
|
-
await writeIdentityOnce(
|
|
13200
|
+
await writeIdentityOnce(path13, JSON.stringify(config, null, 2) + "\n");
|
|
13198
13201
|
} catch (error) {
|
|
13199
13202
|
if (error.code === "EEXIST")
|
|
13200
|
-
throw new Error(`Another Connect wrote a Runner identity for this Team at ${
|
|
13203
|
+
throw new Error(`Another Connect wrote a Runner identity for this Team at ${path13} meanwhile; it was left unchanged.`);
|
|
13201
13204
|
throw error;
|
|
13202
13205
|
}
|
|
13203
|
-
return { status: "connected", config, path:
|
|
13206
|
+
return { status: "connected", config, path: path13, replaced };
|
|
13204
13207
|
}
|
|
13205
13208
|
function pathSegment(value) {
|
|
13206
13209
|
const segment = encodeURIComponent(value);
|
|
@@ -13240,7 +13243,7 @@ async function refuseExisting(target) {
|
|
|
13240
13243
|
throw new Error(`This machine already has a Runner${name ? ` (${name})` : ""} configured at ${target}.`);
|
|
13241
13244
|
}
|
|
13242
13245
|
async function disconnectRunner({
|
|
13243
|
-
identity: { path:
|
|
13246
|
+
identity: { path: path13, config },
|
|
13244
13247
|
serviceManager,
|
|
13245
13248
|
othersRemain
|
|
13246
13249
|
}) {
|
|
@@ -13273,7 +13276,7 @@ async function disconnectRunner({
|
|
|
13273
13276
|
await restore();
|
|
13274
13277
|
throw new Error(`The Hub refused to disconnect ${name} (${body.error ?? response.status}); it is still connected.`);
|
|
13275
13278
|
}
|
|
13276
|
-
await forgetRunner(
|
|
13279
|
+
await forgetRunner(path13);
|
|
13277
13280
|
if (othersRemain) await restore();
|
|
13278
13281
|
else await serviceManager?.remove();
|
|
13279
13282
|
return result;
|
|
@@ -13426,18 +13429,18 @@ async function runRunnerCommandV2(input, options = {}) {
|
|
|
13426
13429
|
`This machine is already connected to this Team as ${outcome.name}, but ${why}. ` + (code ? `The code was not used: connect a new Runner in its place with ${retry}. ` : `Connect a new Runner in its place with a Connect code from Settings \u2192 Runners: ${retry}. `) + `The old ${outcome.name} stays listed in Settings \u2192 Runners, offline.`
|
|
13427
13430
|
);
|
|
13428
13431
|
}
|
|
13429
|
-
const { config, path:
|
|
13432
|
+
const { config, path: path13, replaced } = outcome;
|
|
13430
13433
|
for (const aside of replaced)
|
|
13431
13434
|
process.stdout.write(
|
|
13432
13435
|
`The Hub no longer recognised this machine's earlier identity for this Team; it was moved aside to ${aside}.
|
|
13433
13436
|
`
|
|
13434
13437
|
);
|
|
13435
13438
|
process.stdout.write(
|
|
13436
|
-
`Connected as ${config.name ?? config.runnerId}. Identity saved to ${
|
|
13439
|
+
`Connected as ${config.name ?? config.runnerId}. Identity saved to ${path13}.
|
|
13437
13440
|
`
|
|
13438
13441
|
);
|
|
13439
13442
|
if (services) {
|
|
13440
|
-
const service = await ensureService(services, config,
|
|
13443
|
+
const service = await ensureService(services, config, path13);
|
|
13441
13444
|
process.stdout.write(`${serviceStarted(service)}
|
|
13442
13445
|
`);
|
|
13443
13446
|
return 0;
|
|
@@ -13446,7 +13449,7 @@ async function runRunnerCommandV2(input, options = {}) {
|
|
|
13446
13449
|
process.stdout.write(
|
|
13447
13450
|
"No launchd or systemd here to run the Runner as a background service; running it in the foreground instead.\n"
|
|
13448
13451
|
);
|
|
13449
|
-
await runConfiguredRunner(
|
|
13452
|
+
await runConfiguredRunner(path13, options.signal);
|
|
13450
13453
|
return 0;
|
|
13451
13454
|
}
|
|
13452
13455
|
case "disconnect": {
|
|
@@ -13517,9 +13520,9 @@ async function runRunnerCommandV2(input, options = {}) {
|
|
|
13517
13520
|
configured: true,
|
|
13518
13521
|
// One entry per Team this machine serves; credentials are never printed.
|
|
13519
13522
|
teams: identities.map(
|
|
13520
|
-
({ path:
|
|
13523
|
+
({ path: path13, config: { token: _token, ...config } }) => ({
|
|
13521
13524
|
...config,
|
|
13522
|
-
path:
|
|
13525
|
+
path: path13
|
|
13523
13526
|
})
|
|
13524
13527
|
),
|
|
13525
13528
|
service: service ? {
|
|
@@ -13615,7 +13618,7 @@ async function recoveryIdentity(runId) {
|
|
|
13615
13618
|
}
|
|
13616
13619
|
|
|
13617
13620
|
// src/app/entry/buildCommand.ts
|
|
13618
|
-
import { execFileSync } from "child_process";
|
|
13621
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
13619
13622
|
|
|
13620
13623
|
// src/core/build/planCommand.ts
|
|
13621
13624
|
import fs6 from "fs";
|
|
@@ -13675,7 +13678,9 @@ function computeTemplateVersion() {
|
|
|
13675
13678
|
JSON.stringify(QA_SECTIONS),
|
|
13676
13679
|
JSON.stringify(GATES),
|
|
13677
13680
|
JSON.stringify(RENDERER_RULES),
|
|
13678
|
-
JSON.stringify(LAYOUT_MARKERS)
|
|
13681
|
+
JSON.stringify(LAYOUT_MARKERS),
|
|
13682
|
+
JSON.stringify(MERGE_SIGN_OFF),
|
|
13683
|
+
BUILD_STRINGS.mergeSignOff
|
|
13679
13684
|
];
|
|
13680
13685
|
const hash = createHash("sha256");
|
|
13681
13686
|
for (const part of parts) hash.update(`${part.length}:${part}`);
|
|
@@ -13755,7 +13760,7 @@ function runBuildPlan(deps) {
|
|
|
13755
13760
|
const fixturePullRequests = fixtureDir ? readJson(path6.join(fixtureDir, "pull-requests.json")) : void 0;
|
|
13756
13761
|
const pullRequests = fixturePullRequests ?? Object.fromEntries(
|
|
13757
13762
|
input.issues.filter(
|
|
13758
|
-
(issue) => issue.branchName && issue.state.type !== "canceled" && !issue
|
|
13763
|
+
(issue) => issue.branchName && issue.state.type !== "canceled" && !eligibilityReason(issue)
|
|
13759
13764
|
).map((issue) => [
|
|
13760
13765
|
issue.branchName,
|
|
13761
13766
|
deps.pullRequests(deps.folder, issue.branchName)
|
|
@@ -13780,7 +13785,8 @@ function runBuildPlan(deps) {
|
|
|
13780
13785
|
fills: result.fills.map((fill) => ({
|
|
13781
13786
|
...fill,
|
|
13782
13787
|
path: fillPath(fill.identifier)
|
|
13783
|
-
}))
|
|
13788
|
+
})),
|
|
13789
|
+
...result.reason ? { reason: result.reason } : {}
|
|
13784
13790
|
};
|
|
13785
13791
|
const host = deps.hostCapabilities();
|
|
13786
13792
|
for (const workflow of result.workflows) {
|
|
@@ -13864,9 +13870,9 @@ var DrispClient = class _DrispClient {
|
|
|
13864
13870
|
if (!match) throw new Error("invalid_hub_url");
|
|
13865
13871
|
return new _DrispClient(url.origin, decodeURIComponent(match[1]), async () => token);
|
|
13866
13872
|
}
|
|
13867
|
-
async request(
|
|
13873
|
+
async request(path13, body) {
|
|
13868
13874
|
const response = await fetch(
|
|
13869
|
-
`${this.baseUrl}/v2/orgs/${encodeURIComponent(this.orgId)}${
|
|
13875
|
+
`${this.baseUrl}/v2/orgs/${encodeURIComponent(this.orgId)}${path13}`,
|
|
13870
13876
|
{
|
|
13871
13877
|
method: body === void 0 ? "GET" : "POST",
|
|
13872
13878
|
headers: {
|
|
@@ -14266,8 +14272,22 @@ function occupies(view) {
|
|
|
14266
14272
|
function assessTick(facts) {
|
|
14267
14273
|
const { entries, orchestratorRunId } = facts;
|
|
14268
14274
|
const state = structuredClone(facts.state);
|
|
14275
|
+
for (const [id, reason] of Object.entries(state.needsPerson))
|
|
14276
|
+
if (reason.startsWith("Issue is no longer eligible") || reason.startsWith("Waiting for prerequisite"))
|
|
14277
|
+
delete state.needsPerson[id];
|
|
14269
14278
|
const views = new Map(facts.children.map((view) => [view.runId, view]));
|
|
14270
14279
|
const issues = new Map(facts.issues.map((issue) => [issue.id, issue]));
|
|
14280
|
+
const parentOnly = new Set(
|
|
14281
|
+
facts.skipped?.filter((issue) => issue.reason === "parent-only").map((issue) => issue.id) ?? []
|
|
14282
|
+
);
|
|
14283
|
+
const expandBlocker = (id, seen = /* @__PURE__ */ new Set()) => {
|
|
14284
|
+
if (!parentOnly.has(id) || seen.has(id)) return [id];
|
|
14285
|
+
const children = facts.issues.filter((issue) => issue.parentId === id);
|
|
14286
|
+
if (!children.length) return [id];
|
|
14287
|
+
return children.flatMap(
|
|
14288
|
+
(issue) => expandBlocker(issue.id, /* @__PURE__ */ new Set([...seen, id]))
|
|
14289
|
+
);
|
|
14290
|
+
};
|
|
14271
14291
|
const attemptsOf = (id) => state.attempts[id] ?? [];
|
|
14272
14292
|
for (const entry of entries) {
|
|
14273
14293
|
const prefix = `${orchestratorRunId}:${entry.identifier}:a`;
|
|
@@ -14310,7 +14330,7 @@ function assessTick(facts) {
|
|
|
14310
14330
|
const status = /* @__PURE__ */ new Map();
|
|
14311
14331
|
const skippedBlocker = (id) => {
|
|
14312
14332
|
const linear = issues.get(id)?.state.type;
|
|
14313
|
-
return linear === "completed"
|
|
14333
|
+
return linear === "completed" ? "done" : "blocked";
|
|
14314
14334
|
};
|
|
14315
14335
|
const repair = [];
|
|
14316
14336
|
const repaired = new Set(state.repaired ?? []);
|
|
@@ -14321,7 +14341,7 @@ function assessTick(facts) {
|
|
|
14321
14341
|
const linear = issues.get(entry.id)?.state.type;
|
|
14322
14342
|
const statusOf = () => {
|
|
14323
14343
|
if (linear === "completed" || linear === "canceled") return "done";
|
|
14324
|
-
const prs = prsOf(entry);
|
|
14344
|
+
const prs = entry.profile === "investigation" ? void 0 : prsOf(entry);
|
|
14325
14345
|
if (prs?.merged) {
|
|
14326
14346
|
if (!repaired.has(entry.id) && !(newest && occupies(view))) {
|
|
14327
14347
|
const prUrl = prs.mergedUrl ?? branchOf(entry);
|
|
@@ -14336,18 +14356,36 @@ function assessTick(facts) {
|
|
|
14336
14356
|
return "done";
|
|
14337
14357
|
}
|
|
14338
14358
|
if (newest && (!view || !view.closed)) return "live";
|
|
14359
|
+
const current = issues.get(entry.id);
|
|
14360
|
+
if (!current || eligibilityReason(current)) {
|
|
14361
|
+
state.needsPerson[entry.id] = `Issue is no longer eligible (${current ? eligibilityReason(current) : "missing from Linear"}). Update Linear, then Build again.`;
|
|
14362
|
+
return "needs_person";
|
|
14363
|
+
}
|
|
14364
|
+
if (entry.scopeFingerprint && entry.scopeFingerprint !== scopeFingerprint(current)) {
|
|
14365
|
+
state.needsPerson[entry.id] = "Issue scope changed after approval. Build again to review the revised plan.";
|
|
14366
|
+
return "needs_person";
|
|
14367
|
+
}
|
|
14339
14368
|
if (newest?.outcome === "template_mismatch") return "replan";
|
|
14340
14369
|
if (newest?.outcome === "completed")
|
|
14341
|
-
state.needsPerson[entry.id] ??= BUILD_STRINGS.completedUnmerged;
|
|
14370
|
+
state.needsPerson[entry.id] ??= entry.profile === "investigation" ? "The investigation ended without marking its accepted findings Done in Linear. Review its evidence." : BUILD_STRINGS.completedUnmerged;
|
|
14342
14371
|
if (state.needsPerson[entry.id] || newest && !mayRetry(attempts))
|
|
14343
14372
|
return "needs_person";
|
|
14344
|
-
const blockers =
|
|
14345
|
-
|
|
14346
|
-
|
|
14373
|
+
const blockers = [
|
|
14374
|
+
.../* @__PURE__ */ new Set([
|
|
14375
|
+
...entry.blockedBy,
|
|
14376
|
+
...current.blockedBy.flatMap((id) => expandBlocker(id))
|
|
14377
|
+
])
|
|
14378
|
+
].map((id) => {
|
|
14379
|
+
if (issues.get(id)?.state.type === "canceled") return "blocked";
|
|
14380
|
+
return status.get(id) ?? (entries.some((each) => each.id === id) && issues.get(id)?.state.type !== "completed" ? "pending" : skippedBlocker(id));
|
|
14381
|
+
});
|
|
14347
14382
|
if (blockers.some(
|
|
14348
14383
|
(b) => b === "needs_person" || b === "replan" || b === "blocked"
|
|
14349
|
-
))
|
|
14384
|
+
)) {
|
|
14385
|
+
if (current.blockedBy.some((id) => !entry.blockedBy.includes(id)))
|
|
14386
|
+
state.needsPerson[entry.id] = "Waiting for prerequisite work. Resolve its readiness, completion or cancellation in Linear, then resume.";
|
|
14350
14387
|
return "blocked";
|
|
14388
|
+
}
|
|
14351
14389
|
return blockers.every((b) => b === "done") ? "ready" : "pending";
|
|
14352
14390
|
};
|
|
14353
14391
|
status.set(entry.id, statusOf());
|
|
@@ -14399,6 +14437,12 @@ function tickAction(input) {
|
|
|
14399
14437
|
const done = input.entries.filter(
|
|
14400
14438
|
(entry) => input.status.get(entry.id) === "done"
|
|
14401
14439
|
).length;
|
|
14440
|
+
if (done !== input.entries.length)
|
|
14441
|
+
return {
|
|
14442
|
+
action: "park",
|
|
14443
|
+
reason: "attention",
|
|
14444
|
+
message: `Built ${done} of ${input.entries.length}. Remaining issues are blocked or need attention. Resolve the issue or dependency, then resume; Build again if the approved scope changed.`
|
|
14445
|
+
};
|
|
14402
14446
|
return {
|
|
14403
14447
|
action: "complete",
|
|
14404
14448
|
message: `Built ${done} of ${input.entries.length}`
|
|
@@ -14523,6 +14567,7 @@ async function runBuildTick(deps) {
|
|
|
14523
14567
|
const entries = plan.groups.flatMap((group) => group.issues).filter((entry) => approved.has(entry.id));
|
|
14524
14568
|
const issues = new Map(input.issues.map((issue) => [issue.id, issue]));
|
|
14525
14569
|
const assessment = assessTick({
|
|
14570
|
+
skipped: plan.skipped,
|
|
14526
14571
|
orchestratorRunId,
|
|
14527
14572
|
entries,
|
|
14528
14573
|
issues: input.issues,
|
|
@@ -14725,8 +14770,25 @@ function evaluateRemoteChecks(runs) {
|
|
|
14725
14770
|
}
|
|
14726
14771
|
|
|
14727
14772
|
// src/core/build/step.ts
|
|
14773
|
+
import { execFileSync } from "child_process";
|
|
14774
|
+
import { createHash as createHash2 } from "crypto";
|
|
14728
14775
|
import fs8 from "fs";
|
|
14729
14776
|
import path8 from "path";
|
|
14777
|
+
var receiptSchema = external_exports.strictObject({
|
|
14778
|
+
title: external_exports.string().min(1),
|
|
14779
|
+
revision: external_exports.string().regex(/^[0-9a-f]{64}$/),
|
|
14780
|
+
evidence: external_exports.string().min(1).max(16e3),
|
|
14781
|
+
kind: external_exports.literal("agent-attestation")
|
|
14782
|
+
});
|
|
14783
|
+
var COMMIT_SHA = /^[0-9a-f]{40}$/;
|
|
14784
|
+
var gateEvidenceSchema = external_exports.strictObject({
|
|
14785
|
+
receipts: external_exports.array(receiptSchema).max(100),
|
|
14786
|
+
/**
|
|
14787
|
+
* The Sign-off on the Merge step (`merge: you`): the head commit the child attests the member signed off on in
|
|
14788
|
+
* its Thread. Like the receipts, an agent attestation.
|
|
14789
|
+
*/
|
|
14790
|
+
signOff: external_exports.strictObject({ sha: external_exports.string().regex(COMMIT_SHA) }).optional()
|
|
14791
|
+
});
|
|
14730
14792
|
var QA_KINDS = fillSchema.shape.qa.options;
|
|
14731
14793
|
function runBuildStep(input) {
|
|
14732
14794
|
const directory = requireEnv(input.env, "DRISP_RUN_ARTIFACTS");
|
|
@@ -14735,20 +14797,133 @@ function runBuildStep(input) {
|
|
|
14735
14797
|
throw new BuildUsageError(
|
|
14736
14798
|
`--qa must be one of ${QA_KINDS.join(", ")}, not "${qa}".`
|
|
14737
14799
|
);
|
|
14738
|
-
const
|
|
14800
|
+
const parsedProfile = fillSchema.shape.profile.safeParse(input.profile);
|
|
14801
|
+
if (!parsedProfile.success)
|
|
14802
|
+
throw new BuildUsageError("Unknown workflow profile.");
|
|
14803
|
+
const profile = parsedProfile.data;
|
|
14804
|
+
const selection = (value) => {
|
|
14805
|
+
if (value === void 0) return void 0;
|
|
14806
|
+
if (value !== "true" && value !== "false")
|
|
14807
|
+
throw new BuildUsageError("Step selection must be true or false.");
|
|
14808
|
+
return { enabled: value === "true", reason: "Approved workflow" };
|
|
14809
|
+
};
|
|
14810
|
+
const titles = gateTitles({
|
|
14811
|
+
qa,
|
|
14812
|
+
profile,
|
|
14813
|
+
testFirst: selection(input.testFirst),
|
|
14814
|
+
review: selection(input.review)
|
|
14815
|
+
});
|
|
14739
14816
|
const index = /^[0-9]+$/.test(input.n ?? "") ? Number(input.n) : 0;
|
|
14740
14817
|
if (index < 1 || index > titles.length)
|
|
14741
14818
|
throw new BuildUsageError(
|
|
14742
14819
|
`Step must be a whole number between 1 and ${titles.length}, not "${input.n ?? ""}".`
|
|
14743
14820
|
);
|
|
14821
|
+
if (input.merge !== void 0 && input.merge !== "agent" && input.merge !== "you")
|
|
14822
|
+
throw new BuildUsageError("--merge must be agent or you.");
|
|
14823
|
+
const mergeStep = titles.indexOf("Merge") + 1;
|
|
14824
|
+
const signsOff = input.merge === "you" && index === mergeStep;
|
|
14825
|
+
if (input.signOff !== void 0) {
|
|
14826
|
+
if (input.merge !== "you")
|
|
14827
|
+
throw new BuildUsageError(
|
|
14828
|
+
"--sign-off needs --merge you: agents merge this pull request."
|
|
14829
|
+
);
|
|
14830
|
+
if (mergeStep === 0)
|
|
14831
|
+
throw new BuildUsageError(
|
|
14832
|
+
"--sign-off is for the Merge step, and this workflow has none."
|
|
14833
|
+
);
|
|
14834
|
+
if (!signsOff)
|
|
14835
|
+
throw new BuildUsageError(
|
|
14836
|
+
`--sign-off is for the Merge step (${mergeStep}), not step ${index}.`
|
|
14837
|
+
);
|
|
14838
|
+
if (!COMMIT_SHA.test(input.signOff))
|
|
14839
|
+
throw new BuildUsageError(
|
|
14840
|
+
"--sign-off needs the full 40-character commit SHA the member signed off on."
|
|
14841
|
+
);
|
|
14842
|
+
}
|
|
14744
14843
|
if (!fs8.statSync(directory, { throwIfNoEntry: false })?.isDirectory())
|
|
14745
14844
|
throw new BuildUsageError(
|
|
14746
14845
|
`DRISP_RUN_ARTIFACTS (${directory}) is not a directory.`
|
|
14747
14846
|
);
|
|
14847
|
+
const receiptsPath = path8.join(directory, "gate_evidence.json");
|
|
14848
|
+
let receipts = [];
|
|
14849
|
+
let signOff;
|
|
14850
|
+
if (fs8.existsSync(receiptsPath)) {
|
|
14851
|
+
try {
|
|
14852
|
+
({ receipts, signOff } = gateEvidenceSchema.parse(
|
|
14853
|
+
JSON.parse(fs8.readFileSync(receiptsPath, "utf8"))
|
|
14854
|
+
));
|
|
14855
|
+
} catch {
|
|
14856
|
+
throw new BuildUsageError("Gate evidence is invalid.");
|
|
14857
|
+
}
|
|
14858
|
+
}
|
|
14859
|
+
const save = () => fs8.writeFileSync(
|
|
14860
|
+
receiptsPath,
|
|
14861
|
+
JSON.stringify({ receipts, ...signOff ? { signOff } : {} }) + "\n"
|
|
14862
|
+
);
|
|
14863
|
+
const head = signsOff && (input.signOff || input.verify) ? headCommit(input.cwd ?? process.cwd()) : "";
|
|
14864
|
+
if (input.signOff !== void 0) {
|
|
14865
|
+
if (input.signOff !== head)
|
|
14866
|
+
throw new BuildUsageError(
|
|
14867
|
+
`The Sign-off names ${input.signOff}, but HEAD is ${head}. ${askForSignOff(head)}`
|
|
14868
|
+
);
|
|
14869
|
+
signOff = { sha: head };
|
|
14870
|
+
save();
|
|
14871
|
+
}
|
|
14872
|
+
const revision = receipts.length || input.complete || input.verify ? workRevision(input.cwd ?? process.cwd()) : "";
|
|
14873
|
+
const fresh = (receipt) => ["Explore", "Pull request", "Evidence", "Merge"].includes(receipt.title) || receipt.revision === revision;
|
|
14874
|
+
if (input.verify || input.complete && titles[index - 1] === "Evidence") {
|
|
14875
|
+
const missing = titles.slice(0, index - 1).filter((title) => !receipts.some((r) => r.title === title && fresh(r)));
|
|
14876
|
+
if (missing.length)
|
|
14877
|
+
throw new BuildUsageError(
|
|
14878
|
+
`Missing or stale evidence: ${missing.join(", ")}. Repeat those steps on the current revision.`
|
|
14879
|
+
);
|
|
14880
|
+
}
|
|
14881
|
+
if (signsOff && input.verify) {
|
|
14882
|
+
if (!signOff)
|
|
14883
|
+
throw new BuildUsageError(
|
|
14884
|
+
`No Sign-off on HEAD (${head}) yet. ${askForSignOff(head)}`
|
|
14885
|
+
);
|
|
14886
|
+
if (signOff.sha !== head)
|
|
14887
|
+
throw new BuildUsageError(
|
|
14888
|
+
`The Sign-off names ${signOff.sha}, but HEAD is now ${head}. ${askForSignOff(head)}`
|
|
14889
|
+
);
|
|
14890
|
+
}
|
|
14891
|
+
if (signsOff && input.complete && !signOff)
|
|
14892
|
+
throw new BuildUsageError(
|
|
14893
|
+
"No Sign-off was recorded: verify and merge only after the member signs off on HEAD."
|
|
14894
|
+
);
|
|
14895
|
+
if (input.complete) {
|
|
14896
|
+
if (!input.evidence)
|
|
14897
|
+
throw new BuildUsageError(
|
|
14898
|
+
"--complete requires --evidence <file> containing the result and supporting paths."
|
|
14899
|
+
);
|
|
14900
|
+
let evidence;
|
|
14901
|
+
try {
|
|
14902
|
+
evidence = fs8.readFileSync(
|
|
14903
|
+
path8.resolve(input.cwd ?? process.cwd(), input.evidence),
|
|
14904
|
+
"utf8"
|
|
14905
|
+
).trim();
|
|
14906
|
+
} catch {
|
|
14907
|
+
throw new BuildUsageError("Cannot read the evidence file.");
|
|
14908
|
+
}
|
|
14909
|
+
if (!evidence || evidence.length > 16e3)
|
|
14910
|
+
throw new BuildUsageError("Evidence must contain 1\u201316000 characters.");
|
|
14911
|
+
receipts = receipts.filter((r) => r.title !== titles[index - 1]);
|
|
14912
|
+
receipts.push({
|
|
14913
|
+
title: titles[index - 1],
|
|
14914
|
+
revision,
|
|
14915
|
+
evidence,
|
|
14916
|
+
kind: "agent-attestation"
|
|
14917
|
+
});
|
|
14918
|
+
save();
|
|
14919
|
+
}
|
|
14748
14920
|
const artifact = {
|
|
14749
14921
|
index,
|
|
14750
14922
|
title: titles[index - 1],
|
|
14751
|
-
total: titles.length
|
|
14923
|
+
total: titles.length,
|
|
14924
|
+
...receipts.length ? {
|
|
14925
|
+
completed: receipts.filter(fresh).map((r) => titles.indexOf(r.title) + 1).filter((n) => n > 0)
|
|
14926
|
+
} : {}
|
|
14752
14927
|
};
|
|
14753
14928
|
fs8.writeFileSync(
|
|
14754
14929
|
path8.join(directory, "step.json"),
|
|
@@ -14757,6 +14932,34 @@ function runBuildStep(input) {
|
|
|
14757
14932
|
);
|
|
14758
14933
|
return artifact;
|
|
14759
14934
|
}
|
|
14935
|
+
function askForSignOff(sha) {
|
|
14936
|
+
return `Ask the member: end the Turn with <!-- NEEDS_HUMAN: ${BUILD_STRINGS.mergeSignOff.replace("{sha}", sha)} -->`;
|
|
14937
|
+
}
|
|
14938
|
+
var gitIn = (cwd) => (...args) => execFileSync("git", args, {
|
|
14939
|
+
cwd,
|
|
14940
|
+
encoding: "utf8",
|
|
14941
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
14942
|
+
});
|
|
14943
|
+
function headCommit(cwd) {
|
|
14944
|
+
try {
|
|
14945
|
+
return gitIn(cwd)("rev-parse", "HEAD").trim();
|
|
14946
|
+
} catch {
|
|
14947
|
+
throw new BuildUsageError("A Sign-off must be recorded in a git worktree.");
|
|
14948
|
+
}
|
|
14949
|
+
}
|
|
14950
|
+
function workRevision(cwd) {
|
|
14951
|
+
const git2 = gitIn(cwd);
|
|
14952
|
+
try {
|
|
14953
|
+
const hash = createHash2("sha256").update(git2("rev-parse", "HEAD")).update(git2("diff", "HEAD", "--", ".", ":!.athena/evidence"));
|
|
14954
|
+
for (const name of git2("ls-files", "--others", "--exclude-standard", "-z").split("\0").filter(Boolean).sort()) {
|
|
14955
|
+
if (name.startsWith(".athena/evidence/")) continue;
|
|
14956
|
+
hash.update(name).update(fs8.readFileSync(path8.join(cwd, name)));
|
|
14957
|
+
}
|
|
14958
|
+
return hash.digest("hex");
|
|
14959
|
+
} catch {
|
|
14960
|
+
throw new BuildUsageError("Evidence must be recorded in a git worktree.");
|
|
14961
|
+
}
|
|
14962
|
+
}
|
|
14760
14963
|
|
|
14761
14964
|
// src/core/build/merged.ts
|
|
14762
14965
|
import fs9 from "fs";
|
|
@@ -14812,21 +15015,89 @@ function runBuildMerged(input) {
|
|
|
14812
15015
|
return parsed.data;
|
|
14813
15016
|
}
|
|
14814
15017
|
|
|
15018
|
+
// src/core/build/check.ts
|
|
15019
|
+
import { spawnSync } from "child_process";
|
|
15020
|
+
import fs10 from "fs";
|
|
15021
|
+
import path10 from "path";
|
|
15022
|
+
var checkRecordSchema = external_exports.strictObject({
|
|
15023
|
+
name: external_exports.string().trim().min(1).max(64),
|
|
15024
|
+
outcome: external_exports.enum(["passed", "failed"])
|
|
15025
|
+
});
|
|
15026
|
+
var NAME_PATTERN = /^[^\p{Cc}]+$/u;
|
|
15027
|
+
var MAX_RECORDS = 50;
|
|
15028
|
+
function spawnCheck(command, cwd, onOutput) {
|
|
15029
|
+
const [program, ...args] = command;
|
|
15030
|
+
const result = spawnSync(program, args, {
|
|
15031
|
+
cwd,
|
|
15032
|
+
stdio: onOutput ? ["inherit", "pipe", "inherit"] : "inherit",
|
|
15033
|
+
maxBuffer: 64 * 1024 * 1024
|
|
15034
|
+
});
|
|
15035
|
+
if (onOutput) onOutput(result.stdout);
|
|
15036
|
+
if (result.error) return 127;
|
|
15037
|
+
return result.status ?? 1;
|
|
15038
|
+
}
|
|
15039
|
+
function readRecords(file) {
|
|
15040
|
+
try {
|
|
15041
|
+
const parsed = external_exports.array(checkRecordSchema).safeParse(JSON.parse(fs10.readFileSync(file, "utf8")));
|
|
15042
|
+
return parsed.success ? parsed.data : [];
|
|
15043
|
+
} catch {
|
|
15044
|
+
return [];
|
|
15045
|
+
}
|
|
15046
|
+
}
|
|
15047
|
+
function runBuildCheck(input) {
|
|
15048
|
+
const directory = requireEnv(input.env, "DRISP_RUN_ARTIFACTS");
|
|
15049
|
+
const name = (input.name ?? "").trim();
|
|
15050
|
+
if (!name || name.length > 64 || !NAME_PATTERN.test(name))
|
|
15051
|
+
throw new BuildUsageError(
|
|
15052
|
+
"A check needs a name of 1 to 64 characters on one line."
|
|
15053
|
+
);
|
|
15054
|
+
if (input.command.length === 0 || input.command.some((token) => !token))
|
|
15055
|
+
throw new BuildUsageError("A check needs a command after `--`.");
|
|
15056
|
+
if (!fs10.statSync(directory, { throwIfNoEntry: false })?.isDirectory())
|
|
15057
|
+
throw new BuildUsageError(
|
|
15058
|
+
`DRISP_RUN_ARTIFACTS (${directory}) is not a directory.`
|
|
15059
|
+
);
|
|
15060
|
+
const code = input.run(input.command, input.cwd);
|
|
15061
|
+
const file = path10.join(directory, "checks.json");
|
|
15062
|
+
const record = { name, outcome: code === 0 ? "passed" : "failed" };
|
|
15063
|
+
const records = readRecords(file);
|
|
15064
|
+
const at = records.findIndex((existing) => existing.name === name);
|
|
15065
|
+
if (at >= 0) records[at] = record;
|
|
15066
|
+
else records.push(record);
|
|
15067
|
+
const temporary = `${file}.${process.pid}.tmp`;
|
|
15068
|
+
fs10.writeFileSync(
|
|
15069
|
+
temporary,
|
|
15070
|
+
`${JSON.stringify(records.slice(-MAX_RECORDS))}
|
|
15071
|
+
`
|
|
15072
|
+
);
|
|
15073
|
+
fs10.renameSync(temporary, file);
|
|
15074
|
+
return code;
|
|
15075
|
+
}
|
|
15076
|
+
|
|
14815
15077
|
// src/app/entry/buildCommand.ts
|
|
14816
15078
|
var USAGE3 = `Usage: drisp build plan --input <path>
|
|
14817
15079
|
drisp build tick --input <path> [--rebase-failed <IDENTIFIER>]...
|
|
14818
15080
|
drisp build checks
|
|
14819
|
-
drisp build step <n> [--qa none|web|macos]
|
|
15081
|
+
drisp build step <n> [--qa none|web|macos|both] [--profile implementation|documentation|investigation]
|
|
15082
|
+
[--test-first true|false] [--review true|false] [--merge agent|you] [--sign-off <sha>]
|
|
15083
|
+
[--complete --evidence <file>] [--verify]
|
|
14820
15084
|
drisp build merged [<pr url or number>]
|
|
15085
|
+
drisp build check <name> -- <command>
|
|
14821
15086
|
plan and tick run inside an Orchestrator Run (DRISP_RUN_ID, DRISP_RUNNER_ID and DRISP_RUN_ARTIFACTS set; tick also
|
|
14822
15087
|
DRISP_RUN_TOKEN and DRISP_HUB_URL). DRISP_BUILD_PLAN_INPUT=<path> stands in for plan's --input, with
|
|
14823
15088
|
fills/<IDENTIFIER>.json beside it. checks runs in a child's worktree: the merge gate's verdict on HEAD's GitHub runs.
|
|
14824
15089
|
step runs in any Run with DRISP_RUN_ARTIFACTS set: it writes the step artifact {index, title, total} for gate <n> of the
|
|
14825
|
-
build-child
|
|
15090
|
+
selected build-child profile (QA is a gate unless --qa none) and refuses an index outside the list.
|
|
15091
|
+
--complete --evidence <file> records an agent attestation bound to the source revision; --verify requires fresh
|
|
15092
|
+
receipts for all preceding steps. Keep evidence files under .athena/evidence/. With --merge you, the Merge step's
|
|
15093
|
+
--verify also needs the member's Sign-off on HEAD (--complete one at all), which --sign-off <sha> records for that full
|
|
15094
|
+
SHA only.
|
|
14826
15095
|
merged runs in a child's worktree after its pull request merged: it writes the pull_request artifact
|
|
14827
|
-
{url, number, sha, mergedAt} and refuses a pull request that is not merged
|
|
15096
|
+
{url, number, sha, mergedAt} and refuses a pull request that is not merged.
|
|
15097
|
+
check runs <command>, passes its output through, exits with its code and records {name, outcome} in the checks run artifact
|
|
15098
|
+
(DRISP_RUN_ARTIFACTS set); it refuses a missing name or command before running anything.`;
|
|
14828
15099
|
function githubPullRequests(folder, branch) {
|
|
14829
|
-
const output =
|
|
15100
|
+
const output = execFileSync2(
|
|
14830
15101
|
"gh",
|
|
14831
15102
|
[
|
|
14832
15103
|
"pr",
|
|
@@ -14865,7 +15136,7 @@ function hostCapabilities(folder) {
|
|
|
14865
15136
|
}
|
|
14866
15137
|
var defaultChecks = {
|
|
14867
15138
|
head: (cwd) => git(cwd, ["rev-parse", "HEAD"]),
|
|
14868
|
-
gh: (args, cwd) =>
|
|
15139
|
+
gh: (args, cwd) => execFileSync2("gh", args, {
|
|
14869
15140
|
cwd,
|
|
14870
15141
|
encoding: "utf8",
|
|
14871
15142
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -14942,6 +15213,16 @@ async function runBuildCommand(input) {
|
|
|
14942
15213
|
case "checks":
|
|
14943
15214
|
output = runBuildChecks(input.cwd, input.checks ?? defaultChecks);
|
|
14944
15215
|
break;
|
|
15216
|
+
case "check": {
|
|
15217
|
+
const code = runBuildCheck({
|
|
15218
|
+
env: env2,
|
|
15219
|
+
cwd: input.cwd,
|
|
15220
|
+
name: input.positional?.[0],
|
|
15221
|
+
command: input.command ?? [],
|
|
15222
|
+
run: input.checkRunner ?? spawnCheck
|
|
15223
|
+
});
|
|
15224
|
+
return code;
|
|
15225
|
+
}
|
|
14945
15226
|
case "merged":
|
|
14946
15227
|
output = runBuildMerged({
|
|
14947
15228
|
env: env2,
|
|
@@ -14954,6 +15235,15 @@ async function runBuildCommand(input) {
|
|
|
14954
15235
|
output = runBuildStep({
|
|
14955
15236
|
env: env2,
|
|
14956
15237
|
n: input.positional?.[0],
|
|
15238
|
+
cwd: input.cwd,
|
|
15239
|
+
profile: input.flags.profile,
|
|
15240
|
+
testFirst: input.flags.testFirst,
|
|
15241
|
+
review: input.flags.review,
|
|
15242
|
+
merge: input.flags.merge,
|
|
15243
|
+
signOff: input.flags.signOff,
|
|
15244
|
+
complete: input.flags.complete,
|
|
15245
|
+
verify: input.flags.verify,
|
|
15246
|
+
evidence: input.flags.evidence,
|
|
14957
15247
|
...input.flags.qa ? { qa: input.flags.qa } : {}
|
|
14958
15248
|
});
|
|
14959
15249
|
break;
|
|
@@ -14978,10 +15268,10 @@ ${USAGE3}
|
|
|
14978
15268
|
import process7 from "process";
|
|
14979
15269
|
|
|
14980
15270
|
// src/harnesses/claude/system/doctorEnvironment.ts
|
|
14981
|
-
import { execFileSync as
|
|
14982
|
-
import * as
|
|
15271
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
15272
|
+
import * as fs11 from "fs";
|
|
14983
15273
|
import * as os4 from "os";
|
|
14984
|
-
import * as
|
|
15274
|
+
import * as path11 from "path";
|
|
14985
15275
|
var MANAGED_POLICY_KEYS = [
|
|
14986
15276
|
"forceLoginMethod",
|
|
14987
15277
|
"forceLoginOrgUUID",
|
|
@@ -15056,7 +15346,7 @@ function readEnforcement(scopes) {
|
|
|
15056
15346
|
}
|
|
15057
15347
|
function tryRichAuth(claudeBinary) {
|
|
15058
15348
|
try {
|
|
15059
|
-
const output =
|
|
15349
|
+
const output = execFileSync3(claudeBinary, ["auth", "status"], {
|
|
15060
15350
|
timeout: 1e4,
|
|
15061
15351
|
encoding: "utf-8",
|
|
15062
15352
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -15085,8 +15375,8 @@ function collectEnvironment(options = {}) {
|
|
|
15085
15375
|
const detectVersion = options.detectClaudeVersionFn ?? detectClaudeVersion;
|
|
15086
15376
|
const runAuthStatus = options.runClaudeAuthStatusFn ?? runClaudeAuthStatus;
|
|
15087
15377
|
const resolveForwarder = options.resolveHookForwarderCommandFn ?? resolveHookForwarderCommand;
|
|
15088
|
-
const statFn = options.statFn ?? ((p) =>
|
|
15089
|
-
const readFileFn = options.readFileFn ?? ((p) =>
|
|
15378
|
+
const statFn = options.statFn ?? ((p) => fs11.statSync(p));
|
|
15379
|
+
const readFileFn = options.readFileFn ?? ((p) => fs11.readFileSync(p, "utf8"));
|
|
15090
15380
|
const settingsPaths = resolveClaudeSettingsSurfacePaths(
|
|
15091
15381
|
homeDir,
|
|
15092
15382
|
cwd,
|
|
@@ -15131,7 +15421,7 @@ function collectEnvironment(options = {}) {
|
|
|
15131
15421
|
});
|
|
15132
15422
|
let globalConfigPresent = false;
|
|
15133
15423
|
try {
|
|
15134
|
-
statFn(
|
|
15424
|
+
statFn(path11.join(homeDir, ".claude.json"));
|
|
15135
15425
|
globalConfigPresent = true;
|
|
15136
15426
|
} catch {
|
|
15137
15427
|
globalConfigPresent = false;
|
|
@@ -15611,13 +15901,13 @@ function runRunsCommand(input) {
|
|
|
15611
15901
|
// src/app/entry/cli.tsx
|
|
15612
15902
|
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
15613
15903
|
function resolvePackageJsonPath(entryUrl) {
|
|
15614
|
-
let currentDir =
|
|
15904
|
+
let currentDir = path12.dirname(fileURLToPath(entryUrl));
|
|
15615
15905
|
for (; ; ) {
|
|
15616
|
-
const candidatePath =
|
|
15617
|
-
if (
|
|
15906
|
+
const candidatePath = path12.join(currentDir, "package.json");
|
|
15907
|
+
if (fs12.existsSync(candidatePath)) {
|
|
15618
15908
|
return candidatePath;
|
|
15619
15909
|
}
|
|
15620
|
-
const parentDir =
|
|
15910
|
+
const parentDir = path12.dirname(currentDir);
|
|
15621
15911
|
if (parentDir === currentDir) {
|
|
15622
15912
|
throw new Error("Could not locate package.json for CLI metadata.");
|
|
15623
15913
|
}
|
|
@@ -15789,7 +16079,8 @@ var cli = meow(
|
|
|
15789
16079
|
build plan --input <path> Plan a Build inside an Orchestrator Run (prints one JSON object)
|
|
15790
16080
|
build tick --input <path> Run one step of a started Build (prints the next action; [--rebase-failed <ID>]...)
|
|
15791
16081
|
build checks The merge gate's verdict on HEAD's GitHub runs (in a child's worktree)
|
|
15792
|
-
build step <n> Report the Run's current step: writes the step run artifact ([--qa none|web|macos])
|
|
16082
|
+
build step <n> Report the Run's current step: writes the step run artifact ([--qa none|web|macos|both], --profile, --merge you, --sign-off <sha>, --complete --evidence, --verify)
|
|
16083
|
+
build check <name> -- <cmd> Run a command and record its outcome: writes the checks run artifact
|
|
15793
16084
|
build merged Record the merged pull request: writes the pull_request run artifact
|
|
15794
16085
|
telemetry [action] Manage anonymous telemetry (enable/disable/status)
|
|
15795
16086
|
doctor Diagnose Claude headless setup (use with --harness=claude)
|
|
@@ -15928,6 +16219,14 @@ var cli = meow(
|
|
|
15928
16219
|
type: "string",
|
|
15929
16220
|
isMultiple: true
|
|
15930
16221
|
},
|
|
16222
|
+
profile: { type: "string" },
|
|
16223
|
+
testFirst: { type: "string" },
|
|
16224
|
+
review: { type: "string" },
|
|
16225
|
+
merge: { type: "string" },
|
|
16226
|
+
signOff: { type: "string" },
|
|
16227
|
+
complete: { type: "boolean" },
|
|
16228
|
+
verify: { type: "boolean" },
|
|
16229
|
+
evidence: { type: "string" },
|
|
15931
16230
|
qa: {
|
|
15932
16231
|
type: "string"
|
|
15933
16232
|
},
|
|
@@ -15970,7 +16269,7 @@ var cli = meow(
|
|
|
15970
16269
|
}
|
|
15971
16270
|
);
|
|
15972
16271
|
async function main() {
|
|
15973
|
-
const projectDir =
|
|
16272
|
+
const projectDir = path12.resolve(cli.flags.projectDir);
|
|
15974
16273
|
const [command, ...commandArgs] = cli.input;
|
|
15975
16274
|
const isRunCommand = command === "run" || command === "exec";
|
|
15976
16275
|
if (command && !KNOWN_COMMANDS.has(command)) {
|
|
@@ -16024,7 +16323,7 @@ Available commands: ${[...KNOWN_COMMANDS].join(", ")}`
|
|
|
16024
16323
|
await exitWith(1);
|
|
16025
16324
|
return;
|
|
16026
16325
|
}
|
|
16027
|
-
const { default: WorkflowInstallWizard } = await import("./WorkflowInstallWizard-
|
|
16326
|
+
const { default: WorkflowInstallWizard } = await import("./WorkflowInstallWizard-IOJD3YOA.js");
|
|
16028
16327
|
const { waitUntilExit } = render(
|
|
16029
16328
|
/* @__PURE__ */ jsx24(
|
|
16030
16329
|
WorkflowInstallWizard,
|
|
@@ -16103,13 +16402,26 @@ Available commands: ${[...KNOWN_COMMANDS].join(", ")}`
|
|
|
16103
16402
|
return;
|
|
16104
16403
|
}
|
|
16105
16404
|
if (command === "build") {
|
|
16106
|
-
const
|
|
16405
|
+
const rawArgs = process.argv.slice(2);
|
|
16406
|
+
const dashIdx = rawArgs.indexOf("--");
|
|
16407
|
+
const checkTokens = dashIdx >= 0 ? rawArgs.slice(dashIdx + 1) : [];
|
|
16408
|
+
const cleanArgs = checkTokens.length > 0 ? commandArgs.slice(0, commandArgs.length - checkTokens.length) : commandArgs;
|
|
16409
|
+
const [subcommand = "", ...buildArgs] = cleanArgs;
|
|
16107
16410
|
await exitWith(
|
|
16108
16411
|
await runBuildCommand({
|
|
16109
16412
|
subcommand,
|
|
16110
16413
|
positional: buildArgs,
|
|
16414
|
+
command: checkTokens,
|
|
16111
16415
|
flags: {
|
|
16112
16416
|
...typeof cli.flags.qa === "string" ? { qa: cli.flags.qa } : {},
|
|
16417
|
+
profile: cli.flags.profile,
|
|
16418
|
+
testFirst: cli.flags.testFirst,
|
|
16419
|
+
review: cli.flags.review,
|
|
16420
|
+
merge: cli.flags.merge,
|
|
16421
|
+
signOff: cli.flags.signOff,
|
|
16422
|
+
complete: cli.flags.complete,
|
|
16423
|
+
verify: cli.flags.verify,
|
|
16424
|
+
evidence: cli.flags.evidence,
|
|
16113
16425
|
...typeof cli.flags.input === "string" ? { input: cli.flags.input } : {},
|
|
16114
16426
|
...cli.flags.rebaseFailed?.length ? { rebaseFailed: cli.flags.rebaseFailed } : {}
|
|
16115
16427
|
},
|
|
@@ -16191,8 +16503,8 @@ Available commands: ${[...KNOWN_COMMANDS].join(", ")}`
|
|
|
16191
16503
|
const showSetup = isRunCommand ? false : shouldShowSetup({
|
|
16192
16504
|
cliInput: cli.input,
|
|
16193
16505
|
setupComplete: globalConfig.setupComplete,
|
|
16194
|
-
globalConfigExists:
|
|
16195
|
-
|
|
16506
|
+
globalConfigExists: fs12.existsSync(
|
|
16507
|
+
path12.join(os5.homedir(), ".config", "athena", "config.json")
|
|
16196
16508
|
)
|
|
16197
16509
|
});
|
|
16198
16510
|
let runtimeConfig;
|