@drisp/cli 0.7.1 → 0.7.3
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-BVWAIVBH.js → WorkflowInstallWizard-AJYDKFDL.js} +2 -2
- package/dist/{chunk-CPU4RLSW.js → chunk-6HOVFCCB.js} +67 -19
- package/dist/{chunk-LCT645C4.js → chunk-7R3HR7VJ.js} +2 -2
- package/dist/{chunk-TRNUPQQJ.js → chunk-TSIMXPJN.js} +10 -6
- package/dist/cli.js +20 -6
- 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-TSIMXPJN.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-AJYDKFDL.js.map
|
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
verifyRendered,
|
|
56
56
|
wakesFreshAfterHandover,
|
|
57
57
|
workflowRegistryDir
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-TSIMXPJN.js";
|
|
59
59
|
import {
|
|
60
60
|
__commonJS,
|
|
61
61
|
__toESM
|
|
@@ -3487,6 +3487,7 @@ function createTokenAccumulator() {
|
|
|
3487
3487
|
let openingContextSize = 0;
|
|
3488
3488
|
let contextWindowSize = null;
|
|
3489
3489
|
let hasMessageUsage = false;
|
|
3490
|
+
const countedById = /* @__PURE__ */ new Map();
|
|
3490
3491
|
function promptSize(usage) {
|
|
3491
3492
|
return (usage.input_tokens ?? 0) + (usage.cache_read_input_tokens ?? 0) + (usage.cache_creation_input_tokens ?? 0);
|
|
3492
3493
|
}
|
|
@@ -3544,10 +3545,13 @@ function createTokenAccumulator() {
|
|
|
3544
3545
|
}
|
|
3545
3546
|
} else {
|
|
3546
3547
|
hasMessageUsage = true;
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3548
|
+
const messageId = isAssistantEnvelope ? parsed.message["id"] : parsed["id"];
|
|
3549
|
+
const counted = typeof messageId === "string" ? countedById.get(messageId) : void 0;
|
|
3550
|
+
inputTokens += (usage.input_tokens ?? 0) - (counted?.input_tokens ?? 0);
|
|
3551
|
+
outputTokens += (usage.output_tokens ?? 0) - (counted?.output_tokens ?? 0);
|
|
3552
|
+
cacheRead += (usage.cache_read_input_tokens ?? 0) - (counted?.cache_read_input_tokens ?? 0);
|
|
3553
|
+
cacheWrite += (usage.cache_creation_input_tokens ?? 0) - (counted?.cache_creation_input_tokens ?? 0);
|
|
3554
|
+
if (typeof messageId === "string") countedById.set(messageId, usage);
|
|
3551
3555
|
if (!isSubagent) {
|
|
3552
3556
|
observeRootContext(promptSize(usage));
|
|
3553
3557
|
}
|
|
@@ -3601,6 +3605,7 @@ function createTokenAccumulator() {
|
|
|
3601
3605
|
reset() {
|
|
3602
3606
|
buffer = "";
|
|
3603
3607
|
hasMessageUsage = false;
|
|
3608
|
+
countedById.clear();
|
|
3604
3609
|
inputTokens = 0;
|
|
3605
3610
|
outputTokens = 0;
|
|
3606
3611
|
cacheRead = 0;
|
|
@@ -14868,7 +14873,7 @@ async function restoreCheckpoint(store, input) {
|
|
|
14868
14873
|
|
|
14869
14874
|
// ../../modules/runtime/src/software-version.ts
|
|
14870
14875
|
import "fs";
|
|
14871
|
-
var runnerSoftwareVersion = true ? "0.7.
|
|
14876
|
+
var runnerSoftwareVersion = true ? "0.7.3" : JSON.parse(readFileSync2(new URL("../../../apps/cli/package.json", import.meta.url), "utf8")).version;
|
|
14872
14877
|
|
|
14873
14878
|
// ../../modules/runtime/src/connection.ts
|
|
14874
14879
|
var RunnerDisconnectedError = class extends Error {
|
|
@@ -20125,7 +20130,7 @@ function sessionStore(store, runId, options = {}) {
|
|
|
20125
20130
|
|
|
20126
20131
|
// ../../modules/runtime/src/workflow-executor.ts
|
|
20127
20132
|
import { execFileSync as execFileSync9 } from "child_process";
|
|
20128
|
-
import { statSync as
|
|
20133
|
+
import { statSync as statSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
20129
20134
|
import { join as join8 } from "path";
|
|
20130
20135
|
|
|
20131
20136
|
// src/core/build/workspace.ts
|
|
@@ -20393,8 +20398,20 @@ import { readFileSync as readFileSync3, realpathSync as realpathSync3 } from "fs
|
|
|
20393
20398
|
import { join as join6, relative as relative3 } from "path";
|
|
20394
20399
|
|
|
20395
20400
|
// src/core/build/answer.ts
|
|
20401
|
+
var GUIDANCE_ROUNDS = 10;
|
|
20402
|
+
function approvalAnswer(value) {
|
|
20403
|
+
if (typeof value === "string")
|
|
20404
|
+
return value.trim() === "" ? { kind: "none" } : { kind: "guidance", guidance: value.trim() };
|
|
20405
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value) && Object.keys(value).length === 1 && value.choice === "start")
|
|
20406
|
+
return { kind: "start" };
|
|
20407
|
+
return { kind: "none" };
|
|
20408
|
+
}
|
|
20396
20409
|
function isStartAnswer(value) {
|
|
20397
|
-
return
|
|
20410
|
+
return approvalAnswer(value).kind === "start";
|
|
20411
|
+
}
|
|
20412
|
+
function mergeGuidance(earlier, guidance) {
|
|
20413
|
+
const rounds = earlier.at(-1) === guidance ? earlier : [...earlier, guidance];
|
|
20414
|
+
return rounds.slice(-GUIDANCE_ROUNDS);
|
|
20398
20415
|
}
|
|
20399
20416
|
|
|
20400
20417
|
// src/core/build/planner.ts
|
|
@@ -21148,20 +21165,22 @@ async function closeOrphanedRuns(store, {
|
|
|
21148
21165
|
|
|
21149
21166
|
// ../../modules/runtime/src/run-artifacts.ts
|
|
21150
21167
|
import { createHash as createHash3 } from "crypto";
|
|
21151
|
-
import { mkdirSync as mkdirSync2, readdirSync as readdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
21168
|
+
import { mkdirSync as mkdirSync2, readdirSync as readdirSync2, readFileSync as readFileSync4, statSync as statSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
21152
21169
|
import { tmpdir as tmpdir5 } from "os";
|
|
21153
21170
|
import { dirname as dirname4, join as join7 } from "path";
|
|
21154
21171
|
var ARTIFACT_MAX_BYTES = 64 * 1024;
|
|
21155
21172
|
var ARTIFACT_NAME = /^[a-z][a-z0-9_]{0,63}$/;
|
|
21156
21173
|
var NEVER_EMITTED = /* @__PURE__ */ new Set(["answer"]);
|
|
21157
21174
|
var EMITTED_STATE = ".emitted.json";
|
|
21175
|
+
var MID_TURN_MAX_BYTES = 1024 * 1024;
|
|
21176
|
+
var MID_TURN_MIN_GAP_MS = 5e3;
|
|
21158
21177
|
function runnerDataDirectory(databasePath) {
|
|
21159
21178
|
return databasePath && databasePath !== ":memory:" ? dirname4(databasePath) : join7(tmpdir5(), "drisp-runner");
|
|
21160
21179
|
}
|
|
21161
21180
|
function runArtifactsDirectory(dataDirectory, runId) {
|
|
21162
21181
|
return join7(dataDirectory, "artifacts", runId) + "/";
|
|
21163
21182
|
}
|
|
21164
|
-
function runArtifactEmitter(directory, record) {
|
|
21183
|
+
function runArtifactEmitter(directory, record, midTurnMinGapMs = MID_TURN_MIN_GAP_MS) {
|
|
21165
21184
|
mkdirSync2(directory, { recursive: true, mode: 448 });
|
|
21166
21185
|
const statePath = join7(directory, EMITTED_STATE);
|
|
21167
21186
|
let emitted = {};
|
|
@@ -21169,27 +21188,43 @@ function runArtifactEmitter(directory, record) {
|
|
|
21169
21188
|
emitted = JSON.parse(readFileSync4(statePath, "utf8"));
|
|
21170
21189
|
} catch {
|
|
21171
21190
|
}
|
|
21172
|
-
|
|
21191
|
+
const lastEmittedAt = {};
|
|
21192
|
+
return (midTurn = false) => {
|
|
21173
21193
|
let changed = false;
|
|
21194
|
+
const now = Date.now();
|
|
21174
21195
|
for (const entry of readdirSync2(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
21175
21196
|
if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
|
|
21176
21197
|
const name = entry.name.slice(0, -".json".length);
|
|
21177
21198
|
if (!ARTIFACT_NAME.test(name) || NEVER_EMITTED.has(name)) continue;
|
|
21178
|
-
const
|
|
21199
|
+
const path23 = join7(directory, entry.name);
|
|
21200
|
+
let bytes;
|
|
21201
|
+
try {
|
|
21202
|
+
if (midTurn) {
|
|
21203
|
+
if (statSync2(path23).size > MID_TURN_MAX_BYTES) continue;
|
|
21204
|
+
if (now - (lastEmittedAt[name] ?? -Infinity) < midTurnMinGapMs) continue;
|
|
21205
|
+
}
|
|
21206
|
+
bytes = readFileSync4(path23);
|
|
21207
|
+
} catch {
|
|
21208
|
+
continue;
|
|
21209
|
+
}
|
|
21179
21210
|
const hash = createHash3("sha256").update(bytes).digest("hex");
|
|
21180
21211
|
if (emitted[name] === hash) continue;
|
|
21181
|
-
emitted[name] = hash;
|
|
21182
|
-
changed = true;
|
|
21183
21212
|
let json;
|
|
21184
21213
|
try {
|
|
21185
21214
|
json = JSON.parse(bytes.toString("utf8"));
|
|
21186
21215
|
} catch {
|
|
21216
|
+
if (midTurn) continue;
|
|
21187
21217
|
record("run.artifact_rejected", { name, bytes: bytes.length });
|
|
21218
|
+
emitted[name] = hash;
|
|
21219
|
+
changed = true;
|
|
21188
21220
|
continue;
|
|
21189
21221
|
}
|
|
21190
21222
|
const serialized = Buffer.byteLength(JSON.stringify(json));
|
|
21191
21223
|
if (serialized > ARTIFACT_MAX_BYTES) record("run.artifact_rejected", { name, bytes: serialized });
|
|
21192
21224
|
else record("run.artifact", { name, json });
|
|
21225
|
+
emitted[name] = hash;
|
|
21226
|
+
lastEmittedAt[name] = now;
|
|
21227
|
+
changed = true;
|
|
21193
21228
|
}
|
|
21194
21229
|
if (changed) writeFileSync3(statePath, JSON.stringify(emitted));
|
|
21195
21230
|
};
|
|
@@ -21225,7 +21260,7 @@ function delegationEnvironment(grant, hubUrl) {
|
|
|
21225
21260
|
function requireProjectDirectory(projectDir) {
|
|
21226
21261
|
let directory = false;
|
|
21227
21262
|
try {
|
|
21228
|
-
directory =
|
|
21263
|
+
directory = statSync3(projectDir).isDirectory();
|
|
21229
21264
|
} catch {
|
|
21230
21265
|
}
|
|
21231
21266
|
if (!directory)
|
|
@@ -21316,7 +21351,7 @@ function createWorkflowExecutor(dependencies = {}) {
|
|
|
21316
21351
|
dependencies.dataDirectory ?? runnerDataDirectory(store.sql.database.name),
|
|
21317
21352
|
grant.runId
|
|
21318
21353
|
);
|
|
21319
|
-
const emitArtifacts2 = runArtifactEmitter(artifacts, record);
|
|
21354
|
+
const emitArtifacts2 = runArtifactEmitter(artifacts, record, (dependencies.artifactIntervalMs ?? 2e3) * 2.5);
|
|
21320
21355
|
const loop = bootstrapped.workflow?.loop;
|
|
21321
21356
|
const childLoop = grant.parent && loop ? { ...loop, maxRunTokens: Math.min(loop.maxRunTokens ?? Infinity, grant.parent.tokenCap) } : loop;
|
|
21322
21357
|
const config2 = {
|
|
@@ -21360,6 +21395,8 @@ function createWorkflowExecutor(dependencies = {}) {
|
|
|
21360
21395
|
record(APPROVAL_ANSWERED, { answer: continuation.answer, plan: pending2.plan });
|
|
21361
21396
|
}
|
|
21362
21397
|
}
|
|
21398
|
+
const guidedPlan = continuation?.kind === "resume" && continuation.guidance?.trim() && pendingApproval(store, grant.runId) ? continuation.guidance : void 0;
|
|
21399
|
+
if (guidedPlan !== void 0) writeFileSync4(join8(artifacts, "answer.json"), JSON.stringify(guidedPlan));
|
|
21363
21400
|
let storedAnswer2;
|
|
21364
21401
|
if (continuation?.kind === "answer") {
|
|
21365
21402
|
const answer = permissionAnswerSchema.safeParse(continuation.answer);
|
|
@@ -21373,7 +21410,9 @@ function createWorkflowExecutor(dependencies = {}) {
|
|
|
21373
21410
|
};
|
|
21374
21411
|
}
|
|
21375
21412
|
}
|
|
21376
|
-
let prompt2 =
|
|
21413
|
+
let prompt2 = guidedPlan !== void 0 ? `The member wrote this before starting the Build, to change the plan:
|
|
21414
|
+
${guidedPlan}
|
|
21415
|
+
Run \`drisp build tick\` as in your later-wake instructions and act on its action.` : continuation?.kind === "resume" ? continuation.guidance ?? "Continue the parked workflow." : continuation?.kind === "answer" ? `Human answer to the parked interruption:
|
|
21377
21416
|
${JSON.stringify(continuation.answer)}` : grant.spec.prompt;
|
|
21378
21417
|
const displayText2 = continuation?.kind === "resume" ? continuation.guidance : continuation?.kind === "answer" ? typeof continuation.answer === "string" ? continuation.answer : JSON.stringify(continuation.answer) : grant.spec.prompt;
|
|
21379
21418
|
if (grant.previousRun) {
|
|
@@ -21403,6 +21442,13 @@ ${prompt2}`;
|
|
|
21403
21442
|
const { workingDirectory, config, view, adapterResumeSessionId, storedAnswer, prompt, displayText, emitArtifacts } = setup2;
|
|
21404
21443
|
const queue = createSteerQueue();
|
|
21405
21444
|
queues.set(grant.runId, queue);
|
|
21445
|
+
const sweep = setInterval(() => {
|
|
21446
|
+
try {
|
|
21447
|
+
emitArtifacts(true);
|
|
21448
|
+
} catch {
|
|
21449
|
+
}
|
|
21450
|
+
}, dependencies.artifactIntervalMs ?? 2e3);
|
|
21451
|
+
sweep.unref();
|
|
21406
21452
|
const result = await trackHarnessProcesses(store, grant.runId, () => (dependencies.execute ?? runExec)({
|
|
21407
21453
|
prompt,
|
|
21408
21454
|
promptPresentation: displayText === void 0 ? { origin: "workflow" } : { origin: "human", displayText },
|
|
@@ -21440,6 +21486,7 @@ ${prompt2}`;
|
|
|
21440
21486
|
json: false
|
|
21441
21487
|
})).finally(() => {
|
|
21442
21488
|
queues.delete(grant.runId);
|
|
21489
|
+
clearInterval(sweep);
|
|
21443
21490
|
emitArtifacts();
|
|
21444
21491
|
});
|
|
21445
21492
|
if (!result.workflowOutcome)
|
|
@@ -21862,7 +21909,8 @@ export {
|
|
|
21862
21909
|
commitBuildFiles,
|
|
21863
21910
|
lastCommitTouching,
|
|
21864
21911
|
repoLayoutAt,
|
|
21865
|
-
|
|
21912
|
+
approvalAnswer,
|
|
21913
|
+
mergeGuidance,
|
|
21866
21914
|
planBuild,
|
|
21867
21915
|
finalizePlan,
|
|
21868
21916
|
fallbackBranch,
|
|
@@ -21887,4 +21935,4 @@ export {
|
|
|
21887
21935
|
runMachineRunners,
|
|
21888
21936
|
writeIdentityOnce
|
|
21889
21937
|
};
|
|
21890
|
-
//# sourceMappingURL=chunk-
|
|
21938
|
+
//# sourceMappingURL=chunk-6HOVFCCB.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runMachineRunners
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6HOVFCCB.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-7R3HR7VJ.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 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`),\nthen 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- `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';
|
|
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`),\nthen 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";
|
|
@@ -22322,6 +22322,10 @@ import path10 from "path";
|
|
|
22322
22322
|
// src/core/workflows/continuationPolicy.ts
|
|
22323
22323
|
var DEFAULT_RESTART_TOKENS = 2e3;
|
|
22324
22324
|
var DEFAULT_WORKING_TOKENS = 8e3;
|
|
22325
|
+
function budgetTokens(memory) {
|
|
22326
|
+
if (memory.cumulativeTokens === null) return null;
|
|
22327
|
+
return Math.max(0, memory.cumulativeTokens - (memory.usage?.cacheRead ?? 0));
|
|
22328
|
+
}
|
|
22325
22329
|
function resourceInterruption(stop) {
|
|
22326
22330
|
const names2 = {
|
|
22327
22331
|
tokens: "token budget",
|
|
@@ -23302,7 +23306,7 @@ function admitResult(result, previous, cfg) {
|
|
|
23302
23306
|
const stop = admitContinuation({
|
|
23303
23307
|
loop: cfg.loop,
|
|
23304
23308
|
iteration: memory.iteration,
|
|
23305
|
-
tokens: memory
|
|
23309
|
+
tokens: budgetTokens(memory),
|
|
23306
23310
|
checkpointPath: memory.checkpoint?.path,
|
|
23307
23311
|
context: fresh ? context : void 0
|
|
23308
23312
|
});
|
|
@@ -23750,7 +23754,7 @@ function createWorkflowRunner(input2) {
|
|
|
23750
23754
|
cumulativeTokens: total,
|
|
23751
23755
|
stop: {
|
|
23752
23756
|
...event.stop,
|
|
23753
|
-
...event.stop.cause === "tokens" ? { used: total } : {}
|
|
23757
|
+
...event.stop.cause === "tokens" ? { used: budgetTokens(memory) ?? total } : {}
|
|
23754
23758
|
}
|
|
23755
23759
|
};
|
|
23756
23760
|
}
|
|
@@ -23785,7 +23789,7 @@ function createWorkflowRunner(input2) {
|
|
|
23785
23789
|
const limit = admitContinuation({
|
|
23786
23790
|
loop,
|
|
23787
23791
|
iteration: memory.iteration,
|
|
23788
|
-
tokens: memory
|
|
23792
|
+
tokens: budgetTokens(memory)
|
|
23789
23793
|
});
|
|
23790
23794
|
if (limit) {
|
|
23791
23795
|
stop(limit);
|
|
@@ -23802,7 +23806,7 @@ function createWorkflowRunner(input2) {
|
|
|
23802
23806
|
const decision = admitContinuation({
|
|
23803
23807
|
loop,
|
|
23804
23808
|
iteration: memory.iteration,
|
|
23805
|
-
tokens: memory
|
|
23809
|
+
tokens: budgetTokens(memory),
|
|
23806
23810
|
context: {
|
|
23807
23811
|
opening: usage.openingContextSize,
|
|
23808
23812
|
required: required2,
|
|
@@ -24247,4 +24251,4 @@ export {
|
|
|
24247
24251
|
compileWorkflowPlan,
|
|
24248
24252
|
collectMcpServersWithOptions
|
|
24249
24253
|
};
|
|
24250
|
-
//# sourceMappingURL=chunk-
|
|
24254
|
+
//# sourceMappingURL=chunk-TSIMXPJN.js.map
|
package/dist/cli.js
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
PORTABLE_PROVIDER_ENV_VARS,
|
|
9
9
|
RUN_EXIT_CODE,
|
|
10
10
|
ServiceNotEnabledError,
|
|
11
|
+
approvalAnswer,
|
|
11
12
|
attachRuntimeEventLoop,
|
|
12
13
|
behindMain,
|
|
13
14
|
bootstrapRuntimeConfig,
|
|
@@ -70,7 +71,6 @@ import {
|
|
|
70
71
|
isCommandPrefix,
|
|
71
72
|
isGitHubRepository,
|
|
72
73
|
isScopedPermissionsRequest,
|
|
73
|
-
isStartAnswer,
|
|
74
74
|
lastCommitTouching,
|
|
75
75
|
listAwaitingAttentionRuns,
|
|
76
76
|
listHarnessAdapters,
|
|
@@ -82,6 +82,7 @@ import {
|
|
|
82
82
|
machineInstallationId,
|
|
83
83
|
makeSkippedProbe,
|
|
84
84
|
mergeFeedItems,
|
|
85
|
+
mergeGuidance,
|
|
85
86
|
messageGlyphs,
|
|
86
87
|
overriddenIdentityPath,
|
|
87
88
|
parseFrontmatter,
|
|
@@ -138,7 +139,7 @@ import {
|
|
|
138
139
|
visualPositionToOffset,
|
|
139
140
|
wrapText,
|
|
140
141
|
writeIdentityOnce
|
|
141
|
-
} from "./chunk-
|
|
142
|
+
} from "./chunk-6HOVFCCB.js";
|
|
142
143
|
import {
|
|
143
144
|
generateId as generateId2
|
|
144
145
|
} from "./chunk-PQIB66SG.js";
|
|
@@ -196,7 +197,7 @@ import {
|
|
|
196
197
|
workflowRegistryDir,
|
|
197
198
|
writeGlobalConfig,
|
|
198
199
|
writeProjectConfig
|
|
199
|
-
} from "./chunk-
|
|
200
|
+
} from "./chunk-TSIMXPJN.js";
|
|
200
201
|
import {
|
|
201
202
|
__toESM
|
|
202
203
|
} from "./chunk-G3PMV62Z.js";
|
|
@@ -14411,6 +14412,16 @@ var notStarted = () => ({
|
|
|
14411
14412
|
action: "complete",
|
|
14412
14413
|
message: BUILD_STRINGS.notStarted
|
|
14413
14414
|
});
|
|
14415
|
+
var guidanceFile = (artifacts) => path7.join(artifacts, "input", "guidance.json");
|
|
14416
|
+
function replan(artifacts, guidance) {
|
|
14417
|
+
const earlier = readJson(guidanceFile(artifacts));
|
|
14418
|
+
const rounds = mergeGuidance(
|
|
14419
|
+
Array.isArray(earlier) ? earlier.filter((round) => typeof round === "string") : [],
|
|
14420
|
+
guidance
|
|
14421
|
+
);
|
|
14422
|
+
writeFile(guidanceFile(artifacts), json(rounds));
|
|
14423
|
+
return { action: "replan", guidance: rounds };
|
|
14424
|
+
}
|
|
14414
14425
|
function pushBranch(worktree, branch) {
|
|
14415
14426
|
git(worktree, ["push", "--quiet", "origin", `${branch}:${branch}`]);
|
|
14416
14427
|
}
|
|
@@ -14479,8 +14490,11 @@ async function runBuildTick(deps) {
|
|
|
14479
14490
|
if (parsedState.success && parsedState.data.orchestratorRunId === orchestratorRunId) {
|
|
14480
14491
|
stored = parsedState.data;
|
|
14481
14492
|
} else {
|
|
14482
|
-
|
|
14483
|
-
|
|
14493
|
+
const answer = approvalAnswer(
|
|
14494
|
+
readJson(path7.join(artifacts, "answer.json"))
|
|
14495
|
+
);
|
|
14496
|
+
if (answer.kind === "guidance") return replan(artifacts, answer.guidance);
|
|
14497
|
+
if (answer.kind !== "start") return notStarted();
|
|
14484
14498
|
stored = {
|
|
14485
14499
|
version: 1,
|
|
14486
14500
|
orchestratorRunId,
|
|
@@ -15939,7 +15953,7 @@ Available commands: ${[...KNOWN_COMMANDS].join(", ")}`
|
|
|
15939
15953
|
await exitWith(1);
|
|
15940
15954
|
return;
|
|
15941
15955
|
}
|
|
15942
|
-
const { default: WorkflowInstallWizard } = await import("./WorkflowInstallWizard-
|
|
15956
|
+
const { default: WorkflowInstallWizard } = await import("./WorkflowInstallWizard-AJYDKFDL.js");
|
|
15943
15957
|
const { waitUntilExit } = render(
|
|
15944
15958
|
/* @__PURE__ */ jsx24(
|
|
15945
15959
|
WorkflowInstallWizard,
|
package/dist/dashboard-daemon.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "./chunk-
|
|
2
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-7R3HR7VJ.js";
|
|
2
|
+
import "./chunk-6HOVFCCB.js";
|
|
3
3
|
import "./chunk-PQIB66SG.js";
|
|
4
|
-
import "./chunk-
|
|
4
|
+
import "./chunk-TSIMXPJN.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-7R3HR7VJ.js";
|
|
2
|
+
import "./chunk-6HOVFCCB.js";
|
|
3
3
|
import "./chunk-PQIB66SG.js";
|
|
4
|
-
import "./chunk-
|
|
4
|
+
import "./chunk-TSIMXPJN.js";
|
|
5
5
|
import "./chunk-G3PMV62Z.js";
|
|
6
6
|
//# sourceMappingURL=runner.js.map
|