@hongmaple0820/scale-engine 0.40.1 → 0.43.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/api/cli.js +286 -7
- package/dist/api/cli.js.map +1 -1
- package/dist/api/doctor.js +1 -1
- package/dist/api/doctor.js.map +1 -1
- package/dist/api/quickstart.d.ts +11 -0
- package/dist/api/quickstart.js +98 -1
- package/dist/api/quickstart.js.map +1 -1
- package/dist/artifact/fsmDefinitions.js +15 -2
- package/dist/artifact/fsmDefinitions.js.map +1 -1
- package/dist/artifact/types.d.ts +1 -1
- package/dist/artifact/types.js.map +1 -1
- package/dist/bootstrap/DependencyBootstrap.d.ts +1 -0
- package/dist/bootstrap/DependencyBootstrap.js +137 -25
- package/dist/bootstrap/DependencyBootstrap.js.map +1 -1
- package/dist/cache/ScanCache.d.ts +41 -0
- package/dist/cache/ScanCache.js +120 -0
- package/dist/cache/ScanCache.js.map +1 -0
- package/dist/capabilities/BrowserQACapability.d.ts +14 -0
- package/dist/capabilities/BrowserQACapability.js +94 -0
- package/dist/capabilities/BrowserQACapability.js.map +1 -1
- package/dist/capabilities/InstalledSkillsIntegration.js +29 -9
- package/dist/capabilities/InstalledSkillsIntegration.js.map +1 -1
- package/dist/cli/autofixCommands.d.ts +22 -0
- package/dist/cli/autofixCommands.js +32 -0
- package/dist/cli/autofixCommands.js.map +1 -0
- package/dist/cli/cortexCommands.d.ts +71 -0
- package/dist/cli/cortexCommands.js +335 -0
- package/dist/cli/cortexCommands.js.map +1 -0
- package/dist/cli/costCommands.d.ts +13 -0
- package/dist/cli/costCommands.js +48 -0
- package/dist/cli/costCommands.js.map +1 -0
- package/dist/cli/orchCommands.d.ts +43 -0
- package/dist/cli/orchCommands.js +135 -0
- package/dist/cli/orchCommands.js.map +1 -0
- package/dist/cli/phaseCommands.js +1 -2
- package/dist/cli/phaseCommands.js.map +1 -1
- package/dist/cli/qaCommands.d.ts +22 -0
- package/dist/cli/qaCommands.js +84 -0
- package/dist/cli/qaCommands.js.map +1 -0
- package/dist/cli/quickstartCommands.d.ts +17 -0
- package/dist/cli/quickstartCommands.js +47 -0
- package/dist/cli/quickstartCommands.js.map +1 -0
- package/dist/cli/shieldCommands.d.ts +30 -0
- package/dist/cli/shieldCommands.js +212 -0
- package/dist/cli/shieldCommands.js.map +1 -0
- package/dist/cli/tuiCommands.d.ts +7 -0
- package/dist/cli/tuiCommands.js +33 -0
- package/dist/cli/tuiCommands.js.map +1 -0
- package/dist/config/profiles.js +26 -0
- package/dist/config/profiles.js.map +1 -1
- package/dist/context/ContextBudget.js +2 -2
- package/dist/core/GbrainRuntime.d.ts +25 -0
- package/dist/core/GbrainRuntime.js +270 -0
- package/dist/core/GbrainRuntime.js.map +1 -0
- package/dist/cortex/GovernanceMetrics.d.ts +66 -0
- package/dist/cortex/GovernanceMetrics.js +230 -0
- package/dist/cortex/GovernanceMetrics.js.map +1 -0
- package/dist/cortex/InstinctExtractor.d.ts +61 -0
- package/dist/cortex/InstinctExtractor.js +184 -0
- package/dist/cortex/InstinctExtractor.js.map +1 -0
- package/dist/cortex/InstinctStore.d.ts +54 -0
- package/dist/cortex/InstinctStore.js +266 -0
- package/dist/cortex/InstinctStore.js.map +1 -0
- package/dist/cortex/ReflexionEngine.d.ts +34 -0
- package/dist/cortex/ReflexionEngine.js +157 -0
- package/dist/cortex/ReflexionEngine.js.map +1 -0
- package/dist/cortex/SessionInjector.d.ts +44 -0
- package/dist/cortex/SessionInjector.js +127 -0
- package/dist/cortex/SessionInjector.js.map +1 -0
- package/dist/cortex/adapters/ClaudeAdapter.d.ts +17 -0
- package/dist/cortex/adapters/ClaudeAdapter.js +61 -0
- package/dist/cortex/adapters/ClaudeAdapter.js.map +1 -0
- package/dist/cortex/adapters/CodexAdapter.d.ts +10 -0
- package/dist/cortex/adapters/CodexAdapter.js +52 -0
- package/dist/cortex/adapters/CodexAdapter.js.map +1 -0
- package/dist/cortex/adapters/CursorAdapter.d.ts +10 -0
- package/dist/cortex/adapters/CursorAdapter.js +46 -0
- package/dist/cortex/adapters/CursorAdapter.js.map +1 -0
- package/dist/cortex/adapters/GeminiAdapter.d.ts +11 -0
- package/dist/cortex/adapters/GeminiAdapter.js +48 -0
- package/dist/cortex/adapters/GeminiAdapter.js.map +1 -0
- package/dist/env/EnvironmentDoctor.js +221 -5
- package/dist/env/EnvironmentDoctor.js.map +1 -1
- package/dist/eval/BenchmarkPublisher.d.ts +25 -0
- package/dist/eval/BenchmarkPublisher.js +27 -0
- package/dist/eval/BenchmarkPublisher.js.map +1 -0
- package/dist/guardrails/DependencyAuditor.js +10 -1
- package/dist/guardrails/DependencyAuditor.js.map +1 -1
- package/dist/memory/MemoryProviders.js +38 -91
- package/dist/memory/MemoryProviders.js.map +1 -1
- package/dist/orchestrator/OrchestratorDaemon.d.ts +44 -0
- package/dist/orchestrator/OrchestratorDaemon.js +150 -0
- package/dist/orchestrator/OrchestratorDaemon.js.map +1 -0
- package/dist/orchestrator/PolicyLoader.d.ts +80 -0
- package/dist/orchestrator/PolicyLoader.js +229 -0
- package/dist/orchestrator/PolicyLoader.js.map +1 -0
- package/dist/orchestrator/ReconciliationLoop.d.ts +71 -0
- package/dist/orchestrator/ReconciliationLoop.js +266 -0
- package/dist/orchestrator/ReconciliationLoop.js.map +1 -0
- package/dist/orchestrator/TrackerAdapter.d.ts +60 -0
- package/dist/orchestrator/TrackerAdapter.js +147 -0
- package/dist/orchestrator/TrackerAdapter.js.map +1 -0
- package/dist/orchestrator/WorkspaceManager.d.ts +66 -0
- package/dist/orchestrator/WorkspaceManager.js +257 -0
- package/dist/orchestrator/WorkspaceManager.js.map +1 -0
- package/dist/qa/BrowserDaemon.d.ts +23 -0
- package/dist/qa/BrowserDaemon.js +79 -0
- package/dist/qa/BrowserDaemon.js.map +1 -0
- package/dist/qa/E2ETestOrchestrator.d.ts +14 -0
- package/dist/qa/E2ETestOrchestrator.js +19 -0
- package/dist/qa/E2ETestOrchestrator.js.map +1 -0
- package/dist/review/CrossModelReviewer.d.ts +35 -0
- package/dist/review/CrossModelReviewer.js +75 -0
- package/dist/review/CrossModelReviewer.js.map +1 -0
- package/dist/review/ReviewAggregator.d.ts +13 -0
- package/dist/review/ReviewAggregator.js +28 -0
- package/dist/review/ReviewAggregator.js.map +1 -0
- package/dist/review/reviewCommands.d.ts +15 -0
- package/dist/review/reviewCommands.js +24 -0
- package/dist/review/reviewCommands.js.map +1 -0
- package/dist/routing/LocalModelProvider.d.ts +11 -0
- package/dist/routing/LocalModelProvider.js +21 -0
- package/dist/routing/LocalModelProvider.js.map +1 -0
- package/dist/routing/ModelRouter.d.ts +12 -0
- package/dist/routing/ModelRouter.js +31 -4
- package/dist/routing/ModelRouter.js.map +1 -1
- package/dist/runtime/AiOsRuntime.d.ts +1 -0
- package/dist/runtime/AiOsRuntime.js +15 -0
- package/dist/runtime/AiOsRuntime.js.map +1 -1
- package/dist/runtime/CostAnalyzer.d.ts +53 -0
- package/dist/runtime/CostAnalyzer.js +160 -0
- package/dist/runtime/CostAnalyzer.js.map +1 -0
- package/dist/runtime/CostOptimizer.d.ts +11 -0
- package/dist/runtime/CostOptimizer.js +21 -0
- package/dist/runtime/CostOptimizer.js.map +1 -0
- package/dist/runtime/ModelUsageLedger.d.ts +53 -2
- package/dist/runtime/ModelUsageLedger.js +243 -39
- package/dist/runtime/ModelUsageLedger.js.map +1 -1
- package/dist/setup/SetupVerification.d.ts +42 -0
- package/dist/setup/SetupVerification.js +180 -0
- package/dist/setup/SetupVerification.js.map +1 -0
- package/dist/shield/PolicyCompiler.d.ts +70 -0
- package/dist/shield/PolicyCompiler.js +540 -0
- package/dist/shield/PolicyCompiler.js.map +1 -0
- package/dist/shield/ProtectedPaths.d.ts +39 -0
- package/dist/shield/ProtectedPaths.js +179 -0
- package/dist/shield/ProtectedPaths.js.map +1 -0
- package/dist/shield/ShieldProtocol.d.ts +50 -0
- package/dist/shield/ShieldProtocol.js +103 -0
- package/dist/shield/ShieldProtocol.js.map +1 -0
- package/dist/skills/SkillMdStandard.d.ts +33 -0
- package/dist/skills/SkillMdStandard.js +88 -0
- package/dist/skills/SkillMdStandard.js.map +1 -0
- package/dist/skills/SkillRegistry.d.ts +9 -1
- package/dist/skills/SkillRegistry.js +20 -0
- package/dist/skills/SkillRegistry.js.map +1 -1
- package/dist/skills/interop/GStackInterop.d.ts +15 -0
- package/dist/skills/interop/GStackInterop.js +34 -0
- package/dist/skills/interop/GStackInterop.js.map +1 -0
- package/dist/skills/interop/OMCInterop.d.ts +15 -0
- package/dist/skills/interop/OMCInterop.js +34 -0
- package/dist/skills/interop/OMCInterop.js.map +1 -0
- package/dist/tools/ToolCapabilityRegistry.js +10 -0
- package/dist/tools/ToolCapabilityRegistry.js.map +1 -1
- package/dist/tui/TuiDashboard.d.ts +3 -0
- package/dist/tui/TuiDashboard.js +120 -0
- package/dist/tui/TuiDashboard.js.map +1 -0
- package/dist/workflow/GateCatalog.d.ts +2 -0
- package/dist/workflow/GateCatalog.js +59 -3
- package/dist/workflow/GateCatalog.js.map +1 -1
- package/dist/workflow/GovernanceTemplatePacks.d.ts +1 -1
- package/dist/workflow/GovernanceTemplatePacks.js +15 -0
- package/dist/workflow/GovernanceTemplatePacks.js.map +1 -1
- package/dist/workflow/TddLoop.d.ts +2 -0
- package/dist/workflow/TddLoop.js +2 -0
- package/dist/workflow/TddLoop.js.map +1 -1
- package/dist/workflow/UpgradeManager.d.ts +10 -1
- package/dist/workflow/UpgradeManager.js +55 -0
- package/dist/workflow/UpgradeManager.js.map +1 -1
- package/dist/workflow/VerificationProfile.d.ts +8 -0
- package/dist/workflow/VerificationProfile.js +62 -1
- package/dist/workflow/VerificationProfile.js.map +1 -1
- package/dist/workflow/VerificationSchema.d.ts +46 -0
- package/dist/workflow/VerificationSchema.js +97 -0
- package/dist/workflow/VerificationSchema.js.map +1 -0
- package/dist/workflow/autofix/AutoFixEngine.d.ts +37 -0
- package/dist/workflow/autofix/AutoFixEngine.js +169 -0
- package/dist/workflow/autofix/AutoFixEngine.js.map +1 -0
- package/dist/workflow/execution/RalphEngine.d.ts +18 -0
- package/dist/workflow/execution/RalphEngine.js +22 -0
- package/dist/workflow/execution/RalphEngine.js.map +1 -1
- package/dist/workflow/gates/EnhancedGates.d.ts +74 -0
- package/dist/workflow/gates/EnhancedGates.js +653 -0
- package/dist/workflow/gates/EnhancedGates.js.map +1 -0
- package/dist/workflow/gates/GateSystem.d.ts +3 -0
- package/dist/workflow/gates/GateSystem.js +94 -1
- package/dist/workflow/gates/GateSystem.js.map +1 -1
- package/dist/workflow/types.d.ts +1 -1
- package/docs/README.md +3 -0
- package/docs/guides/DEVELOPMENT_WORKFLOW.md +28 -9
- package/docs/guides/GETTING_STARTED.md +19 -0
- package/docs/guides/MIGRATION.md +119 -0
- package/docs/start/quickstart.md +1 -0
- package/docs/workflow/GATES_AND_SCORE.md +34 -1
- package/docs/workflow/README.md +58 -10
- package/package.json +7 -18
- package/scripts/workflow/lib/gbrain-runtime.mjs +185 -0
- package/scripts/workflow/lib/report-output.mjs +107 -0
- package/scripts/workflow/provider-rehearsal.mjs +129 -48
- package/scripts/workflow/setup-smoke.mjs +142 -8
- package/docs/ACTIVE_SECURITY_VISUAL_GATES.md +0 -87
- package/docs/AI_ENGINEERING_OS_POSITIONING.md +0 -607
- package/docs/BACKGROUND_HUNTER.md +0 -62
- package/docs/CODE_INTELLIGENCE.md +0 -180
- package/docs/CONTEXT_BUDGET.md +0 -155
- package/docs/DEPENDENCY_AUDIT.md +0 -118
- package/docs/EVOLUTION_SHADOW_MODE.md +0 -63
- package/docs/GITLAB_FLOW.md +0 -125
- package/docs/GOVERNANCE_DASHBOARD.md +0 -85
- package/docs/MEMORY_BRAIN.md +0 -104
- package/docs/MEMORY_FABRIC.md +0 -161
- package/docs/RESOURCE_GOVERNANCE.md +0 -92
- package/docs/RUNTIME_EVIDENCE.md +0 -101
- package/docs/WORKFLOW_EVAL.md +0 -151
- package/image/wechat-public.jpg +0 -0
- package/image/wxPay.jpg +0 -0
- package/image/zfb.jpg +0 -0
|
@@ -10,10 +10,11 @@ Use `scale gates status` to inspect the active gate catalog.
|
|
|
10
10
|
scale gates status --json
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
The report separates
|
|
13
|
+
The report separates four concepts that were previously easy to confuse:
|
|
14
14
|
|
|
15
15
|
- Core gates: `G0-G8`, used by workflow verification, preflight, and product smoke profiles.
|
|
16
16
|
- Meta-governance gates: `G9-G15`, used by `scale meta-governance`.
|
|
17
|
+
- Enhanced gates: `G16-G22`, covering commit discipline, doc hygiene, runtime evidence, code review, supply chain, context budget, and session health.
|
|
17
18
|
- Extension gates: policy-backed checks such as engineering standards, product smoke policy, and tool evidence.
|
|
18
19
|
|
|
19
20
|
`scale gates status` is intentionally read-only. It does not execute checks; it explains which checks exist and which policies are blocking.
|
|
@@ -28,6 +29,38 @@ Architecture and engineering standards are driven by project configuration:
|
|
|
28
29
|
|
|
29
30
|
Preflight now uses changed-file standards scope when the target is inside a Git worktree. Non-Git projects keep the old full-scan behavior so bootstrap and fixture projects still get complete feedback.
|
|
30
31
|
|
|
32
|
+
## Enhanced Gates (G16-G22)
|
|
33
|
+
|
|
34
|
+
Added in v0.41.0, these gates cover commit discipline, runtime quality, and session hygiene:
|
|
35
|
+
|
|
36
|
+
| Gate | Name | Blocking | Description |
|
|
37
|
+
| --- | --- | --- | --- |
|
|
38
|
+
| G16 | Commit Discipline | ✅ | Uncommitted file count (warn=10, block=25), time since last commit (warn=60min, block=180min), staged files >1MB, whitespace errors |
|
|
39
|
+
| G17 | Documentation Hygiene | — | Changed markdown files must have valid internal links |
|
|
40
|
+
| G18 | Runtime Evidence | ✅ | Task must have recorded runtime evidence with matching exit codes |
|
|
41
|
+
| G19 | Code Review | ✅ (L/CRITICAL) | L and CRITICAL tasks require reviewed changes with resolved findings |
|
|
42
|
+
| G20 | Supply Chain | ✅ | No CRITICAL/HIGH vulnerabilities; lock file must be consistent |
|
|
43
|
+
| G21 | Context Budget | — | Advisory check on context token usage against configured budget |
|
|
44
|
+
| G22 | Session Health | — | Advisory check on stale worktrees and session state consistency |
|
|
45
|
+
|
|
46
|
+
Run enhanced gates individually:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
bash scripts/gates/G16-verify.sh # Commit Discipline
|
|
50
|
+
bash scripts/gates/G17-verify.sh # Documentation Hygiene
|
|
51
|
+
bash scripts/gates/G18-verify.sh # Runtime Evidence
|
|
52
|
+
bash scripts/gates/G19-verify.sh # Code Review
|
|
53
|
+
bash scripts/gates/G20-verify.sh # Supply Chain
|
|
54
|
+
bash scripts/gates/G21-verify.sh # Context Budget
|
|
55
|
+
bash scripts/gates/G22-verify.sh # Session Health
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Or run all gates including enhanced:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
bash scripts/gates/all.sh --all
|
|
62
|
+
```
|
|
63
|
+
|
|
31
64
|
## Task Score
|
|
32
65
|
|
|
33
66
|
Use `scale score task` to produce an algorithmic completion score.
|
package/docs/workflow/README.md
CHANGED
|
@@ -23,6 +23,25 @@ scale score task --changed --json
|
|
|
23
23
|
scale prompt optimize --input "raw coding request" --json
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
+
### SCALE 2.0 引擎命令
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Scale Shield — 钩子拦截
|
|
30
|
+
scale shield compile # 编译策略 + 安装 hook
|
|
31
|
+
scale shield status # 验证 hook 注册 + .scale/ 完整性
|
|
32
|
+
scale shield test # 运行 allow/block 测试
|
|
33
|
+
|
|
34
|
+
# Scale Orchestrator — 编排守护进程
|
|
35
|
+
scale orch start # 启动 daemon
|
|
36
|
+
scale orch status # 查看状态 + workspace 列表
|
|
37
|
+
|
|
38
|
+
# Scale Cortex — 持续进化
|
|
39
|
+
scale cortex evolve # 完整进化周期
|
|
40
|
+
scale cortex extract # 提取 Instincts
|
|
41
|
+
scale cortex inject --minimal # 预览 SessionStart 注入
|
|
42
|
+
scale cortex metrics --days 30 # 治理 ROI 报告
|
|
43
|
+
```
|
|
44
|
+
|
|
26
45
|
PowerShell:
|
|
27
46
|
|
|
28
47
|
```powershell
|
|
@@ -35,16 +54,45 @@ See [PROMPT_OPTIMIZATION.md](PROMPT_OPTIMIZATION.md) for the deterministic promp
|
|
|
35
54
|
|
|
36
55
|
## 门禁说明
|
|
37
56
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
|
43
|
-
|
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
57
|
+
SCALE 2.0 共 23 个门禁,分三层:核心门禁(G0-G8)、元治理门禁(G9-G15)、增强门禁(G16-G22)。
|
|
58
|
+
|
|
59
|
+
### 核心门禁(G0-G8)
|
|
60
|
+
|
|
61
|
+
| Gate | 作用 | 默认 | 阻断 |
|
|
62
|
+
| --- | | --- | --- |
|
|
63
|
+
| G0 | 构建命令或配置的验证命令必须通过 | ✅ | ✅ |
|
|
64
|
+
| G1 | 探索是否记录到状态文件,且至少读了 3 个文件 | ✅ | — |
|
|
65
|
+
| G2 | 计划是否包含边界、异常、回滚、现实校验 | ✅ | — |
|
|
66
|
+
| G3 | `src/` 行为改动是否伴随测试改动 | ✅ | ✅ |
|
|
67
|
+
| G4 | lint 命令必须通过 | ✅ | ✅ |
|
|
68
|
+
| G5 | 测试命令必须通过 | ✅ | ✅ |
|
|
69
|
+
| G6 | 覆盖率、任务证据和 diff hygiene 必须满足当前 profile | profile | ✅ |
|
|
70
|
+
| G7 | 安全和依赖风险检查必须通过 | profile | ✅ |
|
|
71
|
+
| G8 | 产品冒烟命令必须通过 | profile | ✅ |
|
|
72
|
+
|
|
73
|
+
### 元治理门禁(G9-G15)
|
|
74
|
+
|
|
75
|
+
| Gate | 作用 | 默认 | 阻断 |
|
|
76
|
+
| --- | | --- | --- |
|
|
77
|
+
| G9 | 知识库和 recall 能力是否被使用 | ✅ | — |
|
|
78
|
+
| G10 | 改进候选是否有证据支撑 | — | — |
|
|
79
|
+
| G11 | 护栏结果是否可见且可操作 | ✅ | — |
|
|
80
|
+
| G12 | 工作流阶段和制品是否完整 | ✅ | — |
|
|
81
|
+
| G13 | 多 Agent 协作是否有协调证据 | — | — |
|
|
82
|
+
| G14 | 必需 skill 是否被选择和验证 | — | — |
|
|
83
|
+
| G15 | 经验教训是否安全进入学习循环 | — | — |
|
|
84
|
+
|
|
85
|
+
### 增强门禁(G16-G22)
|
|
86
|
+
|
|
87
|
+
| Gate | 作用 | 默认 | 阻断 |
|
|
88
|
+
| --- | | --- | --- |
|
|
89
|
+
| G16 | 未提交文件数量和大文件阈值检查 | ✅ | ✅ |
|
|
90
|
+
| G17 | 变更的文档链接有效性检查 | ✅ | — |
|
|
91
|
+
| G18 | 运行时证据记录和退出码匹配 | ✅ | ✅ |
|
|
92
|
+
| G19 | L/CRITICAL 任务需要代码审查记录 | profile | ✅ |
|
|
93
|
+
| G20 | 无 CRITICAL/HIGH 漏洞;lock 文件一致性 | ✅ | ✅ |
|
|
94
|
+
| G21 | 上下文 token 预算检查(advisory) | ✅ | — |
|
|
95
|
+
| G22 | 会话健康检查:worktree 泄露和状态一致性 | ✅ | — |
|
|
48
96
|
|
|
49
97
|
## 分支策略
|
|
50
98
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hongmaple0820/scale-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.43.0",
|
|
4
4
|
"description": "Executable AI agent governance with workflow gates, evidence, skill/tool orchestration, and traceable HTML artifacts",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -25,29 +25,15 @@
|
|
|
25
25
|
"files": [
|
|
26
26
|
"dist",
|
|
27
27
|
"docs/README.md",
|
|
28
|
-
"docs/AI_ENGINEERING_OS_POSITIONING.md",
|
|
29
|
-
"docs/CODE_INTELLIGENCE.md",
|
|
30
|
-
"docs/CONTEXT_BUDGET.md",
|
|
31
|
-
"docs/BACKGROUND_HUNTER.md",
|
|
32
|
-
"docs/DEPENDENCY_AUDIT.md",
|
|
33
|
-
"docs/ACTIVE_SECURITY_VISUAL_GATES.md",
|
|
34
|
-
"docs/EVOLUTION_SHADOW_MODE.md",
|
|
35
|
-
"docs/WORKFLOW_EVAL.md",
|
|
36
28
|
"docs/SKILL_RADAR.md",
|
|
37
29
|
"docs/SKILL-REPOSITORY.md",
|
|
38
|
-
"docs/THIRD_PARTY_SKILLS.md",
|
|
39
30
|
"docs/EXTERNAL_REFERENCES.md",
|
|
40
|
-
"docs/
|
|
41
|
-
"docs/GOVERNANCE_DASHBOARD.md",
|
|
42
|
-
"docs/GITLAB_FLOW.md",
|
|
43
|
-
"docs/MEMORY_FABRIC.md",
|
|
44
|
-
"docs/RUNTIME_EVIDENCE.md",
|
|
45
|
-
"docs/RESOURCE_GOVERNANCE.md",
|
|
31
|
+
"docs/THIRD_PARTY_SKILLS.md",
|
|
46
32
|
"docs/guides",
|
|
47
33
|
"docs/start",
|
|
48
34
|
"docs/workflow",
|
|
49
|
-
"image",
|
|
50
35
|
"examples/demo-projects/agent-governance-demo",
|
|
36
|
+
"scripts/workflow/lib",
|
|
51
37
|
"scripts/workflow/setup-smoke.mjs",
|
|
52
38
|
"scripts/workflow/provider-rehearsal.mjs"
|
|
53
39
|
],
|
|
@@ -65,7 +51,7 @@
|
|
|
65
51
|
"smoke:providers": "node scripts/workflow/provider-rehearsal.mjs",
|
|
66
52
|
"smoke:gbrain": "node scripts/workflow/provider-rehearsal.mjs --skip-graphify --require-gbrain",
|
|
67
53
|
"smoke:graphify": "node scripts/workflow/provider-rehearsal.mjs --skip-gbrain --require-graphify",
|
|
68
|
-
"release:check": "npm run typecheck && npm run lint && npm test && npm run smoke:setup && npm run build && npm audit --omit=dev && git diff --check && npm pack --dry-run",
|
|
54
|
+
"release:check": "npm run typecheck && npm run lint && npm test && npm run smoke:setup && npm run smoke:providers -- --write-report && npm run build && npm audit --omit=dev && git diff --check && npm pack --dry-run",
|
|
69
55
|
"mcp": "node dist/api/mcp.js",
|
|
70
56
|
"serve": "node dist/api/http.js"
|
|
71
57
|
},
|
|
@@ -88,6 +74,9 @@
|
|
|
88
74
|
"type-is": "2.0.1",
|
|
89
75
|
"qs": "6.15.2"
|
|
90
76
|
},
|
|
77
|
+
"optionalDependencies": {
|
|
78
|
+
"playwright": "^1.50.0"
|
|
79
|
+
},
|
|
91
80
|
"devDependencies": {
|
|
92
81
|
"@types/better-sqlite3": "^7.6.0",
|
|
93
82
|
"@types/js-yaml": "^4.0.9",
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto'
|
|
2
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs'
|
|
3
|
+
import { tmpdir } from 'node:os'
|
|
4
|
+
import { dirname, join, resolve } from 'node:path'
|
|
5
|
+
|
|
6
|
+
const MIRROR_META_FILE = '.scale-gbrain-runtime.json'
|
|
7
|
+
const GBRAIN_TIMEOUT_RECOVERY_COMMANDS = new Set(['--version', 'version', 'doctor', 'list', 'get', 'query', 'search'])
|
|
8
|
+
|
|
9
|
+
export function resolveDirectWindowsGbrainInvocation(command, args, resolveCommandPath) {
|
|
10
|
+
if (process.platform !== 'win32' || command !== 'gbrain') return null
|
|
11
|
+
const gbrainShim = resolveCommandPath('gbrain')
|
|
12
|
+
if (!gbrainShim || !/\.cmd$/i.test(gbrainShim) || !existsSync(gbrainShim)) return null
|
|
13
|
+
try {
|
|
14
|
+
const content = readFileSync(gbrainShim, 'utf8')
|
|
15
|
+
const match = content.match(/call\s+"([^"]*bun\.cmd)"\s+"([^"]*src[\\/]cli\.ts)"/i)
|
|
16
|
+
const cliPath = match?.[2]
|
|
17
|
+
const bunShim = match?.[1] ?? resolveCommandPath('bun')
|
|
18
|
+
const bunExe = bunShim ? join(dirname(bunShim), 'node_modules', 'bun', 'bin', 'bun.exe') : ''
|
|
19
|
+
if (cliPath && bunExe && existsSync(bunExe)) {
|
|
20
|
+
return {
|
|
21
|
+
command: bunExe,
|
|
22
|
+
args: [cliPath, ...args],
|
|
23
|
+
cwd: dirname(dirname(cliPath)),
|
|
24
|
+
cliPath,
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
} catch {
|
|
28
|
+
return null
|
|
29
|
+
}
|
|
30
|
+
return null
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function shouldRetryWithMirroredGbrain(invocation, result) {
|
|
34
|
+
if (!invocation?.cliPath) return false
|
|
35
|
+
if (result.status === 0) return false
|
|
36
|
+
const output = `${String(result.stdout ?? '')}\n${String(result.stderr ?? '')}\n${String(result.error?.message ?? '')}`
|
|
37
|
+
if (!/EPERM reading/i.test(output)) return false
|
|
38
|
+
return normalizeForCompare(output).includes(normalizeForCompare(invocation.cliPath))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function ensureMirroredGbrainInvocation(invocation) {
|
|
42
|
+
const packageRoot = invocation.cwd
|
|
43
|
+
const cliMtimeMs = statSync(invocation.cliPath).mtimeMs
|
|
44
|
+
const version = readPackageVersion(packageRoot)
|
|
45
|
+
const mirrorKey = `${resolve(packageRoot)}|${version ?? ''}|${cliMtimeMs}`
|
|
46
|
+
const mirrorRoot = join(
|
|
47
|
+
tmpdir(),
|
|
48
|
+
'scale-engine',
|
|
49
|
+
'gbrain-runtime',
|
|
50
|
+
createHash('sha1').update(mirrorKey).digest('hex').slice(0, 16),
|
|
51
|
+
)
|
|
52
|
+
const cliRelativePath = invocation.cliPath.slice(packageRoot.length + 1)
|
|
53
|
+
const mirrorCliPath = join(mirrorRoot, cliRelativePath)
|
|
54
|
+
let selectedRoot = mirrorRoot
|
|
55
|
+
if (!isMirrorFresh(mirrorRoot, packageRoot, version, cliMtimeMs, mirrorCliPath)) {
|
|
56
|
+
const stagedRoot = `${mirrorRoot}-staging-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2, 8)}`
|
|
57
|
+
rmSync(stagedRoot, { recursive: true, force: true })
|
|
58
|
+
mkdirSync(dirname(mirrorRoot), { recursive: true })
|
|
59
|
+
cpSync(packageRoot, stagedRoot, { recursive: true, force: true })
|
|
60
|
+
writeFileSync(join(stagedRoot, MIRROR_META_FILE), JSON.stringify({
|
|
61
|
+
sourceRoot: packageRoot,
|
|
62
|
+
version,
|
|
63
|
+
cliMtimeMs,
|
|
64
|
+
}, null, 2), 'utf8')
|
|
65
|
+
const stagedCliPath = join(stagedRoot, cliRelativePath)
|
|
66
|
+
if (!isMirrorFresh(mirrorRoot, packageRoot, version, cliMtimeMs, mirrorCliPath)) {
|
|
67
|
+
try {
|
|
68
|
+
renameSync(stagedRoot, mirrorRoot)
|
|
69
|
+
} catch {
|
|
70
|
+
if (isMirrorFresh(mirrorRoot, packageRoot, version, cliMtimeMs, mirrorCliPath)) {
|
|
71
|
+
rmSync(stagedRoot, { recursive: true, force: true })
|
|
72
|
+
} else {
|
|
73
|
+
selectedRoot = stagedRoot
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
rmSync(stagedRoot, { recursive: true, force: true })
|
|
78
|
+
}
|
|
79
|
+
if (selectedRoot === mirrorRoot && !existsSync(mirrorCliPath) && existsSync(stagedCliPath)) selectedRoot = stagedRoot
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
...invocation,
|
|
83
|
+
args: [join(selectedRoot, cliRelativePath), ...invocation.args.slice(1)],
|
|
84
|
+
cwd: selectedRoot,
|
|
85
|
+
cliPath: join(selectedRoot, cliRelativePath),
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function normalizeGbrainSpawnResult(args, result) {
|
|
90
|
+
const stdout = String(result.stdout ?? '')
|
|
91
|
+
const stderr = `${String(result.stderr ?? '')}${result.error ? `\n${result.error.message}` : ''}`.trim()
|
|
92
|
+
const exitCode = typeof result.status === 'number' ? result.status : 1
|
|
93
|
+
const timedOut = /ETIMEDOUT/i.test(String(result.error?.message ?? ''))
|
|
94
|
+
const recoveredTimeout = shouldRecoverGbrainTimeout(args, stdout, stderr, exitCode, timedOut)
|
|
95
|
+
return {
|
|
96
|
+
stdout,
|
|
97
|
+
stderr: recoveredTimeout ? stripRecoverableTimeoutNoise(stderr) : stderr,
|
|
98
|
+
exitCode: recoveredTimeout ? 0 : exitCode,
|
|
99
|
+
timedOut: recoveredTimeout ? false : timedOut,
|
|
100
|
+
recoveredTimeout,
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function isMirrorFresh(mirrorRoot, sourceRoot, version, cliMtimeMs, mirrorCliPath) {
|
|
105
|
+
if (!existsSync(mirrorCliPath)) return false
|
|
106
|
+
const metadataPath = join(mirrorRoot, MIRROR_META_FILE)
|
|
107
|
+
if (!existsSync(metadataPath)) return false
|
|
108
|
+
try {
|
|
109
|
+
const parsed = JSON.parse(readFileSync(metadataPath, 'utf8'))
|
|
110
|
+
return parsed.sourceRoot === sourceRoot
|
|
111
|
+
&& parsed.version === version
|
|
112
|
+
&& parsed.cliMtimeMs === cliMtimeMs
|
|
113
|
+
} catch {
|
|
114
|
+
return false
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function readPackageVersion(packageRoot) {
|
|
119
|
+
try {
|
|
120
|
+
const parsed = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8'))
|
|
121
|
+
return typeof parsed.version === 'string' ? parsed.version : undefined
|
|
122
|
+
} catch {
|
|
123
|
+
return undefined
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function normalizeForCompare(value) {
|
|
128
|
+
return String(value).replace(/\//g, '\\').toLowerCase()
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function shouldRecoverGbrainTimeout(args, stdout, stderr, exitCode, timedOut) {
|
|
132
|
+
if (!timedOut || exitCode === 0) return false
|
|
133
|
+
const command = String(args?.[0] ?? '').trim().toLowerCase()
|
|
134
|
+
if (!command || !GBRAIN_TIMEOUT_RECOVERY_COMMANDS.has(command)) return false
|
|
135
|
+
const cleanedStderr = stripRecoverableTimeoutNoise(stderr)
|
|
136
|
+
if (cleanedStderr) return false
|
|
137
|
+
return hasRecoverableGbrainOutput(command, stdout.trim())
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function hasRecoverableGbrainOutput(command, stdout) {
|
|
141
|
+
if (!stdout) return false
|
|
142
|
+
switch (command) {
|
|
143
|
+
case '--version':
|
|
144
|
+
case 'version':
|
|
145
|
+
return /\bgbrain\b/i.test(stdout) || /\d+\.\d+\.\d+/.test(stdout)
|
|
146
|
+
case 'doctor':
|
|
147
|
+
return looksLikeJsonOutput(stdout)
|
|
148
|
+
case 'list':
|
|
149
|
+
return /no pages found/i.test(stdout)
|
|
150
|
+
|| /^\d+\.\s+\S+/m.test(stdout)
|
|
151
|
+
|| /^\[\d+(?:\.\d+)?\]\s+/m.test(stdout)
|
|
152
|
+
case 'get':
|
|
153
|
+
return /^---$/m.test(stdout)
|
|
154
|
+
|| /^#\s+\S+/m.test(stdout)
|
|
155
|
+
|| looksLikeJsonOutput(stdout)
|
|
156
|
+
case 'query':
|
|
157
|
+
case 'search':
|
|
158
|
+
return looksLikeJsonOutput(stdout)
|
|
159
|
+
|| /no (pages|results) found/i.test(stdout)
|
|
160
|
+
|| /^\[\d+(?:\.\d+)?\]\s+/m.test(stdout)
|
|
161
|
+
|| /^\d+\.\s+\S+/m.test(stdout)
|
|
162
|
+
default:
|
|
163
|
+
return false
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function looksLikeJsonOutput(stdout) {
|
|
168
|
+
const trimmed = String(stdout ?? '').trim()
|
|
169
|
+
if (!trimmed || (!trimmed.startsWith('{') && !trimmed.startsWith('['))) return false
|
|
170
|
+
try {
|
|
171
|
+
JSON.parse(trimmed)
|
|
172
|
+
return true
|
|
173
|
+
} catch {
|
|
174
|
+
return false
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function stripRecoverableTimeoutNoise(stderr) {
|
|
179
|
+
return String(stderr ?? '')
|
|
180
|
+
.replace(/\n?spawnSync .*?\bETIMEDOUT\b\s*/gim, '\n')
|
|
181
|
+
.replace(/\n?Command failed: .*?\bETIMEDOUT\b\s*/gim, '\n')
|
|
182
|
+
.replace(/\n?timed out after .*$/gim, '\n')
|
|
183
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
184
|
+
.trim()
|
|
185
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
function stripAnsi(value) {
|
|
2
|
+
return String(value ?? '').replace(/\u001B\[[0-9;]*m/g, '')
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function summarizeCommandOutput(name, stream, value, max = 1600) {
|
|
6
|
+
const sanitized = sanitizeCommandOutput(name, stream, stripAnsi(value))
|
|
7
|
+
if (!sanitized.trim()) return ''
|
|
8
|
+
const summary = commandSpecificSummary(name, stream, sanitized)
|
|
9
|
+
return compactText(summary ?? sanitized, max)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function summarizeCommandRecord(record) {
|
|
13
|
+
if (!record) return record
|
|
14
|
+
const {
|
|
15
|
+
stdout,
|
|
16
|
+
stderr,
|
|
17
|
+
...rest
|
|
18
|
+
} = record
|
|
19
|
+
return {
|
|
20
|
+
...rest,
|
|
21
|
+
stdoutTail: summarizeCommandOutput(record.name, 'stdout', stdout ?? record.stdoutTail ?? ''),
|
|
22
|
+
stderrTail: summarizeCommandOutput(record.name, 'stderr', stderr ?? record.stderrTail ?? ''),
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function sanitizeCommandOutput(name, stream, value) {
|
|
27
|
+
let text = String(value ?? '').replace(/\r\n/g, '\n').replace(/[�]+/g, '')
|
|
28
|
+
if (isGbrainCommand(name)) {
|
|
29
|
+
if (stream === 'stderr') {
|
|
30
|
+
text = text
|
|
31
|
+
.replace(/^\s*The system cannot find the path specified\.\s*$/gim, '')
|
|
32
|
+
.replace(/\n?={20,}\n[\s\S]*?The user owns this decision\.\n={20,}\n?/g, '\n')
|
|
33
|
+
}
|
|
34
|
+
if (stream === 'stdout' && /init/i.test(name)) {
|
|
35
|
+
text = text
|
|
36
|
+
.replace(/\n?═{10,}\n\[gbrain\] search mode tentatively set[\s\S]*?To see what is running: gbrain search modes\n*/g, '\n')
|
|
37
|
+
.replace(/\n--- GBrain Mod Status ---[\s\S]*$/g, '')
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return normalizeMultiline(text)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function commandSpecificSummary(name, stream, value) {
|
|
44
|
+
if (stream !== 'stdout') return undefined
|
|
45
|
+
if (name === 'gbrain-init' || name === 'gbrain-init-isolated-home') {
|
|
46
|
+
return collectMatchingLines(value, [
|
|
47
|
+
/migration\(s\) applied/i,
|
|
48
|
+
/^Brain ready at /i,
|
|
49
|
+
/^0 pages\./i,
|
|
50
|
+
/^Next: /i,
|
|
51
|
+
/^When you outgrow local:/i,
|
|
52
|
+
])
|
|
53
|
+
}
|
|
54
|
+
if (name === 'graphify-update' || name === 'graphify-extract') {
|
|
55
|
+
return collectMatchingLines(value, [
|
|
56
|
+
/Rebuilt/i,
|
|
57
|
+
/graph\.json updated/i,
|
|
58
|
+
/^Code graph updated\./i,
|
|
59
|
+
/^Tip:/i,
|
|
60
|
+
])
|
|
61
|
+
}
|
|
62
|
+
if (name === 'graphify-benchmark') {
|
|
63
|
+
return collectMatchingLines(value, [
|
|
64
|
+
/^graphify token reduction benchmark$/i,
|
|
65
|
+
/^\s*Corpus:/i,
|
|
66
|
+
/^\s*Graph:/i,
|
|
67
|
+
/^\s*Avg query cost:/i,
|
|
68
|
+
/^\s*Reduction:/i,
|
|
69
|
+
])
|
|
70
|
+
}
|
|
71
|
+
if (name === 'graphify-query') {
|
|
72
|
+
return firstInterestingLines(value, 12)
|
|
73
|
+
}
|
|
74
|
+
return undefined
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function collectMatchingLines(value, patterns) {
|
|
78
|
+
const lines = normalizeMultiline(value).split('\n').map(line => line.trim()).filter(Boolean)
|
|
79
|
+
const selected = lines.filter(line => patterns.some(pattern => pattern.test(line)))
|
|
80
|
+
return selected.length > 0 ? selected.join('\n') : undefined
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function firstInterestingLines(value, maxLines) {
|
|
84
|
+
const lines = normalizeMultiline(value)
|
|
85
|
+
.split('\n')
|
|
86
|
+
.map(line => line.trim())
|
|
87
|
+
.filter(Boolean)
|
|
88
|
+
.filter(line => !/^[=._-]{6,}$/.test(line))
|
|
89
|
+
return lines.slice(0, maxLines).join('\n')
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function compactText(value, max) {
|
|
93
|
+
const normalized = normalizeMultiline(value)
|
|
94
|
+
if (normalized.length <= max) return normalized
|
|
95
|
+
return `${normalized.slice(0, max - 1)}…`
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function normalizeMultiline(value) {
|
|
99
|
+
return String(value ?? '')
|
|
100
|
+
.replace(/[ \t]+\n/g, '\n')
|
|
101
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
102
|
+
.trim()
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function isGbrainCommand(name) {
|
|
106
|
+
return /^gbrain-/i.test(String(name ?? ''))
|
|
107
|
+
}
|