@hongmaple0820/scale-engine 0.18.0 → 0.20.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.en.md +310 -237
- package/README.md +255 -63
- package/dist/api/cli.js +2656 -1258
- package/dist/api/cli.js.map +1 -1
- package/dist/api/doctor.d.ts +4 -1
- package/dist/api/doctor.js +85 -1
- package/dist/api/doctor.js.map +1 -1
- package/dist/api/quickstart.d.ts +3 -0
- package/dist/api/quickstart.js +9 -4
- package/dist/api/quickstart.js.map +1 -1
- package/dist/cli/phaseCommands.js +7 -0
- package/dist/cli/phaseCommands.js.map +1 -1
- package/dist/codegraph/CodeIntelligence.d.ts +135 -0
- package/dist/codegraph/CodeIntelligence.js +460 -0
- package/dist/codegraph/CodeIntelligence.js.map +1 -0
- package/dist/context/ContextBudget.d.ts +90 -0
- package/dist/context/ContextBudget.js +322 -0
- package/dist/context/ContextBudget.js.map +1 -0
- package/dist/eval/WorkflowEval.d.ts +161 -0
- package/dist/eval/WorkflowEval.js +379 -0
- package/dist/eval/WorkflowEval.js.map +1 -0
- package/dist/governance/GovernanceRoi.d.ts +25 -0
- package/dist/governance/GovernanceRoi.js +70 -0
- package/dist/governance/GovernanceRoi.js.map +1 -0
- package/dist/governance/ProgressiveGovernance.d.ts +22 -0
- package/dist/governance/ProgressiveGovernance.js +159 -0
- package/dist/governance/ProgressiveGovernance.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/memory/MemoryBrain.d.ts +135 -0
- package/dist/memory/MemoryBrain.js +635 -0
- package/dist/memory/MemoryBrain.js.map +1 -0
- package/dist/memory/MemoryFabric.d.ts +118 -0
- package/dist/memory/MemoryFabric.js +281 -0
- package/dist/memory/MemoryFabric.js.map +1 -0
- package/dist/memory/MemoryLearning.d.ts +61 -0
- package/dist/memory/MemoryLearning.js +203 -0
- package/dist/memory/MemoryLearning.js.map +1 -0
- package/dist/memory/index.d.ts +3 -0
- package/dist/memory/index.js +4 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/output/GovernanceDashboard.d.ts +57 -0
- package/dist/output/GovernanceDashboard.js +250 -0
- package/dist/output/GovernanceDashboard.js.map +1 -0
- package/dist/output/HTMLArtifactLayer.js +31 -31
- package/dist/output/index.d.ts +2 -0
- package/dist/output/index.js +1 -0
- package/dist/output/index.js.map +1 -1
- package/dist/prompts/VibeTemplateGallery.js +121 -121
- package/dist/runtime/FinalReportGuard.d.ts +16 -0
- package/dist/runtime/FinalReportGuard.js +14 -0
- package/dist/runtime/FinalReportGuard.js.map +1 -0
- package/dist/runtime/RuntimeDoctor.d.ts +23 -0
- package/dist/runtime/RuntimeDoctor.js +151 -0
- package/dist/runtime/RuntimeDoctor.js.map +1 -0
- package/dist/runtime/RuntimeEvidenceLedger.d.ts +50 -0
- package/dist/runtime/RuntimeEvidenceLedger.js +89 -0
- package/dist/runtime/RuntimeEvidenceLedger.js.map +1 -0
- package/dist/runtime/SessionLedger.d.ts +53 -0
- package/dist/runtime/SessionLedger.js +104 -0
- package/dist/runtime/SessionLedger.js.map +1 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.js +5 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/skills/SkillRadar.d.ts +83 -0
- package/dist/skills/SkillRadar.js +384 -0
- package/dist/skills/SkillRadar.js.map +1 -0
- package/dist/workflow/EngineeringStandards.js +69 -66
- package/dist/workflow/EngineeringStandards.js.map +1 -1
- package/dist/workflow/GovernanceTemplatePacks.js +126 -126
- package/dist/workflow/GovernanceTemplates.d.ts +1 -1
- package/dist/workflow/GovernanceTemplates.js +500 -229
- package/dist/workflow/GovernanceTemplates.js.map +1 -1
- package/dist/workflow/ResourceGovernance.js +27 -18
- package/dist/workflow/ResourceGovernance.js.map +1 -1
- package/dist/workflow/VerificationCommands.d.ts +11 -0
- package/dist/workflow/VerificationCommands.js +2 -0
- package/dist/workflow/VerificationCommands.js.map +1 -1
- package/dist/workflow/VerificationProfile.d.ts +2 -1
- package/dist/workflow/VerificationProfile.js +3 -0
- package/dist/workflow/VerificationProfile.js.map +1 -1
- package/dist/workflow/WorkflowArtifactWriter.js +2 -1
- package/dist/workflow/WorkflowArtifactWriter.js.map +1 -1
- package/dist/workflow/WorkflowEngine.js +4 -1
- package/dist/workflow/WorkflowEngine.js.map +1 -1
- package/dist/workflow/WorkspaceSafety.d.ts +9 -0
- package/dist/workflow/WorkspaceSafety.js +49 -0
- package/dist/workflow/WorkspaceSafety.js.map +1 -0
- package/dist/workflow/gates/GateSystem.d.ts +12 -1
- package/dist/workflow/gates/GateSystem.js +106 -0
- package/dist/workflow/gates/GateSystem.js.map +1 -1
- package/dist/workflow/types.d.ts +1 -1
- package/docs/CODE_INTELLIGENCE.md +138 -0
- package/docs/CONTEXT_BUDGET.md +87 -0
- package/docs/GOVERNANCE_DASHBOARD.md +69 -0
- package/docs/MEMORY_BRAIN.md +104 -0
- package/docs/MEMORY_FABRIC.md +107 -0
- package/docs/README.md +76 -0
- package/docs/RUNTIME_EVIDENCE.md +101 -0
- package/docs/SKILL_RADAR.md +115 -0
- package/docs/WORKFLOW_EVAL.md +151 -0
- package/docs/start/README.md +42 -0
- package/docs/start/agent-governance-demo.md +107 -0
- package/docs/start/quickstart.md +127 -0
- package/examples/demo-projects/agent-governance-demo/README.md +37 -0
- package/examples/demo-projects/agent-governance-demo/package.json +16 -0
- package/examples/demo-projects/agent-governance-demo/src/oauth-state.ts +39 -0
- package/examples/demo-projects/agent-governance-demo/tests/oauth-state.test.ts +52 -0
- package/package.json +14 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
2
|
+
import { basename, join } from 'node:path';
|
|
3
3
|
import { skillRoutingPolicyTemplate } from '../skills/routing/SkillPolicy.js';
|
|
4
4
|
import { readGovernanceLock, writeGovernanceLock } from './GovernanceLock.js';
|
|
5
5
|
import { resolveGovernanceTemplatePack, } from './GovernanceTemplatePacks.js';
|
|
@@ -12,7 +12,7 @@ export function writeGovernanceTemplates(projectDir = process.cwd(), options = {
|
|
|
12
12
|
const projectName = options.projectName ?? 'Project';
|
|
13
13
|
const pack = resolveGovernanceTemplatePack(options.pack);
|
|
14
14
|
const packMode = pack.modeDefaults[mode];
|
|
15
|
-
const services = options.services ?? pack.defaultServices ??
|
|
15
|
+
const services = options.services ?? pack.defaultServices ?? detectRootServices(projectDir, pack.id);
|
|
16
16
|
const exclude = options.exclude ?? pack.exclude ?? ['node_modules', 'dist', 'tmp', 'vendor'];
|
|
17
17
|
const result = { created: [], skipped: [] };
|
|
18
18
|
const lockFiles = new Map();
|
|
@@ -34,6 +34,7 @@ export function writeGovernanceTemplates(projectDir = process.cwd(), options = {
|
|
|
34
34
|
writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/security-review.md', governanceTemplateContent('security-review.md'));
|
|
35
35
|
writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/db-change-plan.md', governanceTemplateContent('db-change-plan.md'));
|
|
36
36
|
writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/e2e-plan.md', governanceTemplateContent('e2e-plan.md'));
|
|
37
|
+
writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/product-smoke.md', governanceTemplateContent('product-smoke.md'));
|
|
37
38
|
writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/plan.md', governanceTemplateContent('plan.md'));
|
|
38
39
|
writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/verification.md', governanceTemplateContent('verification.md'));
|
|
39
40
|
writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/review.md', governanceTemplateContent('review.md'));
|
|
@@ -41,6 +42,8 @@ export function writeGovernanceTemplates(projectDir = process.cwd(), options = {
|
|
|
41
42
|
writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/github-actions-scale-preflight.yml', githubActionsPreflightTemplate());
|
|
42
43
|
writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/pre-push-scale-preflight.sh', prePushPreflightTemplate());
|
|
43
44
|
writeTracked(result, lockFiles, projectDir, 'docs/worklog/metrics.md', metricsTemplate());
|
|
45
|
+
writeTracked(result, lockFiles, projectDir, 'scripts/qa/product-smoke.ps1', productSmokePowerShellScript());
|
|
46
|
+
writeTracked(result, lockFiles, projectDir, 'scripts/qa/product-smoke.sh', productSmokeShellScript());
|
|
44
47
|
writeTracked(result, lockFiles, projectDir, '.scale/verification.json', verificationMatrixTemplate(mode, {
|
|
45
48
|
services,
|
|
46
49
|
exclude,
|
|
@@ -51,6 +54,7 @@ export function writeGovernanceTemplates(projectDir = process.cwd(), options = {
|
|
|
51
54
|
writeTracked(result, lockFiles, projectDir, '.scale/resource-policy.json', resourcePolicyTemplate());
|
|
52
55
|
writeTracked(result, lockFiles, projectDir, '.scale/assets.json', resourceManifestTemplate());
|
|
53
56
|
writeTracked(result, lockFiles, projectDir, '.scale/output-policy.json', outputPolicyTemplate());
|
|
57
|
+
writeTracked(result, lockFiles, projectDir, '.scale/product-smoke.json', productSmokeConfigTemplate(mode));
|
|
54
58
|
writeTracked(result, lockFiles, projectDir, '.scale/engineering-standards.json', engineeringStandardsPolicyTemplate());
|
|
55
59
|
writeTracked(result, lockFiles, projectDir, '.scale/engineering-standards-baseline.json', engineeringStandardsBaselineTemplate());
|
|
56
60
|
writeTracked(result, lockFiles, projectDir, '.scale/frameworks.json', frameworksCatalogTemplate());
|
|
@@ -83,6 +87,7 @@ export function governanceTemplateContent(name) {
|
|
|
83
87
|
case 'security-review.md': return securityReviewTemplate();
|
|
84
88
|
case 'db-change-plan.md': return dbChangePlanTemplate();
|
|
85
89
|
case 'e2e-plan.md': return e2ePlanTemplate();
|
|
90
|
+
case 'product-smoke.md': return productSmokeTemplate();
|
|
86
91
|
case 'plan.md': return planTemplate();
|
|
87
92
|
case 'verification.md': return verificationTemplate();
|
|
88
93
|
case 'review.md': return reviewTemplate();
|
|
@@ -114,6 +119,38 @@ function writePackGeneratedFile(result, lockFiles, projectDir, packId, packVersi
|
|
|
114
119
|
if (created)
|
|
115
120
|
lockFiles.set(file.path, { path: file.path, owned: file.owned });
|
|
116
121
|
}
|
|
122
|
+
function detectRootServices(projectDir, packId) {
|
|
123
|
+
if (packId === 'moe-workspace' || packId === 'go-service-matrix')
|
|
124
|
+
return [];
|
|
125
|
+
if (existsSync(join(projectDir, 'package.json'))) {
|
|
126
|
+
return [{ name: detectNodeServiceName(projectDir), path: '.', type: 'node', required: true }];
|
|
127
|
+
}
|
|
128
|
+
if (existsSync(join(projectDir, 'go.mod'))) {
|
|
129
|
+
return [{ name: basename(projectDir) || 'app', path: '.', type: 'go', required: true }];
|
|
130
|
+
}
|
|
131
|
+
if (existsSync(join(projectDir, 'pyproject.toml')) ||
|
|
132
|
+
existsSync(join(projectDir, 'requirements.txt')) ||
|
|
133
|
+
existsSync(join(projectDir, 'setup.py'))) {
|
|
134
|
+
return [{ name: basename(projectDir) || 'app', path: '.', type: 'python', required: true }];
|
|
135
|
+
}
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
function detectNodeServiceName(projectDir) {
|
|
139
|
+
try {
|
|
140
|
+
const pkg = JSON.parse(readFileSync(join(projectDir, 'package.json'), 'utf-8'));
|
|
141
|
+
const raw = typeof pkg.name === 'string' ? pkg.name : '';
|
|
142
|
+
const normalized = raw
|
|
143
|
+
.replace(/^@[^/]+\//, '')
|
|
144
|
+
.replace(/[^a-zA-Z0-9_-]+/g, '-')
|
|
145
|
+
.replace(/^-+|-+$/g, '');
|
|
146
|
+
if (normalized)
|
|
147
|
+
return normalized;
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// Fall back to the directory name when package.json is absent or malformed.
|
|
151
|
+
}
|
|
152
|
+
return basename(projectDir) || 'app';
|
|
153
|
+
}
|
|
117
154
|
function shouldUseGeneratedHeader(file) {
|
|
118
155
|
return file.kind === 'doc' || file.kind === 'template' || file.kind === 'script';
|
|
119
156
|
}
|
|
@@ -141,17 +178,17 @@ Governance pack: ${packId}
|
|
|
141
178
|
## Standard Task Directory
|
|
142
179
|
|
|
143
180
|
\`\`\`text
|
|
144
|
-
docs/worklog/tasks/<yyyy-mm-dd>-<task-slug>/
|
|
145
|
-
├── explore.md
|
|
146
|
-
├── mini-prd.md
|
|
147
|
-
├── plan.md
|
|
148
|
-
├── verification.md
|
|
149
|
-
├── review.md
|
|
150
|
-
├── summary.md
|
|
151
|
-
├── artifact-manifest.json
|
|
152
|
-
└── artifacts/
|
|
153
|
-
├── index.html
|
|
154
|
-
└── release-report.html
|
|
181
|
+
docs/worklog/tasks/<yyyy-mm-dd>-<task-slug>/
|
|
182
|
+
├── explore.md
|
|
183
|
+
├── mini-prd.md
|
|
184
|
+
├── plan.md
|
|
185
|
+
├── verification.md
|
|
186
|
+
├── review.md
|
|
187
|
+
├── summary.md
|
|
188
|
+
├── artifact-manifest.json
|
|
189
|
+
└── artifacts/
|
|
190
|
+
├── index.html
|
|
191
|
+
└── release-report.html
|
|
155
192
|
\`\`\`
|
|
156
193
|
|
|
157
194
|
## Verification
|
|
@@ -164,40 +201,41 @@ scale preflight --service all --preflight-profile full
|
|
|
164
201
|
scale verify <task-id> --profile default
|
|
165
202
|
scale verify <task-id> --service <service-name>
|
|
166
203
|
scale verify <task-id> --artifact-gate warn
|
|
167
|
-
scale verify <task-id> --artifact-gate block
|
|
168
|
-
scale verify <task-id> --require-installed-skills
|
|
169
|
-
scale
|
|
170
|
-
scale
|
|
171
|
-
scale artifact
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
Keep \`.scale/
|
|
176
|
-
Keep \`.scale/
|
|
177
|
-
Keep \`.scale/
|
|
178
|
-
Keep \`.scale/
|
|
179
|
-
Keep \`.scale/engineering-standards
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
-
|
|
196
|
-
-
|
|
197
|
-
-
|
|
198
|
-
-
|
|
199
|
-
|
|
200
|
-
|
|
204
|
+
scale verify <task-id> --artifact-gate block
|
|
205
|
+
scale verify <task-id> --require-installed-skills
|
|
206
|
+
scale verify <task-id> --profile productSmoke
|
|
207
|
+
scale task-artifacts check --dir docs/worklog/tasks/<task-dir> --level L
|
|
208
|
+
scale artifact render --task-id <task-dir> --type release-report
|
|
209
|
+
scale artifact doctor --task-id <task-dir>
|
|
210
|
+
\`\`\`
|
|
211
|
+
|
|
212
|
+
Keep \`.scale/verification.json\` as the source of truth for profiles and service commands.
|
|
213
|
+
Keep \`.scale/skills.json\` as the source of truth for active skill routing policy.
|
|
214
|
+
Keep \`.scale/output-policy.json\` as the source of truth for derived HTML artifact types, source Markdown mapping, security policy, and Git retention behavior.
|
|
215
|
+
Keep \`.scale/resource-policy.json\` and \`.scale/assets.json\` as the source of truth for generated reports, temporary files, module documentation, media, reusable scripts, and Git retention policy.
|
|
216
|
+
Keep \`.scale/engineering-standards.json\` and \`.scale/frameworks.json\` as the source of truth for logging, security, ORM, architecture, framework, UI/UX, testing, and coding standard checks.
|
|
217
|
+
Keep \`.scale/engineering-standards-baseline.json\` as the temporary exception list for known legacy standards findings; it must not be used to hide new or changed-file problems.
|
|
218
|
+
Use \`artifactGate: "warn"\` while introducing the workflow, then move M/L/CRITICAL work to \`"block"\` once templates and local gates are stable.
|
|
219
|
+
|
|
220
|
+
## HTML Artifacts
|
|
221
|
+
|
|
222
|
+
Markdown remains the editable source of truth for task artifacts. HTML artifacts are derived human-review surfaces for plan comparison, implementation plans, code reviews, status reports, incident reports, and release reports.
|
|
223
|
+
|
|
224
|
+
Use HTML when a human needs to compare, review, or sign off. Keep source Markdown, manifest metadata, and safety checks in place so the derived HTML stays traceable and does not leak secrets or remote scripts.
|
|
225
|
+
|
|
226
|
+
## Active Skill Routing
|
|
227
|
+
|
|
228
|
+
SCALE plans required skills from task description, service selection, and changed files. UI/API work requires a Mini-PRD plus domain evidence such as \`ui-spec.md\`, \`visual-review.md\`, or \`api-contract.md\`. Security and database work require explicit review or rollback artifacts.
|
|
229
|
+
|
|
230
|
+
Tool orchestration is part of the workflow contract:
|
|
231
|
+
|
|
232
|
+
- UI/UX work requires \`frontend-design\` and \`ui-ux-pro-max\`, and should consider \`awesome-design-md\`, browser screenshots, responsive checks, and visual review evidence.
|
|
233
|
+
- Web research, logged-in pages, and dynamic browser work require \`web-access\` evidence, source citations, and browser/network/console evidence when available.
|
|
234
|
+
- Browser E2E work should combine \`webapp-testing\`, Playwright, Agent Browser, web-access, or Chrome DevTools MCP according to the target and record screenshots plus console/network findings.
|
|
235
|
+
- Desktop or client-side GUI automation uses CUA/computer-use only with explicit operator-safety notes, desktop screenshots, and a side-effect boundary.
|
|
236
|
+
- External agent or CLI orchestration such as Codex, Gemini CLI, OpenCode, WPS, or WeChat automation must record version checks, exact commands, output summaries, and dry-run or safe-mode evidence.
|
|
237
|
+
|
|
238
|
+
When a task records \`servicesTouched\`, \`scale verify <task-id>\` uses those services automatically. You can still override selection with \`--service all\`, \`--service api\`, or \`--service api,gateway\`.
|
|
201
239
|
|
|
202
240
|
Before M/L work, check whether required workflow skills are physically installed:
|
|
203
241
|
|
|
@@ -211,67 +249,69 @@ scale skill check --require-installed --json
|
|
|
211
249
|
Before finishing an agent-created branch or deleting a temporary worktree, inspect root and child repository state:
|
|
212
250
|
|
|
213
251
|
\`\`\`bash
|
|
214
|
-
scale workspace status --json
|
|
215
|
-
scale workspace finish --summary
|
|
216
|
-
scale workspace finish --json
|
|
217
|
-
scale workspace cleanup --dir <temporary-worktree> --dry-run --json
|
|
218
|
-
scale workspace cleanup --dir <temporary-worktree> --apply --confirm <branch-or-head> --json
|
|
219
|
-
\`\`\`
|
|
220
|
-
|
|
221
|
-
Do not remove a temporary worktree while any submodule or nested repository has uncommitted or unpushed work. Child repositories must be committed and reviewed in their own remotes, then the root repository can record any required pointer or governance updates. Cleanup defaults to dry-run. Applying cleanup requires the reported confirmation token, normally the temporary branch name.
|
|
222
|
-
|
|
223
|
-
Use \`scale ship <task-id>\` for governed commits. It checks MOE/submodule child repository state before staging reviewed root files, so dirty or unpushed child work cannot be hidden inside a root commit. Raw \`git add .\` is outside the governed path and must not be used for MOE releases.
|
|
224
|
-
|
|
225
|
-
## Resource Governance
|
|
226
|
-
|
|
227
|
-
Use asset scanning before committing generated reports, media, temporary scripts, or long-lived documentation changes:
|
|
228
|
-
|
|
229
|
-
\`\`\`bash
|
|
230
|
-
scale assets scan --json
|
|
231
|
-
scale assets doctor --json
|
|
232
|
-
scale assets settle --task-id <task-id> --artifact-dir docs/worklog/tasks/<task-dir>
|
|
233
|
-
\`\`\`
|
|
234
|
-
|
|
235
|
-
Default policy:
|
|
236
|
-
|
|
237
|
-
- maintained module docs, standards, contracts, ADRs, reusable scripts: commit and keep current.
|
|
238
|
-
- task worklog artifacts: review before commit; promote final truth to maintained docs when useful.
|
|
239
|
-
- screenshots, videos, E2E reports, coverage, temporary scripts, and runtime logs: keep out of Git unless explicitly promoted.
|
|
240
|
-
- large media: use Git LFS or external artifact storage instead of normal Git history.
|
|
241
|
-
|
|
242
|
-
## Engineering Standards
|
|
243
|
-
|
|
244
|
-
Use standards scanning before reviewing or shipping M/L/CRITICAL work:
|
|
245
|
-
|
|
246
|
-
\`\`\`bash
|
|
247
|
-
scale standards scan --json
|
|
248
|
-
scale standards doctor --json
|
|
249
|
-
scale standards doctor --changed --json
|
|
250
|
-
scale standards doctor --changed-files src/example.ts,src/example.test.ts --json
|
|
251
|
-
scale standards baseline --write --artifact-dir docs/worklog/tasks/<task-dir> --task-id <task-id> --json
|
|
252
|
-
scale standards settle --task-id <task-id> --artifact-dir docs/worklog/tasks/<task-dir>
|
|
253
|
-
scale preflight --preflight-profile full --json
|
|
254
|
-
scale verify <task-id> --json
|
|
255
|
-
\`\`\`
|
|
256
|
-
|
|
257
|
-
Default policy:
|
|
258
|
-
|
|
259
|
-
- ad-hoc console/output logging is allowed only for CLI/script paths.
|
|
260
|
-
- sensitive fields such as token, password, secret, authorization, cookie, and credentials must not be logged.
|
|
261
|
-
- hardcoded secret-like assignments are blocked before review or release.
|
|
262
|
-
- SQL must use parameterized queries, ORM bind parameters, or safe query builders.
|
|
263
|
-
- unsafe HTML sinks, dynamic code execution, empty catch blocks, and type suppressions require remediation before release.
|
|
264
|
-
- framework and architecture rules live in \`.scale/frameworks.json\` and module standards docs.
|
|
265
|
-
- \`.scale/frameworks.json > bannedImports\` blocks direct use of deprecated ORMs, unsafe SDKs, or off-system UI components.
|
|
266
|
-
- \`.scale/frameworks.json > lastReviewedAt/reviewIntervalDays\` warns when module framework decisions need review.
|
|
267
|
-
- \`.scale/engineering-standards.json > blockingRules\` promotes selected warning rule IDs to release-blocking findings.
|
|
268
|
-
- \`.scale/engineering-standards.json > allowedFindingPatterns\` allows narrow rule/path/evidence exceptions without hiding unrelated findings in the same file.
|
|
269
|
-
- \`.scale/engineering-standards-baseline.json\` may hold known legacy findings during rollout, but normal task gates should prefer \`--changed\` or \`--changed-files\` so new work is blocked without forcing a whole-repo cleanup.
|
|
270
|
-
- \`.scale/verification.json > policy.engineeringStandardsGate\` controls whether preflight and task verification treat standards as \`off\`, \`warn\`, or \`block\`.
|
|
271
|
-
-
|
|
272
|
-
-
|
|
273
|
-
|
|
274
|
-
|
|
252
|
+
scale workspace status --json
|
|
253
|
+
scale workspace finish --summary
|
|
254
|
+
scale workspace finish --json
|
|
255
|
+
scale workspace cleanup --dir <temporary-worktree> --dry-run --json
|
|
256
|
+
scale workspace cleanup --dir <temporary-worktree> --apply --confirm <branch-or-head> --json
|
|
257
|
+
\`\`\`
|
|
258
|
+
|
|
259
|
+
Do not remove a temporary worktree while any submodule or nested repository has uncommitted or unpushed work. Child repositories must be committed and reviewed in their own remotes, then the root repository can record any required pointer or governance updates. Cleanup defaults to dry-run. Applying cleanup requires the reported confirmation token, normally the temporary branch name.
|
|
260
|
+
|
|
261
|
+
Use \`scale ship <task-id>\` for governed commits. It checks MOE/submodule child repository state before staging reviewed root files, so dirty or unpushed child work cannot be hidden inside a root commit. Raw \`git add .\` is outside the governed path and must not be used for MOE releases.
|
|
262
|
+
|
|
263
|
+
## Resource Governance
|
|
264
|
+
|
|
265
|
+
Use asset scanning before committing generated reports, media, temporary scripts, or long-lived documentation changes:
|
|
266
|
+
|
|
267
|
+
\`\`\`bash
|
|
268
|
+
scale assets scan --json
|
|
269
|
+
scale assets doctor --json
|
|
270
|
+
scale assets settle --task-id <task-id> --artifact-dir docs/worklog/tasks/<task-dir>
|
|
271
|
+
\`\`\`
|
|
272
|
+
|
|
273
|
+
Default policy:
|
|
274
|
+
|
|
275
|
+
- maintained module docs, standards, contracts, ADRs, reusable scripts: commit and keep current.
|
|
276
|
+
- task worklog artifacts: review before commit; promote final truth to maintained docs when useful.
|
|
277
|
+
- screenshots, videos, E2E reports, coverage, temporary scripts, and runtime logs: keep out of Git unless explicitly promoted.
|
|
278
|
+
- large media: use Git LFS or external artifact storage instead of normal Git history.
|
|
279
|
+
|
|
280
|
+
## Engineering Standards
|
|
281
|
+
|
|
282
|
+
Use standards scanning before reviewing or shipping M/L/CRITICAL work:
|
|
283
|
+
|
|
284
|
+
\`\`\`bash
|
|
285
|
+
scale standards scan --json
|
|
286
|
+
scale standards doctor --json
|
|
287
|
+
scale standards doctor --changed --json
|
|
288
|
+
scale standards doctor --changed-files src/example.ts,src/example.test.ts --json
|
|
289
|
+
scale standards baseline --write --artifact-dir docs/worklog/tasks/<task-dir> --task-id <task-id> --json
|
|
290
|
+
scale standards settle --task-id <task-id> --artifact-dir docs/worklog/tasks/<task-dir>
|
|
291
|
+
scale preflight --preflight-profile full --json
|
|
292
|
+
scale verify <task-id> --json
|
|
293
|
+
\`\`\`
|
|
294
|
+
|
|
295
|
+
Default policy:
|
|
296
|
+
|
|
297
|
+
- ad-hoc console/output logging is allowed only for CLI/script paths.
|
|
298
|
+
- sensitive fields such as token, password, secret, authorization, cookie, and credentials must not be logged.
|
|
299
|
+
- hardcoded secret-like assignments are blocked before review or release.
|
|
300
|
+
- SQL must use parameterized queries, ORM bind parameters, or safe query builders.
|
|
301
|
+
- unsafe HTML sinks, dynamic code execution, empty catch blocks, and type suppressions require remediation before release.
|
|
302
|
+
- framework and architecture rules live in \`.scale/frameworks.json\` and module standards docs.
|
|
303
|
+
- \`.scale/frameworks.json > bannedImports\` blocks direct use of deprecated ORMs, unsafe SDKs, or off-system UI components.
|
|
304
|
+
- \`.scale/frameworks.json > lastReviewedAt/reviewIntervalDays\` warns when module framework decisions need review.
|
|
305
|
+
- \`.scale/engineering-standards.json > blockingRules\` promotes selected warning rule IDs to release-blocking findings.
|
|
306
|
+
- \`.scale/engineering-standards.json > allowedFindingPatterns\` allows narrow rule/path/evidence exceptions without hiding unrelated findings in the same file.
|
|
307
|
+
- \`.scale/engineering-standards-baseline.json\` may hold known legacy findings during rollout, but normal task gates should prefer \`--changed\` or \`--changed-files\` so new work is blocked without forcing a whole-repo cleanup.
|
|
308
|
+
- \`.scale/verification.json > policy.engineeringStandardsGate\` controls whether preflight and task verification treat standards as \`off\`, \`warn\`, or \`block\`.
|
|
309
|
+
- \`.scale/product-smoke.json\` defines real product-path probes. Use it to prove a routed user/business flow, not only build, unit tests, or \`/health\`.
|
|
310
|
+
- \`.scale/verification.json > policy.productSmokeGate\` controls whether missing or failed product smoke evidence warns or blocks M/L/CRITICAL delivery.
|
|
311
|
+
- Full standards scans are for release readiness, scheduled remediation, and architecture cleanup. Changed-file scans are the default for day-to-day feature and bug branches.
|
|
312
|
+
- Use \`scale standards baseline --write\` only during an explicit rollout or remediation planning task. It writes the machine-readable baseline and a \`standards-legacy-debt.md\` classification report for staged cleanup.
|
|
313
|
+
|
|
314
|
+
## Automation Templates
|
|
275
315
|
|
|
276
316
|
Optional automation templates are generated under \`docs/workflow/templates/\`:
|
|
277
317
|
|
|
@@ -370,23 +410,23 @@ function skillPlanTemplate() {
|
|
|
370
410
|
|
|
371
411
|
- TBD
|
|
372
412
|
|
|
373
|
-
## Required Verification Evidence
|
|
374
|
-
|
|
375
|
-
- TBD
|
|
376
|
-
|
|
377
|
-
## Tool Orchestration
|
|
378
|
-
|
|
379
|
-
| Capability | Primary Tool Or Skill | Fallback | Required Evidence |
|
|
380
|
-
| --- | --- | --- | --- |
|
|
381
|
-
| UI/UX design | frontend-design, ui-ux-pro-max | awesome-design-md | design-system, ui-spec.md, visual-review.md |
|
|
382
|
-
| Web research or logged-in pages | web-access | agent-browser, Chrome DevTools MCP | source citations, browser evidence |
|
|
383
|
-
| Browser E2E | webapp-testing, Playwright | agent-browser, web-access | screenshot, console, network evidence |
|
|
384
|
-
| Desktop GUI automation | CUA/computer-use | manual verification | desktop screenshot, operator-safety notes |
|
|
385
|
-
| External agent CLI | codex/gemini/opencode CLI | manual review | version check, exact command output |
|
|
386
|
-
|
|
387
|
-
## Skipped Skills
|
|
388
|
-
|
|
389
|
-
| Skill | Reason | Fallback Evidence |
|
|
413
|
+
## Required Verification Evidence
|
|
414
|
+
|
|
415
|
+
- TBD
|
|
416
|
+
|
|
417
|
+
## Tool Orchestration
|
|
418
|
+
|
|
419
|
+
| Capability | Primary Tool Or Skill | Fallback | Required Evidence |
|
|
420
|
+
| --- | --- | --- | --- |
|
|
421
|
+
| UI/UX design | frontend-design, ui-ux-pro-max | awesome-design-md | design-system, ui-spec.md, visual-review.md |
|
|
422
|
+
| Web research or logged-in pages | web-access | agent-browser, Chrome DevTools MCP | source citations, browser evidence |
|
|
423
|
+
| Browser E2E | webapp-testing, Playwright | agent-browser, web-access | screenshot, console, network evidence |
|
|
424
|
+
| Desktop GUI automation | CUA/computer-use | manual verification | desktop screenshot, operator-safety notes |
|
|
425
|
+
| External agent CLI | codex/gemini/opencode CLI | manual review | version check, exact command output |
|
|
426
|
+
|
|
427
|
+
## Skipped Skills
|
|
428
|
+
|
|
429
|
+
| Skill | Reason | Fallback Evidence |
|
|
390
430
|
| --- | --- | --- |
|
|
391
431
|
| | | |
|
|
392
432
|
`;
|
|
@@ -394,34 +434,34 @@ function skillPlanTemplate() {
|
|
|
394
434
|
function skillEvidenceTemplate() {
|
|
395
435
|
return `# Skill Evidence
|
|
396
436
|
|
|
397
|
-
## Planned Skills
|
|
398
|
-
|
|
399
|
-
- TBD
|
|
400
|
-
|
|
401
|
-
## Tool Selection Rationale
|
|
402
|
-
|
|
403
|
-
TBD
|
|
404
|
-
|
|
405
|
-
## Used Skills
|
|
406
|
-
|
|
407
|
-
| Skill | Phase | Trigger | Evidence | Status |
|
|
408
|
-
| --- | --- | --- | --- | --- |
|
|
409
|
-
| skill-id | plan/build/verify/review | why it was selected | command, screenshot, report, or artifact path | executed/skipped/fallback |
|
|
410
|
-
|
|
411
|
-
## Browser Or Web Evidence
|
|
412
|
-
|
|
413
|
-
| Tool | Target | Evidence | Result |
|
|
414
|
-
| --- | --- | --- | --- |
|
|
415
|
-
| web-access/agent-browser/Chrome DevTools MCP | URL or local target | screenshot, console log, network finding, source URL | passed/failed/skipped |
|
|
416
|
-
|
|
417
|
-
## Desktop Or External CLI Evidence
|
|
418
|
-
|
|
419
|
-
| Tool | Scope | Safety Boundary | Evidence | Result |
|
|
420
|
-
| --- | --- | --- | --- | --- |
|
|
421
|
-
| cua/codex/gemini/opencode/wps/wechat | command or app target | read-only/dry-run/test account/manual approval | output summary, screenshot, or report path | passed/failed/skipped |
|
|
422
|
-
|
|
423
|
-
## Skipped Skills
|
|
424
|
-
|
|
437
|
+
## Planned Skills
|
|
438
|
+
|
|
439
|
+
- TBD
|
|
440
|
+
|
|
441
|
+
## Tool Selection Rationale
|
|
442
|
+
|
|
443
|
+
TBD
|
|
444
|
+
|
|
445
|
+
## Used Skills
|
|
446
|
+
|
|
447
|
+
| Skill | Phase | Trigger | Evidence | Status |
|
|
448
|
+
| --- | --- | --- | --- | --- |
|
|
449
|
+
| skill-id | plan/build/verify/review | why it was selected | command, screenshot, report, or artifact path | executed/skipped/fallback |
|
|
450
|
+
|
|
451
|
+
## Browser Or Web Evidence
|
|
452
|
+
|
|
453
|
+
| Tool | Target | Evidence | Result |
|
|
454
|
+
| --- | --- | --- | --- |
|
|
455
|
+
| web-access/agent-browser/Chrome DevTools MCP | URL or local target | screenshot, console log, network finding, source URL | passed/failed/skipped |
|
|
456
|
+
|
|
457
|
+
## Desktop Or External CLI Evidence
|
|
458
|
+
|
|
459
|
+
| Tool | Scope | Safety Boundary | Evidence | Result |
|
|
460
|
+
| --- | --- | --- | --- | --- |
|
|
461
|
+
| cua/codex/gemini/opencode/wps/wechat | command or app target | read-only/dry-run/test account/manual approval | output summary, screenshot, or report path | passed/failed/skipped |
|
|
462
|
+
|
|
463
|
+
## Skipped Skills
|
|
464
|
+
|
|
425
465
|
| Skill | Reason | Fallback Evidence |
|
|
426
466
|
| --- | --- | --- |
|
|
427
467
|
| skill-id | why it could not run | manual review, alternate command, or explicit risk |
|
|
@@ -542,88 +582,88 @@ function toolModeFromGovernanceMode(mode) {
|
|
|
542
582
|
return 'evidence-required';
|
|
543
583
|
}
|
|
544
584
|
function resourceImpactTemplate() {
|
|
545
|
-
return `# Resource Impact
|
|
546
|
-
|
|
547
|
-
## Resources Created
|
|
548
|
-
|
|
549
|
-
| Path | Type | Git Policy | Retention |
|
|
550
|
-
| --- | --- | --- | --- |
|
|
551
|
-
| TBD | canonical-doc/task-artifact/evidence-report/temporary/reusable-script/generated-media/contract/decision-record | commit/ignore/lfs/external/review | TBD |
|
|
552
|
-
|
|
553
|
-
## Resources Updated
|
|
554
|
-
|
|
555
|
-
- TBD
|
|
556
|
-
|
|
557
|
-
## Resources Promoted To Maintained Docs
|
|
558
|
-
|
|
559
|
-
- TBD
|
|
560
|
-
|
|
561
|
-
## Resources To Delete Or Archive Before Finish
|
|
562
|
-
|
|
563
|
-
- TBD
|
|
564
|
-
|
|
565
|
-
## Source Of Truth Updates
|
|
566
|
-
|
|
567
|
-
- [ ] .scale/resource-policy.json
|
|
568
|
-
- [ ] .scale/assets.json
|
|
569
|
-
- [ ] docs/modules/<module>/README.md
|
|
585
|
+
return `# Resource Impact
|
|
586
|
+
|
|
587
|
+
## Resources Created
|
|
588
|
+
|
|
589
|
+
| Path | Type | Git Policy | Retention |
|
|
590
|
+
| --- | --- | --- | --- |
|
|
591
|
+
| TBD | canonical-doc/task-artifact/evidence-report/temporary/reusable-script/generated-media/contract/decision-record | commit/ignore/lfs/external/review | TBD |
|
|
592
|
+
|
|
593
|
+
## Resources Updated
|
|
594
|
+
|
|
595
|
+
- TBD
|
|
596
|
+
|
|
597
|
+
## Resources Promoted To Maintained Docs
|
|
598
|
+
|
|
599
|
+
- TBD
|
|
600
|
+
|
|
601
|
+
## Resources To Delete Or Archive Before Finish
|
|
602
|
+
|
|
603
|
+
- TBD
|
|
604
|
+
|
|
605
|
+
## Source Of Truth Updates
|
|
606
|
+
|
|
607
|
+
- [ ] .scale/resource-policy.json
|
|
608
|
+
- [ ] .scale/assets.json
|
|
609
|
+
- [ ] docs/modules/<module>/README.md
|
|
570
610
|
`;
|
|
571
611
|
}
|
|
572
612
|
function standardsImpactTemplate() {
|
|
573
|
-
return `# Standards Impact
|
|
574
|
-
|
|
575
|
-
## Standards Checked
|
|
576
|
-
|
|
577
|
-
- [ ] Logging and redaction
|
|
578
|
-
- [ ] Architecture boundaries
|
|
579
|
-
- [ ] ORM/database access
|
|
580
|
-
- [ ] Framework/component conventions
|
|
581
|
-
- [ ] UI/UX acceptance where user-facing
|
|
582
|
-
- [ ] Test and verification rigor
|
|
583
|
-
- [ ] Security-sensitive inputs and outputs
|
|
584
|
-
|
|
585
|
-
## Findings
|
|
586
|
-
|
|
587
|
-
| Severity | Rule | Path | Decision |
|
|
588
|
-
| --- | --- | --- | --- |
|
|
589
|
-
| TBD | TBD | TBD | fix/accept/escalate |
|
|
590
|
-
|
|
591
|
-
## Policy Updates
|
|
592
|
-
|
|
593
|
-
- [ ] .scale/engineering-standards.json
|
|
594
|
-
- [ ] .scale/frameworks.json
|
|
595
|
-
- [ ] docs/standards/
|
|
596
|
-
|
|
597
|
-
## Settlement
|
|
598
|
-
|
|
599
|
-
- Standards scan:
|
|
600
|
-
- Standards doctor:
|
|
613
|
+
return `# Standards Impact
|
|
614
|
+
|
|
615
|
+
## Standards Checked
|
|
616
|
+
|
|
617
|
+
- [ ] Logging and redaction
|
|
618
|
+
- [ ] Architecture boundaries
|
|
619
|
+
- [ ] ORM/database access
|
|
620
|
+
- [ ] Framework/component conventions
|
|
621
|
+
- [ ] UI/UX acceptance where user-facing
|
|
622
|
+
- [ ] Test and verification rigor
|
|
623
|
+
- [ ] Security-sensitive inputs and outputs
|
|
624
|
+
|
|
625
|
+
## Findings
|
|
626
|
+
|
|
627
|
+
| Severity | Rule | Path | Decision |
|
|
628
|
+
| --- | --- | --- | --- |
|
|
629
|
+
| TBD | TBD | TBD | fix/accept/escalate |
|
|
630
|
+
|
|
631
|
+
## Policy Updates
|
|
632
|
+
|
|
633
|
+
- [ ] .scale/engineering-standards.json
|
|
634
|
+
- [ ] .scale/frameworks.json
|
|
635
|
+
- [ ] docs/standards/
|
|
636
|
+
|
|
637
|
+
## Settlement
|
|
638
|
+
|
|
639
|
+
- Standards scan:
|
|
640
|
+
- Standards doctor:
|
|
601
641
|
`;
|
|
602
642
|
}
|
|
603
643
|
function architectureReviewTemplate() {
|
|
604
|
-
return `# Architecture Review
|
|
605
|
-
|
|
606
|
-
## Scope
|
|
607
|
-
|
|
608
|
-
- Modules touched:
|
|
609
|
-
- Public contracts touched:
|
|
610
|
-
- Data flow touched:
|
|
611
|
-
|
|
612
|
-
## Boundary Checks
|
|
613
|
-
|
|
614
|
-
- [ ] API/controller layer does not bypass service/usecase layer
|
|
615
|
-
- [ ] Domain layer is not coupled to infrastructure details
|
|
616
|
-
- [ ] Repository/ORM usage follows project conventions
|
|
617
|
-
- [ ] Shared framework components are reused instead of duplicated
|
|
618
|
-
- [ ] New abstractions remove real complexity
|
|
619
|
-
|
|
620
|
-
## Risks
|
|
621
|
-
|
|
622
|
-
- TBD
|
|
623
|
-
|
|
624
|
-
## Decision
|
|
625
|
-
|
|
626
|
-
- Approved/changes required:
|
|
644
|
+
return `# Architecture Review
|
|
645
|
+
|
|
646
|
+
## Scope
|
|
647
|
+
|
|
648
|
+
- Modules touched:
|
|
649
|
+
- Public contracts touched:
|
|
650
|
+
- Data flow touched:
|
|
651
|
+
|
|
652
|
+
## Boundary Checks
|
|
653
|
+
|
|
654
|
+
- [ ] API/controller layer does not bypass service/usecase layer
|
|
655
|
+
- [ ] Domain layer is not coupled to infrastructure details
|
|
656
|
+
- [ ] Repository/ORM usage follows project conventions
|
|
657
|
+
- [ ] Shared framework components are reused instead of duplicated
|
|
658
|
+
- [ ] New abstractions remove real complexity
|
|
659
|
+
|
|
660
|
+
## Risks
|
|
661
|
+
|
|
662
|
+
- TBD
|
|
663
|
+
|
|
664
|
+
## Decision
|
|
665
|
+
|
|
666
|
+
- Approved/changes required:
|
|
627
667
|
`;
|
|
628
668
|
}
|
|
629
669
|
function securityReviewTemplate() {
|
|
@@ -701,6 +741,70 @@ TBD
|
|
|
701
741
|
TBD
|
|
702
742
|
`;
|
|
703
743
|
}
|
|
744
|
+
function productSmokeTemplate() {
|
|
745
|
+
return `# Product Smoke
|
|
746
|
+
|
|
747
|
+
## Real Product Path
|
|
748
|
+
|
|
749
|
+
Describe the smallest end-to-end path that proves the change works through the real product boundary.
|
|
750
|
+
|
|
751
|
+
Example:
|
|
752
|
+
|
|
753
|
+
\`\`\`text
|
|
754
|
+
UI or client -> gateway/router -> service -> database/storage/queue -> observable result
|
|
755
|
+
\`\`\`
|
|
756
|
+
|
|
757
|
+
Do not use a green health endpoint as the only proof when the user-facing path depends on routing, authentication, storage, async tasks, browser behavior, or third-party integration.
|
|
758
|
+
|
|
759
|
+
## Quick Setup
|
|
760
|
+
|
|
761
|
+
1. Open \`.scale/product-smoke.json\`.
|
|
762
|
+
2. Replace the example command with one real product path command.
|
|
763
|
+
3. Set that probe's \`enabled\` field to \`true\`.
|
|
764
|
+
4. Run \`scale preflight --profile productSmoke --json\`.
|
|
765
|
+
5. Run \`scale runtime final-check --level M --json\`.
|
|
766
|
+
|
|
767
|
+
\`status: "skipped"\` means no real product path was exercised. It does not count as completion evidence.
|
|
768
|
+
|
|
769
|
+
## Setup
|
|
770
|
+
|
|
771
|
+
- Base URL:
|
|
772
|
+
- Test user or tenant:
|
|
773
|
+
- Required fixtures:
|
|
774
|
+
- Services that must be running:
|
|
775
|
+
|
|
776
|
+
## Smoke Commands
|
|
777
|
+
|
|
778
|
+
| Command | Expected Result | Evidence Artifact |
|
|
779
|
+
| --- | --- | --- |
|
|
780
|
+
| TBD | TBD | TBD |
|
|
781
|
+
|
|
782
|
+
## Runtime Evidence
|
|
783
|
+
|
|
784
|
+
Record at least one runtime evidence item:
|
|
785
|
+
|
|
786
|
+
\`\`\`bash
|
|
787
|
+
scale runtime record \\
|
|
788
|
+
--kind command \\
|
|
789
|
+
--title "Product smoke: <flow>" \\
|
|
790
|
+
--status passed \\
|
|
791
|
+
--command "<exact smoke command>" \\
|
|
792
|
+
--exit-code 0 \\
|
|
793
|
+
--summary "<business result, task id, status, or observable output>" \\
|
|
794
|
+
--artifacts ".agent/logs/<service>/<smoke>.json" \\
|
|
795
|
+
--metadata-json '{"productSmoke":true,"realProductPath":true}'
|
|
796
|
+
\`\`\`
|
|
797
|
+
|
|
798
|
+
## Assertions
|
|
799
|
+
|
|
800
|
+
- [ ] Request crossed the real product boundary, not only an isolated unit.
|
|
801
|
+
- [ ] Authentication or user identity path was exercised when relevant.
|
|
802
|
+
- [ ] Persistence/storage/queue side effect was verified when relevant.
|
|
803
|
+
- [ ] Async task or eventual state was polled to terminal status when relevant.
|
|
804
|
+
- [ ] Failure output is specific enough to diagnose the failing layer.
|
|
805
|
+
- [ ] Runtime artifacts are ignored or deliberately promoted according to resource governance.
|
|
806
|
+
`;
|
|
807
|
+
}
|
|
704
808
|
function planTemplate() {
|
|
705
809
|
return `# Plan
|
|
706
810
|
|
|
@@ -828,6 +932,12 @@ function verificationMatrixTemplate(mode, options = {}) {
|
|
|
828
932
|
commands: {},
|
|
829
933
|
services: options.services?.filter(service => service.required !== false).map(service => service.name) ?? [],
|
|
830
934
|
},
|
|
935
|
+
productSmoke: {
|
|
936
|
+
commands: {
|
|
937
|
+
smoke: 'powershell -ExecutionPolicy Bypass -File scripts/qa/product-smoke.ps1',
|
|
938
|
+
},
|
|
939
|
+
services: options.services?.filter(service => service.required !== false).map(service => service.name) ?? [],
|
|
940
|
+
},
|
|
831
941
|
},
|
|
832
942
|
services: options.services ?? [],
|
|
833
943
|
exclude: options.exclude ?? ['node_modules', 'dist', 'tmp', 'vendor'],
|
|
@@ -837,9 +947,170 @@ function verificationMatrixTemplate(mode, options = {}) {
|
|
|
837
947
|
artifactGate: options.artifactGate ?? (mode === 'critical' ? 'block' : 'warn'),
|
|
838
948
|
artifactGateLevels: ['M', 'L', 'CRITICAL'],
|
|
839
949
|
engineeringStandardsGate: mode === 'minimal' ? 'warn' : 'block',
|
|
950
|
+
productSmokeGate: mode === 'critical' ? 'block' : 'warn',
|
|
951
|
+
},
|
|
952
|
+
}, null, 2) + '\n';
|
|
953
|
+
}
|
|
954
|
+
function productSmokeConfigTemplate(mode) {
|
|
955
|
+
return JSON.stringify({
|
|
956
|
+
version: 1,
|
|
957
|
+
gate: mode === 'critical' ? 'block' : 'warn',
|
|
958
|
+
requiredForLevels: ['M', 'L', 'CRITICAL'],
|
|
959
|
+
emptyProbeBehavior: 'block',
|
|
960
|
+
setupGuide: [
|
|
961
|
+
'Set probes[].enabled=true only after replacing the example command with a real product path.',
|
|
962
|
+
'Use a command that crosses the real boundary: client/UI -> gateway/router -> service -> persistence or observable result.',
|
|
963
|
+
'Run: scale preflight --profile productSmoke --json',
|
|
964
|
+
'Run: scale runtime final-check --level M --json',
|
|
965
|
+
],
|
|
966
|
+
runtimeEvidence: {
|
|
967
|
+
requiredKind: 'command',
|
|
968
|
+
requiredStatus: 'passed',
|
|
969
|
+
requireArtifacts: true,
|
|
840
970
|
},
|
|
971
|
+
probes: [
|
|
972
|
+
{
|
|
973
|
+
id: 'example-business-flow',
|
|
974
|
+
enabled: false,
|
|
975
|
+
description: 'Replace with a real user/product path such as UI -> gateway -> service -> database/storage.',
|
|
976
|
+
command: 'curl -fsS http://127.0.0.1:3000/health',
|
|
977
|
+
expected: {
|
|
978
|
+
exitCode: 0,
|
|
979
|
+
evidenceArtifact: '.agent/logs/product-smoke.json',
|
|
980
|
+
},
|
|
981
|
+
},
|
|
982
|
+
],
|
|
841
983
|
}, null, 2) + '\n';
|
|
842
984
|
}
|
|
985
|
+
function productSmokePowerShellScript() {
|
|
986
|
+
return `# Product smoke probe runner generated by scale-engine.
|
|
987
|
+
$ErrorActionPreference = "Stop"
|
|
988
|
+
|
|
989
|
+
$Root = (Resolve-Path (Join-Path $PSScriptRoot "..\\..")).Path
|
|
990
|
+
$ConfigPath = Join-Path $Root ".scale\\product-smoke.json"
|
|
991
|
+
$LogDir = Join-Path $Root ".agent\\logs"
|
|
992
|
+
$LogPath = Join-Path $LogDir "product-smoke.json"
|
|
993
|
+
|
|
994
|
+
New-Item -ItemType Directory -Force -Path $LogDir | Out-Null
|
|
995
|
+
|
|
996
|
+
$NodeProgram = @'
|
|
997
|
+
${productSmokeNodeProgram()}
|
|
998
|
+
'@
|
|
999
|
+
|
|
1000
|
+
$TempFile = [System.IO.Path]::GetTempFileName() + ".js"
|
|
1001
|
+
Set-Content -Path $TempFile -Value $NodeProgram -Encoding UTF8
|
|
1002
|
+
try {
|
|
1003
|
+
node $TempFile $ConfigPath $LogPath
|
|
1004
|
+
exit $LASTEXITCODE
|
|
1005
|
+
} finally {
|
|
1006
|
+
Remove-Item -Force $TempFile -ErrorAction SilentlyContinue
|
|
1007
|
+
}
|
|
1008
|
+
`;
|
|
1009
|
+
}
|
|
1010
|
+
function productSmokeShellScript() {
|
|
1011
|
+
return `#!/usr/bin/env sh
|
|
1012
|
+
set -eu
|
|
1013
|
+
|
|
1014
|
+
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
1015
|
+
CONFIG_PATH="$ROOT/.scale/product-smoke.json"
|
|
1016
|
+
LOG_DIR="$ROOT/.agent/logs"
|
|
1017
|
+
LOG_PATH="$LOG_DIR/product-smoke.json"
|
|
1018
|
+
|
|
1019
|
+
mkdir -p "$LOG_DIR"
|
|
1020
|
+
|
|
1021
|
+
node - "$CONFIG_PATH" "$LOG_PATH" <<'NODE'
|
|
1022
|
+
${productSmokeNodeProgram()}
|
|
1023
|
+
NODE
|
|
1024
|
+
`;
|
|
1025
|
+
}
|
|
1026
|
+
function productSmokeNodeProgram() {
|
|
1027
|
+
return `const fs = require('fs');
|
|
1028
|
+
const cp = require('child_process');
|
|
1029
|
+
const path = require('path');
|
|
1030
|
+
|
|
1031
|
+
const configPath = process.argv[2];
|
|
1032
|
+
const logPath = process.argv[3];
|
|
1033
|
+
|
|
1034
|
+
function writeReport(report) {
|
|
1035
|
+
fs.mkdirSync(path.dirname(logPath), { recursive: true });
|
|
1036
|
+
fs.writeFileSync(logPath, JSON.stringify(report, null, 2) + '\\n', 'utf8');
|
|
1037
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\\n');
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
if (!fs.existsSync(configPath)) {
|
|
1041
|
+
writeReport({
|
|
1042
|
+
version: 1,
|
|
1043
|
+
status: 'failed',
|
|
1044
|
+
verifiedAt: new Date().toISOString(),
|
|
1045
|
+
message: 'Missing .scale/product-smoke.json',
|
|
1046
|
+
results: []
|
|
1047
|
+
});
|
|
1048
|
+
process.exit(1);
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8').replace(/^\\uFEFF/, ''));
|
|
1052
|
+
const probes = Array.isArray(config.probes) ? config.probes.filter(probe => probe && probe.enabled === true) : [];
|
|
1053
|
+
|
|
1054
|
+
if (probes.length === 0) {
|
|
1055
|
+
const status = config.emptyProbeBehavior === 'block' ? 'failed' : 'skipped';
|
|
1056
|
+
writeReport({
|
|
1057
|
+
version: 1,
|
|
1058
|
+
status,
|
|
1059
|
+
verifiedAt: new Date().toISOString(),
|
|
1060
|
+
message: 'No enabled product smoke probes. Enable probes in .scale/product-smoke.json after defining the real product path.',
|
|
1061
|
+
results: []
|
|
1062
|
+
});
|
|
1063
|
+
process.exit(status === 'failed' ? 1 : 0);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
const results = probes.map((probe) => {
|
|
1067
|
+
const startedAt = new Date().toISOString();
|
|
1068
|
+
const expectedExitCode = Number.isInteger(probe.expected && probe.expected.exitCode) ? probe.expected.exitCode : 0;
|
|
1069
|
+
const command = String(probe.command || '');
|
|
1070
|
+
if (!command.trim()) {
|
|
1071
|
+
return {
|
|
1072
|
+
id: String(probe.id || 'unnamed-probe'),
|
|
1073
|
+
description: String(probe.description || ''),
|
|
1074
|
+
command,
|
|
1075
|
+
expectedExitCode,
|
|
1076
|
+
exitCode: 1,
|
|
1077
|
+
status: 'failed',
|
|
1078
|
+
startedAt,
|
|
1079
|
+
endedAt: new Date().toISOString(),
|
|
1080
|
+
outputTail: 'Probe command is empty'
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
const result = cp.spawnSync(command, {
|
|
1084
|
+
cwd: process.cwd(),
|
|
1085
|
+
shell: true,
|
|
1086
|
+
encoding: 'utf8',
|
|
1087
|
+
timeout: Number(config.timeoutMs || 180000)
|
|
1088
|
+
});
|
|
1089
|
+
const output = String(result.stdout || '') + String(result.stderr || '') + String(result.error ? result.error.message : '');
|
|
1090
|
+
const exitCode = typeof result.status === 'number' ? result.status : 1;
|
|
1091
|
+
return {
|
|
1092
|
+
id: String(probe.id || 'unnamed-probe'),
|
|
1093
|
+
description: String(probe.description || ''),
|
|
1094
|
+
command,
|
|
1095
|
+
expectedExitCode,
|
|
1096
|
+
exitCode,
|
|
1097
|
+
status: exitCode === expectedExitCode ? 'passed' : 'failed',
|
|
1098
|
+
startedAt,
|
|
1099
|
+
endedAt: new Date().toISOString(),
|
|
1100
|
+
outputTail: output.length > 2000 ? output.slice(-2000) : output
|
|
1101
|
+
};
|
|
1102
|
+
});
|
|
1103
|
+
|
|
1104
|
+
const failed = results.filter(result => result.status !== 'passed');
|
|
1105
|
+
writeReport({
|
|
1106
|
+
version: 1,
|
|
1107
|
+
status: failed.length === 0 ? 'passed' : 'failed',
|
|
1108
|
+
verifiedAt: new Date().toISOString(),
|
|
1109
|
+
results
|
|
1110
|
+
});
|
|
1111
|
+
process.exit(failed.length === 0 ? 0 : 1);
|
|
1112
|
+
`;
|
|
1113
|
+
}
|
|
843
1114
|
function packageVersion() {
|
|
844
1115
|
try {
|
|
845
1116
|
const pkg = JSON.parse(readFileSync(join(process.cwd(), 'package.json'), 'utf-8'));
|