@hongmaple0820/scale-engine 0.12.2 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -2
- package/dist/adapters/ClaudeCodeAdapter.d.ts +1 -0
- package/dist/adapters/ClaudeCodeAdapter.js.map +1 -1
- package/dist/adapters/KiroAdapter.d.ts +14 -0
- package/dist/adapters/KiroAdapter.js +180 -0
- package/dist/adapters/KiroAdapter.js.map +1 -0
- package/dist/adapters/index.d.ts +1 -0
- package/dist/adapters/index.js +3 -0
- package/dist/adapters/index.js.map +1 -1
- package/dist/api/cli.js +396 -5
- package/dist/api/cli.js.map +1 -1
- package/dist/api/doctor.d.ts +12 -0
- package/dist/api/doctor.js +232 -5
- package/dist/api/doctor.js.map +1 -1
- package/dist/api/quickstart.d.ts +19 -1
- package/dist/api/quickstart.js +103 -2
- package/dist/api/quickstart.js.map +1 -1
- package/dist/artifact/types.d.ts +16 -2
- package/dist/artifact/types.js.map +1 -1
- package/dist/cli/phaseCommands.d.ts +61 -0
- package/dist/cli/phaseCommands.js +559 -39
- package/dist/cli/phaseCommands.js.map +1 -1
- package/dist/cli/vibeCommands.d.ts +44 -0
- package/dist/cli/vibeCommands.js +244 -0
- package/dist/cli/vibeCommands.js.map +1 -0
- package/dist/guardrails/detectors.d.ts +9 -0
- package/dist/guardrails/detectors.js +102 -0
- package/dist/guardrails/detectors.js.map +1 -1
- package/dist/hooks/HookGeneratorEnhanced.js +29 -0
- package/dist/hooks/HookGeneratorEnhanced.js.map +1 -1
- package/dist/hooks/WorkflowHooksManager.js +20 -1
- package/dist/hooks/WorkflowHooksManager.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/output/BrandThemeLoader.d.ts +54 -0
- package/dist/output/BrandThemeLoader.js +340 -0
- package/dist/output/BrandThemeLoader.js.map +1 -0
- package/dist/output/HTMLDocumentRenderer.d.ts +83 -0
- package/dist/output/HTMLDocumentRenderer.js +717 -0
- package/dist/output/HTMLDocumentRenderer.js.map +1 -0
- package/dist/output/UIPrototypeRenderer.d.ts +61 -0
- package/dist/output/UIPrototypeRenderer.js +500 -0
- package/dist/output/UIPrototypeRenderer.js.map +1 -0
- package/dist/output/index.d.ts +6 -0
- package/dist/output/index.js +6 -0
- package/dist/output/index.js.map +1 -0
- package/dist/prompts/PhasePromptRegistry.d.ts +53 -0
- package/dist/prompts/PhasePromptRegistry.js +517 -0
- package/dist/prompts/PhasePromptRegistry.js.map +1 -0
- package/dist/skills/SkillDiscovery.js +2 -1
- package/dist/skills/SkillDiscovery.js.map +1 -1
- package/dist/skills/index.d.ts +1 -0
- package/dist/skills/index.js +1 -0
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/routing/SkillGate.d.ts +11 -0
- package/dist/skills/routing/SkillGate.js +76 -0
- package/dist/skills/routing/SkillGate.js.map +1 -0
- package/dist/skills/routing/SkillPlanner.d.ts +8 -0
- package/dist/skills/routing/SkillPlanner.js +91 -0
- package/dist/skills/routing/SkillPlanner.js.map +1 -0
- package/dist/skills/routing/SkillPolicy.d.ts +6 -0
- package/dist/skills/routing/SkillPolicy.js +146 -0
- package/dist/skills/routing/SkillPolicy.js.map +1 -0
- package/dist/skills/routing/SkillRoutingTypes.d.ts +72 -0
- package/dist/skills/routing/SkillRoutingTypes.js +2 -0
- package/dist/skills/routing/SkillRoutingTypes.js.map +1 -0
- package/dist/skills/routing/TaskIntentClassifier.d.ts +6 -0
- package/dist/skills/routing/TaskIntentClassifier.js +79 -0
- package/dist/skills/routing/TaskIntentClassifier.js.map +1 -0
- package/dist/skills/routing/index.d.ts +5 -0
- package/dist/skills/routing/index.js +6 -0
- package/dist/skills/routing/index.js.map +1 -0
- package/dist/workflow/GovernanceTemplates.d.ts +12 -0
- package/dist/workflow/GovernanceTemplates.js +515 -0
- package/dist/workflow/GovernanceTemplates.js.map +1 -0
- package/dist/workflow/PhaseMarkerTracker.d.ts +63 -0
- package/dist/workflow/PhaseMarkerTracker.js +291 -0
- package/dist/workflow/PhaseMarkerTracker.js.map +1 -0
- package/dist/workflow/SessionStateTracker.d.ts +74 -0
- package/dist/workflow/SessionStateTracker.js +270 -0
- package/dist/workflow/SessionStateTracker.js.map +1 -0
- package/dist/workflow/TaskArtifactScaffolder.d.ts +47 -0
- package/dist/workflow/TaskArtifactScaffolder.js +237 -0
- package/dist/workflow/TaskArtifactScaffolder.js.map +1 -0
- package/dist/workflow/TaskMetricsStore.d.ts +49 -0
- package/dist/workflow/TaskMetricsStore.js +149 -0
- package/dist/workflow/TaskMetricsStore.js.map +1 -0
- package/dist/workflow/VerificationCommands.d.ts +2 -0
- package/dist/workflow/VerificationCommands.js +7 -4
- package/dist/workflow/VerificationCommands.js.map +1 -1
- package/dist/workflow/VerificationProfile.d.ts +55 -0
- package/dist/workflow/VerificationProfile.js +133 -0
- package/dist/workflow/VerificationProfile.js.map +1 -0
- package/dist/workflow/WorkflowArtifactWriter.d.ts +113 -0
- package/dist/workflow/WorkflowArtifactWriter.js +241 -0
- package/dist/workflow/WorkflowArtifactWriter.js.map +1 -0
- package/dist/workflow/WorkflowEngine.d.ts +20 -2
- package/dist/workflow/WorkflowEngine.js +37 -8
- package/dist/workflow/WorkflowEngine.js.map +1 -1
- package/dist/workflow/autonomous/AutonomousDevLoop.d.ts +88 -0
- package/dist/workflow/autonomous/AutonomousDevLoop.js +381 -0
- package/dist/workflow/autonomous/AutonomousDevLoop.js.map +1 -0
- package/dist/workflow/autonomous/WorklogManager.d.ts +50 -0
- package/dist/workflow/autonomous/WorklogManager.js +264 -0
- package/dist/workflow/autonomous/WorklogManager.js.map +1 -0
- package/dist/workflow/autonomous/index.d.ts +2 -0
- package/dist/workflow/autonomous/index.js +4 -0
- package/dist/workflow/autonomous/index.js.map +1 -0
- package/dist/workflow/gates/GateSystem.d.ts +12 -3
- package/dist/workflow/gates/GateSystem.js +185 -41
- package/dist/workflow/gates/GateSystem.js.map +1 -1
- package/dist/workflow/index.d.ts +7 -0
- package/dist/workflow/index.js +7 -0
- package/dist/workflow/index.js.map +1 -1
- package/package.json +3 -3
package/dist/api/cli.js
CHANGED
|
@@ -12,6 +12,11 @@ import { DangerousCommandDetector, SecretLeakDetector, RoleGateDetector, ScopeCr
|
|
|
12
12
|
import { SQLiteKnowledgeBase } from '../knowledge/SQLiteKnowledgeBase.js';
|
|
13
13
|
import { ContextBuilder } from '../context/ContextBuilder.js';
|
|
14
14
|
import { FSMAgentBridge } from '../fsm/FSMAgentBridge.js';
|
|
15
|
+
import { CapabilityRegistry } from '../capabilities/CapabilityRegistry.js';
|
|
16
|
+
import { SkillRegistry } from '../skills/SkillRegistry.js';
|
|
17
|
+
import { registerCoreSkills } from '../skills/coreSkills.js';
|
|
18
|
+
import { registerExternalSkills } from '../skills/ExternalSkills.js';
|
|
19
|
+
import { createSkillPlan, evaluateSkillGate, loadSkillRoutingPolicy, skillPlanMarkdown } from '../skills/routing/index.js';
|
|
15
20
|
import { createAdapter, SUPPORTED_AGENTS } from '../adapters/index.js';
|
|
16
21
|
import { LessonExtractor, RuleProposer, HookGenerator, EvolutionEngine } from '../evolution/EvolutionEngine.js';
|
|
17
22
|
import { Doctor } from './doctor.js';
|
|
@@ -21,17 +26,34 @@ import { listWorkflowPresets, getPresetsByScenario } from '../workflows/presets.
|
|
|
21
26
|
import { EvidenceStore } from '../workflow/EvidenceStore.js';
|
|
22
27
|
import { OutOfScopeStore } from '../workflow/OutOfScopeStore.js';
|
|
23
28
|
import { ReviewStore } from '../workflow/ReviewStore.js';
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
29
|
+
import { WorkflowEngine } from '../workflow/WorkflowEngine.js';
|
|
30
|
+
import { resolveVerificationTargets } from '../workflow/VerificationProfile.js';
|
|
31
|
+
import { writeGovernanceTemplates } from '../workflow/GovernanceTemplates.js';
|
|
32
|
+
import { TaskMetricsStore } from '../workflow/TaskMetricsStore.js';
|
|
33
|
+
import { checkTaskArtifactCompleteness } from '../workflow/TaskArtifactScaffolder.js';
|
|
34
|
+
import { WorkflowArtifactWriter } from '../workflow/WorkflowArtifactWriter.js';
|
|
35
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
36
|
+
import { join, resolve } from 'node:path';
|
|
26
37
|
// ============================================================================
|
|
27
38
|
// Engine bootstrap (单例 + lazy init)
|
|
28
39
|
// ============================================================================
|
|
29
40
|
const SCALE_DIR = process.env.SCALE_DIR ?? '.scale';
|
|
41
|
+
const PROJECT_DIR = process.env.SCALE_PROJECT_DIR ?? process.cwd();
|
|
30
42
|
const DB_PATH = join(SCALE_DIR, 'scale.db');
|
|
43
|
+
function governanceModeFromScenario(scenario) {
|
|
44
|
+
if (scenario === 'critical')
|
|
45
|
+
return 'critical';
|
|
46
|
+
if (scenario === 'sandbox')
|
|
47
|
+
return 'minimal';
|
|
48
|
+
return 'standard';
|
|
49
|
+
}
|
|
31
50
|
function ensureDir(dir) {
|
|
32
51
|
if (!existsSync(dir))
|
|
33
52
|
mkdirSync(dir, { recursive: true });
|
|
34
53
|
}
|
|
54
|
+
function isTruthyFlag(value) {
|
|
55
|
+
return value === true || value === '' || value === 'true' || value === '1';
|
|
56
|
+
}
|
|
35
57
|
let _engine = null;
|
|
36
58
|
function getEngine() {
|
|
37
59
|
if (!_engine)
|
|
@@ -60,7 +82,17 @@ function createEngine() {
|
|
|
60
82
|
const kb = new SQLiteKnowledgeBase(eventBus, { dbPath: join(SCALE_DIR, 'knowledge.db') });
|
|
61
83
|
const ctx = new ContextBuilder(store, kb, eventBus);
|
|
62
84
|
const fsmAgentBridge = new FSMAgentBridge(fsm, store);
|
|
63
|
-
|
|
85
|
+
const capabilityRegistry = new CapabilityRegistry(eventBus);
|
|
86
|
+
const skillRegistry = new SkillRegistry(eventBus);
|
|
87
|
+
registerCoreSkills(skillRegistry);
|
|
88
|
+
registerExternalSkills(skillRegistry, eventBus);
|
|
89
|
+
const workflowEngine = new WorkflowEngine({
|
|
90
|
+
eventBus,
|
|
91
|
+
capabilityRegistry,
|
|
92
|
+
skillRegistry,
|
|
93
|
+
scaleDir: SCALE_DIR,
|
|
94
|
+
});
|
|
95
|
+
return { eventBus, store, fsm, gateway, roleGate, kb, ctx, fsmAgentBridge, workflowEngine };
|
|
64
96
|
}
|
|
65
97
|
// ============================================================================
|
|
66
98
|
// session commands
|
|
@@ -699,6 +731,161 @@ const stats = defineCommand({
|
|
|
699
731
|
console.log(JSON.stringify({ ...s, eventCount: events.length }, null, 2));
|
|
700
732
|
},
|
|
701
733
|
});
|
|
734
|
+
const metricsList = defineCommand({
|
|
735
|
+
meta: { name: 'list', description: 'List M/L task workflow metrics' },
|
|
736
|
+
args: {
|
|
737
|
+
json: { type: 'boolean', default: false },
|
|
738
|
+
},
|
|
739
|
+
async run({ args }) {
|
|
740
|
+
const store = new TaskMetricsStore(SCALE_DIR);
|
|
741
|
+
const records = store.list();
|
|
742
|
+
const summary = store.summarize();
|
|
743
|
+
if (args.json) {
|
|
744
|
+
console.log(JSON.stringify({ summary, records }, null, 2));
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
console.log('\nWorkflow Metrics');
|
|
748
|
+
console.log(` Total tasks: ${summary.total}`);
|
|
749
|
+
console.log(` First-pass verification rate: ${(summary.firstPassRate * 100).toFixed(1)}%`);
|
|
750
|
+
console.log(` Average fix iterations: ${summary.averageFixIterations.toFixed(2)}`);
|
|
751
|
+
console.log(` Artifact completeness: ${(summary.artifactCompletenessRate * 100).toFixed(1)}%`);
|
|
752
|
+
for (const record of records.slice(-10)) {
|
|
753
|
+
console.log(` - ${record.date} ${record.level} ${record.taskName}: ${record.finalGateStatus}`);
|
|
754
|
+
}
|
|
755
|
+
},
|
|
756
|
+
});
|
|
757
|
+
const metrics = defineCommand({
|
|
758
|
+
meta: { name: 'metrics', description: 'Inspect workflow task metrics' },
|
|
759
|
+
subCommands: { list: metricsList },
|
|
760
|
+
});
|
|
761
|
+
function normalizeTaskArtifactLevel(value) {
|
|
762
|
+
const normalized = String(value ?? 'M').trim().toUpperCase();
|
|
763
|
+
if (normalized === 'S' || normalized === 'M' || normalized === 'L' || normalized === 'CRITICAL') {
|
|
764
|
+
return normalized;
|
|
765
|
+
}
|
|
766
|
+
throw new Error(`Invalid task level "${String(value)}"; expected S, M, L, or CRITICAL.`);
|
|
767
|
+
}
|
|
768
|
+
const taskArtifactsCheck = defineCommand({
|
|
769
|
+
meta: { name: 'check', description: 'Check task artifact completeness' },
|
|
770
|
+
args: {
|
|
771
|
+
dir: { type: 'string', description: 'Task artifact directory; defaults to .scale/state/current.json artifactsDir' },
|
|
772
|
+
level: { type: 'string', description: 'Task level: S, M, L, or CRITICAL; defaults to current state level or M' },
|
|
773
|
+
'warn-only': { type: 'boolean', default: false, description: 'Return zero even when artifacts are incomplete' },
|
|
774
|
+
json: { type: 'boolean', default: false },
|
|
775
|
+
},
|
|
776
|
+
run({ args }) {
|
|
777
|
+
const state = new WorkflowArtifactWriter(SCALE_DIR).readCurrentState();
|
|
778
|
+
let level;
|
|
779
|
+
try {
|
|
780
|
+
level = normalizeTaskArtifactLevel(args.level ?? state?.level ?? 'M');
|
|
781
|
+
}
|
|
782
|
+
catch (e) {
|
|
783
|
+
console.error(e.message);
|
|
784
|
+
process.exit(1);
|
|
785
|
+
}
|
|
786
|
+
const result = checkTaskArtifactCompleteness({
|
|
787
|
+
projectDir: PROJECT_DIR,
|
|
788
|
+
artifactsDir: args.dir ?? state?.artifactsDir,
|
|
789
|
+
level,
|
|
790
|
+
skillRequiredArtifacts: state?.requiredSkillArtifacts,
|
|
791
|
+
});
|
|
792
|
+
if (args.json) {
|
|
793
|
+
console.log(JSON.stringify(result, null, 2));
|
|
794
|
+
}
|
|
795
|
+
else {
|
|
796
|
+
console.log(`\nTask Artifacts: ${result.complete ? 'COMPLETE' : 'INCOMPLETE'}`);
|
|
797
|
+
if (result.artifactsDir)
|
|
798
|
+
console.log(` Directory: ${result.artifactsDir}`);
|
|
799
|
+
console.log(` Required: ${result.required.join(', ') || 'none'}`);
|
|
800
|
+
for (const file of result.missing)
|
|
801
|
+
console.log(` [MISSING] ${file}`);
|
|
802
|
+
for (const item of result.incomplete)
|
|
803
|
+
console.log(` [INCOMPLETE] ${item.file}: ${item.reason}`);
|
|
804
|
+
}
|
|
805
|
+
if (!result.complete && !args['warn-only'])
|
|
806
|
+
process.exitCode = 1;
|
|
807
|
+
},
|
|
808
|
+
});
|
|
809
|
+
const taskArtifacts = defineCommand({
|
|
810
|
+
meta: { name: 'task-artifacts', description: 'Inspect task artifact completeness' },
|
|
811
|
+
subCommands: { check: taskArtifactsCheck },
|
|
812
|
+
});
|
|
813
|
+
const preflight = defineCommand({
|
|
814
|
+
meta: { name: 'preflight', description: 'Run service-aware verification without a task artifact' },
|
|
815
|
+
args: {
|
|
816
|
+
'build-cmd': { type: 'string', description: 'Override build command' },
|
|
817
|
+
'lint-cmd': { type: 'string', description: 'Override lint command' },
|
|
818
|
+
'test-cmd': { type: 'string', description: 'Override test command' },
|
|
819
|
+
'coverage-cmd': { type: 'string', description: 'Override coverage command' },
|
|
820
|
+
profile: { type: 'string', description: 'Verification profile from .scale/verification.json' },
|
|
821
|
+
service: { type: 'string', description: 'Service name from .scale/verification.json; use all for required services' },
|
|
822
|
+
'tdd-evidence': { type: 'string', description: 'Path to JSON TDD evidence with red/green/refactor/testFirst=true' },
|
|
823
|
+
'tdd-strict': { type: 'boolean', default: false, description: 'Require TDD evidence before other gates' },
|
|
824
|
+
json: { type: 'boolean', default: false },
|
|
825
|
+
},
|
|
826
|
+
async run({ args }) {
|
|
827
|
+
const { workflowEngine } = getEngine();
|
|
828
|
+
const resolved = resolveVerificationTargets({
|
|
829
|
+
projectDir: PROJECT_DIR,
|
|
830
|
+
scaleDir: SCALE_DIR,
|
|
831
|
+
profile: args.profile,
|
|
832
|
+
service: args.service,
|
|
833
|
+
});
|
|
834
|
+
const targetResults = [];
|
|
835
|
+
if (!args.json) {
|
|
836
|
+
console.log('\nSCALE Preflight');
|
|
837
|
+
for (const warning of resolved.warnings)
|
|
838
|
+
console.log(` [WARN] ${warning}`);
|
|
839
|
+
console.log(` Profile: ${resolved.profileName}`);
|
|
840
|
+
}
|
|
841
|
+
for (const target of resolved.targets) {
|
|
842
|
+
if (!args.json) {
|
|
843
|
+
const label = target.service ? `${target.service.name} (${target.service.path})` : 'root';
|
|
844
|
+
console.log(`\n Target: ${label}`);
|
|
845
|
+
}
|
|
846
|
+
const gates = await workflowEngine.verify({
|
|
847
|
+
cwd: target.config.cwd,
|
|
848
|
+
build: args['build-cmd'] ?? target.config.build,
|
|
849
|
+
lint: args['lint-cmd'] ?? target.config.lint,
|
|
850
|
+
test: args['test-cmd'] ?? target.config.test,
|
|
851
|
+
coverage: args['coverage-cmd'] ?? target.config.coverage,
|
|
852
|
+
tddEvidence: args['tdd-evidence'],
|
|
853
|
+
tddStrict: isTruthyFlag(args['tdd-strict']),
|
|
854
|
+
});
|
|
855
|
+
const passed = gates.every(gate => gate.passed);
|
|
856
|
+
targetResults.push({
|
|
857
|
+
service: target.service?.name,
|
|
858
|
+
cwd: target.config.cwd ?? PROJECT_DIR,
|
|
859
|
+
gates,
|
|
860
|
+
passed,
|
|
861
|
+
});
|
|
862
|
+
if (!args.json) {
|
|
863
|
+
for (const gate of gates) {
|
|
864
|
+
console.log(` ${gate.passed ? '[PASS]' : '[FAIL]'} ${gate.gate}: ${gate.evidence.slice(0, 80)}`);
|
|
865
|
+
for (const blocker of gate.blockers)
|
|
866
|
+
console.log(` [BLOCKER] ${blocker.slice(0, 120)}`);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
const passed = targetResults.length > 0 && targetResults.every(target => target.passed);
|
|
871
|
+
const result = {
|
|
872
|
+
phase: 'PREFLIGHT',
|
|
873
|
+
profile: resolved.profileName,
|
|
874
|
+
services: targetResults.map(target => target.service).filter(Boolean),
|
|
875
|
+
policy: resolved.policy,
|
|
876
|
+
targets: targetResults,
|
|
877
|
+
passed,
|
|
878
|
+
};
|
|
879
|
+
if (args.json) {
|
|
880
|
+
console.log(JSON.stringify(result, null, 2));
|
|
881
|
+
}
|
|
882
|
+
else {
|
|
883
|
+
console.log(`\nPREFLIGHT: ${passed ? 'PASSED' : 'FAILED'}\n`);
|
|
884
|
+
}
|
|
885
|
+
if (!passed)
|
|
886
|
+
process.exitCode = 1;
|
|
887
|
+
},
|
|
888
|
+
});
|
|
702
889
|
const status = defineCommand({
|
|
703
890
|
meta: { name: 'status', description: 'Show current SCALE workflow status' },
|
|
704
891
|
args: {
|
|
@@ -821,8 +1008,88 @@ const init = defineCommand({
|
|
|
821
1008
|
dir: { type: 'string', default: '.', description: 'Project directory' },
|
|
822
1009
|
scenario: { type: 'string', default: 'standard', description: 'Scenario mode (sandbox/standard/critical)' },
|
|
823
1010
|
quick: { type: 'boolean', default: false, description: 'Quick start with auto-detection' },
|
|
1011
|
+
interactive: { type: 'boolean', default: false, description: 'Interactive configuration mode with prompts' },
|
|
1012
|
+
'coverage-threshold': { type: 'string', default: '80', description: 'Coverage threshold (default 80%)' },
|
|
1013
|
+
'retry-threshold': { type: 'string', default: '3', description: 'Brute retry threshold (default 3)' },
|
|
1014
|
+
'block-severity': { type: 'string', default: 'CRITICAL', description: 'Block severity level (CRITICAL/HIGH/MEDIUM)' },
|
|
824
1015
|
},
|
|
825
1016
|
async run({ args }) {
|
|
1017
|
+
// Interactive configuration mode
|
|
1018
|
+
if (args.interactive) {
|
|
1019
|
+
console.log('\n🔧 SCALE Engine Interactive Configuration\n');
|
|
1020
|
+
console.log('='.repeat(50));
|
|
1021
|
+
// Step 1: Detect and suggest agent platform
|
|
1022
|
+
const detection = detectPlatform(args.dir);
|
|
1023
|
+
console.log('\n📋 Step 1: Agent Platform Selection');
|
|
1024
|
+
console.log(` Detected suggestions: ${detection.suggestions.join(', ') || 'none'}`);
|
|
1025
|
+
const agentType = args.agent || detection.suggestions[0] || 'claude-code';
|
|
1026
|
+
console.log(` Using: ${agentType}`);
|
|
1027
|
+
// Step 2: Scenario mode
|
|
1028
|
+
console.log('\n📋 Step 2: Scenario Mode');
|
|
1029
|
+
console.log(' sandbox - No quality gates (POC/prototype)');
|
|
1030
|
+
console.log(' standard - Default quality gates');
|
|
1031
|
+
console.log(' critical - Hardened gates + manual approval');
|
|
1032
|
+
const scenarioMode = args.scenario;
|
|
1033
|
+
console.log(` Using: ${scenarioMode}`);
|
|
1034
|
+
// Step 3: Quality Gate Thresholds (quantified)
|
|
1035
|
+
console.log('\n📋 Step 3: Quality Gate Thresholds');
|
|
1036
|
+
const coverageThreshold = parseInt(args['coverage-threshold'], 10) || 80;
|
|
1037
|
+
const retryThreshold = parseInt(args['retry-threshold'], 10) || 3;
|
|
1038
|
+
const blockSeverity = args['block-severity'] || 'CRITICAL';
|
|
1039
|
+
console.log(` Coverage threshold: ${coverageThreshold}%`);
|
|
1040
|
+
console.log(` Retry threshold: ${retryThreshold} (brute retry block)`);
|
|
1041
|
+
console.log(` Block severity: ${blockSeverity}`);
|
|
1042
|
+
// Step 4: Write thresholds to .scale/thresholds.json
|
|
1043
|
+
const thresholdsPath = join(args.dir, '.scale', 'thresholds.json');
|
|
1044
|
+
ensureDir(join(args.dir, '.scale'));
|
|
1045
|
+
writeFileSync(thresholdsPath, JSON.stringify({
|
|
1046
|
+
coverage: { minimum: coverageThreshold, unit: 'percent' },
|
|
1047
|
+
retry: { bruteMaximum: retryThreshold, unit: 'count' },
|
|
1048
|
+
severity: { blockLevel: blockSeverity },
|
|
1049
|
+
gates: {
|
|
1050
|
+
G3_build: { required: scenarioMode !== 'sandbox', exitCode: 0 },
|
|
1051
|
+
G4_lint: { required: scenarioMode !== 'sandbox', exitCode: 0 },
|
|
1052
|
+
G5_tests: { required: scenarioMode !== 'sandbox', allPass: true },
|
|
1053
|
+
G6_coverage: { required: scenarioMode !== 'sandbox', minimum: coverageThreshold },
|
|
1054
|
+
G7_security: { required: scenarioMode === 'critical', noCritical: true },
|
|
1055
|
+
},
|
|
1056
|
+
}, null, 2));
|
|
1057
|
+
console.log(`\n ✓ Thresholds written to: ${thresholdsPath}`);
|
|
1058
|
+
// Initialize with adapter
|
|
1059
|
+
const adapter = createAdapter(agentType);
|
|
1060
|
+
const result = await adapter.init({
|
|
1061
|
+
projectDir: args.dir,
|
|
1062
|
+
agentType: agentType,
|
|
1063
|
+
scenarioMode,
|
|
1064
|
+
thresholdsPath,
|
|
1065
|
+
});
|
|
1066
|
+
const projectName = args.dir.split(/[/\\]/).pop() || 'Project';
|
|
1067
|
+
const governance = writeGovernanceTemplates(args.dir, {
|
|
1068
|
+
mode: governanceModeFromScenario(scenarioMode),
|
|
1069
|
+
projectName,
|
|
1070
|
+
});
|
|
1071
|
+
result.created.push(...governance.created);
|
|
1072
|
+
result.skipped.push(...governance.skipped);
|
|
1073
|
+
console.log(`\n✅ SCALE Engine initialized for ${agentType} (interactive mode)`);
|
|
1074
|
+
console.log(`\n📁 Created:`);
|
|
1075
|
+
for (const f of result.created)
|
|
1076
|
+
console.log(` + ${f}`);
|
|
1077
|
+
if (result.skipped.length > 0) {
|
|
1078
|
+
console.log(`\n⏭️ Skipped (already exist):`);
|
|
1079
|
+
for (const f of result.skipped)
|
|
1080
|
+
console.log(` - ${f}`);
|
|
1081
|
+
}
|
|
1082
|
+
console.log(`\n🔧 Configuration Summary:`);
|
|
1083
|
+
console.log(` Settings: ${result.settingsPath}`);
|
|
1084
|
+
console.log(` Knowledge: ${result.knowledgeDocPath}`);
|
|
1085
|
+
console.log(` Thresholds: ${thresholdsPath}`);
|
|
1086
|
+
console.log(` Data dir: ${result.scaleDir}`);
|
|
1087
|
+
console.log(` Scenario: ${scenarioMode}`);
|
|
1088
|
+
console.log(`\n📋 Next steps:`);
|
|
1089
|
+
console.log(` → scale doctor`);
|
|
1090
|
+
console.log(` → scale create Spec "<feature name>"`);
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
826
1093
|
// One-click quick start mode
|
|
827
1094
|
if (args.quick || !args.agent) {
|
|
828
1095
|
const qsResult = await quickStart(args.dir);
|
|
@@ -853,6 +1120,13 @@ const init = defineCommand({
|
|
|
853
1120
|
// Manual agent specification mode
|
|
854
1121
|
const adapter = createAdapter(args.agent);
|
|
855
1122
|
const result = await adapter.init({ projectDir: args.dir, agentType: args.agent, scenarioMode: args.scenario });
|
|
1123
|
+
const projectName = args.dir.split(/[/\\]/).pop() || 'Project';
|
|
1124
|
+
const governance = writeGovernanceTemplates(args.dir, {
|
|
1125
|
+
mode: governanceModeFromScenario(args.scenario),
|
|
1126
|
+
projectName,
|
|
1127
|
+
});
|
|
1128
|
+
result.created.push(...governance.created);
|
|
1129
|
+
result.skipped.push(...governance.skipped);
|
|
856
1130
|
console.log(`\n✅ SCALE Engine initialized for ${args.agent} (scenario: ${args.scenario})`);
|
|
857
1131
|
console.log(`\n📁 Created:`);
|
|
858
1132
|
for (const f of result.created)
|
|
@@ -1115,9 +1389,117 @@ const skillScan = defineCommand({
|
|
|
1115
1389
|
}
|
|
1116
1390
|
},
|
|
1117
1391
|
});
|
|
1392
|
+
const skillPlanCommand = defineCommand({
|
|
1393
|
+
meta: { name: 'plan', description: 'Create or refresh a task skill plan' },
|
|
1394
|
+
args: {
|
|
1395
|
+
'task-id': { type: 'positional', required: true },
|
|
1396
|
+
dir: { type: 'string', description: 'Task artifact directory; defaults to current state artifactsDir' },
|
|
1397
|
+
json: { type: 'boolean', default: false },
|
|
1398
|
+
},
|
|
1399
|
+
async run({ args }) {
|
|
1400
|
+
const { store } = getEngine();
|
|
1401
|
+
const task = await store.get(args['task-id']);
|
|
1402
|
+
if (!task || task.type !== 'Task') {
|
|
1403
|
+
console.error(`Task not found: ${args['task-id']}`);
|
|
1404
|
+
process.exit(1);
|
|
1405
|
+
}
|
|
1406
|
+
const payload = task.payload;
|
|
1407
|
+
const level = normalizeTaskArtifactLevel(payload.workflowLevel ?? 'M');
|
|
1408
|
+
const policy = loadSkillRoutingPolicy(PROJECT_DIR, SCALE_DIR);
|
|
1409
|
+
const plan = createSkillPlan({
|
|
1410
|
+
taskId: task.id,
|
|
1411
|
+
taskName: task.title,
|
|
1412
|
+
description: payload.description,
|
|
1413
|
+
level,
|
|
1414
|
+
services: payload.servicesTouched ?? [],
|
|
1415
|
+
files: payload.filesInvolved ?? [],
|
|
1416
|
+
policy,
|
|
1417
|
+
});
|
|
1418
|
+
const updatedPayload = {
|
|
1419
|
+
...payload,
|
|
1420
|
+
skillIntents: plan.intents.map(intent => intent.domain),
|
|
1421
|
+
skillRoutingMode: plan.mode,
|
|
1422
|
+
skillPlanRequired: plan.required,
|
|
1423
|
+
requiredSkills: plan.requiredSkills,
|
|
1424
|
+
recommendedSkills: plan.recommendedSkills,
|
|
1425
|
+
requiredSkillArtifacts: plan.requiredArtifacts,
|
|
1426
|
+
requiredSkillVerification: plan.requiredVerification,
|
|
1427
|
+
};
|
|
1428
|
+
await store.update(task.id, { payload: updatedPayload });
|
|
1429
|
+
const state = new WorkflowArtifactWriter(SCALE_DIR).readCurrentState();
|
|
1430
|
+
const artifactsDir = args.dir ?? (state?.taskId === task.id ? state.artifactsDir : undefined);
|
|
1431
|
+
let writtenPath;
|
|
1432
|
+
if (artifactsDir) {
|
|
1433
|
+
const dir = resolve(PROJECT_DIR, artifactsDir);
|
|
1434
|
+
ensureDir(dir);
|
|
1435
|
+
writtenPath = join(dir, 'skill-plan.md');
|
|
1436
|
+
writeFileSync(writtenPath, skillPlanMarkdown(plan), 'utf-8');
|
|
1437
|
+
}
|
|
1438
|
+
new WorkflowArtifactWriter(SCALE_DIR).updateCurrentState({
|
|
1439
|
+
taskId: task.id,
|
|
1440
|
+
level,
|
|
1441
|
+
phase: 'plan',
|
|
1442
|
+
artifactsDir,
|
|
1443
|
+
skillIntents: plan.intents.map(intent => intent.domain),
|
|
1444
|
+
skillRoutingMode: plan.mode,
|
|
1445
|
+
skillPlanRequired: plan.required,
|
|
1446
|
+
skillPlanPath: writtenPath,
|
|
1447
|
+
requiredSkills: plan.requiredSkills,
|
|
1448
|
+
recommendedSkills: plan.recommendedSkills,
|
|
1449
|
+
requiredSkillArtifacts: plan.requiredArtifacts,
|
|
1450
|
+
requiredSkillVerification: plan.requiredVerification,
|
|
1451
|
+
});
|
|
1452
|
+
if (args.json) {
|
|
1453
|
+
console.log(JSON.stringify({ plan, writtenPath }, null, 2));
|
|
1454
|
+
return;
|
|
1455
|
+
}
|
|
1456
|
+
console.log('\nSkill Plan');
|
|
1457
|
+
console.log(` Task: ${task.id}`);
|
|
1458
|
+
console.log(` Intents: ${plan.intents.map(intent => intent.domain).join(', ') || 'none'}`);
|
|
1459
|
+
console.log(` Required skills: ${plan.requiredSkills.join(', ') || 'none'}`);
|
|
1460
|
+
console.log(` Recommended skills: ${plan.recommendedSkills.join(', ') || 'none'}`);
|
|
1461
|
+
console.log(` Required artifacts: ${plan.requiredArtifacts.join(', ') || 'none'}`);
|
|
1462
|
+
if (writtenPath)
|
|
1463
|
+
console.log(` Written: ${writtenPath}`);
|
|
1464
|
+
},
|
|
1465
|
+
});
|
|
1466
|
+
const skillCheckCommand = defineCommand({
|
|
1467
|
+
meta: { name: 'check', description: 'Check required skill evidence artifacts' },
|
|
1468
|
+
args: {
|
|
1469
|
+
dir: { type: 'string', description: 'Task artifact directory; defaults to current state artifactsDir' },
|
|
1470
|
+
level: { type: 'string', description: 'Task level: S, M, L, or CRITICAL; defaults to current state level or M' },
|
|
1471
|
+
json: { type: 'boolean', default: false },
|
|
1472
|
+
},
|
|
1473
|
+
run({ args }) {
|
|
1474
|
+
const state = new WorkflowArtifactWriter(SCALE_DIR).readCurrentState();
|
|
1475
|
+
const level = normalizeTaskArtifactLevel(args.level ?? state?.level ?? 'M');
|
|
1476
|
+
const policy = loadSkillRoutingPolicy(PROJECT_DIR, SCALE_DIR);
|
|
1477
|
+
const result = evaluateSkillGate({
|
|
1478
|
+
projectDir: PROJECT_DIR,
|
|
1479
|
+
artifactsDir: args.dir ?? state?.artifactsDir,
|
|
1480
|
+
level,
|
|
1481
|
+
requiredArtifacts: state?.requiredSkillArtifacts,
|
|
1482
|
+
mode: state?.skillRoutingMode ?? policy.policy.mode,
|
|
1483
|
+
enforceLevels: policy.policy.enforceLevels,
|
|
1484
|
+
});
|
|
1485
|
+
if (args.json) {
|
|
1486
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1487
|
+
return;
|
|
1488
|
+
}
|
|
1489
|
+
console.log(`\nSkill Gate: ${result.complete ? 'COMPLETE' : 'INCOMPLETE'}`);
|
|
1490
|
+
console.log(` Mode: ${result.mode}`);
|
|
1491
|
+
console.log(` Required: ${result.required.join(', ') || 'none'}`);
|
|
1492
|
+
for (const file of result.missing)
|
|
1493
|
+
console.log(` [MISSING] ${file}`);
|
|
1494
|
+
for (const item of result.incomplete)
|
|
1495
|
+
console.log(` [INCOMPLETE] ${item.file}: ${item.reason}`);
|
|
1496
|
+
if (result.blocked)
|
|
1497
|
+
process.exitCode = 1;
|
|
1498
|
+
},
|
|
1499
|
+
});
|
|
1118
1500
|
const skill = defineCommand({
|
|
1119
1501
|
meta: { name: 'skill', description: 'Skill discovery and management' },
|
|
1120
|
-
subCommands: { scan: skillScan },
|
|
1502
|
+
subCommands: { scan: skillScan, plan: skillPlanCommand, check: skillCheckCommand },
|
|
1121
1503
|
});
|
|
1122
1504
|
// ============================================================================
|
|
1123
1505
|
// agent commands — Multi-Agent 协作系统 (Phase 9)
|
|
@@ -1242,11 +1624,16 @@ const team = defineCommand({
|
|
|
1242
1624
|
// ============================================================================
|
|
1243
1625
|
import * as phaseCommands from '../cli/phaseCommands.js';
|
|
1244
1626
|
import * as liteCommands from '../cli/liteCommands.js';
|
|
1627
|
+
import * as vibeCommands from '../cli/vibeCommands.js';
|
|
1245
1628
|
const main = defineCommand({
|
|
1246
|
-
meta: { name: 'scale', version: '0.
|
|
1629
|
+
meta: { name: 'scale', version: '0.13.0', description: 'SCALE Engine v0.13.0 CLI - hardened phase workflow gates: define/plan/build/verify/review/ship; Vibe templates: scale vibe; 16 platform adapters; 12 agents; 10 workflows; 19 detectors' },
|
|
1247
1630
|
subCommands: {
|
|
1248
1631
|
// Lite Mode (agent-skills style interactive entry)
|
|
1249
1632
|
lite: liteCommands.liteCommand,
|
|
1633
|
+
// Vibe Templates (one-click prompt workflow)
|
|
1634
|
+
vibe: vibeCommands.vibeCommand,
|
|
1635
|
+
'vibe-next': vibeCommands.vibeNextCommand,
|
|
1636
|
+
'vibe-index': vibeCommands.vibeIndexCommand,
|
|
1250
1637
|
// Phase-Aligned Commands (agent-skills style)
|
|
1251
1638
|
define: phaseCommands.phaseDefine,
|
|
1252
1639
|
plan: phaseCommands.phasePlan,
|
|
@@ -1269,10 +1656,14 @@ const main = defineCommand({
|
|
|
1269
1656
|
context,
|
|
1270
1657
|
evolve,
|
|
1271
1658
|
stats,
|
|
1659
|
+
preflight,
|
|
1660
|
+
metrics,
|
|
1661
|
+
'task-artifacts': taskArtifacts,
|
|
1272
1662
|
status,
|
|
1273
1663
|
workflow,
|
|
1274
1664
|
evidence,
|
|
1275
1665
|
skill,
|
|
1666
|
+
skills: skill,
|
|
1276
1667
|
agent,
|
|
1277
1668
|
team,
|
|
1278
1669
|
'create-prd': createPRD,
|