supipowers 2.0.2 → 2.2.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/README.md +5 -6
- package/package.json +4 -2
- package/skills/harness/SKILL.md +1 -0
- package/src/bootstrap.ts +8 -133
- package/src/commands/optimize-context.ts +153 -16
- package/src/commands/runbook.ts +511 -0
- package/src/config/defaults.ts +5 -5
- package/src/config/loader.ts +1 -0
- package/src/config/schema.ts +2 -6
- package/src/context/rule-renderer.ts +274 -2
- package/src/context/runbook-extension-template.ts +193 -0
- package/src/context/startup-check.ts +197 -2
- package/src/context/startup-optimizer.ts +133 -10
- package/src/context-mode/knowledge/store.ts +381 -43
- package/src/context-mode/tools.ts +41 -3
- package/src/deps/registry.ts +1 -12
- package/src/fix-pr/assessment.ts +1 -0
- package/src/fix-pr/prompt-builder.ts +1 -0
- package/src/git/commit.ts +76 -18
- package/src/harness/command.ts +201 -12
- package/src/harness/default-agents/docs.md +39 -0
- package/src/harness/docs/config.ts +29 -0
- package/src/harness/docs/glob-match.ts +27 -0
- package/src/harness/docs/index-renderer.ts +82 -0
- package/src/harness/docs/provenance.ts +125 -0
- package/src/harness/docs/regen-decision.ts +167 -0
- package/src/harness/docs/representative-files.ts +175 -0
- package/src/harness/docs/source-hash.ts +106 -0
- package/src/harness/docs/validator.ts +233 -0
- package/src/harness/git-verification.ts +515 -0
- package/src/harness/git-verify-qa.ts +406 -0
- package/src/harness/hooks/layer-context-inject.ts +35 -1
- package/src/harness/hooks/register.ts +24 -3
- package/src/harness/pipeline.ts +37 -13
- package/src/harness/pr-comment/baseline.ts +105 -0
- package/src/harness/pr-comment/ci-env.ts +120 -0
- package/src/harness/pr-comment/gh-poster.ts +227 -0
- package/src/harness/pr-comment/handler.ts +198 -0
- package/src/harness/pr-comment/render.ts +297 -0
- package/src/harness/pr-comment/status.ts +95 -0
- package/src/harness/pr-comment/types.ts +73 -0
- package/src/harness/pr-comment/workflow-summary.ts +47 -0
- package/src/harness/project-paths.ts +95 -0
- package/src/harness/stages/design.ts +1 -0
- package/src/harness/stages/discover.ts +1 -13
- package/src/harness/stages/docs.ts +708 -0
- package/src/harness/stages/implement-apply.ts +934 -0
- package/src/harness/stages/implement.ts +64 -51
- package/src/harness/stages/plan.ts +25 -16
- package/src/harness/stages/validate.ts +478 -0
- package/src/harness/storage.ts +142 -0
- package/src/harness/tools.ts +130 -0
- package/src/mempalace/bridge.ts +207 -41
- package/src/mempalace/config.ts +10 -4
- package/src/mempalace/format.ts +122 -6
- package/src/mempalace/hooks.ts +204 -56
- package/src/mempalace/installer-helper.ts +18 -4
- package/src/mempalace/python/mempalace_bridge.py +128 -3
- package/src/mempalace/runtime.ts +53 -16
- package/src/mempalace/schema.ts +151 -30
- package/src/mempalace/session-summary.ts +5 -0
- package/src/mempalace/tool.ts +17 -4
- package/src/mempalace/upstream-limits.ts +69 -0
- package/src/planning/approval-flow.ts +25 -2
- package/src/planning/planning-ask-tool.ts +34 -4
- package/src/planning/system-prompt.ts +1 -1
- package/src/tool-catalog/active-tool-controller.ts +0 -22
- package/src/tool-catalog/active-tool-planner.ts +0 -26
- package/src/tool-catalog/tool-groups.ts +1 -9
- package/src/types.ts +127 -8
- package/src/ui-design/session.ts +114 -8
- package/src/utils/executable.ts +10 -1
- package/src/workspace/state-paths.ts +1 -1
- package/src/commands/mcp.ts +0 -814
- package/src/mcp/activation.ts +0 -77
- package/src/mcp/config.ts +0 -223
- package/src/mcp/docs.ts +0 -154
- package/src/mcp/gateway.ts +0 -103
- package/src/mcp/lifecycle.ts +0 -79
- package/src/mcp/manager-tool.ts +0 -104
- package/src/mcp/mcpc.ts +0 -113
- package/src/mcp/registry.ts +0 -98
- package/src/mcp/triggers.ts +0 -62
- package/src/mcp/types.ts +0 -95
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* IMPLEMENT stage runner.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* (
|
|
4
|
+
* Programmatic apply of every Tier 1 artifact defined by the design spec. Mirrors the
|
|
5
|
+
* `/supi:checks` pattern: the stage runs deterministically inside the harness command,
|
|
6
|
+
* with no handoff to the user's active agent. After this stage completes, the pipeline
|
|
7
|
+
* naturally continues to docs (per-layer subagent dispatch) and validate (mechanical
|
|
8
|
+
* checks) inside the same `/supi:harness` invocation.
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
10
|
+
* `decideImplementRouting` is retained as an exported helper for tests + future tooling;
|
|
11
|
+
* the in-session-vs-batch heuristic is no longer used by the stage runner itself because
|
|
12
|
+
* the apply path no longer needs the active agent.
|
|
11
13
|
*/
|
|
12
14
|
|
|
13
15
|
import * as fs from "node:fs";
|
|
14
|
-
import * as path from "node:path";
|
|
15
16
|
|
|
16
17
|
import type { Plan } from "../../types.js";
|
|
17
|
-
import { parsePlan } from "../../storage/plans.js";
|
|
18
18
|
import {
|
|
19
19
|
type HarnessStageRunResult,
|
|
20
20
|
type HarnessStageRunner,
|
|
@@ -23,7 +23,10 @@ import {
|
|
|
23
23
|
} from "../stage-runner.js";
|
|
24
24
|
import {
|
|
25
25
|
appendImplementLog,
|
|
26
|
+
hasSuccessfulImplementApply,
|
|
27
|
+
loadHarnessDesignSpecJson,
|
|
26
28
|
} from "../storage.js";
|
|
29
|
+
import { applyHarnessPlan } from "./implement-apply.js";
|
|
27
30
|
|
|
28
31
|
const DEFAULT_IN_SESSION_THRESHOLD = 10;
|
|
29
32
|
|
|
@@ -81,20 +84,15 @@ export class HarnessImplementStage implements HarnessStageRunner {
|
|
|
81
84
|
return fs.existsSync(this.input.planPath);
|
|
82
85
|
}
|
|
83
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Implement is driven by the programmatic apply, so `isComplete` returns true once a
|
|
89
|
+
* successful apply has been recorded in `implement-log.jsonl`. This keeps reruns
|
|
90
|
+
* idempotent without re-walking every applier (the appliers themselves are also
|
|
91
|
+
* idempotent — this is a fast-skip for the common case). A subsequent failed apply in
|
|
92
|
+
* the same session resets the result via the scan-from-end logic in storage.
|
|
93
|
+
*/
|
|
84
94
|
async isComplete(ctx: HarnessStageRunnerContext): Promise<boolean> {
|
|
85
|
-
|
|
86
|
-
// implement-log.jsonl with `kind: "self-check-passed"`. The command handler appends
|
|
87
|
-
// that record after running typecheck/test/scan.
|
|
88
|
-
const logPath = path.join(
|
|
89
|
-
path.dirname(this.input.planPath),
|
|
90
|
-
"..",
|
|
91
|
-
"harness",
|
|
92
|
-
"sessions",
|
|
93
|
-
ctx.sessionId,
|
|
94
|
-
"implement-log.jsonl",
|
|
95
|
-
);
|
|
96
|
-
void logPath; // tracked but the stage runner does not introspect it directly.
|
|
97
|
-
return false;
|
|
95
|
+
return hasSuccessfulImplementApply(ctx.paths, ctx.cwd, ctx.sessionId);
|
|
98
96
|
}
|
|
99
97
|
|
|
100
98
|
async run(ctx: HarnessStageRunnerContext): Promise<HarnessStageRunResult> {
|
|
@@ -111,51 +109,66 @@ export class HarnessImplementStage implements HarnessStageRunner {
|
|
|
111
109
|
blocker: { code: "implement-preflight-failed", message: errors.join("; ") },
|
|
112
110
|
};
|
|
113
111
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
raw = fs.readFileSync(this.input.planPath, "utf8");
|
|
117
|
-
} catch (error) {
|
|
112
|
+
const designResult = loadHarnessDesignSpecJson(ctx.paths, ctx.cwd, ctx.sessionId);
|
|
113
|
+
if (!designResult.ok) {
|
|
118
114
|
return {
|
|
119
|
-
status: "
|
|
120
|
-
stage: this.stage,
|
|
121
|
-
artifactPaths: [],
|
|
122
|
-
error: `unable to read plan: ${error instanceof Error ? error.message : String(error)}`,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
let plan: Plan;
|
|
126
|
-
try {
|
|
127
|
-
plan = parsePlan(raw, this.input.planPath);
|
|
128
|
-
} catch (error) {
|
|
129
|
-
return {
|
|
130
|
-
status: "failed",
|
|
115
|
+
status: "blocked",
|
|
131
116
|
stage: this.stage,
|
|
132
117
|
artifactPaths: [],
|
|
133
|
-
|
|
118
|
+
blocker: {
|
|
119
|
+
code: "design-spec-missing",
|
|
120
|
+
message: "implement stage requires <session>/design-spec.json. Run /supi:harness design first.",
|
|
121
|
+
},
|
|
134
122
|
};
|
|
135
123
|
}
|
|
136
124
|
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
125
|
+
const recordedAt = nowIso(ctx);
|
|
126
|
+
const outcome = await applyHarnessPlan({
|
|
127
|
+
platform: ctx.platform,
|
|
128
|
+
paths: ctx.paths,
|
|
129
|
+
cwd: ctx.cwd,
|
|
130
|
+
spec: designResult.value,
|
|
131
|
+
apply: true,
|
|
140
132
|
});
|
|
141
133
|
|
|
142
134
|
appendImplementLog(ctx.paths, ctx.cwd, ctx.sessionId, {
|
|
143
|
-
recordedAt
|
|
144
|
-
kind: "
|
|
145
|
-
routing: decision.routing,
|
|
146
|
-
taskCount: decision.taskCount,
|
|
147
|
-
reason: decision.reason,
|
|
135
|
+
recordedAt,
|
|
136
|
+
kind: "applied",
|
|
148
137
|
planPath: this.input.planPath,
|
|
138
|
+
applied: outcome.applied,
|
|
139
|
+
warnings: outcome.warnings,
|
|
140
|
+
errors: outcome.errors,
|
|
149
141
|
});
|
|
150
142
|
|
|
143
|
+
const artifactPaths = outcome.applied
|
|
144
|
+
.filter((entry) => entry.action === "wrote" || entry.action === "patched")
|
|
145
|
+
.map((entry) => entry.path);
|
|
146
|
+
|
|
147
|
+
if (outcome.errors.length > 0) {
|
|
148
|
+
const summary = outcome.errors
|
|
149
|
+
.map((err) => `${err.step}: ${err.message}`)
|
|
150
|
+
.join("; ");
|
|
151
|
+
return {
|
|
152
|
+
status: "blocked",
|
|
153
|
+
stage: this.stage,
|
|
154
|
+
artifactPaths,
|
|
155
|
+
blocker: { code: "implement-apply-failed", message: summary },
|
|
156
|
+
details: {
|
|
157
|
+
applied: outcome.applied.length,
|
|
158
|
+
errors: outcome.errors.length,
|
|
159
|
+
warnings: outcome.warnings.length,
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
151
164
|
return {
|
|
152
|
-
status: "
|
|
165
|
+
status: "completed",
|
|
153
166
|
stage: this.stage,
|
|
154
|
-
artifactPaths
|
|
167
|
+
artifactPaths,
|
|
155
168
|
details: {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
169
|
+
applied: outcome.applied.length,
|
|
170
|
+
warnings: outcome.warnings.length,
|
|
171
|
+
wrote: artifactPaths.length,
|
|
159
172
|
},
|
|
160
173
|
};
|
|
161
174
|
}
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
} from "../stage-runner.js";
|
|
25
25
|
import {
|
|
26
26
|
loadHarnessDesignSpecJson,
|
|
27
|
+
loadHarnessSession,
|
|
27
28
|
} from "../storage.js";
|
|
28
29
|
|
|
29
30
|
export interface HarnessPlanTask {
|
|
@@ -36,22 +37,14 @@ export interface HarnessPlanTask {
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
|
-
* Build the canonical task list from a design spec. Always emits the
|
|
40
|
-
* (
|
|
41
|
-
*
|
|
40
|
+
* Build the canonical task list from a design spec. Always emits the source
|
|
41
|
+
* harness artifacts first (docs, tooling, CI, queue, review wiring), then ends
|
|
42
|
+
* with AGENTS.md so the agent-facing summary can reference completed artifacts.
|
|
42
43
|
*/
|
|
43
44
|
export function buildHarnessPlanTasks(spec: HarnessDesignSpec): HarnessPlanTask[] {
|
|
44
45
|
const tasks: HarnessPlanTask[] = [];
|
|
45
46
|
let id = 1;
|
|
46
47
|
|
|
47
|
-
tasks.push({
|
|
48
|
-
id: id++,
|
|
49
|
-
name: "Generate AGENTS.md",
|
|
50
|
-
description: "Write a ≤120-line AGENTS.md at the repo root summarizing the harness contract for any agent.",
|
|
51
|
-
files: ["AGENTS.md"],
|
|
52
|
-
criteria: "AGENTS.md exists, references docs/architecture.md and docs/golden-principles.md, and ends with a 'When in doubt' section.",
|
|
53
|
-
complexity: "small",
|
|
54
|
-
});
|
|
55
48
|
|
|
56
49
|
tasks.push({
|
|
57
50
|
id: id++,
|
|
@@ -159,10 +152,10 @@ export function buildHarnessPlanTasks(spec: HarnessDesignSpec): HarnessPlanTask[
|
|
|
159
152
|
|
|
160
153
|
tasks.push({
|
|
161
154
|
id: id++,
|
|
162
|
-
name: "
|
|
163
|
-
description: "
|
|
164
|
-
files: ["
|
|
165
|
-
criteria:
|
|
155
|
+
name: "Enable repo-local anti-slop hooks",
|
|
156
|
+
description: "Create the repo-local harness marker. The installed Supipowers extension already registers the runtime hooks; the marker gates them for this repository.",
|
|
157
|
+
files: [".omp/supipowers/harness/marker.json"],
|
|
158
|
+
criteria: `Marker JSON exists with backend ${spec.antiSlop.backend}; no supipowers extension source files are modified.`,
|
|
166
159
|
complexity: "small",
|
|
167
160
|
});
|
|
168
161
|
|
|
@@ -206,9 +199,20 @@ export function buildHarnessPlanTasks(spec: HarnessDesignSpec): HarnessPlanTask[
|
|
|
206
199
|
});
|
|
207
200
|
}
|
|
208
201
|
|
|
202
|
+
tasks.push({
|
|
203
|
+
id: id++,
|
|
204
|
+
name: "Generate AGENTS.md",
|
|
205
|
+
description: "Write a ≤120-line AGENTS.md at the repo root summarizing the harness contract for any agent.",
|
|
206
|
+
files: ["AGENTS.md"],
|
|
207
|
+
criteria: "AGENTS.md exists, references docs/architecture.md and docs/golden-principles.md, and ends with a 'When in doubt' section.",
|
|
208
|
+
complexity: "small",
|
|
209
|
+
});
|
|
210
|
+
|
|
209
211
|
return tasks;
|
|
210
212
|
}
|
|
211
213
|
|
|
214
|
+
|
|
215
|
+
|
|
212
216
|
/** Render the plan markdown that lands in the canonical plans directory. */
|
|
213
217
|
export function renderHarnessPlanMarkdown(input: {
|
|
214
218
|
spec: HarnessDesignSpec;
|
|
@@ -321,7 +325,12 @@ export function emitHarnessPlanFromSpec(input: {
|
|
|
321
325
|
const recordedAt = input.recordedAt ?? new Date().toISOString();
|
|
322
326
|
const planName = input.planName ?? `harness-${input.spec.sessionId}`;
|
|
323
327
|
const tasks = buildHarnessPlanTasks(input.spec);
|
|
324
|
-
const planMarkdown = renderHarnessPlanMarkdown({
|
|
328
|
+
const planMarkdown = renderHarnessPlanMarkdown({
|
|
329
|
+
spec: input.spec,
|
|
330
|
+
tasks,
|
|
331
|
+
recordedAt,
|
|
332
|
+
planName,
|
|
333
|
+
});
|
|
325
334
|
const filename = `${planName}.md`;
|
|
326
335
|
const planPath = savePlan(input.ctx.paths, input.ctx.cwd, filename, planMarkdown);
|
|
327
336
|
return { planPath, planMarkdown, tasks };
|