@decantr/cli 1.10.0 → 1.11.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/README.md +2 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-FLZVSNB5.js → chunk-5RODH77L.js} +4 -3
- package/dist/{chunk-K5KCZSEI.js → chunk-6YCFRZZI.js} +45 -6
- package/dist/{health-SIKAOE2Z.js → health-3TJYYTX6.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/{studio-EQSSNA6D.js → studio-7TE7YXFG.js} +1 -1
- package/package.json +4 -4
- package/src/templates/decantr-health.workflow.yml.template +5 -5
package/README.md
CHANGED
|
@@ -99,11 +99,12 @@ decantr health --ci --fail-on warn
|
|
|
99
99
|
decantr health --prompt <finding-id>
|
|
100
100
|
decantr health init-ci
|
|
101
101
|
decantr health init-ci --fail-on warn --cli-version latest --force
|
|
102
|
+
decantr health init-ci --project apps/registry
|
|
102
103
|
```
|
|
103
104
|
|
|
104
105
|
Use `--json` for machines and schema validation, `--markdown` for CI summaries, and `--prompt <finding-id>` when you want a scoped remediation prompt for an AI assistant. `--ci --fail-on error` fails only when blocking errors exist; `--ci --fail-on warn` also fails on warnings.
|
|
105
106
|
|
|
106
|
-
`decantr health init-ci` installs `.github/workflows/decantr-health.yml` for GitHub Actions. The generated workflow installs project dependencies, writes `decantr-health.json`, gates with `decantr health --ci --fail-on error --markdown --output decantr-health.md`, appends the markdown report to the GitHub step summary, and uploads both files as artifacts. Use `--force` to replace an existing workflow, `--fail-on warn` for stricter repositories, or `--cli-version <version|latest>` to pin the package used by CI.
|
|
107
|
+
`decantr health init-ci` installs `.github/workflows/decantr-health.yml` for GitHub Actions. The generated workflow installs project dependencies, writes `decantr-health.json`, gates with `decantr health --ci --fail-on error --markdown --output decantr-health.md`, appends the markdown report to the GitHub step summary, and uploads both files as artifacts. Use `--force` to replace an existing workflow, `--fail-on warn` for stricter repositories, or `--cli-version <version|latest>` to pin the package used by CI. In monorepos, add `--project <path>` from the repository root; dependency install stays at the root while health runs inside the app contract and uploads artifacts from that project path.
|
|
107
108
|
|
|
108
109
|
`decantr studio` starts a local-only dashboard powered by the same report. It uses Node built-ins only and serves `GET /`, `GET /api/health`, and `POST /api/refresh`.
|
|
109
110
|
|
package/dist/bin.js
CHANGED
|
@@ -6927,7 +6927,7 @@ ${BOLD6}Usage:${RESET13}
|
|
|
6927
6927
|
decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]
|
|
6928
6928
|
decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>]
|
|
6929
6929
|
decantr registry audit-project [--namespace <namespace>] [--json] [--essence <path>] [--dist <path>] [--sources <dir>]
|
|
6930
|
-
decantr health init-ci [--force] [--fail-on <error|warn|none>] [--cli-version <version|latest>]
|
|
6930
|
+
decantr health init-ci [--force] [--project <path>] [--fail-on <error|warn|none>] [--cli-version <version|latest>]
|
|
6931
6931
|
decantr content-health [--json] [--markdown] [--ci]
|
|
6932
6932
|
decantr rules preview [--project=<path>]
|
|
6933
6933
|
decantr rules apply [--project=<path>]
|
|
@@ -7007,6 +7007,7 @@ ${BOLD6}Examples:${RESET13}
|
|
|
7007
7007
|
decantr status
|
|
7008
7008
|
decantr health
|
|
7009
7009
|
decantr health init-ci
|
|
7010
|
+
decantr health init-ci --project apps/web
|
|
7010
7011
|
decantr health --ci --fail-on error
|
|
7011
7012
|
decantr content-health --ci --fail-on error
|
|
7012
7013
|
decantr studio
|
|
@@ -7190,7 +7191,7 @@ async function main() {
|
|
|
7190
7191
|
}
|
|
7191
7192
|
case "health": {
|
|
7192
7193
|
try {
|
|
7193
|
-
const { cmdHealth, parseHealthArgs } = await import("./health-
|
|
7194
|
+
const { cmdHealth, parseHealthArgs } = await import("./health-3TJYYTX6.js");
|
|
7194
7195
|
await cmdHealth(process.cwd(), parseHealthArgs(args));
|
|
7195
7196
|
} catch (e) {
|
|
7196
7197
|
console.error(error3(e.message));
|
|
@@ -7210,7 +7211,7 @@ async function main() {
|
|
|
7210
7211
|
}
|
|
7211
7212
|
case "studio": {
|
|
7212
7213
|
try {
|
|
7213
|
-
const { cmdStudio, parseStudioArgs } = await import("./studio-
|
|
7214
|
+
const { cmdStudio, parseStudioArgs } = await import("./studio-7TE7YXFG.js");
|
|
7214
7215
|
await cmdStudio(process.cwd(), parseStudioArgs(args));
|
|
7215
7216
|
} catch (e) {
|
|
7216
7217
|
console.error(error3(e.message));
|
|
@@ -92,17 +92,45 @@ function validateArtifactPath(value, flag) {
|
|
|
92
92
|
}
|
|
93
93
|
return normalized;
|
|
94
94
|
}
|
|
95
|
+
function validateProjectPath(value) {
|
|
96
|
+
if (value === void 0) return void 0;
|
|
97
|
+
const raw = value.trim();
|
|
98
|
+
if (!raw || raw === ".") return void 0;
|
|
99
|
+
const normalized = raw.replace(/^\.\/+/, "").replace(/\/+$/, "");
|
|
100
|
+
if (!normalized || normalized.startsWith("/") || normalized.startsWith("-") || normalized.includes("..") || normalized.includes("\\") || /\s/.test(normalized) || !/^[A-Za-z0-9._@/-]+$/.test(normalized)) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
"Invalid --project value. Use a relative project path without spaces or parent-directory segments."
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
const segments = normalized.split("/");
|
|
106
|
+
if (segments.some((segment) => !segment || segment === "." || segment === "..")) {
|
|
107
|
+
throw new Error(
|
|
108
|
+
"Invalid --project value. Use a relative project path without empty or parent-directory segments."
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
return normalized;
|
|
112
|
+
}
|
|
113
|
+
function prefixArtifactPath(projectPath, artifactPath) {
|
|
114
|
+
return projectPath ? `${projectPath}/${artifactPath}` : artifactPath;
|
|
115
|
+
}
|
|
95
116
|
function renderProjectHealthCiWorkflow(options = {}) {
|
|
96
117
|
const failOn = normalizeHealthFailOn(options.failOn);
|
|
118
|
+
const projectPath = validateProjectPath(options.projectPath);
|
|
119
|
+
const reportPath = validateArtifactPath(
|
|
120
|
+
options.reportPath || DEFAULT_HEALTH_CI_REPORT_PATH,
|
|
121
|
+
"--report-path"
|
|
122
|
+
);
|
|
123
|
+
const jsonPath = validateArtifactPath(options.jsonPath || DEFAULT_HEALTH_CI_JSON_PATH, "--json-path");
|
|
97
124
|
const template = loadHealthTemplate("decantr-health.workflow.yml.template");
|
|
98
125
|
return renderTemplate(template, {
|
|
99
126
|
CLI_PACKAGE: normalizeCliPackageSpecifier(options.cliVersion),
|
|
100
127
|
FAIL_ON: failOn,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
128
|
+
PROJECT_WORKING_DIRECTORY: projectPath ? ` working-directory: ${projectPath}
|
|
129
|
+
` : "",
|
|
130
|
+
REPORT_PATH: reportPath,
|
|
131
|
+
JSON_PATH: jsonPath,
|
|
132
|
+
REPORT_ARTIFACT_PATH: prefixArtifactPath(projectPath, reportPath),
|
|
133
|
+
JSON_ARTIFACT_PATH: prefixArtifactPath(projectPath, jsonPath)
|
|
106
134
|
});
|
|
107
135
|
}
|
|
108
136
|
function writeProjectHealthCiWorkflow(projectRoot, options = {}) {
|
|
@@ -118,12 +146,15 @@ function writeProjectHealthCiWorkflow(projectRoot, options = {}) {
|
|
|
118
146
|
}
|
|
119
147
|
mkdirSync(dirname(workflowPath), { recursive: true });
|
|
120
148
|
writeFileSync(workflowPath, renderProjectHealthCiWorkflow(options), "utf-8");
|
|
121
|
-
|
|
149
|
+
const projectPath = validateProjectPath(options.projectPath);
|
|
150
|
+
const result = {
|
|
122
151
|
path: workflowRelativePath,
|
|
123
152
|
created: !alreadyExists,
|
|
124
153
|
cliPackage: normalizeCliPackageSpecifier(options.cliVersion),
|
|
125
154
|
failOn: normalizeHealthFailOn(options.failOn)
|
|
126
155
|
};
|
|
156
|
+
if (projectPath) result.projectPath = projectPath;
|
|
157
|
+
return result;
|
|
127
158
|
}
|
|
128
159
|
function collectDeclaredRoutes(essence) {
|
|
129
160
|
if (!essence || typeof essence !== "object") return [];
|
|
@@ -490,6 +521,9 @@ async function cmdHealth(projectRoot = process.cwd(), options = {}) {
|
|
|
490
521
|
const action = result.created ? "Created" : "Updated";
|
|
491
522
|
console.log(`${GREEN}${action} Decantr Project Health workflow:${RESET} ${result.path}`);
|
|
492
523
|
console.log(`${DIM}CLI package: ${result.cliPackage}${RESET}`);
|
|
524
|
+
if (result.projectPath) {
|
|
525
|
+
console.log(`${DIM}Project: ${result.projectPath}${RESET}`);
|
|
526
|
+
}
|
|
493
527
|
console.log(`${DIM}CI gate: decantr health --ci --fail-on ${result.failOn}${RESET}`);
|
|
494
528
|
} catch (e) {
|
|
495
529
|
console.error(`${RED}${e.message}${RESET}`);
|
|
@@ -552,9 +586,14 @@ function parseHealthArgs(args) {
|
|
|
552
586
|
options.initCi.jsonPath = args[++index];
|
|
553
587
|
} else if (arg.startsWith("--json-path=")) {
|
|
554
588
|
options.initCi.jsonPath = arg.split("=")[1];
|
|
589
|
+
} else if (arg === "--project" && args[index + 1]) {
|
|
590
|
+
options.initCi.projectPath = args[++index];
|
|
591
|
+
} else if (arg.startsWith("--project=")) {
|
|
592
|
+
options.initCi.projectPath = arg.split("=")[1];
|
|
555
593
|
}
|
|
556
594
|
}
|
|
557
595
|
normalizeHealthFailOn(options.initCi.failOn);
|
|
596
|
+
validateProjectPath(options.initCi.projectPath);
|
|
558
597
|
return options;
|
|
559
598
|
}
|
|
560
599
|
for (let index = 1; index < args.length; index += 1) {
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decantr/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"description": "Decantr CLI - scaffold, audit, inspect Project Health, and maintain Decantr projects from the terminal",
|
|
5
5
|
"author": "Decantr AI",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,12 +30,12 @@
|
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"ajv": "^8.
|
|
33
|
+
"ajv": "^8.20.0",
|
|
34
34
|
"@decantr/core": "1.0.6",
|
|
35
|
-
"@decantr/essence-spec": "1.0.7",
|
|
36
35
|
"@decantr/registry": "1.1.0",
|
|
37
36
|
"@decantr/telemetry": "0.1.2",
|
|
38
|
-
"@decantr/verifier": "1.1.
|
|
37
|
+
"@decantr/verifier": "1.1.1",
|
|
38
|
+
"@decantr/essence-spec": "1.0.8"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "tsup",
|
|
@@ -38,14 +38,14 @@ jobs:
|
|
|
38
38
|
fi
|
|
39
39
|
|
|
40
40
|
- name: Generate Decantr health JSON
|
|
41
|
-
run: npx --yes {{CLI_PACKAGE}} health --json --output {{JSON_PATH}}
|
|
41
|
+
{{PROJECT_WORKING_DIRECTORY}} run: npx --yes {{CLI_PACKAGE}} health --json --output {{JSON_PATH}}
|
|
42
42
|
|
|
43
43
|
- name: Audit Decantr health
|
|
44
|
-
run: npx --yes {{CLI_PACKAGE}} health --ci --fail-on {{FAIL_ON}} --markdown --output {{REPORT_PATH}}
|
|
44
|
+
{{PROJECT_WORKING_DIRECTORY}} run: npx --yes {{CLI_PACKAGE}} health --ci --fail-on {{FAIL_ON}} --markdown --output {{REPORT_PATH}}
|
|
45
45
|
|
|
46
46
|
- name: Publish health summary
|
|
47
47
|
if: always()
|
|
48
|
-
shell: bash
|
|
48
|
+
{{PROJECT_WORKING_DIRECTORY}} shell: bash
|
|
49
49
|
run: |
|
|
50
50
|
if [ -f {{REPORT_PATH}} ]; then
|
|
51
51
|
cat {{REPORT_PATH}} >> "$GITHUB_STEP_SUMMARY"
|
|
@@ -57,6 +57,6 @@ jobs:
|
|
|
57
57
|
with:
|
|
58
58
|
name: decantr-project-health
|
|
59
59
|
path: |
|
|
60
|
-
{{
|
|
61
|
-
{{
|
|
60
|
+
{{JSON_ARTIFACT_PATH}}
|
|
61
|
+
{{REPORT_ARTIFACT_PATH}}
|
|
62
62
|
if-no-files-found: ignore
|