refactor(#3309): consolidate adviseRemedy() into the shared types leaf
adviseRemedy() was defined identically in two of the eight rule-group
files (config-validation.cts, agent-install.cts) while the other six
repeated the same {action: ADVISE, risk: NONE, args: {command}} object
literal inline ~20+ times. Found by the Standards-axis orthogonal
review (Duplicated Code smell).
Moves the one-line helper into health-diagnostic-types.cts, the leaf
module every rule-group file already imports for its enums/types, and
uses it consistently across all 8 files. Pure mechanical refactor — no
ADVISE remedy's command text, code, or action changed.
This commit is contained in:
@@ -26,10 +26,9 @@
|
|||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-require-imports -- health-diagnostic-types.cjs is an export= CommonJS module
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- health-diagnostic-types.cjs is an export= CommonJS module
|
||||||
import healthDiagnosticMod = require('../health-diagnostic-types.cjs');
|
import healthDiagnosticMod = require('../health-diagnostic-types.cjs');
|
||||||
const { SEVERITY, REMEDY_ACTION, REMEDY_RISK } = healthDiagnosticMod;
|
const { SEVERITY, adviseRemedy } = healthDiagnosticMod;
|
||||||
type Rule = healthDiagnosticMod.Rule;
|
type Rule = healthDiagnosticMod.Rule;
|
||||||
type Diagnostic = healthDiagnosticMod.Diagnostic;
|
type Diagnostic = healthDiagnosticMod.Diagnostic;
|
||||||
type Remedy = healthDiagnosticMod.Remedy;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-require-imports -- type-only; erased at compile time, no runtime require emitted
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- type-only; erased at compile time, no runtime require emitted
|
||||||
import type planningSnapshotMod = require('../planning-snapshot.cjs');
|
import type planningSnapshotMod = require('../planning-snapshot.cjs');
|
||||||
@@ -41,10 +40,6 @@ const { SCOPE } = planningScopeMod;
|
|||||||
|
|
||||||
import { PACKAGE_NAME } from '../package-identity.cjs';
|
import { PACKAGE_NAME } from '../package-identity.cjs';
|
||||||
|
|
||||||
function adviseRemedy(command: string): Remedy {
|
|
||||||
return { action: REMEDY_ACTION.ADVISE, risk: REMEDY_RISK.NONE, args: { command } };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `check(snapshot)` for W010 — see module header for the exact 4-way
|
* `check(snapshot)` for W010 — see module header for the exact 4-way
|
||||||
* branching this ports from `verify.cts:1992-2027`, and its message/fix
|
* branching this ports from `verify.cts:1992-2027`, and its message/fix
|
||||||
|
|||||||
@@ -56,9 +56,8 @@ type PlanningSnapshot = ReturnType<typeof planningSnapshotMod.buildPlanningSnaps
|
|||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-require-imports -- health-diagnostic-types.cjs is an export= CommonJS module
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- health-diagnostic-types.cjs is an export= CommonJS module
|
||||||
import healthDiagnosticMod = require('../health-diagnostic-types.cjs');
|
import healthDiagnosticMod = require('../health-diagnostic-types.cjs');
|
||||||
const { SEVERITY, REMEDY_ACTION, REMEDY_RISK } = healthDiagnosticMod;
|
const { SEVERITY, REMEDY_ACTION, REMEDY_RISK, adviseRemedy } = healthDiagnosticMod;
|
||||||
type Diagnostic = healthDiagnosticMod.Diagnostic;
|
type Diagnostic = healthDiagnosticMod.Diagnostic;
|
||||||
type Remedy = healthDiagnosticMod.Remedy;
|
|
||||||
type Rule = healthDiagnosticMod.Rule;
|
type Rule = healthDiagnosticMod.Rule;
|
||||||
|
|
||||||
import { VALID_PROFILES, VALID_TIERS, VALID_PHASE_TYPES } from '../model-catalog.cjs';
|
import { VALID_PROFILES, VALID_TIERS, VALID_PHASE_TYPES } from '../model-catalog.cjs';
|
||||||
@@ -66,10 +65,6 @@ import { VALID_PROFILES, VALID_TIERS, VALID_PHASE_TYPES } from '../model-catalog
|
|||||||
// verify.cts:2141 — inlined literal, not exported from anywhere; same list.
|
// verify.cts:2141 — inlined literal, not exported from anywhere; same list.
|
||||||
const VALID_BRANCHING_STRATEGIES = ['none', 'phase', 'milestone'];
|
const VALID_BRANCHING_STRATEGIES = ['none', 'phase', 'milestone'];
|
||||||
|
|
||||||
function adviseRemedy(command: string): Remedy {
|
|
||||||
return { action: REMEDY_ACTION.ADVISE, risk: REMEDY_RISK.NONE, args: { command } };
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── W003 — config.json not found (verify.cts:1777-1785) ───────────────────
|
// ─── W003 — config.json not found (verify.cts:1777-1785) ───────────────────
|
||||||
|
|
||||||
function checkW003(snapshot: PlanningSnapshot): Diagnostic[] {
|
function checkW003(snapshot: PlanningSnapshot): Diagnostic[] {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ type PlanningSnapshot = ReturnType<typeof planningSnapshotMod.buildPlanningSnaps
|
|||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
import healthDiagnosticMod = require('../health-diagnostic-types.cjs');
|
import healthDiagnosticMod = require('../health-diagnostic-types.cjs');
|
||||||
const { SEVERITY, REMEDY_ACTION, REMEDY_RISK } = healthDiagnosticMod;
|
const { SEVERITY, REMEDY_ACTION, REMEDY_RISK, adviseRemedy } = healthDiagnosticMod;
|
||||||
type Diagnostic = healthDiagnosticMod.Diagnostic;
|
type Diagnostic = healthDiagnosticMod.Diagnostic;
|
||||||
type Rule = healthDiagnosticMod.Rule;
|
type Rule = healthDiagnosticMod.Rule;
|
||||||
|
|
||||||
@@ -85,14 +85,9 @@ function checkW019(snapshot: PlanningSnapshot): Diagnostic[] {
|
|||||||
code: 'W019',
|
code: 'W019',
|
||||||
severity: SEVERITY.WARNING,
|
severity: SEVERITY.WARNING,
|
||||||
message: `Unrecognized .planning/ file: ${filename} — not a canonical GSD artifact`,
|
message: `Unrecognized .planning/ file: ${filename} — not a canonical GSD artifact`,
|
||||||
remedy: {
|
remedy: adviseRemedy(
|
||||||
action: REMEDY_ACTION.ADVISE,
|
'Move to .planning/milestones/ archive subdir or delete if stale. See templates/README.md for the canonical artifact list.',
|
||||||
risk: REMEDY_RISK.NONE,
|
),
|
||||||
args: {
|
|
||||||
command:
|
|
||||||
'Move to .planning/milestones/ archive subdir or delete if stale. See templates/README.md for the canonical artifact list.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return diagnostics;
|
return diagnostics;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ type PlanningSnapshot = ReturnType<typeof planningSnapshotMod.buildPlanningSnaps
|
|||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
import healthDiagnosticMod = require('../health-diagnostic-types.cjs');
|
import healthDiagnosticMod = require('../health-diagnostic-types.cjs');
|
||||||
const { SEVERITY, REMEDY_ACTION, REMEDY_RISK } = healthDiagnosticMod;
|
const { SEVERITY, adviseRemedy } = healthDiagnosticMod;
|
||||||
type Diagnostic = healthDiagnosticMod.Diagnostic;
|
type Diagnostic = healthDiagnosticMod.Diagnostic;
|
||||||
type Rule = healthDiagnosticMod.Rule;
|
type Rule = healthDiagnosticMod.Rule;
|
||||||
|
|
||||||
@@ -77,11 +77,7 @@ function checkW005(snapshot: PlanningSnapshot): Diagnostic[] {
|
|||||||
code: 'W005',
|
code: 'W005',
|
||||||
severity: SEVERITY.WARNING,
|
severity: SEVERITY.WARNING,
|
||||||
message: `Phase directory "${name}" doesn't follow NN-name format`,
|
message: `Phase directory "${name}" doesn't follow NN-name format`,
|
||||||
remedy: {
|
remedy: adviseRemedy('Rename to match pattern (e.g., 01-setup)'),
|
||||||
action: REMEDY_ACTION.ADVISE,
|
|
||||||
risk: REMEDY_RISK.NONE,
|
|
||||||
args: { command: 'Rename to match pattern (e.g., 01-setup)' },
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,14 +123,9 @@ function checkW023(snapshot: PlanningSnapshot): Diagnostic[] {
|
|||||||
code: 'W023',
|
code: 'W023',
|
||||||
severity: SEVERITY.WARNING,
|
severity: SEVERITY.WARNING,
|
||||||
message: `Phase directories collide on normalized key "${key}": ${described}`,
|
message: `Phase directories collide on normalized key "${key}": ${described}`,
|
||||||
remedy: {
|
remedy: adviseRemedy(
|
||||||
action: REMEDY_ACTION.ADVISE,
|
'Inspect each directory; rename or remove the duplicate so only one directory maps to this phase key',
|
||||||
risk: REMEDY_RISK.NONE,
|
),
|
||||||
args: {
|
|
||||||
command:
|
|
||||||
'Inspect each directory; rename or remove the duplicate so only one directory maps to this phase key',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return diagnostics;
|
return diagnostics;
|
||||||
@@ -161,11 +152,7 @@ function checkI001(snapshot: PlanningSnapshot): Diagnostic[] {
|
|||||||
code: 'I001',
|
code: 'I001',
|
||||||
severity: SEVERITY.INFO,
|
severity: SEVERITY.INFO,
|
||||||
message: `Phase ${phase.dir} has ${deficit} plan(s) without a matching summary`,
|
message: `Phase ${phase.dir} has ${deficit} plan(s) without a matching summary`,
|
||||||
remedy: {
|
remedy: adviseRemedy('May be in progress'),
|
||||||
action: REMEDY_ACTION.ADVISE,
|
|
||||||
risk: REMEDY_RISK.NONE,
|
|
||||||
args: { command: 'May be in progress' },
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,11 +170,7 @@ function checkW009(snapshot: PlanningSnapshot): Diagnostic[] {
|
|||||||
code: 'W009',
|
code: 'W009',
|
||||||
severity: SEVERITY.WARNING,
|
severity: SEVERITY.WARNING,
|
||||||
message: `Phase ${entry.dir}: has Validation Architecture in RESEARCH.md but no VALIDATION.md`,
|
message: `Phase ${entry.dir}: has Validation Architecture in RESEARCH.md but no VALIDATION.md`,
|
||||||
remedy: {
|
remedy: adviseRemedy('Re-run /gsd-plan-phase with --research to regenerate'),
|
||||||
action: REMEDY_ACTION.ADVISE,
|
|
||||||
risk: REMEDY_RISK.NONE,
|
|
||||||
args: { command: 'Re-run /gsd-plan-phase with --research to regenerate' },
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ type PlanningSnapshot = ReturnType<typeof planningSnapshotMod.buildPlanningSnaps
|
|||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
import healthDiagnosticMod = require('../health-diagnostic-types.cjs');
|
import healthDiagnosticMod = require('../health-diagnostic-types.cjs');
|
||||||
const { SEVERITY, REMEDY_ACTION, REMEDY_RISK } = healthDiagnosticMod;
|
const { SEVERITY, adviseRemedy } = healthDiagnosticMod;
|
||||||
type Diagnostic = healthDiagnosticMod.Diagnostic;
|
type Diagnostic = healthDiagnosticMod.Diagnostic;
|
||||||
type Rule = healthDiagnosticMod.Rule;
|
type Rule = healthDiagnosticMod.Rule;
|
||||||
|
|
||||||
@@ -158,11 +158,7 @@ function checkW006(snapshot: PlanningSnapshot): Diagnostic[] {
|
|||||||
code: 'W006',
|
code: 'W006',
|
||||||
severity: SEVERITY.WARNING,
|
severity: SEVERITY.WARNING,
|
||||||
message: `Phase ${phaseId} in ROADMAP.md but no directory on disk`,
|
message: `Phase ${phaseId} in ROADMAP.md but no directory on disk`,
|
||||||
remedy: {
|
remedy: adviseRemedy('Create phase directory or remove from roadmap'),
|
||||||
action: REMEDY_ACTION.ADVISE,
|
|
||||||
risk: REMEDY_RISK.NONE,
|
|
||||||
args: { command: 'Create phase directory or remove from roadmap' },
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return diagnostics;
|
return diagnostics;
|
||||||
@@ -205,11 +201,7 @@ function checkW007(snapshot: PlanningSnapshot): Diagnostic[] {
|
|||||||
code: 'W007',
|
code: 'W007',
|
||||||
severity: SEVERITY.WARNING,
|
severity: SEVERITY.WARNING,
|
||||||
message: `Phase ${token} exists on disk but not in ROADMAP.md`,
|
message: `Phase ${token} exists on disk but not in ROADMAP.md`,
|
||||||
remedy: {
|
remedy: adviseRemedy('Add to roadmap or remove directory'),
|
||||||
action: REMEDY_ACTION.ADVISE,
|
|
||||||
risk: REMEDY_RISK.NONE,
|
|
||||||
args: { command: 'Add to roadmap or remove directory' },
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return diagnostics;
|
return diagnostics;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ type PlanningSnapshot = ReturnType<typeof planningSnapshotMod.buildPlanningSnaps
|
|||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
import healthDiagnosticMod = require('../health-diagnostic-types.cjs');
|
import healthDiagnosticMod = require('../health-diagnostic-types.cjs');
|
||||||
const { SEVERITY, REMEDY_ACTION, REMEDY_RISK } = healthDiagnosticMod;
|
const { SEVERITY, REMEDY_ACTION, REMEDY_RISK, adviseRemedy } = healthDiagnosticMod;
|
||||||
type Diagnostic = healthDiagnosticMod.Diagnostic;
|
type Diagnostic = healthDiagnosticMod.Diagnostic;
|
||||||
type Rule = healthDiagnosticMod.Rule;
|
type Rule = healthDiagnosticMod.Rule;
|
||||||
|
|
||||||
@@ -52,11 +52,7 @@ function checkE002(snapshot: PlanningSnapshot): Diagnostic[] {
|
|||||||
code: 'E002',
|
code: 'E002',
|
||||||
severity: SEVERITY.ERROR,
|
severity: SEVERITY.ERROR,
|
||||||
message: 'PROJECT.md not found',
|
message: 'PROJECT.md not found',
|
||||||
remedy: {
|
remedy: adviseRemedy('/gsd-new-project'),
|
||||||
action: REMEDY_ACTION.ADVISE,
|
|
||||||
risk: REMEDY_RISK.NONE,
|
|
||||||
args: { command: '/gsd-new-project' },
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -86,11 +82,7 @@ function checkE003(snapshot: PlanningSnapshot): Diagnostic[] {
|
|||||||
code: 'E003',
|
code: 'E003',
|
||||||
severity: SEVERITY.ERROR,
|
severity: SEVERITY.ERROR,
|
||||||
message: 'ROADMAP.md not found',
|
message: 'ROADMAP.md not found',
|
||||||
remedy: {
|
remedy: adviseRemedy('/gsd-new-milestone'),
|
||||||
action: REMEDY_ACTION.ADVISE,
|
|
||||||
risk: REMEDY_RISK.NONE,
|
|
||||||
args: { command: '/gsd-new-milestone' },
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -161,11 +153,7 @@ function checkW001(snapshot: PlanningSnapshot): Diagnostic[] {
|
|||||||
code: 'W001',
|
code: 'W001',
|
||||||
severity: SEVERITY.WARNING,
|
severity: SEVERITY.WARNING,
|
||||||
message: `PROJECT.md missing section: ${required}`,
|
message: `PROJECT.md missing section: ${required}`,
|
||||||
remedy: {
|
remedy: adviseRemedy('Add section manually'),
|
||||||
action: REMEDY_ACTION.ADVISE,
|
|
||||||
risk: REMEDY_RISK.NONE,
|
|
||||||
args: { command: 'Add section manually' },
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
// `planning-snapshot.cjs`, which never touches that module's runtime values.
|
// `planning-snapshot.cjs`, which never touches that module's runtime values.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-require-imports -- export= CommonJS module
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- export= CommonJS module
|
||||||
import healthDiagnosticMod = require('../health-diagnostic-types.cjs');
|
import healthDiagnosticMod = require('../health-diagnostic-types.cjs');
|
||||||
const { SEVERITY, REMEDY_ACTION, REMEDY_RISK } = healthDiagnosticMod;
|
const { SEVERITY, adviseRemedy } = healthDiagnosticMod;
|
||||||
type Rule = healthDiagnosticMod.Rule;
|
type Rule = healthDiagnosticMod.Rule;
|
||||||
type Diagnostic = healthDiagnosticMod.Diagnostic;
|
type Diagnostic = healthDiagnosticMod.Diagnostic;
|
||||||
|
|
||||||
@@ -161,14 +161,9 @@ const RULE_W002: Rule = {
|
|||||||
code: 'W002',
|
code: 'W002',
|
||||||
severity: SEVERITY.WARNING,
|
severity: SEVERITY.WARNING,
|
||||||
message: `STATE.md references phase ${ref}, but only phases ${sortedValid.join(', ')} are declared`,
|
message: `STATE.md references phase ${ref}, but only phases ${sortedValid.join(', ')} are declared`,
|
||||||
remedy: {
|
remedy: adviseRemedy(
|
||||||
action: REMEDY_ACTION.ADVISE,
|
'Review STATE.md manually before changing it; /gsd-health --repair will not overwrite an existing STATE.md for phase mismatches',
|
||||||
risk: REMEDY_RISK.NONE,
|
),
|
||||||
args: {
|
|
||||||
command:
|
|
||||||
'Review STATE.md manually before changing it; /gsd-health --repair will not overwrite an existing STATE.md for phase mismatches',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return diagnostics;
|
return diagnostics;
|
||||||
@@ -210,11 +205,7 @@ const RULE_W011: Rule = {
|
|||||||
code: 'W011',
|
code: 'W011',
|
||||||
severity: SEVERITY.WARNING,
|
severity: SEVERITY.WARNING,
|
||||||
message: `STATE.md says current phase is ${phaseId} (status: ${statusVal || 'unknown'}) but ROADMAP.md shows it as [x] complete — state files may be out of sync`,
|
message: `STATE.md says current phase is ${phaseId} (status: ${statusVal || 'unknown'}) but ROADMAP.md shows it as [x] complete — state files may be out of sync`,
|
||||||
remedy: {
|
remedy: adviseRemedy('Run /gsd-progress to re-derive current position, or manually update STATE.md'),
|
||||||
action: REMEDY_ACTION.ADVISE,
|
|
||||||
risk: REMEDY_RISK.NONE,
|
|
||||||
args: { command: 'Run /gsd-progress to re-derive current position, or manually update STATE.md' },
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
@@ -243,11 +234,7 @@ const RULE_W021: Rule = {
|
|||||||
code: 'W021',
|
code: 'W021',
|
||||||
severity: SEVERITY.WARNING,
|
severity: SEVERITY.WARNING,
|
||||||
message: `Phase ${entry.phaseId}: integer prefix implies ${expectedMilestone} but listed under ${entry.milestone}`,
|
message: `Phase ${entry.phaseId}: integer prefix implies ${expectedMilestone} but listed under ${entry.milestone}`,
|
||||||
remedy: {
|
remedy: adviseRemedy('gsd-tools roadmap upgrade --convention milestone-prefixed'),
|
||||||
action: REMEDY_ACTION.ADVISE,
|
|
||||||
risk: REMEDY_RISK.NONE,
|
|
||||||
args: { command: 'gsd-tools roadmap upgrade --convention milestone-prefixed' },
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return diagnostics;
|
return diagnostics;
|
||||||
@@ -283,13 +270,9 @@ const RULE_W026: Rule = {
|
|||||||
code: 'W026',
|
code: 'W026',
|
||||||
severity: SEVERITY.WARNING,
|
severity: SEVERITY.WARNING,
|
||||||
message: `STATE says milestone complete but ROADMAP lists ${unstarted.length} unstarted phase(s) (e.g. Phase ${unstarted[0]})`,
|
message: `STATE says milestone complete but ROADMAP lists ${unstarted.length} unstarted phase(s) (e.g. Phase ${unstarted[0]})`,
|
||||||
remedy: {
|
remedy: adviseRemedy(
|
||||||
action: REMEDY_ACTION.ADVISE,
|
'Run validate consistency or re-run complete-milestone after verifying all phases are done',
|
||||||
risk: REMEDY_RISK.NONE,
|
),
|
||||||
args: {
|
|
||||||
command: 'Run validate consistency or re-run complete-milestone after verifying all phases are done',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -80,12 +80,27 @@ interface Rule {
|
|||||||
check: (snapshot: PlanningSnapshot) => Diagnostic[]; // §8.1 rule 1 signature, verbatim
|
check: (snapshot: PlanningSnapshot) => Diagnostic[]; // §8.1 rule 1 signature, verbatim
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── adviseRemedy — shared ADVISE-remedy builder ───────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Every rule-group file needs the same `{action: ADVISE, risk: NONE, args:
|
||||||
|
* {command}}` shape for a non-repairable finding's `fix` string (§8.3 rule
|
||||||
|
* 5). Was defined identically in `config-validation.cts` and
|
||||||
|
* `agent-install.cts`, and repeated inline elsewhere — moved to this shared,
|
||||||
|
* dependency-free leaf so every rule-group file imports one implementation
|
||||||
|
* instead of duplicating it.
|
||||||
|
*/
|
||||||
|
function adviseRemedy(command: string): Remedy {
|
||||||
|
return { action: REMEDY_ACTION.ADVISE, risk: REMEDY_RISK.NONE, args: { command } };
|
||||||
|
}
|
||||||
|
|
||||||
// ─── Exports ────────────────────────────────────────────────────────────────
|
// ─── Exports ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
const healthDiagnosticTypes = {
|
const healthDiagnosticTypes = {
|
||||||
SEVERITY,
|
SEVERITY,
|
||||||
REMEDY_ACTION,
|
REMEDY_ACTION,
|
||||||
REMEDY_RISK,
|
REMEDY_RISK,
|
||||||
|
adviseRemedy,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Namespace merge (same binding name as the value above) is how a CommonJS
|
// Namespace merge (same binding name as the value above) is how a CommonJS
|
||||||
|
|||||||
Reference in New Issue
Block a user