@gluecharm-lab/easyspecs-cli 0.0.28 → 0.1.1
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 +1 -1
- package/commands.md +8 -8
- package/dist/main.cjs +207 -82
- package/dist/main.cjs.map +3 -3
- package/error-code.md +75 -81
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -219,7 +219,7 @@ These appear **before** the subcommand (everything after the first non-flag toke
|
|
|
219
219
|
| ---- | ------ |
|
|
220
220
|
| `--cwd <dir>` | Repository root for git resolution and paths (default: current working directory). |
|
|
221
221
|
| `--ci` | Non-interactive mode; affects merged settings (e.g. Factory outer-iteration default). **`EASYSPECS_CI` is not read** — use this flag. |
|
|
222
|
-
| `--json` | On supported exits, one JSON summary line on stdout. On **non-zero** exits, the line includes **`exitCode`** (number) and **`exitMeaning`** (one-line classification) alongside any command-specific fields.
|
|
222
|
+
| `--json` | On supported exits, one JSON summary line on stdout. On **non-zero** exits, the line includes **`exitCode`** (number) and **`exitMeaning`** (one-line classification) alongside any command-specific fields. Factory / pipeline failures include **`factoryFailures`** (per failed phase), **`failurePhase`**, and **`validationExitId`** (legacy alias of **`failureExitId`**). See [error-code.md](./error-code.md) — OS exit **`5`** is **not** used (**SRS-70**). |
|
|
223
223
|
| `--verbose` | Extra stderr logging where implemented. |
|
|
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**. |
|
package/commands.md
CHANGED
|
@@ -24,21 +24,21 @@ Quick usage:
|
|
|
24
24
|
easyspecs-cli help
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
### Factory
|
|
27
|
+
### Factory failure reporting (**SRS-57** / **SRS-70**)
|
|
28
28
|
|
|
29
|
-
When `**easyspecs-cli analysis`** exits
|
|
29
|
+
When `**easyspecs-cli analysis`** exits **non-zero** with factory failures, human stderr prints a short banner and **one bullet per failed factory phase** (readable label, `**failureExitId**`, normative `**title**`, optional `**detail**`). **OS exit `5` is never used** — each phase maps to a dedicated code (**50–58**), **59** when multiple distinct phases fail in one run, or **49** when unattributed. `**--json**` adds:
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
| JSON key | Meaning |
|
|
33
33
|
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
34
|
-
| `**factoryFailures**` | Array of `**{ factory, phase, exitCode, failureExitId, title, validationExitId
|
|
34
|
+
| `**factoryFailures**` | Array of `**{ factory, phase, exitCode, failureExitId, title, validationExitId?, detail?, validationSubcode? }**` — `**failureExitId**` is the canonical `**major.minor**` id (**SRS-58**); `**major**` matches **`process.exit`** (**SRS-70**). See `[error-code.md](./error-code.md)`. |
|
|
35
35
|
| `**failurePhase**` | Last failed phase in macro order (alias for scripts). |
|
|
36
|
-
| `**validationExitId**` |
|
|
36
|
+
| `**validationExitId**` | Legacy alias: same string as `**failureExitId**` when present. |
|
|
37
37
|
| `**exitMeaning**` | First failure `**title**`, or that title plus “and *N* other pipeline phases failed”. |
|
|
38
|
-
| `**error**` | Orchestrator message; if several phases failed, a short appendix lists extra `**
|
|
38
|
+
| `**error**` | Orchestrator message; if several phases failed, a short appendix lists extra `**failureExitId`**s (see `[factoryValidationFailures.ts](../../src/factory/factoryValidationFailures.ts)`). |
|
|
39
39
|
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
**Phase → OS exit (generate_context):** **50** `create_analysis_worktree`, **51** `materialize_opencode_agents`, **52** `synthesis_convergence`, **53** `reference_coverage`, **54** `zero_reference_remediation_convergence`, **55** `reference_coverage_execution_report`, **56** `link_mapping_pipeline`, **57** `assemble_application_context_index`, **58** `backend_context_sync`, **49** unknown / unattributed. Full table: `[error-code.md](./error-code.md)`.
|
|
42
42
|
|
|
43
43
|
**Optional `validationSubcode` (v1):** `**R5_MACRO_PING_PONG`** when synthesis `**detail**` notes **R5** unstable convergence; `**COVERAGE_PERCENT_THRESHOLD`** when reference-coverage `**detail**` matches the strict percent gate pattern.
|
|
44
44
|
|
|
@@ -53,7 +53,7 @@ These flags may appear **before** the subcommand. Parsing and command registrati
|
|
|
53
53
|
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
54
54
|
| `--cwd <dir>` | Repository root for git resolution and file paths (default: current working directory). |
|
|
55
55
|
| `--ci` | Non-interactive mode; feeds into merged settings (e.g. Factory outer-iteration default when unlimited). `**EASYSPECS_CI` is not read** — use this flag in CI. |
|
|
56
|
-
| `--json` | On supported exits, prints one JSON summary line on stdout; suppresses some human-oriented stderr unless `--verbose`. On `**analysis
|
|
56
|
+
| `--json` | On supported exits, prints one JSON summary line on stdout; suppresses some human-oriented stderr unless `--verbose`. On `**analysis**` factory failure, the JSON line includes `**factoryFailures`** (**SRS-57** — one object per `**failed`** factory phase) plus `**failurePhase**`, `**validationExitId**`, composed `**error**`, and `**exitMeaning**` tailored to the first failure. **Exit codes:** **[SRS-70](../../.gluecharm/docs/srs/srs-70.md)** — OS **5** is not used; see `[error-code.md](./error-code.md)`. |
|
|
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. |
|
|
@@ -185,7 +185,7 @@ Each row lists **command-specific CLI tokens**, then **what configuration applie
|
|
|
185
185
|
| `diagnose coverage-report` | Same `**--root**` / `**--worktree**` | Uses repo/worktree paths only; no extra env in `main.ts`. |
|
|
186
186
|
| `diagnose missing-artefacts` | Same `**--root**` / `**--worktree**` | Reads artefact snapshot from workspace state; no OpenCode. |
|
|
187
187
|
| `diagnose zero-reference` | Optional `**--worktree <path>**` (no `--root` branch in this handler) | `**requireOpenCode**`; `**merged.pipelineOpenCode**` for pool concurrency/argv/timeout. Checkout from `**--worktree**` or snapshot (`[resolveAdHocCheckoutRoot](../../src/cli/main.ts)`). On full success, runs **SRS-51** markdown link graph on `**<checkout>/.gluecharm/context`** before exit (**non-zero** if link validation fails). |
|
|
188
|
-
| `context link-graph` | `**--root workspace`** | `**--root worktree**`, optional `**--worktree <path>**` | **SRS-51:** deterministic navigation sections in context markdown under `**<root>/.gluecharm/context`**. No OpenCode. `**--json**`: `**ok**`, `**contextDir**`, `**error**`, `**brokenLinks**`. Exit
|
|
188
|
+
| `context link-graph` | `**--root workspace`** | `**--root worktree**`, optional `**--worktree <path>**` | **SRS-51:** deterministic navigation sections in context markdown under `**<root>/.gluecharm/context`**. No OpenCode. `**--json**`: `**ok**`, `**contextDir**`, `**error**`, `**brokenLinks**`. Exit **78** on broken relative links inside EasySpecs nav regions (**SRS-70**). |
|
|
189
189
|
| `context drift <referencePath>` | `**--label <slug>**`, `**--index <path>**`, `**--dry-run**`. Optional `**--root**` / `**--worktree**` tail tokens are accepted and ignored for v1 routing. | **SRS-56:** analysis worktree → OpenCode drift agent → `**.gluecharm/context/drift/drift-<slug>-<date>.md`** + reference index patch → global `**--promote` / `--no-promote**`. Success stdout: drift report path. |
|
|
190
190
|
| `download context` | Optional `**--force**`, `**--replace-from-cloud**` | **SRS-49:** requires `**auth`** session. `**GET /api/content/application/:id**` → `**srs_discovery**` ids → `**POST /api/batch/content/srs_discovery/get**` → writes files under `**<repoRoot>/.gluecharm/context**`. `**--force**` overwrites existing paths; `**--replace-from-cloud**` deletes local context files first (preserves root `**easyspecs-upload-target.json**`). `**--json**` stdout: `**downloaded**`, `**skipped**`, `**failed**`, `**localRemoved**`. Exit `**upload**` when any row fails. |
|
|
191
191
|
| `upload context` | — | Requires `**auth**` session. Context dir: `**<repoRoot>/.gluecharm/context**`. Project id: `**easyspecs.easyspecsProjectId**` in `**config.json**` only. **SRS-46:** on full success, optional cloud status GET (see `**fetchContextAnalyzedInCloud`**); `**--json**` may add `**contextAnalyzedInCloud**` / `**contextAnalyzedInCloudAt**`; updates `**easyspecs.factory.cloudContext***` when fetch is enabled (legacy `**easyspecs.analysis.cloudContext***`). |
|
package/dist/main.cjs
CHANGED
|
@@ -10640,17 +10640,53 @@ var fs62 = __toESM(require("node:fs"));
|
|
|
10640
10640
|
var path59 = __toESM(require("node:path"));
|
|
10641
10641
|
|
|
10642
10642
|
// src/cli/exitCodes.ts
|
|
10643
|
+
var OsExit = {
|
|
10644
|
+
/** Unknown / unclassified factory failure */
|
|
10645
|
+
factoryUnknown: 49,
|
|
10646
|
+
/** Rollup: multiple failed generate_context phases with distinct OS codes in one run */
|
|
10647
|
+
factoryMultiPhaseRollup: 59,
|
|
10648
|
+
createAnalysisWorktree: 50,
|
|
10649
|
+
materializeOpenCodeAgents: 51,
|
|
10650
|
+
synthesisConvergence: 52,
|
|
10651
|
+
referenceCoverage: 53,
|
|
10652
|
+
zeroReferenceRemediation: 54,
|
|
10653
|
+
referenceCoverageExecutionReport: 55,
|
|
10654
|
+
linkMappingPipeline: 56,
|
|
10655
|
+
assembleApplicationContextIndex: 57,
|
|
10656
|
+
backendContextSync: 58,
|
|
10657
|
+
driftEmptyBundle: 60,
|
|
10658
|
+
driftUnresolvedReferenceRoot: 61,
|
|
10659
|
+
driftManifestFailed: 62,
|
|
10660
|
+
driftReportWriteFailed: 63,
|
|
10661
|
+
driftIndexPatchFailed: 64,
|
|
10662
|
+
diagnoseReferenceCoveragePipeline: 70,
|
|
10663
|
+
diagnoseReferenceCoverageThreshold: 71,
|
|
10664
|
+
diagnoseCoordinationDuplicatesPolicy: 72,
|
|
10665
|
+
diagnoseCoordinationDuplicatesEngine: 73,
|
|
10666
|
+
diagnoseCoverageReport: 74,
|
|
10667
|
+
diagnoseZeroReferenceReadCoverage: 75,
|
|
10668
|
+
diagnoseZeroReferenceLinkMapping: 76,
|
|
10669
|
+
diagnoseZeroReferencePool: 77,
|
|
10670
|
+
contextLinkGraph: 78,
|
|
10671
|
+
resumeSynthesisIndex: 79,
|
|
10672
|
+
runSynthesisPipeline: 80,
|
|
10673
|
+
aceLearnTrace: 81,
|
|
10674
|
+
aceAutoLearnPool: 82,
|
|
10675
|
+
updateContextFactory: 83
|
|
10676
|
+
};
|
|
10643
10677
|
var ExitCode = {
|
|
10644
10678
|
ok: 0,
|
|
10645
10679
|
usage: 2,
|
|
10646
10680
|
misconfiguration: 3,
|
|
10647
10681
|
opencode: 4,
|
|
10648
|
-
validation: 5,
|
|
10649
10682
|
auth: 6,
|
|
10650
10683
|
upload: 7,
|
|
10651
10684
|
cancelled: 8,
|
|
10652
10685
|
internal: 99
|
|
10653
10686
|
};
|
|
10687
|
+
function failureExitIdFromParts(exitCode, minor) {
|
|
10688
|
+
return `${String(exitCode)}.${String(minor)}`;
|
|
10689
|
+
}
|
|
10654
10690
|
function describeExitCode(code) {
|
|
10655
10691
|
switch (code) {
|
|
10656
10692
|
case ExitCode.ok:
|
|
@@ -10661,8 +10697,6 @@ function describeExitCode(code) {
|
|
|
10661
10697
|
return "Configuration or repo layout problem \u2014 fix `.easyspecs/config.json`, paths, or prerequisites, then retry.";
|
|
10662
10698
|
case ExitCode.opencode:
|
|
10663
10699
|
return "OpenCode (agent runner) failed \u2014 check `opencode` install, credentials, and stderr from the tool run.";
|
|
10664
|
-
case ExitCode.validation:
|
|
10665
|
-
return "Validation or factory pipeline did not succeed \u2014 see `error` above and logs for the failing phase (synthesis, coverage, remediation, index, etc.).";
|
|
10666
10700
|
case ExitCode.auth:
|
|
10667
10701
|
return "Authentication failed or session missing \u2014 run `easyspecs-cli auth login` or fix CI credentials in config.";
|
|
10668
10702
|
case ExitCode.upload:
|
|
@@ -10671,6 +10705,66 @@ function describeExitCode(code) {
|
|
|
10671
10705
|
return "Operation was cancelled (abort/stop).";
|
|
10672
10706
|
case ExitCode.internal:
|
|
10673
10707
|
return "Unexpected internal CLI error \u2014 retry; if it persists, report with full stderr and `--verbose` output.";
|
|
10708
|
+
case OsExit.factoryUnknown:
|
|
10709
|
+
return "Factory pipeline failed (phase could not be classified). See `error` and logs; retry with --verbose.";
|
|
10710
|
+
case OsExit.factoryMultiPhaseRollup:
|
|
10711
|
+
return "Multiple factory pipeline phases failed in one run. Inspect `factoryFailures` for each phase.";
|
|
10712
|
+
case OsExit.createAnalysisWorktree:
|
|
10713
|
+
return "Analysis Git worktree could not be prepared. Check disk space, permissions, and a valid Git checkout.";
|
|
10714
|
+
case OsExit.materializeOpenCodeAgents:
|
|
10715
|
+
return "OpenCode agent files could not be installed into the analysis worktree.";
|
|
10716
|
+
case OsExit.synthesisConvergence:
|
|
10717
|
+
return "Context synthesis did not finish successfully. Inspect OpenCode logs and workstation output.";
|
|
10718
|
+
case OsExit.referenceCoverage:
|
|
10719
|
+
return "Reference coverage could not be computed or written. Check coverage JSON and schema.";
|
|
10720
|
+
case OsExit.zeroReferenceRemediation:
|
|
10721
|
+
return "Zero-reference remediation did not complete. Inspect remediation logs and outputs.";
|
|
10722
|
+
case OsExit.referenceCoverageExecutionReport:
|
|
10723
|
+
return "Coverage execution report could not be generated. Ensure coverage inputs exist.";
|
|
10724
|
+
case OsExit.linkMappingPipeline:
|
|
10725
|
+
return "Context link graph could not be updated. Check coordination JSON and markdown.";
|
|
10726
|
+
case OsExit.assembleApplicationContextIndex:
|
|
10727
|
+
return "Application context index could not be assembled or failed schema validation.";
|
|
10728
|
+
case OsExit.backendContextSync:
|
|
10729
|
+
return "Upload or cloud sync after analysis did not succeed.";
|
|
10730
|
+
case OsExit.driftEmptyBundle:
|
|
10731
|
+
return "Context drift: reference bundle was empty or could not be read.";
|
|
10732
|
+
case OsExit.driftUnresolvedReferenceRoot:
|
|
10733
|
+
return "Context drift: reference root document could not be resolved.";
|
|
10734
|
+
case OsExit.driftManifestFailed:
|
|
10735
|
+
return "Context drift: comparison manifest could not be built.";
|
|
10736
|
+
case OsExit.driftReportWriteFailed:
|
|
10737
|
+
return "Context drift: report markdown could not be written.";
|
|
10738
|
+
case OsExit.driftIndexPatchFailed:
|
|
10739
|
+
return "Context drift: reference index could not be updated with the drift link.";
|
|
10740
|
+
case OsExit.diagnoseReferenceCoveragePipeline:
|
|
10741
|
+
return "diagnose reference-coverage: pipeline or write failed.";
|
|
10742
|
+
case OsExit.diagnoseReferenceCoverageThreshold:
|
|
10743
|
+
return "diagnose reference-coverage: percentNonReferenced exceeded the configured threshold.";
|
|
10744
|
+
case OsExit.diagnoseCoordinationDuplicatesPolicy:
|
|
10745
|
+
return "diagnose coordination-duplicates: strict mode reported duplicates or orphan markdown.";
|
|
10746
|
+
case OsExit.diagnoseCoordinationDuplicatesEngine:
|
|
10747
|
+
return "diagnose coordination-duplicates: scan or I/O failed.";
|
|
10748
|
+
case OsExit.diagnoseCoverageReport:
|
|
10749
|
+
return "diagnose coverage-report: report generation failed.";
|
|
10750
|
+
case OsExit.diagnoseZeroReferenceReadCoverage:
|
|
10751
|
+
return "diagnose zero-reference: could not read coverage / zero-reference inputs.";
|
|
10752
|
+
case OsExit.diagnoseZeroReferenceLinkMapping:
|
|
10753
|
+
return "diagnose zero-reference: link mapping after remediation failed.";
|
|
10754
|
+
case OsExit.diagnoseZeroReferencePool:
|
|
10755
|
+
return "diagnose zero-reference: remediation pool reported failures or cancellation.";
|
|
10756
|
+
case OsExit.contextLinkGraph:
|
|
10757
|
+
return "context link-graph: link mapping pipeline failed.";
|
|
10758
|
+
case OsExit.resumeSynthesisIndex:
|
|
10759
|
+
return "run synthesis resume-*: index assembly after remediation failed.";
|
|
10760
|
+
case OsExit.runSynthesisPipeline:
|
|
10761
|
+
return "run synthesis: pipeline did not complete successfully.";
|
|
10762
|
+
case OsExit.aceLearnTrace:
|
|
10763
|
+
return "ace learn: processing a trace failed.";
|
|
10764
|
+
case OsExit.aceAutoLearnPool:
|
|
10765
|
+
return "ace auto-learn: one or more learn runs failed.";
|
|
10766
|
+
case OsExit.updateContextFactory:
|
|
10767
|
+
return "update context: factory run did not succeed.";
|
|
10674
10768
|
default:
|
|
10675
10769
|
return `Non-zero exit (${String(code)}) \u2014 see stderr and any JSON \`error\` field for detail.`;
|
|
10676
10770
|
}
|
|
@@ -21612,9 +21706,19 @@ var FACTORY_PIPELINE_EXIT_CONDITIONS = {
|
|
|
21612
21706
|
function factoryFailureDisplayId(row2) {
|
|
21613
21707
|
return row2.failureExitId;
|
|
21614
21708
|
}
|
|
21709
|
+
function parseMajorFromFailureExitId(id) {
|
|
21710
|
+
const m = /^(\d+)\.\d+$/.exec(id.trim());
|
|
21711
|
+
if (!m) {
|
|
21712
|
+
return void 0;
|
|
21713
|
+
}
|
|
21714
|
+
const n = Number(m[1]);
|
|
21715
|
+
return Number.isFinite(n) ? n : void 0;
|
|
21716
|
+
}
|
|
21615
21717
|
function normalizeFactoryFailureRow(r) {
|
|
21616
|
-
const failureExitId = r.failureExitId ?? r.validationExitId ??
|
|
21617
|
-
const
|
|
21718
|
+
const failureExitId = r.failureExitId ?? r.validationExitId ?? failureExitIdFromParts(OsExit.factoryUnknown, 0);
|
|
21719
|
+
const exitCodeFromField = typeof r.exitCode === "number" ? r.exitCode : void 0;
|
|
21720
|
+
const exitCodeFromId = parseMajorFromFailureExitId(failureExitId);
|
|
21721
|
+
const exitCode = exitCodeFromField ?? exitCodeFromId ?? OsExit.factoryUnknown;
|
|
21618
21722
|
const factory = r.factory ?? "generate_context";
|
|
21619
21723
|
const base = {
|
|
21620
21724
|
factory,
|
|
@@ -21625,10 +21729,7 @@ function normalizeFactoryFailureRow(r) {
|
|
|
21625
21729
|
...typeof r.detail === "string" ? { detail: r.detail } : {},
|
|
21626
21730
|
...typeof r.validationSubcode === "string" ? { validationSubcode: r.validationSubcode } : {}
|
|
21627
21731
|
};
|
|
21628
|
-
|
|
21629
|
-
return { ...base, validationExitId: r.validationExitId ?? failureExitId };
|
|
21630
|
-
}
|
|
21631
|
-
return base;
|
|
21732
|
+
return { ...base, validationExitId: r.validationExitId ?? failureExitId };
|
|
21632
21733
|
}
|
|
21633
21734
|
var FACTORY_VALIDATION_PHASE_ORDER = [
|
|
21634
21735
|
"create_analysis_worktree",
|
|
@@ -21644,29 +21745,29 @@ var FACTORY_VALIDATION_PHASE_ORDER = [
|
|
|
21644
21745
|
var DETAIL_MAX = 600;
|
|
21645
21746
|
var ERROR_JOIN_MAX = 900;
|
|
21646
21747
|
var ADDITIONAL_APPEND_MAX = 200;
|
|
21647
|
-
var
|
|
21648
|
-
unknown_factory_phase:
|
|
21649
|
-
create_analysis_worktree:
|
|
21650
|
-
materialize_opencode_agents:
|
|
21651
|
-
synthesis_convergence:
|
|
21652
|
-
reference_coverage:
|
|
21653
|
-
zero_reference_remediation_convergence:
|
|
21654
|
-
reference_coverage_execution_report:
|
|
21655
|
-
link_mapping_pipeline:
|
|
21656
|
-
assemble_application_context_index:
|
|
21657
|
-
backend_context_sync:
|
|
21748
|
+
var PHASE_TO_OS_EXIT = {
|
|
21749
|
+
unknown_factory_phase: OsExit.factoryUnknown,
|
|
21750
|
+
create_analysis_worktree: OsExit.createAnalysisWorktree,
|
|
21751
|
+
materialize_opencode_agents: OsExit.materializeOpenCodeAgents,
|
|
21752
|
+
synthesis_convergence: OsExit.synthesisConvergence,
|
|
21753
|
+
reference_coverage: OsExit.referenceCoverage,
|
|
21754
|
+
zero_reference_remediation_convergence: OsExit.zeroReferenceRemediation,
|
|
21755
|
+
reference_coverage_execution_report: OsExit.referenceCoverageExecutionReport,
|
|
21756
|
+
link_mapping_pipeline: OsExit.linkMappingPipeline,
|
|
21757
|
+
assemble_application_context_index: OsExit.assembleApplicationContextIndex,
|
|
21758
|
+
backend_context_sync: OsExit.backendContextSync
|
|
21658
21759
|
};
|
|
21659
|
-
var
|
|
21660
|
-
|
|
21661
|
-
|
|
21662
|
-
|
|
21663
|
-
|
|
21664
|
-
|
|
21665
|
-
|
|
21666
|
-
|
|
21667
|
-
|
|
21668
|
-
|
|
21669
|
-
|
|
21760
|
+
var TITLE_BY_PHASE = {
|
|
21761
|
+
unknown_factory_phase: "EasySpecs stopped: the failing pipeline phase could not be identified. Retry with --verbose; report this outcome if it persists.",
|
|
21762
|
+
create_analysis_worktree: "Could not prepare the analysis Git worktree (temporary checkout). Check disk space, repo permissions, and that the project is a valid Git checkout.",
|
|
21763
|
+
materialize_opencode_agents: "Could not install OpenCode agent files into the analysis worktree. Check bundled extension assets and disk permissions under the worktree path.",
|
|
21764
|
+
synthesis_convergence: "Context synthesis did not finish: required context files are still missing or invalid after retries. Inspect OpenCode errors and workstation logs for this phase.",
|
|
21765
|
+
reference_coverage: "Reference coverage could not be computed or written. Check coverage-reference-validation.json prerequisites and disk/schema errors.",
|
|
21766
|
+
zero_reference_remediation_convergence: "Zero-reference remediation did not complete successfully. Inspect remediation logs and zero-reference outputs for this checkout.",
|
|
21767
|
+
reference_coverage_execution_report: "Reference coverage execution report could not be generated. Ensure coverage inputs exist from the coverage phase; see coverage-reference-validation.json.",
|
|
21768
|
+
link_mapping_pipeline: "Context link graph (navigation links) could not be updated. Check coordination JSON and markdown under .gluecharm/context.",
|
|
21769
|
+
assemble_application_context_index: "Application context index could not be assembled or failed schema validation. Inspect index-application-context.json and preceding context files.",
|
|
21770
|
+
backend_context_sync: "Upload / cloud sync after analysis did not succeed. Check auth, project id, network, and upload error details."
|
|
21670
21771
|
};
|
|
21671
21772
|
var READABLE_PHASE_LABEL = {
|
|
21672
21773
|
create_analysis_worktree: "Analysis worktree",
|
|
@@ -21700,11 +21801,11 @@ function inferValidationSubcode(phase, detail) {
|
|
|
21700
21801
|
}
|
|
21701
21802
|
return void 0;
|
|
21702
21803
|
}
|
|
21703
|
-
function
|
|
21704
|
-
return
|
|
21804
|
+
function phaseToSemanticOsExitForGenerateContext(phase) {
|
|
21805
|
+
return PHASE_TO_OS_EXIT[phase] ?? OsExit.factoryUnknown;
|
|
21705
21806
|
}
|
|
21706
|
-
function
|
|
21707
|
-
return
|
|
21807
|
+
function titleForGenerateContextPhase(phase) {
|
|
21808
|
+
return TITLE_BY_PHASE[phase] ?? TITLE_BY_PHASE.unknown_factory_phase;
|
|
21708
21809
|
}
|
|
21709
21810
|
function readableLabelForFactoryPhase(phase) {
|
|
21710
21811
|
return READABLE_PHASE_LABEL[phase] ?? phase;
|
|
@@ -21713,33 +21814,53 @@ function phaseIndex(key) {
|
|
|
21713
21814
|
const i = FACTORY_VALIDATION_PHASE_ORDER.indexOf(key);
|
|
21714
21815
|
return i >= 0 ? i : 999;
|
|
21715
21816
|
}
|
|
21817
|
+
function finalizeFactoryFailuresForProcessExit(rows) {
|
|
21818
|
+
if (rows.length === 0) {
|
|
21819
|
+
return [];
|
|
21820
|
+
}
|
|
21821
|
+
const candidates = [...new Set(rows.map((r) => r.exitCode))];
|
|
21822
|
+
const processExit = candidates.length > 1 ? OsExit.factoryMultiPhaseRollup : candidates[0] ?? OsExit.factoryUnknown;
|
|
21823
|
+
return rows.map((r, i) => {
|
|
21824
|
+
const minor = processExit === OsExit.factoryMultiPhaseRollup ? i : 0;
|
|
21825
|
+
const fid = failureExitIdFromParts(processExit, minor);
|
|
21826
|
+
return {
|
|
21827
|
+
...r,
|
|
21828
|
+
exitCode: processExit,
|
|
21829
|
+
failureExitId: fid,
|
|
21830
|
+
validationExitId: fid
|
|
21831
|
+
};
|
|
21832
|
+
});
|
|
21833
|
+
}
|
|
21716
21834
|
function buildFactoryFailuresFromRows(phases) {
|
|
21717
21835
|
const failed = phases.filter((p) => p.status === "failed");
|
|
21718
21836
|
failed.sort((a, b) => phaseIndex(a.key) - phaseIndex(b.key));
|
|
21719
|
-
|
|
21720
|
-
const
|
|
21837
|
+
const semantic = failed.map((p) => {
|
|
21838
|
+
const os7 = phaseToSemanticOsExitForGenerateContext(p.key);
|
|
21721
21839
|
const sub = inferValidationSubcode(p.key, p.detail);
|
|
21840
|
+
const fid = failureExitIdFromParts(os7, 0);
|
|
21722
21841
|
return {
|
|
21723
21842
|
factory: "generate_context",
|
|
21724
21843
|
phase: p.key,
|
|
21725
|
-
exitCode:
|
|
21726
|
-
failureExitId:
|
|
21727
|
-
validationExitId:
|
|
21728
|
-
title:
|
|
21844
|
+
exitCode: os7,
|
|
21845
|
+
failureExitId: fid,
|
|
21846
|
+
validationExitId: fid,
|
|
21847
|
+
title: titleForGenerateContextPhase(p.key),
|
|
21729
21848
|
detail: trimDetail(p.detail),
|
|
21730
21849
|
...sub !== void 0 ? { validationSubcode: sub } : {}
|
|
21731
21850
|
};
|
|
21732
21851
|
});
|
|
21852
|
+
return finalizeFactoryFailuresForProcessExit(semantic);
|
|
21733
21853
|
}
|
|
21734
21854
|
function syntheticUnknownFactoryFailure(message) {
|
|
21855
|
+
const fid = failureExitIdFromParts(OsExit.factoryUnknown, 0);
|
|
21735
21856
|
return [
|
|
21736
21857
|
{
|
|
21737
21858
|
factory: "generate_context",
|
|
21738
21859
|
phase: "unknown_factory_phase",
|
|
21739
|
-
exitCode:
|
|
21740
|
-
failureExitId:
|
|
21741
|
-
validationExitId:
|
|
21742
|
-
title:
|
|
21860
|
+
exitCode: OsExit.factoryUnknown,
|
|
21861
|
+
failureExitId: fid,
|
|
21862
|
+
validationExitId: fid,
|
|
21863
|
+
title: titleForGenerateContextPhase("unknown_factory_phase"),
|
|
21743
21864
|
detail: trimDetail(message)
|
|
21744
21865
|
}
|
|
21745
21866
|
];
|
|
@@ -21747,7 +21868,8 @@ function syntheticUnknownFactoryFailure(message) {
|
|
|
21747
21868
|
function primaryFailureAliases(failures) {
|
|
21748
21869
|
const last = failures[failures.length - 1];
|
|
21749
21870
|
if (!last) {
|
|
21750
|
-
|
|
21871
|
+
const fid = failureExitIdFromParts(OsExit.factoryUnknown, 0);
|
|
21872
|
+
return { failurePhase: "unknown_factory_phase", validationExitId: fid };
|
|
21751
21873
|
}
|
|
21752
21874
|
return {
|
|
21753
21875
|
failurePhase: last.phase,
|
|
@@ -21767,7 +21889,7 @@ function exitMeaningFromFactoryFailures(failures) {
|
|
|
21767
21889
|
function composeFactoryValidationError(orchestratorMessage, failures) {
|
|
21768
21890
|
const m = orchestratorMessage?.trim() ?? "";
|
|
21769
21891
|
if (failures.length <= 1) {
|
|
21770
|
-
return m.length > 0 ? m : failures[0]?.title ?? "
|
|
21892
|
+
return m.length > 0 ? m : failures[0]?.title ?? "Factory pipeline failed.";
|
|
21771
21893
|
}
|
|
21772
21894
|
const extraIds = failures.slice(1).map((f) => factoryFailureDisplayId(f)).join(", ");
|
|
21773
21895
|
let appendix = `(+${String(failures.length - 1)} additional phase failure(s): ${extraIds})`;
|
|
@@ -25373,9 +25495,6 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25373
25495
|
|
|
25374
25496
|
// src/cli/failureExitRegistry.ts
|
|
25375
25497
|
var DRIFT_FACTORY = "context_drift";
|
|
25376
|
-
function failureExitIdFromParts(exitCode, minor) {
|
|
25377
|
-
return `${String(exitCode)}.${String(minor)}`;
|
|
25378
|
-
}
|
|
25379
25498
|
var DRIFT_META = {
|
|
25380
25499
|
INVALID_REFERENCE_PATH: {
|
|
25381
25500
|
phase: "resolve_reference_bundle",
|
|
@@ -25391,20 +25510,20 @@ var DRIFT_META = {
|
|
|
25391
25510
|
},
|
|
25392
25511
|
EMPTY_BUNDLE: {
|
|
25393
25512
|
phase: "resolve_reference_bundle",
|
|
25394
|
-
exitCode:
|
|
25395
|
-
minor:
|
|
25513
|
+
exitCode: OsExit.driftEmptyBundle,
|
|
25514
|
+
minor: 0,
|
|
25396
25515
|
title: "Reference bundle was empty or could not be read for drift analysis."
|
|
25397
25516
|
},
|
|
25398
25517
|
UNRESOLVED_REFERENCE_ROOT: {
|
|
25399
25518
|
phase: "resolve_reference_root",
|
|
25400
|
-
exitCode:
|
|
25401
|
-
minor:
|
|
25519
|
+
exitCode: OsExit.driftUnresolvedReferenceRoot,
|
|
25520
|
+
minor: 0,
|
|
25402
25521
|
title: "Reference root document could not be resolved. Use --index or ensure an index markdown exists."
|
|
25403
25522
|
},
|
|
25404
25523
|
MANIFEST_FAILED: {
|
|
25405
25524
|
phase: "build_comparison_manifest",
|
|
25406
|
-
exitCode:
|
|
25407
|
-
minor:
|
|
25525
|
+
exitCode: OsExit.driftManifestFailed,
|
|
25526
|
+
minor: 0,
|
|
25408
25527
|
title: "Comparison manifest could not be built for drift analysis."
|
|
25409
25528
|
},
|
|
25410
25529
|
AGENT_FAILED: {
|
|
@@ -25421,14 +25540,14 @@ var DRIFT_META = {
|
|
|
25421
25540
|
},
|
|
25422
25541
|
REPORT_WRITE_FAILED: {
|
|
25423
25542
|
phase: "validate_and_render_report",
|
|
25424
|
-
exitCode:
|
|
25425
|
-
minor:
|
|
25543
|
+
exitCode: OsExit.driftReportWriteFailed,
|
|
25544
|
+
minor: 0,
|
|
25426
25545
|
title: "Drift report markdown could not be written under the analysis worktree."
|
|
25427
25546
|
},
|
|
25428
25547
|
INDEX_PATCH_FAILED: {
|
|
25429
25548
|
phase: "update_reference_index",
|
|
25430
|
-
exitCode:
|
|
25431
|
-
minor:
|
|
25549
|
+
exitCode: OsExit.driftIndexPatchFailed,
|
|
25550
|
+
minor: 0,
|
|
25432
25551
|
title: "Reference root markdown could not be updated with the drift report link."
|
|
25433
25552
|
},
|
|
25434
25553
|
PROMOTE_FAILED: {
|
|
@@ -25484,10 +25603,7 @@ function contextDriftFactoryFailureRow(code, error) {
|
|
|
25484
25603
|
title: meta.title,
|
|
25485
25604
|
detail
|
|
25486
25605
|
};
|
|
25487
|
-
|
|
25488
|
-
return { ...base, validationExitId: failureExitId };
|
|
25489
|
-
}
|
|
25490
|
-
return base;
|
|
25606
|
+
return { ...base, validationExitId: failureExitId };
|
|
25491
25607
|
}
|
|
25492
25608
|
|
|
25493
25609
|
// src/cli/factoryValidationStderr.ts
|
|
@@ -28395,7 +28511,7 @@ function formatCliStderrLine(line, useAnsi) {
|
|
|
28395
28511
|
}
|
|
28396
28512
|
|
|
28397
28513
|
// src/cli/main.ts
|
|
28398
|
-
var PKG_VERSION = "0.
|
|
28514
|
+
var PKG_VERSION = "0.1.1";
|
|
28399
28515
|
function isNonEmptyFactoryFailureArray(x) {
|
|
28400
28516
|
if (!Array.isArray(x) || x.length === 0) {
|
|
28401
28517
|
return false;
|
|
@@ -28412,6 +28528,12 @@ function isNonEmptyFactoryFailureArray(x) {
|
|
|
28412
28528
|
}
|
|
28413
28529
|
return true;
|
|
28414
28530
|
}
|
|
28531
|
+
function processExitFromNormalizedFactoryFailures(rows) {
|
|
28532
|
+
return rows?.length ? rows[0].exitCode : OsExit.factoryUnknown;
|
|
28533
|
+
}
|
|
28534
|
+
function isContextDriftSrs70ValidationExit(code) {
|
|
28535
|
+
return code >= OsExit.driftEmptyBundle && code <= OsExit.driftIndexPatchFailed;
|
|
28536
|
+
}
|
|
28415
28537
|
function isEasyspecsConfigReadError(e) {
|
|
28416
28538
|
return e instanceof EasyspecsConfigInvalidJsonError || e instanceof EasyspecsConfigSchemaError;
|
|
28417
28539
|
}
|
|
@@ -29012,7 +29134,7 @@ async function main() {
|
|
|
29012
29134
|
finish(ExitCode.cancelled, { ok: false, error: "Remediation cancelled.", analysisWorktreePath: analysisRoot });
|
|
29013
29135
|
}
|
|
29014
29136
|
if (!poolRes.indexOk) {
|
|
29015
|
-
finish(
|
|
29137
|
+
finish(OsExit.resumeSynthesisIndex, {
|
|
29016
29138
|
ok: false,
|
|
29017
29139
|
error: poolRes.indexError ?? "Index failed after remediation.",
|
|
29018
29140
|
analysisWorktreePath: analysisRoot
|
|
@@ -29029,7 +29151,7 @@ async function main() {
|
|
|
29029
29151
|
finish(ExitCode.cancelled, { ok: false, error: "Remediation cancelled.", analysisWorktreePath: analysisRoot });
|
|
29030
29152
|
}
|
|
29031
29153
|
if (!poolRes.indexOk) {
|
|
29032
|
-
finish(
|
|
29154
|
+
finish(OsExit.resumeSynthesisIndex, {
|
|
29033
29155
|
ok: false,
|
|
29034
29156
|
error: poolRes.indexError ?? "Index failed after remediation.",
|
|
29035
29157
|
analysisWorktreePath: analysisRoot
|
|
@@ -29082,7 +29204,7 @@ async function main() {
|
|
|
29082
29204
|
adHocCreatedAtIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
29083
29205
|
});
|
|
29084
29206
|
}
|
|
29085
|
-
finish(result.cancelled ? ExitCode.cancelled :
|
|
29207
|
+
finish(result.cancelled ? ExitCode.cancelled : OsExit.runSynthesisPipeline, {
|
|
29086
29208
|
ok: false,
|
|
29087
29209
|
error: result.error ?? "run synthesis failed",
|
|
29088
29210
|
cancelled: result.cancelled === true,
|
|
@@ -29110,14 +29232,14 @@ async function main() {
|
|
|
29110
29232
|
const d = res.document;
|
|
29111
29233
|
const maxPct = repoConfig.easyspecs?.diagnose?.zeroReference?.maxPercentNonReferenced;
|
|
29112
29234
|
if (maxPct !== null && maxPct !== void 0 && Number.isFinite(maxPct) && d.metrics.percentNonReferenced > maxPct) {
|
|
29113
|
-
finish(
|
|
29235
|
+
finish(OsExit.diagnoseReferenceCoverageThreshold, {
|
|
29114
29236
|
ok: false,
|
|
29115
29237
|
error: `percentNonReferenced ${String(d.metrics.percentNonReferenced)} > ${String(maxPct)}`
|
|
29116
29238
|
});
|
|
29117
29239
|
}
|
|
29118
29240
|
finish(ExitCode.ok, { ok: true, percentNonReferenced: d.metrics.percentNonReferenced });
|
|
29119
29241
|
} else {
|
|
29120
|
-
finish(
|
|
29242
|
+
finish(OsExit.diagnoseReferenceCoveragePipeline, { ok: false, error: res.error ?? "coverage failed" });
|
|
29121
29243
|
}
|
|
29122
29244
|
}
|
|
29123
29245
|
if (sub === "coordination-duplicates") {
|
|
@@ -29131,7 +29253,7 @@ async function main() {
|
|
|
29131
29253
|
if (res.ok) {
|
|
29132
29254
|
const strict = repoConfig.easyspecs?.diagnose?.coordinationDuplicates?.strict !== false;
|
|
29133
29255
|
const bad = strict && ((res.groupCount ?? 0) > 0 || (res.orphanMarkdownCount ?? 0) > 0);
|
|
29134
|
-
finish(bad ?
|
|
29256
|
+
finish(bad ? OsExit.diagnoseCoordinationDuplicatesPolicy : ExitCode.ok, {
|
|
29135
29257
|
ok: !bad,
|
|
29136
29258
|
groupCount: res.groupCount,
|
|
29137
29259
|
orphanMarkdownCount: res.orphanMarkdownCount,
|
|
@@ -29141,7 +29263,7 @@ async function main() {
|
|
|
29141
29263
|
groupsByList: res.groupsByList
|
|
29142
29264
|
});
|
|
29143
29265
|
}
|
|
29144
|
-
finish(
|
|
29266
|
+
finish(OsExit.diagnoseCoordinationDuplicatesEngine, { ok: false, error: res.message ?? "duplicates failed" });
|
|
29145
29267
|
}
|
|
29146
29268
|
if (sub === "coverage-report") {
|
|
29147
29269
|
const rootAbs = resolveAnalysisRoot(repoRoot, rootKind, worktree);
|
|
@@ -29153,7 +29275,7 @@ async function main() {
|
|
|
29153
29275
|
if (rep.ok) {
|
|
29154
29276
|
finish(ExitCode.ok, { ok: true, reportPath: rep.outputAbsolutePath });
|
|
29155
29277
|
} else {
|
|
29156
|
-
finish(
|
|
29278
|
+
finish(OsExit.diagnoseCoverageReport, { ok: false, error: rep.error ?? "report failed" });
|
|
29157
29279
|
}
|
|
29158
29280
|
}
|
|
29159
29281
|
if (sub === "missing-artefacts") {
|
|
@@ -29183,7 +29305,7 @@ async function main() {
|
|
|
29183
29305
|
requireMinimalGluecharmLayoutAt(analysisRoot);
|
|
29184
29306
|
const cov = readNonReferencedFilesFromRepositoryRoot(analysisRoot);
|
|
29185
29307
|
if (!cov.ok) {
|
|
29186
|
-
finish(
|
|
29308
|
+
finish(OsExit.diagnoseZeroReferenceReadCoverage, { ok: false, error: cov.error });
|
|
29187
29309
|
} else {
|
|
29188
29310
|
const zrPaths = cov.paths;
|
|
29189
29311
|
if (zrPaths.length === 0) {
|
|
@@ -29212,7 +29334,7 @@ async function main() {
|
|
|
29212
29334
|
const ctxDir = path59.join(analysisRoot, ".gluecharm", "context");
|
|
29213
29335
|
const lg = runLinkMappingPipeline(ctxDir, { log: (line) => logErr(flags, line) });
|
|
29214
29336
|
if (!lg.ok) {
|
|
29215
|
-
finish(
|
|
29337
|
+
finish(OsExit.diagnoseZeroReferenceLinkMapping, {
|
|
29216
29338
|
ok: false,
|
|
29217
29339
|
completed: poolRes.completed,
|
|
29218
29340
|
failures: poolRes.failures,
|
|
@@ -29222,7 +29344,7 @@ async function main() {
|
|
|
29222
29344
|
});
|
|
29223
29345
|
}
|
|
29224
29346
|
}
|
|
29225
|
-
finish(bad ?
|
|
29347
|
+
finish(bad ? OsExit.diagnoseZeroReferencePool : ExitCode.ok, {
|
|
29226
29348
|
ok: !bad,
|
|
29227
29349
|
completed: poolRes.completed,
|
|
29228
29350
|
failures: poolRes.failures,
|
|
@@ -29244,7 +29366,7 @@ async function main() {
|
|
|
29244
29366
|
log: (line) => logErr(flags, line)
|
|
29245
29367
|
});
|
|
29246
29368
|
if (!res.ok) {
|
|
29247
|
-
finish(
|
|
29369
|
+
finish(OsExit.contextLinkGraph, {
|
|
29248
29370
|
ok: false,
|
|
29249
29371
|
contextDir: contextDir2,
|
|
29250
29372
|
error: res.error,
|
|
@@ -29307,7 +29429,7 @@ async function main() {
|
|
|
29307
29429
|
factoryFailures: [row2],
|
|
29308
29430
|
error: composeFactoryValidationError(dres.error, [row2])
|
|
29309
29431
|
};
|
|
29310
|
-
if (driftExit
|
|
29432
|
+
if (isContextDriftSrs70ValidationExit(driftExit)) {
|
|
29311
29433
|
Object.assign(envelope, primaryFailureAliases([row2]));
|
|
29312
29434
|
}
|
|
29313
29435
|
finish(driftExit, envelope);
|
|
@@ -29409,7 +29531,10 @@ async function main() {
|
|
|
29409
29531
|
Object.assign(analysisEnvelope, primaryFailureAliases(res.factoryFailures));
|
|
29410
29532
|
analysisEnvelope.error = composeFactoryValidationError(res.message, res.factoryFailures);
|
|
29411
29533
|
}
|
|
29412
|
-
finish(
|
|
29534
|
+
finish(
|
|
29535
|
+
res.ok ? ExitCode.ok : res.cancelled ? ExitCode.cancelled : processExitFromNormalizedFactoryFailures(res.factoryFailures),
|
|
29536
|
+
analysisEnvelope
|
|
29537
|
+
);
|
|
29413
29538
|
}
|
|
29414
29539
|
if (pos[0] === "update" && pos[1] === "context") {
|
|
29415
29540
|
for (const a of pos.slice(2)) {
|
|
@@ -29437,7 +29562,7 @@ async function main() {
|
|
|
29437
29562
|
log: (line) => logErr(flags, line)
|
|
29438
29563
|
});
|
|
29439
29564
|
const { exitOk, ...payload } = ures;
|
|
29440
|
-
const code = exitOk ? ExitCode.ok : ures.code === "MISSING_BASELINE" ? ExitCode.usage :
|
|
29565
|
+
const code = exitOk ? ExitCode.ok : ures.code === "MISSING_BASELINE" ? ExitCode.usage : OsExit.updateContextFactory;
|
|
29441
29566
|
finish(code, payload);
|
|
29442
29567
|
}
|
|
29443
29568
|
if (pos[0] === "download" && pos[1] === "context") {
|
|
@@ -29700,7 +29825,7 @@ async function main() {
|
|
|
29700
29825
|
diagnosticLog: (line) => logErr(flags, line)
|
|
29701
29826
|
});
|
|
29702
29827
|
if (!res.ok) {
|
|
29703
|
-
finish(
|
|
29828
|
+
finish(OsExit.aceLearnTrace, { ok: false, error: res.message });
|
|
29704
29829
|
}
|
|
29705
29830
|
okCount += 1;
|
|
29706
29831
|
}
|
|
@@ -29726,7 +29851,7 @@ async function main() {
|
|
|
29726
29851
|
diagnosticLog: (line) => logErr(flags, line)
|
|
29727
29852
|
}
|
|
29728
29853
|
});
|
|
29729
|
-
finish(pool.failed ?
|
|
29854
|
+
finish(pool.failed ? OsExit.aceAutoLearnPool : ExitCode.ok, {
|
|
29730
29855
|
ok: pool.failed === 0,
|
|
29731
29856
|
completed: pool.completed,
|
|
29732
29857
|
failed: pool.failed,
|