@drisp/cli 0.7.6 → 0.7.7
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-VVEEJW25.js} +2 -2
- package/dist/{chunk-2N7IBKJF.js → chunk-D246FR4I.js} +88 -10
- package/dist/{chunk-Y6XJPUR2.js → chunk-D5VZT7M3.js} +2 -2
- package/dist/{chunk-W57EQYCM.js → chunk-HZ6GRLOM.js} +110 -17
- package/dist/cli.js +170 -21
- package/dist/dashboard-daemon.js +3 -3
- package/dist/runner.js +3 -3
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
installWorkflowPlugins,
|
|
9
9
|
resolveWorkflow,
|
|
10
10
|
writeGlobalConfig
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-HZ6GRLOM.js";
|
|
12
12
|
import "./chunk-G3PMV62Z.js";
|
|
13
13
|
|
|
14
14
|
// src/setup/steps/WorkflowInstallWizard.tsx
|
|
@@ -93,4 +93,4 @@ function WorkflowInstallWizard({ source, onDone }) {
|
|
|
93
93
|
export {
|
|
94
94
|
WorkflowInstallWizard as default
|
|
95
95
|
};
|
|
96
|
-
//# sourceMappingURL=WorkflowInstallWizard-
|
|
96
|
+
//# sourceMappingURL=WorkflowInstallWizard-VVEEJW25.js.map
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
verifyRendered,
|
|
55
55
|
wakesFreshAfterHandover,
|
|
56
56
|
workflowRegistryDir
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-HZ6GRLOM.js";
|
|
58
58
|
import {
|
|
59
59
|
__commonJS,
|
|
60
60
|
__toESM
|
|
@@ -14892,7 +14892,7 @@ async function restoreCheckpoint(store, input) {
|
|
|
14892
14892
|
|
|
14893
14893
|
// ../../modules/runtime/src/software-version.ts
|
|
14894
14894
|
import "fs";
|
|
14895
|
-
var runnerSoftwareVersion = true ? "0.7.
|
|
14895
|
+
var runnerSoftwareVersion = true ? "0.7.7" : JSON.parse(readFileSync2(new URL("../../../apps/cli/package.json", import.meta.url), "utf8")).version;
|
|
14896
14896
|
|
|
14897
14897
|
// ../../modules/runtime/src/connection.ts
|
|
14898
14898
|
var RunnerDisconnectedError = class extends Error {
|
|
@@ -20176,7 +20176,33 @@ var fillSchema = external_exports.strictObject({
|
|
|
20176
20176
|
areas: external_exports.array(external_exports.enum(AREAS)).min(1).refine((areas) => new Set(areas).size === areas.length, {
|
|
20177
20177
|
error: "areas must be unique"
|
|
20178
20178
|
}),
|
|
20179
|
-
qa: external_exports.enum(["none", "web", "macos"]),
|
|
20179
|
+
qa: external_exports.enum(["none", "web", "macos", "both"]),
|
|
20180
|
+
profile: external_exports.enum(["implementation", "documentation", "investigation"]).optional(),
|
|
20181
|
+
rationale: external_exports.string().min(1).max(2e3).refine((text) => !TEMPLATE_STRUCTURE.test(text), {
|
|
20182
|
+
error: INSTRUCTIONS_MESSAGE
|
|
20183
|
+
}).optional(),
|
|
20184
|
+
acceptanceEvidence: external_exports.array(
|
|
20185
|
+
external_exports.string().min(1).max(2e3).refine((text) => !TEMPLATE_STRUCTURE.test(text), {
|
|
20186
|
+
error: INSTRUCTIONS_MESSAGE
|
|
20187
|
+
})
|
|
20188
|
+
).min(1).optional(),
|
|
20189
|
+
testFirst: external_exports.strictObject({
|
|
20190
|
+
enabled: external_exports.boolean(),
|
|
20191
|
+
reason: external_exports.string().min(1).max(1e3).refine((text) => !TEMPLATE_STRUCTURE.test(text), {
|
|
20192
|
+
error: INSTRUCTIONS_MESSAGE
|
|
20193
|
+
})
|
|
20194
|
+
}).optional(),
|
|
20195
|
+
review: external_exports.strictObject({
|
|
20196
|
+
enabled: external_exports.boolean(),
|
|
20197
|
+
reason: external_exports.string().min(1).max(1e3).refine((text) => !TEMPLATE_STRUCTURE.test(text), {
|
|
20198
|
+
error: INSTRUCTIONS_MESSAGE
|
|
20199
|
+
})
|
|
20200
|
+
}).optional(),
|
|
20201
|
+
checks: external_exports.array(
|
|
20202
|
+
external_exports.string().min(1).max(500).regex(
|
|
20203
|
+
/^(?:npm (?:run|test|--prefix apps\/cli run)|npx vitest run|make (?:-C apps\/macos|check|typecheck)|git diff --check)(?: [a-zA-Z0-9_./:=@-]+)*$/
|
|
20204
|
+
)
|
|
20205
|
+
).min(1).optional(),
|
|
20180
20206
|
sizeClass: external_exports.enum(["S", "M", "L"]),
|
|
20181
20207
|
instructions: external_exports.string().min(1).max(6e3).refine((text) => !TEMPLATE_STRUCTURE.test(text), {
|
|
20182
20208
|
error: INSTRUCTIONS_MESSAGE
|
|
@@ -20211,6 +20237,9 @@ var planInputSchema = external_exports.strictObject({
|
|
|
20211
20237
|
// Names the issue's directory under `.athena/workflows/<slugId>/`, so only a Linear identifier.
|
|
20212
20238
|
identifier: external_exports.string().regex(/^[A-Z][A-Z0-9]*-[0-9]+$/),
|
|
20213
20239
|
title: external_exports.string(),
|
|
20240
|
+
description: external_exports.string().optional(),
|
|
20241
|
+
acceptanceCriteria: external_exports.string().optional(),
|
|
20242
|
+
external: external_exports.boolean().optional(),
|
|
20214
20243
|
url: external_exports.string().url(),
|
|
20215
20244
|
branchName: external_exports.string().nullable(),
|
|
20216
20245
|
state: external_exports.strictObject({
|
|
@@ -20240,7 +20269,12 @@ var SKIP_REASONS = [
|
|
|
20240
20269
|
"ready-for-human",
|
|
20241
20270
|
"merged",
|
|
20242
20271
|
"done-pr-open",
|
|
20243
|
-
"parent-only"
|
|
20272
|
+
"parent-only",
|
|
20273
|
+
"external",
|
|
20274
|
+
"needs-info",
|
|
20275
|
+
"needs-triage",
|
|
20276
|
+
"wontfix",
|
|
20277
|
+
"not-ready-for-agent"
|
|
20244
20278
|
];
|
|
20245
20279
|
var count = external_exports.number().int().nonnegative();
|
|
20246
20280
|
var issueEntrySchema = external_exports.strictObject({
|
|
@@ -20249,7 +20283,9 @@ var issueEntrySchema = external_exports.strictObject({
|
|
|
20249
20283
|
title: external_exports.string(),
|
|
20250
20284
|
blockedBy: external_exports.array(external_exports.string()),
|
|
20251
20285
|
areas: external_exports.array(external_exports.enum(AREAS)).min(1),
|
|
20252
|
-
qa: external_exports.enum(["none", "web", "macos"]),
|
|
20286
|
+
qa: external_exports.enum(["none", "web", "macos", "both"]),
|
|
20287
|
+
profile: external_exports.enum(["implementation", "documentation", "investigation"]).optional(),
|
|
20288
|
+
scopeFingerprint: external_exports.string().optional(),
|
|
20253
20289
|
sizeClass: external_exports.enum(["S", "M", "L"]),
|
|
20254
20290
|
tokenCap: external_exports.number().int().positive(),
|
|
20255
20291
|
model: external_exports.string(),
|
|
@@ -20441,6 +20477,32 @@ function mergeGuidance(earlier, guidance) {
|
|
|
20441
20477
|
return rounds.slice(-GUIDANCE_ROUNDS);
|
|
20442
20478
|
}
|
|
20443
20479
|
|
|
20480
|
+
// src/core/build/eligibility.ts
|
|
20481
|
+
import { createHash as createHash3 } from "crypto";
|
|
20482
|
+
function eligibilityReason(issue) {
|
|
20483
|
+
if (issue.external) return "external";
|
|
20484
|
+
for (const label of [
|
|
20485
|
+
"ready-for-human",
|
|
20486
|
+
"needs-info",
|
|
20487
|
+
"needs-triage",
|
|
20488
|
+
"wontfix"
|
|
20489
|
+
])
|
|
20490
|
+
if (issue.labels.includes(label)) return label;
|
|
20491
|
+
if (issue.state.type === "triage") return "needs-triage";
|
|
20492
|
+
if (!issue.labels.includes("ready-for-agent")) return "not-ready-for-agent";
|
|
20493
|
+
return void 0;
|
|
20494
|
+
}
|
|
20495
|
+
function scopeFingerprint(issue) {
|
|
20496
|
+
return createHash3("sha256").update(
|
|
20497
|
+
JSON.stringify([
|
|
20498
|
+
issue.title,
|
|
20499
|
+
issue.description ?? "",
|
|
20500
|
+
issue.acceptanceCriteria ?? "",
|
|
20501
|
+
issue.parentId
|
|
20502
|
+
])
|
|
20503
|
+
).digest("hex");
|
|
20504
|
+
}
|
|
20505
|
+
|
|
20444
20506
|
// src/core/build/planner.ts
|
|
20445
20507
|
function skipReason(issue, pullRequests) {
|
|
20446
20508
|
const prs = issue.branchName ? pullRequests[issue.branchName] : void 0;
|
|
@@ -20449,6 +20511,8 @@ function skipReason(issue, pullRequests) {
|
|
|
20449
20511
|
if (issue.state.type === "completed") return "done";
|
|
20450
20512
|
if (issue.state.type === "canceled") return "canceled";
|
|
20451
20513
|
if (prs?.merged) return "merged";
|
|
20514
|
+
const eligibility = eligibilityReason(issue);
|
|
20515
|
+
if (eligibility) return eligibility;
|
|
20452
20516
|
return void 0;
|
|
20453
20517
|
}
|
|
20454
20518
|
var byIdentifier = (a, b) => a.localeCompare(b, "en", { numeric: true });
|
|
@@ -20492,6 +20556,7 @@ function shownFromFill(fill) {
|
|
|
20492
20556
|
return {
|
|
20493
20557
|
areas: fill.areas,
|
|
20494
20558
|
qa: fill.qa,
|
|
20559
|
+
...fill.profile ? { profile: fill.profile } : {},
|
|
20495
20560
|
sizeClass: fill.sizeClass,
|
|
20496
20561
|
tokenCap: limits.maxRunTokens,
|
|
20497
20562
|
model: limits.model,
|
|
@@ -20590,11 +20655,21 @@ function planBuild(context) {
|
|
|
20590
20655
|
({ children, blockers } = blockingGraph(entries));
|
|
20591
20656
|
}
|
|
20592
20657
|
const held = new Set(
|
|
20593
|
-
skipped.filter(
|
|
20658
|
+
skipped.filter(
|
|
20659
|
+
(skip) => !["done", "merged", "done-pr-open", "parent-only"].includes(
|
|
20660
|
+
skip.reason
|
|
20661
|
+
)
|
|
20662
|
+
).map((skip) => skip.id)
|
|
20594
20663
|
);
|
|
20595
20664
|
const waitsFor = (issue) => [
|
|
20596
20665
|
.../* @__PURE__ */ new Set([
|
|
20597
|
-
...issue.blockedBy.filter(
|
|
20666
|
+
...issue.blockedBy.filter(
|
|
20667
|
+
(id2) => !input.issues.some(
|
|
20668
|
+
(each) => each.id === id2 && (each.state.type === "completed" || skipped.some(
|
|
20669
|
+
(skip) => skip.id === id2 && skip.reason === "merged"
|
|
20670
|
+
))
|
|
20671
|
+
)
|
|
20672
|
+
),
|
|
20598
20673
|
...children.get(issue.id) ?? [],
|
|
20599
20674
|
...input.issues.filter((each) => each.parentId === issue.id && held.has(each.id)).map((each) => each.id)
|
|
20600
20675
|
])
|
|
@@ -20624,6 +20699,7 @@ function planBuild(context) {
|
|
|
20624
20699
|
title: issue.title,
|
|
20625
20700
|
blockedBy: waitsFor(issue),
|
|
20626
20701
|
...shownFromFill(fill),
|
|
20702
|
+
scopeFingerprint: scopeFingerprint(issue),
|
|
20627
20703
|
workflowName: workflowName2
|
|
20628
20704
|
});
|
|
20629
20705
|
workflows.push({
|
|
@@ -21195,7 +21271,7 @@ async function closeOrphanedRuns(store, {
|
|
|
21195
21271
|
}
|
|
21196
21272
|
|
|
21197
21273
|
// ../../modules/runtime/src/run-artifacts.ts
|
|
21198
|
-
import { createHash as
|
|
21274
|
+
import { createHash as createHash4 } from "crypto";
|
|
21199
21275
|
import { mkdirSync as mkdirSync2, readdirSync as readdirSync2, readFileSync as readFileSync4, statSync as statSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
21200
21276
|
import { tmpdir as tmpdir5 } from "os";
|
|
21201
21277
|
import { dirname as dirname4, join as join7 } from "path";
|
|
@@ -21238,7 +21314,7 @@ function runArtifactEmitter(directory, record, midTurnMinGapMs = MID_TURN_MIN_GA
|
|
|
21238
21314
|
} catch {
|
|
21239
21315
|
continue;
|
|
21240
21316
|
}
|
|
21241
|
-
const hash =
|
|
21317
|
+
const hash = createHash4("sha256").update(bytes).digest("hex");
|
|
21242
21318
|
if (emitted[name] === hash) continue;
|
|
21243
21319
|
let json;
|
|
21244
21320
|
try {
|
|
@@ -21943,6 +22019,8 @@ export {
|
|
|
21943
22019
|
repoLayoutAt,
|
|
21944
22020
|
approvalAnswer,
|
|
21945
22021
|
mergeGuidance,
|
|
22022
|
+
eligibilityReason,
|
|
22023
|
+
scopeFingerprint,
|
|
21946
22024
|
planBuild,
|
|
21947
22025
|
finalizePlan,
|
|
21948
22026
|
fallbackBranch,
|
|
@@ -21967,4 +22045,4 @@ export {
|
|
|
21967
22045
|
runMachineRunners,
|
|
21968
22046
|
writeIdentityOnce
|
|
21969
22047
|
};
|
|
21970
|
-
//# sourceMappingURL=chunk-
|
|
22048
|
+
//# sourceMappingURL=chunk-D246FR4I.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runMachineRunners
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-D246FR4I.js";
|
|
4
4
|
|
|
5
5
|
// src/app/entry/runnerDaemon.ts
|
|
6
6
|
if (process.argv.includes("--help")) {
|
|
@@ -13,4 +13,4 @@ if (process.argv.includes("--help")) {
|
|
|
13
13
|
process.exitCode = 1;
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
|
-
//# sourceMappingURL=chunk-
|
|
16
|
+
//# sourceMappingURL=chunk-D5VZT7M3.js.map
|
|
@@ -21281,7 +21281,7 @@ var GATES = [
|
|
|
21281
21281
|
];
|
|
21282
21282
|
|
|
21283
21283
|
// src/core/workflows/builtins/orchestrator/workflow.md
|
|
21284
|
-
var workflow_default = '# Orchestrator: plan and run a Build\n\nYou plan and run a Drisp Build of one Plan: the open issues of one Linear project. The Run\'s prompt names the\nLinear project, the Plan key and the project folder, which is your working directory. You never write code here:\neach issue is built by its own child Run, which `drisp build tick` starts.\n\nThe Runner sets these for you:\n\n- `DRISP_RUN_ARTIFACTS`: this Run\'s artifact directory. Files you write there are shown to the member.\n- `DRISP_RUN_ID`, `DRISP_RUNNER_ID`, `DRISP_RUN_TOKEN`, `DRISP_HUB_URL`: this Run, its Runner and its right to start\n child Runs; `drisp build` reads them itself.\n\n## 1. Read Linear (first Turn)\n\nWith the `linear` MCP server, read the project and every issue in it, then write\n`$DRISP_RUN_ARTIFACTS/input/plan-input.json` (create the `input` directory) in exactly this shape. Every issue carries\nevery field, empty when it has none. `readAt` is the output of\n`node -e "console.log(new Date().toISOString())"` run just before you read Linear; never write a time yourself:\n\n```json\n{\n "version": 1,\n "readAt": "<the command\'s output, e.g. 2026-10-11T09:30:00.000Z>",\n "project": {\n "id": "<the project\'s `uuid`, not its `id`>",\n "name": "<the project\'s `name`>",\n "slugId": "<the last `-`-separated part of the project\'s `url`>"\n },\n "issues": [\n {\n "id": "<the issue\'s `uuid`, not its `id`>",\n "identifier": "<the issue\'s `id`, e.g. DRI-12>",\n "title": "<the issue\'s `title`>",\n "url": "<the issue\'s `url`>",\n "branchName": "<the issue\'s `gitBranchName`, or null>",\n "state": {\n "type": "<the issue\'s `statusType`: backlog|unstarted|started|completed|canceled|triage>",\n "name": "<the issue\'s `status`>"\n },\n "labels": ["<each of the issue\'s `labels`>"],\n "parentId": "<the parent issue\'s `uuid`, or null>",\n "blockedBy": ["<the `uuid` of each issue in `relations.blockedBy`>"],\n "prioritySortOrder": 0\n }\n ]\n}\n```\n\nLinear\'s MCP names fields differently from this file, and the difference matters: the app finds each issue\'s row by\nits UUID, so a plan that carries identifiers shows no Build state on any row.\n\n- The MCP\'s `id` is the readable identifier (`DRI-12`, or `P-DRI-7` for a project); the UUID is in `uuid`. Every\n `id`, `parentId` and `blockedBy` value in `plan-input.json` is a UUID (`7f7b03f7-accf-46b2-98fb-abadfed76594`).\n- An issue\'s `parentId` and `relations.blockedBy` from the MCP name issues by identifier. Look each one up: use the\n `uuid` of the project\'s issue with that identifier, or `get_issue` it when it is outside the project.\n- Read relations with `get_issue` and `includeRelations: true`; read the project\'s issues with `list_issues` and\n `fields` including `uuid`.\n- The project\'s `url` ends in its `slugId` (`\u2026/project/build-sandbox-b7640301cd64` \u2192 `b7640301cd64`).\n\n`drisp build plan` rejects a plan with an identifier where a UUID belongs and names the field to fix.\n\nInclude every issue of the project, done and canceled ones too: the plan decides what to skip. Then run:\n\n```sh\ndrisp build plan --input "$DRISP_RUN_ARTIFACTS/input/plan-input.json"\n```\n\nIt prints one JSON object. Act on its `status`.\n\n## 2. `needs_fills`\n\n`fills` lists issues that need a `fill.json` (`identifier`, `title`, `url`, `path`) and `templateVersion` is the value\neach fill must carry. For each listed issue: read it through `linear` (description, acceptance criteria, comments) and\nthe repo\'s ADRs and CONTEXT files it touches, then write its `fill.json` at `path`:\n\n```json\n{\n "version": 1,\n "templateVersion": "<templateVersion, copied exactly>",\n "areas": ["macos|web|cli|hub|protocol|docs", "\u2026"],\n "qa": "none|web|macos",\n "sizeClass": "S|M|L",\n "instructions": "<what the child needs beyond the issue>",\n "ownWork": true\n}\n```\n\n- `areas`: the parts of the repo the change touches, each once.\n- `qa`: `web` when the change shows in a web page, `macos` when it shows in the macOS app, else `none`.\n- `sizeClass`: `S` for a change of a file or two, `M` for a feature across a few modules, `L` for a large or risky\n change.\n- `instructions` (at most 6000 characters): start with one short paragraph saying what to build, then restate the\n acceptance criteria, name the ADRs it touches and the parts of the codebase involved. Plain prose and `-` lists\n only: no headings, code fences or HTML comments (`drisp build plan` rejects them).\n- `ownWork`: `false` only for an issue with sub-issues whose own description asks for nothing beyond them, such as\n a PRD above its slices; the plan then skips it and waits for its sub-issues instead. Otherwise `true`.\n\nThen run `drisp build plan` again with the same `--input` path.\n\n## 3. `planned` or `failed`\n\nOn `planned` the Build plan is written and shown to the member, who decides whether to start it: end the Turn with\n`<!-- AWAITING_APPROVAL -->` as the Journal\'s last line. On `failed` the reason is shown instead: end with\n`<!-- WORKFLOW_COMPLETE -->`.\n\n## 4. Every later wake: tick\n\nYou are woken when the member answers the approval question (with Start, or with words of their own before it) and whenever one of your child Runs closes or parks.\nEach time: read Linear again into `$DRISP_RUN_ARTIFACTS/input/plan-input.json` as in step 1 (with a new `readAt`),\
|
|
21284
|
+
var workflow_default = '# Orchestrator: plan and run a Build\n\nYou plan and run a Drisp Build of one Plan: the open issues of one Linear project. The Run\'s prompt names the\nLinear project, the Plan key and the project folder, which is your working directory. You never write code here:\neach issue is built by its own child Run, which `drisp build tick` starts.\n\nThe Runner sets these for you:\n\n- `DRISP_RUN_ARTIFACTS`: this Run\'s artifact directory. Files you write there are shown to the member.\n- `DRISP_RUN_ID`, `DRISP_RUNNER_ID`, `DRISP_RUN_TOKEN`, `DRISP_HUB_URL`: this Run, its Runner and its right to start\n child Runs; `drisp build` reads them itself.\n\n## 1. Read Linear (first Turn)\n\nWith the `linear` MCP server, read the project and every issue in it, then write\n`$DRISP_RUN_ARTIFACTS/input/plan-input.json` (create the `input` directory) in exactly this shape. Every issue carries\nevery field, empty when it has none. `readAt` is the output of\n`node -e "console.log(new Date().toISOString())"` run just before you read Linear; never write a time yourself:\n\n```json\n{\n "version": 1,\n "readAt": "<the command\'s output, e.g. 2026-10-11T09:30:00.000Z>",\n "project": {\n "id": "<the project\'s `uuid`, not its `id`>",\n "name": "<the project\'s `name`>",\n "slugId": "<the last `-`-separated part of the project\'s `url`>"\n },\n "issues": [\n {\n "id": "<the issue\'s `uuid`, not its `id`>",\n "identifier": "<the issue\'s `id`, e.g. DRI-12>",\n "title": "<the issue\'s `title`>",\n "description": "<full current description>",\n "acceptanceCriteria": "<acceptance criteria, empty when included in description>",\n "external": false,\n "url": "<the issue\'s `url`>",\n "branchName": "<the issue\'s `gitBranchName`, or null>",\n "state": {\n "type": "<the issue\'s `statusType`: backlog|unstarted|started|completed|canceled|triage>",\n "name": "<the issue\'s `status`>"\n },\n "labels": ["<each of the issue\'s `labels`>"],\n "parentId": "<the parent issue\'s `uuid`, or null>",\n "blockedBy": ["<the `uuid` of each issue in `relations.blockedBy`>"],\n "prioritySortOrder": 0\n }\n ]\n}\n```\n\nLinear\'s MCP names fields differently from this file, and the difference matters: the app finds each issue\'s row by\nits UUID, so a plan that carries identifiers shows no Build state on any row.\n\n- The MCP\'s `id` is the readable identifier (`DRI-12`, or `P-DRI-7` for a project); the UUID is in `uuid`. Every\n `id`, `parentId` and `blockedBy` value in `plan-input.json` is a UUID (`7f7b03f7-accf-46b2-98fb-abadfed76594`).\n- An issue\'s `parentId` and `relations.blockedBy` from the MCP name issues by identifier. Look each one up: use the\n `uuid` of the project\'s issue with that identifier, or `get_issue` it when it is outside the project.\n- Read relations with `get_issue` and `includeRelations: true`; read the project\'s issues with `list_issues` and\n `fields` including `uuid`.\n- The project\'s `url` ends in its `slugId` (`\u2026/project/build-sandbox-b7640301cd64` \u2192 `b7640301cd64`).\n\n`drisp build plan` rejects a plan with an identifier where a UUID belongs and names the field to fix.\n\nAlso include every referenced blocker outside the project, with `external: true`, its current status and UUID. Follow blocker relations recursively; deduplicate by UUID. Never mark a project issue external. External issues are read only and never scheduled. Preserve actual prioritySortOrder when available.\n\nOnly ready-for-agent issues without conflicting ready-for-human, needs-info, needs-triage or wontfix labels are eligible. Do not invent or change labels to make an issue eligible.\n\nInclude every issue of the project, done and canceled ones too: the plan decides what to skip. Then run:\n\n```sh\ndrisp build plan --input "$DRISP_RUN_ARTIFACTS/input/plan-input.json"\n```\n\nIt prints one JSON object. Act on its `status`.\n\n## 2. `needs_fills`\n\n`fills` lists issues that need a `fill.json` (`identifier`, `title`, `url`, `path`) and `templateVersion` is the value\neach fill must carry. For each listed issue: read it through `linear` (description, acceptance criteria, comments) and\nthe repo\'s ADRs and CONTEXT files it touches, then write its `fill.json` at `path`:\n\n```json\n{\n "version": 1,\n "templateVersion": "<templateVersion, copied exactly>",\n "areas": ["macos|web|cli|hub|protocol|docs", "\u2026"],\n "qa": "none|web|macos|both",\n "profile": "implementation|documentation|investigation",\n "rationale": "<why these steps are appropriate>",\n "acceptanceEvidence": [\n "<each acceptance criterion and the evidence that demonstrates it>"\n ],\n "sizeClass": "S|M|L",\n "instructions": "<what the child needs beyond the issue>",\n "ownWork": true\n}\n```\n\n- `areas`: the parts of the repo the change touches, each once.\n- `profile`: implementation for behavior changes, documentation for prose-only repository changes, investigation for findings with no repository changes. Implementation defaults to TDD and two-reviewer code review; documentation and investigation omit these by default. Choose the profile from the actual deliverable, not the issue size.\n- Optional `testFirst` and `review`: `{ "enabled": true|false, "reason": "<issue-specific justification>" }`. Retain tests and review for behavioral changes; omit only when not applicable and explain why. These selections also control required skills.\n- Optional `checks`: a nonempty list of actual validation commands from the repo, using the supported npm, vitest, make or git diff command families. Read repository tooling and add the relevant test/build checks: typechecking alone does not prove behavior. If a necessary command is unsupported, state that limitation in instructions and require human attention, never claim validation passed.\n- `acceptanceEvidence`: cover every criterion, including the method and expected outcome.\n- `qa`: `both` when both interfaces change, `web` when the change shows in a web page, `macos` when it shows in the macOS app, else `none`.\n- `sizeClass`: `S` for a change of a file or two, `M` for a feature across a few modules, `L` for a large or risky\n change.\n- `instructions` (at most 6000 characters): start with one short paragraph saying what to build, then restate the\n acceptance criteria, name the ADRs it touches and the parts of the codebase involved. Plain prose and `-` lists\n only: no headings, code fences or HTML comments (`drisp build plan` rejects them).\n- `ownWork`: `false` only for an issue with sub-issues whose own description asks for nothing beyond them, such as\n a PRD above its slices; the plan then skips it and waits for its sub-issues instead. Otherwise `true`.\n\nThen run `drisp build plan` again with the same `--input` path.\n\n## 3. `planned` or `failed`\n\nOn `planned` the Build plan is written and shown to the member, who decides whether to start it: end the Turn with\n`<!-- AWAITING_APPROVAL -->` as the Journal\'s last line. On `failed` the reason is shown instead: end with\n`<!-- WORKFLOW_COMPLETE -->`.\n\n## 4. Every later wake: tick\n\nYou are woken when the member answers the approval question (with Start, or with words of their own before it) and whenever one of your child Runs closes or parks.\nEach time: read Linear again into `$DRISP_RUN_ARTIFACTS/input/plan-input.json` as in step 1 (with a new `readAt`),\nincluding full descriptions, acceptance criteria, labels and external blocker status. A scope change holds the affected issue for a fresh Build and approval. Then run:\n\n```sh\ndrisp build tick --input "$DRISP_RUN_ARTIFACTS/input/plan-input.json"\n```\n\nIt prints one JSON object. Act on its `action`, and repeat until an action ends the Turn:\n\n- `refresh_input`: read Linear into the input again (a newer `readAt`) and tick again.\n- `replan`: the member wrote words before starting, and `guidance` lists every round of them, oldest first. Plan again\n with them as the member\'s wishes: read the issues they concern (and the repo) as in step 2, rewrite the `fill.json`\n of each issue the guidance changes (`instructions`, `areas`, `qa`, `sizeClass`, or `ownWork` to leave an issue out),\n and run `drisp build plan` again with the same `--input` path. Then end as in step 3: with\n `<!-- AWAITING_APPROVAL -->` on `planned`, `<!-- WORKFLOW_COMPLETE -->` on `failed`. Write nothing but those\n `fill.json` files.\n- `repair`: for each of `issues`, read it in Linear first and skip an issue Linear now shows Done or Canceled (its\n child got there first); otherwise move it to Done and post its `comment` verbatim through `linear`. Then read\n Linear into the input again and tick again.\n- `rebase`: for each of `items`, in its `worktree`: `git rebase origin/main`, resolve the conflicts, then\n `git push --force-with-lease origin <branch>` (the item\'s `branch`) if the branch is on the remote. Never push any\n other branch. If a rebase cannot be resolved, `git rebase --abort`.\n Then read Linear into the input again and tick again, adding `--rebase-failed <identifier>` for each that failed.\n- `wait`: end the Turn with `<!-- WAITING_ON_CHILDREN -->` as the Journal\'s last line.\n- `park`: end the Turn with `<!-- NEEDS_HUMAN: <message> -->` as the Journal\'s last line, copying `message`\n verbatim.\n- `complete`: end the Turn with `<!-- WORKFLOW_COMPLETE -->` as the Journal\'s last line.\n\n## Rules\n\n- Never start, cancel or edit Runs, Workflows, worktrees or branches except as an action says; `drisp build` does\n what is needed.\n- Never write to Linear except a `repair`; never open a pull request.\n- Write only `plan-input.json` and the `fill.json` files `drisp build plan` asks for. Never write `answer.json`.\n';
|
|
21285
21285
|
|
|
21286
21286
|
// src/core/workflows/builtins/orchestrator/index.ts
|
|
21287
21287
|
var ORCHESTRATOR_WORKFLOW_NAME = "orchestrator";
|
|
@@ -21440,6 +21440,14 @@ Journal's last line.
|
|
|
21440
21440
|
|
|
21441
21441
|
{instructions}
|
|
21442
21442
|
|
|
21443
|
+
## Evidence receipts
|
|
21444
|
+
|
|
21445
|
+
Progress is not proof that a step passed. Follow each Finish instruction only after its acceptance condition holds.
|
|
21446
|
+
Record actual results, commands, output paths and acceptance criteria, never a generic claim of success.
|
|
21447
|
+
Commit repository changes before recording validation evidence. Changes to HEAD or source invalidate validation
|
|
21448
|
+
receipts: rerun affected tests, review, checks and QA, including after a rebase, before verifying the Merge step.
|
|
21449
|
+
Keep evidence files under .athena/evidence/ and do not commit them after validation, since a new commit invalidates receipts.
|
|
21450
|
+
|
|
21443
21451
|
## Gates
|
|
21444
21452
|
|
|
21445
21453
|
Work through the gates in this order. Start each gate by running the command its "Start" line gives, which reports the
|
|
@@ -21464,6 +21472,9 @@ is in \`ignored\`: it does not block the merge and its name goes in the evidence
|
|
|
21464
21472
|
empty, wait a minute and run it again. When \`failed\` is not empty, fix the change; if it still fails, the Merge gate
|
|
21465
21473
|
cannot pass. Never judge a check by its timing.
|
|
21466
21474
|
|
|
21475
|
+
Immediately before merging, verify the current revision again: {mergeVerify}. If evidence is stale, rerun the
|
|
21476
|
+
selected validation steps and record fresh receipts before continuing.
|
|
21477
|
+
|
|
21467
21478
|
Merge with \`gh pr merge --squash --delete-branch --match-head-commit <sha>\`, where \`<sha>\` is HEAD after the last
|
|
21468
21479
|
push. When it exits non-zero, \`gh pr view --json state\` decides: \`MERGED\` means the merge happened (a worktree
|
|
21469
21480
|
cannot check out main afterwards); anything else means it did not.
|
|
@@ -21506,12 +21517,13 @@ No gate text: the loop's caps apply.`;
|
|
|
21506
21517
|
|
|
21507
21518
|
// src/core/workflows/builtins/build-child/render.ts
|
|
21508
21519
|
var RENDERER_RULES = {
|
|
21509
|
-
alwaysSkills: [
|
|
21520
|
+
alwaysSkills: [],
|
|
21521
|
+
profiles: ["implementation", "documentation", "investigation"],
|
|
21510
21522
|
alwaysMcpServers: ["linear"],
|
|
21511
21523
|
areaSkills: {
|
|
21512
21524
|
macos: ["swiftui-expert-skill", "apple-docs", "apple-hig-components"]
|
|
21513
21525
|
},
|
|
21514
|
-
qaMcpServers: { web: ["drisp-browser"] },
|
|
21526
|
+
qaMcpServers: { web: ["drisp-browser"], both: ["drisp-browser"] },
|
|
21515
21527
|
npmTestAreas: ["cli", "hub", "protocol"],
|
|
21516
21528
|
/**
|
|
21517
21529
|
* The Checks gate's commands, resolved from the fill's areas and the repo's layout at the plan's commit: a repo
|
|
@@ -21574,6 +21586,7 @@ var RENDERER_RULES = {
|
|
|
21574
21586
|
shell: [
|
|
21575
21587
|
"drisp build checks",
|
|
21576
21588
|
"drisp build step",
|
|
21589
|
+
"drisp build merged",
|
|
21577
21590
|
"gh pr checks",
|
|
21578
21591
|
"gh pr create",
|
|
21579
21592
|
"gh pr list",
|
|
@@ -21615,7 +21628,10 @@ var LAYOUT_MARKERS = [
|
|
|
21615
21628
|
"apps/cli/package.json"
|
|
21616
21629
|
];
|
|
21617
21630
|
function checkCommands(fill, layout) {
|
|
21631
|
+
if (fill.checks) return [...fill.checks];
|
|
21618
21632
|
const rules = RENDERER_RULES.checks;
|
|
21633
|
+
if (fill.profile === "documentation" || fill.profile === "investigation")
|
|
21634
|
+
return [...rules.otherwise];
|
|
21619
21635
|
if (layout.includes("Makefile"))
|
|
21620
21636
|
return [
|
|
21621
21637
|
...rules.rootMakefile,
|
|
@@ -21634,7 +21650,11 @@ function checkCommands(fill, layout) {
|
|
|
21634
21650
|
function installCommand(fill, layout) {
|
|
21635
21651
|
const { install } = RENDERER_RULES.checks;
|
|
21636
21652
|
if (!layout.includes(install.needs)) return void 0;
|
|
21637
|
-
const needsNode =
|
|
21653
|
+
const needsNode = checkCommands(fill, layout).some(
|
|
21654
|
+
(command) => /^np[mx] /.test(command) || layout.includes("Makefile") && RENDERER_RULES.checks.rootMakefile.some(
|
|
21655
|
+
(rootCommand) => rootCommand === command
|
|
21656
|
+
)
|
|
21657
|
+
);
|
|
21638
21658
|
return needsNode ? install.command : void 0;
|
|
21639
21659
|
}
|
|
21640
21660
|
var GENERATED_NAME = /^build--([a-z0-9]+)--([A-Z][A-Z0-9]*-[0-9]+)$/;
|
|
@@ -21652,6 +21672,8 @@ function renderedSkills(fill) {
|
|
|
21652
21672
|
return [
|
|
21653
21673
|
.../* @__PURE__ */ new Set([
|
|
21654
21674
|
...RENDERER_RULES.alwaysSkills,
|
|
21675
|
+
...usesTestFirst(fill) ? ["tdd"] : [],
|
|
21676
|
+
...usesReview(fill) ? ["code-review"] : [],
|
|
21655
21677
|
...fill.areas.flatMap((area) => RENDERER_RULES.areaSkills[area] ?? [])
|
|
21656
21678
|
])
|
|
21657
21679
|
].sort();
|
|
@@ -21664,8 +21686,24 @@ function renderedMcpServers(fill) {
|
|
|
21664
21686
|
])
|
|
21665
21687
|
].sort();
|
|
21666
21688
|
}
|
|
21689
|
+
function shellCommands(fill) {
|
|
21690
|
+
const commands = [...RENDERER_RULES.permissions.shell];
|
|
21691
|
+
return fill.profile !== "investigation" ? commands : commands.filter(
|
|
21692
|
+
(command) => ![
|
|
21693
|
+
"drisp build merged",
|
|
21694
|
+
"gh pr create",
|
|
21695
|
+
"gh pr merge",
|
|
21696
|
+
"git add",
|
|
21697
|
+
"git commit",
|
|
21698
|
+
"git push",
|
|
21699
|
+
"git rebase",
|
|
21700
|
+
"git restore"
|
|
21701
|
+
].includes(command)
|
|
21702
|
+
);
|
|
21703
|
+
}
|
|
21667
21704
|
function renderedPermissions(fill) {
|
|
21668
|
-
const { edit,
|
|
21705
|
+
const { edit, deny } = RENDERER_RULES.permissions;
|
|
21706
|
+
const shell = shellCommands(fill);
|
|
21669
21707
|
return {
|
|
21670
21708
|
allow: [
|
|
21671
21709
|
...edit,
|
|
@@ -21675,10 +21713,29 @@ function renderedPermissions(fill) {
|
|
|
21675
21713
|
deny: [...deny]
|
|
21676
21714
|
};
|
|
21677
21715
|
}
|
|
21678
|
-
|
|
21679
|
-
|
|
21680
|
-
|
|
21716
|
+
var usesTestFirst = (fill) => fill.testFirst?.enabled ?? (!fill.profile || fill.profile === "implementation");
|
|
21717
|
+
var usesReview = (fill) => fill.review?.enabled ?? (!fill.profile || fill.profile === "implementation");
|
|
21718
|
+
function selectedGates(fill) {
|
|
21719
|
+
const gates = GATES.filter(
|
|
21720
|
+
(gate) => (gate.title !== "QA" || fill.qa !== "none") && (gate.title !== "Test first" || usesTestFirst(fill)) && (gate.title !== "Code review" || usesReview(fill)) && (fill.profile !== "investigation" || !["Pull request", "Merge"].includes(gate.title))
|
|
21721
|
+
).map(
|
|
21722
|
+
(gate) => fill.profile === "investigation" && gate.title === "Checks" ? {
|
|
21723
|
+
...gate,
|
|
21724
|
+
passesWhen: "{install}{checks} pass; each finding is supported by a source or reproducible observation and each acceptance criterion has evidence; unresolved questions are stated explicitly"
|
|
21725
|
+
} : fill.profile === "investigation" && gate.title === "Evidence" ? {
|
|
21726
|
+
...gate,
|
|
21727
|
+
passesWhen: "findings and evidence for each acceptance criterion are posted on the Linear issue, with unresolved questions explicitly stated; the issue is moved to Done only when all acceptance criteria are satisfied"
|
|
21728
|
+
} : gate
|
|
21681
21729
|
);
|
|
21730
|
+
if (!usesTestFirst(fill))
|
|
21731
|
+
gates.splice(1, 0, {
|
|
21732
|
+
title: fill.profile === "investigation" ? "Investigate" : "Implement",
|
|
21733
|
+
passesWhen: fill.profile === "investigation" ? "the question is investigated and findings address every acceptance criterion; no repository changes are made" : "the requested change is implemented and each acceptance criterion is checked"
|
|
21734
|
+
});
|
|
21735
|
+
return gates;
|
|
21736
|
+
}
|
|
21737
|
+
function gateTitles(fill) {
|
|
21738
|
+
return selectedGates(fill).map((gate) => gate.title);
|
|
21682
21739
|
}
|
|
21683
21740
|
function summarizeInstructions(instructions) {
|
|
21684
21741
|
const paragraph = (instructions.trim().split(/\n\s*\n/)[0] ?? "").replace(/\s+/g, " ").trim();
|
|
@@ -21693,21 +21750,29 @@ function checksText(commands) {
|
|
|
21693
21750
|
return quoted.length === 1 ? quoted[0] : `${quoted.slice(0, -1).join(", ")} and ${quoted.at(-1)}`;
|
|
21694
21751
|
}
|
|
21695
21752
|
var fillSlots = (template, slots) => template.replace(/\{(\w+)\}/g, (whole, key) => slots[key] ?? whole);
|
|
21753
|
+
function selectionFlags(fill) {
|
|
21754
|
+
return `${fill.profile ? ` --profile ${fill.profile}` : ""}${fill.testFirst ? ` --test-first ${fill.testFirst.enabled}` : ""}${fill.review ? ` --review ${fill.review.enabled}` : ""}`;
|
|
21755
|
+
}
|
|
21696
21756
|
function renderStages(fill, checks, install) {
|
|
21697
|
-
const gates =
|
|
21757
|
+
const gates = selectedGates(fill);
|
|
21698
21758
|
return gates.map((gate, index) => {
|
|
21699
21759
|
const passesWhen = fillSlots(gate.passesWhen, {
|
|
21700
21760
|
install: install ? `after \`${install}\`, ` : "",
|
|
21701
21761
|
checks: checksText(checks),
|
|
21702
|
-
qa: fill.qa === "none" ? "" : QA_SECTIONS[fill.qa]
|
|
21762
|
+
qa: fill.qa === "none" ? "" : fill.qa === "both" ? `${QA_SECTIONS.web}; also ${QA_SECTIONS.macos}` : QA_SECTIONS[fill.qa]
|
|
21703
21763
|
});
|
|
21764
|
+
const command = `drisp build step ${index + 1} --qa ${fill.qa}${selectionFlags(fill)}`;
|
|
21704
21765
|
const stage = fillSlots(STAGE_TEMPLATE, {
|
|
21705
21766
|
n: String(index + 1),
|
|
21706
21767
|
title: gate.title,
|
|
21707
|
-
stepCommand:
|
|
21768
|
+
stepCommand: command,
|
|
21708
21769
|
passesWhen
|
|
21709
21770
|
});
|
|
21710
|
-
return stage + (
|
|
21771
|
+
return stage + (["Merge", "Evidence"].includes(gate.title) ? `
|
|
21772
|
+
|
|
21773
|
+
Before doing this step: run \`${command} --verify\`. Missing or stale evidence must be refreshed first.` : "") + `
|
|
21774
|
+
|
|
21775
|
+
Finish: write the actual result and supporting paths to \`.athena/evidence/step-${index + 1}.md\`, then run \`${command} --complete --evidence .athena/evidence/step-${index + 1}.md\`. This records an agent attestation, not independent verification.` + (gate.cannotPass ? fillSlots(CANNOT_PASS_TEMPLATE, { cannotPass: gate.cannotPass }) : NO_GATE_TEXT_TEMPLATE);
|
|
21711
21776
|
}).join("\n\n");
|
|
21712
21777
|
}
|
|
21713
21778
|
function render(fill, workflowName, layout) {
|
|
@@ -21717,7 +21782,7 @@ function render(fill, workflowName, layout) {
|
|
|
21717
21782
|
const limits = sizeClassLimits(fill.sizeClass);
|
|
21718
21783
|
const workflow = {
|
|
21719
21784
|
name: workflowName,
|
|
21720
|
-
description: fillSlots(DESCRIPTION_TEMPLATE, {
|
|
21785
|
+
description: fill.profile === "investigation" ? `Investigates ${parsed.identifier} and delivers findings with acceptance evidence.` : fillSlots(DESCRIPTION_TEMPLATE, {
|
|
21721
21786
|
identifier: parsed.identifier
|
|
21722
21787
|
}),
|
|
21723
21788
|
promptTemplate: "{input}",
|
|
@@ -21734,12 +21799,40 @@ function render(fill, workflowName, layout) {
|
|
|
21734
21799
|
permissions: renderedPermissions(fill)
|
|
21735
21800
|
};
|
|
21736
21801
|
const checks = checkCommands(fill, layout);
|
|
21737
|
-
|
|
21802
|
+
let template = WORKFLOW_MD_TEMPLATE;
|
|
21803
|
+
if (!usesReview(fill))
|
|
21804
|
+
template = template.replaceAll(
|
|
21805
|
+
"both reviewers pass;",
|
|
21806
|
+
"review is omitted by the approved plan;"
|
|
21807
|
+
).replaceAll(
|
|
21808
|
+
"Review: Standards \u2713 \xB7 Spec \u2713",
|
|
21809
|
+
"Review: omitted by the approved plan"
|
|
21810
|
+
);
|
|
21811
|
+
if (fill.profile === "investigation") {
|
|
21812
|
+
template = template.replace(
|
|
21813
|
+
/## Merge gate[\s\S]*?## Linear/,
|
|
21814
|
+
"## Findings\n\nPost findings and acceptance evidence on the Linear issue. No pull request or merge is required.\n\n## Linear"
|
|
21815
|
+
);
|
|
21816
|
+
template = template.replace(
|
|
21817
|
+
"Your Linear writes are exactly: In Progress in Explore, `PR: <url>` in Pull request, the evidence comment and Done in\nEvidence.",
|
|
21818
|
+
"Your Linear writes are In Progress in Explore, findings and evidence, and Done in Evidence."
|
|
21819
|
+
);
|
|
21820
|
+
}
|
|
21821
|
+
const workflowMd = fillSlots(template, {
|
|
21738
21822
|
identifier: parsed.identifier,
|
|
21739
|
-
instructions:
|
|
21823
|
+
instructions: [
|
|
21824
|
+
fill.instructions.trim(),
|
|
21825
|
+
fill.rationale ? `Plan rationale: ${fill.rationale}` : "",
|
|
21826
|
+
fill.testFirst ? `Test first: ${fill.testFirst.enabled ? "included" : "omitted"} \u2014 ${fill.testFirst.reason}` : "",
|
|
21827
|
+
fill.review ? `Code review: ${fill.review.enabled ? "included" : "omitted"} \u2014 ${fill.review.reason}` : "",
|
|
21828
|
+
...(fill.acceptanceEvidence ?? []).map(
|
|
21829
|
+
(item) => `Acceptance evidence: ${item}`
|
|
21830
|
+
)
|
|
21831
|
+
].filter(Boolean).join("\n\n"),
|
|
21740
21832
|
gates: renderStages(fill, checks, installCommand(fill, layout)),
|
|
21833
|
+
mergeVerify: `\`drisp build step ${gateTitles(fill).indexOf("Merge") + 1} --qa ${fill.qa}${selectionFlags(fill)} --verify\``,
|
|
21741
21834
|
checksEvidence: checks.map((command) => `${command} \u2713`).join(" \xB7 "),
|
|
21742
|
-
shellCommands: checksText(
|
|
21835
|
+
shellCommands: checksText(shellCommands(fill))
|
|
21743
21836
|
});
|
|
21744
21837
|
return { workflowJson: `${JSON.stringify(workflow, null, 2)}
|
|
21745
21838
|
`, workflowMd };
|
|
@@ -24254,4 +24347,4 @@ export {
|
|
|
24254
24347
|
compileWorkflowPlan,
|
|
24255
24348
|
collectMcpServersWithOptions
|
|
24256
24349
|
};
|
|
24257
|
-
//# sourceMappingURL=chunk-
|
|
24350
|
+
//# sourceMappingURL=chunk-HZ6GRLOM.js.map
|
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-D246FR4I.js";
|
|
144
146
|
import {
|
|
145
147
|
generateId as generateId2
|
|
146
148
|
} from "./chunk-PQIB66SG.js";
|
|
@@ -198,7 +200,7 @@ import {
|
|
|
198
200
|
workflowRegistryDir,
|
|
199
201
|
writeGlobalConfig,
|
|
200
202
|
writeProjectConfig
|
|
201
|
-
} from "./chunk-
|
|
203
|
+
} from "./chunk-HZ6GRLOM.js";
|
|
202
204
|
import {
|
|
203
205
|
__toESM
|
|
204
206
|
} from "./chunk-G3PMV62Z.js";
|
|
@@ -13615,7 +13617,7 @@ async function recoveryIdentity(runId) {
|
|
|
13615
13617
|
}
|
|
13616
13618
|
|
|
13617
13619
|
// src/app/entry/buildCommand.ts
|
|
13618
|
-
import { execFileSync } from "child_process";
|
|
13620
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
13619
13621
|
|
|
13620
13622
|
// src/core/build/planCommand.ts
|
|
13621
13623
|
import fs6 from "fs";
|
|
@@ -13755,7 +13757,7 @@ function runBuildPlan(deps) {
|
|
|
13755
13757
|
const fixturePullRequests = fixtureDir ? readJson(path6.join(fixtureDir, "pull-requests.json")) : void 0;
|
|
13756
13758
|
const pullRequests = fixturePullRequests ?? Object.fromEntries(
|
|
13757
13759
|
input.issues.filter(
|
|
13758
|
-
(issue) => issue.branchName && issue.state.type !== "canceled" && !issue
|
|
13760
|
+
(issue) => issue.branchName && issue.state.type !== "canceled" && !eligibilityReason(issue)
|
|
13759
13761
|
).map((issue) => [
|
|
13760
13762
|
issue.branchName,
|
|
13761
13763
|
deps.pullRequests(deps.folder, issue.branchName)
|
|
@@ -14266,8 +14268,22 @@ function occupies(view) {
|
|
|
14266
14268
|
function assessTick(facts) {
|
|
14267
14269
|
const { entries, orchestratorRunId } = facts;
|
|
14268
14270
|
const state = structuredClone(facts.state);
|
|
14271
|
+
for (const [id, reason] of Object.entries(state.needsPerson))
|
|
14272
|
+
if (reason.startsWith("Issue is no longer eligible") || reason.startsWith("Waiting for prerequisite"))
|
|
14273
|
+
delete state.needsPerson[id];
|
|
14269
14274
|
const views = new Map(facts.children.map((view) => [view.runId, view]));
|
|
14270
14275
|
const issues = new Map(facts.issues.map((issue) => [issue.id, issue]));
|
|
14276
|
+
const parentOnly = new Set(
|
|
14277
|
+
facts.skipped?.filter((issue) => issue.reason === "parent-only").map((issue) => issue.id) ?? []
|
|
14278
|
+
);
|
|
14279
|
+
const expandBlocker = (id, seen = /* @__PURE__ */ new Set()) => {
|
|
14280
|
+
if (!parentOnly.has(id) || seen.has(id)) return [id];
|
|
14281
|
+
const children = facts.issues.filter((issue) => issue.parentId === id);
|
|
14282
|
+
if (!children.length) return [id];
|
|
14283
|
+
return children.flatMap(
|
|
14284
|
+
(issue) => expandBlocker(issue.id, /* @__PURE__ */ new Set([...seen, id]))
|
|
14285
|
+
);
|
|
14286
|
+
};
|
|
14271
14287
|
const attemptsOf = (id) => state.attempts[id] ?? [];
|
|
14272
14288
|
for (const entry of entries) {
|
|
14273
14289
|
const prefix = `${orchestratorRunId}:${entry.identifier}:a`;
|
|
@@ -14310,7 +14326,7 @@ function assessTick(facts) {
|
|
|
14310
14326
|
const status = /* @__PURE__ */ new Map();
|
|
14311
14327
|
const skippedBlocker = (id) => {
|
|
14312
14328
|
const linear = issues.get(id)?.state.type;
|
|
14313
|
-
return linear === "completed"
|
|
14329
|
+
return linear === "completed" ? "done" : "blocked";
|
|
14314
14330
|
};
|
|
14315
14331
|
const repair = [];
|
|
14316
14332
|
const repaired = new Set(state.repaired ?? []);
|
|
@@ -14321,7 +14337,7 @@ function assessTick(facts) {
|
|
|
14321
14337
|
const linear = issues.get(entry.id)?.state.type;
|
|
14322
14338
|
const statusOf = () => {
|
|
14323
14339
|
if (linear === "completed" || linear === "canceled") return "done";
|
|
14324
|
-
const prs = prsOf(entry);
|
|
14340
|
+
const prs = entry.profile === "investigation" ? void 0 : prsOf(entry);
|
|
14325
14341
|
if (prs?.merged) {
|
|
14326
14342
|
if (!repaired.has(entry.id) && !(newest && occupies(view))) {
|
|
14327
14343
|
const prUrl = prs.mergedUrl ?? branchOf(entry);
|
|
@@ -14336,18 +14352,36 @@ function assessTick(facts) {
|
|
|
14336
14352
|
return "done";
|
|
14337
14353
|
}
|
|
14338
14354
|
if (newest && (!view || !view.closed)) return "live";
|
|
14355
|
+
const current = issues.get(entry.id);
|
|
14356
|
+
if (!current || eligibilityReason(current)) {
|
|
14357
|
+
state.needsPerson[entry.id] = `Issue is no longer eligible (${current ? eligibilityReason(current) : "missing from Linear"}). Update Linear, then Build again.`;
|
|
14358
|
+
return "needs_person";
|
|
14359
|
+
}
|
|
14360
|
+
if (entry.scopeFingerprint && entry.scopeFingerprint !== scopeFingerprint(current)) {
|
|
14361
|
+
state.needsPerson[entry.id] = "Issue scope changed after approval. Build again to review the revised plan.";
|
|
14362
|
+
return "needs_person";
|
|
14363
|
+
}
|
|
14339
14364
|
if (newest?.outcome === "template_mismatch") return "replan";
|
|
14340
14365
|
if (newest?.outcome === "completed")
|
|
14341
|
-
state.needsPerson[entry.id] ??= BUILD_STRINGS.completedUnmerged;
|
|
14366
|
+
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
14367
|
if (state.needsPerson[entry.id] || newest && !mayRetry(attempts))
|
|
14343
14368
|
return "needs_person";
|
|
14344
|
-
const blockers =
|
|
14345
|
-
|
|
14346
|
-
|
|
14369
|
+
const blockers = [
|
|
14370
|
+
.../* @__PURE__ */ new Set([
|
|
14371
|
+
...entry.blockedBy,
|
|
14372
|
+
...current.blockedBy.flatMap((id) => expandBlocker(id))
|
|
14373
|
+
])
|
|
14374
|
+
].map((id) => {
|
|
14375
|
+
if (issues.get(id)?.state.type === "canceled") return "blocked";
|
|
14376
|
+
return status.get(id) ?? (entries.some((each) => each.id === id) && issues.get(id)?.state.type !== "completed" ? "pending" : skippedBlocker(id));
|
|
14377
|
+
});
|
|
14347
14378
|
if (blockers.some(
|
|
14348
14379
|
(b) => b === "needs_person" || b === "replan" || b === "blocked"
|
|
14349
|
-
))
|
|
14380
|
+
)) {
|
|
14381
|
+
if (current.blockedBy.some((id) => !entry.blockedBy.includes(id)))
|
|
14382
|
+
state.needsPerson[entry.id] = "Waiting for prerequisite work. Resolve its readiness, completion or cancellation in Linear, then resume.";
|
|
14350
14383
|
return "blocked";
|
|
14384
|
+
}
|
|
14351
14385
|
return blockers.every((b) => b === "done") ? "ready" : "pending";
|
|
14352
14386
|
};
|
|
14353
14387
|
status.set(entry.id, statusOf());
|
|
@@ -14399,6 +14433,12 @@ function tickAction(input) {
|
|
|
14399
14433
|
const done = input.entries.filter(
|
|
14400
14434
|
(entry) => input.status.get(entry.id) === "done"
|
|
14401
14435
|
).length;
|
|
14436
|
+
if (done !== input.entries.length)
|
|
14437
|
+
return {
|
|
14438
|
+
action: "park",
|
|
14439
|
+
reason: "attention",
|
|
14440
|
+
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.`
|
|
14441
|
+
};
|
|
14402
14442
|
return {
|
|
14403
14443
|
action: "complete",
|
|
14404
14444
|
message: `Built ${done} of ${input.entries.length}`
|
|
@@ -14523,6 +14563,7 @@ async function runBuildTick(deps) {
|
|
|
14523
14563
|
const entries = plan.groups.flatMap((group) => group.issues).filter((entry) => approved.has(entry.id));
|
|
14524
14564
|
const issues = new Map(input.issues.map((issue) => [issue.id, issue]));
|
|
14525
14565
|
const assessment = assessTick({
|
|
14566
|
+
skipped: plan.skipped,
|
|
14526
14567
|
orchestratorRunId,
|
|
14527
14568
|
entries,
|
|
14528
14569
|
issues: input.issues,
|
|
@@ -14725,8 +14766,16 @@ function evaluateRemoteChecks(runs) {
|
|
|
14725
14766
|
}
|
|
14726
14767
|
|
|
14727
14768
|
// src/core/build/step.ts
|
|
14769
|
+
import { execFileSync } from "child_process";
|
|
14770
|
+
import { createHash as createHash2 } from "crypto";
|
|
14728
14771
|
import fs8 from "fs";
|
|
14729
14772
|
import path8 from "path";
|
|
14773
|
+
var receiptSchema = external_exports.strictObject({
|
|
14774
|
+
title: external_exports.string().min(1),
|
|
14775
|
+
revision: external_exports.string().regex(/^[0-9a-f]{64}$/),
|
|
14776
|
+
evidence: external_exports.string().min(1).max(16e3),
|
|
14777
|
+
kind: external_exports.literal("agent-attestation")
|
|
14778
|
+
});
|
|
14730
14779
|
var QA_KINDS = fillSchema.shape.qa.options;
|
|
14731
14780
|
function runBuildStep(input) {
|
|
14732
14781
|
const directory = requireEnv(input.env, "DRISP_RUN_ARTIFACTS");
|
|
@@ -14735,7 +14784,22 @@ function runBuildStep(input) {
|
|
|
14735
14784
|
throw new BuildUsageError(
|
|
14736
14785
|
`--qa must be one of ${QA_KINDS.join(", ")}, not "${qa}".`
|
|
14737
14786
|
);
|
|
14738
|
-
const
|
|
14787
|
+
const parsedProfile = fillSchema.shape.profile.safeParse(input.profile);
|
|
14788
|
+
if (!parsedProfile.success)
|
|
14789
|
+
throw new BuildUsageError("Unknown workflow profile.");
|
|
14790
|
+
const profile = parsedProfile.data;
|
|
14791
|
+
const selection = (value) => {
|
|
14792
|
+
if (value === void 0) return void 0;
|
|
14793
|
+
if (value !== "true" && value !== "false")
|
|
14794
|
+
throw new BuildUsageError("Step selection must be true or false.");
|
|
14795
|
+
return { enabled: value === "true", reason: "Approved workflow" };
|
|
14796
|
+
};
|
|
14797
|
+
const titles = gateTitles({
|
|
14798
|
+
qa,
|
|
14799
|
+
profile,
|
|
14800
|
+
testFirst: selection(input.testFirst),
|
|
14801
|
+
review: selection(input.review)
|
|
14802
|
+
});
|
|
14739
14803
|
const index = /^[0-9]+$/.test(input.n ?? "") ? Number(input.n) : 0;
|
|
14740
14804
|
if (index < 1 || index > titles.length)
|
|
14741
14805
|
throw new BuildUsageError(
|
|
@@ -14745,10 +14809,56 @@ function runBuildStep(input) {
|
|
|
14745
14809
|
throw new BuildUsageError(
|
|
14746
14810
|
`DRISP_RUN_ARTIFACTS (${directory}) is not a directory.`
|
|
14747
14811
|
);
|
|
14812
|
+
const receiptsPath = path8.join(directory, "gate_evidence.json");
|
|
14813
|
+
let receipts = [];
|
|
14814
|
+
if (fs8.existsSync(receiptsPath)) {
|
|
14815
|
+
try {
|
|
14816
|
+
receipts = external_exports.strictObject({ receipts: external_exports.array(receiptSchema).max(100) }).parse(JSON.parse(fs8.readFileSync(receiptsPath, "utf8"))).receipts;
|
|
14817
|
+
} catch {
|
|
14818
|
+
throw new BuildUsageError("Gate evidence is invalid.");
|
|
14819
|
+
}
|
|
14820
|
+
}
|
|
14821
|
+
const revision = receipts.length || input.complete || input.verify ? workRevision(input.cwd ?? process.cwd()) : "";
|
|
14822
|
+
const fresh = (receipt) => ["Explore", "Pull request", "Evidence", "Merge"].includes(receipt.title) || receipt.revision === revision;
|
|
14823
|
+
if (input.verify || input.complete && titles[index - 1] === "Evidence") {
|
|
14824
|
+
const missing = titles.slice(0, index - 1).filter((title) => !receipts.some((r) => r.title === title && fresh(r)));
|
|
14825
|
+
if (missing.length)
|
|
14826
|
+
throw new BuildUsageError(
|
|
14827
|
+
`Missing or stale evidence: ${missing.join(", ")}. Repeat those steps on the current revision.`
|
|
14828
|
+
);
|
|
14829
|
+
}
|
|
14830
|
+
if (input.complete) {
|
|
14831
|
+
if (!input.evidence)
|
|
14832
|
+
throw new BuildUsageError(
|
|
14833
|
+
"--complete requires --evidence <file> containing the result and supporting paths."
|
|
14834
|
+
);
|
|
14835
|
+
let evidence;
|
|
14836
|
+
try {
|
|
14837
|
+
evidence = fs8.readFileSync(
|
|
14838
|
+
path8.resolve(input.cwd ?? process.cwd(), input.evidence),
|
|
14839
|
+
"utf8"
|
|
14840
|
+
).trim();
|
|
14841
|
+
} catch {
|
|
14842
|
+
throw new BuildUsageError("Cannot read the evidence file.");
|
|
14843
|
+
}
|
|
14844
|
+
if (!evidence || evidence.length > 16e3)
|
|
14845
|
+
throw new BuildUsageError("Evidence must contain 1\u201316000 characters.");
|
|
14846
|
+
receipts = receipts.filter((r) => r.title !== titles[index - 1]);
|
|
14847
|
+
receipts.push({
|
|
14848
|
+
title: titles[index - 1],
|
|
14849
|
+
revision,
|
|
14850
|
+
evidence,
|
|
14851
|
+
kind: "agent-attestation"
|
|
14852
|
+
});
|
|
14853
|
+
fs8.writeFileSync(receiptsPath, JSON.stringify({ receipts }) + "\n");
|
|
14854
|
+
}
|
|
14748
14855
|
const artifact = {
|
|
14749
14856
|
index,
|
|
14750
14857
|
title: titles[index - 1],
|
|
14751
|
-
total: titles.length
|
|
14858
|
+
total: titles.length,
|
|
14859
|
+
...receipts.length ? {
|
|
14860
|
+
completed: receipts.filter(fresh).map((r) => titles.indexOf(r.title) + 1).filter((n) => n > 0)
|
|
14861
|
+
} : {}
|
|
14752
14862
|
};
|
|
14753
14863
|
fs8.writeFileSync(
|
|
14754
14864
|
path8.join(directory, "step.json"),
|
|
@@ -14757,6 +14867,23 @@ function runBuildStep(input) {
|
|
|
14757
14867
|
);
|
|
14758
14868
|
return artifact;
|
|
14759
14869
|
}
|
|
14870
|
+
function workRevision(cwd) {
|
|
14871
|
+
const git2 = (...args) => execFileSync("git", args, {
|
|
14872
|
+
cwd,
|
|
14873
|
+
encoding: "utf8",
|
|
14874
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
14875
|
+
});
|
|
14876
|
+
try {
|
|
14877
|
+
const hash = createHash2("sha256").update(git2("rev-parse", "HEAD")).update(git2("diff", "HEAD", "--", ".", ":!.athena/evidence"));
|
|
14878
|
+
for (const name of git2("ls-files", "--others", "--exclude-standard", "-z").split("\0").filter(Boolean).sort()) {
|
|
14879
|
+
if (name.startsWith(".athena/evidence/")) continue;
|
|
14880
|
+
hash.update(name).update(fs8.readFileSync(path8.join(cwd, name)));
|
|
14881
|
+
}
|
|
14882
|
+
return hash.digest("hex");
|
|
14883
|
+
} catch {
|
|
14884
|
+
throw new BuildUsageError("Evidence must be recorded in a git worktree.");
|
|
14885
|
+
}
|
|
14886
|
+
}
|
|
14760
14887
|
|
|
14761
14888
|
// src/core/build/merged.ts
|
|
14762
14889
|
import fs9 from "fs";
|
|
@@ -14816,17 +14943,20 @@ function runBuildMerged(input) {
|
|
|
14816
14943
|
var USAGE3 = `Usage: drisp build plan --input <path>
|
|
14817
14944
|
drisp build tick --input <path> [--rebase-failed <IDENTIFIER>]...
|
|
14818
14945
|
drisp build checks
|
|
14819
|
-
drisp build step <n> [--qa none|web|macos]
|
|
14946
|
+
drisp build step <n> [--qa none|web|macos|both] [--profile implementation|documentation|investigation]
|
|
14947
|
+
[--test-first true|false] [--review true|false] [--complete --evidence <file>] [--verify]
|
|
14820
14948
|
drisp build merged [<pr url or number>]
|
|
14821
14949
|
plan and tick run inside an Orchestrator Run (DRISP_RUN_ID, DRISP_RUNNER_ID and DRISP_RUN_ARTIFACTS set; tick also
|
|
14822
14950
|
DRISP_RUN_TOKEN and DRISP_HUB_URL). DRISP_BUILD_PLAN_INPUT=<path> stands in for plan's --input, with
|
|
14823
14951
|
fills/<IDENTIFIER>.json beside it. checks runs in a child's worktree: the merge gate's verdict on HEAD's GitHub runs.
|
|
14824
14952
|
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
|
|
14953
|
+
selected build-child profile (QA is a gate unless --qa none) and refuses an index outside the list.
|
|
14954
|
+
--complete --evidence <file> records an agent attestation bound to the source revision; --verify requires fresh
|
|
14955
|
+
receipts for all preceding steps. Keep evidence files under .athena/evidence/.
|
|
14826
14956
|
merged runs in a child's worktree after its pull request merged: it writes the pull_request artifact
|
|
14827
14957
|
{url, number, sha, mergedAt} and refuses a pull request that is not merged.`;
|
|
14828
14958
|
function githubPullRequests(folder, branch) {
|
|
14829
|
-
const output =
|
|
14959
|
+
const output = execFileSync2(
|
|
14830
14960
|
"gh",
|
|
14831
14961
|
[
|
|
14832
14962
|
"pr",
|
|
@@ -14865,7 +14995,7 @@ function hostCapabilities(folder) {
|
|
|
14865
14995
|
}
|
|
14866
14996
|
var defaultChecks = {
|
|
14867
14997
|
head: (cwd) => git(cwd, ["rev-parse", "HEAD"]),
|
|
14868
|
-
gh: (args, cwd) =>
|
|
14998
|
+
gh: (args, cwd) => execFileSync2("gh", args, {
|
|
14869
14999
|
cwd,
|
|
14870
15000
|
encoding: "utf8",
|
|
14871
15001
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -14954,6 +15084,13 @@ async function runBuildCommand(input) {
|
|
|
14954
15084
|
output = runBuildStep({
|
|
14955
15085
|
env: env2,
|
|
14956
15086
|
n: input.positional?.[0],
|
|
15087
|
+
cwd: input.cwd,
|
|
15088
|
+
profile: input.flags.profile,
|
|
15089
|
+
testFirst: input.flags.testFirst,
|
|
15090
|
+
review: input.flags.review,
|
|
15091
|
+
complete: input.flags.complete,
|
|
15092
|
+
verify: input.flags.verify,
|
|
15093
|
+
evidence: input.flags.evidence,
|
|
14957
15094
|
...input.flags.qa ? { qa: input.flags.qa } : {}
|
|
14958
15095
|
});
|
|
14959
15096
|
break;
|
|
@@ -14978,7 +15115,7 @@ ${USAGE3}
|
|
|
14978
15115
|
import process7 from "process";
|
|
14979
15116
|
|
|
14980
15117
|
// src/harnesses/claude/system/doctorEnvironment.ts
|
|
14981
|
-
import { execFileSync as
|
|
15118
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
14982
15119
|
import * as fs10 from "fs";
|
|
14983
15120
|
import * as os4 from "os";
|
|
14984
15121
|
import * as path10 from "path";
|
|
@@ -15056,7 +15193,7 @@ function readEnforcement(scopes) {
|
|
|
15056
15193
|
}
|
|
15057
15194
|
function tryRichAuth(claudeBinary) {
|
|
15058
15195
|
try {
|
|
15059
|
-
const output =
|
|
15196
|
+
const output = execFileSync3(claudeBinary, ["auth", "status"], {
|
|
15060
15197
|
timeout: 1e4,
|
|
15061
15198
|
encoding: "utf-8",
|
|
15062
15199
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -15789,7 +15926,7 @@ var cli = meow(
|
|
|
15789
15926
|
build plan --input <path> Plan a Build inside an Orchestrator Run (prints one JSON object)
|
|
15790
15927
|
build tick --input <path> Run one step of a started Build (prints the next action; [--rebase-failed <ID>]...)
|
|
15791
15928
|
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])
|
|
15929
|
+
build step <n> Report the Run's current step: writes the step run artifact ([--qa none|web|macos|both], --profile, --complete --evidence, --verify)
|
|
15793
15930
|
build merged Record the merged pull request: writes the pull_request run artifact
|
|
15794
15931
|
telemetry [action] Manage anonymous telemetry (enable/disable/status)
|
|
15795
15932
|
doctor Diagnose Claude headless setup (use with --harness=claude)
|
|
@@ -15928,6 +16065,12 @@ var cli = meow(
|
|
|
15928
16065
|
type: "string",
|
|
15929
16066
|
isMultiple: true
|
|
15930
16067
|
},
|
|
16068
|
+
profile: { type: "string" },
|
|
16069
|
+
testFirst: { type: "string" },
|
|
16070
|
+
review: { type: "string" },
|
|
16071
|
+
complete: { type: "boolean" },
|
|
16072
|
+
verify: { type: "boolean" },
|
|
16073
|
+
evidence: { type: "string" },
|
|
15931
16074
|
qa: {
|
|
15932
16075
|
type: "string"
|
|
15933
16076
|
},
|
|
@@ -16024,7 +16167,7 @@ Available commands: ${[...KNOWN_COMMANDS].join(", ")}`
|
|
|
16024
16167
|
await exitWith(1);
|
|
16025
16168
|
return;
|
|
16026
16169
|
}
|
|
16027
|
-
const { default: WorkflowInstallWizard } = await import("./WorkflowInstallWizard-
|
|
16170
|
+
const { default: WorkflowInstallWizard } = await import("./WorkflowInstallWizard-VVEEJW25.js");
|
|
16028
16171
|
const { waitUntilExit } = render(
|
|
16029
16172
|
/* @__PURE__ */ jsx24(
|
|
16030
16173
|
WorkflowInstallWizard,
|
|
@@ -16110,6 +16253,12 @@ Available commands: ${[...KNOWN_COMMANDS].join(", ")}`
|
|
|
16110
16253
|
positional: buildArgs,
|
|
16111
16254
|
flags: {
|
|
16112
16255
|
...typeof cli.flags.qa === "string" ? { qa: cli.flags.qa } : {},
|
|
16256
|
+
profile: cli.flags.profile,
|
|
16257
|
+
testFirst: cli.flags.testFirst,
|
|
16258
|
+
review: cli.flags.review,
|
|
16259
|
+
complete: cli.flags.complete,
|
|
16260
|
+
verify: cli.flags.verify,
|
|
16261
|
+
evidence: cli.flags.evidence,
|
|
16113
16262
|
...typeof cli.flags.input === "string" ? { input: cli.flags.input } : {},
|
|
16114
16263
|
...cli.flags.rebaseFailed?.length ? { rebaseFailed: cli.flags.rebaseFailed } : {}
|
|
16115
16264
|
},
|
package/dist/dashboard-daemon.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "./chunk-
|
|
2
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-D5VZT7M3.js";
|
|
2
|
+
import "./chunk-D246FR4I.js";
|
|
3
3
|
import "./chunk-PQIB66SG.js";
|
|
4
|
-
import "./chunk-
|
|
4
|
+
import "./chunk-HZ6GRLOM.js";
|
|
5
5
|
import "./chunk-G3PMV62Z.js";
|
|
6
6
|
//# sourceMappingURL=dashboard-daemon.js.map
|
package/dist/runner.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "./chunk-
|
|
2
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-D5VZT7M3.js";
|
|
2
|
+
import "./chunk-D246FR4I.js";
|
|
3
3
|
import "./chunk-PQIB66SG.js";
|
|
4
|
-
import "./chunk-
|
|
4
|
+
import "./chunk-HZ6GRLOM.js";
|
|
5
5
|
import "./chunk-G3PMV62Z.js";
|
|
6
6
|
//# sourceMappingURL=runner.js.map
|