@farmslot/agent-runtime 0.8.1 → 0.9.0
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/CHANGELOG.md +10 -0
- package/README.md +2 -2
- package/bin/farmslot-agent.mjs +3 -43
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/native/affinity.test.d.ts +2 -0
- package/dist/native/affinity.test.d.ts.map +1 -0
- package/dist/native/affinity.test.js +30 -0
- package/dist/native/affinity.test.js.map +1 -0
- package/dist/native/claude.d.ts +11 -0
- package/dist/native/claude.d.ts.map +1 -0
- package/dist/native/claude.js +490 -0
- package/dist/native/claude.js.map +1 -0
- package/dist/native/client.d.ts +21 -0
- package/dist/native/client.d.ts.map +1 -0
- package/dist/native/client.js +106 -0
- package/dist/native/client.js.map +1 -0
- package/dist/native/codex.d.ts +3 -0
- package/dist/native/codex.d.ts.map +1 -0
- package/dist/native/codex.js +266 -0
- package/dist/native/codex.js.map +1 -0
- package/dist/native/durability.test.d.ts +2 -0
- package/dist/native/durability.test.d.ts.map +1 -0
- package/dist/native/durability.test.js +516 -0
- package/dist/native/durability.test.js.map +1 -0
- package/dist/native/host.d.ts +2 -0
- package/dist/native/host.d.ts.map +1 -0
- package/dist/native/host.js +90 -0
- package/dist/native/host.js.map +1 -0
- package/dist/native/index.d.ts +4 -0
- package/dist/native/index.d.ts.map +1 -0
- package/dist/native/index.js +3 -0
- package/dist/native/index.js.map +1 -0
- package/dist/native/ipc.d.ts +49 -0
- package/dist/native/ipc.d.ts.map +1 -0
- package/dist/native/ipc.js +109 -0
- package/dist/native/ipc.js.map +1 -0
- package/dist/native/manager.d.ts +43 -0
- package/dist/native/manager.d.ts.map +1 -0
- package/dist/native/manager.js +510 -0
- package/dist/native/manager.js.map +1 -0
- package/dist/native/process-tree.d.ts +15 -0
- package/dist/native/process-tree.d.ts.map +1 -0
- package/dist/native/process-tree.js +128 -0
- package/dist/native/process-tree.js.map +1 -0
- package/dist/native/process-tree.test.d.ts +2 -0
- package/dist/native/process-tree.test.d.ts.map +1 -0
- package/dist/native/process-tree.test.js +49 -0
- package/dist/native/process-tree.test.js.map +1 -0
- package/dist/native/process.d.ts +34 -0
- package/dist/native/process.d.ts.map +1 -0
- package/dist/native/process.js +223 -0
- package/dist/native/process.js.map +1 -0
- package/dist/native/service.d.ts +7 -0
- package/dist/native/service.d.ts.map +1 -0
- package/dist/native/service.js +117 -0
- package/dist/native/service.js.map +1 -0
- package/dist/native/storage.d.ts +11 -0
- package/dist/native/storage.d.ts.map +1 -0
- package/dist/native/storage.js +102 -0
- package/dist/native/storage.js.map +1 -0
- package/dist/native/supervisor.d.ts +2 -0
- package/dist/native/supervisor.d.ts.map +1 -0
- package/dist/native/supervisor.js +127 -0
- package/dist/native/supervisor.js.map +1 -0
- package/dist/native/types.d.ts +26 -0
- package/dist/native/types.d.ts.map +1 -0
- package/dist/native/types.js +2 -0
- package/dist/native/types.js.map +1 -0
- package/dist/native/workspace-files.d.ts +6 -0
- package/dist/native/workspace-files.d.ts.map +1 -0
- package/dist/native/workspace-files.js +62 -0
- package/dist/native/workspace-files.js.map +1 -0
- package/dist/native/workspace.d.ts +5 -0
- package/dist/native/workspace.d.ts.map +1 -0
- package/dist/native/workspace.js +120 -0
- package/dist/native/workspace.js.map +1 -0
- package/dist/task-init/index.d.ts +66 -0
- package/dist/task-init/index.d.ts.map +1 -0
- package/dist/task-init/index.js +120 -0
- package/dist/task-init/index.js.map +1 -0
- package/dist/task-init/task-document.d.ts +98 -0
- package/dist/task-init/task-document.d.ts.map +1 -0
- package/dist/task-init/task-document.js +184 -0
- package/dist/task-init/task-document.js.map +1 -0
- package/dist/task-init/write.d.ts +48 -0
- package/dist/task-init/write.d.ts.map +1 -0
- package/dist/task-init/write.js +70 -0
- package/dist/task-init/write.js.map +1 -0
- package/package.json +13 -4
- package/scripts/checklist-target.cjs +5 -3
- package/scripts/execution-template-cli.mjs +9 -7
- package/scripts/mark-checklist-step.cjs +1 -1
- package/scripts/task-init-cli.mjs +166 -0
- package/scripts/worker-terminal-contract.cjs +15 -3
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// `task init`: the one producer of a task directory.
|
|
2
|
+
//
|
|
3
|
+
// A harness (or an engineer) calls `taskInit` with what it knows and gets the
|
|
4
|
+
// same TASK.md, CHECKLIST.md, mark, and inputs/ a Farmslot dispatch writes. The
|
|
5
|
+
// gateway composes the same pieces (`renderTemplatePlaceholders`,
|
|
6
|
+
// `buildTaskDocument`, `writeTaskDir`) around its control-plane steps.
|
|
7
|
+
import { randomUUID } from 'node:crypto';
|
|
8
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
9
|
+
import { createRequire } from 'node:module';
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
import { renderTemplatePlaceholders, } from '@farmslot/protocol';
|
|
12
|
+
import { selectExecutionTemplate } from '../execution-template/select.js';
|
|
13
|
+
import { executionTemplateReference, readExecutionTemplateSnapshot, } from '../execution-template/snapshot.js';
|
|
14
|
+
import { buildHandoffMetadata, buildTaskDocument, HANDOFF_INPUT, } from './task-document.js';
|
|
15
|
+
import { writeTaskDir } from './write.js';
|
|
16
|
+
export * from './task-document.js';
|
|
17
|
+
export * from './write.js';
|
|
18
|
+
// The renderer lives in protocol; re-exported so CLI wrappers reach it through the runtime entry.
|
|
19
|
+
export { renderTemplatePlaceholders } from '@farmslot/protocol';
|
|
20
|
+
const require = createRequire(import.meta.url);
|
|
21
|
+
/** Built-in terminal contract for a flow, as the gateway resolves it without project overrides. */
|
|
22
|
+
export function builtinTerminalContract(flow, options = {}) {
|
|
23
|
+
const { resolveWorkerTerminalContract } = require('../../scripts/worker-terminal-contract.cjs');
|
|
24
|
+
return resolveWorkerTerminalContract(null, flow, options);
|
|
25
|
+
}
|
|
26
|
+
export async function taskInit(spec) {
|
|
27
|
+
const selected = selectExecutionTemplate({
|
|
28
|
+
sources: spec.template.sources,
|
|
29
|
+
flow: spec.flow,
|
|
30
|
+
platform: spec.platform,
|
|
31
|
+
runMode: spec.runMode,
|
|
32
|
+
...(spec.domain ? { domain: spec.domain } : {}),
|
|
33
|
+
...(spec.template.explicitId ? { explicitId: spec.template.explicitId } : {}),
|
|
34
|
+
});
|
|
35
|
+
const taskDirLabel = spec.taskDirLabel ?? spec.taskDir;
|
|
36
|
+
const vars = {
|
|
37
|
+
TICKET: spec.task.ticket ?? '',
|
|
38
|
+
TITLE: spec.task.title,
|
|
39
|
+
FLOW: spec.flow,
|
|
40
|
+
MODE: spec.runMode,
|
|
41
|
+
PLATFORM: spec.platform,
|
|
42
|
+
...(spec.domain ? { DOMAIN: spec.domain } : {}),
|
|
43
|
+
TEMPLATE: selected.entry.id,
|
|
44
|
+
TASK_DIR: taskDirLabel,
|
|
45
|
+
...(spec.task.sourceRef
|
|
46
|
+
? /^https?:\/\//.test(spec.task.sourceRef)
|
|
47
|
+
? { TICKET_URL: spec.task.sourceRef }
|
|
48
|
+
: { SOURCE_REF: spec.task.sourceRef }
|
|
49
|
+
: {}),
|
|
50
|
+
...(spec.vars ?? {}),
|
|
51
|
+
};
|
|
52
|
+
const source = `Execution template ${selected.entry.id} (${selected.entry.sourceId})`;
|
|
53
|
+
const checklistMarkdown = renderTemplatePlaceholders(readExecutionTemplateSnapshot(selected.entry).markdown, vars, source);
|
|
54
|
+
const reference = executionTemplateReference(selected.entry, checklistMarkdown);
|
|
55
|
+
const executionTemplate = {
|
|
56
|
+
selectionReason: selected.reason,
|
|
57
|
+
...reference,
|
|
58
|
+
};
|
|
59
|
+
const terminalContract = spec.terminalContract ?? builtinTerminalContract(spec.flow, { mode: spec.runMode });
|
|
60
|
+
const handoffMetadata = buildHandoffMetadata({
|
|
61
|
+
attemptId: spec.handoff.attemptId ?? randomUUID(),
|
|
62
|
+
surface: spec.handoff.surface,
|
|
63
|
+
project: spec.handoff.project,
|
|
64
|
+
flow: spec.flow,
|
|
65
|
+
repo: spec.handoff.repo,
|
|
66
|
+
domain: spec.domain,
|
|
67
|
+
title: spec.task.title,
|
|
68
|
+
sourceKind: spec.task.sourceKind,
|
|
69
|
+
ticket: spec.task.ticket,
|
|
70
|
+
sourceRef: spec.task.sourceRef,
|
|
71
|
+
terminalContract,
|
|
72
|
+
startedAt: spec.handoff.startedAt,
|
|
73
|
+
executionTemplate,
|
|
74
|
+
});
|
|
75
|
+
const taskMarkdown = buildTaskDocument({
|
|
76
|
+
flowType: spec.flow,
|
|
77
|
+
modePreamble: spec.modePreamble ?? '',
|
|
78
|
+
vars,
|
|
79
|
+
description: spec.task.description ?? '',
|
|
80
|
+
acceptanceCriteria: spec.task.acceptanceCriteria ?? [],
|
|
81
|
+
addendum: spec.addendum
|
|
82
|
+
? renderTemplatePlaceholders(spec.addendum, vars, 'Task document addendum')
|
|
83
|
+
: null,
|
|
84
|
+
hasTicketData: spec.bugInput !== undefined,
|
|
85
|
+
});
|
|
86
|
+
const written = await writeTaskDir({
|
|
87
|
+
taskDir: spec.taskDir,
|
|
88
|
+
taskMarkdown,
|
|
89
|
+
checklistMarkdown,
|
|
90
|
+
markCommand: spec.markCommand,
|
|
91
|
+
handoff: handoffMetadata,
|
|
92
|
+
terminalContract,
|
|
93
|
+
bugInput: spec.bugInput,
|
|
94
|
+
});
|
|
95
|
+
return { ...written, executionTemplate, handoffMetadata };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Selected-template provenance for a task dir. Reads `inputs/handoff.json`;
|
|
99
|
+
* falls back to the pre-0.9 `inputs/template-provenance.json` for task dirs
|
|
100
|
+
* written before the merge. Drop the fallback next release.
|
|
101
|
+
*/
|
|
102
|
+
export function readTaskProvenance(taskDir) {
|
|
103
|
+
const handoffPath = path.join(taskDir, HANDOFF_INPUT);
|
|
104
|
+
if (existsSync(handoffPath)) {
|
|
105
|
+
const handoff = JSON.parse(readFileSync(handoffPath, 'utf-8'));
|
|
106
|
+
if (handoff.executionTemplate || handoff.templateProvenance) {
|
|
107
|
+
return {
|
|
108
|
+
...(handoff.executionTemplate ? { executionTemplate: handoff.executionTemplate } : {}),
|
|
109
|
+
...(handoff.templateProvenance ? { templateProvenance: handoff.templateProvenance } : {}),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const legacyPath = path.join(taskDir, 'inputs', 'template-provenance.json');
|
|
114
|
+
if (!existsSync(legacyPath))
|
|
115
|
+
return null;
|
|
116
|
+
const legacy = JSON.parse(readFileSync(legacyPath, 'utf-8'));
|
|
117
|
+
const { executionTemplate, ...templateProvenance } = legacy;
|
|
118
|
+
return { ...(executionTemplate ? { executionTemplate } : {}), templateProvenance };
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/task-init/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { type ExecutionTemplateReference, type TemplateProvenance, type WorkerTerminalContractDocument } from '@farmslot/protocol';
|
|
2
|
+
export declare const HANDOFF_INPUT = "inputs/handoff.json";
|
|
3
|
+
export declare const BUG_INPUT = "inputs/bug-input.json";
|
|
4
|
+
/** Optional project-owned addendum rendered into TASK.md (relative to `templates/`). */
|
|
5
|
+
export declare const TASK_DOCUMENT_ADDENDUM_TEMPLATE = "task-document.md";
|
|
6
|
+
/**
|
|
7
|
+
* Acceptance criteria arrive as plain strings, but ticket adapters keep the
|
|
8
|
+
* author's list markers. Normalize to one bullet per criterion so TASK.md never
|
|
9
|
+
* carries a live `- [ ]` box that could be mistaken for a step.
|
|
10
|
+
*/
|
|
11
|
+
export declare function renderAcceptanceCriteria(items: ReadonlyArray<string>): string;
|
|
12
|
+
export interface TaskDocumentInput {
|
|
13
|
+
flowType: string;
|
|
14
|
+
/** One blockquote line describing the run mode; empty string for none. */
|
|
15
|
+
modePreamble: string;
|
|
16
|
+
vars: Record<string, string>;
|
|
17
|
+
description: string;
|
|
18
|
+
acceptanceCriteria: ReadonlyArray<string>;
|
|
19
|
+
affectedArea?: string;
|
|
20
|
+
screenshotsMarkdown?: string;
|
|
21
|
+
commentsMarkdown?: string;
|
|
22
|
+
linkedTicketsMarkdown?: string;
|
|
23
|
+
linkedDescriptionsMarkdown?: string;
|
|
24
|
+
/** pr-complete: control-plane pre-fetched PR comment summary. */
|
|
25
|
+
commentSummaryMarkdown?: string;
|
|
26
|
+
/** Rendered project addendum (`templates/task-document.md`), if the project ships one. */
|
|
27
|
+
addendum?: string | null;
|
|
28
|
+
hasTicketData: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare function buildTaskDocument(input: TaskDocumentInput): string;
|
|
31
|
+
export declare function readTaskDocumentAddendum(projectTemplatesDir: string): Promise<{
|
|
32
|
+
path: string;
|
|
33
|
+
content: string;
|
|
34
|
+
} | null>;
|
|
35
|
+
export type HandoffSourceKind = 'text' | 'file' | 'github-pr' | 'github-issue' | 'jira';
|
|
36
|
+
/** Selected checklist, as `execution-template materialize --provenance` reports it. */
|
|
37
|
+
export interface HandoffExecutionTemplate extends ExecutionTemplateReference {
|
|
38
|
+
selectionReason: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The one task record. `@farmslot/handoff closeout` reads the identity keys;
|
|
42
|
+
* replay and eval read `executionTemplate` / `templateProvenance`; everything
|
|
43
|
+
* else ignores keys it does not know.
|
|
44
|
+
*/
|
|
45
|
+
export interface HandoffMetadata {
|
|
46
|
+
schemaVersion: 1;
|
|
47
|
+
attemptId: string;
|
|
48
|
+
surface: string;
|
|
49
|
+
project: string;
|
|
50
|
+
repo?: string;
|
|
51
|
+
/** Effective run domain; empty string when none — the closeout parser requires the key. */
|
|
52
|
+
domain: string;
|
|
53
|
+
flow: string;
|
|
54
|
+
startedAt: string;
|
|
55
|
+
task: {
|
|
56
|
+
title: string;
|
|
57
|
+
sourceKind: HandoffSourceKind;
|
|
58
|
+
ticket?: string;
|
|
59
|
+
sourceRef?: string;
|
|
60
|
+
};
|
|
61
|
+
taskDocument: 'TASK.md';
|
|
62
|
+
report: string;
|
|
63
|
+
learnings: string;
|
|
64
|
+
executionTemplate?: HandoffExecutionTemplate;
|
|
65
|
+
/** Control-plane provenance (repo revisions, selection source); never carries the reference twice. */
|
|
66
|
+
templateProvenance?: Omit<TemplateProvenance, 'executionTemplate'>;
|
|
67
|
+
}
|
|
68
|
+
export declare function buildHandoffMetadata(input: {
|
|
69
|
+
attemptId: string;
|
|
70
|
+
surface: string;
|
|
71
|
+
project: string;
|
|
72
|
+
flow: string;
|
|
73
|
+
repo?: string;
|
|
74
|
+
domain?: string;
|
|
75
|
+
title: string;
|
|
76
|
+
sourceKind: HandoffSourceKind;
|
|
77
|
+
ticket?: string;
|
|
78
|
+
sourceRef?: string;
|
|
79
|
+
terminalContract: Pick<WorkerTerminalContractDocument, 'commands'>;
|
|
80
|
+
startedAt?: string;
|
|
81
|
+
executionTemplate?: HandoffExecutionTemplate;
|
|
82
|
+
templateProvenance?: Omit<TemplateProvenance, 'executionTemplate'>;
|
|
83
|
+
}): HandoffMetadata;
|
|
84
|
+
/**
|
|
85
|
+
* `owner/name` from a repository URL or scp-style remote. Undefined when the
|
|
86
|
+
* value is not portable (local path, credentialed URL, odd segments).
|
|
87
|
+
*/
|
|
88
|
+
export declare function portableRepoIdentity(raw: string): string | undefined;
|
|
89
|
+
/**
|
|
90
|
+
* `owner/name` from a project's repository declaration (`repo_url` or `ci.repo`).
|
|
91
|
+
*/
|
|
92
|
+
export declare function portableProjectRepo(projectJson: {
|
|
93
|
+
repo_url?: unknown;
|
|
94
|
+
ci?: {
|
|
95
|
+
repo?: unknown;
|
|
96
|
+
};
|
|
97
|
+
}): string | undefined;
|
|
98
|
+
//# sourceMappingURL=task-document.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-document.d.ts","sourceRoot":"","sources":["../../src/task-init/task-document.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// TASK.md, the task document beside the CHECKLIST.md execution checklist.
|
|
2
|
+
//
|
|
3
|
+
// The execution template renders verbatim into CHECKLIST.md, the only file whose
|
|
4
|
+
// checkboxes count as steps. TASK.md carries the task (description, acceptance
|
|
5
|
+
// criteria, screenshots, comments), the run facts, the mark instructions, and
|
|
6
|
+
// pointers to `inputs/`. One builder serves every surface: a control plane passes
|
|
7
|
+
// its slot facts as extra vars; a harness passes only what it knows.
|
|
8
|
+
import { existsSync } from 'node:fs';
|
|
9
|
+
import { readFile } from 'node:fs/promises';
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
import { EXECUTION_CHECKLIST_DOCUMENT, } from '@farmslot/protocol';
|
|
12
|
+
export const HANDOFF_INPUT = 'inputs/handoff.json';
|
|
13
|
+
export const BUG_INPUT = 'inputs/bug-input.json';
|
|
14
|
+
/** Optional project-owned addendum rendered into TASK.md (relative to `templates/`). */
|
|
15
|
+
export const TASK_DOCUMENT_ADDENDUM_TEMPLATE = 'task-document.md';
|
|
16
|
+
/**
|
|
17
|
+
* Ordered keys of the `## Task` block. A key renders only when the caller set
|
|
18
|
+
* it, except the four every surface knows. Farmslot sets its slot facts; a
|
|
19
|
+
* harness sets FLOW/MODE/TEMPLATE; neither sees blank lines for the other's.
|
|
20
|
+
*/
|
|
21
|
+
const TASK_BLOCK_KEYS = [
|
|
22
|
+
{ key: 'TICKET', required: true },
|
|
23
|
+
{ key: 'TICKET_URL' },
|
|
24
|
+
{ key: 'TITLE', required: true },
|
|
25
|
+
{ key: 'FLOW' },
|
|
26
|
+
{ key: 'MODE' },
|
|
27
|
+
{ key: 'RUN_ID' },
|
|
28
|
+
{ key: 'FAMILY_ID' },
|
|
29
|
+
{ key: 'BRANCH' },
|
|
30
|
+
{ key: 'PR_NUMBER' },
|
|
31
|
+
{ key: 'PR_URL' },
|
|
32
|
+
{ key: 'PR_BRANCH' },
|
|
33
|
+
{ key: 'GH_REPO' },
|
|
34
|
+
{ key: 'PR_INTEGRATION_NOTE', label: 'PR_INTEGRATION' },
|
|
35
|
+
{ key: 'REVIEW_TIER' },
|
|
36
|
+
{ key: 'RECIPE_STRATEGY' },
|
|
37
|
+
{ key: 'BRANCH_UPDATE_STRATEGY' },
|
|
38
|
+
{ key: 'HAS_RECIPE' },
|
|
39
|
+
{ key: 'RECIPE_SOURCE' },
|
|
40
|
+
{ key: 'TASK_DIR', required: true },
|
|
41
|
+
{ key: 'SESSION' },
|
|
42
|
+
{ key: 'REPO' },
|
|
43
|
+
{ key: 'PLATFORM' },
|
|
44
|
+
{ key: 'DOMAIN' },
|
|
45
|
+
{ key: 'TEMPLATE' },
|
|
46
|
+
{ key: 'SLOT_ID' },
|
|
47
|
+
{ key: 'RUNTIME_DIR' },
|
|
48
|
+
{ key: 'WATCHER_PORT' },
|
|
49
|
+
{ key: 'CDP_PORT' },
|
|
50
|
+
{ key: 'IOS_SIMULATOR' },
|
|
51
|
+
{ key: 'ADB_SERIAL' },
|
|
52
|
+
];
|
|
53
|
+
/**
|
|
54
|
+
* Acceptance criteria arrive as plain strings, but ticket adapters keep the
|
|
55
|
+
* author's list markers. Normalize to one bullet per criterion so TASK.md never
|
|
56
|
+
* carries a live `- [ ]` box that could be mistaken for a step.
|
|
57
|
+
*/
|
|
58
|
+
export function renderAcceptanceCriteria(items) {
|
|
59
|
+
const normalized = items
|
|
60
|
+
.map((item) => item
|
|
61
|
+
.split('\n')
|
|
62
|
+
.map((line) => line
|
|
63
|
+
.trim()
|
|
64
|
+
.replace(/^[-*]\s+/, '')
|
|
65
|
+
.replace(/^\[(?: |x|X)\]\s*/, '')
|
|
66
|
+
.trim())
|
|
67
|
+
.filter(Boolean))
|
|
68
|
+
.filter((lines) => lines.length > 0)
|
|
69
|
+
// Continuation lines stay with their criterion, indented so they never start a list item.
|
|
70
|
+
.map(([first, ...rest]) => [`- ${first}`, ...rest.map((line) => ` ${line}`)].join('\n'));
|
|
71
|
+
return normalized.length > 0 ? normalized.join('\n') : '_Not specified_';
|
|
72
|
+
}
|
|
73
|
+
export function buildTaskDocument(input) {
|
|
74
|
+
const { vars } = input;
|
|
75
|
+
const taskDir = vars.TASK_DIR;
|
|
76
|
+
const title = vars.TITLE?.trim() || vars.TICKET || input.flowType;
|
|
77
|
+
const taskBlock = TASK_BLOCK_KEYS.filter(({ key, required }) => required || vars[key]?.trim())
|
|
78
|
+
.map(({ key, label }) => `${label ?? key}: ${vars[key] ?? ''}`)
|
|
79
|
+
.join('\n');
|
|
80
|
+
const sections = [`# ${input.flowType}: ${title}`, ''];
|
|
81
|
+
if (input.modePreamble.trim())
|
|
82
|
+
sections.push(input.modePreamble, '');
|
|
83
|
+
sections.push('## Task', '', '```text', taskBlock, 'STATUS: pending', '```', '', '## Description', '', input.description || '_No description_', '', '## Acceptance Criteria', '', renderAcceptanceCriteria(input.acceptanceCriteria));
|
|
84
|
+
if (input.affectedArea && input.affectedArea !== '_Not specified_') {
|
|
85
|
+
sections.push('', '## Affected Area', '', input.affectedArea);
|
|
86
|
+
}
|
|
87
|
+
if (input.screenshotsMarkdown && input.screenshotsMarkdown !== '_No screenshots_') {
|
|
88
|
+
sections.push('', '## Screenshots', '', input.screenshotsMarkdown);
|
|
89
|
+
}
|
|
90
|
+
if (input.commentsMarkdown && input.commentsMarkdown !== '_No comments_') {
|
|
91
|
+
sections.push('', '## Comments', '', input.commentsMarkdown);
|
|
92
|
+
}
|
|
93
|
+
if (input.linkedTicketsMarkdown && input.linkedTicketsMarkdown !== '_No linked tickets_') {
|
|
94
|
+
sections.push('', '## Linked Tickets', '', input.linkedTicketsMarkdown);
|
|
95
|
+
}
|
|
96
|
+
if (input.linkedDescriptionsMarkdown &&
|
|
97
|
+
input.linkedDescriptionsMarkdown !== '_No linked tickets_') {
|
|
98
|
+
sections.push('', '## Linked Ticket Descriptions', '', input.linkedDescriptionsMarkdown);
|
|
99
|
+
}
|
|
100
|
+
if (input.commentSummaryMarkdown?.trim()) {
|
|
101
|
+
sections.push('', '## Comment Summary', '', input.commentSummaryMarkdown.trim());
|
|
102
|
+
}
|
|
103
|
+
if (input.addendum?.trim()) {
|
|
104
|
+
sections.push('', input.addendum.trim());
|
|
105
|
+
}
|
|
106
|
+
sections.push('', '## Checklist', '', `Follow \`${taskDir}/${EXECUTION_CHECKLIST_DOCUMENT}\` top to bottom. That file is the only checklist that counts.`, `Marker: \`${taskDir}/mark\`, run from the repo root. \`mark start\` once when work begins, \`mark N\` after each step (visible 1-based number), then \`mark complete --mark-last\`, \`mark no-change --reason "…"\`, or \`mark blocked --reason "…"\`.`, 'Never hand-write `SIGNAL.json`. Do not add step checkboxes to this document; update `STATUS` above and append notes (for example `## Recipe ACs`) below.', '', '## Inputs', '', `Under \`${taskDir}/inputs/\`:`, '', `- \`${path.basename(HANDOFF_INPUT)}\` — run identity, selected checklist provenance, and terminal report paths`, '- `worker-terminal-contract.json` — artifacts required before a terminal mark');
|
|
107
|
+
if (input.hasTicketData) {
|
|
108
|
+
sections.push(`- \`${path.basename(BUG_INPUT)}\` — full ticket data as fetched`);
|
|
109
|
+
}
|
|
110
|
+
sections.push('');
|
|
111
|
+
return sections.join('\n');
|
|
112
|
+
}
|
|
113
|
+
export async function readTaskDocumentAddendum(projectTemplatesDir) {
|
|
114
|
+
const addendumPath = path.join(projectTemplatesDir, TASK_DOCUMENT_ADDENDUM_TEMPLATE);
|
|
115
|
+
if (!existsSync(addendumPath))
|
|
116
|
+
return null;
|
|
117
|
+
return { path: addendumPath, content: await readFile(addendumPath, 'utf-8') };
|
|
118
|
+
}
|
|
119
|
+
export function buildHandoffMetadata(input) {
|
|
120
|
+
const complete = input.terminalContract.commands.complete;
|
|
121
|
+
const ticket = input.ticket?.trim();
|
|
122
|
+
const sourceRef = input.sourceRef?.trim();
|
|
123
|
+
return {
|
|
124
|
+
schemaVersion: 1,
|
|
125
|
+
attemptId: input.attemptId,
|
|
126
|
+
surface: input.surface,
|
|
127
|
+
project: input.project,
|
|
128
|
+
...(input.repo ? { repo: input.repo } : {}),
|
|
129
|
+
domain: input.domain ?? '',
|
|
130
|
+
flow: input.flow,
|
|
131
|
+
startedAt: input.startedAt ?? new Date().toISOString(),
|
|
132
|
+
task: {
|
|
133
|
+
title: input.title,
|
|
134
|
+
sourceKind: input.sourceKind,
|
|
135
|
+
...(ticket ? { ticket } : {}),
|
|
136
|
+
...(sourceRef ? { sourceRef } : {}),
|
|
137
|
+
},
|
|
138
|
+
taskDocument: 'TASK.md',
|
|
139
|
+
report: complete?.report ?? 'artifacts/report.md',
|
|
140
|
+
learnings: 'artifacts/learnings.md',
|
|
141
|
+
...(input.executionTemplate ? { executionTemplate: input.executionTemplate } : {}),
|
|
142
|
+
...(input.templateProvenance ? { templateProvenance: input.templateProvenance } : {}),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* `owner/name` from a repository URL or scp-style remote. Undefined when the
|
|
147
|
+
* value is not portable (local path, credentialed URL, odd segments).
|
|
148
|
+
*/
|
|
149
|
+
export function portableRepoIdentity(raw) {
|
|
150
|
+
let pathname;
|
|
151
|
+
try {
|
|
152
|
+
const url = new URL(raw);
|
|
153
|
+
if (!['http:', 'https:', 'ssh:', 'git:'].includes(url.protocol))
|
|
154
|
+
return undefined;
|
|
155
|
+
pathname = url.pathname;
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
const scp = raw.match(/^(?:[^@/\s]+@)?[^:/\s]+:(.+)$/u);
|
|
159
|
+
if (scp)
|
|
160
|
+
pathname = scp[1];
|
|
161
|
+
else if (/^[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)+$/u.test(raw))
|
|
162
|
+
pathname = raw;
|
|
163
|
+
else
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
166
|
+
const identity = pathname.replace(/^\/+|\/+$/gu, '').replace(/\.git$/iu, '');
|
|
167
|
+
const segments = identity.split('/');
|
|
168
|
+
const portable = segments.length > 0 &&
|
|
169
|
+
segments.every((segment) => segment !== '.' && segment !== '..' && /^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(segment));
|
|
170
|
+
return portable ? identity : undefined;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* `owner/name` from a project's repository declaration (`repo_url` or `ci.repo`).
|
|
174
|
+
*/
|
|
175
|
+
export function portableProjectRepo(projectJson) {
|
|
176
|
+
const candidates = [projectJson.repo_url, projectJson.ci?.repo].filter((value) => typeof value === 'string' && value.trim().length > 0);
|
|
177
|
+
for (const candidate of candidates) {
|
|
178
|
+
const identity = portableRepoIdentity(candidate.trim());
|
|
179
|
+
if (identity)
|
|
180
|
+
return identity;
|
|
181
|
+
}
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=task-document.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-document.js","sourceRoot":"","sources":["../../src/task-init/task-document.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type WorkerTerminalContractDocument } from '@farmslot/protocol';
|
|
2
|
+
import { type HandoffMetadata } from './task-document.js';
|
|
3
|
+
export declare const TASK_DOCUMENT = "TASK.md";
|
|
4
|
+
export declare const MARK_SHIM = "mark";
|
|
5
|
+
/** Whole-command env override honoured by every `mark` shim. */
|
|
6
|
+
export declare const MARK_COMMAND_ENV = "FARMSLOT_MARK_CMD";
|
|
7
|
+
/**
|
|
8
|
+
* Quote one word for the shim's default command: double quotes keep spaces
|
|
9
|
+
* together while `$HOME` (a remote slot's home) still expands.
|
|
10
|
+
*/
|
|
11
|
+
export declare function quoteMarkCommandWord(word: string): string;
|
|
12
|
+
/** Generic default: this package's mark engine. A control plane or harness passes its own. */
|
|
13
|
+
export declare function defaultMarkCommand(): string;
|
|
14
|
+
/**
|
|
15
|
+
* The `mark` shim. One env override, one recorded default; `markCommand` is a
|
|
16
|
+
* whole command line and stays unquoted so multi-word commands split and `$HOME`
|
|
17
|
+
* expands on the machine that runs it.
|
|
18
|
+
*/
|
|
19
|
+
export declare function buildMarkShim(markCommand: string): string;
|
|
20
|
+
export interface WriteTaskDirInput {
|
|
21
|
+
/** Absolute task directory; created when missing. */
|
|
22
|
+
taskDir: string;
|
|
23
|
+
taskMarkdown: string;
|
|
24
|
+
/** null when the caller already wrote CHECKLIST.md (lightweight interactive dev). */
|
|
25
|
+
checklistMarkdown: string | null;
|
|
26
|
+
markCommand?: string;
|
|
27
|
+
handoff: HandoffMetadata;
|
|
28
|
+
terminalContract: WorkerTerminalContractDocument;
|
|
29
|
+
/** Ticket data as fetched, written to inputs/bug-input.json when present. */
|
|
30
|
+
bugInput?: unknown;
|
|
31
|
+
/**
|
|
32
|
+
* Transition only: also write `checklist-target.json` with the default target so
|
|
33
|
+
* a mark engine older than 0.9 (which fails closed without it) keeps working on
|
|
34
|
+
* slots not yet redeployed. Absent means the same thing. Remove next release.
|
|
35
|
+
*/
|
|
36
|
+
writeChecklistManifest?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface WrittenTaskDir {
|
|
39
|
+
taskDir: string;
|
|
40
|
+
taskDocument: string;
|
|
41
|
+
checklist: string | null;
|
|
42
|
+
mark: string;
|
|
43
|
+
handoff: string;
|
|
44
|
+
terminalContract: string;
|
|
45
|
+
bugInput: string | null;
|
|
46
|
+
}
|
|
47
|
+
export declare function writeTaskDir(input: WriteTaskDirInput): Promise<WrittenTaskDir>;
|
|
48
|
+
//# sourceMappingURL=write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/task-init/write.ts"],"names":[],"mappings":"AAQA,OAAO,EAIL,KAAK,8BAA8B,EACpC,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAA4B,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEpF,eAAO,MAAM,aAAa,YAAY,CAAC;AACvC,eAAO,MAAM,SAAS,SAAS,CAAC;AAChC,gEAAgE;AAChE,eAAO,MAAM,gBAAgB,sBAAsB,CAAC;AAIpD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,8FAA8F;AAC9F,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAQzD;AAED,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,qFAAqF;IACrF,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,eAAe,CAAC;IACzB,gBAAgB,EAAE,8BAA8B,CAAC;IACjD,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CA8CpF"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// The task-dir writer: the only code that lays out a task directory. A control
|
|
2
|
+
// plane and a harness both call it, so the two surfaces cannot drift.
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
import { chmod, mkdir, writeFile } from 'node:fs/promises';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { CHECKLIST_TARGET_MANIFEST, EXECUTION_CHECKLIST_DOCUMENT, WORKER_TERMINAL_CONTRACT_INPUT, } from '@farmslot/protocol';
|
|
8
|
+
import { BUG_INPUT, HANDOFF_INPUT } from './task-document.js';
|
|
9
|
+
export const TASK_DOCUMENT = 'TASK.md';
|
|
10
|
+
export const MARK_SHIM = 'mark';
|
|
11
|
+
/** Whole-command env override honoured by every `mark` shim. */
|
|
12
|
+
export const MARK_COMMAND_ENV = 'FARMSLOT_MARK_CMD';
|
|
13
|
+
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
14
|
+
/**
|
|
15
|
+
* Quote one word for the shim's default command: double quotes keep spaces
|
|
16
|
+
* together while `$HOME` (a remote slot's home) still expands.
|
|
17
|
+
*/
|
|
18
|
+
export function quoteMarkCommandWord(word) {
|
|
19
|
+
return `"${word.replace(/(["\\`])/g, '\\$1')}"`;
|
|
20
|
+
}
|
|
21
|
+
/** Generic default: this package's mark engine. A control plane or harness passes its own. */
|
|
22
|
+
export function defaultMarkCommand() {
|
|
23
|
+
return `node ${quoteMarkCommandWord(path.join(packageRoot, 'scripts', 'mark-checklist-step.cjs'))}`;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The `mark` shim. One env override, one recorded default; `markCommand` is a
|
|
27
|
+
* whole command line and stays unquoted so multi-word commands split and `$HOME`
|
|
28
|
+
* expands on the machine that runs it.
|
|
29
|
+
*/
|
|
30
|
+
export function buildMarkShim(markCommand) {
|
|
31
|
+
return [
|
|
32
|
+
'#!/usr/bin/env bash',
|
|
33
|
+
'set -euo pipefail',
|
|
34
|
+
'DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"',
|
|
35
|
+
`exec \${${MARK_COMMAND_ENV}:-${markCommand}} "$DIR" "$@"`,
|
|
36
|
+
'',
|
|
37
|
+
].join('\n');
|
|
38
|
+
}
|
|
39
|
+
export async function writeTaskDir(input) {
|
|
40
|
+
const taskDir = path.resolve(input.taskDir);
|
|
41
|
+
await mkdir(path.join(taskDir, 'inputs'), { recursive: true });
|
|
42
|
+
await mkdir(path.join(taskDir, 'artifacts'), { recursive: true });
|
|
43
|
+
const taskDocument = path.join(taskDir, TASK_DOCUMENT);
|
|
44
|
+
await writeFile(taskDocument, input.taskMarkdown, 'utf-8');
|
|
45
|
+
let checklist = null;
|
|
46
|
+
if (input.checklistMarkdown !== null) {
|
|
47
|
+
checklist = path.join(taskDir, EXECUTION_CHECKLIST_DOCUMENT);
|
|
48
|
+
await writeFile(checklist, input.checklistMarkdown, 'utf-8');
|
|
49
|
+
}
|
|
50
|
+
const mark = path.join(taskDir, MARK_SHIM);
|
|
51
|
+
await writeFile(mark, buildMarkShim(input.markCommand ?? defaultMarkCommand()), 'utf-8');
|
|
52
|
+
await chmod(mark, 0o755);
|
|
53
|
+
const handoff = path.join(taskDir, HANDOFF_INPUT);
|
|
54
|
+
await writeFile(handoff, `${JSON.stringify(input.handoff, null, 2)}\n`, 'utf-8');
|
|
55
|
+
const terminalContract = path.join(taskDir, WORKER_TERMINAL_CONTRACT_INPUT);
|
|
56
|
+
await writeFile(terminalContract, `${JSON.stringify(input.terminalContract, null, 2)}\n`, 'utf-8');
|
|
57
|
+
if (input.writeChecklistManifest) {
|
|
58
|
+
const checklistName = existsSync(path.join(taskDir, EXECUTION_CHECKLIST_DOCUMENT))
|
|
59
|
+
? EXECUTION_CHECKLIST_DOCUMENT
|
|
60
|
+
: TASK_DOCUMENT;
|
|
61
|
+
await writeFile(path.join(taskDir, CHECKLIST_TARGET_MANIFEST), `${JSON.stringify({ checklist: checklistName, signal: 'SIGNAL.json' }, null, 2)}\n`, 'utf-8');
|
|
62
|
+
}
|
|
63
|
+
let bugInput = null;
|
|
64
|
+
if (input.bugInput !== undefined) {
|
|
65
|
+
bugInput = path.join(taskDir, BUG_INPUT);
|
|
66
|
+
await writeFile(bugInput, `${JSON.stringify(input.bugInput, null, 2)}\n`, 'utf-8');
|
|
67
|
+
}
|
|
68
|
+
return { taskDir, taskDocument, checklist, mark, handoff, terminalContract, bugInput };
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/task-init/write.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farmslot/agent-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -17,11 +17,20 @@
|
|
|
17
17
|
"./scripts/checklist-target.cjs": "./scripts/checklist-target.cjs",
|
|
18
18
|
"./scripts/worker-terminal-contract.cjs": "./scripts/worker-terminal-contract.cjs",
|
|
19
19
|
"./scripts/check-task-artifact-contract.mjs": "./scripts/check-task-artifact-contract.mjs",
|
|
20
|
-
"./scripts/execution-template-cli.mjs": "./scripts/execution-template-cli.mjs"
|
|
20
|
+
"./scripts/execution-template-cli.mjs": "./scripts/execution-template-cli.mjs",
|
|
21
|
+
"./scripts/task-init-cli.mjs": "./scripts/task-init-cli.mjs",
|
|
22
|
+
"./native": {
|
|
23
|
+
"types": "./dist/native/index.d.ts",
|
|
24
|
+
"import": "./dist/native/index.js"
|
|
25
|
+
},
|
|
26
|
+
"./native/*": {
|
|
27
|
+
"types": "./dist/native/*.d.ts",
|
|
28
|
+
"import": "./dist/native/*.js"
|
|
29
|
+
}
|
|
21
30
|
},
|
|
22
31
|
"scripts": {
|
|
23
32
|
"typecheck": "yarn workspace @farmslot/protocol build && tsc --noEmit --project tsconfig.json",
|
|
24
|
-
"test": "node test/mark-checklist-step.test.cjs && node test/checklist-target-sync.test.mjs && node test/package-exports.test.cjs && node test/check-task-artifact-contract.test.cjs && node test/recipe-quality-builder.test.cjs && node ../../scripts/quality/run-tsx-tests.mjs --cwd . --tsconfig tsconfig.json src/execution-template",
|
|
33
|
+
"test": "node test/mark-checklist-step.test.cjs && node test/checklist-target-sync.test.mjs && node test/package-exports.test.cjs && node test/check-task-artifact-contract.test.cjs && node test/recipe-quality-builder.test.cjs && node test/task-init.test.mjs && node ../../scripts/quality/run-tsx-tests.mjs --cwd . --tsconfig tsconfig.json src/execution-template && node ../../scripts/quality/run-tsx-tests.mjs --cwd . --tsconfig tsconfig.json src/native",
|
|
25
34
|
"format": "prettier --write --ignore-path ../../.prettierignore .",
|
|
26
35
|
"format:check": "prettier --check --ignore-path ../../.prettierignore .",
|
|
27
36
|
"lint": "eslint \"src/**/*.ts\"",
|
|
@@ -32,7 +41,7 @@
|
|
|
32
41
|
"prepublishOnly": "node ../../scripts/quality/check-farmslot-package-readiness.mjs --publish --packages @farmslot/agent-runtime"
|
|
33
42
|
},
|
|
34
43
|
"dependencies": {
|
|
35
|
-
"@farmslot/protocol": "0.
|
|
44
|
+
"@farmslot/protocol": "0.26.0"
|
|
36
45
|
},
|
|
37
46
|
"devDependencies": {
|
|
38
47
|
"@types/node": "^22.0.0",
|
|
@@ -170,8 +170,8 @@ function readManifest(taskDir) {
|
|
|
170
170
|
function manifestModeTeachingError(taskDir, reason) {
|
|
171
171
|
const manifestPath = path.join(path.resolve(taskDir), CHECKLIST_TARGET_MANIFEST);
|
|
172
172
|
return (
|
|
173
|
-
`
|
|
174
|
-
'
|
|
173
|
+
`Invalid ${CHECKLIST_TARGET_MANIFEST} at ${manifestPath} (${reason}). ` +
|
|
174
|
+
'Absent means the worker default; a role switch writes this file to point at its own checklist — re-run the role switch, fix the JSON, or remove the file. ' +
|
|
175
175
|
'Escape hatch: farmslot-agent mark <task-dir> --checklist FILE.md <step> [--signal FILE.json].'
|
|
176
176
|
);
|
|
177
177
|
}
|
|
@@ -244,8 +244,10 @@ function parseTaskDirMarkArgs(taskDir, rawArgs, { isMarkStepToken, usage }) {
|
|
|
244
244
|
function resolveChecklistTarget(taskDir) {
|
|
245
245
|
const normalizedDir = path.resolve(taskDir);
|
|
246
246
|
const manifestPath = path.join(normalizedDir, CHECKLIST_TARGET_MANIFEST);
|
|
247
|
+
// Absent means the worker default (CHECKLIST.md when present, else TASK.md).
|
|
248
|
+
// Only a role switch writes the manifest, to point at its own checklist.
|
|
247
249
|
if (!fs.existsSync(manifestPath)) {
|
|
248
|
-
|
|
250
|
+
return defaultWorkerTarget(normalizedDir);
|
|
249
251
|
}
|
|
250
252
|
const fromManifest = readManifest(normalizedDir);
|
|
251
253
|
if (!fromManifest) {
|