@hongmaple0820/scale-engine 0.17.0 → 0.19.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.
Files changed (94) hide show
  1. package/README.en.md +296 -237
  2. package/README.md +157 -63
  3. package/dist/api/cli.js +661 -33
  4. package/dist/api/cli.js.map +1 -1
  5. package/dist/api/doctor.d.ts +5 -1
  6. package/dist/api/doctor.js +130 -1
  7. package/dist/api/doctor.js.map +1 -1
  8. package/dist/api/quickstart.d.ts +3 -0
  9. package/dist/api/quickstart.js +12 -4
  10. package/dist/api/quickstart.js.map +1 -1
  11. package/dist/cli/phaseCommands.js +7 -0
  12. package/dist/cli/phaseCommands.js.map +1 -1
  13. package/dist/core/logger.js +1 -1
  14. package/dist/index.d.ts +2 -0
  15. package/dist/index.js +4 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/memory/MemoryFabric.d.ts +118 -0
  18. package/dist/memory/MemoryFabric.js +281 -0
  19. package/dist/memory/MemoryFabric.js.map +1 -0
  20. package/dist/memory/MemoryLearning.d.ts +61 -0
  21. package/dist/memory/MemoryLearning.js +203 -0
  22. package/dist/memory/MemoryLearning.js.map +1 -0
  23. package/dist/memory/index.d.ts +2 -0
  24. package/dist/memory/index.js +3 -0
  25. package/dist/memory/index.js.map +1 -0
  26. package/dist/output/HTMLArtifactLayer.d.ts +97 -0
  27. package/dist/output/HTMLArtifactLayer.js +576 -0
  28. package/dist/output/HTMLArtifactLayer.js.map +1 -0
  29. package/dist/output/index.d.ts +2 -0
  30. package/dist/output/index.js +1 -0
  31. package/dist/output/index.js.map +1 -1
  32. package/dist/prompts/VibeTemplateGallery.js +121 -121
  33. package/dist/runtime/FinalReportGuard.d.ts +16 -0
  34. package/dist/runtime/FinalReportGuard.js +14 -0
  35. package/dist/runtime/FinalReportGuard.js.map +1 -0
  36. package/dist/runtime/RuntimeDoctor.d.ts +23 -0
  37. package/dist/runtime/RuntimeDoctor.js +151 -0
  38. package/dist/runtime/RuntimeDoctor.js.map +1 -0
  39. package/dist/runtime/RuntimeEvidenceLedger.d.ts +50 -0
  40. package/dist/runtime/RuntimeEvidenceLedger.js +89 -0
  41. package/dist/runtime/RuntimeEvidenceLedger.js.map +1 -0
  42. package/dist/runtime/SessionLedger.d.ts +53 -0
  43. package/dist/runtime/SessionLedger.js +104 -0
  44. package/dist/runtime/SessionLedger.js.map +1 -0
  45. package/dist/runtime/index.d.ts +4 -0
  46. package/dist/runtime/index.js +5 -0
  47. package/dist/runtime/index.js.map +1 -0
  48. package/dist/skills/routing/SkillGate.js +26 -2
  49. package/dist/skills/routing/SkillGate.js.map +1 -1
  50. package/dist/skills/routing/SkillPolicy.js +2 -2
  51. package/dist/skills/routing/SkillPolicy.js.map +1 -1
  52. package/dist/tools/ToolCapabilityRegistry.d.ts +1 -1
  53. package/dist/tools/ToolCapabilityRegistry.js +4 -4
  54. package/dist/tools/ToolCapabilityRegistry.js.map +1 -1
  55. package/dist/tools/ToolOrchestrator.js +5 -1
  56. package/dist/tools/ToolOrchestrator.js.map +1 -1
  57. package/dist/workflow/EngineeringStandards.js +69 -66
  58. package/dist/workflow/EngineeringStandards.js.map +1 -1
  59. package/dist/workflow/GovernanceTemplatePacks.d.ts +1 -1
  60. package/dist/workflow/GovernanceTemplatePacks.js +137 -79
  61. package/dist/workflow/GovernanceTemplatePacks.js.map +1 -1
  62. package/dist/workflow/GovernanceTemplates.d.ts +1 -1
  63. package/dist/workflow/GovernanceTemplates.js +494 -199
  64. package/dist/workflow/GovernanceTemplates.js.map +1 -1
  65. package/dist/workflow/ResourceGovernance.js +29 -19
  66. package/dist/workflow/ResourceGovernance.js.map +1 -1
  67. package/dist/workflow/VerificationCommands.d.ts +11 -0
  68. package/dist/workflow/VerificationCommands.js +2 -0
  69. package/dist/workflow/VerificationCommands.js.map +1 -1
  70. package/dist/workflow/VerificationProfile.d.ts +2 -1
  71. package/dist/workflow/VerificationProfile.js +3 -0
  72. package/dist/workflow/VerificationProfile.js.map +1 -1
  73. package/dist/workflow/WorkflowArtifactWriter.js +2 -1
  74. package/dist/workflow/WorkflowArtifactWriter.js.map +1 -1
  75. package/dist/workflow/WorkflowEngine.js +4 -1
  76. package/dist/workflow/WorkflowEngine.js.map +1 -1
  77. package/dist/workflow/WorkspaceSafety.d.ts +9 -0
  78. package/dist/workflow/WorkspaceSafety.js +49 -0
  79. package/dist/workflow/WorkspaceSafety.js.map +1 -0
  80. package/dist/workflow/gates/GateSystem.d.ts +12 -1
  81. package/dist/workflow/gates/GateSystem.js +106 -0
  82. package/dist/workflow/gates/GateSystem.js.map +1 -1
  83. package/dist/workflow/types.d.ts +1 -1
  84. package/docs/MEMORY_FABRIC.md +107 -0
  85. package/docs/README.md +68 -0
  86. package/docs/RUNTIME_EVIDENCE.md +101 -0
  87. package/docs/start/README.md +42 -0
  88. package/docs/start/agent-governance-demo.md +107 -0
  89. package/docs/start/quickstart.md +127 -0
  90. package/examples/demo-projects/agent-governance-demo/README.md +37 -0
  91. package/examples/demo-projects/agent-governance-demo/package.json +16 -0
  92. package/examples/demo-projects/agent-governance-demo/src/oauth-state.ts +39 -0
  93. package/examples/demo-projects/agent-governance-demo/tests/oauth-state.test.ts +52 -0
  94. package/package.json +8 -3
@@ -1,16 +1,18 @@
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';
6
6
  import { engineeringStandardsBaselineTemplate, engineeringStandardsPolicyTemplate, frameworksCatalogTemplate, } from './EngineeringStandards.js';
7
7
  import { resourceManifestTemplate, resourcePolicyTemplate } from './ResourceGovernance.js';
8
+ import { toolPolicyTemplate } from '../tools/ToolPolicy.js';
9
+ import { outputPolicyTemplate } from '../output/HTMLArtifactLayer.js';
8
10
  export function writeGovernanceTemplates(projectDir = process.cwd(), options = {}) {
9
11
  const mode = options.mode ?? 'standard';
10
12
  const projectName = options.projectName ?? 'Project';
11
13
  const pack = resolveGovernanceTemplatePack(options.pack);
12
14
  const packMode = pack.modeDefaults[mode];
13
- const services = options.services ?? pack.defaultServices ?? [];
15
+ const services = options.services ?? pack.defaultServices ?? detectRootServices(projectDir, pack.id);
14
16
  const exclude = options.exclude ?? pack.exclude ?? ['node_modules', 'dist', 'tmp', 'vendor'];
15
17
  const result = { created: [], skipped: [] };
16
18
  const lockFiles = new Map();
@@ -32,6 +34,7 @@ export function writeGovernanceTemplates(projectDir = process.cwd(), options = {
32
34
  writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/security-review.md', governanceTemplateContent('security-review.md'));
33
35
  writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/db-change-plan.md', governanceTemplateContent('db-change-plan.md'));
34
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'));
35
38
  writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/plan.md', governanceTemplateContent('plan.md'));
36
39
  writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/verification.md', governanceTemplateContent('verification.md'));
37
40
  writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/review.md', governanceTemplateContent('review.md'));
@@ -39,14 +42,19 @@ export function writeGovernanceTemplates(projectDir = process.cwd(), options = {
39
42
  writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/github-actions-scale-preflight.yml', githubActionsPreflightTemplate());
40
43
  writeTracked(result, lockFiles, projectDir, 'docs/workflow/templates/pre-push-scale-preflight.sh', prePushPreflightTemplate());
41
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());
42
47
  writeTracked(result, lockFiles, projectDir, '.scale/verification.json', verificationMatrixTemplate(mode, {
43
48
  services,
44
49
  exclude,
45
50
  artifactGate: packMode.artifactGate,
46
51
  }));
47
52
  writeTracked(result, lockFiles, projectDir, '.scale/skills.json', skillRoutingPolicyTemplate(mode));
53
+ writeTracked(result, lockFiles, projectDir, '.scale/tools.json', toolPolicyTemplate(toolModeFromGovernanceMode(mode)));
48
54
  writeTracked(result, lockFiles, projectDir, '.scale/resource-policy.json', resourcePolicyTemplate());
49
55
  writeTracked(result, lockFiles, projectDir, '.scale/assets.json', resourceManifestTemplate());
56
+ writeTracked(result, lockFiles, projectDir, '.scale/output-policy.json', outputPolicyTemplate());
57
+ writeTracked(result, lockFiles, projectDir, '.scale/product-smoke.json', productSmokeConfigTemplate(mode));
50
58
  writeTracked(result, lockFiles, projectDir, '.scale/engineering-standards.json', engineeringStandardsPolicyTemplate());
51
59
  writeTracked(result, lockFiles, projectDir, '.scale/engineering-standards-baseline.json', engineeringStandardsBaselineTemplate());
52
60
  writeTracked(result, lockFiles, projectDir, '.scale/frameworks.json', frameworksCatalogTemplate());
@@ -79,6 +87,7 @@ export function governanceTemplateContent(name) {
79
87
  case 'security-review.md': return securityReviewTemplate();
80
88
  case 'db-change-plan.md': return dbChangePlanTemplate();
81
89
  case 'e2e-plan.md': return e2ePlanTemplate();
90
+ case 'product-smoke.md': return productSmokeTemplate();
82
91
  case 'plan.md': return planTemplate();
83
92
  case 'verification.md': return verificationTemplate();
84
93
  case 'review.md': return reviewTemplate();
@@ -110,6 +119,38 @@ function writePackGeneratedFile(result, lockFiles, projectDir, packId, packVersi
110
119
  if (created)
111
120
  lockFiles.set(file.path, { path: file.path, owned: file.owned });
112
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
+ }
113
154
  function shouldUseGeneratedHeader(file) {
114
155
  return file.kind === 'doc' || file.kind === 'template' || file.kind === 'script';
115
156
  }
@@ -143,7 +184,11 @@ docs/worklog/tasks/<yyyy-mm-dd>-<task-slug>/
143
184
  ├── plan.md
144
185
  ├── verification.md
145
186
  ├── review.md
146
- └── summary.md
187
+ ├── summary.md
188
+ ├── artifact-manifest.json
189
+ └── artifacts/
190
+ ├── index.html
191
+ └── release-report.html
147
192
  \`\`\`
148
193
 
149
194
  ## Verification
@@ -157,30 +202,40 @@ scale verify <task-id> --profile default
157
202
  scale verify <task-id> --service <service-name>
158
203
  scale verify <task-id> --artifact-gate warn
159
204
  scale verify <task-id> --artifact-gate block
160
- scale verify <task-id> --require-installed-skills
161
- scale task-artifacts check --dir docs/worklog/tasks/<task-dir> --level L
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>
162
210
  \`\`\`
163
211
 
164
- Keep \`.scale/verification.json\` as the source of truth for profiles and service commands.
165
- Keep \`.scale/skills.json\` as the source of truth for active skill routing policy.
166
- 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.
167
- 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.
168
- 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.
169
- Use \`artifactGate: "warn"\` while introducing the workflow, then move M/L/CRITICAL work to \`"block"\` once templates and local gates are stable.
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.
170
219
 
171
- ## Active Skill Routing
172
-
173
- 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.
174
-
175
- Tool orchestration is part of the workflow contract:
176
-
177
- - 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.
178
- - Web research, logged-in pages, and dynamic browser work require \`web-access\` evidence, source citations, and browser/network/console evidence when available.
179
- - 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.
180
- - Desktop or client-side GUI automation uses CUA/computer-use only with explicit operator-safety notes, desktop screenshots, and a side-effect boundary.
181
- - 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.
182
-
183
- 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\`.
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\`.
184
239
 
185
240
  Before M/L work, check whether required workflow skills are physically installed:
186
241
 
@@ -194,67 +249,69 @@ scale skill check --require-installed --json
194
249
  Before finishing an agent-created branch or deleting a temporary worktree, inspect root and child repository state:
195
250
 
196
251
  \`\`\`bash
197
- scale workspace status --json
198
- scale workspace finish --summary
199
- scale workspace finish --json
200
- scale workspace cleanup --dir <temporary-worktree> --dry-run --json
201
- scale workspace cleanup --dir <temporary-worktree> --apply --confirm <branch-or-head> --json
202
- \`\`\`
203
-
204
- 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.
205
-
206
- 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.
207
-
208
- ## Resource Governance
209
-
210
- Use asset scanning before committing generated reports, media, temporary scripts, or long-lived documentation changes:
211
-
212
- \`\`\`bash
213
- scale assets scan --json
214
- scale assets doctor --json
215
- scale assets settle --task-id <task-id> --artifact-dir docs/worklog/tasks/<task-dir>
216
- \`\`\`
217
-
218
- Default policy:
219
-
220
- - maintained module docs, standards, contracts, ADRs, reusable scripts: commit and keep current.
221
- - task worklog artifacts: review before commit; promote final truth to maintained docs when useful.
222
- - screenshots, videos, E2E reports, coverage, temporary scripts, and runtime logs: keep out of Git unless explicitly promoted.
223
- - large media: use Git LFS or external artifact storage instead of normal Git history.
224
-
225
- ## Engineering Standards
226
-
227
- Use standards scanning before reviewing or shipping M/L/CRITICAL work:
228
-
229
- \`\`\`bash
230
- scale standards scan --json
231
- scale standards doctor --json
232
- scale standards doctor --changed --json
233
- scale standards doctor --changed-files src/example.ts,src/example.test.ts --json
234
- scale standards baseline --write --artifact-dir docs/worklog/tasks/<task-dir> --task-id <task-id> --json
235
- scale standards settle --task-id <task-id> --artifact-dir docs/worklog/tasks/<task-dir>
236
- scale preflight --preflight-profile full --json
237
- scale verify <task-id> --json
238
- \`\`\`
239
-
240
- Default policy:
241
-
242
- - ad-hoc console/output logging is allowed only for CLI/script paths.
243
- - sensitive fields such as token, password, secret, authorization, cookie, and credentials must not be logged.
244
- - hardcoded secret-like assignments are blocked before review or release.
245
- - SQL must use parameterized queries, ORM bind parameters, or safe query builders.
246
- - unsafe HTML sinks, dynamic code execution, empty catch blocks, and type suppressions require remediation before release.
247
- - framework and architecture rules live in \`.scale/frameworks.json\` and module standards docs.
248
- - \`.scale/frameworks.json > bannedImports\` blocks direct use of deprecated ORMs, unsafe SDKs, or off-system UI components.
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.
249
304
  - \`.scale/frameworks.json > lastReviewedAt/reviewIntervalDays\` warns when module framework decisions need review.
250
305
  - \`.scale/engineering-standards.json > blockingRules\` promotes selected warning rule IDs to release-blocking findings.
251
306
  - \`.scale/engineering-standards.json > allowedFindingPatterns\` allows narrow rule/path/evidence exceptions without hiding unrelated findings in the same file.
252
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.
253
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.
254
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.
255
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.
256
-
257
- ## Automation Templates
313
+
314
+ ## Automation Templates
258
315
 
259
316
  Optional automation templates are generated under \`docs/workflow/templates/\`:
260
317
 
@@ -353,23 +410,23 @@ function skillPlanTemplate() {
353
410
 
354
411
  - TBD
355
412
 
356
- ## Required Verification Evidence
357
-
358
- - TBD
359
-
360
- ## Tool Orchestration
361
-
362
- | Capability | Primary Tool Or Skill | Fallback | Required Evidence |
363
- | --- | --- | --- | --- |
364
- | UI/UX design | frontend-design, ui-ux-pro-max | awesome-design-md | design-system, ui-spec.md, visual-review.md |
365
- | Web research or logged-in pages | web-access | agent-browser, Chrome DevTools MCP | source citations, browser evidence |
366
- | Browser E2E | webapp-testing, Playwright | agent-browser, web-access | screenshot, console, network evidence |
367
- | Desktop GUI automation | CUA/computer-use | manual verification | desktop screenshot, operator-safety notes |
368
- | External agent CLI | codex/gemini/opencode CLI | manual review | version check, exact command output |
369
-
370
- ## Skipped Skills
371
-
372
- | 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 |
373
430
  | --- | --- | --- |
374
431
  | | | |
375
432
  `;
@@ -377,34 +434,34 @@ function skillPlanTemplate() {
377
434
  function skillEvidenceTemplate() {
378
435
  return `# Skill Evidence
379
436
 
380
- ## Planned Skills
381
-
382
- - TBD
383
-
384
- ## Tool Selection Rationale
385
-
386
- TBD
387
-
388
- ## Used Skills
389
-
390
- | Skill | Phase | Trigger | Evidence | Status |
391
- | --- | --- | --- | --- | --- |
392
- | skill-id | plan/build/verify/review | why it was selected | command, screenshot, report, or artifact path | executed/skipped/fallback |
393
-
394
- ## Browser Or Web Evidence
395
-
396
- | Tool | Target | Evidence | Result |
397
- | --- | --- | --- | --- |
398
- | web-access/agent-browser/Chrome DevTools MCP | URL or local target | screenshot, console log, network finding, source URL | passed/failed/skipped |
399
-
400
- ## Desktop Or External CLI Evidence
401
-
402
- | Tool | Scope | Safety Boundary | Evidence | Result |
403
- | --- | --- | --- | --- | --- |
404
- | 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 |
405
-
406
- ## Skipped Skills
407
-
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
+
408
465
  | Skill | Reason | Fallback Evidence |
409
466
  | --- | --- | --- |
410
467
  | skill-id | why it could not run | manual review, alternate command, or explicit risk |
@@ -517,89 +574,96 @@ TBD
517
574
  - TBD
518
575
  `;
519
576
  }
577
+ function toolModeFromGovernanceMode(mode) {
578
+ if (mode === 'critical')
579
+ return 'block';
580
+ if (mode === 'minimal')
581
+ return 'advisory';
582
+ return 'evidence-required';
583
+ }
520
584
  function resourceImpactTemplate() {
521
- return `# Resource Impact
522
-
523
- ## Resources Created
524
-
525
- | Path | Type | Git Policy | Retention |
526
- | --- | --- | --- | --- |
527
- | TBD | canonical-doc/task-artifact/evidence-report/temporary/reusable-script/generated-media/contract/decision-record | commit/ignore/lfs/external/review | TBD |
528
-
529
- ## Resources Updated
530
-
531
- - TBD
532
-
533
- ## Resources Promoted To Maintained Docs
534
-
535
- - TBD
536
-
537
- ## Resources To Delete Or Archive Before Finish
538
-
539
- - TBD
540
-
541
- ## Source Of Truth Updates
542
-
543
- - [ ] .scale/resource-policy.json
544
- - [ ] .scale/assets.json
545
- - [ ] 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
546
610
  `;
547
611
  }
548
612
  function standardsImpactTemplate() {
549
- return `# Standards Impact
550
-
551
- ## Standards Checked
552
-
553
- - [ ] Logging and redaction
554
- - [ ] Architecture boundaries
555
- - [ ] ORM/database access
556
- - [ ] Framework/component conventions
557
- - [ ] UI/UX acceptance where user-facing
558
- - [ ] Test and verification rigor
559
- - [ ] Security-sensitive inputs and outputs
560
-
561
- ## Findings
562
-
563
- | Severity | Rule | Path | Decision |
564
- | --- | --- | --- | --- |
565
- | TBD | TBD | TBD | fix/accept/escalate |
566
-
567
- ## Policy Updates
568
-
569
- - [ ] .scale/engineering-standards.json
570
- - [ ] .scale/frameworks.json
571
- - [ ] docs/standards/
572
-
573
- ## Settlement
574
-
575
- - Standards scan:
576
- - 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:
577
641
  `;
578
642
  }
579
643
  function architectureReviewTemplate() {
580
- return `# Architecture Review
581
-
582
- ## Scope
583
-
584
- - Modules touched:
585
- - Public contracts touched:
586
- - Data flow touched:
587
-
588
- ## Boundary Checks
589
-
590
- - [ ] API/controller layer does not bypass service/usecase layer
591
- - [ ] Domain layer is not coupled to infrastructure details
592
- - [ ] Repository/ORM usage follows project conventions
593
- - [ ] Shared framework components are reused instead of duplicated
594
- - [ ] New abstractions remove real complexity
595
-
596
- ## Risks
597
-
598
- - TBD
599
-
600
- ## Decision
601
-
602
- - 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:
603
667
  `;
604
668
  }
605
669
  function securityReviewTemplate() {
@@ -677,6 +741,70 @@ TBD
677
741
  TBD
678
742
  `;
679
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
+ }
680
808
  function planTemplate() {
681
809
  return `# Plan
682
810
 
@@ -804,6 +932,12 @@ function verificationMatrixTemplate(mode, options = {}) {
804
932
  commands: {},
805
933
  services: options.services?.filter(service => service.required !== false).map(service => service.name) ?? [],
806
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
+ },
807
941
  },
808
942
  services: options.services ?? [],
809
943
  exclude: options.exclude ?? ['node_modules', 'dist', 'tmp', 'vendor'],
@@ -813,9 +947,170 @@ function verificationMatrixTemplate(mode, options = {}) {
813
947
  artifactGate: options.artifactGate ?? (mode === 'critical' ? 'block' : 'warn'),
814
948
  artifactGateLevels: ['M', 'L', 'CRITICAL'],
815
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,
816
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
+ ],
817
983
  }, null, 2) + '\n';
818
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
+ }
819
1114
  function packageVersion() {
820
1115
  try {
821
1116
  const pkg = JSON.parse(readFileSync(join(process.cwd(), 'package.json'), 'utf-8'));