principles-disciple 1.11.0 → 1.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/CHANGELOG.md +26 -0
- package/README.md +66 -0
- package/esbuild.config.js +1 -1
- package/openclaw.plugin.json +4 -4
- package/package.json +2 -3
- package/run-nocturnal.mjs +30 -0
- package/scripts/db-migrate.mjs +170 -0
- package/scripts/sync-plugin.mjs +250 -6
- package/src/commands/archive-impl.ts +136 -0
- package/src/commands/capabilities.ts +4 -2
- package/src/commands/context.ts +5 -1
- package/src/commands/disable-impl.ts +151 -0
- package/src/commands/evolution-status.ts +64 -19
- package/src/commands/export.ts +8 -6
- package/src/commands/focus.ts +8 -20
- package/src/commands/nocturnal-review.ts +5 -7
- package/src/commands/nocturnal-rollout.ts +1 -12
- package/src/commands/nocturnal-train.ts +21 -47
- package/src/commands/pain.ts +10 -5
- package/src/commands/principle-rollback.ts +4 -2
- package/src/commands/promote-impl.ts +274 -0
- package/src/commands/rollback-impl.ts +234 -0
- package/src/commands/rollback.ts +6 -3
- package/src/commands/samples.ts +2 -0
- package/src/commands/thinking-os.ts +3 -4
- package/src/commands/workflow-debug.ts +2 -1
- package/src/config/errors.ts +1 -0
- package/src/core/AGENTS.md +34 -0
- package/src/core/adaptive-thresholds.ts +4 -3
- package/src/core/code-implementation-storage.ts +241 -0
- package/src/core/config.ts +5 -2
- package/src/core/control-ui-db.ts +29 -10
- package/src/core/detection-funnel.ts +12 -7
- package/src/core/diagnostician-task-store.ts +156 -0
- package/src/core/dictionary.ts +4 -4
- package/src/core/empathy-keyword-matcher.ts +7 -3
- package/src/core/empathy-types.ts +13 -2
- package/src/core/event-log.ts +14 -6
- package/src/core/evolution-engine.ts +27 -31
- package/src/core/evolution-logger.ts +3 -2
- package/src/core/evolution-reducer.ts +110 -31
- package/src/core/evolution-types.ts +10 -0
- package/src/core/external-training-contract.ts +1 -0
- package/src/core/focus-history.ts +38 -24
- package/src/core/hygiene/tracker.ts +10 -6
- package/src/core/init.ts +5 -2
- package/src/core/migration.ts +3 -3
- package/src/core/model-deployment-registry.ts +6 -4
- package/src/core/model-training-registry.ts +5 -3
- package/src/core/nocturnal-arbiter.ts +13 -14
- package/src/core/nocturnal-artifact-lineage.ts +117 -0
- package/src/core/nocturnal-artificer.ts +257 -0
- package/src/core/nocturnal-candidate-scoring.ts +4 -2
- package/src/core/nocturnal-compliance.ts +67 -19
- package/src/core/nocturnal-dataset.ts +95 -2
- package/src/core/nocturnal-executability.ts +2 -3
- package/src/core/nocturnal-export.ts +6 -3
- package/src/core/nocturnal-rule-implementation-validator.ts +245 -0
- package/src/core/nocturnal-trajectory-extractor.ts +10 -3
- package/src/core/nocturnal-trinity.ts +319 -61
- package/src/core/pain-context-extractor.ts +29 -15
- package/src/core/pain.ts +7 -5
- package/src/core/path-resolver.ts +16 -15
- package/src/core/paths.ts +2 -1
- package/src/core/pd-task-reconciler.ts +463 -0
- package/src/core/pd-task-service.ts +42 -0
- package/src/core/pd-task-store.ts +77 -0
- package/src/core/pd-task-types.ts +128 -0
- package/src/core/principle-internalization/deprecated-readiness.ts +91 -0
- package/src/core/principle-internalization/internalization-routing-policy.ts +208 -0
- package/src/core/principle-internalization/lifecycle-metrics.ts +149 -0
- package/src/core/principle-internalization/lifecycle-read-model.ts +243 -0
- package/src/core/principle-internalization/lifecycle-refresh.ts +11 -0
- package/src/core/principle-internalization/principle-lifecycle-service.ts +167 -0
- package/src/core/principle-training-state.ts +95 -370
- package/src/core/principle-tree-ledger.ts +733 -0
- package/src/core/principle-tree-migration.ts +195 -0
- package/src/core/profile.ts +3 -1
- package/src/core/promotion-gate.ts +14 -18
- package/src/core/replay-engine.ts +562 -0
- package/src/core/risk-calculator.ts +6 -4
- package/src/core/rule-host-helpers.ts +39 -0
- package/src/core/rule-host-types.ts +82 -0
- package/src/core/rule-host.ts +245 -0
- package/src/core/rule-implementation-runtime.ts +38 -0
- package/src/core/schema/db-types.ts +16 -0
- package/src/core/schema/index.ts +26 -0
- package/src/core/schema/migration-runner.ts +207 -0
- package/src/core/schema/migrations/001-init-trajectory.ts +211 -0
- package/src/core/schema/migrations/002-init-central.ts +122 -0
- package/src/core/schema/migrations/003-init-workflow.ts +55 -0
- package/src/core/schema/migrations/004-add-thinking-and-gfi.ts +74 -0
- package/src/core/schema/migrations/index.ts +31 -0
- package/src/core/schema/schema-definitions.ts +650 -0
- package/src/core/session-tracker.ts +6 -4
- package/src/core/shadow-observation-registry.ts +6 -3
- package/src/core/system-logger.ts +2 -2
- package/src/core/thinking-models.ts +182 -46
- package/src/core/thinking-os-parser.ts +156 -0
- package/src/core/training-program.ts +7 -7
- package/src/core/trajectory.ts +42 -36
- package/src/core/workspace-context.ts +77 -11
- package/src/core/workspace-dir-validation.ts +152 -0
- package/src/hooks/AGENTS.md +31 -0
- package/src/hooks/bash-risk.ts +3 -1
- package/src/hooks/edit-verification.ts +9 -5
- package/src/hooks/gate-block-helper.ts +5 -1
- package/src/hooks/gate.ts +152 -5
- package/src/hooks/gfi-gate.ts +9 -2
- package/src/hooks/lifecycle-routing.ts +124 -0
- package/src/hooks/lifecycle.ts +12 -12
- package/src/hooks/llm.ts +17 -109
- package/src/hooks/message-sanitize.ts +5 -3
- package/src/hooks/pain.ts +19 -15
- package/src/hooks/progressive-trust-gate.ts +7 -1
- package/src/hooks/prompt.ts +169 -60
- package/src/hooks/subagent.ts +5 -4
- package/src/hooks/thinking-checkpoint.ts +2 -0
- package/src/hooks/trajectory-collector.ts +15 -12
- package/src/http/principles-console-route.ts +31 -68
- package/src/i18n/commands.ts +2 -2
- package/src/index.ts +130 -40
- package/src/service/central-database.ts +131 -43
- package/src/service/central-health-service.ts +47 -0
- package/src/service/central-overview-service.ts +135 -0
- package/src/service/central-sync-service.ts +87 -0
- package/src/service/control-ui-query-service.ts +46 -36
- package/src/service/event-log-auditor.ts +261 -0
- package/src/service/evolution-query-service.ts +23 -22
- package/src/service/evolution-worker.ts +565 -261
- package/src/service/health-query-service.ts +213 -36
- package/src/service/nocturnal-runtime.ts +8 -4
- package/src/service/nocturnal-service.ts +503 -59
- package/src/service/nocturnal-target-selector.ts +5 -7
- package/src/service/runtime-summary-service.ts +2 -1
- package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +25 -336
- package/src/service/subagent-workflow/dynamic-timeout.ts +30 -0
- package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +48 -386
- package/src/service/subagent-workflow/index.ts +2 -0
- package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +169 -284
- package/src/service/subagent-workflow/runtime-direct-driver.ts +114 -16
- package/src/service/subagent-workflow/subagent-error-utils.ts +25 -0
- package/src/service/subagent-workflow/types.ts +9 -4
- package/src/service/subagent-workflow/workflow-manager-base.ts +573 -0
- package/src/service/subagent-workflow/workflow-store.ts +71 -11
- package/src/service/trajectory-service.ts +2 -1
- package/src/tools/critique-prompt.ts +1 -1
- package/src/tools/deep-reflect.ts +175 -209
- package/src/tools/model-index.ts +2 -1
- package/src/types/event-types.ts +2 -2
- package/src/types/principle-tree-schema.ts +29 -23
- package/src/utils/file-lock.ts +5 -3
- package/src/utils/io.ts +5 -2
- package/src/utils/nlp.ts +5 -46
- package/src/utils/node-vm-polyfill.ts +11 -0
- package/src/utils/plugin-logger.ts +2 -0
- package/src/utils/retry.ts +572 -0
- package/src/utils/subagent-probe.ts +1 -1
- package/templates/langs/en/core/AGENTS.md +0 -13
- package/templates/langs/en/core/SOUL.md +1 -31
- package/templates/langs/en/core/TOOLS.md +0 -4
- package/templates/langs/en/principles/THINKING_OS.md +77 -0
- package/templates/langs/en/skills/admin/SKILL.md +0 -1
- package/templates/langs/en/skills/evolution-framework-update/SKILL.md +1 -1
- package/templates/langs/en/skills/pd-diagnostician/SKILL.md +18 -5
- package/templates/langs/zh/core/AGENTS.md +0 -22
- package/templates/langs/zh/core/SOUL.md +1 -31
- package/templates/langs/zh/core/TOOLS.md +0 -4
- package/templates/langs/zh/principles/THINKING_OS.md +77 -0
- package/templates/langs/zh/skills/admin/SKILL.md +0 -1
- package/templates/langs/zh/skills/evolution-framework-update/SKILL.md +1 -1
- package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +25 -4
- package/tests/commands/evolution-status.test.ts +119 -0
- package/tests/commands/implementation-lifecycle.test.ts +362 -0
- package/tests/core/code-implementation-storage.test.ts +398 -0
- package/tests/core/evolution-reducer.detector-metadata.test.ts +28 -28
- package/tests/core/nocturnal-artifact-lineage.test.ts +53 -0
- package/tests/core/nocturnal-artificer.test.ts +241 -0
- package/tests/core/nocturnal-compliance-p-principles.test.ts +133 -0
- package/tests/core/nocturnal-rule-implementation-validator.test.ts +127 -0
- package/tests/core/pd-task-store.test.ts +126 -0
- package/tests/core/principle-internalization/deprecated-readiness.test.ts +193 -0
- package/tests/core/principle-internalization/internalization-routing-policy.test.ts +212 -0
- package/tests/core/principle-internalization/lifecycle-metrics.test.ts +350 -0
- package/tests/core/principle-internalization/principle-lifecycle-service.test.ts +211 -0
- package/tests/core/principle-training-state.test.ts +228 -1
- package/tests/core/principle-tree-ledger.test.ts +423 -0
- package/tests/core/regression-v1-9-1.test.ts +265 -0
- package/tests/core/replay-engine.test.ts +234 -0
- package/tests/core/rule-host-helpers.test.ts +120 -0
- package/tests/core/rule-host.test.ts +389 -0
- package/tests/core/rule-implementation-runtime.test.ts +64 -0
- package/tests/core/workspace-context.test.ts +53 -0
- package/tests/core/workspace-dir-validation.test.ts +272 -0
- package/tests/hooks/gate-rule-host-pipeline.test.ts +385 -0
- package/tests/hooks/pain.test.ts +74 -10
- package/tests/hooks/prompt.test.ts +63 -1
- package/tests/integration/principle-lifecycle.e2e.test.ts +197 -0
- package/tests/integration/tool-hooks-workspace-dir.e2e.test.ts +211 -0
- package/tests/service/data-endpoints-regression.test.ts +834 -0
- package/tests/service/evolution-worker.test.ts +0 -123
- package/tests/service/nocturnal-service-code-candidate.test.ts +330 -0
- package/tests/utils/nlp.test.ts +1 -19
- package/tests/utils/retry.test.ts +327 -0
- package/ui/src/App.tsx +1 -1
- package/ui/src/api.ts +4 -0
- package/ui/src/charts.tsx +366 -0
- package/ui/src/components/WorkspaceConfig.tsx +107 -75
- package/ui/src/i18n/ui.ts +89 -31
- package/ui/src/pages/EvolutionPage.tsx +1 -1
- package/ui/src/pages/OverviewPage.tsx +441 -81
- package/ui/src/pages/ThinkingModelsPage.tsx +287 -69
- package/ui/src/styles.css +43 -0
- package/ui/src/types.ts +17 -1
- package/src/agents/nocturnal-dreamer.md +0 -152
- package/src/agents/nocturnal-philosopher.md +0 -138
- package/src/agents/nocturnal-reflector.md +0 -126
- package/src/agents/nocturnal-scribe.md +0 -164
- package/templates/workspace/.principles/00-kernel.md +0 -51
- package/templates/workspace/.principles/DECISION_POLICY.json +0 -44
- package/templates/workspace/.principles/PRINCIPLES.md +0 -20
- package/templates/workspace/.principles/PROFILE.json +0 -54
- package/templates/workspace/.principles/PROFILE.schema.json +0 -56
- package/templates/workspace/.principles/THINKING_OS.md +0 -64
- package/templates/workspace/.principles/THINKING_OS_ARCHIVE.md +0 -7
- package/templates/workspace/.principles/THINKING_OS_CANDIDATES.md +0 -9
- package/templates/workspace/.principles/models/_INDEX.md +0 -27
- package/templates/workspace/.principles/models/first_principles.md +0 -62
- package/templates/workspace/.principles/models/marketing_4p.md +0 -52
- package/templates/workspace/.principles/models/porter_five.md +0 -63
- package/templates/workspace/.principles/models/swot.md +0 -60
- package/templates/workspace/.principles/models/user_story_map.md +0 -63
- package/templates/workspace/.state/WORKBOARD.json +0 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# principles-disciple
|
|
2
|
+
|
|
3
|
+
## 1.10.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 650ae5a: ## v1.9.1: WebUI Data Source Fixes
|
|
8
|
+
|
|
9
|
+
### Phase 16-20 Complete
|
|
10
|
+
|
|
11
|
+
- **Phase 16**: Data Source Tracing - mapped all 4 WebUI pages to API endpoints
|
|
12
|
+
- **Phase 17**: Overview Page Fix - fixed `/api/central/overview`, `/api/overview`, `/api/overview/health`
|
|
13
|
+
- **Phase 18**: Loop/Samples + Feedback Fix - fixed `/api/samples`, `/api/feedback/*` data sources
|
|
14
|
+
- **Phase 19**: Gate Monitor Frontend - fixed `/api/gate/stats`, `/api/gate/blocks` types
|
|
15
|
+
- **Phase 20**: E2E Validation - 19 regression tests added for all API endpoints
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
- Fixed `evolution-worker.ts` missing `runtimeAdapter` parameter
|
|
20
|
+
- Fixed `nocturnal-train.ts` mode field type annotation
|
|
21
|
+
- Fixed `sync-version.sh` to include `create-principles-disciple` package
|
|
22
|
+
|
|
23
|
+
### Infrastructure
|
|
24
|
+
|
|
25
|
+
- Added `@changesets/cli` for monorepo version management
|
|
26
|
+
- Added `data-endpoints-regression.test.ts` with 19 tests
|
package/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<!-- generated-by: gsd-doc-writer -->
|
|
2
|
+
# principles-disciple
|
|
3
|
+
|
|
4
|
+
Native OpenClaw plugin for Principles Disciple: an evolutionary programming agent framework with strategic guardrails and reflection loops.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install principles-disciple
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Requires OpenClaw `>=2026.4.4` as a peer dependency.
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
This plugin integrates with OpenClaw to provide an evolutionary programming framework. It intercepts agent operations through hooks to enforce security guardrails, track pain points, collect trajectory data, and enable deep reflection capabilities.
|
|
17
|
+
|
|
18
|
+
### Slash Commands
|
|
19
|
+
|
|
20
|
+
| Command | Description |
|
|
21
|
+
|---------|-------------|
|
|
22
|
+
| `/pd-init` | Initialize workspace |
|
|
23
|
+
| `/pd-bootstrap` | Scan environment tools |
|
|
24
|
+
| `/pd-research` | Research tools and capabilities |
|
|
25
|
+
| `/pd-thinking` | Manage thinking models |
|
|
26
|
+
| `/pd-status` | View evolution status |
|
|
27
|
+
| `/pd-context` | Control context injection |
|
|
28
|
+
| `/pd-focus` | Focus file management |
|
|
29
|
+
| `/pd-evolution-status` | View evolution state |
|
|
30
|
+
| `/pd-rollback` | Rollback to previous state |
|
|
31
|
+
| `/pd-export` | Export trajectory/correction data |
|
|
32
|
+
| `/pd-samples` | Review correction samples |
|
|
33
|
+
| `/pd-nocturnal-review` | Review nocturnal training samples |
|
|
34
|
+
| `/nocturnal-train` | Nocturnal training operations |
|
|
35
|
+
| `/nocturnal-rollout` | Nocturnal rollout and promotion |
|
|
36
|
+
| `/pd-workflow-debug` | Debug workflow state |
|
|
37
|
+
| `/pd-help` | Show command reference |
|
|
38
|
+
|
|
39
|
+
### Tools
|
|
40
|
+
|
|
41
|
+
**`deep_reflect`** - Executes deep meta-cognitive reflection to analyze potential risks, logical gaps, or architectural improvements in the current task.
|
|
42
|
+
|
|
43
|
+
Parameters:
|
|
44
|
+
- `context` (required): Task context, code snippet, or current difficulty
|
|
45
|
+
- `depth` (optional): Reflection depth 1-3 (default: 2)
|
|
46
|
+
- `model_id` (optional): Force specific thinking model
|
|
47
|
+
|
|
48
|
+
### Configuration
|
|
49
|
+
|
|
50
|
+
The plugin accepts the following configuration options:
|
|
51
|
+
|
|
52
|
+
| Option | Default | Description |
|
|
53
|
+
|--------|---------|-------------|
|
|
54
|
+
| `language` | `zh` | Interaction language (`en` or `zh`) |
|
|
55
|
+
| `auditLevel` | `medium` | Security guardrail level (`low`, `medium`, `high`) |
|
|
56
|
+
| `riskPaths` | `[]` | High-risk directories requiring explicit authorization |
|
|
57
|
+
| `deep_reflection.enabled` | `true` | Enable AI deep reflection |
|
|
58
|
+
| `deep_reflection.mode` | `auto` | Reflection trigger mode (`auto` or `forced`) |
|
|
59
|
+
|
|
60
|
+
## Part of the principles monorepo
|
|
61
|
+
|
|
62
|
+
See the root [README.md](https://github.com/csuzngjh/principles#readme) for the full project overview.
|
|
63
|
+
|
|
64
|
+
## License
|
|
65
|
+
|
|
66
|
+
MIT License - [LICENSE](https://github.com/csuzngjh/principles/blob/main/LICENSE)
|
package/esbuild.config.js
CHANGED
|
@@ -46,7 +46,7 @@ async function bundlePlugin() {
|
|
|
46
46
|
|
|
47
47
|
console.log('Bundle created: dist/bundle.js');
|
|
48
48
|
|
|
49
|
-
const staticFiles = ['templates', '
|
|
49
|
+
const staticFiles = ['templates', 'openclaw.plugin.json'];
|
|
50
50
|
const distDir = 'dist';
|
|
51
51
|
|
|
52
52
|
for (const file of staticFiles) {
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "principles-disciple",
|
|
3
3
|
"name": "Principles Disciple",
|
|
4
4
|
"description": "Evolutionary programming agent framework with strategic guardrails and reflection loops.",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.13.0",
|
|
6
6
|
"skills": [
|
|
7
7
|
"./skills"
|
|
8
8
|
],
|
|
@@ -76,8 +76,8 @@
|
|
|
76
76
|
}
|
|
77
77
|
},
|
|
78
78
|
"buildFingerprint": {
|
|
79
|
-
"gitSha": "
|
|
80
|
-
"bundleMd5": "
|
|
81
|
-
"builtAt": "2026-04-
|
|
79
|
+
"gitSha": "ad52c5fcc9c5",
|
|
80
|
+
"bundleMd5": "3dc29cb961c7132e1ad419550686df6c",
|
|
81
|
+
"builtAt": "2026-04-10T01:19:54.357Z"
|
|
82
82
|
}
|
|
83
83
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "principles-disciple",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"description": "Native OpenClaw plugin for Principles Disciple",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/bundle.js",
|
|
@@ -32,8 +32,7 @@
|
|
|
32
32
|
"build:production": "node esbuild.config.js --production && node scripts/build-web.mjs --production && node scripts/verify-build.mjs",
|
|
33
33
|
"test": "vitest run",
|
|
34
34
|
"test:coverage": "vitest run --coverage",
|
|
35
|
-
"lint": "eslint src/"
|
|
36
|
-
"postinstall": "node scripts/install-dependencies.cjs"
|
|
35
|
+
"lint": "eslint src/"
|
|
37
36
|
},
|
|
38
37
|
"devDependencies": {
|
|
39
38
|
"@testing-library/react": "^16.3.0",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
|
|
4
|
+
const workspaceDir = '/home/csuzngjh/.openclaw/workspace-main';
|
|
5
|
+
const stateDir = '/home/csuzngjh/.openclaw/workspace-main/.state';
|
|
6
|
+
|
|
7
|
+
console.error('WorkspaceDir:', workspaceDir);
|
|
8
|
+
console.error('StateDir:', stateDir);
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
const bundlePath = './dist/nocturnal-service.bundle.js';
|
|
12
|
+
console.error('Importing from:', bundlePath);
|
|
13
|
+
|
|
14
|
+
const mod = await import(bundlePath);
|
|
15
|
+
|
|
16
|
+
console.log('Available exports:', Object.keys(mod));
|
|
17
|
+
|
|
18
|
+
if (!mod.executeNocturnalReflection) {
|
|
19
|
+
throw new Error('executeNocturnalReflection not found in bundle. Available exports: ' + Object.keys(mod).join(', '));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
console.error('Calling executeNocturnalReflection...');
|
|
23
|
+
const result = await mod.executeNocturnalReflection(workspaceDir, stateDir);
|
|
24
|
+
|
|
25
|
+
console.log(JSON.stringify(result, null, 2));
|
|
26
|
+
} catch (err) {
|
|
27
|
+
console.error('ERROR:', err.message);
|
|
28
|
+
if (err.stack) console.error(err.stack);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Database Migration CLI
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* node scripts/db-migrate.mjs status # Show migration status
|
|
8
|
+
* node scripts/db-migrate.mjs run [--db trajectory.db|central.db|workflow.db]
|
|
9
|
+
* node scripts/db-migrate.mjs rollback [--db trajectory.db|central.db|workflow.db]
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { Database } from 'better-sqlite3';
|
|
13
|
+
import { join } from 'path';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
import { dirname } from 'path';
|
|
16
|
+
|
|
17
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
+
const __dirname = dirname(__filename);
|
|
19
|
+
|
|
20
|
+
// Resolve paths
|
|
21
|
+
const PROJECT_ROOT = join(__dirname, '..');
|
|
22
|
+
const STATE_DIR = process.env.STATE_DIR || join(PROJECT_ROOT, '..', '.state');
|
|
23
|
+
|
|
24
|
+
// We need to dynamically import the schema module since it's TypeScript
|
|
25
|
+
// For CLI, we'll use the compiled JS version
|
|
26
|
+
async function run() {
|
|
27
|
+
let SchemaModule;
|
|
28
|
+
try {
|
|
29
|
+
SchemaModule = await import('../dist/core/schema/index.js');
|
|
30
|
+
} catch {
|
|
31
|
+
// Try running from source with tsx
|
|
32
|
+
console.error('Schema module not found in dist/. Running from source...');
|
|
33
|
+
console.error('Please build the plugin first: node esbuild.config.js --production');
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const { MigrationRunner, ensureDatabaseSchema, ALL_MIGRATIONS, DB_TYPES } = SchemaModule;
|
|
38
|
+
|
|
39
|
+
const args = process.argv.slice(2);
|
|
40
|
+
const command = args[0];
|
|
41
|
+
|
|
42
|
+
if (!command || command === '--help' || command === '-h') {
|
|
43
|
+
console.log(`
|
|
44
|
+
Database Migration CLI
|
|
45
|
+
|
|
46
|
+
Usage:
|
|
47
|
+
node scripts/db-migrate.mjs status Show migration status for all databases
|
|
48
|
+
node scripts/db-migrate.mjs run [--db <db>] Run pending migrations
|
|
49
|
+
node scripts/db-migrate.mjs rollback [--db <db>] Rollback latest migration
|
|
50
|
+
|
|
51
|
+
Options:
|
|
52
|
+
--db <db> Target database: trajectory.db, central.db, or workflow.db
|
|
53
|
+
(default: all databases)
|
|
54
|
+
--state-dir Override state directory (default: .state/)
|
|
55
|
+
|
|
56
|
+
Examples:
|
|
57
|
+
node scripts/db-migrate.mjs status
|
|
58
|
+
node scripts/db-migrate.mjs run --db trajectory.db
|
|
59
|
+
node scripts/db-migrate.mjs rollback --db central.db
|
|
60
|
+
`);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const dbFlag = args.indexOf('--db');
|
|
65
|
+
const targetDb = dbFlag >= 0 ? args[dbFlag + 1] : null;
|
|
66
|
+
|
|
67
|
+
const dbs = targetDb ? [targetDb] : DB_TYPES;
|
|
68
|
+
|
|
69
|
+
for (const dbType of dbs) {
|
|
70
|
+
if (!DB_TYPES.includes(dbType)) {
|
|
71
|
+
console.error(`Unknown database: ${dbType}. Valid options: ${DB_TYPES.join(', ')}`);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const dbPath = getDbPath(dbType);
|
|
76
|
+
const db = new Database(dbPath);
|
|
77
|
+
|
|
78
|
+
console.log(`\n=== ${dbType} (${dbPath}) ===`);
|
|
79
|
+
|
|
80
|
+
switch (command) {
|
|
81
|
+
case 'status':
|
|
82
|
+
showStatus(db, dbType, ALL_MIGRATIONS, MigrationRunner);
|
|
83
|
+
break;
|
|
84
|
+
case 'run':
|
|
85
|
+
runMigrations(db, dbType, ALL_MIGRATIONS, MigrationRunner);
|
|
86
|
+
break;
|
|
87
|
+
case 'rollback':
|
|
88
|
+
rollbackMigration(db, dbType, ALL_MIGRATIONS, MigrationRunner);
|
|
89
|
+
break;
|
|
90
|
+
case 'ensure':
|
|
91
|
+
console.log('Ensuring schema...');
|
|
92
|
+
ensureDatabaseSchema(db, dbType);
|
|
93
|
+
console.log('Schema ensured.');
|
|
94
|
+
break;
|
|
95
|
+
default:
|
|
96
|
+
console.error(`Unknown command: ${command}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
db.close();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function getDbPath(dbType) {
|
|
104
|
+
switch (dbType) {
|
|
105
|
+
case 'trajectory.db':
|
|
106
|
+
return join(STATE_DIR, 'trajectory.db');
|
|
107
|
+
case 'central.db':
|
|
108
|
+
return join(process.env.HOME, '.openclaw', '.central', 'aggregated.db');
|
|
109
|
+
case 'workflow.db':
|
|
110
|
+
return join(STATE_DIR, 'subagent_workflows.db');
|
|
111
|
+
default:
|
|
112
|
+
throw new Error(`Unknown database type: ${dbType}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function showStatus(db, dbType, migrations, Runner) {
|
|
117
|
+
const runner = new Runner(db);
|
|
118
|
+
const current = runner.getCurrentVersion();
|
|
119
|
+
const info = runner.getMigrationInfo(migrations, dbType);
|
|
120
|
+
|
|
121
|
+
console.log(`Current version: ${current}`);
|
|
122
|
+
console.log('');
|
|
123
|
+
|
|
124
|
+
for (const m of info) {
|
|
125
|
+
const status = m.applied ? '✅' : '⏳';
|
|
126
|
+
console.log(` ${status} ${m.id}-${m.name}`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (info.length === 0) {
|
|
130
|
+
console.log(' No migrations defined for this database.');
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function runMigrations(db, dbType, migrations, Runner) {
|
|
135
|
+
const runner = new Runner(db);
|
|
136
|
+
|
|
137
|
+
// First ensure base schema
|
|
138
|
+
console.log('Applying schema catalog...');
|
|
139
|
+
runner.applySchemaCatalog(dbType);
|
|
140
|
+
|
|
141
|
+
// Then run any additional migrations
|
|
142
|
+
const dbMigrations = migrations.filter(m => m.db === dbType);
|
|
143
|
+
if (dbMigrations.length > 0) {
|
|
144
|
+
const applied = runner.runMigrations(dbMigrations, dbType);
|
|
145
|
+
if (applied.length === 0) {
|
|
146
|
+
console.log('All migrations already applied.');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
showStatus(db, dbType, migrations, Runner);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function rollbackMigration(db, dbType, migrations, Runner) {
|
|
154
|
+
const runner = new Runner(db);
|
|
155
|
+
const dbMigrations = migrations.filter(m => m.db === dbType);
|
|
156
|
+
const rolledBack = runner.rollback(dbMigrations, dbType);
|
|
157
|
+
|
|
158
|
+
if (rolledBack) {
|
|
159
|
+
console.log(`Rolled back migration ${rolledBack}`);
|
|
160
|
+
} else {
|
|
161
|
+
console.log('No migrations to roll back.');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
showStatus(db, dbType, migrations, Runner);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
run().catch(err => {
|
|
168
|
+
console.error('Migration CLI error:', err);
|
|
169
|
+
process.exit(1);
|
|
170
|
+
});
|
package/scripts/sync-plugin.mjs
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* --help Show help message
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { copyFileSync, cpSync, existsSync, rmSync, readFileSync, readFileSync as readFileSyncRaw, mkdirSync, writeFileSync, readdirSync } from 'fs';
|
|
20
|
+
import { copyFileSync, cpSync, existsSync, rmSync, readFileSync, readFileSync as readFileSyncRaw, mkdirSync, writeFileSync, readdirSync, statSync } from 'fs';
|
|
21
21
|
import { createHash } from 'crypto';
|
|
22
22
|
import { join, dirname } from 'path';
|
|
23
23
|
import { fileURLToPath } from 'url';
|
|
@@ -54,6 +54,7 @@ function parseArgs() {
|
|
|
54
54
|
force: false,
|
|
55
55
|
restart: false,
|
|
56
56
|
dev: false,
|
|
57
|
+
bump: false,
|
|
57
58
|
help: false,
|
|
58
59
|
};
|
|
59
60
|
|
|
@@ -78,6 +79,11 @@ function parseArgs() {
|
|
|
78
79
|
args.dev = true;
|
|
79
80
|
args.force = true;
|
|
80
81
|
args.restart = true;
|
|
82
|
+
args.bump = true;
|
|
83
|
+
break;
|
|
84
|
+
case '--bump':
|
|
85
|
+
case '-b':
|
|
86
|
+
args.bump = true;
|
|
81
87
|
break;
|
|
82
88
|
case '--force':
|
|
83
89
|
case '-f':
|
|
@@ -112,7 +118,8 @@ Options:
|
|
|
112
118
|
--skip-build Skip build step (use existing dist/)
|
|
113
119
|
--skip-deps Skip dependency installation
|
|
114
120
|
--restart Automatically restart OpenClaw gateway after installation
|
|
115
|
-
--dev, -d Developer mode: --force + --restart + clean stale backups
|
|
121
|
+
--dev, -d Developer mode: --force + --restart + --bump + clean stale backups
|
|
122
|
+
--bump, -b Auto-bump patch version if there are uncommitted source changes
|
|
116
123
|
--force, -f Force overwrite without prompts
|
|
117
124
|
--help, -h Show this help message
|
|
118
125
|
|
|
@@ -123,9 +130,12 @@ Examples:
|
|
|
123
130
|
# Install with English skills
|
|
124
131
|
node scripts/sync-plugin.mjs --lang en
|
|
125
132
|
|
|
126
|
-
# Developer mode: build, deploy, restart, clean up (recommended
|
|
133
|
+
# Developer mode: bump version, build, deploy, restart, clean up (recommended)
|
|
127
134
|
node scripts/sync-plugin.mjs --dev
|
|
128
135
|
|
|
136
|
+
# Just bump version without deploying
|
|
137
|
+
node scripts/sync-plugin.mjs --bump --skip-build --skip-deps
|
|
138
|
+
|
|
129
139
|
# Quick sync after local build
|
|
130
140
|
node scripts/sync-plugin.mjs --skip-deps --skip-build
|
|
131
141
|
|
|
@@ -206,6 +216,80 @@ function getVersion(dir) {
|
|
|
206
216
|
}
|
|
207
217
|
}
|
|
208
218
|
|
|
219
|
+
/**
|
|
220
|
+
* Auto-bump patch version if there are uncommitted source changes.
|
|
221
|
+
* Updates all version files: package.json (root + plugin), openclaw.plugin.json, README_ZH.md.
|
|
222
|
+
*/
|
|
223
|
+
function autoBumpVersion(sourceDir) {
|
|
224
|
+
const rootDir = join(sourceDir, '..', '..');
|
|
225
|
+
const pluginDir = sourceDir;
|
|
226
|
+
|
|
227
|
+
// Check for uncommitted changes in source files
|
|
228
|
+
try {
|
|
229
|
+
const diffOutput = execSync('git diff --name-only HEAD', {
|
|
230
|
+
cwd: rootDir,
|
|
231
|
+
encoding: 'utf-8',
|
|
232
|
+
}).trim();
|
|
233
|
+
const changedFiles = diffOutput ? diffOutput.split('\n').filter(f => {
|
|
234
|
+
return f.startsWith('packages/openclaw-plugin/src/') ||
|
|
235
|
+
f.startsWith('packages/openclaw-plugin/skills/') ||
|
|
236
|
+
f.startsWith('scripts/') ||
|
|
237
|
+
f === 'packages/openclaw-plugin/package.json' ||
|
|
238
|
+
f === 'package.json' ||
|
|
239
|
+
f === 'README_ZH.md';
|
|
240
|
+
}) : [];
|
|
241
|
+
|
|
242
|
+
if (changedFiles.length === 0) {
|
|
243
|
+
console.log('📋 No uncommitted source changes — skipping version bump');
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
console.log(`📋 Found uncommitted changes in ${changedFiles.length} file(s) — bumping version...`);
|
|
248
|
+
|
|
249
|
+
const currentVersion = getVersion(pluginDir);
|
|
250
|
+
if (!currentVersion) {
|
|
251
|
+
console.error('❌ Cannot determine current version');
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const [major, minor, patch] = currentVersion.split('.').map(Number);
|
|
256
|
+
const newVersion = `${major}.${minor}.${patch + 1}`;
|
|
257
|
+
|
|
258
|
+
// Update package.json (plugin)
|
|
259
|
+
const pkgPath = join(pluginDir, 'package.json');
|
|
260
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
261
|
+
pkg.version = newVersion;
|
|
262
|
+
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
|
|
263
|
+
|
|
264
|
+
// Update openclaw.plugin.json
|
|
265
|
+
const manifestPath = join(pluginDir, 'openclaw.plugin.json');
|
|
266
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
267
|
+
manifest.version = newVersion;
|
|
268
|
+
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n', 'utf-8');
|
|
269
|
+
|
|
270
|
+
// Update root package.json
|
|
271
|
+
const rootPkgPath = join(rootDir, 'package.json');
|
|
272
|
+
if (existsSync(rootPkgPath)) {
|
|
273
|
+
const rootPkg = JSON.parse(readFileSync(rootPkgPath, 'utf-8'));
|
|
274
|
+
rootPkg.version = newVersion;
|
|
275
|
+
writeFileSync(rootPkgPath, JSON.stringify(rootPkg, null, 2) + '\n', 'utf-8');
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Update README_ZH.md
|
|
279
|
+
const readmePath = join(rootDir, 'README_ZH.md');
|
|
280
|
+
if (existsSync(readmePath)) {
|
|
281
|
+
let readme = readFileSync(readmePath, 'utf-8');
|
|
282
|
+
readme = readme.replace(/v\d+\.\d+\.\d+/g, `v${newVersion}`);
|
|
283
|
+
writeFileSync(readmePath, readme, 'utf-8');
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
console.log(`✅ Version bumped: ${currentVersion} → ${newVersion}`);
|
|
287
|
+
} catch (err) {
|
|
288
|
+
console.warn(`⚠️ Auto-bump failed: ${err.message}`);
|
|
289
|
+
console.warn(' Continuing with current version');
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
209
293
|
/**
|
|
210
294
|
* Install project dependencies
|
|
211
295
|
*/
|
|
@@ -583,6 +667,158 @@ function syncItem(item) {
|
|
|
583
667
|
}
|
|
584
668
|
}
|
|
585
669
|
|
|
670
|
+
/**
|
|
671
|
+
* Sync workspace templates to all workspace directories.
|
|
672
|
+
* This ensures workspaces get the latest template files when the plugin is updated.
|
|
673
|
+
*
|
|
674
|
+
* IMPORTANT SAFETY RULES:
|
|
675
|
+
* - Core files (AGENTS.md, SOUL.md, IDENTITY.md, USER.md, etc.) are NEVER overwritten.
|
|
676
|
+
* They are only copied on first-time workspace creation (file doesn't exist).
|
|
677
|
+
* Users heavily customize these files — overwriting would destroy their work.
|
|
678
|
+
* - Non-core templates (pain_samples, THINKING_OS.md, workspace boilerplate) are synced
|
|
679
|
+
* via MD5 comparison (only update if template content changed and workspace hasn't diverged).
|
|
680
|
+
*
|
|
681
|
+
* Syncs:
|
|
682
|
+
* - templates/workspace/** → workspace root (recursive, skip core files)
|
|
683
|
+
* - templates/langs/{lang}/core/** → workspace root (ONLY if missing)
|
|
684
|
+
* - templates/langs/{lang}/pain/** → .state/pain_samples/
|
|
685
|
+
* - templates/langs/{lang}/principles/THINKING_OS.md → .principles/THINKING_OS.md
|
|
686
|
+
*/
|
|
687
|
+
function syncWorkspaceTemplates(lang) {
|
|
688
|
+
const workspacesRoot = OPENCLAW_DIR;
|
|
689
|
+
if (!existsSync(workspacesRoot)) return;
|
|
690
|
+
|
|
691
|
+
const entries = readdirSync(workspacesRoot);
|
|
692
|
+
const workspaceDirs = entries.filter(e =>
|
|
693
|
+
e.startsWith('workspace-') || e === 'workspace'
|
|
694
|
+
);
|
|
695
|
+
|
|
696
|
+
if (workspaceDirs.length === 0) return;
|
|
697
|
+
|
|
698
|
+
// Core files that should NEVER be overwritten after creation
|
|
699
|
+
const CORE_FILES = new Set([
|
|
700
|
+
'AGENTS.md', 'SOUL.md', 'BOOT.md', 'BOOTSTRAP.md',
|
|
701
|
+
'IDENTITY.md', 'USER.md', 'TOOLS.md', 'HEARTBEAT.md',
|
|
702
|
+
'PRINCIPLES.md', 'PROFILE.json',
|
|
703
|
+
]);
|
|
704
|
+
|
|
705
|
+
let updated = 0;
|
|
706
|
+
|
|
707
|
+
// Helper: compute MD5 of a file
|
|
708
|
+
function md5(filePath) {
|
|
709
|
+
try {
|
|
710
|
+
const content = readFileSyncRaw(filePath);
|
|
711
|
+
return createHash('md5').update(content).digest('hex');
|
|
712
|
+
} catch {
|
|
713
|
+
return null;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
for (const ws of workspaceDirs) {
|
|
718
|
+
const wsDir = join(workspacesRoot, ws);
|
|
719
|
+
|
|
720
|
+
// 1. templates/workspace/** → workspace root (recursive)
|
|
721
|
+
const workspaceTemplateDir = join(SOURCE_DIR, 'templates', 'workspace');
|
|
722
|
+
if (existsSync(workspaceTemplateDir)) {
|
|
723
|
+
updated += syncDirRecursive(workspaceTemplateDir, wsDir, md5, CORE_FILES);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// 2. templates/langs/{lang}/core/** → workspace root (ONLY if file missing)
|
|
727
|
+
const coreDir = join(SOURCE_DIR, 'templates', 'langs', lang, 'core');
|
|
728
|
+
if (existsSync(coreDir)) {
|
|
729
|
+
updated += syncCoreFiles(coreDir, wsDir);
|
|
730
|
+
} else {
|
|
731
|
+
const zhCoreDir = join(SOURCE_DIR, 'templates', 'langs', 'zh', 'core');
|
|
732
|
+
if (existsSync(zhCoreDir)) {
|
|
733
|
+
updated += syncCoreFiles(zhCoreDir, wsDir);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// 3. templates/langs/{lang}/pain/** → .state/pain_samples/
|
|
738
|
+
const painSrc = join(SOURCE_DIR, 'templates', 'langs', lang, 'pain');
|
|
739
|
+
const painDest = join(wsDir, '.state', 'pain_samples');
|
|
740
|
+
if (existsSync(painSrc)) {
|
|
741
|
+
updated += syncDirRecursive(painSrc, painDest, md5, CORE_FILES);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
// 4. templates/langs/{lang}/principles/THINKING_OS.md → .principles/THINKING_OS.md
|
|
745
|
+
const thinkingOsSrc = join(SOURCE_DIR, 'templates', 'langs', lang, 'principles', 'THINKING_OS.md');
|
|
746
|
+
const thinkingOsDest = join(wsDir, '.principles', 'THINKING_OS.md');
|
|
747
|
+
if (existsSync(thinkingOsSrc)) {
|
|
748
|
+
const srcMd5 = md5(thinkingOsSrc);
|
|
749
|
+
const destMd5 = existsSync(thinkingOsDest) ? md5(thinkingOsDest) : null;
|
|
750
|
+
if (srcMd5 !== destMd5) {
|
|
751
|
+
if (!existsSync(join(wsDir, '.principles'))) {
|
|
752
|
+
mkdirSync(join(wsDir, '.principles'), { recursive: true });
|
|
753
|
+
}
|
|
754
|
+
cpSync(thinkingOsSrc, thinkingOsDest, { force: true });
|
|
755
|
+
updated++;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
if (updated > 0) {
|
|
761
|
+
console.log(` 📄 Workspace templates → ${updated} file(s) synced across ${workspaceDirs.length} workspace(s)`);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* Sync core files ONLY if they don't exist yet.
|
|
767
|
+
* NEVER overwrites existing core files (user customizations).
|
|
768
|
+
*/
|
|
769
|
+
function syncCoreFiles(srcDir, destDir) {
|
|
770
|
+
let count = 0;
|
|
771
|
+
if (!existsSync(srcDir)) return count;
|
|
772
|
+
|
|
773
|
+
const items = readdirSync(srcDir);
|
|
774
|
+
for (const item of items) {
|
|
775
|
+
const srcPath = join(srcDir, item);
|
|
776
|
+
const destPath = join(destDir, item);
|
|
777
|
+
const stat = statSync(srcPath);
|
|
778
|
+
|
|
779
|
+
if (stat.isDirectory()) continue;
|
|
780
|
+
// Core files: only copy if missing
|
|
781
|
+
if (!existsSync(destPath)) {
|
|
782
|
+
cpSync(srcPath, destPath, { force: false });
|
|
783
|
+
count++;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
return count;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
/**
|
|
790
|
+
* Recursively sync source dir to dest dir, skipping core files that already exist.
|
|
791
|
+
* Non-core files: only copy if missing or different (MD5).
|
|
792
|
+
*/
|
|
793
|
+
function syncDirRecursive(srcDir, destDir, md5Fn, coreFiles) {
|
|
794
|
+
let count = 0;
|
|
795
|
+
if (!existsSync(destDir)) {
|
|
796
|
+
mkdirSync(destDir, { recursive: true });
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
const items = readdirSync(srcDir);
|
|
800
|
+
for (const item of items) {
|
|
801
|
+
const srcPath = join(srcDir, item);
|
|
802
|
+
const destPath = join(destDir, item);
|
|
803
|
+
const stat = statSync(srcPath);
|
|
804
|
+
|
|
805
|
+
if (stat.isDirectory()) {
|
|
806
|
+
count += syncDirRecursive(srcPath, destPath, md5Fn, coreFiles);
|
|
807
|
+
} else {
|
|
808
|
+
// Skip core files that already exist
|
|
809
|
+
if (coreFiles.has(item) && existsSync(destPath)) continue;
|
|
810
|
+
|
|
811
|
+
const srcMd5 = md5Fn(srcPath);
|
|
812
|
+
const destMd5 = existsSync(destPath) ? md5Fn(destPath) : null;
|
|
813
|
+
if (srcMd5 !== destMd5) {
|
|
814
|
+
cpSync(srcPath, destPath, { force: true });
|
|
815
|
+
count++;
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
return count;
|
|
820
|
+
}
|
|
821
|
+
|
|
586
822
|
/**
|
|
587
823
|
* Install production dependencies in target directory
|
|
588
824
|
*/
|
|
@@ -693,12 +929,17 @@ function main() {
|
|
|
693
929
|
console.log('║ Principles Disciple Plugin Installer ║');
|
|
694
930
|
console.log('╚════════════════════════════════════════════════════════════╝\n');
|
|
695
931
|
|
|
696
|
-
// Dev mode: auto-force, auto-restart, clean stale backups
|
|
932
|
+
// Dev mode: auto-force, auto-restart, auto-bump, clean stale backups
|
|
697
933
|
if (args.dev) {
|
|
698
|
-
console.log('🛠️ DEV MODE: force + restart + stale backup cleanup\n');
|
|
934
|
+
console.log('🛠️ DEV MODE: force + restart + bump + stale backup cleanup\n');
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
// Auto-bump version if requested
|
|
938
|
+
if (args.bump) {
|
|
939
|
+
autoBumpVersion(SOURCE_DIR);
|
|
699
940
|
}
|
|
700
941
|
|
|
701
|
-
// Get source version
|
|
942
|
+
// Get source version (after potential bump)
|
|
702
943
|
const sourceVersion = getVersion(SOURCE_DIR);
|
|
703
944
|
if (!sourceVersion) {
|
|
704
945
|
console.error('❌ Cannot determine source version. Check package.json.');
|
|
@@ -736,6 +977,9 @@ function main() {
|
|
|
736
977
|
// Step 7: Sync skills
|
|
737
978
|
syncSkills(args.lang);
|
|
738
979
|
|
|
980
|
+
// Step 7.5: Sync THINKING_OS.md to all workspace .principles/ directories
|
|
981
|
+
syncWorkspaceTemplates(args.lang);
|
|
982
|
+
|
|
739
983
|
// Step 8: Install production dependencies in target (ALWAYS — cleanTargetDir wiped node_modules)
|
|
740
984
|
// --skip-deps only applies to SOURCE directory deps, not the installed plugin.
|
|
741
985
|
installTargetDependencies();
|