@sensigo/realm-cli 0.40.0 → 0.42.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/dist/agent/providers/agent-utils.d.ts +37 -13
- package/dist/agent/providers/agent-utils.d.ts.map +1 -1
- package/dist/agent/providers/agent-utils.js +92 -17
- package/dist/agent/providers/agent-utils.js.map +1 -1
- package/dist/agent/run-attach.d.ts.map +1 -1
- package/dist/agent/run-attach.js +8 -21
- package/dist/agent/run-attach.js.map +1 -1
- package/dist/commands/agent.d.ts +6 -0
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/agent.js +28 -4
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/drain.d.ts.map +1 -1
- package/dist/commands/drain.js +60 -9
- package/dist/commands/drain.js.map +1 -1
- package/dist/commands/inspect.d.ts.map +1 -1
- package/dist/commands/inspect.js +20 -2
- package/dist/commands/inspect.js.map +1 -1
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +61 -8
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/listen.d.ts +13 -0
- package/dist/commands/listen.d.ts.map +1 -1
- package/dist/commands/listen.js +36 -4
- package/dist/commands/listen.js.map +1 -1
- package/dist/commands/register.d.ts +1 -14
- package/dist/commands/register.d.ts.map +1 -1
- package/dist/commands/register.js +52 -56
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/replay.d.ts.map +1 -1
- package/dist/commands/replay.js +4 -2
- package/dist/commands/replay.js.map +1 -1
- package/dist/commands/respond.d.ts.map +1 -1
- package/dist/commands/respond.js +30 -3
- package/dist/commands/respond.js.map +1 -1
- package/dist/commands/resume.d.ts.map +1 -1
- package/dist/commands/resume.js +3 -2
- package/dist/commands/resume.js.map +1 -1
- package/dist/commands/run.d.ts +35 -0
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +246 -12
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/test.d.ts.map +1 -1
- package/dist/commands/test.js +51 -8
- package/dist/commands/test.js.map +1 -1
- package/dist/commands/validate.d.ts +31 -0
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +658 -132
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/watch.d.ts +43 -1
- package/dist/commands/watch.d.ts.map +1 -1
- package/dist/commands/watch.js +366 -42
- package/dist/commands/watch.js.map +1 -1
- package/dist/commands/workflow-list.d.ts +16 -0
- package/dist/commands/workflow-list.d.ts.map +1 -0
- package/dist/commands/workflow-list.js +96 -0
- package/dist/commands/workflow-list.js.map +1 -0
- package/dist/commands-registry.d.ts.map +1 -1
- package/dist/commands-registry.js +2 -0
- package/dist/commands-registry.js.map +1 -1
- package/dist/extensions/load-project-extensions.d.ts.map +1 -1
- package/dist/extensions/load-project-extensions.js +9 -3
- package/dist/extensions/load-project-extensions.js.map +1 -1
- package/dist/index.js +22 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/admission-context.d.ts +58 -0
- package/dist/lib/admission-context.d.ts.map +1 -0
- package/dist/lib/admission-context.js +57 -0
- package/dist/lib/admission-context.js.map +1 -0
- package/dist/lib/load-workflow-for-admission.d.ts +69 -0
- package/dist/lib/load-workflow-for-admission.d.ts.map +1 -0
- package/dist/lib/load-workflow-for-admission.js +130 -0
- package/dist/lib/load-workflow-for-admission.js.map +1 -0
- package/dist/lib/loader-warnings.d.ts +28 -10
- package/dist/lib/loader-warnings.d.ts.map +1 -1
- package/dist/lib/loader-warnings.js +84 -30
- package/dist/lib/loader-warnings.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// The ONE admission path (issue #553): what `validate` blesses, `register` accepts, and what
|
|
2
|
+
// `register` refuses, `validate` refuses — by construction, because both (and `watch`) call
|
|
3
|
+
// this function and nothing else. Relocated from register.ts, where validate could not import
|
|
4
|
+
// it without a cycle.
|
|
5
|
+
import { loadWorkflowFromFileWithDiagnostics, } from '@sensigo/realm';
|
|
6
|
+
import { loadProjectExtensions, } from '../extensions/load-project-extensions.js';
|
|
7
|
+
import { ManifestSecretsError } from '../extensions/manifest-secrets.js';
|
|
8
|
+
import { wrapSentinelWarnings } from './loader-warnings.js';
|
|
9
|
+
/**
|
|
10
|
+
* Tags a failure thrown by the extensions load inside `loadWorkflowForAdmission` so the
|
|
11
|
+
* callers' catches can say `Error loading extensions:` — the sentence run and validate already
|
|
12
|
+
* print for this class (issue #451) — without guessing from the message. The message is the
|
|
13
|
+
* original's, byte for byte (register-extensions.test.ts's broken-module cell matches on it
|
|
14
|
+
* THROUGH this wrapper), and the original rides along as `cause`.
|
|
15
|
+
*
|
|
16
|
+
* Minted at exactly the two throw paths out of the extensions block: the real-mode load's
|
|
17
|
+
* non-secrets failure, and the sentinel retry. The retry can never throw ManifestSecretsError
|
|
18
|
+
* itself (sentinel mode resolves every name without reading a source), so nothing is wrapped
|
|
19
|
+
* twice. A WorkflowError from the two-pass re-validation is thrown OUTSIDE the block and keeps
|
|
20
|
+
* the family split.
|
|
21
|
+
*
|
|
22
|
+
* Carries the workflow's own pass-1 loader warnings (issue #463 — the #424 carry shape on this
|
|
23
|
+
* vehicle) so the catch that renders the sentence can print them FIRST, instead of the author
|
|
24
|
+
* fixing the module, re-running, and only then learning about the typo. ABSENT, never `[]`: a
|
|
25
|
+
* construction that passes no warnings, or an empty list, leaves the field unset.
|
|
26
|
+
*
|
|
27
|
+
* Carries the pass-1 definition too (issue #553): validate's `--json` names `workflow_id` on
|
|
28
|
+
* this arm and computes the retry advisory from the definition before printing the sentence.
|
|
29
|
+
*
|
|
30
|
+
* @internal Exported for register.ts, watch.ts, validate.ts and for tests.
|
|
31
|
+
*/
|
|
32
|
+
export class ExtensionLoadError extends Error {
|
|
33
|
+
warnings;
|
|
34
|
+
definition;
|
|
35
|
+
constructor(original, warnings, definition) {
|
|
36
|
+
super(original instanceof Error ? original.message : String(original), { cause: original });
|
|
37
|
+
this.name = 'ExtensionLoadError';
|
|
38
|
+
// The if-guard form on purpose: a ternary to `undefined` is a TS2412 under the repo's
|
|
39
|
+
// exactOptionalPropertyTypes (lane-executed, #463).
|
|
40
|
+
if (warnings !== undefined && warnings.length > 0)
|
|
41
|
+
this.warnings = [...warnings];
|
|
42
|
+
if (definition !== undefined)
|
|
43
|
+
this.definition = definition;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The pass-1 definition of a workflow whose pass-2 (config_schema) re-validation threw. The
|
|
48
|
+
* thrown WorkflowError is register's and watch's to render exactly as before — its identity,
|
|
49
|
+
* message and family are untouched — so the definition rides beside it rather than on it.
|
|
50
|
+
* validate's `--json` reads it back for `workflow_id` (issue #553, audit round 2 Q9).
|
|
51
|
+
*/
|
|
52
|
+
const admittedDefinitions = new WeakMap();
|
|
53
|
+
/** @internal Exported for validate.ts. */
|
|
54
|
+
export function admittedDefinitionOf(err) {
|
|
55
|
+
return typeof err === 'object' && err !== null ? admittedDefinitions.get(err) : undefined;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The project-extensions pass ALONE (issue #553 correction C2) — the real load, degrading to
|
|
59
|
+
* SENTINEL credentials with a loud, surface-keyed WARN pair when a secret source is unavailable,
|
|
60
|
+
* and the RAW error on any other failure (the caller decides how to wrap/report it; this function
|
|
61
|
+
* throws nothing `ExtensionLoadError`-shaped itself). This is the ONE mint site for "⚠ …with
|
|
62
|
+
* SENTINEL credentials — execution paths still require real secret resolution." — before this
|
|
63
|
+
* extraction it was minted here AND hand-typed a second time in `validate --registered`'s own
|
|
64
|
+
* extensions arm (the #444/#508 two-mints-of-one-string class); both callers now share it.
|
|
65
|
+
* `overrideModule` is `--extensions-module`: it must travel into BOTH loads (the real attempt and
|
|
66
|
+
* the sentinel retry) or a repair flag dies in its own retry (the #353/#466 flag-travel class).
|
|
67
|
+
*/
|
|
68
|
+
export async function admitProjectExtensions(definition, opts) {
|
|
69
|
+
const override = opts.overrideModule !== undefined ? { overrideModule: opts.overrideModule } : {};
|
|
70
|
+
// Full module load + duck validation + manifest construction BEFORE persisting. Secret sources
|
|
71
|
+
// may be unavailable at provisioning time: degrade to SENTINEL construction with a loud WARN
|
|
72
|
+
// (never silent, never a registration blocker); execution paths still require real resolution.
|
|
73
|
+
try {
|
|
74
|
+
return await loadProjectExtensions(definition, { ...override });
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
// The guard is the degradation itself: only a secrets failure degrades, everything else is
|
|
78
|
+
// the caller's to tag and report. Dropping the conditional kills degradation —
|
|
79
|
+
// register-extensions.test.ts's sentinel control is the cell in this command's own home that
|
|
80
|
+
// sees it (the manifest E2E in extensions/ does too, one substring deep).
|
|
81
|
+
if (!(err instanceof ManifestSecretsError))
|
|
82
|
+
throw err;
|
|
83
|
+
console.warn(`⚠ ${err.message}`);
|
|
84
|
+
// Surface-keyed (issue #553): validate registers nothing, so "Registering" there is a false
|
|
85
|
+
// claim; register and watch keep their text byte for byte.
|
|
86
|
+
console.warn(`⚠ ${opts.surface === 'validate' ? 'Validating' : 'Registering'} with SENTINEL credentials — execution paths still require real secret resolution.`);
|
|
87
|
+
return await loadProjectExtensions(definition, { ...override, secretMode: 'sentinel' });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Loads and validates a workflow for admission — register, watch and validate all take exactly
|
|
92
|
+
* this path (issue #553). The file loader (agent-profile resolution included), then the
|
|
93
|
+
* UNCONDITIONAL project-extensions load (modules, manifest, config_schema two-pass), degrading
|
|
94
|
+
* to SENTINEL credentials with a loud WARN when a secret source is unavailable.
|
|
95
|
+
* Returns the definition alongside every accumulated LoaderWarning (issue #169) — pass-1's
|
|
96
|
+
* structural warnings plus the sentinel-credential warnings, if any — and the resolved manifest
|
|
97
|
+
* (validate's `Extensions:` line reports its counts). Prints NOTHING itself beyond the two
|
|
98
|
+
* sentinel ⚠ lines; every caller decides how to surface/act on warnings (register supports
|
|
99
|
+
* `--strict` + the dormant #170 reject; watch just prints and continues; validate reports).
|
|
100
|
+
* @throws on any validation or extension-load failure — nothing is persisted on throw.
|
|
101
|
+
* Extension-load failures are tagged `ExtensionLoadError` (issue #451).
|
|
102
|
+
*/
|
|
103
|
+
export async function loadWorkflowForAdmission(filePath, opts) {
|
|
104
|
+
const { definition, warnings: pass1Warnings } = loadWorkflowFromFileWithDiagnostics(filePath);
|
|
105
|
+
let loaded;
|
|
106
|
+
try {
|
|
107
|
+
loaded = await admitProjectExtensions(definition, opts);
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
throw new ExtensionLoadError(err, pass1Warnings, definition);
|
|
111
|
+
}
|
|
112
|
+
// Two-pass: re-validate with the resolved registry so step config is checked against
|
|
113
|
+
// each adapter's config_schema before the definition is persisted. Its warnings are proven
|
|
114
|
+
// identical to pass-1's (same content, registry only adds config_schema checks) — discarded
|
|
115
|
+
// here to avoid double-counting the same unknown key twice.
|
|
116
|
+
try {
|
|
117
|
+
loadWorkflowFromFileWithDiagnostics(filePath, loaded.registry);
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
if (typeof err === 'object' && err !== null)
|
|
121
|
+
admittedDefinitions.set(err, definition);
|
|
122
|
+
throw err;
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
definition,
|
|
126
|
+
warnings: [...pass1Warnings, ...wrapSentinelWarnings(loaded.sentinelWarnings)],
|
|
127
|
+
manifest: loaded.manifest,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=load-workflow-for-admission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-workflow-for-admission.js","sourceRoot":"","sources":["../../src/lib/load-workflow-for-admission.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import { type LoaderWarning, type WarningCode } from '@sensigo/realm';
|
|
1
|
+
import { type WorkflowError, type LoaderWarning, type WarningCode } from '@sensigo/realm';
|
|
2
2
|
/**
|
|
3
|
-
* Prints every warning via the single renderLoaderWarning format source
|
|
4
|
-
* "— ignored"
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* that only fails under `--strict` still renders "— ignored" — see the report's design note; the
|
|
8
|
-
* `--strict` path prints its own "failing due to --strict" line, so the author is not left
|
|
9
|
-
* without an explanation.
|
|
3
|
+
* Prints every warning via the single renderLoaderWarning format source — no substitution (see
|
|
4
|
+
* the module header for why the former "— ignored" → "— REFUSED below" rewrite was deleted,
|
|
5
|
+
* issue #540). The `DEFAULT_POLICY` import above stays: `rejectOnErrorSeverity` and
|
|
6
|
+
* `failsStrict`, both exported from this module, still resolve against it.
|
|
10
7
|
*/
|
|
11
|
-
export declare function printLoaderWarnings(warnings: LoaderWarning[]): void;
|
|
8
|
+
export declare function printLoaderWarnings(warnings: readonly LoaderWarning[]): void;
|
|
12
9
|
/**
|
|
13
10
|
* The dormant issue #170 boundary-reject hook, factored ONCE so validate/register/watch can't
|
|
14
11
|
* drift from each other: resolves every warning against `policy` (default DEFAULT_POLICY — inert
|
|
@@ -20,6 +17,17 @@ export declare function printLoaderWarnings(warnings: LoaderWarning[]): void;
|
|
|
20
17
|
export declare function rejectOnErrorSeverity(warnings: LoaderWarning[], policy?: Record<WarningCode, 'warn' | 'error'>): boolean;
|
|
21
18
|
/** True if `--strict` should fail the command given these accumulated warnings. */
|
|
22
19
|
export declare function failsStrict(warnings: LoaderWarning[]): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Wraps loadProjectExtensions' sentinel-credential warnings as LoaderWarning (issue #169).
|
|
22
|
+
*
|
|
23
|
+
* ONE copy (issue #444): validate.ts and register.ts each carried a byte-identical private one,
|
|
24
|
+
* and both baked a two-space `⚠ ` into the message. The prefix now belongs to
|
|
25
|
+
* `renderLoaderWarning` alone, so the message here is the input string verbatim.
|
|
26
|
+
*
|
|
27
|
+
* register's caller is `loadWorkflowForAdmission`, which `watch` and `validate` also use — so the strip
|
|
28
|
+
* reaches watch too, and there is no third caller.
|
|
29
|
+
*/
|
|
30
|
+
export declare function wrapSentinelWarnings(sentinelWarnings: string[] | undefined): LoaderWarning[];
|
|
23
31
|
/**
|
|
24
32
|
* Renders a load failure without saying "invalid" twice (issue #417).
|
|
25
33
|
*
|
|
@@ -32,5 +40,15 @@ export declare function failsStrict(warnings: LoaderWarning[]): boolean;
|
|
|
32
40
|
* Applies only to the message-echoing renders. The standalone strict-escalation lines have their
|
|
33
41
|
* own text and are untouched.
|
|
34
42
|
*/
|
|
35
|
-
export declare function renderLoadFailure(
|
|
43
|
+
export declare function renderLoadFailure(err: WorkflowError | string): string;
|
|
44
|
+
/**
|
|
45
|
+
* The escalation line (issue #425). Extracted so the keyless branch below is reachable from a
|
|
46
|
+
* test: every WarningCode that escalates under the default policy happens to carry a key today,
|
|
47
|
+
* so no real fixture can drive it — and a clause nothing can exercise rots into a wrong guess
|
|
48
|
+
* about what a future keyless code would print.
|
|
49
|
+
*
|
|
50
|
+
* Shared by validate, register and watch (issue #451) — three callers earned it this home, per
|
|
51
|
+
* the one-caller rule recorded on validate's exitOnLoadFailure.
|
|
52
|
+
*/
|
|
53
|
+
export declare function renderEscalationLine(warnings: readonly LoaderWarning[]): string;
|
|
36
54
|
//# sourceMappingURL=loader-warnings.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader-warnings.d.ts","sourceRoot":"","sources":["../../src/lib/loader-warnings.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loader-warnings.d.ts","sourceRoot":"","sources":["../../src/lib/loader-warnings.ts"],"names":[],"mappings":"AA2BA,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,WAAW,EACjB,MAAM,gBAAgB,CAAC;AAExB;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,IAAI,CAI5E;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,aAAa,EAAE,EACzB,MAAM,GAAE,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAkB,GAC7D,OAAO,CAET;AAWD,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,OAAO,CAE9D;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,gBAAgB,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,aAAa,EAAE,CAO5F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,GAAG,MAAM,CAiBrE;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAW/E"}
|
|
@@ -1,37 +1,40 @@
|
|
|
1
1
|
// loader-warnings.ts — shared CLI surfacing for the structured loader-warning channel (issue
|
|
2
|
-
// #169).
|
|
3
|
-
//
|
|
4
|
-
//
|
|
2
|
+
// #169). The BOUNDARY commands — validate, register, watch — funnel every LoaderWarning through
|
|
3
|
+
// printLoaderWarnings, and the dormant #170 boundary-reject is factored into ONE shared helper so
|
|
4
|
+
// they can't drift.
|
|
5
|
+
//
|
|
6
|
+
// issue #540: printLoaderWarnings used to rewrite the mint's "— ignored" clause to
|
|
7
|
+
// "— REFUSED below" for any warning the boundary resolves to 'error', on the theory that
|
|
8
|
+
// "ignored" is false once a boundary is about to refuse the workflow over it. That substitution
|
|
9
|
+
// is gone: "— ignored" is a true statement about what the PARSE did (the key was dropped) on
|
|
10
|
+
// EVERY surface, including this one — the refusal is a separate fact, already stated per-key by
|
|
11
|
+
// renderEscalationLine below. The substitution could also name the WRONG cause on any arm that
|
|
12
|
+
// bypasses renderEscalationLine's own gate (see the "hard-error carry"/orphan-manifest/extensions-
|
|
13
|
+
// failure comments in validate.ts and register.ts) and, being a first-occurrence unanchored
|
|
14
|
+
// string replace, could corrupt author-controlled text that happened to contain the clause
|
|
15
|
+
// (issue #525 item 1). See
|
|
16
|
+
// `plans/issue-540/design-d2.md` for the full adjudication between this and issue #170's
|
|
17
|
+
// (superseded) legibility argument for the substitution.
|
|
18
|
+
//
|
|
19
|
+
// One consequence, since `test` was never the exception any more (issue #450): with the
|
|
20
|
+
// substitution gone, printLoaderWarnings is now behaviorally identical to
|
|
21
|
+
// `renderLoaderWarning`'s plain-render loop that `realm workflow test` already used directly.
|
|
22
|
+
// Whether the two call shapes should unify is its own question — filed as #542, not answered here.
|
|
23
|
+
//
|
|
24
|
+
// Precise as of issue #444: no command hand-rolls a ⚠ prefix for a LOADER WARNING. A few
|
|
25
|
+
// adjacent one-off notices — register's sentinel lines, test's sentinel echo — still print their
|
|
26
|
+
// own `⚠ ` directly, because they are plain strings rather than LoaderWarnings; they were
|
|
27
|
+
// normalized to the same single-space grammar so a mixed block cannot recur.
|
|
5
28
|
import { renderLoaderWarning, resolveSeverity, DEFAULT_POLICY, } from '@sensigo/realm';
|
|
6
29
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* the author the opposite of what is about to happen to them.
|
|
12
|
-
*
|
|
13
|
-
* Substituted at the RENDER, not the mint, precisely because the mint is shared with the lenient
|
|
14
|
-
* path — where the original wording is true and worth keeping. The did-you-mean fragment is
|
|
15
|
-
* untouched: it is the most useful half of the line and the reason the author can fix this in one
|
|
16
|
-
* edit.
|
|
17
|
-
*/
|
|
18
|
-
const IGNORED_CLAUSE = '— ignored';
|
|
19
|
-
const REFUSED_CLAUSE = '— REFUSED below';
|
|
20
|
-
/**
|
|
21
|
-
* Prints every warning via the single renderLoaderWarning format source, correcting the
|
|
22
|
-
* "— ignored" claim for any warning this boundary will actually refuse.
|
|
23
|
-
*
|
|
24
|
-
* Resolved against DEFAULT_POLICY, which is the policy the boundary-reject itself uses. A warning
|
|
25
|
-
* that only fails under `--strict` still renders "— ignored" — see the report's design note; the
|
|
26
|
-
* `--strict` path prints its own "failing due to --strict" line, so the author is not left
|
|
27
|
-
* without an explanation.
|
|
30
|
+
* Prints every warning via the single renderLoaderWarning format source — no substitution (see
|
|
31
|
+
* the module header for why the former "— ignored" → "— REFUSED below" rewrite was deleted,
|
|
32
|
+
* issue #540). The `DEFAULT_POLICY` import above stays: `rejectOnErrorSeverity` and
|
|
33
|
+
* `failsStrict`, both exported from this module, still resolve against it.
|
|
28
34
|
*/
|
|
29
35
|
export function printLoaderWarnings(warnings) {
|
|
30
36
|
for (const w of warnings) {
|
|
31
|
-
|
|
32
|
-
console.warn(resolveSeverity(w.code, DEFAULT_POLICY) === 'error'
|
|
33
|
-
? line.replace(IGNORED_CLAUSE, REFUSED_CLAUSE)
|
|
34
|
-
: line);
|
|
37
|
+
console.warn(renderLoaderWarning(w));
|
|
35
38
|
}
|
|
36
39
|
}
|
|
37
40
|
/**
|
|
@@ -55,6 +58,24 @@ const ALL_ERROR_POLICY = Object.fromEntries(Object.keys(DEFAULT_POLICY).map((cod
|
|
|
55
58
|
export function failsStrict(warnings) {
|
|
56
59
|
return rejectOnErrorSeverity(warnings, ALL_ERROR_POLICY);
|
|
57
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Wraps loadProjectExtensions' sentinel-credential warnings as LoaderWarning (issue #169).
|
|
63
|
+
*
|
|
64
|
+
* ONE copy (issue #444): validate.ts and register.ts each carried a byte-identical private one,
|
|
65
|
+
* and both baked a two-space `⚠ ` into the message. The prefix now belongs to
|
|
66
|
+
* `renderLoaderWarning` alone, so the message here is the input string verbatim.
|
|
67
|
+
*
|
|
68
|
+
* register's caller is `loadWorkflowForAdmission`, which `watch` and `validate` also use — so the strip
|
|
69
|
+
* reaches watch too, and there is no third caller.
|
|
70
|
+
*/
|
|
71
|
+
export function wrapSentinelWarnings(sentinelWarnings) {
|
|
72
|
+
return (sentinelWarnings ?? []).map((message) => ({
|
|
73
|
+
code: 'EXTENSION_SENTINEL',
|
|
74
|
+
severity: resolveSeverity('EXTENSION_SENTINEL'),
|
|
75
|
+
scope: 'workflow',
|
|
76
|
+
message,
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
58
79
|
/**
|
|
59
80
|
* Renders a load failure without saying "invalid" twice (issue #417).
|
|
60
81
|
*
|
|
@@ -67,7 +88,40 @@ export function failsStrict(warnings) {
|
|
|
67
88
|
* Applies only to the message-echoing renders. The standalone strict-escalation lines have their
|
|
68
89
|
* own text and are untouched.
|
|
69
90
|
*/
|
|
70
|
-
export function renderLoadFailure(
|
|
71
|
-
|
|
91
|
+
export function renderLoadFailure(err) {
|
|
92
|
+
// The string branch FIRST, and not only for the unit cells that drive it: several call sites
|
|
93
|
+
// pass `err instanceof Error ? err.message : String(err)`, so a plain string is a real caller
|
|
94
|
+
// shape, and an object-first implementation would reach for `.errors` on it.
|
|
95
|
+
if (typeof err === 'string') {
|
|
96
|
+
return err.startsWith('Invalid workflow:') ? err : `Invalid: ${err}`;
|
|
97
|
+
}
|
|
98
|
+
// issue #425: several problems collected into one throw get one line each. The array is the
|
|
99
|
+
// only place the boundaries survive — a loader message can itself contain '; ' (the #413
|
|
100
|
+
// four-clause text does), so splitting the joined message back apart would cut one message in
|
|
101
|
+
// half and call the halves two errors.
|
|
102
|
+
const parts = err.errors;
|
|
103
|
+
if (parts !== undefined && parts.length > 1) {
|
|
104
|
+
return [`Invalid workflow — ${parts.length} errors:`, ...parts.map((e) => ` ${e}`)].join('\n');
|
|
105
|
+
}
|
|
106
|
+
return renderLoadFailure(err.message);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The escalation line (issue #425). Extracted so the keyless branch below is reachable from a
|
|
110
|
+
* test: every WarningCode that escalates under the default policy happens to carry a key today,
|
|
111
|
+
* so no real fixture can drive it — and a clause nothing can exercise rots into a wrong guess
|
|
112
|
+
* about what a future keyless code would print.
|
|
113
|
+
*
|
|
114
|
+
* Shared by validate, register and watch (issue #451) — three callers earned it this home, per
|
|
115
|
+
* the one-caller rule recorded on validate's exitOnLoadFailure.
|
|
116
|
+
*/
|
|
117
|
+
export function renderEscalationLine(warnings) {
|
|
118
|
+
// Same default policy `rejectOnErrorSeverity` just gated on, so the list can never disagree
|
|
119
|
+
// with the refusal it explains.
|
|
120
|
+
const escalated = warnings.filter((w) => resolveSeverity(w.code) === 'error');
|
|
121
|
+
const list = escalated
|
|
122
|
+
.map((w) => (w.key === undefined ? w.code : `${w.code} '${w.key}'`))
|
|
123
|
+
.join(', ');
|
|
124
|
+
return (`Invalid: ${warnings.length} ${warnings.length === 1 ? 'warning' : 'warnings'}, ` +
|
|
125
|
+
`${escalated.length} escalated to an error by policy: ${list}`);
|
|
72
126
|
}
|
|
73
127
|
//# sourceMappingURL=loader-warnings.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader-warnings.js","sourceRoot":"","sources":["../../src/lib/loader-warnings.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,gGAAgG;AAChG,
|
|
1
|
+
{"version":3,"file":"loader-warnings.js","sourceRoot":"","sources":["../../src/lib/loader-warnings.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sensigo/realm-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.42.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -64,9 +64,9 @@
|
|
|
64
64
|
"vitest": "^4.1.0"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@sensigo/realm": "^0.
|
|
68
|
-
"@sensigo/realm-mcp": "^0.
|
|
69
|
-
"@sensigo/realm-testing": "^0.
|
|
67
|
+
"@sensigo/realm": "^0.42.0",
|
|
68
|
+
"@sensigo/realm-mcp": "^0.42.0",
|
|
69
|
+
"@sensigo/realm-testing": "^0.42.0",
|
|
70
70
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
71
71
|
"chalk": "^5.0.0",
|
|
72
72
|
"commander": "^15.0.0",
|