@hongmaple0820/scale-engine 0.24.0 → 0.26.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/LICENSE +15 -15
- package/README.en.md +336 -304
- package/README.md +500 -475
- package/dist/adapters/AiderAdapter.js +52 -52
- package/dist/adapters/AntigravityAdapter.d.ts +4 -0
- package/dist/adapters/AntigravityAdapter.js +21 -0
- package/dist/adapters/AntigravityAdapter.js.map +1 -0
- package/dist/adapters/ClaudeCodeAdapter.d.ts +4 -1
- package/dist/adapters/ClaudeCodeAdapter.js +34 -34
- package/dist/adapters/ClaudeCodeAdapter.js.map +1 -1
- package/dist/adapters/ClineAdapter.d.ts +4 -0
- package/dist/adapters/ClineAdapter.js +20 -0
- package/dist/adapters/ClineAdapter.js.map +1 -0
- package/dist/adapters/CodexAdapter.js +28 -28
- package/dist/adapters/CursorAdapter.js +26 -26
- package/dist/adapters/DeepSeekTuiAdapter.js +97 -97
- package/dist/adapters/DoubaoAdapter.js +33 -33
- package/dist/adapters/GeminiAdapter.js +26 -26
- package/dist/adapters/GenericProjectAgentAdapter.d.ts +29 -0
- package/dist/adapters/GenericProjectAgentAdapter.js +204 -0
- package/dist/adapters/GenericProjectAgentAdapter.js.map +1 -0
- package/dist/adapters/HermesAdapter.js +26 -26
- package/dist/adapters/JCodeAdapter.d.ts +4 -0
- package/dist/adapters/JCodeAdapter.js +19 -0
- package/dist/adapters/JCodeAdapter.js.map +1 -0
- package/dist/adapters/KiloCodeAdapter.d.ts +4 -0
- package/dist/adapters/KiloCodeAdapter.js +20 -0
- package/dist/adapters/KiloCodeAdapter.js.map +1 -0
- package/dist/adapters/KimiAdapter.js +32 -32
- package/dist/adapters/KiroAdapter.js +26 -26
- package/dist/adapters/OpenClawAdapter.js +26 -26
- package/dist/adapters/OpenCodeAdapter.js +26 -26
- package/dist/adapters/QCoderAdapter.js +26 -26
- package/dist/adapters/QoderAdapter.d.ts +4 -0
- package/dist/adapters/QoderAdapter.js +21 -0
- package/dist/adapters/QoderAdapter.js.map +1 -0
- package/dist/adapters/TraeAdapter.js +26 -26
- package/dist/adapters/VSCAdapter.js +26 -26
- package/dist/adapters/WindsurfAdapter.js +32 -32
- package/dist/adapters/WorkBuddyAdapter.js +26 -26
- package/dist/adapters/index.d.ts +5 -0
- package/dist/adapters/index.js +15 -0
- package/dist/adapters/index.js.map +1 -1
- package/dist/api/cli.js +226 -48
- package/dist/api/cli.js.map +1 -1
- package/dist/api/doctor.js +10 -3
- package/dist/api/doctor.js.map +1 -1
- package/dist/api/quickstart.js +7 -1
- package/dist/api/quickstart.js.map +1 -1
- package/dist/artifact/sqliteStore.js +89 -89
- package/dist/artifact/types.d.ts +1 -1
- package/dist/cli/phaseCommands.js +45 -45
- package/dist/context/AntiPatternRegistry.js +20 -20
- package/dist/context/ContextBuilder.js +155 -155
- package/dist/evolution/EvolutionEngine.js +31 -31
- package/dist/evolution/EvolutionEvaluator.d.ts +2 -0
- package/dist/evolution/EvolutionEvaluator.js +7 -1
- package/dist/evolution/EvolutionEvaluator.js.map +1 -1
- package/dist/fsm/FSMAgentBridge.js +11 -11
- package/dist/hooks/HookGeneratorEnhanced.js +218 -218
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/knowledge/SQLiteKnowledgeBase.js +28 -28
- package/dist/memory/MemoryBrain.d.ts +1 -0
- package/dist/memory/MemoryBrain.js +55 -52
- package/dist/memory/MemoryBrain.js.map +1 -1
- package/dist/memory/MemoryFabric.d.ts +13 -1
- package/dist/memory/MemoryFabric.js +35 -0
- package/dist/memory/MemoryFabric.js.map +1 -1
- package/dist/memory/MemoryProviders.d.ts +111 -0
- package/dist/memory/MemoryProviders.js +385 -0
- package/dist/memory/MemoryProviders.js.map +1 -0
- package/dist/memory/index.d.ts +1 -0
- package/dist/memory/index.js +1 -0
- package/dist/memory/index.js.map +1 -1
- package/dist/output/GovernanceDashboard.js +44 -44
- package/dist/output/HTMLArtifactLayer.js +31 -31
- package/dist/prompts/VibeTemplateGallery.js +121 -121
- package/dist/skills/SkillDiscovery.js +12 -1
- package/dist/skills/SkillDiscovery.js.map +1 -1
- package/dist/skills/SkillRadar.js +20 -0
- package/dist/skills/SkillRadar.js.map +1 -1
- package/dist/skills/SkillRepository.d.ts +9 -1
- package/dist/skills/SkillRepository.js +70 -0
- package/dist/skills/SkillRepository.js.map +1 -1
- package/dist/skills/routing/SkillPlanner.js +40 -40
- package/dist/workflow/EngineeringStandards.js +62 -62
- package/dist/workflow/GovernanceTemplatePacks.d.ts +1 -1
- package/dist/workflow/GovernanceTemplatePacks.js +1990 -162
- package/dist/workflow/GovernanceTemplatePacks.js.map +1 -1
- package/dist/workflow/GovernanceTemplates.d.ts +2 -0
- package/dist/workflow/GovernanceTemplates.js +1012 -1001
- package/dist/workflow/GovernanceTemplates.js.map +1 -1
- package/dist/workflow/ResourceGovernance.js +16 -16
- package/dist/workflow/TaskArtifactScaffolder.js +10 -10
- package/dist/workflow/UpgradeManager.d.ts +3 -2
- package/dist/workflow/UpgradeManager.js +134 -49
- package/dist/workflow/UpgradeManager.js.map +1 -1
- package/dist/workflow/WorkspaceTopology.js +18 -15
- package/dist/workflow/WorkspaceTopology.js.map +1 -1
- package/docs/CODE_INTELLIGENCE.md +138 -138
- package/docs/CONTEXT_BUDGET.md +81 -81
- package/docs/EXTERNAL_REFERENCES.md +63 -0
- package/docs/GITLAB_FLOW.md +125 -125
- package/docs/GOVERNANCE_DASHBOARD.md +64 -64
- package/docs/MEMORY_BRAIN.md +104 -104
- package/docs/MEMORY_FABRIC.md +134 -107
- package/docs/README.md +79 -68
- package/docs/RUNTIME_EVIDENCE.md +101 -101
- package/docs/SKILL-REPOSITORY.md +57 -0
- package/docs/SKILL_RADAR.md +122 -115
- package/docs/THIRD_PARTY_SKILLS.md +57 -0
- package/docs/WORKFLOW_EVAL.md +151 -151
- package/docs/guides/DEVELOPMENT_WORKFLOW.md +80 -0
- package/docs/guides/GETTING_STARTED.md +50 -0
- package/docs/start/README.md +78 -72
- package/docs/start/agent-governance-demo.md +107 -107
- package/docs/start/quickstart.md +137 -127
- package/docs/start/workflow-upgrade.md +32 -8
- package/docs/workflow/README.md +67 -0
- package/docs/workflow/node-library.md +52 -0
- package/docs/workflow/templates/api-contract.md +29 -0
- package/docs/workflow/templates/architecture-review.md +23 -0
- package/docs/workflow/templates/db-change-plan.md +20 -0
- package/docs/workflow/templates/docs-impact.md +17 -0
- package/docs/workflow/templates/e2e-plan.md +20 -0
- package/docs/workflow/templates/explore.md +16 -0
- package/docs/workflow/templates/github-actions-scale-preflight.yml +32 -0
- package/docs/workflow/templates/mini-prd.md +16 -0
- package/docs/workflow/templates/plan.md +37 -0
- package/docs/workflow/templates/pre-push-scale-preflight.sh +8 -0
- package/docs/workflow/templates/product-smoke.md +61 -0
- package/docs/workflow/templates/reality-check.md +28 -0
- package/docs/workflow/templates/resource-cleanup.md +17 -0
- package/docs/workflow/templates/resource-impact.md +25 -0
- package/docs/workflow/templates/review.md +12 -0
- package/docs/workflow/templates/runtime.md +23 -0
- package/docs/workflow/templates/security-review.md +26 -0
- package/docs/workflow/templates/skill-evidence.md +33 -0
- package/docs/workflow/templates/skill-plan.md +39 -0
- package/docs/workflow/templates/spec.md +17 -0
- package/docs/workflow/templates/standards-impact.md +28 -0
- package/docs/workflow/templates/summary.md +16 -0
- package/docs/workflow/templates/tasks.md +8 -0
- package/docs/workflow/templates/ui-spec.md +29 -0
- package/docs/workflow/templates/verification.md +20 -0
- package/docs/workflow/templates/visual-review.md +20 -0
- package/examples/demo-projects/agent-governance-demo/CONTEXT.md +14 -14
- package/examples/demo-projects/agent-governance-demo/README.md +48 -48
- package/examples/demo-projects/agent-governance-demo/docs/CONTEXT-MAP.md +14 -14
- package/examples/demo-projects/agent-governance-demo/package.json +22 -21
- package/examples/demo-projects/agent-governance-demo/src/oauth-state.ts +39 -39
- package/examples/demo-projects/agent-governance-demo/tests/oauth-state.test.ts +52 -52
- package/package.json +88 -75
|
@@ -36,18 +36,14 @@ const PACKS = [
|
|
|
36
36
|
version: 2,
|
|
37
37
|
description: 'Reference project governance scaffold with workflow wrappers.',
|
|
38
38
|
modeDefaults,
|
|
39
|
-
generatedFiles:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
{ path: 'scripts/workflow/resume.ps1', kind: 'script', owned: true, content: powershellWorkflowWrapper('workflow/resume', 'status') },
|
|
48
|
-
{ path: 'scripts/workflow/verify.ps1', kind: 'script', owned: true, content: powershellWorkflowWrapper('workflow/verify', 'preflight') },
|
|
49
|
-
{ path: 'scripts/gates/all.ps1', kind: 'script', owned: true, content: powershellWorkflowWrapper('gates/all', 'preflight --service all') },
|
|
50
|
-
],
|
|
39
|
+
generatedFiles: workflowWrapperFiles(),
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: 'scale-engine-repo',
|
|
43
|
+
version: 1,
|
|
44
|
+
description: 'Self-hosted repository workflow for developing scale-engine itself.',
|
|
45
|
+
modeDefaults,
|
|
46
|
+
generatedFiles: scaleEngineRepoFiles(),
|
|
51
47
|
},
|
|
52
48
|
{
|
|
53
49
|
id: 'moe-workspace',
|
|
@@ -85,10 +81,17 @@ const PACKS = [
|
|
|
85
81
|
},
|
|
86
82
|
{
|
|
87
83
|
id: 'node-library',
|
|
88
|
-
version:
|
|
84
|
+
version: 2,
|
|
89
85
|
description: 'Node/npm library governance with build, test, diff, and pack checks.',
|
|
90
86
|
modeDefaults,
|
|
91
|
-
generatedFiles: [
|
|
87
|
+
generatedFiles: [
|
|
88
|
+
...workflowWrapperFiles(),
|
|
89
|
+
{ path: 'scripts/preflight/all.sh', kind: 'script', owned: true, content: nodeLibraryPreflightShellScript() },
|
|
90
|
+
{ path: 'scripts/preflight/all.ps1', kind: 'script', owned: true, content: nodeLibraryPreflightPowerShellScript() },
|
|
91
|
+
{ path: '.scale/workspace.json', kind: 'config', owned: true, content: workspaceTopologyTemplate({ topology: 'single' }) },
|
|
92
|
+
{ path: 'docs/workflow/node-library.md', kind: 'doc', owned: true, content: nodeLibraryGuide() },
|
|
93
|
+
{ path: '.planning/tasks/.gitkeep', kind: 'config', owned: true, content: '' },
|
|
94
|
+
],
|
|
92
95
|
},
|
|
93
96
|
{
|
|
94
97
|
id: 'frontend-app',
|
|
@@ -99,171 +102,1996 @@ const PACKS = [
|
|
|
99
102
|
},
|
|
100
103
|
];
|
|
101
104
|
function workflowWrapper(label, scaleCommand) {
|
|
102
|
-
return `#!/usr/bin/env bash
|
|
103
|
-
set -euo pipefail
|
|
104
|
-
|
|
105
|
-
is_wsl() {
|
|
106
|
-
grep -qiE "(microsoft|wsl)" /proc/version /proc/sys/kernel/osrelease 2>/dev/null
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
is_windows_npm_shim() {
|
|
110
|
-
local command_path="$1"
|
|
111
|
-
printf '%s' "$command_path" | grep -qiE '^/mnt/[a-z]/.*nodejs/[^/]+$'
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
run_scale() {
|
|
115
|
-
local scale_path=""
|
|
116
|
-
scale_path="$(command -v scale 2>/dev/null || true)"
|
|
117
|
-
if [ -n "$scale_path" ]; then
|
|
118
|
-
if is_wsl && is_windows_npm_shim "$scale_path"; then
|
|
119
|
-
echo "[scale-engine] Windows npm scale was detected inside WSL: $scale_path" >&2
|
|
120
|
-
echo "[scale-engine] Use the matching PowerShell wrapper (*.ps1), or install scale-engine inside WSL with a Linux Node.js toolchain." >&2
|
|
121
|
-
return 2
|
|
122
|
-
fi
|
|
123
|
-
scale "$@"
|
|
124
|
-
else
|
|
125
|
-
local npx_path=""
|
|
126
|
-
npx_path="$(command -v npx 2>/dev/null || true)"
|
|
127
|
-
if [ -n "$npx_path" ] && is_wsl && is_windows_npm_shim "$npx_path"; then
|
|
128
|
-
echo "[scale-engine] Windows npm npx was detected inside WSL: $npx_path" >&2
|
|
129
|
-
echo "[scale-engine] Use the matching PowerShell wrapper (*.ps1), or install Node.js/npm inside WSL." >&2
|
|
130
|
-
return 2
|
|
131
|
-
fi
|
|
132
|
-
npx @hongmaple0820/scale-engine@latest "$@"
|
|
133
|
-
fi
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
echo "[scale-engine] compatibility wrapper: scripts/${label}.sh -> scale ${scaleCommand}" >&2
|
|
137
|
-
run_scale ${scaleCommand} "$@"
|
|
105
|
+
return `#!/usr/bin/env bash
|
|
106
|
+
set -euo pipefail
|
|
107
|
+
|
|
108
|
+
is_wsl() {
|
|
109
|
+
grep -qiE "(microsoft|wsl)" /proc/version /proc/sys/kernel/osrelease 2>/dev/null
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
is_windows_npm_shim() {
|
|
113
|
+
local command_path="$1"
|
|
114
|
+
printf '%s' "$command_path" | grep -qiE '^/mnt/[a-z]/.*nodejs/[^/]+$'
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
run_scale() {
|
|
118
|
+
local scale_path=""
|
|
119
|
+
scale_path="$(command -v scale 2>/dev/null || true)"
|
|
120
|
+
if [ -n "$scale_path" ]; then
|
|
121
|
+
if is_wsl && is_windows_npm_shim "$scale_path"; then
|
|
122
|
+
echo "[scale-engine] Windows npm scale was detected inside WSL: $scale_path" >&2
|
|
123
|
+
echo "[scale-engine] Use the matching PowerShell wrapper (*.ps1), or install scale-engine inside WSL with a Linux Node.js toolchain." >&2
|
|
124
|
+
return 2
|
|
125
|
+
fi
|
|
126
|
+
scale "$@"
|
|
127
|
+
else
|
|
128
|
+
local npx_path=""
|
|
129
|
+
npx_path="$(command -v npx 2>/dev/null || true)"
|
|
130
|
+
if [ -n "$npx_path" ] && is_wsl && is_windows_npm_shim "$npx_path"; then
|
|
131
|
+
echo "[scale-engine] Windows npm npx was detected inside WSL: $npx_path" >&2
|
|
132
|
+
echo "[scale-engine] Use the matching PowerShell wrapper (*.ps1), or install Node.js/npm inside WSL." >&2
|
|
133
|
+
return 2
|
|
134
|
+
fi
|
|
135
|
+
npx @hongmaple0820/scale-engine@latest "$@"
|
|
136
|
+
fi
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
echo "[scale-engine] compatibility wrapper: scripts/${label}.sh -> scale ${scaleCommand}" >&2
|
|
140
|
+
run_scale ${scaleCommand} "$@"
|
|
138
141
|
`;
|
|
139
142
|
}
|
|
143
|
+
function workflowWrapperFiles() {
|
|
144
|
+
return [
|
|
145
|
+
{ path: 'scripts/workflow/new-task.sh', kind: 'script', owned: true, content: workflowWrapper('workflow/new-task', 'create-prd') },
|
|
146
|
+
{ path: 'scripts/workflow/explore.sh', kind: 'script', owned: true, content: workflowWrapper('workflow/explore', 'skill scan') },
|
|
147
|
+
{ path: 'scripts/workflow/resume.sh', kind: 'script', owned: true, content: workflowWrapper('workflow/resume', 'status') },
|
|
148
|
+
{ path: 'scripts/workflow/verify.sh', kind: 'script', owned: true, content: workflowWrapper('workflow/verify', 'preflight') },
|
|
149
|
+
{ path: 'scripts/gates/all.sh', kind: 'script', owned: true, content: workflowWrapper('gates/all', 'preflight --service all') },
|
|
150
|
+
{ path: 'scripts/workflow/new-task.ps1', kind: 'script', owned: true, content: powershellWorkflowWrapper('workflow/new-task', 'create-prd') },
|
|
151
|
+
{ path: 'scripts/workflow/explore.ps1', kind: 'script', owned: true, content: powershellWorkflowWrapper('workflow/explore', 'skill scan') },
|
|
152
|
+
{ path: 'scripts/workflow/resume.ps1', kind: 'script', owned: true, content: powershellWorkflowWrapper('workflow/resume', 'status') },
|
|
153
|
+
{ path: 'scripts/workflow/verify.ps1', kind: 'script', owned: true, content: powershellWorkflowWrapper('workflow/verify', 'preflight') },
|
|
154
|
+
{ path: 'scripts/gates/all.ps1', kind: 'script', owned: true, content: powershellWorkflowWrapper('gates/all', 'preflight --service all') },
|
|
155
|
+
];
|
|
156
|
+
}
|
|
157
|
+
function scaleEngineRepoFiles() {
|
|
158
|
+
return [
|
|
159
|
+
{ path: '.scale/workspace.json', kind: 'config', owned: true, content: scaleEngineRepoWorkspaceJson() },
|
|
160
|
+
{ path: '.agent/project.json', kind: 'config', owned: true, content: scaleEngineRepoProjectJson() },
|
|
161
|
+
{ path: '.claude/settings.json', kind: 'config', owned: true, content: scaleEngineRepoClaudeSettings() },
|
|
162
|
+
{ path: '.claude/workflow.json', kind: 'config', owned: true, content: scaleEngineRepoClaudeWorkflow() },
|
|
163
|
+
{ path: '.claude/hooks/session-start-reminder.sh', kind: 'script', owned: true, content: scaleEngineSessionStartHook() },
|
|
164
|
+
{ path: '.claude/hooks/gate-execute-phase.sh', kind: 'script', owned: true, content: scaleEngineExecutePhaseHook() },
|
|
165
|
+
{ path: '.claude/hooks/session-end-gate.sh', kind: 'script', owned: true, content: scaleEngineSessionEndHook() },
|
|
166
|
+
{ path: 'scripts/hooks/check-dangerous-file.sh', kind: 'script', owned: true, content: scaleEngineDangerousFileHook() },
|
|
167
|
+
{ path: 'scripts/hooks/check-explore.sh', kind: 'script', owned: true, content: scaleEngineExploreHook() },
|
|
168
|
+
{ path: 'scripts/hooks/check-tdd.sh', kind: 'script', owned: true, content: scaleEngineTddHook() },
|
|
169
|
+
{ path: 'scripts/hooks/check-context.sh', kind: 'script', owned: true, content: scaleEngineContextHook() },
|
|
170
|
+
...workflowWrapperFiles(),
|
|
171
|
+
{ path: 'AGENTS.md', kind: 'config', owned: true, content: scaleEngineRepoAgentsMd() },
|
|
172
|
+
{ path: 'CLAUDE.md', kind: 'config', owned: true, content: scaleEngineRepoClaudeMd() },
|
|
173
|
+
{ path: 'Makefile', kind: 'config', owned: true, content: scaleEngineRepoMakefile() },
|
|
174
|
+
{ path: 'docs/guides/GETTING_STARTED.md', kind: 'config', owned: true, content: scaleEngineRepoGettingStartedGuide() },
|
|
175
|
+
{ path: 'docs/guides/DEVELOPMENT_WORKFLOW.md', kind: 'config', owned: true, content: scaleEngineRepoDevelopmentWorkflowGuide() },
|
|
176
|
+
{ path: 'docs/workflow/README.md', kind: 'config', owned: true, content: scaleEngineRepoWorkflowReadme() },
|
|
177
|
+
];
|
|
178
|
+
}
|
|
140
179
|
function powershellWorkflowWrapper(label, scaleCommand) {
|
|
141
180
|
const commandParts = scaleCommand.split(/\s+/).filter(Boolean);
|
|
142
181
|
const psArgs = commandParts.map(part => `'${part.replace(/'/g, "''")}'`).join(', ');
|
|
143
|
-
return `$ErrorActionPreference = 'Stop'
|
|
144
|
-
|
|
145
|
-
function Invoke-Scale {
|
|
146
|
-
param([string[]]$ScaleArgs)
|
|
147
|
-
|
|
148
|
-
if (Get-Command scale -ErrorAction SilentlyContinue) {
|
|
149
|
-
& scale @ScaleArgs
|
|
150
|
-
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
|
151
|
-
return
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
& npx @hongmaple0820/scale-engine@latest @ScaleArgs
|
|
155
|
-
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
[Console]::Error.WriteLine("[scale-engine] compatibility wrapper: scripts/${label}.ps1 -> scale ${scaleCommand}")
|
|
159
|
-
$scaleArgs = @(${psArgs}) + $args
|
|
160
|
-
Invoke-Scale -ScaleArgs $scaleArgs
|
|
182
|
+
return `$ErrorActionPreference = 'Stop'
|
|
183
|
+
|
|
184
|
+
function Invoke-Scale {
|
|
185
|
+
param([string[]]$ScaleArgs)
|
|
186
|
+
|
|
187
|
+
if (Get-Command scale -ErrorAction SilentlyContinue) {
|
|
188
|
+
& scale @ScaleArgs
|
|
189
|
+
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
|
190
|
+
return
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
& npx @hongmaple0820/scale-engine@latest @ScaleArgs
|
|
194
|
+
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
[Console]::Error.WriteLine("[scale-engine] compatibility wrapper: scripts/${label}.ps1 -> scale ${scaleCommand}")
|
|
198
|
+
$scaleArgs = @(${psArgs}) + $args
|
|
199
|
+
Invoke-Scale -ScaleArgs $scaleArgs
|
|
200
|
+
`;
|
|
201
|
+
}
|
|
202
|
+
function scaleEngineWorkflowBaselineEvalJson() {
|
|
203
|
+
return `${JSON.stringify({
|
|
204
|
+
version: '1.0',
|
|
205
|
+
id: 'workflow-baseline',
|
|
206
|
+
name: 'SCALE workflow baseline',
|
|
207
|
+
cases: [
|
|
208
|
+
{
|
|
209
|
+
id: 'governance-command-smoke',
|
|
210
|
+
type: 'bugfix',
|
|
211
|
+
title: 'Command evidence smoke',
|
|
212
|
+
task: 'Verify that a local command can produce concrete eval evidence.',
|
|
213
|
+
phase: 'verify',
|
|
214
|
+
successCriteria: [
|
|
215
|
+
'command exits 0',
|
|
216
|
+
'output contains scale-eval-ok',
|
|
217
|
+
],
|
|
218
|
+
attempts: [
|
|
219
|
+
{
|
|
220
|
+
id: 'attempt-1',
|
|
221
|
+
command: 'node -e "console.log(\'scale-eval-ok\')"',
|
|
222
|
+
expectedExitCode: 0,
|
|
223
|
+
outputContains: 'scale-eval-ok',
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
},
|
|
227
|
+
],
|
|
228
|
+
}, null, 2)}\n`;
|
|
229
|
+
}
|
|
230
|
+
function scaleEngineWorkflowPlanShellScript() {
|
|
231
|
+
return `#!/bin/bash
|
|
232
|
+
# Create an implementation plan directory and update workflow state.
|
|
233
|
+
# Usage: bash scripts/workflow/plan.sh "feature-name" [level]
|
|
234
|
+
|
|
235
|
+
set -euo pipefail
|
|
236
|
+
|
|
237
|
+
PROJECT_ROOT="$(cd "$(dirname "\${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
238
|
+
NAME="\${1:-}"
|
|
239
|
+
LEVEL="\${2:-M}"
|
|
240
|
+
|
|
241
|
+
if [ -z "$NAME" ]; then
|
|
242
|
+
echo "[PLAN] usage: bash scripts/workflow/plan.sh feature-name [S|M|L|CRITICAL]"
|
|
243
|
+
exit 1
|
|
244
|
+
fi
|
|
245
|
+
|
|
246
|
+
DATE="$(date +%Y-%m-%d)"
|
|
247
|
+
TASK_ID="\${DATE}-\${NAME}"
|
|
248
|
+
TASK_DIR="$PROJECT_ROOT/.planning/tasks/$TASK_ID"
|
|
249
|
+
STATE_DIR="$PROJECT_ROOT/.agent/state"
|
|
250
|
+
STATE_FILE="$STATE_DIR/current.json"
|
|
251
|
+
TEMPLATES="$PROJECT_ROOT/docs/workflow/templates"
|
|
252
|
+
PY_STATE="$PROJECT_ROOT/scripts/lib/workflow_state.py"
|
|
253
|
+
|
|
254
|
+
mkdir -p "$TASK_DIR" "$STATE_DIR"
|
|
255
|
+
|
|
256
|
+
for file in explore.md mini-prd.md spec.md plan.md tasks.md runtime.md reality-check.md resource-cleanup.md verification.md review.md summary.md; do
|
|
257
|
+
target="$TASK_DIR/$file"
|
|
258
|
+
if [ -f "$TEMPLATES/$file" ]; then
|
|
259
|
+
sed "s/{{TASK_ID}}/$TASK_ID/g; s/{{NAME}}/$NAME/g; s/{{DATE}}/$DATE/g; s/{{LEVEL}}/$LEVEL/g" "$TEMPLATES/$file" > "$target"
|
|
260
|
+
else
|
|
261
|
+
cat > "$target" <<EOF
|
|
262
|
+
# \${file%.md} - $NAME
|
|
263
|
+
|
|
264
|
+
Date: $DATE
|
|
265
|
+
Level: $LEVEL
|
|
266
|
+
|
|
267
|
+
Fill in this plan artifact.
|
|
268
|
+
EOF
|
|
269
|
+
fi
|
|
270
|
+
done
|
|
271
|
+
|
|
272
|
+
python3 "$PY_STATE" plan "$STATE_FILE" "$TASK_ID" "$LEVEL" ".planning/tasks/$TASK_ID"
|
|
273
|
+
|
|
274
|
+
echo "[PLAN] task artifacts dir: $TASK_DIR"
|
|
275
|
+
echo "[PLAN] state: $STATE_FILE"
|
|
276
|
+
`;
|
|
277
|
+
}
|
|
278
|
+
function scaleEngineGatesAllShellScript() {
|
|
279
|
+
return `#!/usr/bin/env bash
|
|
280
|
+
# Run workflow and quality gates.
|
|
281
|
+
|
|
282
|
+
set -euo pipefail
|
|
283
|
+
|
|
284
|
+
SCRIPT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
|
|
285
|
+
|
|
286
|
+
DRY_RUN=false
|
|
287
|
+
MODE="all"
|
|
288
|
+
SERVICES=()
|
|
289
|
+
|
|
290
|
+
usage() {
|
|
291
|
+
cat <<'USAGE'
|
|
292
|
+
Usage:
|
|
293
|
+
bash scripts/gates/all.sh [--dry-run] [--workflow|--quality|--all] [--service <root|all>]
|
|
294
|
+
|
|
295
|
+
Examples:
|
|
296
|
+
bash scripts/gates/all.sh --dry-run
|
|
297
|
+
bash scripts/gates/all.sh --workflow
|
|
298
|
+
bash scripts/gates/all.sh --quality --service root
|
|
299
|
+
USAGE
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
while [ "$#" -gt 0 ]; do
|
|
303
|
+
case "$1" in
|
|
304
|
+
--dry-run)
|
|
305
|
+
DRY_RUN=true
|
|
306
|
+
;;
|
|
307
|
+
--workflow)
|
|
308
|
+
MODE="workflow"
|
|
309
|
+
;;
|
|
310
|
+
--quality)
|
|
311
|
+
MODE="quality"
|
|
312
|
+
;;
|
|
313
|
+
--all)
|
|
314
|
+
MODE="all"
|
|
315
|
+
;;
|
|
316
|
+
--service)
|
|
317
|
+
shift
|
|
318
|
+
if [ -z "\${1:-}" ]; then
|
|
319
|
+
echo "[GATE] --service requires a value" >&2
|
|
320
|
+
exit 1
|
|
321
|
+
fi
|
|
322
|
+
SERVICES+=("$1")
|
|
323
|
+
;;
|
|
324
|
+
root|all)
|
|
325
|
+
SERVICES+=("$1")
|
|
326
|
+
;;
|
|
327
|
+
-h|--help)
|
|
328
|
+
usage
|
|
329
|
+
exit 0
|
|
330
|
+
;;
|
|
331
|
+
*)
|
|
332
|
+
echo "[GATE] unknown argument: $1" >&2
|
|
333
|
+
usage >&2
|
|
334
|
+
exit 1
|
|
335
|
+
;;
|
|
336
|
+
esac
|
|
337
|
+
shift
|
|
338
|
+
done
|
|
339
|
+
|
|
340
|
+
case "$MODE" in
|
|
341
|
+
workflow) GATES=(G1 G2 G3) ;;
|
|
342
|
+
quality) GATES=(G4 G5 G6 G7 G8) ;;
|
|
343
|
+
all) GATES=(G1 G2 G3 G4 G5 G6 G7 G8) ;;
|
|
344
|
+
*)
|
|
345
|
+
echo "[GATE] invalid mode: $MODE" >&2
|
|
346
|
+
exit 1
|
|
347
|
+
;;
|
|
348
|
+
esac
|
|
349
|
+
|
|
350
|
+
PASSED=0
|
|
351
|
+
FAILED=0
|
|
352
|
+
SKIPPED=0
|
|
353
|
+
|
|
354
|
+
echo "========================================"
|
|
355
|
+
echo "[GATE] mode: $MODE"
|
|
356
|
+
echo "========================================"
|
|
357
|
+
|
|
358
|
+
for gate in "\${GATES[@]}"; do
|
|
359
|
+
script="$SCRIPT_DIR/\${gate}-verify.sh"
|
|
360
|
+
echo "[GATE] $gate"
|
|
361
|
+
|
|
362
|
+
if [ ! -f "$script" ]; then
|
|
363
|
+
echo " skipped: missing $script"
|
|
364
|
+
SKIPPED=$((SKIPPED + 1))
|
|
365
|
+
continue
|
|
366
|
+
fi
|
|
367
|
+
|
|
368
|
+
if [ "$DRY_RUN" = true ]; then
|
|
369
|
+
if bash -n "$script"; then
|
|
370
|
+
echo " schedulable"
|
|
371
|
+
PASSED=$((PASSED + 1))
|
|
372
|
+
else
|
|
373
|
+
echo " syntax failed"
|
|
374
|
+
FAILED=$((FAILED + 1))
|
|
375
|
+
fi
|
|
376
|
+
continue
|
|
377
|
+
fi
|
|
378
|
+
|
|
379
|
+
if [[ "$gate" =~ ^G[4-7]$ ]]; then
|
|
380
|
+
if bash "$script" "\${SERVICES[@]}"; then
|
|
381
|
+
PASSED=$((PASSED + 1))
|
|
382
|
+
else
|
|
383
|
+
FAILED=$((FAILED + 1))
|
|
384
|
+
fi
|
|
385
|
+
else
|
|
386
|
+
if bash "$script"; then
|
|
387
|
+
PASSED=$((PASSED + 1))
|
|
388
|
+
else
|
|
389
|
+
FAILED=$((FAILED + 1))
|
|
390
|
+
fi
|
|
391
|
+
fi
|
|
392
|
+
echo ""
|
|
393
|
+
done
|
|
394
|
+
|
|
395
|
+
echo "========================================"
|
|
396
|
+
echo "[GATE] summary"
|
|
397
|
+
echo "passed: $PASSED"
|
|
398
|
+
echo "failed: $FAILED"
|
|
399
|
+
echo "skipped: $SKIPPED"
|
|
400
|
+
echo "========================================"
|
|
401
|
+
|
|
402
|
+
if [ "$FAILED" -gt 0 ]; then
|
|
403
|
+
exit 1
|
|
404
|
+
fi
|
|
405
|
+
`;
|
|
406
|
+
}
|
|
407
|
+
function scaleEngineG8VerifyShellScript() {
|
|
408
|
+
return `#!/usr/bin/env bash
|
|
409
|
+
# G8: document and workflow artifact standards verification.
|
|
410
|
+
|
|
411
|
+
set -euo pipefail
|
|
412
|
+
|
|
413
|
+
PROJECT_ROOT="$(cd "$(dirname "\${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
414
|
+
|
|
415
|
+
echo "========================================"
|
|
416
|
+
echo "[G8] Document standards gate"
|
|
417
|
+
echo "========================================"
|
|
418
|
+
|
|
419
|
+
cd "$PROJECT_ROOT"
|
|
420
|
+
|
|
421
|
+
CHANGED_MD="$(
|
|
422
|
+
{
|
|
423
|
+
git diff --name-only --diff-filter=AM HEAD -- '*.md' 2>/dev/null || true
|
|
424
|
+
git ls-files --others --exclude-standard -- '*.md' 2>/dev/null || true
|
|
425
|
+
} | sort -u
|
|
426
|
+
)"
|
|
427
|
+
|
|
428
|
+
if [ -z "$CHANGED_MD" ]; then
|
|
429
|
+
echo "[G8] passed: no new/modified markdown files"
|
|
430
|
+
exit 0
|
|
431
|
+
fi
|
|
432
|
+
|
|
433
|
+
echo "[G8] checking changed markdown files:"
|
|
434
|
+
echo "$CHANGED_MD"
|
|
435
|
+
echo ""
|
|
436
|
+
|
|
437
|
+
ALL_PASS=true
|
|
438
|
+
|
|
439
|
+
while IFS= read -r file; do
|
|
440
|
+
[ -z "$file" ] && continue
|
|
441
|
+
filepath="$PROJECT_ROOT/$file"
|
|
442
|
+
[ -f "$filepath" ] || continue
|
|
443
|
+
|
|
444
|
+
echo "[G8] checking: $file"
|
|
445
|
+
|
|
446
|
+
if grep -qiE "(password|secret|token|api_key)[[:space:]]*[:=][[:space:]]*['\\"][^'\\"]{8,}" "$filepath" 2>/dev/null; then
|
|
447
|
+
echo " [FAIL] possible hardcoded secret detected"
|
|
448
|
+
ALL_PASS=false
|
|
449
|
+
fi
|
|
450
|
+
|
|
451
|
+
if grep -q $'\\r' "$filepath" 2>/dev/null; then
|
|
452
|
+
echo " [WARN] CRLF detected in markdown"
|
|
453
|
+
fi
|
|
454
|
+
|
|
455
|
+
if grep -nE '[[:blank:]]$' "$filepath" >/dev/null 2>&1; then
|
|
456
|
+
echo " [WARN] trailing whitespace detected"
|
|
457
|
+
fi
|
|
458
|
+
|
|
459
|
+
if grep -qE '\\[[^]]+\\]\\(https?://(localhost|127\\.0\\.0\\.1)' "$filepath" 2>/dev/null; then
|
|
460
|
+
echo " [WARN] localhost links found; prefer relative paths or runtime notes"
|
|
461
|
+
fi
|
|
462
|
+
done <<< "$CHANGED_MD"
|
|
463
|
+
|
|
464
|
+
echo ""
|
|
465
|
+
if [ "$ALL_PASS" = true ]; then
|
|
466
|
+
echo "[G8] passed"
|
|
467
|
+
exit 0
|
|
468
|
+
fi
|
|
469
|
+
|
|
470
|
+
echo "[G8] failed"
|
|
471
|
+
exit 1
|
|
472
|
+
`;
|
|
473
|
+
}
|
|
474
|
+
function scaleEngineSpecTemplate() {
|
|
475
|
+
return `# Spec - {{TASK_ID}}
|
|
476
|
+
|
|
477
|
+
Date: {{DATE}}
|
|
478
|
+
Level: {{LEVEL}}
|
|
479
|
+
|
|
480
|
+
## What
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
## Why
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
## Boundaries
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
## Acceptance Criteria
|
|
490
|
+
|
|
491
|
+
- [ ]
|
|
492
|
+
`;
|
|
493
|
+
}
|
|
494
|
+
function scaleEngineTasksTemplate() {
|
|
495
|
+
return `# Tasks - {{TASK_ID}}
|
|
496
|
+
|
|
497
|
+
Date: {{DATE}}
|
|
498
|
+
Level: {{LEVEL}}
|
|
499
|
+
|
|
500
|
+
## Task List
|
|
501
|
+
|
|
502
|
+
- [ ]
|
|
503
|
+
`;
|
|
504
|
+
}
|
|
505
|
+
function scaleEngineWorkflowStatePython() {
|
|
506
|
+
return `#!/usr/bin/env python3
|
|
507
|
+
"""Small helper for .agent/state/current.json.
|
|
508
|
+
|
|
509
|
+
The workflow scripts run in Git Bash, WSL, and PowerShell-adjacent
|
|
510
|
+
environments where jq is not always installed. Keep canonical state
|
|
511
|
+
reads and writes in Python's standard library.
|
|
512
|
+
"""
|
|
513
|
+
|
|
514
|
+
from __future__ import annotations
|
|
515
|
+
|
|
516
|
+
import json
|
|
517
|
+
import subprocess
|
|
518
|
+
import sys
|
|
519
|
+
from datetime import datetime, timezone
|
|
520
|
+
from pathlib import Path
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
def now() -> str:
|
|
524
|
+
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
def load(path: Path) -> dict:
|
|
528
|
+
if not path.exists():
|
|
529
|
+
return {}
|
|
530
|
+
try:
|
|
531
|
+
data = json.loads(path.read_text(encoding="utf-8"))
|
|
532
|
+
except Exception:
|
|
533
|
+
return {}
|
|
534
|
+
return data if isinstance(data, dict) else {}
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
def save(path: Path, data: dict) -> None:
|
|
538
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
539
|
+
tmp = path.with_suffix(path.suffix + ".tmp")
|
|
540
|
+
tmp.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\\n", encoding="utf-8")
|
|
541
|
+
tmp.replace(path)
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
def default_state(task_id: str = "", level: str = "M") -> dict:
|
|
545
|
+
return {
|
|
546
|
+
"task_id": task_id,
|
|
547
|
+
"level": level,
|
|
548
|
+
"phase": "explore",
|
|
549
|
+
"artifacts_dir": "",
|
|
550
|
+
"runtime_contract": "",
|
|
551
|
+
"reality_check": "",
|
|
552
|
+
"resource_cleanup": "",
|
|
553
|
+
"explored_files": [],
|
|
554
|
+
"file_count": 0,
|
|
555
|
+
"main_contradiction": "",
|
|
556
|
+
"completed_gates": [],
|
|
557
|
+
"open_tasks": [],
|
|
558
|
+
"files_modified": [],
|
|
559
|
+
"updated_at": now(),
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
def cmd_init(args: list[str]) -> int:
|
|
564
|
+
state_path = Path(args[0])
|
|
565
|
+
task_id, level, artifacts_dir = args[1], args[2], args[3]
|
|
566
|
+
data = default_state(task_id, level)
|
|
567
|
+
data["artifacts_dir"] = artifacts_dir
|
|
568
|
+
data["runtime_contract"] = str(Path(artifacts_dir) / "runtime.md")
|
|
569
|
+
data["reality_check"] = str(Path(artifacts_dir) / "reality-check.md")
|
|
570
|
+
data["resource_cleanup"] = str(Path(artifacts_dir) / "resource-cleanup.md")
|
|
571
|
+
save(state_path, data)
|
|
572
|
+
return 0
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
def cmd_explore(args: list[str]) -> int:
|
|
576
|
+
state_path = Path(args[0])
|
|
577
|
+
detail_path = Path(args[1])
|
|
578
|
+
contradiction = args[2]
|
|
579
|
+
files = args[3:]
|
|
580
|
+
data = load(state_path) or default_state(
|
|
581
|
+
"ad-hoc-" + datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ"),
|
|
582
|
+
"M",
|
|
583
|
+
)
|
|
584
|
+
data.update(
|
|
585
|
+
{
|
|
586
|
+
"phase": "explore",
|
|
587
|
+
"explored_files": files,
|
|
588
|
+
"file_count": len(files),
|
|
589
|
+
"main_contradiction": contradiction,
|
|
590
|
+
"updated_at": now(),
|
|
591
|
+
}
|
|
592
|
+
)
|
|
593
|
+
save(state_path, data)
|
|
594
|
+
save(
|
|
595
|
+
detail_path,
|
|
596
|
+
{
|
|
597
|
+
"updated_at": data["updated_at"],
|
|
598
|
+
"files": files,
|
|
599
|
+
"file_count": len(files),
|
|
600
|
+
"main_contradiction": contradiction,
|
|
601
|
+
"skills_checked": True,
|
|
602
|
+
},
|
|
603
|
+
)
|
|
604
|
+
return 0
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
def cmd_plan(args: list[str]) -> int:
|
|
608
|
+
state_path = Path(args[0])
|
|
609
|
+
task_id, level, artifacts_dir = args[1], args[2], args[3]
|
|
610
|
+
data = load(state_path) or default_state(task_id, level)
|
|
611
|
+
data.update(
|
|
612
|
+
{
|
|
613
|
+
"task_id": task_id,
|
|
614
|
+
"level": level,
|
|
615
|
+
"phase": "plan",
|
|
616
|
+
"artifacts_dir": artifacts_dir,
|
|
617
|
+
"runtime_contract": str(Path(artifacts_dir) / "runtime.md"),
|
|
618
|
+
"reality_check": str(Path(artifacts_dir) / "reality-check.md"),
|
|
619
|
+
"resource_cleanup": str(Path(artifacts_dir) / "resource-cleanup.md"),
|
|
620
|
+
"updated_at": now(),
|
|
621
|
+
}
|
|
622
|
+
)
|
|
623
|
+
save(state_path, data)
|
|
624
|
+
return 0
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
def cmd_checkpoint(args: list[str]) -> int:
|
|
628
|
+
state_path = Path(args[0])
|
|
629
|
+
root = Path(args[1])
|
|
630
|
+
phase = args[2]
|
|
631
|
+
data = load(state_path) or default_state(
|
|
632
|
+
"ad-hoc-" + datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ"),
|
|
633
|
+
"M",
|
|
634
|
+
)
|
|
635
|
+
try:
|
|
636
|
+
result = subprocess.run(
|
|
637
|
+
["git", "diff", "--name-only"],
|
|
638
|
+
cwd=root,
|
|
639
|
+
text=True,
|
|
640
|
+
stdout=subprocess.PIPE,
|
|
641
|
+
stderr=subprocess.DEVNULL,
|
|
642
|
+
check=False,
|
|
643
|
+
)
|
|
644
|
+
files = [line for line in result.stdout.splitlines() if line]
|
|
645
|
+
except Exception:
|
|
646
|
+
files = []
|
|
647
|
+
data["phase"] = phase
|
|
648
|
+
data["files_modified"] = files
|
|
649
|
+
data["updated_at"] = now()
|
|
650
|
+
data.setdefault("completed_gates", [])
|
|
651
|
+
data.setdefault("open_tasks", [])
|
|
652
|
+
save(state_path, data)
|
|
653
|
+
return 0
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
def cmd_get(args: list[str]) -> int:
|
|
657
|
+
data = load(Path(args[0]))
|
|
658
|
+
value = data.get(args[1], args[2] if len(args) > 2 else "")
|
|
659
|
+
if isinstance(value, list):
|
|
660
|
+
print(", ".join(str(v) for v in value))
|
|
661
|
+
else:
|
|
662
|
+
print(value)
|
|
663
|
+
return 0
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
def cmd_len(args: list[str]) -> int:
|
|
667
|
+
data = load(Path(args[0]))
|
|
668
|
+
value = data.get(args[1], [])
|
|
669
|
+
if isinstance(value, list):
|
|
670
|
+
print(len(value))
|
|
671
|
+
else:
|
|
672
|
+
print(int(value or 0))
|
|
673
|
+
return 0
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
def cmd_add_gates(args: list[str]) -> int:
|
|
677
|
+
state_path = Path(args[0])
|
|
678
|
+
data = load(state_path)
|
|
679
|
+
existing = data.get("completed_gates", [])
|
|
680
|
+
if not isinstance(existing, list):
|
|
681
|
+
existing = []
|
|
682
|
+
data["completed_gates"] = sorted(set(str(item) for item in existing + args[1:]))
|
|
683
|
+
data["phase"] = "verify"
|
|
684
|
+
data["updated_at"] = now()
|
|
685
|
+
save(state_path, data)
|
|
686
|
+
return 0
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
COMMANDS = {
|
|
690
|
+
"init": cmd_init,
|
|
691
|
+
"explore": cmd_explore,
|
|
692
|
+
"plan": cmd_plan,
|
|
693
|
+
"checkpoint": cmd_checkpoint,
|
|
694
|
+
"get": cmd_get,
|
|
695
|
+
"len": cmd_len,
|
|
696
|
+
"add-gates": cmd_add_gates,
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
if len(sys.argv) < 2 or sys.argv[1] not in COMMANDS:
|
|
701
|
+
print("usage: workflow_state.py <command> ...", file=sys.stderr)
|
|
702
|
+
raise SystemExit(2)
|
|
703
|
+
|
|
704
|
+
raise SystemExit(COMMANDS[sys.argv[1]](sys.argv[2:]))
|
|
161
705
|
`;
|
|
162
706
|
}
|
|
163
707
|
function moeWorkspaceGuide() {
|
|
164
|
-
return `# MOE Workspace Governance
|
|
165
|
-
|
|
166
|
-
MOE workspaces are multi-repository engineering environments where the root checkout, nested repositories, submodules, and temporary agent worktrees must be finished as one coordinated unit.
|
|
167
|
-
|
|
168
|
-
## Source Of Truth
|
|
169
|
-
|
|
170
|
-
- \`.scale/workspace.json\`: repository topology, branch policy, and finish policy.
|
|
171
|
-
- \`.scale/verification.json\`: service matrix and verification commands.
|
|
172
|
-
- \`docs/worklog/tasks/<task>/\`: task artifacts, verification evidence, and cross-repository impact.
|
|
173
|
-
|
|
174
|
-
## Required Finish Checks
|
|
175
|
-
|
|
176
|
-
Before deleting an agent worktree or reporting a task complete:
|
|
177
|
-
|
|
178
|
-
1. Run \`scale workspace map --json\` to confirm the expected repositories are known.
|
|
179
|
-
2. Run \`scale workspace finish --summary\` for the short blocker list; use \`--json\` only when full audit detail is needed.
|
|
180
|
-
3. Commit and push child repository work in each repository's own remote.
|
|
181
|
-
4. Review whether the root repository needs a submodule pointer, lock file, integration metadata, or documentation update.
|
|
182
|
-
5. Run service-aware verification for every touched service.
|
|
183
|
-
|
|
184
|
-
\`scale ship <task-id>\` performs the same child-repository boundary check before creating a root commit. Dirty or unpushed child repositories block shipping. The default branch policy follows GitLab Flow: short branches merge to \`dev\`, verified production changes land on \`master\`, and release publishing is triggered by user-created \`vX.Y.Z\` tags. Direct governed commits on \`dev\`, \`master\`, \`main\`, or detached HEAD are blocked. Raw \`git add .\` bypasses this protection and is not allowed for governed MOE workspaces.
|
|
185
|
-
|
|
186
|
-
## Branch Naming
|
|
187
|
-
|
|
188
|
-
Use readable branches with author/platform/scope/date context, for example:
|
|
189
|
-
|
|
190
|
-
\`\`\`text
|
|
191
|
-
feature/maple-codex-storage-policy-0515
|
|
192
|
-
fix/zpei-claude-upload-retry-0515
|
|
193
|
-
codex/moe-workspace-governance-0515
|
|
194
|
-
\`\`\`
|
|
195
|
-
|
|
196
|
-
Protected branches such as \`dev\`, \`main\`, and \`master\` require explicit human authorization before direct pushes.
|
|
708
|
+
return `# MOE Workspace Governance
|
|
709
|
+
|
|
710
|
+
MOE workspaces are multi-repository engineering environments where the root checkout, nested repositories, submodules, and temporary agent worktrees must be finished as one coordinated unit.
|
|
711
|
+
|
|
712
|
+
## Source Of Truth
|
|
713
|
+
|
|
714
|
+
- \`.scale/workspace.json\`: repository topology, branch policy, and finish policy.
|
|
715
|
+
- \`.scale/verification.json\`: service matrix and verification commands.
|
|
716
|
+
- \`docs/worklog/tasks/<task>/\`: task artifacts, verification evidence, and cross-repository impact.
|
|
717
|
+
|
|
718
|
+
## Required Finish Checks
|
|
719
|
+
|
|
720
|
+
Before deleting an agent worktree or reporting a task complete:
|
|
721
|
+
|
|
722
|
+
1. Run \`scale workspace map --json\` to confirm the expected repositories are known.
|
|
723
|
+
2. Run \`scale workspace finish --summary\` for the short blocker list; use \`--json\` only when full audit detail is needed.
|
|
724
|
+
3. Commit and push child repository work in each repository's own remote.
|
|
725
|
+
4. Review whether the root repository needs a submodule pointer, lock file, integration metadata, or documentation update.
|
|
726
|
+
5. Run service-aware verification for every touched service.
|
|
727
|
+
|
|
728
|
+
\`scale ship <task-id>\` performs the same child-repository boundary check before creating a root commit. Dirty or unpushed child repositories block shipping. The default branch policy follows GitLab Flow: short branches merge to \`dev\`, verified production changes land on \`master\`, and release publishing is triggered by user-created \`vX.Y.Z\` tags. Direct governed commits on \`dev\`, \`master\`, \`main\`, or detached HEAD are blocked. Raw \`git add .\` bypasses this protection and is not allowed for governed MOE workspaces.
|
|
729
|
+
|
|
730
|
+
## Branch Naming
|
|
731
|
+
|
|
732
|
+
Use readable branches with author/platform/scope/date context, for example:
|
|
733
|
+
|
|
734
|
+
\`\`\`text
|
|
735
|
+
feature/maple-codex-storage-policy-0515
|
|
736
|
+
fix/zpei-claude-upload-retry-0515
|
|
737
|
+
codex/moe-workspace-governance-0515
|
|
738
|
+
\`\`\`
|
|
739
|
+
|
|
740
|
+
Protected branches such as \`dev\`, \`main\`, and \`master\` require explicit human authorization before direct pushes.
|
|
197
741
|
`;
|
|
198
742
|
}
|
|
199
743
|
function resourceGovernanceGuide() {
|
|
200
|
-
return `# Resource Governance
|
|
201
|
-
|
|
202
|
-
This project uses SCALE resource governance to keep generated outputs, maintained documentation, task evidence, media, and temporary files from collapsing into one unmanaged document pile.
|
|
203
|
-
|
|
204
|
-
## Source Of Truth
|
|
205
|
-
|
|
206
|
-
- \`.scale/resource-policy.json\`: asset classes, retention rules, owners, module mapping, and size limits.
|
|
207
|
-
- \`.scale/assets.json\`: explicit long-lived resource catalog and source-of-truth declarations.
|
|
208
|
-
- \`docs/modules/\`: maintained module-level product, architecture, API, and operations documentation.
|
|
209
|
-
- \`docs/decisions/\`: ADRs and superseded architecture decisions.
|
|
210
|
-
|
|
211
|
-
## Default Git Policy
|
|
212
|
-
|
|
213
|
-
| Resource | Default policy |
|
|
214
|
-
| --- | --- |
|
|
215
|
-
| Module docs, standards, ADRs, contracts, reusable scripts | Commit |
|
|
216
|
-
| Task worklog artifacts | Review before commit |
|
|
217
|
-
| E2E reports, coverage, screenshots, videos, logs | Ignore or external artifact storage |
|
|
218
|
-
| Temporary scripts and scratch files | Ignore and delete after settlement |
|
|
219
|
-
| Large media | Git LFS or external storage |
|
|
220
|
-
|
|
221
|
-
## Required Finish Behavior
|
|
222
|
-
|
|
223
|
-
Before reporting a M/L/CRITICAL task complete:
|
|
224
|
-
|
|
225
|
-
1. Run \`scale assets scan --json\`.
|
|
226
|
-
2. Run \`scale assets doctor --json\`.
|
|
227
|
-
3. Run \`scale assets settle --task-id <task-id> --artifact-dir <task-dir>\`.
|
|
228
|
-
4. Promote final product or architecture truth into maintained docs.
|
|
229
|
-
5. Keep raw reports, screenshots, videos, and logs out of Git unless they are deliberately promoted.
|
|
230
|
-
6. Delete or archive expired temporary files.
|
|
744
|
+
return `# Resource Governance
|
|
745
|
+
|
|
746
|
+
This project uses SCALE resource governance to keep generated outputs, maintained documentation, task evidence, media, and temporary files from collapsing into one unmanaged document pile.
|
|
747
|
+
|
|
748
|
+
## Source Of Truth
|
|
749
|
+
|
|
750
|
+
- \`.scale/resource-policy.json\`: asset classes, retention rules, owners, module mapping, and size limits.
|
|
751
|
+
- \`.scale/assets.json\`: explicit long-lived resource catalog and source-of-truth declarations.
|
|
752
|
+
- \`docs/modules/\`: maintained module-level product, architecture, API, and operations documentation.
|
|
753
|
+
- \`docs/decisions/\`: ADRs and superseded architecture decisions.
|
|
754
|
+
|
|
755
|
+
## Default Git Policy
|
|
756
|
+
|
|
757
|
+
| Resource | Default policy |
|
|
758
|
+
| --- | --- |
|
|
759
|
+
| Module docs, standards, ADRs, contracts, reusable scripts | Commit |
|
|
760
|
+
| Task worklog artifacts | Review before commit |
|
|
761
|
+
| E2E reports, coverage, screenshots, videos, logs | Ignore or external artifact storage |
|
|
762
|
+
| Temporary scripts and scratch files | Ignore and delete after settlement |
|
|
763
|
+
| Large media | Git LFS or external storage |
|
|
764
|
+
|
|
765
|
+
## Required Finish Behavior
|
|
766
|
+
|
|
767
|
+
Before reporting a M/L/CRITICAL task complete:
|
|
768
|
+
|
|
769
|
+
1. Run \`scale assets scan --json\`.
|
|
770
|
+
2. Run \`scale assets doctor --json\`.
|
|
771
|
+
3. Run \`scale assets settle --task-id <task-id> --artifact-dir <task-dir>\`.
|
|
772
|
+
4. Promote final product or architecture truth into maintained docs.
|
|
773
|
+
5. Keep raw reports, screenshots, videos, and logs out of Git unless they are deliberately promoted.
|
|
774
|
+
6. Delete or archive expired temporary files.
|
|
231
775
|
`;
|
|
232
776
|
}
|
|
233
777
|
function moduleDocsIndex() {
|
|
234
|
-
return `# Module Documentation
|
|
235
|
-
|
|
236
|
-
Use one directory per maintained module:
|
|
237
|
-
|
|
238
|
-
\`\`\`text
|
|
239
|
-
docs/modules/<module>/
|
|
240
|
-
├── README.md
|
|
241
|
-
├── product.md
|
|
242
|
-
├── architecture.md
|
|
243
|
-
├── api.md
|
|
244
|
-
└── operations.md
|
|
245
|
-
\`\`\`
|
|
246
|
-
|
|
247
|
-
Keep task-specific drafts in \`docs/worklog/tasks/\`. Promote only final, durable decisions and user-facing behavior into module documentation.
|
|
778
|
+
return `# Module Documentation
|
|
779
|
+
|
|
780
|
+
Use one directory per maintained module:
|
|
781
|
+
|
|
782
|
+
\`\`\`text
|
|
783
|
+
docs/modules/<module>/
|
|
784
|
+
├── README.md
|
|
785
|
+
├── product.md
|
|
786
|
+
├── architecture.md
|
|
787
|
+
├── api.md
|
|
788
|
+
└── operations.md
|
|
789
|
+
\`\`\`
|
|
790
|
+
|
|
791
|
+
Keep task-specific drafts in \`docs/worklog/tasks/\`. Promote only final, durable decisions and user-facing behavior into module documentation.
|
|
248
792
|
`;
|
|
249
793
|
}
|
|
250
794
|
function resourceGitignoreExample() {
|
|
251
|
-
return `# SCALE resource governance runtime outputs
|
|
252
|
-
.scale/tmp/
|
|
253
|
-
.scale/reports/
|
|
254
|
-
.scale/resource-reports/
|
|
255
|
-
tmp/
|
|
256
|
-
temp/
|
|
257
|
-
test-results/
|
|
258
|
-
playwright-report/
|
|
259
|
-
coverage/
|
|
260
|
-
|
|
261
|
-
# Raw generated media should be promoted deliberately or stored externally
|
|
262
|
-
*.webm
|
|
263
|
-
*.mp4
|
|
264
|
-
*.mov
|
|
265
|
-
*.wav
|
|
266
|
-
*.mp3
|
|
795
|
+
return `# SCALE resource governance runtime outputs
|
|
796
|
+
.scale/tmp/
|
|
797
|
+
.scale/reports/
|
|
798
|
+
.scale/resource-reports/
|
|
799
|
+
tmp/
|
|
800
|
+
temp/
|
|
801
|
+
test-results/
|
|
802
|
+
playwright-report/
|
|
803
|
+
coverage/
|
|
804
|
+
|
|
805
|
+
# Raw generated media should be promoted deliberately or stored externally
|
|
806
|
+
*.webm
|
|
807
|
+
*.mp4
|
|
808
|
+
*.mov
|
|
809
|
+
*.wav
|
|
810
|
+
*.mp3
|
|
811
|
+
`;
|
|
812
|
+
}
|
|
813
|
+
function nodeLibraryGuide() {
|
|
814
|
+
return `# Node Library Workflow
|
|
815
|
+
|
|
816
|
+
This repository uses the latest SCALE repository workflow for Node/npm package delivery.
|
|
817
|
+
|
|
818
|
+
## Command Entry Points
|
|
819
|
+
|
|
820
|
+
\`\`\`bash
|
|
821
|
+
bash scripts/preflight/all.sh
|
|
822
|
+
bash scripts/gates/all.sh --dry-run
|
|
823
|
+
bash scripts/workflow/new-task.sh
|
|
824
|
+
bash scripts/workflow/resume.sh
|
|
825
|
+
bash scripts/workflow/verify.sh --preflight-profile quick
|
|
826
|
+
\`\`\`
|
|
827
|
+
|
|
828
|
+
PowerShell:
|
|
829
|
+
|
|
830
|
+
\`\`\`powershell
|
|
831
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/preflight/all.ps1
|
|
832
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gates/all.ps1 --dry-run
|
|
833
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/workflow/new-task.ps1
|
|
834
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/workflow/resume.ps1
|
|
835
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/workflow/verify.ps1 --preflight-profile quick
|
|
836
|
+
\`\`\`
|
|
837
|
+
|
|
838
|
+
## Default Verification Matrix
|
|
839
|
+
|
|
840
|
+
- quick loop: \`npm run build\`, \`npm run lint\`, \`npm test\`
|
|
841
|
+
- release loop: add \`npm run typecheck\`, \`git diff --check\`, and \`npm pack --dry-run\`
|
|
842
|
+
- product smoke: enable a real probe in \`.scale/product-smoke.json\` instead of treating a health endpoint as completion proof
|
|
843
|
+
|
|
844
|
+
## Branch Policy
|
|
845
|
+
|
|
846
|
+
This repository follows a GitLab Flow variant:
|
|
847
|
+
|
|
848
|
+
\`\`\`text
|
|
849
|
+
feature/fix/docs/chore/codex -> dev -> master -> tag/publish
|
|
850
|
+
\`\`\`
|
|
851
|
+
|
|
852
|
+
Use short-lived branches for governed work. Direct governed commits on \`dev\`, \`master\`, or \`main\` are blocked by SCALE ship rules.
|
|
853
|
+
|
|
854
|
+
## Release Expectations
|
|
855
|
+
|
|
856
|
+
Before a package release or demo handoff:
|
|
857
|
+
|
|
858
|
+
1. Run \`bash scripts/preflight/all.sh\` or the PowerShell equivalent.
|
|
859
|
+
2. Run \`scale preflight --preflight-profile full --json\`.
|
|
860
|
+
3. Run \`npm pack --dry-run\`.
|
|
861
|
+
4. Run \`git diff --check\`.
|
|
862
|
+
5. Confirm runtime evidence and review artifacts for M/L/CRITICAL work.
|
|
863
|
+
`;
|
|
864
|
+
}
|
|
865
|
+
function nodeLibraryPreflightShellScript() {
|
|
866
|
+
return `#!/usr/bin/env bash
|
|
867
|
+
set -euo pipefail
|
|
868
|
+
|
|
869
|
+
SCRIPT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
|
|
870
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
871
|
+
|
|
872
|
+
ERRORS=0
|
|
873
|
+
WARNINGS=0
|
|
874
|
+
|
|
875
|
+
note_ok() { echo "[OK] $*"; }
|
|
876
|
+
note_warn() { echo "[WARN] $*"; WARNINGS=$((WARNINGS + 1)); }
|
|
877
|
+
note_error() { echo "[ERROR] $*"; ERRORS=$((ERRORS + 1)); }
|
|
878
|
+
|
|
879
|
+
find_python() {
|
|
880
|
+
for candidate in python3 python py; do
|
|
881
|
+
if command -v "$candidate" >/dev/null 2>&1; then
|
|
882
|
+
echo "$candidate"
|
|
883
|
+
return 0
|
|
884
|
+
fi
|
|
885
|
+
done
|
|
886
|
+
return 1
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
json_valid() {
|
|
890
|
+
local file="$1"
|
|
891
|
+
if command -v node >/dev/null 2>&1; then
|
|
892
|
+
node -e "JSON.parse(require('fs').readFileSync(process.argv[1], 'utf8').replace(/^\\\\uFEFF/, ''))" "$file" >/dev/null
|
|
893
|
+
return $?
|
|
894
|
+
fi
|
|
895
|
+
local py
|
|
896
|
+
py="$(find_python || true)"
|
|
897
|
+
if [ -n "$py" ]; then
|
|
898
|
+
"$py" -c "import json,sys; json.load(open(sys.argv[1], encoding='utf-8-sig'))" "$file" >/dev/null
|
|
899
|
+
return $?
|
|
900
|
+
fi
|
|
901
|
+
return 2
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
package_script_exists() {
|
|
905
|
+
local script_name="$1"
|
|
906
|
+
node - "$PROJECT_ROOT/package.json" "$script_name" <<'NODE' >/dev/null
|
|
907
|
+
const fs = require('fs');
|
|
908
|
+
const pkgPath = process.argv[2];
|
|
909
|
+
const scriptName = process.argv[3];
|
|
910
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8').replace(/^\\uFEFF/, ''));
|
|
911
|
+
process.exit(pkg.scripts && Object.prototype.hasOwnProperty.call(pkg.scripts, scriptName) ? 0 : 1);
|
|
912
|
+
NODE
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
echo "========================================"
|
|
916
|
+
echo "[PREFLIGHT] node-library workflow"
|
|
917
|
+
echo "========================================"
|
|
918
|
+
echo ""
|
|
919
|
+
|
|
920
|
+
echo "[CHECK] required tools"
|
|
921
|
+
if command -v git >/dev/null 2>&1; then
|
|
922
|
+
note_ok "git"
|
|
923
|
+
else
|
|
924
|
+
note_error "git is required"
|
|
925
|
+
fi
|
|
926
|
+
|
|
927
|
+
if command -v node >/dev/null 2>&1; then
|
|
928
|
+
note_ok "node $(node --version)"
|
|
929
|
+
else
|
|
930
|
+
note_error "node is required"
|
|
931
|
+
fi
|
|
932
|
+
|
|
933
|
+
if command -v npm >/dev/null 2>&1; then
|
|
934
|
+
note_ok "npm $(npm --version)"
|
|
935
|
+
elif command -v pnpm >/dev/null 2>&1; then
|
|
936
|
+
note_ok "pnpm $(pnpm --version)"
|
|
937
|
+
else
|
|
938
|
+
note_error "npm or pnpm is required"
|
|
939
|
+
fi
|
|
940
|
+
echo ""
|
|
941
|
+
|
|
942
|
+
echo "[CHECK] optional tools"
|
|
943
|
+
for tool in bash rg jq gh graphify; do
|
|
944
|
+
if command -v "$tool" >/dev/null 2>&1; then
|
|
945
|
+
note_ok "$tool"
|
|
946
|
+
else
|
|
947
|
+
note_warn "$tool is not installed"
|
|
948
|
+
fi
|
|
949
|
+
done
|
|
950
|
+
PYTHON_BIN="$(find_python || true)"
|
|
951
|
+
if [ -n "$PYTHON_BIN" ]; then
|
|
952
|
+
note_ok "$PYTHON_BIN"
|
|
953
|
+
else
|
|
954
|
+
note_warn "python is not installed"
|
|
955
|
+
fi
|
|
956
|
+
echo ""
|
|
957
|
+
|
|
958
|
+
echo "[CHECK] required directories"
|
|
959
|
+
for dir in \
|
|
960
|
+
".scale" \
|
|
961
|
+
".planning/tasks" \
|
|
962
|
+
"docs/workflow" \
|
|
963
|
+
"docs/workflow/templates" \
|
|
964
|
+
"docs/worklog" \
|
|
965
|
+
"scripts/gates" \
|
|
966
|
+
"scripts/preflight" \
|
|
967
|
+
"scripts/qa" \
|
|
968
|
+
"scripts/workflow" \
|
|
969
|
+
"src" \
|
|
970
|
+
"tests"; do
|
|
971
|
+
if [ -d "$PROJECT_ROOT/$dir" ]; then
|
|
972
|
+
note_ok "$dir"
|
|
973
|
+
else
|
|
974
|
+
note_error "missing directory: $dir"
|
|
975
|
+
fi
|
|
976
|
+
done
|
|
977
|
+
echo ""
|
|
978
|
+
|
|
979
|
+
echo "[CHECK] governance JSON files"
|
|
980
|
+
for file in \
|
|
981
|
+
".scale/verification.json" \
|
|
982
|
+
".scale/workspace.json" \
|
|
983
|
+
".scale/skills.json" \
|
|
984
|
+
".scale/tools.json" \
|
|
985
|
+
".scale/resource-policy.json" \
|
|
986
|
+
".scale/assets.json" \
|
|
987
|
+
".scale/output-policy.json" \
|
|
988
|
+
".scale/product-smoke.json" \
|
|
989
|
+
".scale/engineering-standards.json" \
|
|
990
|
+
".scale/engineering-standards-baseline.json" \
|
|
991
|
+
".scale/frameworks.json" \
|
|
992
|
+
".scale/governance.lock.json"; do
|
|
993
|
+
if [ ! -f "$PROJECT_ROOT/$file" ]; then
|
|
994
|
+
note_error "missing JSON file: $file"
|
|
995
|
+
continue
|
|
996
|
+
fi
|
|
997
|
+
if json_valid "$PROJECT_ROOT/$file"; then
|
|
998
|
+
note_ok "$file"
|
|
999
|
+
else
|
|
1000
|
+
note_error "invalid JSON: $file"
|
|
1001
|
+
fi
|
|
1002
|
+
done
|
|
1003
|
+
echo ""
|
|
1004
|
+
|
|
1005
|
+
echo "[CHECK] key workflow docs"
|
|
1006
|
+
for file in \
|
|
1007
|
+
"docs/workflow/README.md" \
|
|
1008
|
+
"docs/workflow/node-library.md" \
|
|
1009
|
+
"docs/worklog/metrics.md"; do
|
|
1010
|
+
if [ -f "$PROJECT_ROOT/$file" ]; then
|
|
1011
|
+
note_ok "$file"
|
|
1012
|
+
else
|
|
1013
|
+
note_error "missing file: $file"
|
|
1014
|
+
fi
|
|
1015
|
+
done
|
|
1016
|
+
echo ""
|
|
1017
|
+
|
|
1018
|
+
echo "[CHECK] package scripts"
|
|
1019
|
+
for script_name in build lint test typecheck; do
|
|
1020
|
+
if package_script_exists "$script_name"; then
|
|
1021
|
+
note_ok "package.json scripts.$script_name"
|
|
1022
|
+
else
|
|
1023
|
+
note_error "missing package.json script: $script_name"
|
|
1024
|
+
fi
|
|
1025
|
+
done
|
|
1026
|
+
echo ""
|
|
1027
|
+
|
|
1028
|
+
echo "[CHECK] gate wrappers"
|
|
1029
|
+
if [ -f "$PROJECT_ROOT/scripts/gates/all.sh" ] && bash -n "$PROJECT_ROOT/scripts/gates/all.sh"; then
|
|
1030
|
+
note_ok "scripts/gates/all.sh syntax"
|
|
1031
|
+
else
|
|
1032
|
+
note_error "scripts/gates/all.sh is missing or invalid"
|
|
1033
|
+
fi
|
|
1034
|
+
echo ""
|
|
1035
|
+
|
|
1036
|
+
echo "========================================"
|
|
1037
|
+
if [ "$ERRORS" -eq 0 ]; then
|
|
1038
|
+
echo "[PREFLIGHT] PASSED with $WARNINGS warning(s)"
|
|
1039
|
+
exit 0
|
|
1040
|
+
fi
|
|
1041
|
+
|
|
1042
|
+
echo "[PREFLIGHT] FAILED with $ERRORS error(s), $WARNINGS warning(s)"
|
|
1043
|
+
exit 1
|
|
1044
|
+
`;
|
|
1045
|
+
}
|
|
1046
|
+
function nodeLibraryPreflightPowerShellScript() {
|
|
1047
|
+
return `$ErrorActionPreference = 'Stop'
|
|
1048
|
+
if (Get-Variable -Name PSNativeCommandUseErrorActionPreference -ErrorAction SilentlyContinue) {
|
|
1049
|
+
$PSNativeCommandUseErrorActionPreference = $false
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
$ProjectRoot = (Resolve-Path (Join-Path $PSScriptRoot '..\\..')).Path
|
|
1053
|
+
$Errors = 0
|
|
1054
|
+
$Warnings = 0
|
|
1055
|
+
|
|
1056
|
+
function Note-Ok([string]$Message) {
|
|
1057
|
+
Write-Host "[OK] $Message"
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
function Note-Warn([string]$Message) {
|
|
1061
|
+
$script:Warnings++
|
|
1062
|
+
Write-Host "[WARN] $Message"
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
function Note-Error([string]$Message) {
|
|
1066
|
+
$script:Errors++
|
|
1067
|
+
Write-Host "[ERROR] $Message"
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
function Test-JsonFile([string]$Path) {
|
|
1071
|
+
try {
|
|
1072
|
+
$raw = Get-Content -Raw $Path
|
|
1073
|
+
$clean = $raw.TrimStart([char]0xFEFF)
|
|
1074
|
+
$null = $clean | ConvertFrom-Json
|
|
1075
|
+
return $true
|
|
1076
|
+
} catch {
|
|
1077
|
+
return $false
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
function Test-PackageScript([string]$Name) {
|
|
1082
|
+
$pkg = Get-Content -Raw (Join-Path $ProjectRoot 'package.json') | ConvertFrom-Json
|
|
1083
|
+
return $null -ne $pkg.scripts.$Name
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
Write-Host '========================================'
|
|
1087
|
+
Write-Host '[PREFLIGHT] node-library workflow'
|
|
1088
|
+
Write-Host '========================================'
|
|
1089
|
+
Write-Host ''
|
|
1090
|
+
|
|
1091
|
+
Write-Host '[CHECK] required tools'
|
|
1092
|
+
if (Get-Command git -ErrorAction SilentlyContinue) {
|
|
1093
|
+
Note-Ok 'git'
|
|
1094
|
+
} else {
|
|
1095
|
+
Note-Error 'git is required'
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
$Node = Get-Command node -ErrorAction SilentlyContinue
|
|
1099
|
+
if ($Node) {
|
|
1100
|
+
Note-Ok ("node " + (node --version))
|
|
1101
|
+
} else {
|
|
1102
|
+
Note-Error 'node is required'
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
$Npm = Get-Command npm -ErrorAction SilentlyContinue
|
|
1106
|
+
$Pnpm = Get-Command pnpm -ErrorAction SilentlyContinue
|
|
1107
|
+
if ($Npm) {
|
|
1108
|
+
Note-Ok ("npm " + (npm --version))
|
|
1109
|
+
} elseif ($Pnpm) {
|
|
1110
|
+
Note-Ok ("pnpm " + (pnpm --version))
|
|
1111
|
+
} else {
|
|
1112
|
+
Note-Error 'npm or pnpm is required'
|
|
1113
|
+
}
|
|
1114
|
+
Write-Host ''
|
|
1115
|
+
|
|
1116
|
+
Write-Host '[CHECK] optional tools'
|
|
1117
|
+
foreach ($Tool in @('bash', 'rg', 'jq', 'gh', 'graphify', 'python', 'python3')) {
|
|
1118
|
+
if (Get-Command $Tool -ErrorAction SilentlyContinue) {
|
|
1119
|
+
Note-Ok $Tool
|
|
1120
|
+
} else {
|
|
1121
|
+
Note-Warn "$Tool is not installed"
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
Write-Host ''
|
|
1125
|
+
|
|
1126
|
+
Write-Host '[CHECK] required directories'
|
|
1127
|
+
foreach ($Dir in @(
|
|
1128
|
+
'.scale',
|
|
1129
|
+
'.planning\\tasks',
|
|
1130
|
+
'docs\\workflow',
|
|
1131
|
+
'docs\\workflow\\templates',
|
|
1132
|
+
'docs\\worklog',
|
|
1133
|
+
'scripts\\gates',
|
|
1134
|
+
'scripts\\preflight',
|
|
1135
|
+
'scripts\\qa',
|
|
1136
|
+
'scripts\\workflow',
|
|
1137
|
+
'src',
|
|
1138
|
+
'tests'
|
|
1139
|
+
)) {
|
|
1140
|
+
if (Test-Path (Join-Path $ProjectRoot $Dir)) {
|
|
1141
|
+
Note-Ok $Dir
|
|
1142
|
+
} else {
|
|
1143
|
+
Note-Error "missing directory: $Dir"
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
Write-Host ''
|
|
1147
|
+
|
|
1148
|
+
Write-Host '[CHECK] governance JSON files'
|
|
1149
|
+
foreach ($File in @(
|
|
1150
|
+
'.scale\\verification.json',
|
|
1151
|
+
'.scale\\workspace.json',
|
|
1152
|
+
'.scale\\skills.json',
|
|
1153
|
+
'.scale\\tools.json',
|
|
1154
|
+
'.scale\\resource-policy.json',
|
|
1155
|
+
'.scale\\assets.json',
|
|
1156
|
+
'.scale\\output-policy.json',
|
|
1157
|
+
'.scale\\product-smoke.json',
|
|
1158
|
+
'.scale\\engineering-standards.json',
|
|
1159
|
+
'.scale\\engineering-standards-baseline.json',
|
|
1160
|
+
'.scale\\frameworks.json',
|
|
1161
|
+
'.scale\\governance.lock.json'
|
|
1162
|
+
)) {
|
|
1163
|
+
$Path = Join-Path $ProjectRoot $File
|
|
1164
|
+
if (-not (Test-Path $Path)) {
|
|
1165
|
+
Note-Error "missing JSON file: $File"
|
|
1166
|
+
continue
|
|
1167
|
+
}
|
|
1168
|
+
if (Test-JsonFile $Path) {
|
|
1169
|
+
Note-Ok $File
|
|
1170
|
+
} else {
|
|
1171
|
+
Note-Error "invalid JSON: $File"
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
Write-Host ''
|
|
1175
|
+
|
|
1176
|
+
Write-Host '[CHECK] key workflow docs'
|
|
1177
|
+
foreach ($File in @(
|
|
1178
|
+
'docs\\workflow\\README.md',
|
|
1179
|
+
'docs\\workflow\\node-library.md',
|
|
1180
|
+
'docs\\worklog\\metrics.md'
|
|
1181
|
+
)) {
|
|
1182
|
+
if (Test-Path (Join-Path $ProjectRoot $File)) {
|
|
1183
|
+
Note-Ok $File
|
|
1184
|
+
} else {
|
|
1185
|
+
Note-Error "missing file: $File"
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
Write-Host ''
|
|
1189
|
+
|
|
1190
|
+
Write-Host '[CHECK] package scripts'
|
|
1191
|
+
foreach ($ScriptName in @('build', 'lint', 'test', 'typecheck')) {
|
|
1192
|
+
if (Test-PackageScript $ScriptName) {
|
|
1193
|
+
Note-Ok "package.json scripts.$ScriptName"
|
|
1194
|
+
} else {
|
|
1195
|
+
Note-Error "missing package.json script: $ScriptName"
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
Write-Host ''
|
|
1199
|
+
|
|
1200
|
+
Write-Host '[CHECK] gate wrappers'
|
|
1201
|
+
$GateScript = Join-Path $ProjectRoot 'scripts\\gates\\all.ps1'
|
|
1202
|
+
if (Test-Path $GateScript) {
|
|
1203
|
+
$null = [System.Management.Automation.Language.Parser]::ParseFile($GateScript, [ref]$null, [ref]$null)
|
|
1204
|
+
if ($?) {
|
|
1205
|
+
Note-Ok 'scripts/gates/all.ps1 syntax'
|
|
1206
|
+
} else {
|
|
1207
|
+
Note-Error 'scripts/gates/all.ps1 is invalid'
|
|
1208
|
+
}
|
|
1209
|
+
} else {
|
|
1210
|
+
Note-Error 'missing scripts/gates/all.ps1'
|
|
1211
|
+
}
|
|
1212
|
+
Write-Host ''
|
|
1213
|
+
|
|
1214
|
+
Write-Host '========================================'
|
|
1215
|
+
if ($Errors -eq 0) {
|
|
1216
|
+
Write-Host "[PREFLIGHT] PASSED with $Warnings warning(s)"
|
|
1217
|
+
exit 0
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
Write-Host "[PREFLIGHT] FAILED with $Errors error(s), $Warnings warning(s)"
|
|
1221
|
+
exit 1
|
|
1222
|
+
`;
|
|
1223
|
+
}
|
|
1224
|
+
function scaleEngineRepoWorkspaceJson() {
|
|
1225
|
+
return `${JSON.stringify({
|
|
1226
|
+
version: 1,
|
|
1227
|
+
topology: 'single',
|
|
1228
|
+
repositories: [
|
|
1229
|
+
{
|
|
1230
|
+
name: 'root',
|
|
1231
|
+
path: '.',
|
|
1232
|
+
role: 'root',
|
|
1233
|
+
required: true,
|
|
1234
|
+
},
|
|
1235
|
+
],
|
|
1236
|
+
branchPolicy: {
|
|
1237
|
+
mode: 'gitlab-flow',
|
|
1238
|
+
integrationBranch: 'dev',
|
|
1239
|
+
productionBranch: 'master',
|
|
1240
|
+
protectedBranches: ['dev', 'master', 'main'],
|
|
1241
|
+
featurePrefixes: ['feature/', 'feat/', 'fix/', 'chore/', 'docs/', 'codex/'],
|
|
1242
|
+
releasePrefixes: ['release/'],
|
|
1243
|
+
hotfixPrefixes: ['hotfix/'],
|
|
1244
|
+
requireAuthorScopeDate: true,
|
|
1245
|
+
},
|
|
1246
|
+
finishPolicy: {
|
|
1247
|
+
requireCleanRepositories: true,
|
|
1248
|
+
requirePushedBranches: true,
|
|
1249
|
+
requireRootPointerUpdate: false,
|
|
1250
|
+
requireReviewArtifacts: false,
|
|
1251
|
+
},
|
|
1252
|
+
}, null, 2)}\n`;
|
|
1253
|
+
}
|
|
1254
|
+
function scaleEngineRepoProjectJson() {
|
|
1255
|
+
return `${JSON.stringify({
|
|
1256
|
+
version: '1.1',
|
|
1257
|
+
stack: 'auto',
|
|
1258
|
+
coverage_threshold: 80,
|
|
1259
|
+
profiles: {
|
|
1260
|
+
scaffold: {
|
|
1261
|
+
description: 'Validate the repository workflow scaffold itself.',
|
|
1262
|
+
checks: ['lint'],
|
|
1263
|
+
},
|
|
1264
|
+
default: {
|
|
1265
|
+
description: 'Validate the scale-engine repository.',
|
|
1266
|
+
services: ['root'],
|
|
1267
|
+
checks: ['lint', 'typecheck', 'test', 'build'],
|
|
1268
|
+
},
|
|
1269
|
+
all: {
|
|
1270
|
+
description: 'Run the full repository validation surface.',
|
|
1271
|
+
services: '*',
|
|
1272
|
+
checks: ['lint', 'typecheck', 'test', 'build', 'security'],
|
|
1273
|
+
},
|
|
1274
|
+
},
|
|
1275
|
+
services: {
|
|
1276
|
+
root: {
|
|
1277
|
+
path: '.',
|
|
1278
|
+
stack: 'node',
|
|
1279
|
+
required: true,
|
|
1280
|
+
commands: {
|
|
1281
|
+
typecheck: 'npm run typecheck',
|
|
1282
|
+
},
|
|
1283
|
+
},
|
|
1284
|
+
},
|
|
1285
|
+
stacks: {
|
|
1286
|
+
node: {
|
|
1287
|
+
detect: ['package.json'],
|
|
1288
|
+
commands: {
|
|
1289
|
+
build: 'npm run build',
|
|
1290
|
+
lint: 'npm run lint',
|
|
1291
|
+
typecheck: 'npm run typecheck',
|
|
1292
|
+
test: 'npm run test',
|
|
1293
|
+
coverage: 'npm run coverage',
|
|
1294
|
+
security: 'npm audit --audit-level=high',
|
|
1295
|
+
},
|
|
1296
|
+
required_tools: {
|
|
1297
|
+
build: ['npm'],
|
|
1298
|
+
lint: ['npm'],
|
|
1299
|
+
typecheck: ['npm'],
|
|
1300
|
+
test: ['npm'],
|
|
1301
|
+
coverage: ['npm'],
|
|
1302
|
+
security: ['npm'],
|
|
1303
|
+
},
|
|
1304
|
+
},
|
|
1305
|
+
},
|
|
1306
|
+
}, null, 2)}\n`;
|
|
1307
|
+
}
|
|
1308
|
+
function scaleEngineRepoClaudeSettings() {
|
|
1309
|
+
return `${JSON.stringify({
|
|
1310
|
+
permissions: {
|
|
1311
|
+
allow: [
|
|
1312
|
+
'Read',
|
|
1313
|
+
'Grep',
|
|
1314
|
+
'Glob',
|
|
1315
|
+
'WebSearch',
|
|
1316
|
+
'WebFetch',
|
|
1317
|
+
'Agent',
|
|
1318
|
+
'Skill',
|
|
1319
|
+
'Bash(rtk *: *)',
|
|
1320
|
+
'Bash(bash scripts/*: *)',
|
|
1321
|
+
'Bash(bash scripts/hooks/*: *)',
|
|
1322
|
+
'Bash(bash .claude/hooks/*: *)',
|
|
1323
|
+
'Bash(powershell -NoProfile -ExecutionPolicy Bypass -File scripts/*: *)',
|
|
1324
|
+
'Write(.claude/**)',
|
|
1325
|
+
'Write(.agent/**)',
|
|
1326
|
+
'Write(.scale/**)',
|
|
1327
|
+
'Write(docs/**)',
|
|
1328
|
+
'Write(scripts/**)',
|
|
1329
|
+
'Write(README.md)',
|
|
1330
|
+
'Write(AGENTS.md)',
|
|
1331
|
+
'Write(CLAUDE.md)',
|
|
1332
|
+
'Write(Makefile)',
|
|
1333
|
+
'Write(.gitignore)',
|
|
1334
|
+
'Edit(.claude/**)',
|
|
1335
|
+
'Edit(.agent/**)',
|
|
1336
|
+
'Edit(.scale/**)',
|
|
1337
|
+
'Edit(docs/**)',
|
|
1338
|
+
'Edit(scripts/**)',
|
|
1339
|
+
'Edit(README.md)',
|
|
1340
|
+
'Edit(AGENTS.md)',
|
|
1341
|
+
'Edit(CLAUDE.md)',
|
|
1342
|
+
'Edit(Makefile)',
|
|
1343
|
+
'Edit(.gitignore)',
|
|
1344
|
+
],
|
|
1345
|
+
deny: [
|
|
1346
|
+
'Write(.env*)',
|
|
1347
|
+
'Edit(.env*)',
|
|
1348
|
+
'Write(*secret*)',
|
|
1349
|
+
'Edit(*secret*)',
|
|
1350
|
+
'Write(*token*)',
|
|
1351
|
+
'Edit(*token*)',
|
|
1352
|
+
'Write(*password*)',
|
|
1353
|
+
'Edit(*password*)',
|
|
1354
|
+
],
|
|
1355
|
+
},
|
|
1356
|
+
hooks: {
|
|
1357
|
+
SessionStart: [
|
|
1358
|
+
{
|
|
1359
|
+
matcher: '',
|
|
1360
|
+
command: 'bash .claude/hooks/session-start-reminder.sh',
|
|
1361
|
+
timeout: 3000,
|
|
1362
|
+
description: 'Show concise scale-engine workflow entry points.',
|
|
1363
|
+
},
|
|
1364
|
+
],
|
|
1365
|
+
PreToolUse: [
|
|
1366
|
+
{
|
|
1367
|
+
matcher: 'Write|Edit|MultiEdit',
|
|
1368
|
+
command: 'bash scripts/hooks/check-dangerous-file.sh',
|
|
1369
|
+
timeout: 3000,
|
|
1370
|
+
description: 'Block edits to secrets, runtime databases, and generated dependency output.',
|
|
1371
|
+
},
|
|
1372
|
+
{
|
|
1373
|
+
matcher: 'Write|Edit|MultiEdit',
|
|
1374
|
+
command: 'bash scripts/hooks/check-explore.sh',
|
|
1375
|
+
timeout: 3000,
|
|
1376
|
+
description: 'Require recorded exploration before medium or larger source changes.',
|
|
1377
|
+
},
|
|
1378
|
+
{
|
|
1379
|
+
matcher: 'Write|Edit|MultiEdit',
|
|
1380
|
+
command: 'bash scripts/hooks/check-tdd.sh',
|
|
1381
|
+
timeout: 3000,
|
|
1382
|
+
description: 'Warn when TypeScript implementation changes lack nearby test evidence.',
|
|
1383
|
+
},
|
|
1384
|
+
{
|
|
1385
|
+
matcher: 'Write|Edit|MultiEdit',
|
|
1386
|
+
command: 'bash .claude/hooks/gate-execute-phase.sh',
|
|
1387
|
+
timeout: 3000,
|
|
1388
|
+
description: 'Route code edits through the repository workflow phase gates.',
|
|
1389
|
+
},
|
|
1390
|
+
],
|
|
1391
|
+
Stop: [
|
|
1392
|
+
{
|
|
1393
|
+
matcher: '',
|
|
1394
|
+
command: 'bash .claude/hooks/session-end-gate.sh',
|
|
1395
|
+
timeout: 5000,
|
|
1396
|
+
description: 'Summarize uncommitted code changes and verification expectations before handoff.',
|
|
1397
|
+
},
|
|
1398
|
+
],
|
|
1399
|
+
},
|
|
1400
|
+
}, null, 2)}\n`;
|
|
1401
|
+
}
|
|
1402
|
+
function shellScript(lines) {
|
|
1403
|
+
return `${lines.join('\n')}\n`;
|
|
1404
|
+
}
|
|
1405
|
+
function scaleEngineSessionStartHook() {
|
|
1406
|
+
return shellScript([
|
|
1407
|
+
'#!/usr/bin/env bash',
|
|
1408
|
+
'set -euo pipefail',
|
|
1409
|
+
'',
|
|
1410
|
+
'echo "[scale-engine] workflow: read AGENTS.md, use rtk for shell commands, run make preflight or scripts/preflight/all.ps1 before handoff."',
|
|
1411
|
+
]);
|
|
1412
|
+
}
|
|
1413
|
+
function scaleEngineExecutePhaseHook() {
|
|
1414
|
+
return shellScript([
|
|
1415
|
+
'#!/usr/bin/env bash',
|
|
1416
|
+
'set -euo pipefail',
|
|
1417
|
+
'',
|
|
1418
|
+
'ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"',
|
|
1419
|
+
'FILE_PATH="${CLAUDE_FILE_PATH:-${1:-}}"',
|
|
1420
|
+
'',
|
|
1421
|
+
'if [ -z "$FILE_PATH" ]; then',
|
|
1422
|
+
' exit 0',
|
|
1423
|
+
'fi',
|
|
1424
|
+
'',
|
|
1425
|
+
'case "$FILE_PATH" in',
|
|
1426
|
+
' src/*.ts|src/**/*.ts|tests/*.ts|tests/**/*.ts) ;;',
|
|
1427
|
+
' *) exit 0 ;;',
|
|
1428
|
+
'esac',
|
|
1429
|
+
'',
|
|
1430
|
+
'STATE_FILE="$ROOT/.agent/state/current.json"',
|
|
1431
|
+
'if [ ! -f "$STATE_FILE" ]; then',
|
|
1432
|
+
' echo "[scale-engine] workflow state is not initialized. Run: bash scripts/workflow/new-task.sh <task-slug> M"',
|
|
1433
|
+
' exit 0',
|
|
1434
|
+
'fi',
|
|
1435
|
+
'',
|
|
1436
|
+
'if command -v python3 >/dev/null 2>&1; then',
|
|
1437
|
+
' PHASE="$(python3 "$ROOT/scripts/lib/workflow_state.py" get "$STATE_FILE" phase unknown 2>/dev/null || echo unknown)"',
|
|
1438
|
+
'else',
|
|
1439
|
+
' PHASE="unknown"',
|
|
1440
|
+
'fi',
|
|
1441
|
+
'',
|
|
1442
|
+
'case "$PHASE" in',
|
|
1443
|
+
' explore|plan|execute|verify|review|ship|done|unknown) exit 0 ;;',
|
|
1444
|
+
' *)',
|
|
1445
|
+
' echo "[scale-engine] unexpected workflow phase: $PHASE"',
|
|
1446
|
+
' exit 0',
|
|
1447
|
+
' ;;',
|
|
1448
|
+
'esac',
|
|
1449
|
+
]);
|
|
1450
|
+
}
|
|
1451
|
+
function scaleEngineSessionEndHook() {
|
|
1452
|
+
return shellScript([
|
|
1453
|
+
'#!/usr/bin/env bash',
|
|
1454
|
+
'set -euo pipefail',
|
|
1455
|
+
'',
|
|
1456
|
+
'ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"',
|
|
1457
|
+
'cd "$ROOT"',
|
|
1458
|
+
'',
|
|
1459
|
+
'CHANGED_CODE="$(git diff --name-only -- src tests package.json package-lock.json 2>/dev/null | head -20 || true)"',
|
|
1460
|
+
'if [ -n "$CHANGED_CODE" ]; then',
|
|
1461
|
+
' echo "[scale-engine] changed code/package files:"',
|
|
1462
|
+
' echo "$CHANGED_CODE"',
|
|
1463
|
+
' echo "[scale-engine] expected verification: npm run typecheck and targeted Vitest or scripts/preflight/all.ps1."',
|
|
1464
|
+
'fi',
|
|
1465
|
+
'',
|
|
1466
|
+
'exit 0',
|
|
1467
|
+
]);
|
|
1468
|
+
}
|
|
1469
|
+
function scaleEngineDangerousFileHook() {
|
|
1470
|
+
return shellScript([
|
|
1471
|
+
'#!/usr/bin/env bash',
|
|
1472
|
+
'set -euo pipefail',
|
|
1473
|
+
'',
|
|
1474
|
+
'FILE_PATH="${CLAUDE_FILE_PATH:-${1:-}}"',
|
|
1475
|
+
'if [ -z "$FILE_PATH" ]; then',
|
|
1476
|
+
' exit 0',
|
|
1477
|
+
'fi',
|
|
1478
|
+
'',
|
|
1479
|
+
'case "$FILE_PATH" in',
|
|
1480
|
+
' *.env|*.env.*|*.key|*.pem|*.p12|*.crt|*secret*|*credential*|*password*|*token*)',
|
|
1481
|
+
' echo "[scale-engine] blocked sensitive file edit: $FILE_PATH"',
|
|
1482
|
+
' exit 2',
|
|
1483
|
+
' ;;',
|
|
1484
|
+
' node_modules/*|dist/*|coverage/*|test-results/*|playwright-report/*|.scale/events/*|.scale/evidence/*|.scale/state/*|.scale/*.db*)',
|
|
1485
|
+
' echo "[scale-engine] blocked generated/runtime file edit: $FILE_PATH"',
|
|
1486
|
+
' exit 2',
|
|
1487
|
+
' ;;',
|
|
1488
|
+
'esac',
|
|
1489
|
+
'',
|
|
1490
|
+
'exit 0',
|
|
1491
|
+
]);
|
|
1492
|
+
}
|
|
1493
|
+
function scaleEngineExploreHook() {
|
|
1494
|
+
return shellScript([
|
|
1495
|
+
'#!/usr/bin/env bash',
|
|
1496
|
+
'set -euo pipefail',
|
|
1497
|
+
'',
|
|
1498
|
+
'ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"',
|
|
1499
|
+
'FILE_PATH="${CLAUDE_FILE_PATH:-${1:-}}"',
|
|
1500
|
+
'STATE_FILE="$ROOT/.agent/state/current.json"',
|
|
1501
|
+
'PY_STATE="$ROOT/scripts/lib/workflow_state.py"',
|
|
1502
|
+
'',
|
|
1503
|
+
'if [ -z "$FILE_PATH" ]; then',
|
|
1504
|
+
' exit 0',
|
|
1505
|
+
'fi',
|
|
1506
|
+
'',
|
|
1507
|
+
'case "$FILE_PATH" in',
|
|
1508
|
+
' src/*.ts|src/**/*.ts|tests/*.ts|tests/**/*.ts) ;;',
|
|
1509
|
+
' *) exit 0 ;;',
|
|
1510
|
+
'esac',
|
|
1511
|
+
'',
|
|
1512
|
+
'if [ ! -f "$STATE_FILE" ]; then',
|
|
1513
|
+
' echo "[scale-engine] no workflow state found. For M/L work run: bash scripts/workflow/new-task.sh <task-slug> M"',
|
|
1514
|
+
' exit 0',
|
|
1515
|
+
'fi',
|
|
1516
|
+
'',
|
|
1517
|
+
'if ! command -v python3 >/dev/null 2>&1; then',
|
|
1518
|
+
' exit 0',
|
|
1519
|
+
'fi',
|
|
1520
|
+
'',
|
|
1521
|
+
'LEVEL="$(python3 "$PY_STATE" get "$STATE_FILE" level S 2>/dev/null || echo S)"',
|
|
1522
|
+
'FILE_COUNT="$(python3 "$PY_STATE" get "$STATE_FILE" file_count 0 2>/dev/null || echo 0)"',
|
|
1523
|
+
'',
|
|
1524
|
+
'case "$LEVEL" in',
|
|
1525
|
+
' M|L|CRITICAL)',
|
|
1526
|
+
' if [ "${FILE_COUNT:-0}" -lt 3 ]; then',
|
|
1527
|
+
' echo "[scale-engine] M/L/CRITICAL work should record exploration of at least 3 relevant files before editing source."',
|
|
1528
|
+
' echo "[scale-engine] run: bash scripts/workflow/explore.sh <files...> \'<main contradiction>\'"',
|
|
1529
|
+
' exit 2',
|
|
1530
|
+
' fi',
|
|
1531
|
+
' ;;',
|
|
1532
|
+
'esac',
|
|
1533
|
+
'',
|
|
1534
|
+
'exit 0',
|
|
1535
|
+
]);
|
|
1536
|
+
}
|
|
1537
|
+
function scaleEngineTddHook() {
|
|
1538
|
+
return shellScript([
|
|
1539
|
+
'#!/usr/bin/env bash',
|
|
1540
|
+
'set -euo pipefail',
|
|
1541
|
+
'',
|
|
1542
|
+
'FILE_PATH="${CLAUDE_FILE_PATH:-${1:-}}"',
|
|
1543
|
+
'if [ -z "$FILE_PATH" ]; then',
|
|
1544
|
+
' exit 0',
|
|
1545
|
+
'fi',
|
|
1546
|
+
'',
|
|
1547
|
+
'case "$FILE_PATH" in',
|
|
1548
|
+
' src/*.ts|src/**/*.ts) ;;',
|
|
1549
|
+
' *) exit 0 ;;',
|
|
1550
|
+
'esac',
|
|
1551
|
+
'',
|
|
1552
|
+
'case "$FILE_PATH" in',
|
|
1553
|
+
' *.test.ts|*.spec.ts|src/api/cli.ts) exit 0 ;;',
|
|
1554
|
+
'esac',
|
|
1555
|
+
'',
|
|
1556
|
+
'BASENAME="$(basename "$FILE_PATH" .ts)"',
|
|
1557
|
+
'if ! find tests src -name "*${BASENAME}*.test.ts" -o -name "*${BASENAME}*.spec.ts" 2>/dev/null | grep -q .; then',
|
|
1558
|
+
' echo "[scale-engine] test evidence warning: changed $FILE_PATH without a nearby *${BASENAME}*.test.ts file."',
|
|
1559
|
+
'fi',
|
|
1560
|
+
'',
|
|
1561
|
+
'exit 0',
|
|
1562
|
+
]);
|
|
1563
|
+
}
|
|
1564
|
+
function scaleEngineContextHook() {
|
|
1565
|
+
return shellScript([
|
|
1566
|
+
'#!/usr/bin/env bash',
|
|
1567
|
+
'set -euo pipefail',
|
|
1568
|
+
'',
|
|
1569
|
+
'FILE_PATH="${CLAUDE_FILE_PATH:-${1:-}}"',
|
|
1570
|
+
'if [ -z "$FILE_PATH" ] || [ ! -f "$FILE_PATH" ]; then',
|
|
1571
|
+
' exit 0',
|
|
1572
|
+
'fi',
|
|
1573
|
+
'',
|
|
1574
|
+
'case "$FILE_PATH" in',
|
|
1575
|
+
' src/*.ts|src/**/*.ts) ;;',
|
|
1576
|
+
' *) exit 0 ;;',
|
|
1577
|
+
'esac',
|
|
1578
|
+
'',
|
|
1579
|
+
'if grep -Eq "(fetch\\\\(|execa\\\\(|spawn\\\\(|execFile\\\\(|readFileSync\\\\(|writeFileSync\\\\()" "$FILE_PATH" 2>/dev/null; then',
|
|
1580
|
+
' if ! grep -Eq "(timeout|AbortController|try \\\\{|catch \\\\{|safe|validate|z\\\\.)" "$FILE_PATH" 2>/dev/null; then',
|
|
1581
|
+
' echo "[scale-engine] context warning: $FILE_PATH touches IO/process APIs; check timeout, validation, and error handling."',
|
|
1582
|
+
' fi',
|
|
1583
|
+
'fi',
|
|
1584
|
+
'',
|
|
1585
|
+
'exit 0',
|
|
1586
|
+
]);
|
|
1587
|
+
}
|
|
1588
|
+
function scaleEngineRepoClaudeWorkflow() {
|
|
1589
|
+
return `${JSON.stringify({
|
|
1590
|
+
version: '2.0',
|
|
1591
|
+
project: 'scale-engine',
|
|
1592
|
+
description: 'Repository workflow for developing scale-engine itself.',
|
|
1593
|
+
currentPhase: 'idle',
|
|
1594
|
+
currentTier: 'standard',
|
|
1595
|
+
phaseHistory: [],
|
|
1596
|
+
gates: {
|
|
1597
|
+
G1_explore: {
|
|
1598
|
+
status: 'pending',
|
|
1599
|
+
description: 'Explore current repo state and record the main contradiction.',
|
|
1600
|
+
verification: 'bash scripts/gates/G1-verify.sh',
|
|
1601
|
+
autoCheck: false,
|
|
1602
|
+
verifiedAt: null,
|
|
1603
|
+
},
|
|
1604
|
+
G2_plan: {
|
|
1605
|
+
status: 'pending',
|
|
1606
|
+
description: 'Plan includes scope, risk, rollback, and reality check.',
|
|
1607
|
+
verification: 'bash scripts/gates/G2-verify.sh',
|
|
1608
|
+
autoCheck: false,
|
|
1609
|
+
verifiedAt: null,
|
|
1610
|
+
},
|
|
1611
|
+
G3_tdd: {
|
|
1612
|
+
status: 'pending',
|
|
1613
|
+
description: 'Behavior changes in src/ should be accompanied by test changes.',
|
|
1614
|
+
verification: 'bash scripts/gates/G3-verify.sh',
|
|
1615
|
+
autoCheck: true,
|
|
1616
|
+
verifiedAt: null,
|
|
1617
|
+
},
|
|
1618
|
+
G4_lint: {
|
|
1619
|
+
status: 'pending',
|
|
1620
|
+
description: 'Workflow scripts parse and required helper files exist.',
|
|
1621
|
+
verification: 'bash scripts/gates/G4-verify.sh',
|
|
1622
|
+
autoCheck: true,
|
|
1623
|
+
verifiedAt: null,
|
|
1624
|
+
},
|
|
1625
|
+
G5_test: {
|
|
1626
|
+
status: 'pending',
|
|
1627
|
+
description: 'Repository lint, typecheck, test, and build pass.',
|
|
1628
|
+
verification: 'bash scripts/gates/G5-verify.sh',
|
|
1629
|
+
autoCheck: true,
|
|
1630
|
+
verifiedAt: null,
|
|
1631
|
+
},
|
|
1632
|
+
G6_artifacts: {
|
|
1633
|
+
status: 'pending',
|
|
1634
|
+
description: 'Task evidence and diff hygiene are complete.',
|
|
1635
|
+
verification: 'bash scripts/gates/G6-verify.sh',
|
|
1636
|
+
autoCheck: true,
|
|
1637
|
+
verifiedAt: null,
|
|
1638
|
+
},
|
|
1639
|
+
G7_security: {
|
|
1640
|
+
status: 'pending',
|
|
1641
|
+
description: 'Security validation passes or is explicitly blocked.',
|
|
1642
|
+
verification: 'bash scripts/gates/G7-verify.sh',
|
|
1643
|
+
autoCheck: false,
|
|
1644
|
+
verifiedAt: null,
|
|
1645
|
+
},
|
|
1646
|
+
G8_docs: {
|
|
1647
|
+
status: 'pending',
|
|
1648
|
+
description: 'Changed markdown and workflow artifacts meet documentation hygiene rules.',
|
|
1649
|
+
verification: 'bash scripts/gates/G8-verify.sh',
|
|
1650
|
+
autoCheck: true,
|
|
1651
|
+
verifiedAt: null,
|
|
1652
|
+
},
|
|
1653
|
+
},
|
|
1654
|
+
tierConfig: {
|
|
1655
|
+
sandbox: {
|
|
1656
|
+
flow: ['execute', 'verify'],
|
|
1657
|
+
gates: ['G4', 'G5'],
|
|
1658
|
+
description: 'Small local changes.',
|
|
1659
|
+
},
|
|
1660
|
+
standard: {
|
|
1661
|
+
flow: ['explore', 'plan', 'execute', 'verify', 'consolidate'],
|
|
1662
|
+
gates: ['G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G8'],
|
|
1663
|
+
description: 'Default repository workflow.',
|
|
1664
|
+
},
|
|
1665
|
+
critical: {
|
|
1666
|
+
flow: ['explore', 'plan', 'review', 'execute', 'verify', 'security', 'consolidate'],
|
|
1667
|
+
gates: ['G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7', 'G8'],
|
|
1668
|
+
description: 'Release, security, or destructive changes.',
|
|
1669
|
+
},
|
|
1670
|
+
},
|
|
1671
|
+
autoEscalation: {
|
|
1672
|
+
enabled: true,
|
|
1673
|
+
rules: [
|
|
1674
|
+
{
|
|
1675
|
+
pattern: 'auth|security|token|credential|oauth|permission',
|
|
1676
|
+
escalateTo: 'critical',
|
|
1677
|
+
reason: 'Security-sensitive change',
|
|
1678
|
+
},
|
|
1679
|
+
{
|
|
1680
|
+
pattern: 'release|publish|tag|npm',
|
|
1681
|
+
escalateTo: 'critical',
|
|
1682
|
+
reason: 'Release-sensitive change',
|
|
1683
|
+
},
|
|
1684
|
+
],
|
|
1685
|
+
},
|
|
1686
|
+
lastUpdated: '2026-05-20T00:00:00Z',
|
|
1687
|
+
}, null, 2)}\n`;
|
|
1688
|
+
}
|
|
1689
|
+
function scaleEngineRepoAgentsMd() {
|
|
1690
|
+
return `# AGENTS.md
|
|
1691
|
+
|
|
1692
|
+
本文件是 \`scale-engine\` 仓库的工程化工作流入口,面向在本仓库里直接开发 \`scale-engine\` 本身的 Agent 和维护者。
|
|
1693
|
+
|
|
1694
|
+
## 先读
|
|
1695
|
+
|
|
1696
|
+
1. \`README.md\`
|
|
1697
|
+
2. \`docs/guides/GETTING_STARTED.md\`
|
|
1698
|
+
3. \`docs/guides/DEVELOPMENT_WORKFLOW.md\`
|
|
1699
|
+
4. \`docs/workflow/README.md\`
|
|
1700
|
+
5. \`.scale/workspace.json\`
|
|
1701
|
+
|
|
1702
|
+
## 工作原则
|
|
1703
|
+
|
|
1704
|
+
- 先读现状,再改文件;不要把 scaffold 的默认假设直接覆盖到本仓库现实。
|
|
1705
|
+
- 重要规则优先落到脚本、门禁、配置和模板,不只停留在口头约定。
|
|
1706
|
+
- 未运行验证,不得声称通过;\`dry-run\` 只代表入口可调度,不代表质量通过。
|
|
1707
|
+
- 需要执行 shell 命令时,优先使用 \`rtk\` 前缀。
|
|
1708
|
+
- 不覆盖用户已有未提交改动,不把本地 worktree、缓存、日志、截图混进提交。
|
|
1709
|
+
|
|
1710
|
+
## 推荐入口
|
|
1711
|
+
|
|
1712
|
+
\`\`\`bash
|
|
1713
|
+
make preflight
|
|
1714
|
+
make new-task NAME=workflow-adaptation LEVEL=M
|
|
1715
|
+
make plan NAME=workflow-adaptation LEVEL=M
|
|
1716
|
+
make explore FILES='AGENTS.md CLAUDE.md README.md' MSG='main contradiction'
|
|
1717
|
+
make gate-workflow
|
|
1718
|
+
make gate-quality
|
|
1719
|
+
make verify PROFILE=default
|
|
1720
|
+
make bootstrap-scale
|
|
1721
|
+
make workflow-upgrade-check
|
|
1722
|
+
make workflow-upgrade-plan
|
|
1723
|
+
\`\`\`
|
|
1724
|
+
|
|
1725
|
+
PowerShell:
|
|
1726
|
+
|
|
1727
|
+
\`\`\`powershell
|
|
1728
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/workflow/verify.ps1 -Profile default
|
|
1729
|
+
\`\`\`
|
|
1730
|
+
|
|
1731
|
+
## 任务等级
|
|
1732
|
+
|
|
1733
|
+
| Level | 场景 | 最低要求 |
|
|
1734
|
+
| --- | --- | --- |
|
|
1735
|
+
| S | typo、小范围文档、纯注释 | 读相关文件并运行最小相关验证 |
|
|
1736
|
+
| M | 常规 bug、小功能、脚本或治理优化 | 记录 explore/plan/verification/summary |
|
|
1737
|
+
| L | 跨模块、跨流程、模板体系或发布链路调整 | 完整计划、风险、回滚、评审证据 |
|
|
1738
|
+
| CRITICAL | 安全、权限、发布、破坏性操作 | 人工确认、完整验证、安全检查 |
|
|
1739
|
+
|
|
1740
|
+
## 交付要求
|
|
1741
|
+
|
|
1742
|
+
最终汇报至少说明:
|
|
1743
|
+
|
|
1744
|
+
- 改了什么。
|
|
1745
|
+
- 实际运行了哪些验证命令,结果是什么。
|
|
1746
|
+
- 哪些地方未验证,为什么。
|
|
1747
|
+
- 如果工作流规则变了,同步更新了哪些文档和配置。
|
|
1748
|
+
`;
|
|
1749
|
+
}
|
|
1750
|
+
function scaleEngineRepoClaudeMd() {
|
|
1751
|
+
return `# CLAUDE.md
|
|
1752
|
+
|
|
1753
|
+
Claude / Codex 在本仓库开发 \`scale-engine\` 时,默认遵循 \`AGENTS.md\`。
|
|
1754
|
+
|
|
1755
|
+
## 先读
|
|
1756
|
+
|
|
1757
|
+
1. \`AGENTS.md\`
|
|
1758
|
+
2. \`docs/guides/GETTING_STARTED.md\`
|
|
1759
|
+
3. \`docs/guides/DEVELOPMENT_WORKFLOW.md\`
|
|
1760
|
+
4. \`docs/workflow/README.md\`
|
|
1761
|
+
|
|
1762
|
+
## 常用命令
|
|
1763
|
+
|
|
1764
|
+
\`\`\`bash
|
|
1765
|
+
make preflight
|
|
1766
|
+
make gate-workflow
|
|
1767
|
+
make gate-quality
|
|
1768
|
+
make verify PROFILE=default
|
|
1769
|
+
make scale-smoke TASK='workflow adaptation' FILES='AGENTS.md,README.md'
|
|
1770
|
+
make workflow-upgrade-check
|
|
1771
|
+
make workflow-upgrade-plan
|
|
1772
|
+
\`\`\`
|
|
1773
|
+
|
|
1774
|
+
## 约束
|
|
1775
|
+
|
|
1776
|
+
- 没有实际验证结果,不说“已通过”。
|
|
1777
|
+
- 不确定的事实明确标记为 \`[UNCERTAIN]\`。
|
|
1778
|
+
- 修改前先看 Git 状态。
|
|
1779
|
+
- 需要 shell 命令时优先用 \`rtk\` 前缀。
|
|
1780
|
+
`;
|
|
1781
|
+
}
|
|
1782
|
+
function scaleEngineRepoMakefile() {
|
|
1783
|
+
return `.PHONY: help preflight new-task plan explore checkpoint gate gate-workflow gate-quality resume status lint-scaffold verify verify-list validate bootstrap-scale bootstrap-scale-install bootstrap-scale-latest workflow-upgrade-check workflow-upgrade-plan workflow-upgrade-apply workflow-upgrade-rollback workflow-upgrade-verify scale-version scale-mode scale-context scale-codegraph scale-eval scale-radar scale-dashboard scale-smoke
|
|
1784
|
+
|
|
1785
|
+
SCALE ?= scale
|
|
1786
|
+
SCALE_VERSION ?= locked
|
|
1787
|
+
TASK ?= scale-engine workflow adaptation
|
|
1788
|
+
FILES ?= AGENTS.md,CLAUDE.md,README.md
|
|
1789
|
+
LEVEL ?= M
|
|
1790
|
+
PHASE ?= plan
|
|
1791
|
+
SERVICES ?=
|
|
1792
|
+
|
|
1793
|
+
help:
|
|
1794
|
+
\t@echo "make preflight | make new-task NAME=x LEVEL=M | make explore FILES='...' MSG='...'"
|
|
1795
|
+
\t@echo "make plan NAME=x LEVEL=M | make gate-workflow | make gate-quality | make verify PROFILE=default"
|
|
1796
|
+
\t@echo "make bootstrap-scale | make workflow-upgrade-check | make workflow-upgrade-plan"
|
|
1797
|
+
|
|
1798
|
+
gate:
|
|
1799
|
+
\tbash scripts/gates/all.sh --all
|
|
1800
|
+
|
|
1801
|
+
gate-workflow:
|
|
1802
|
+
\tbash scripts/gates/all.sh --workflow
|
|
1803
|
+
|
|
1804
|
+
gate-quality:
|
|
1805
|
+
\tbash scripts/gates/all.sh --quality
|
|
1806
|
+
|
|
1807
|
+
new-task:
|
|
1808
|
+
\t@if [ -z "$(NAME)" ]; then echo "usage: make new-task NAME=x LEVEL=M"; exit 1; fi
|
|
1809
|
+
\tbash scripts/workflow/new-task.sh "$(NAME)" "$(or $(LEVEL),M)"
|
|
1810
|
+
|
|
1811
|
+
plan:
|
|
1812
|
+
\t@if [ -z "$(NAME)" ]; then echo "usage: make plan NAME=x LEVEL=M"; exit 1; fi
|
|
1813
|
+
\tbash scripts/workflow/plan.sh "$(NAME)" "$(or $(LEVEL),M)"
|
|
1814
|
+
|
|
1815
|
+
explore:
|
|
1816
|
+
\t@if [ -z "$(FILES)" ]; then echo "usage: make explore FILES='file1 file2' MSG='main contradiction'"; exit 1; fi
|
|
1817
|
+
\tbash scripts/workflow/explore.sh $(FILES) "$(MSG)"
|
|
1818
|
+
|
|
1819
|
+
checkpoint:
|
|
1820
|
+
\tbash scripts/workflow/checkpoint.sh "$(or $(PHASE),execute)"
|
|
1821
|
+
|
|
1822
|
+
resume:
|
|
1823
|
+
\tbash scripts/workflow/resume.sh
|
|
1824
|
+
|
|
1825
|
+
status: resume
|
|
1826
|
+
|
|
1827
|
+
lint-scaffold:
|
|
1828
|
+
\tbash scripts/workflow/lint-scaffold.sh
|
|
1829
|
+
|
|
1830
|
+
verify:
|
|
1831
|
+
\tbash scripts/workflow/verify.sh --profile "$(or $(PROFILE),default)"
|
|
1832
|
+
|
|
1833
|
+
verify-list:
|
|
1834
|
+
\tbash scripts/workflow/verify.sh --list
|
|
1835
|
+
|
|
1836
|
+
validate:
|
|
1837
|
+
\tbash scripts/validate-config.sh
|
|
1838
|
+
|
|
1839
|
+
preflight:
|
|
1840
|
+
\tbash scripts/preflight/all.sh
|
|
1841
|
+
|
|
1842
|
+
bootstrap-scale:
|
|
1843
|
+
\tpowershell -NoProfile -ExecutionPolicy Bypass -File scripts/bootstrap-scale.ps1 -Version "$(or $(SCALE_VERSION),locked)"
|
|
1844
|
+
|
|
1845
|
+
bootstrap-scale-install:
|
|
1846
|
+
\tpowershell -NoProfile -ExecutionPolicy Bypass -File scripts/bootstrap-scale.ps1 -Version "$(or $(SCALE_VERSION),locked)" -AutoInstall
|
|
1847
|
+
|
|
1848
|
+
bootstrap-scale-latest:
|
|
1849
|
+
\tpowershell -NoProfile -ExecutionPolicy Bypass -File scripts/bootstrap-scale.ps1 -Version latest -AutoInstall
|
|
1850
|
+
|
|
1851
|
+
workflow-upgrade-check:
|
|
1852
|
+
\t$(SCALE) upgrade check --dir .
|
|
1853
|
+
|
|
1854
|
+
workflow-upgrade-plan:
|
|
1855
|
+
\t$(SCALE) upgrade plan --dir . --html
|
|
1856
|
+
|
|
1857
|
+
workflow-upgrade-apply:
|
|
1858
|
+
\t$(SCALE) upgrade apply --dir . --confirm
|
|
1859
|
+
|
|
1860
|
+
workflow-upgrade-rollback:
|
|
1861
|
+
\t$(SCALE) upgrade rollback --dir .
|
|
1862
|
+
|
|
1863
|
+
workflow-upgrade-verify:
|
|
1864
|
+
\t$(SCALE) preflight --dir . --service all --preflight-profile quick
|
|
1865
|
+
|
|
1866
|
+
scale-version:
|
|
1867
|
+
\t$(SCALE) --version
|
|
1868
|
+
|
|
1869
|
+
scale-mode:
|
|
1870
|
+
\t$(SCALE) governance mode --task "$(TASK)" --files "$(FILES)"
|
|
1871
|
+
|
|
1872
|
+
scale-context:
|
|
1873
|
+
\t$(SCALE) context budget --dir .
|
|
1874
|
+
|
|
1875
|
+
scale-codegraph:
|
|
1876
|
+
\t$(SCALE) codegraph status --dir .
|
|
1877
|
+
|
|
1878
|
+
scale-eval:
|
|
1879
|
+
\t$(SCALE) eval run --dir .
|
|
1880
|
+
|
|
1881
|
+
scale-radar:
|
|
1882
|
+
\t$(SCALE) skill radar --dir . --task "$(TASK)" --phase "$(PHASE)" --level "$(LEVEL)" --files "$(FILES)" --services "$(SERVICES)"
|
|
1883
|
+
|
|
1884
|
+
scale-dashboard:
|
|
1885
|
+
\t$(SCALE) artifact dashboard --dir . --lang zh
|
|
1886
|
+
|
|
1887
|
+
scale-smoke:
|
|
1888
|
+
\tpowershell -NoProfile -ExecutionPolicy Bypass -File scripts/workflow/scale-smoke.ps1 -Task "$(TASK)" -Files "$(FILES)" -Level "$(LEVEL)" -Phase "$(PHASE)" -Services "$(SERVICES)"
|
|
1889
|
+
`;
|
|
1890
|
+
}
|
|
1891
|
+
function scaleEngineRepoGettingStartedGuide() {
|
|
1892
|
+
return `# SCALE Engine 仓库上手
|
|
1893
|
+
|
|
1894
|
+
这份文档面向要开发 \`scale-engine\` 仓库本身的人,不是面向安装 CLI 的最终用户。
|
|
1895
|
+
|
|
1896
|
+
## 15 分钟路径
|
|
1897
|
+
|
|
1898
|
+
1. 先读根目录 [README.md](../../README.md)。
|
|
1899
|
+
2. 跑本仓库 workflow 预检:
|
|
1900
|
+
|
|
1901
|
+
\`\`\`bash
|
|
1902
|
+
make preflight
|
|
1903
|
+
\`\`\`
|
|
1904
|
+
|
|
1905
|
+
3. 看当前可用验证面:
|
|
1906
|
+
|
|
1907
|
+
\`\`\`bash
|
|
1908
|
+
make verify-list
|
|
1909
|
+
\`\`\`
|
|
1910
|
+
|
|
1911
|
+
4. 建一个任务骨架并记录探索:
|
|
1912
|
+
|
|
1913
|
+
\`\`\`bash
|
|
1914
|
+
make new-task NAME=example LEVEL=M
|
|
1915
|
+
make plan NAME=example LEVEL=M
|
|
1916
|
+
make explore FILES='AGENTS.md CLAUDE.md README.md package.json' MSG='main contradiction'
|
|
1917
|
+
make gate-workflow
|
|
1918
|
+
\`\`\`
|
|
1919
|
+
|
|
1920
|
+
5. 做完改动后跑质量面:
|
|
1921
|
+
|
|
1922
|
+
\`\`\`bash
|
|
1923
|
+
make gate-quality
|
|
1924
|
+
make verify PROFILE=default
|
|
1925
|
+
git diff --check
|
|
1926
|
+
\`\`\`
|
|
1927
|
+
|
|
1928
|
+
## 你应该看到什么
|
|
1929
|
+
|
|
1930
|
+
- \`.scale/workspace.json\` 明确了 \`dev -> master\` 的仓库分支策略。
|
|
1931
|
+
- \`.agent/project.json\` 定义了本仓库的 Node/TypeScript 验证命令。
|
|
1932
|
+
- \`scripts/gates/*\` 和 \`scripts/workflow/*\` 不是说明文档,而是可执行入口。
|
|
1933
|
+
- \`.planning/tasks/<date>-<task>/\` 用于任务级证据,不再把临时过程写进 \`docs/\`。
|
|
1934
|
+
|
|
1935
|
+
## 常见误区
|
|
1936
|
+
|
|
1937
|
+
- \`make gate-workflow\` 通过,不代表代码质量通过。
|
|
1938
|
+
- \`make gate-quality\` 通过,也不代表你已经记录了风险、回滚和未验证项。
|
|
1939
|
+
- \`G8\` 会检查改动过的 Markdown 和工作流文档卫生,不替代业务验证。
|
|
1940
|
+
- \`--dry-run\` 只能证明入口存在,不能写成“测试通过”。
|
|
1941
|
+
- 不要把 \`.claude/worktrees/\`、\`.agent/state/\`、日志或截图提交进仓库。
|
|
1942
|
+
`;
|
|
1943
|
+
}
|
|
1944
|
+
function scaleEngineRepoDevelopmentWorkflowGuide() {
|
|
1945
|
+
return `# SCALE Engine 开发工作流
|
|
1946
|
+
|
|
1947
|
+
这份文档说明日常如何在 \`scale-engine\` 仓库里按最新工程化工作流工作。
|
|
1948
|
+
|
|
1949
|
+
## 标准闭环
|
|
1950
|
+
|
|
1951
|
+
\`\`\`text
|
|
1952
|
+
探索 -> 规划 -> 执行 -> 验证 -> 沉淀
|
|
1953
|
+
\`\`\`
|
|
1954
|
+
|
|
1955
|
+
## 1. 探索
|
|
1956
|
+
|
|
1957
|
+
目标:先弄清真实仓库状态,再动手。
|
|
1958
|
+
|
|
1959
|
+
\`\`\`bash
|
|
1960
|
+
make new-task NAME=task-slug LEVEL=M
|
|
1961
|
+
make plan NAME=task-slug LEVEL=M
|
|
1962
|
+
make explore FILES='AGENTS.md CLAUDE.md README.md package.json src/api/cli.ts' MSG='main contradiction'
|
|
1963
|
+
make gate-workflow
|
|
1964
|
+
\`\`\`
|
|
1965
|
+
|
|
1966
|
+
最低要求:
|
|
1967
|
+
|
|
1968
|
+
- 至少读 3 个相关文件。
|
|
1969
|
+
- 写清主矛盾,而不是只列文件名。
|
|
1970
|
+
- 对不确定项明确标出,不靠猜。
|
|
1971
|
+
|
|
1972
|
+
## 2. 规划
|
|
1973
|
+
|
|
1974
|
+
在 \`.planning/tasks/<task>/plan.md\` 里至少补齐这些信息:
|
|
1975
|
+
|
|
1976
|
+
- scope / boundary
|
|
1977
|
+
- acceptance criteria
|
|
1978
|
+
- exception / failure path
|
|
1979
|
+
- rollback / fallback
|
|
1980
|
+
- verification commands
|
|
1981
|
+
|
|
1982
|
+
如果任务改动发布、权限、安全、凭据、npm 发版或破坏性行为,按 \`CRITICAL\` 处理。
|
|
1983
|
+
|
|
1984
|
+
## 3. 执行
|
|
1985
|
+
|
|
1986
|
+
原则:
|
|
1987
|
+
|
|
1988
|
+
- 最小必要修改。
|
|
1989
|
+
- 优先复用现有脚本和 \`npm\` 命令,不再发明第二套命令。
|
|
1990
|
+
- 改 \`src/\` 行为时,原则上同步改 \`tests/\`,否则会被 G3 拦下。
|
|
1991
|
+
|
|
1992
|
+
## 4. 验证
|
|
1993
|
+
|
|
1994
|
+
推荐顺序:
|
|
1995
|
+
|
|
1996
|
+
\`\`\`bash
|
|
1997
|
+
make gate-quality
|
|
1998
|
+
make verify PROFILE=default
|
|
1999
|
+
git diff --check
|
|
2000
|
+
\`\`\`
|
|
2001
|
+
|
|
2002
|
+
其中:
|
|
2003
|
+
|
|
2004
|
+
- \`G4\` 验证 workflow 脚本本身可解析。
|
|
2005
|
+
- \`G5\` 运行 \`lint + typecheck + test + build\`。
|
|
2006
|
+
- \`G6\` 检查任务证据和 diff hygiene。
|
|
2007
|
+
- \`G7\` 是安全面,默认走 \`npm audit --audit-level=high\`。
|
|
2008
|
+
- \`G8\` 检查 Markdown 与工作流文档的基础卫生。
|
|
2009
|
+
|
|
2010
|
+
## 5. 沉淀
|
|
2011
|
+
|
|
2012
|
+
应该留下:
|
|
2013
|
+
|
|
2014
|
+
- \`verification.md\`
|
|
2015
|
+
- \`review.md\`
|
|
2016
|
+
- \`summary.md\`
|
|
2017
|
+
- 必要的长期规则文档更新
|
|
2018
|
+
|
|
2019
|
+
不应该留下:
|
|
2020
|
+
|
|
2021
|
+
- 临时日志
|
|
2022
|
+
- worktree 状态
|
|
2023
|
+
- 截图、trace、缓存
|
|
2024
|
+
- 只对一次任务有意义的中间文件
|
|
2025
|
+
`;
|
|
2026
|
+
}
|
|
2027
|
+
function scaleEngineRepoWorkflowReadme() {
|
|
2028
|
+
return `# SCALE Engine 仓库工作流
|
|
2029
|
+
|
|
2030
|
+
这里描述的是 \`scale-engine\` 仓库自身的工程化工作流,不是终端用户如何使用 \`scale\` CLI。
|
|
2031
|
+
|
|
2032
|
+
## 入口
|
|
2033
|
+
|
|
2034
|
+
- 新维护者先读 [GETTING_STARTED.md](../guides/GETTING_STARTED.md)
|
|
2035
|
+
- 日常开发读 [DEVELOPMENT_WORKFLOW.md](../guides/DEVELOPMENT_WORKFLOW.md)
|
|
2036
|
+
- 机器可读分支策略看 [../../.scale/workspace.json](../../.scale/workspace.json)
|
|
2037
|
+
|
|
2038
|
+
## 最小命令面
|
|
2039
|
+
|
|
2040
|
+
\`\`\`bash
|
|
2041
|
+
make preflight
|
|
2042
|
+
make new-task NAME=workflow-adaptation LEVEL=M
|
|
2043
|
+
make plan NAME=workflow-adaptation LEVEL=M
|
|
2044
|
+
make explore FILES='AGENTS.md CLAUDE.md README.md package.json' MSG='main contradiction'
|
|
2045
|
+
make gate-workflow
|
|
2046
|
+
make gate-quality
|
|
2047
|
+
make verify PROFILE=default
|
|
2048
|
+
\`\`\`
|
|
2049
|
+
|
|
2050
|
+
PowerShell:
|
|
2051
|
+
|
|
2052
|
+
\`\`\`powershell
|
|
2053
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/workflow/verify.ps1 -Profile default
|
|
2054
|
+
\`\`\`
|
|
2055
|
+
|
|
2056
|
+
## 门禁说明
|
|
2057
|
+
|
|
2058
|
+
| Gate | 作用 |
|
|
2059
|
+
| --- | --- |
|
|
2060
|
+
| G1 | 探索是否记录到状态文件,且至少读了 3 个文件 |
|
|
2061
|
+
| G2 | 计划是否包含边界、异常、回滚、现实校验 |
|
|
2062
|
+
| G3 | \`src/\` 行为改动是否伴随测试改动 |
|
|
2063
|
+
| G4 | workflow 脚本是否可解析 |
|
|
2064
|
+
| G5 | \`lint + typecheck + test + build\` 是否通过 |
|
|
2065
|
+
| G6 | 任务证据和 \`git diff --check\` 是否通过 |
|
|
2066
|
+
| G7 | 安全面是否通过 |
|
|
2067
|
+
| G8 | Markdown 与工作流文档是否符合基础卫生规则 |
|
|
2068
|
+
|
|
2069
|
+
## 分支策略
|
|
2070
|
+
|
|
2071
|
+
当前仓库采用 GitLab Flow 风格:
|
|
2072
|
+
|
|
2073
|
+
\`\`\`text
|
|
2074
|
+
feature/fix/docs/chore/codex -> dev -> master
|
|
2075
|
+
\`\`\`
|
|
2076
|
+
|
|
2077
|
+
约束:
|
|
2078
|
+
|
|
2079
|
+
- \`dev\` 是集成分支。
|
|
2080
|
+
- \`master\` 是生产基线。
|
|
2081
|
+
- \`release/*\` 只在必须从生产基线隔离发版时使用。
|
|
2082
|
+
- \`hotfix/*\` 用于生产紧急修复,并要求回流 \`dev\`。
|
|
2083
|
+
|
|
2084
|
+
## 升级入口
|
|
2085
|
+
|
|
2086
|
+
如果要把仓库工作流继续升级到更新的 \`scale-engine\` 版本,先跑:
|
|
2087
|
+
|
|
2088
|
+
\`\`\`bash
|
|
2089
|
+
make bootstrap-scale
|
|
2090
|
+
make workflow-upgrade-check
|
|
2091
|
+
make workflow-upgrade-plan
|
|
2092
|
+
\`\`\`
|
|
2093
|
+
|
|
2094
|
+
先审计划,再决定是否 \`make workflow-upgrade-apply\`。
|
|
267
2095
|
`;
|
|
268
2096
|
}
|
|
269
2097
|
//# sourceMappingURL=GovernanceTemplatePacks.js.map
|