@gluecharm-lab/easyspecs-cli 0.0.19 → 0.0.20
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 +4 -4
- package/commands.md +3 -3
- package/dist/main.cjs +59 -22
- package/dist/main.cjs.map +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Headless **EasySpecs** command-line tool: same orchestration ideas as the **Easy
|
|
|
5
5
|
## The three factory-level commands
|
|
6
6
|
|
|
7
7
|
1. **`easyspecs-cli analysis` — create new context**
|
|
8
|
-
Runs the full **Generate Context** factory end to end (synthesis until stable, coverage, remediation, reporting, link mapping, index assembly). Use this when you need a fresh or full rebuild of **`.gluecharm/context`** from the repo. **`--force-new-context-analysis`** overrides skip-when-already-analyzed behavior when **`easyspecs.factory.cloudContextAnalyzed`** would otherwise short-circuit the run. After **`analysis`**, run **`easyspecs-cli upload context`** or **`upload republish`** when you want context on EasySpecs (**`auth login`** + **`config set-project-id`**). If **`git worktree add`** fails because a temp analysis checkout folder was removed but Git still lists it, the CLI runs **`git worktree prune`** in your repository and retries **`git worktree add`** once (same behaviour wherever the CLI creates that temp worktree).
|
|
8
|
+
Runs the full **Generate Context** factory end to end (synthesis until stable, coverage, remediation, reporting, link mapping, index assembly). Use this when you need a fresh or full rebuild of **`.gluecharm/context`** from the repo. **`--force-new-context-analysis`** overrides skip-when-already-analyzed behavior when **`easyspecs.factory.cloudContextAnalyzed`** would otherwise short-circuit the run. On a **successful** factory exit, the CLI **always** copies **`.gluecharm/context`** from the analysis worktree into **`<repoRoot>`** unless you pass **`--no-promote`** (no **`--promote`** needed); stderr **`[pipeline:analysis] promoted …`**. This step does **not** use **`easyspecs.analysis.promoteContextToWorkspace`** — that setting still applies to **`run synthesis`** and **`update context`**. After **`analysis`**, run **`easyspecs-cli upload context`** or **`upload republish`** when you want context on EasySpecs (**`auth login`** + **`config set-project-id`**). If **`git worktree add`** fails because a temp analysis checkout folder was removed but Git still lists it, the CLI runs **`git worktree prune`** in your repository and retries **`git worktree add`** once (same behaviour wherever the CLI creates that temp worktree).
|
|
9
9
|
|
|
10
10
|
2. **`easyspecs-cli update context` — update context from code churn**
|
|
11
11
|
Incremental refresh from a **git delta** since the stored baseline (**`easyspecs.factory.updateContext.lastRunAt`**) or, when that is absent, inferred from workspace context mtimes: materialises **`changes-since-date.md`**, runs **scoped** remediation when commits and touched paths warrant it, then optional promotion. Use **`upload context`** afterward when you need cloud sync. Use this day to day after **`analysis`** when the codebase moved but specs did not restart from zero.
|
|
@@ -224,8 +224,8 @@ These appear **before** the subcommand (everything after the first non-flag toke
|
|
|
224
224
|
| `--api-base-url <url>` | System Manager API origin for this process (overrides `easyspecs.apiBaseUrl`). |
|
|
225
225
|
| `--session-path <file>` | Session JSON path for **this process only** (overrides **`easyspecs.cliSessionPath`**); does not rewrite **`config.json`** unless you use **`auth login`** tail **`--session-path`** as documented under **Auth**. |
|
|
226
226
|
| `--environment production` \| `staging` | Alias **`--env`**. Overrides `easyspecs.deploymentEnvironment` for built-in URL selection when no explicit URL is set. |
|
|
227
|
-
| `--promote` | After **`run synthesis
|
|
228
|
-
| `--no-promote` |
|
|
227
|
+
| `--promote` | After **`run synthesis`**: force copying **`.gluecharm/context`** into the repo when **`easyspecs.analysis.promoteContextToWorkspace`** would disable it. **`analysis`** does not need this flag — promotion is automatic unless **`--no-promote`**. |
|
|
228
|
+
| `--no-promote` | After **`run synthesis`** or **`analysis`**: skip copying **`.gluecharm/context`** into the repo for this run. |
|
|
229
229
|
| `--help`, `-h` | Built-in help. Does **not** create **`.easyspecs/config.json`**. |
|
|
230
230
|
| `--version`, `-V` | CLI package version. Does **not** create config. |
|
|
231
231
|
| `--config <path>` | Parsed but **unused** in current releases; read **`<repo>/.easyspecs/config.json`** instead. |
|
|
@@ -258,7 +258,7 @@ Every command the CLI accepts, with command-specific tokens. Global flags above
|
|
|
258
258
|
| `run synthesis` | — | Context artefact pipeline pass; **`requireOpenCode`** applies. **`--promote` / `--no-promote`** affect promotion after success. |
|
|
259
259
|
| `run synthesis resume-missing` | **`--worktree <path>`** (optional) | Parallel missing-artefact remediation pool on an existing checkout (from **`--worktree`** or last snapshot). **`requireOpenCode`**. |
|
|
260
260
|
| `run synthesis resume-synthesis` | **`--worktree <path>`** (optional) | Same implementation as **`resume-missing`** (alias command path). |
|
|
261
|
-
| `analysis` | **`--force-new-context-analysis`** (optional; tail only). **`--upload`** / **`--skip-upload`** → usage exit; **`--synthesis-only`** → ignored + stderr deprecation (**SRS-60**). | Full **Generate Context** factory — **create new context** trajectory. CLI **does not** run backend upload inside **`analysis`**; use **`upload context`** / **`upload republish`** afterward. If **`easyspecs.factory.cloudContextAnalyzed`** is **`true`** and **`--force-new-context-analysis`** is absent, exits **0** early with **`analysisSkipped`**. Stale temp-worktree registration: **`git worktree prune`** then one retry of **`git worktree add`**. |
|
|
261
|
+
| `analysis` | **`--force-new-context-analysis`** (optional; tail only). **`--upload`** / **`--skip-upload`** → usage exit; **`--synthesis-only`** → ignored + stderr deprecation (**SRS-60**). | Full **Generate Context** factory — **create new context** trajectory. CLI **does not** run backend upload inside **`analysis`**; use **`upload context`** / **`upload republish`** afterward. **Promotion** after success is **automatic** unless **`--no-promote`** (independent of **`easyspecs.analysis.promoteContextToWorkspace`**). If **`easyspecs.factory.cloudContextAnalyzed`** is **`true`** and **`--force-new-context-analysis`** is absent, exits **0** early with **`analysisSkipped`**. Stale temp-worktree registration: **`git worktree prune`** then one retry of **`git worktree add`**. |
|
|
262
262
|
| `update context` | — | **Update context** trajectory: git window after baseline → worktree → **`changes-since-date.md`** → optional remediation → **`--promote` / `--no-promote`** → **`easyspecs.factory.updateContext.lastRunAt`**. Run **`upload context`** separately for cloud sync. Seed context should exist on **HEAD** in the checkout (the factory may copy from workspace when the worktree lacks context). |
|
|
263
263
|
| `diagnose reference-coverage` | **`--root workspace`** \| **`--root worktree`**, optional **`--worktree <path>`** | Reference coverage gate; optional percent limit via **`easyspecs.diagnose.zeroReference.maxPercentNonReferenced`**. |
|
|
264
264
|
| `diagnose coordination-duplicates` | same | Duplicate/orphan reporting; **`easyspecs.diagnose.coordinationDuplicates.strict`**. |
|
package/commands.md
CHANGED
|
@@ -57,8 +57,8 @@ These flags may appear **before** the subcommand. Parsing and command registrati
|
|
|
57
57
|
| `--verbose` | Extra stderr logging where implemented. |
|
|
58
58
|
| `--api-base-url <url>` | System Manager API origin for this process (overrides `easyspecs.apiBaseUrl` in config). |
|
|
59
59
|
| `--environment production` | `--environment staging` | Alias: `**--env**`. Overrides `easyspecs.deploymentEnvironment` for built-in URL selection when no explicit URL is set. |
|
|
60
|
-
| `--promote` | After
|
|
61
|
-
| `--no-promote` |
|
|
60
|
+
| `--promote` | After **`run synthesis`**: force promotion into the repo when **`easyspecs.analysis.promoteContextToWorkspace`** would turn it off. **`analysis`**: not required for promotion (promotion runs by default unless **`--no-promote`**). |
|
|
61
|
+
| `--no-promote` | After **`run synthesis`** or **`analysis`**: skip copying **`.gluecharm/context`** into the repo for this run. |
|
|
62
62
|
| `--help`, `-h` | Show built-in help (also `help` as first positional). Does **not** create `.easyspecs/config.json`. |
|
|
63
63
|
| `--version`, `-V` | Print CLI package version (also `version` as first positional). Does **not** create config. |
|
|
64
64
|
| `--config <path>` | Parsed but **unused** by `main.ts` today; configuration is read from `<repoRoot>/.easyspecs/config.json`. |
|
|
@@ -148,7 +148,7 @@ Each row lists **command-specific CLI tokens**, then **what configuration applie
|
|
|
148
148
|
| `auth status` | — | Reads session file. |
|
|
149
149
|
| `run synthesis` | — | Single SRS-9 context pass (same as extension **Run Analysis**). `**requireOpenCode`** → executable + credentials unless skip flag. Uses `**merged.pipelineOpenCode**` from `**config.json**`. `**--promote` / `--no-promote**` controls promotion after success. |
|
|
150
150
|
| `run synthesis resume-missing`, `run synthesis resume-synthesis` | Optional `**--worktree <path>**` | Same implementation: resolves checkout via `--worktree` or stored snapshot (`[resolveAdHocCheckoutRoot](../../src/cli/main.ts)`). OpenCode + `**merged.pipelineOpenCode**`. |
|
|
151
|
-
| `analysis` | Optional tail: `**--force-new-context-analysis**`. **`--upload`** → usage exit. **`--synthesis-only`**: accepted as a **hidden** Commander option (legacy scripts); **ignored** with one stderr **`[deprecated]`** line (**SRS-60**). | **SRS-32** full **Factory** loop: synthesis convergence (until no missing artefacts), coverage, zero-ref, report, **link mapping**, index assembly; **Phase 7** backend sync is skipped in CLI (**`skipBackendSync`**). Push context with **`upload context`** / **`upload republish`** after analysis. Factory timing from `**merged.factory`** + `**--ci**` defaults. Debug: `**easyspecs.factory.debug**`. OpenCode options from `**merged.pipelineOpenCode**`. **SRS-46:** if `**easyspecs.factory.cloudContextAnalyzed`** is `**true**` and `**--force-new-context-analysis**` is absent, exits **0** without running the Factory (`**analysisSkipped**`, …). **SRS-59:** stale worktree registration recovery — see **§ Analysis git checkout** below. |
|
|
151
|
+
| `analysis` | Optional tail: `**--force-new-context-analysis**`. **`--upload`** → usage exit. **`--synthesis-only`**: accepted as a **hidden** Commander option (legacy scripts); **ignored** with one stderr **`[deprecated]`** line (**SRS-60**). | **SRS-32** full **Factory** loop: synthesis convergence (until no missing artefacts), coverage, zero-ref, report, **link mapping**, index assembly; **Phase 7** backend sync is skipped in CLI (**`skipBackendSync`**). **On success:** always promotes **`.gluecharm/context`** from the analysis worktree into **`<repoRoot>`** unless **`--no-promote`** (stderr **`[pipeline:analysis]`**); **`easyspecs.analysis.promoteContextToWorkspace`** does **not** apply to this step. Push context with **`upload context`** / **`upload republish`** after analysis if you need cloud sync. Factory timing from `**merged.factory`** + `**--ci**` defaults. Debug: `**easyspecs.factory.debug**`. OpenCode options from `**merged.pipelineOpenCode**`. **SRS-46:** if `**easyspecs.factory.cloudContextAnalyzed`** is `**true**` and `**--force-new-context-analysis**` is absent, exits **0** without running the Factory (`**analysisSkipped**`, …). **SRS-59:** stale worktree registration recovery — see **§ Analysis git checkout** below. |
|
|
152
152
|
| `update context` | — (no subcommand flags; **SRS-60** removed `**--upload**`) | **SRS-55:** incremental context refresh — baseline → git delta → worktree → `**changes-since-date.md`** → optional remediation → **`--promote` / `--no-promote**` (global) → persist `**lastRunAt**`. Run **`upload context`** separately if you need cloud sync. |
|
|
153
153
|
| `diagnose reference-coverage` | `**--root workspace**` | `**--root worktree**`, optional `**--worktree <path>**` | Gate when `**easyspecs.diagnose.zeroReference.maxPercentNonReferenced**` is a finite number (not `**null**`): failure when metric exceeds it. |
|
|
154
154
|
| `diagnose coordination-duplicates` | Same `**--root**` / `**--worktree**` | `**easyspecs.diagnose.coordinationDuplicates.strict**`: when `**true**` (default), duplicate/orphan issues fail the exit code. |
|
package/dist/main.cjs
CHANGED
|
@@ -10703,7 +10703,7 @@ var {
|
|
|
10703
10703
|
function createEasyspecsCliProgram() {
|
|
10704
10704
|
const program2 = new Command();
|
|
10705
10705
|
program2.name("easyspecs-cli").allowExcessArguments(false).enablePositionalOptions();
|
|
10706
|
-
program2.option("--cwd <dir>", "Repository root (default: current directory)").option("--ci", "Non-interactive; fail fast if configuration is missing").option("--json", "Print one JSON summary line on stdout").option("--verbose", "Extra stderr logging").option("--config <path>", "Configuration file path (accepted; currently unused)").option("--api-base-url <url>", "System Manager API origin (overrides config)").option("--session-path <file>", "Session JSON for this run (overrides config)").option("--environment <environment>", "Effective deployment (alias: --env)").option("--env <environment>", "Alias for --environment").option("--promote", "
|
|
10706
|
+
program2.option("--cwd <dir>", "Repository root (default: current directory)").option("--ci", "Non-interactive; fail fast if configuration is missing").option("--json", "Print one JSON summary line on stdout").option("--verbose", "Extra stderr logging").option("--config <path>", "Configuration file path (accepted; currently unused)").option("--api-base-url <url>", "System Manager API origin (overrides config)").option("--session-path <file>", "Session JSON for this run (overrides config)").option("--environment <environment>", "Effective deployment (alias: --env)").option("--env <environment>", "Alias for --environment").option("--promote", "After run synthesis: force context promotion when config would disable it").option("--no-promote", "After run synthesis or analysis: skip copying .gluecharm/context into repo for this run");
|
|
10707
10707
|
program2.command("help").description("Show help");
|
|
10708
10708
|
program2.command("version").description("Print CLI version");
|
|
10709
10709
|
program2.command("doctor").description("Check readiness and/or inspect configuration").option("--readiness", "Print readiness summary (default)").option("--inspect-config", "Print redacted merged configuration");
|
|
@@ -21119,13 +21119,28 @@ async function runGenerateContextFactory(deps) {
|
|
|
21119
21119
|
};
|
|
21120
21120
|
await Promise.resolve(deps.post(payload));
|
|
21121
21121
|
};
|
|
21122
|
+
const logFactoryEnd = (r) => {
|
|
21123
|
+
const log = deps.factoryLog;
|
|
21124
|
+
if (!log) {
|
|
21125
|
+
return;
|
|
21126
|
+
}
|
|
21127
|
+
const tag = r.cancelled === true ? "cancelled" : r.ok ? "succeeded" : "failed";
|
|
21128
|
+
const tail = r.message ? ` \u2014 ${r.message}` : "";
|
|
21129
|
+
log(`[factory] Generate Context factory ended (${tag}) \u2014 ${String(r.totalElapsedMs)}ms${tail}`);
|
|
21130
|
+
};
|
|
21131
|
+
const fin = (r) => {
|
|
21132
|
+
logFactoryEnd(r);
|
|
21133
|
+
return r;
|
|
21134
|
+
};
|
|
21122
21135
|
const fail = async (message) => {
|
|
21123
21136
|
await post();
|
|
21124
21137
|
let ff = buildFactoryFailuresFromRows(phases);
|
|
21125
21138
|
if (ff.length === 0) {
|
|
21126
21139
|
ff = syntheticUnknownFactoryFailure(message);
|
|
21127
21140
|
}
|
|
21128
|
-
|
|
21141
|
+
const r = { ok: false, message, totalElapsedMs: macroEnd(), factoryFailures: ff };
|
|
21142
|
+
logFactoryEnd(r);
|
|
21143
|
+
return r;
|
|
21129
21144
|
};
|
|
21130
21145
|
const pipelineCtx = {
|
|
21131
21146
|
signal: deps.signal,
|
|
@@ -21140,7 +21155,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21140
21155
|
if (isAborted(signal)) {
|
|
21141
21156
|
setRowTimed("synthesis_convergence", "cancelled", "Stopped.");
|
|
21142
21157
|
await post();
|
|
21143
|
-
return { ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21158
|
+
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21144
21159
|
}
|
|
21145
21160
|
let delayMs = config.initialDelayMs;
|
|
21146
21161
|
let outerIter = 0;
|
|
@@ -21149,7 +21164,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21149
21164
|
if (isAborted(signal)) {
|
|
21150
21165
|
setRowTimed("synthesis_convergence", "cancelled");
|
|
21151
21166
|
await post();
|
|
21152
|
-
return { ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21167
|
+
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21153
21168
|
}
|
|
21154
21169
|
if (!resumeSynthesis) {
|
|
21155
21170
|
setRowTimed("create_analysis_worktree", "running", "Creating git analysis worktree\u2026");
|
|
@@ -21166,7 +21181,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21166
21181
|
setRowTimed("materialize_opencode_agents", "cancelled");
|
|
21167
21182
|
setRowTimed("synthesis_convergence", "cancelled");
|
|
21168
21183
|
await post();
|
|
21169
|
-
return { ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21184
|
+
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21170
21185
|
}
|
|
21171
21186
|
setRowTimed("materialize_opencode_agents", "running", "Materializing OpenCode agents\u2026");
|
|
21172
21187
|
await post();
|
|
@@ -21199,7 +21214,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21199
21214
|
if (isAborted(signal)) {
|
|
21200
21215
|
setRowTimed("synthesis_convergence", "cancelled");
|
|
21201
21216
|
await post();
|
|
21202
|
-
return { ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21217
|
+
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21203
21218
|
}
|
|
21204
21219
|
setRowTimed(
|
|
21205
21220
|
"synthesis_convergence",
|
|
@@ -21212,7 +21227,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21212
21227
|
if (syn.cancelled || isAborted(signal)) {
|
|
21213
21228
|
setRowTimed("synthesis_convergence", "cancelled");
|
|
21214
21229
|
await post();
|
|
21215
|
-
return { ok: false, cancelled: true, message: syn.message ?? "Synthesis cancelled.", totalElapsedMs: macroEnd() };
|
|
21230
|
+
return fin({ ok: false, cancelled: true, message: syn.message ?? "Synthesis cancelled.", totalElapsedMs: macroEnd() });
|
|
21216
21231
|
}
|
|
21217
21232
|
if (!syn.ok) {
|
|
21218
21233
|
setRowTimed("synthesis_convergence", "failed", syn.message ?? "Synthesis failed.");
|
|
@@ -21246,7 +21261,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21246
21261
|
} catch {
|
|
21247
21262
|
setRowTimed("synthesis_convergence", "cancelled");
|
|
21248
21263
|
await post();
|
|
21249
|
-
return { ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21264
|
+
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21250
21265
|
}
|
|
21251
21266
|
delayMs = computeNextBackoffDelay(delayMs, config.backoffMultiplier, config.maxDelayMs);
|
|
21252
21267
|
setRowTimed("synthesis_convergence", "pending", "Next pass: resume parallel pool on same checkout\u2026");
|
|
@@ -21256,12 +21271,12 @@ async function runGenerateContextFactory(deps) {
|
|
|
21256
21271
|
setRowTimed("synthesis_convergence", "succeeded", "No missing artefacts.");
|
|
21257
21272
|
await post();
|
|
21258
21273
|
if (config.synthesisOnly) {
|
|
21259
|
-
return { ok: true, message: "Synthesis-only analysis complete.", totalElapsedMs: macroEnd() };
|
|
21274
|
+
return fin({ ok: true, message: "Synthesis-only analysis complete.", totalElapsedMs: macroEnd() });
|
|
21260
21275
|
}
|
|
21261
21276
|
if (isAborted(signal)) {
|
|
21262
21277
|
setRowTimed("reference_coverage", "cancelled");
|
|
21263
21278
|
await post();
|
|
21264
|
-
return { ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21279
|
+
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21265
21280
|
}
|
|
21266
21281
|
setRowTimed("reference_coverage", "running");
|
|
21267
21282
|
bumpPhaseRunCount("reference_coverage");
|
|
@@ -21277,7 +21292,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21277
21292
|
if (isAborted(signal)) {
|
|
21278
21293
|
setRowTimed("zero_reference_remediation_convergence", "cancelled");
|
|
21279
21294
|
await post();
|
|
21280
|
-
return { ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21295
|
+
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21281
21296
|
}
|
|
21282
21297
|
let remDelay = config.synthesisRemediationShareBackoff ? delayMs : config.initialDelayMs;
|
|
21283
21298
|
let remIter = 0;
|
|
@@ -21285,7 +21300,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21285
21300
|
if (isAborted(signal)) {
|
|
21286
21301
|
setRowTimed("zero_reference_remediation_convergence", "cancelled");
|
|
21287
21302
|
await post();
|
|
21288
|
-
return { ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21303
|
+
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21289
21304
|
}
|
|
21290
21305
|
setRowTimed("zero_reference_remediation_convergence", "running");
|
|
21291
21306
|
bumpPhaseRunCount("zero_reference_remediation_convergence");
|
|
@@ -21294,7 +21309,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21294
21309
|
if (rem.cancelled || isAborted(signal)) {
|
|
21295
21310
|
setRowTimed("zero_reference_remediation_convergence", "cancelled");
|
|
21296
21311
|
await post();
|
|
21297
|
-
return { ok: false, cancelled: true, message: rem.message ?? "Remediation cancelled.", totalElapsedMs: macroEnd() };
|
|
21312
|
+
return fin({ ok: false, cancelled: true, message: rem.message ?? "Remediation cancelled.", totalElapsedMs: macroEnd() });
|
|
21298
21313
|
}
|
|
21299
21314
|
if (!rem.ok) {
|
|
21300
21315
|
setRowTimed("zero_reference_remediation_convergence", "failed", rem.message);
|
|
@@ -21328,7 +21343,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21328
21343
|
} catch {
|
|
21329
21344
|
setRowTimed("zero_reference_remediation_convergence", "cancelled");
|
|
21330
21345
|
await post();
|
|
21331
|
-
return { ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21346
|
+
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21332
21347
|
}
|
|
21333
21348
|
remDelay = computeNextBackoffDelay(remDelay, config.backoffMultiplier, config.maxDelayMs);
|
|
21334
21349
|
}
|
|
@@ -21337,7 +21352,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21337
21352
|
if (isAborted(signal)) {
|
|
21338
21353
|
setRowTimed("link_mapping_pipeline", "cancelled");
|
|
21339
21354
|
await post();
|
|
21340
|
-
return { ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21355
|
+
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21341
21356
|
}
|
|
21342
21357
|
setRowTimed("link_mapping_pipeline", "running", "Refreshing link navigation after remediation\u2026");
|
|
21343
21358
|
bumpPhaseRunCount("link_mapping_pipeline");
|
|
@@ -21353,7 +21368,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21353
21368
|
if (isAborted(signal)) {
|
|
21354
21369
|
setRowTimed("reference_coverage", "cancelled");
|
|
21355
21370
|
await post();
|
|
21356
|
-
return { ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21371
|
+
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21357
21372
|
}
|
|
21358
21373
|
setRowTimed("reference_coverage", "running", "Refreshing coverage after remediation\u2026");
|
|
21359
21374
|
bumpPhaseRunCount("reference_coverage");
|
|
@@ -21392,7 +21407,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21392
21407
|
if (isAborted(signal)) {
|
|
21393
21408
|
setRowTimed("reference_coverage_execution_report", "cancelled");
|
|
21394
21409
|
await post();
|
|
21395
|
-
return { ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21410
|
+
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21396
21411
|
}
|
|
21397
21412
|
setRowTimed("reference_coverage_execution_report", "running");
|
|
21398
21413
|
bumpPhaseRunCount("reference_coverage_execution_report");
|
|
@@ -21401,7 +21416,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21401
21416
|
if (rep.cancelled || isAborted(signal)) {
|
|
21402
21417
|
setRowTimed("reference_coverage_execution_report", "cancelled", rep.message);
|
|
21403
21418
|
await post();
|
|
21404
|
-
return { ok: false, cancelled: true, message: rep.message ?? "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21419
|
+
return fin({ ok: false, cancelled: true, message: rep.message ?? "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21405
21420
|
}
|
|
21406
21421
|
if (!rep.ok) {
|
|
21407
21422
|
setRowTimed("reference_coverage_execution_report", "failed", rep.message);
|
|
@@ -21413,7 +21428,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21413
21428
|
if (isAborted(signal)) {
|
|
21414
21429
|
setRowTimed("link_mapping_pipeline", "cancelled");
|
|
21415
21430
|
await post();
|
|
21416
|
-
return { ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21431
|
+
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21417
21432
|
}
|
|
21418
21433
|
setRowTimed("link_mapping_pipeline", "running");
|
|
21419
21434
|
bumpPhaseRunCount("link_mapping_pipeline");
|
|
@@ -21429,7 +21444,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21429
21444
|
if (isAborted(signal)) {
|
|
21430
21445
|
setRowTimed("assemble_application_context_index", "cancelled");
|
|
21431
21446
|
await post();
|
|
21432
|
-
return { ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21447
|
+
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21433
21448
|
}
|
|
21434
21449
|
setRowTimed("assemble_application_context_index", "running");
|
|
21435
21450
|
bumpPhaseRunCount("assemble_application_context_index");
|
|
@@ -21445,7 +21460,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21445
21460
|
if (isAborted(signal)) {
|
|
21446
21461
|
setRowTimed("backend_context_sync", "cancelled");
|
|
21447
21462
|
await post();
|
|
21448
|
-
return { ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() };
|
|
21463
|
+
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21449
21464
|
}
|
|
21450
21465
|
setRowTimed("backend_context_sync", "running");
|
|
21451
21466
|
bumpPhaseRunCount("backend_context_sync");
|
|
@@ -21458,7 +21473,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21458
21473
|
}
|
|
21459
21474
|
setRowTimed("backend_context_sync", "succeeded", up.message);
|
|
21460
21475
|
await post();
|
|
21461
|
-
return { ok: true, message: "Analysis complete.", totalElapsedMs: macroEnd() };
|
|
21476
|
+
return fin({ ok: true, message: "Analysis complete.", totalElapsedMs: macroEnd() });
|
|
21462
21477
|
} catch (e) {
|
|
21463
21478
|
const msg = e instanceof Error ? e.message : String(e);
|
|
21464
21479
|
return fail(msg);
|
|
@@ -24500,6 +24515,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
24500
24515
|
};
|
|
24501
24516
|
return {
|
|
24502
24517
|
signal,
|
|
24518
|
+
factoryLog: log,
|
|
24503
24519
|
config: { ...macroConfig, ...input.synthesisOnly ? { synthesisOnly: true } : {} },
|
|
24504
24520
|
sleep: (ms) => sleepUntilAborted(ms, signal),
|
|
24505
24521
|
post: (payload) => {
|
|
@@ -28499,6 +28515,27 @@ async function main() {
|
|
|
28499
28515
|
skipBackendSync: true
|
|
28500
28516
|
});
|
|
28501
28517
|
const res = await runGenerateContextFactory(deps);
|
|
28518
|
+
if (res.ok && res.cancelled !== true && flags.promote !== false) {
|
|
28519
|
+
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
28520
|
+
const wt = snap?.adHocWorktreePath?.trim();
|
|
28521
|
+
if (wt) {
|
|
28522
|
+
const sourceCtx = path59.join(wt, ".gluecharm", "context");
|
|
28523
|
+
if (fs59.existsSync(sourceCtx)) {
|
|
28524
|
+
const n = promoteContextDirectoryToWorkspaceFs(sourceCtx, repoRoot);
|
|
28525
|
+
logErr(flags, `[pipeline:analysis] promoted ${String(n.filesCopied)} file(s) \u2192 ${repoRoot}`);
|
|
28526
|
+
} else {
|
|
28527
|
+
logErr(flags, `[pipeline:analysis] promote skipped: missing ${sourceCtx}`);
|
|
28528
|
+
}
|
|
28529
|
+
} else {
|
|
28530
|
+
logErr(flags, "[pipeline:analysis] promote skipped: no adHocWorktreePath in workspace snapshot");
|
|
28531
|
+
}
|
|
28532
|
+
} else if (res.ok && res.cancelled !== true && flags.promote === false) {
|
|
28533
|
+
logErr(flags, "[pipeline:analysis] promotion skipped (--no-promote)");
|
|
28534
|
+
}
|
|
28535
|
+
{
|
|
28536
|
+
const outcome = res.cancelled === true ? "cancelled" : res.ok ? "ok" : "failed";
|
|
28537
|
+
logErr(flags, `[pipeline:analysis] easyspecs-cli analysis finished (${outcome}) \u2014 ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
28538
|
+
}
|
|
28502
28539
|
const analysisEnvelope = {
|
|
28503
28540
|
ok: res.ok,
|
|
28504
28541
|
cancelled: res.cancelled,
|