@caseyharalson/orrery 0.11.0 → 0.13.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/HELP.md +107 -14
- package/README.md +11 -8
- package/agent/skills/discovery/SKILL.md +13 -5
- package/agent/skills/orrery-execute/SKILL.md +1 -1
- package/agent/skills/refine-plan/SKILL.md +3 -2
- package/agent/skills/simulate-plan/SKILL.md +3 -2
- package/lib/cli/commands/orchestrate.js +66 -1
- package/lib/cli/commands/plans-dir.js +10 -0
- package/lib/cli/commands/resume.js +167 -31
- package/lib/cli/commands/status.js +83 -11
- package/lib/cli/index.js +2 -0
- package/lib/orchestration/index.js +830 -155
- package/lib/utils/git.js +52 -2
- package/lib/utils/lock.js +235 -0
- package/lib/utils/paths.js +46 -3
- package/package.json +3 -2
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
1
2
|
const path = require("path");
|
|
2
3
|
|
|
3
|
-
const {
|
|
4
|
+
const {
|
|
5
|
+
getPlansDir,
|
|
6
|
+
getCompletedDir,
|
|
7
|
+
getWorkDir
|
|
8
|
+
} = require("../../utils/paths");
|
|
4
9
|
const { getPlanFiles, loadPlan } = require("../../orchestration/plan-loader");
|
|
5
10
|
const { findPlanForCurrentBranch } = require("../../utils/plan-detect");
|
|
6
|
-
const { getCurrentBranch } = require("../../utils/git");
|
|
11
|
+
const { getCurrentBranch, derivePlanId } = require("../../utils/git");
|
|
12
|
+
const { getLockStatus, listPlanLocks } = require("../../utils/lock");
|
|
7
13
|
|
|
8
14
|
function supportsColor() {
|
|
9
15
|
return Boolean(process.stdout.isTTY) && !process.env.NO_COLOR;
|
|
@@ -47,7 +53,21 @@ function resolvePlanPath(planArg) {
|
|
|
47
53
|
if (!planArg) return null;
|
|
48
54
|
if (path.isAbsolute(planArg)) return planArg;
|
|
49
55
|
if (planArg.includes(path.sep)) return path.resolve(process.cwd(), planArg);
|
|
50
|
-
|
|
56
|
+
|
|
57
|
+
// Build candidate filenames: exact name, then with .yaml/.yml appended
|
|
58
|
+
const names = [planArg];
|
|
59
|
+
if (!planArg.endsWith(".yaml") && !planArg.endsWith(".yml")) {
|
|
60
|
+
names.push(`${planArg}.yaml`, `${planArg}.yml`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Check active plans first, then completed
|
|
64
|
+
for (const dir of [getPlansDir(), getCompletedDir()]) {
|
|
65
|
+
for (const name of names) {
|
|
66
|
+
const candidate = path.join(dir, name);
|
|
67
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return path.join(getPlansDir(), planArg); // default so caller's error message still works
|
|
51
71
|
}
|
|
52
72
|
|
|
53
73
|
function summarizePlans(plans) {
|
|
@@ -75,6 +95,14 @@ function renderPlanList(plans) {
|
|
|
75
95
|
function renderPlanDetail(plan) {
|
|
76
96
|
const status = getPlanStatus(plan);
|
|
77
97
|
console.log(`${formatStatusLabel(status)} ${plan.fileName}`);
|
|
98
|
+
if (plan.metadata.completed_at) {
|
|
99
|
+
console.log(` Completed: ${plan.metadata.completed_at}`);
|
|
100
|
+
}
|
|
101
|
+
const planId = derivePlanId(plan.fileName);
|
|
102
|
+
const logFile = path.join(getWorkDir(), `exec-${planId}.log`);
|
|
103
|
+
if (fs.existsSync(logFile)) {
|
|
104
|
+
console.log(` Log: ${logFile}`);
|
|
105
|
+
}
|
|
78
106
|
for (const step of plan.steps) {
|
|
79
107
|
const stepLabel = formatStatusLabel(step.status || "pending");
|
|
80
108
|
const description = step.description ? ` - ${step.description}` : "";
|
|
@@ -92,12 +120,44 @@ module.exports = function registerStatusCommand(program) {
|
|
|
92
120
|
.description("Show orchestration status for plans in the current project")
|
|
93
121
|
.option("--plan <file>", "Show detailed status for a specific plan")
|
|
94
122
|
.action((options) => {
|
|
123
|
+
// Check for active global execution
|
|
124
|
+
const lock = getLockStatus();
|
|
125
|
+
if (lock.locked) {
|
|
126
|
+
console.log(
|
|
127
|
+
`Execution in progress (PID ${lock.pid}, started ${lock.startedAt})\n`
|
|
128
|
+
);
|
|
129
|
+
} else if (lock.stale) {
|
|
130
|
+
console.log(
|
|
131
|
+
`Note: Stale lock detected (PID ${lock.pid} no longer running)\n`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Check for per-plan executions
|
|
136
|
+
const planLocks = listPlanLocks();
|
|
137
|
+
const activePlanLocks = planLocks.filter((l) => l.active);
|
|
138
|
+
const stalePlanLocks = planLocks.filter((l) => l.stale);
|
|
139
|
+
|
|
140
|
+
if (activePlanLocks.length > 0) {
|
|
141
|
+
console.log(`Active plan executions (${activePlanLocks.length}):`);
|
|
142
|
+
for (const pl of activePlanLocks) {
|
|
143
|
+
let line = ` - ${pl.planId} (PID ${pl.pid}, started ${pl.startedAt})`;
|
|
144
|
+
if (pl.worktreePath) line += `\n worktree: ${pl.worktreePath}`;
|
|
145
|
+
console.log(line);
|
|
146
|
+
}
|
|
147
|
+
console.log();
|
|
148
|
+
}
|
|
149
|
+
if (stalePlanLocks.length > 0) {
|
|
150
|
+
console.log(
|
|
151
|
+
`Note: ${stalePlanLocks.length} stale per-plan lock(s) detected\n`
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
95
155
|
const plansDir = getPlansDir();
|
|
96
156
|
const planArg = options.plan;
|
|
97
157
|
|
|
98
158
|
if (planArg) {
|
|
99
159
|
const planPath = resolvePlanPath(planArg);
|
|
100
|
-
if (!planPath || !
|
|
160
|
+
if (!planPath || !fs.existsSync(planPath)) {
|
|
101
161
|
console.error(`Plan not found: ${planArg}`);
|
|
102
162
|
process.exitCode = 1;
|
|
103
163
|
return;
|
|
@@ -122,16 +182,28 @@ module.exports = function registerStatusCommand(program) {
|
|
|
122
182
|
}
|
|
123
183
|
|
|
124
184
|
const planFiles = getPlanFiles(plansDir);
|
|
125
|
-
|
|
185
|
+
const completedDir = getCompletedDir();
|
|
186
|
+
const completedFiles = getPlanFiles(completedDir);
|
|
187
|
+
|
|
188
|
+
if (planFiles.length === 0 && completedFiles.length === 0) {
|
|
126
189
|
console.log("No plans found");
|
|
127
190
|
return;
|
|
128
191
|
}
|
|
129
192
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
193
|
+
if (planFiles.length > 0) {
|
|
194
|
+
const plans = planFiles.map((planFile) => loadPlan(planFile));
|
|
195
|
+
const { pendingSteps, completedSteps } = summarizePlans(plans);
|
|
196
|
+
console.log(
|
|
197
|
+
`${plans.length} plans, ${pendingSteps} pending steps, ${completedSteps} completed`
|
|
198
|
+
);
|
|
199
|
+
renderPlanList(plans);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (completedFiles.length > 0) {
|
|
203
|
+
if (planFiles.length > 0) console.log();
|
|
204
|
+
console.log(`Completed (${completedFiles.length}):`);
|
|
205
|
+
const completedPlans = completedFiles.map((f) => loadPlan(f));
|
|
206
|
+
renderPlanList(completedPlans);
|
|
207
|
+
}
|
|
136
208
|
});
|
|
137
209
|
};
|
package/lib/cli/index.js
CHANGED
|
@@ -10,6 +10,7 @@ const registerResume = require("./commands/resume");
|
|
|
10
10
|
const registerValidatePlan = require("./commands/validate-plan");
|
|
11
11
|
const registerIngestPlan = require("./commands/ingest-plan");
|
|
12
12
|
const registerManual = require("./commands/manual");
|
|
13
|
+
const registerPlansDir = require("./commands/plans-dir");
|
|
13
14
|
const registerHelp = require("./commands/help");
|
|
14
15
|
|
|
15
16
|
function getPackageVersion() {
|
|
@@ -36,6 +37,7 @@ function buildProgram() {
|
|
|
36
37
|
registerValidatePlan(program);
|
|
37
38
|
registerIngestPlan(program);
|
|
38
39
|
registerManual(program);
|
|
40
|
+
registerPlansDir(program);
|
|
39
41
|
registerHelp(program);
|
|
40
42
|
|
|
41
43
|
program.on("command:*", (operands) => {
|