synergyspec-selfevolving 2.1.5 → 2.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/learn.js +80 -24
- package/dist/commands/self-evolution-dream.d.ts +15 -1
- package/dist/commands/self-evolution-dream.js +111 -6
- package/dist/commands/self-evolution-episode.d.ts +3 -0
- package/dist/commands/self-evolution-episode.js +157 -108
- package/dist/commands/workflow/status.js +4 -0
- package/dist/core/archive.js +17 -9
- package/dist/core/change-readiness.d.ts +16 -1
- package/dist/core/change-readiness.js +441 -15
- package/dist/core/fitness/loss.d.ts +3 -5
- package/dist/core/fitness/loss.js +2 -2
- package/dist/core/fitness/test-metrics.d.ts +1 -0
- package/dist/core/fitness/test-metrics.js +49 -0
- package/dist/core/learn.js +129 -11
- package/dist/core/migration.d.ts +6 -14
- package/dist/core/migration.js +63 -21
- package/dist/core/runner-evidence.d.ts +53 -0
- package/dist/core/runner-evidence.js +613 -0
- package/dist/core/self-evolution/candidates.js +0 -2
- package/dist/core/self-evolution/dream.d.ts +57 -3
- package/dist/core/self-evolution/dream.js +480 -9
- package/dist/core/self-evolution/episode-orchestrator.d.ts +2 -0
- package/dist/core/self-evolution/episode-orchestrator.js +17 -5
- package/dist/core/self-evolution/episode-store.d.ts +5 -0
- package/dist/core/self-evolution/episode-store.js +6 -2
- package/dist/core/self-evolution/evolving-agent.d.ts +33 -4
- package/dist/core/self-evolution/evolving-agent.js +138 -11
- package/dist/core/self-evolution/host-harness.d.ts +35 -12
- package/dist/core/self-evolution/host-harness.js +188 -49
- package/dist/core/self-evolution/reward-aggregator.js +2 -2
- package/dist/core/templates/workflows/archive-change.js +18 -18
- package/dist/core/templates/workflows/dream.js +57 -47
- package/dist/core/templates/workflows/learn.js +7 -5
- package/dist/core/templates/workflows/run-tests.js +48 -29
- package/dist/core/templates/workflows/self-evolving.js +11 -8
- package/dist/core/trajectory/facts.d.ts +1 -1
- package/dist/core/trajectory/registry.js +39 -8
- package/package.json +1 -1
|
@@ -19,17 +19,19 @@ This is the review-and-learn step after \`/synspec:apply\` and \`/synspec:verify
|
|
|
19
19
|
The runner starts with NO conversation context, so collect every handle it needs:
|
|
20
20
|
- **Project root**: the absolute path of the current working directory.
|
|
21
21
|
- **Change name**: from step 1.
|
|
22
|
-
- **Harness**:
|
|
23
|
-
- **Mode**: always \`apply\` — the episode runs the full loop (score, decide, and the 演进智能体's ONE bounded edit) autonomously, with no confirmation prompt. There is NO read-only episode and NO \`--preview\` flag. If the user wants a read-only look (no rollback, no evolution), do NOT run an episode: use the read-only view \`synergyspec-selfevolving self-evolution policy show\` (or a plain \`synergyspec-selfevolving learn <name>\` without \`--apply\`) instead.
|
|
24
|
-
- **
|
|
22
|
+
- **Harness**: resolve the CURRENT host runtime, not the change metadata. If this skill is running in Codex, use \`codex\`; in Claude Code, use \`claude\`; in OpenCode, use \`opencode\`. Use \`unknown\` only when the host is genuinely unidentified after checking the active session/tooling. Do NOT read \`harness:\` from the per-change YAML for this field: that metadata is historical provenance, not the runtime that will spawn the loop-v2 agents.
|
|
23
|
+
- **Mode**: always \`apply\` — the episode runs the full loop (score, decide, and the 演进智能体's ONE bounded edit) autonomously, with no confirmation prompt. There is NO read-only episode and NO \`--preview\` flag. If the user wants a read-only look (no rollback, no evolution), do NOT run an episode: use the read-only view \`synergyspec-selfevolving self-evolution policy show\` (or a plain \`synergyspec-selfevolving learn <name>\` without \`--apply\`) instead.
|
|
24
|
+
- **Force-new episode**: \`yes\` only when the user explicitly asked to rerun / force a fresh episode; otherwise \`no\`. A normal learn run must not invent a rerun.
|
|
25
|
+
- **Isolation**: \`fresh-context subagent\` for the spawned runner.
|
|
26
|
+
- **Session handle (optional)**: if your harness exposes this session's id or transcript path, capture it; otherwise omit it (the 主智能体 MAIN AGENT arm's trajectory discovery then uses the change window).
|
|
25
27
|
|
|
26
28
|
3. **Spawn the runner**
|
|
27
29
|
|
|
28
|
-
Use the host's available general-purpose Task/subagent runner (for example \`general-purpose\` on Claude or \`general\` on hosts that expose that type), prompt: "Use Skill tool to invoke synergyspec-selfevolving-self-evolving for change '<name>'. Project root: <root>. Harness: <harness>. Mode: apply. Session-id: <id>. Transcript: <path>. Trigger the loop-v2 self-evolution episode autonomously, do not ask the user questions, and end with the '## Episode Verdict' block."
|
|
30
|
+
Use the host's available general-purpose Task/subagent runner (for example \`general-purpose\` on Claude or \`general\` on hosts that expose that type), prompt: "Use Skill tool to invoke synergyspec-selfevolving-self-evolving for change '<name>'. Project root: <root>. Harness: <harness>. Mode: apply. Force-new: <yes|no>. Isolation: fresh-context subagent. Session-id: <id>. Transcript: <path>. Trigger the loop-v2 self-evolution episode autonomously, do not ask the user questions, and end with the '## Episode Verdict' block."
|
|
29
31
|
|
|
30
32
|
Include the \`Session-id: <id>.\` / \`Transcript: <path>.\` segment only when the session handle from step 2 is known — omit it entirely when unknown.
|
|
31
33
|
|
|
32
|
-
The runner triggers exactly one CLI command — \`synergyspec-selfevolving self-evolution episode --change "<name>" --session-id <id
|
|
34
|
+
The runner triggers exactly one CLI command — \`synergyspec-selfevolving self-evolution episode --change "<name>" --harness <harness> --session-id <id> --rerun\` when force-new is \`yes\`; omit \`--rerun\` when force-new is \`no\`; omit \`--harness\` when it is \`unknown\` — and the orchestrator CODE-SPAWNS the 奖励智能体 REWARD AGENT + 演进智能体 EVOLVING AGENT (+ optional CRITIC AGENT(基线智能体)). Neither you nor the runner grades or edits canonical files.
|
|
33
35
|
|
|
34
36
|
Guardrails:
|
|
35
37
|
- Do NOT trigger the episode yourself in this session — it must run from a fresh context.
|
|
@@ -38,35 +38,53 @@ const INSTRUCTIONS_BODY = `**Input**: Optionally specify a change name. If omitt
|
|
|
38
38
|
"startedAt": "<ISO timestamp>",
|
|
39
39
|
"finishedAt": "<ISO timestamp>",
|
|
40
40
|
"exitCode": 0,
|
|
41
|
-
"signal": null,
|
|
42
|
-
"stdoutLog": "synergyspec-selfevolving/changes/<name>/test-evidence/<timestamp>/runner.stdout.log",
|
|
43
|
-
"stderrLog": "synergyspec-selfevolving/changes/<name>/test-evidence/<timestamp>/runner.stderr.log",
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
},
|
|
59
|
-
"junitXml": null,
|
|
60
|
-
"coverageSummary": null,
|
|
61
|
-
"coverageLcov": null,
|
|
62
|
-
"coverageHtml": null
|
|
41
|
+
"signal": null,
|
|
42
|
+
"stdoutLog": "synergyspec-selfevolving/changes/<name>/test-evidence/<timestamp>/runner.stdout.log",
|
|
43
|
+
"stderrLog": "synergyspec-selfevolving/changes/<name>/test-evidence/<timestamp>/runner.stderr.log",
|
|
44
|
+
"stdoutLogSha256": "<sha256 of runner.stdout.log>",
|
|
45
|
+
"stderrLogSha256": "<sha256 of runner.stderr.log>",
|
|
46
|
+
"workspaceIdentity": {
|
|
47
|
+
"changeName": "<name>",
|
|
48
|
+
"taskId": "<benchmark task id, if any>",
|
|
49
|
+
"cwd": "<absolute working directory>",
|
|
50
|
+
"pyproject": null,
|
|
51
|
+
"packageJson": null
|
|
52
|
+
},
|
|
53
|
+
"testMetrics": {
|
|
54
|
+
"total": 29,
|
|
55
|
+
"passed": 29,
|
|
56
|
+
"failed": 0,
|
|
57
|
+
"passRate": 1
|
|
58
|
+
},
|
|
59
|
+
"junitXml": null,
|
|
60
|
+
"coverageSummary": null,
|
|
61
|
+
"coverageLcov": null,
|
|
62
|
+
"coverageHtml": null
|
|
63
63
|
}
|
|
64
64
|
\`\`\`
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
Set each workspace identity file entry to an object ONLY when that file
|
|
67
|
+
exists at the project root. If \`pyproject.toml\` or \`package.json\` is absent,
|
|
68
|
+
leave that field \`null\` (or omit it); do not emit a \`path\` for an absent file.
|
|
69
|
+
Object shape for a present file:
|
|
70
|
+
|
|
71
|
+
\`\`\`json
|
|
72
|
+
{
|
|
73
|
+
"path": "pyproject.toml",
|
|
74
|
+
"name": "<project/package name, or null>",
|
|
75
|
+
"sha256": "<sha256 of the file>"
|
|
76
|
+
}
|
|
77
|
+
\`\`\`
|
|
78
|
+
|
|
79
|
+
If the runner summary exposes pass/fail counts, record them in
|
|
80
|
+
\`testMetrics\`; otherwise set \`testMetrics\` to \`null\` and preserve the raw
|
|
81
|
+
stdout/stderr logs. The \`stdoutLogSha256\` and \`stderrLogSha256\` fields MUST
|
|
82
|
+
be the SHA-256 hashes of the exact saved log files, computed after writing the
|
|
83
|
+
files and before writing \`runner-exit.json\`; do not hand-edit logs after
|
|
84
|
+
hashing. If the runner produces JUnit XML or coverage artifacts,
|
|
85
|
+
record their paths in \`runner-exit.json\`. If it does not, keep those fields
|
|
86
|
+
\`null\`. The markdown report may summarize results, but the raw logs and exit
|
|
87
|
+
JSON are the durable evidence that later verification must inspect.
|
|
70
88
|
|
|
71
89
|
3b. **Promote PBT counterexamples to regression tests**
|
|
72
90
|
|
|
@@ -134,9 +152,10 @@ const INSTRUCTIONS_BODY = `**Input**: Optionally specify a change name. If omitt
|
|
|
134
152
|
| UC1-E4a1 | Error when no grid space | ❌ failed | \`gridSize=0, widgetCount=1\` | \`test/pbt-regression-uc1-e4a1-1.test.ts\` |
|
|
135
153
|
...
|
|
136
154
|
|
|
137
|
-
### Test Run Results
|
|
138
|
-
<
|
|
139
|
-
|
|
155
|
+
### Test Run Results
|
|
156
|
+
Summary: <N collected>, <N passed>, <N failed>, <N skipped>, <N collection errors>
|
|
157
|
+
<raw summary from test runner output: passed/failed/skipped counts>
|
|
158
|
+
If failures: list failing test names and errors.
|
|
140
159
|
|
|
141
160
|
### Runner Evidence
|
|
142
161
|
| Evidence | Path / Value |
|
|
@@ -12,9 +12,11 @@ You are the RUNNER for a completed SynergySpec-SelfEvolving change. In loop v2 (
|
|
|
12
12
|
|
|
13
13
|
Parse these handles from the spawning prompt:
|
|
14
14
|
- **Change name** (required). If the change name is missing or does not resolve via \`synergyspec-selfevolving list --json\`, stop and report the error — do NOT prompt the user (you may have no user channel).
|
|
15
|
-
- **Absolute project root.** Run every CLI command from it.
|
|
16
|
-
- **Harness**: \`claude\` | \`codex\` | \`opencode\` | \`unknown\`. If a harness was provided
|
|
17
|
-
- **
|
|
15
|
+
- **Absolute project root.** Run every CLI command from it.
|
|
16
|
+
- **Harness**: \`claude\` | \`codex\` | \`opencode\` | \`unknown\`. If a concrete harness was provided, pass \`--harness <harness>\` to the CLI invocation below. If the prompt says \`unknown\` but this runner is clearly executing inside Codex, Claude Code, or OpenCode, recover the current host and pass that concrete harness. Omit \`--harness\` only when both the prompt and the current runner host are genuinely unidentified; never set \`SYNERGYSPEC_SELFEVOLVING_HOST_HARNESS=unknown\`.
|
|
17
|
+
- **Force-new**: \`yes\` | \`no\` (optional; default \`no\`). If \`yes\`, append \`--rerun\` so a closed matching episode is not reused.
|
|
18
|
+
- **Isolation**: \`fresh-context subagent\` | \`inline fallback (degraded)\` (optional). If supplied, copy it verbatim into the verdict; otherwise infer from whether this skill is running in a spawned subagent or inline fallback.
|
|
19
|
+
- **Session-id / transcript path** (optional). When the spawning prompt supplied a session-id or transcript path, pass \`--session-id <id>\` / \`--transcript <path>\` to the \`episode\` command so the 主智能体 MAIN AGENT arm's trajectory discovery does not depend on the change-window fallback.
|
|
18
20
|
|
|
19
21
|
**Recursion guard**
|
|
20
22
|
|
|
@@ -49,10 +51,11 @@ Everything in steps 1–6 is CODE. You do not perform any of it. You issue the c
|
|
|
49
51
|
|
|
50
52
|
Run exactly ONE command — the loop-v2 orchestrator. It CODE-SPAWNS the 奖励智能体 REWARD AGENT + 演进智能体 EVOLVING AGENT (+ optional CRITIC AGENT(基线智能体)); you spawn nothing:
|
|
51
53
|
\`\`\`bash
|
|
52
|
-
synergyspec-selfevolving self-evolution episode --change "<change>" --json
|
|
53
|
-
\`\`\`
|
|
54
|
-
- Append \`--session-id <id>\` and/or \`--transcript <path>\` ONLY when the spawning prompt supplied them.
|
|
55
|
-
-
|
|
54
|
+
synergyspec-selfevolving self-evolution episode --change "<change>" --json
|
|
55
|
+
\`\`\`
|
|
56
|
+
- Append \`--session-id <id>\` and/or \`--transcript <path>\` ONLY when the spawning prompt supplied them.
|
|
57
|
+
- Append \`--harness <harness>\` when the spawning prompt supplied \`claude\`, \`codex\`, or \`opencode\`, or when the prompt supplied \`unknown\` but this runner can identify the current host as Codex, Claude Code, or OpenCode. Never append \`--harness unknown\`.
|
|
58
|
+
- Append \`--rerun\` ONLY when the spawning prompt supplied \`Force-new: yes\`.
|
|
56
59
|
|
|
57
60
|
Do NOT grade, score, or author any edit yourself, and do NOT run \`evolve-from-edits\`, \`auto-evolve\`, or \`--agent\` / \`claude -p\` — those are not part of loop v2's host-facing path. The episode command IS the loop.
|
|
58
61
|
|
|
@@ -116,7 +119,7 @@ The session's final message MUST end with exactly this block shape:
|
|
|
116
119
|
- Use \`busy-in-flight\` when the episode command returned the clean concurrency deferral (another in-flight episode holds the same 策略 POLICY target): advantage is null, episode id is none, 策略 POLICY version is unchanged. It is TRANSIENT and self-healing (retry after the lock clears / the 60-min stale window) — it is NOT a DEFECT, do not list it under Defects to surface, and never advise deleting \`in-flight.json\`.
|
|
117
120
|
- When the episode did NOT start (Episode id is none — any not-run / busy-in-flight / error-* outcome), write \`none\` for Evolved target and Canonical file(s) changed, report Decision/Advantage as none/null, and leave 策略 POLICY version unchanged. The change's CONFIGURED target id is context only — do NOT copy it into the Evolved target field on a non-run verdict.
|
|
118
121
|
- A \`kept\` / \`abstained\` outcome on a verified-green run is the CORRECT no-op, not a missed evolution — say so plainly rather than hedging.
|
|
119
|
-
-
|
|
122
|
+
- Copy the supplied \`Isolation:\` value verbatim when present. If it was not supplied, report \`Isolation: fresh-context subagent\` when you were spawned as a subagent, or \`Isolation: inline fallback (degraded)\` when this skill is running inline in the spawning session.`;
|
|
120
123
|
export function getSelfEvolvingSkillTemplate() {
|
|
121
124
|
return {
|
|
122
125
|
name: 'synergyspec-selfevolving-self-evolving',
|
|
@@ -3,7 +3,7 @@ import type { HarnessName, NormalizedTrajectory } from './model.js';
|
|
|
3
3
|
/** One failing test observed in the graded runner result's output. */
|
|
4
4
|
export type ObservedTestFailure = ParsedTestFailure;
|
|
5
5
|
export interface TrajectoryFacts {
|
|
6
|
-
harness: HarnessName;
|
|
6
|
+
harness: HarnessName | 'runner-evidence';
|
|
7
7
|
changeName: string;
|
|
8
8
|
/**
|
|
9
9
|
* A recognizable test-runner invocation (vitest/pytest/go test/…) produced a
|
|
@@ -5,12 +5,11 @@
|
|
|
5
5
|
* Selection order:
|
|
6
6
|
* 1. If the change metadata stamps a `harness` (the strongest signal — see
|
|
7
7
|
* `ChangeMetadata.harness`), use that adapter.
|
|
8
|
-
* 2. Otherwise read the
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* hermetic tests stay on the Claude adapter unchanged.
|
|
8
|
+
* 2. Otherwise read the trusted repo/host harness signal
|
|
9
|
+
* (`resolveHostHarnessDetailsForRepo()`): explicit override, persisted
|
|
10
|
+
* sidecar, explicit session id, or the historical Claude default. An
|
|
11
|
+
* env-only Codex/OpenCode signal on an unstamped change is intentionally
|
|
12
|
+
* too weak to scan the host's whole session store.
|
|
14
13
|
* 3. `trajsz` is OPT-IN (env `SYNERGYSPEC_SELFEVOLVING_TRAJSZ`): when enabled
|
|
15
14
|
* and a fresh archive is present it is tried FIRST, since it already
|
|
16
15
|
* normalizes all three harnesses; absent/stale, we fall back to native.
|
|
@@ -98,8 +97,9 @@ export async function resolveTrajectorySource(projectRoot, changeName, options =
|
|
|
98
97
|
return s;
|
|
99
98
|
}
|
|
100
99
|
catch {
|
|
101
|
-
// fall through to
|
|
100
|
+
// fall through to the fail-closed return below
|
|
102
101
|
}
|
|
102
|
+
return null;
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
// 2. No stamp: use a trusted host recovery signal, not a blind global scan.
|
|
@@ -143,7 +143,7 @@ export async function getTrajectoryForChange(projectRoot, changeName, options =
|
|
|
143
143
|
export async function getTrajectoryResultForChange(projectRoot, changeName, options = {}) {
|
|
144
144
|
const source = await resolveTrajectorySource(projectRoot, changeName, options);
|
|
145
145
|
if (!source)
|
|
146
|
-
return
|
|
146
|
+
return explainTrajectorySourceMiss(projectRoot, changeName, options);
|
|
147
147
|
try {
|
|
148
148
|
const result = source.getTrajectoryResult
|
|
149
149
|
? await source.getTrajectoryResult(changeName)
|
|
@@ -162,4 +162,35 @@ export async function getTrajectoryResultForChange(projectRoot, changeName, opti
|
|
|
162
162
|
};
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
|
+
async function explainTrajectorySourceMiss(projectRoot, changeName, options) {
|
|
166
|
+
const changeProvenance = await readChangeTrajectoryProvenance(projectRoot, changeName);
|
|
167
|
+
const sessionIds = uniqueNonBlank([
|
|
168
|
+
...(options.sessionIds ?? []),
|
|
169
|
+
...changeProvenance.sessionIds,
|
|
170
|
+
process.env.SYNERGYSPEC_SELFEVOLVING_SESSION_ID,
|
|
171
|
+
]);
|
|
172
|
+
if (changeProvenance.harness) {
|
|
173
|
+
return {
|
|
174
|
+
trajectory: null,
|
|
175
|
+
sourceHarness: changeProvenance.harness,
|
|
176
|
+
reason: `stamped-${changeProvenance.harness}-source-unavailable`,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
const hostResolution = await resolveHostHarnessDetailsForRepo(projectRoot);
|
|
180
|
+
const envOnlyNativeHost = hostResolution.source === 'env' &&
|
|
181
|
+
hostResolution.harness !== 'claude' &&
|
|
182
|
+
sessionIds.length === 0;
|
|
183
|
+
if (envOnlyNativeHost) {
|
|
184
|
+
return {
|
|
185
|
+
trajectory: null,
|
|
186
|
+
sourceHarness: hostResolution.harness,
|
|
187
|
+
reason: `env-only-${hostResolution.harness}-requires-stamped-harness-or-session-id`,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
trajectory: null,
|
|
192
|
+
sourceHarness: hostResolution.source === 'default' ? null : hostResolution.harness,
|
|
193
|
+
reason: `${hostResolution.source}-${hostResolution.harness}-source-unavailable`,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
165
196
|
//# sourceMappingURL=registry.js.map
|