principles-disciple 1.40.0 → 1.42.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/.planning/codebase/ARCHITECTURE.md +157 -0
- package/.planning/codebase/CONCERNS.md +145 -0
- package/.planning/codebase/CONVENTIONS.md +148 -0
- package/.planning/codebase/INTEGRATIONS.md +81 -0
- package/.planning/codebase/STACK.md +87 -0
- package/.planning/codebase/STRUCTURE.md +193 -0
- package/.planning/codebase/TESTING.md +243 -0
- package/esbuild.config.js +32 -3
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -1
- package/scripts/compile-principles.mjs +94 -0
- package/scripts/sync-plugin.mjs +96 -281
- package/src/commands/pain.ts +12 -5
- package/src/commands/promote-impl.ts +13 -7
- package/src/commands/rollback.ts +10 -3
- package/src/core/event-log.ts +8 -6
- package/src/core/evolution-types.ts +33 -1
- package/src/core/principle-compiler/code-validator.ts +120 -0
- package/src/core/principle-compiler/compiler.ts +242 -0
- package/src/core/principle-compiler/index.ts +10 -0
- package/src/core/principle-compiler/ledger-registrar.ts +107 -0
- package/src/core/principle-compiler/template-generator.ts +108 -0
- package/src/core/reflection/reflection-context.ts +228 -0
- package/src/hooks/message-sanitize.ts +18 -5
- package/src/hooks/prompt.ts +15 -4
- package/src/hooks/subagent.ts +2 -3
- package/src/http/principles-console-route.ts +21 -4
- package/src/service/evolution-worker.ts +89 -365
- package/src/service/queue-io.ts +375 -0
- package/src/service/queue-migration.ts +122 -0
- package/src/service/sleep-cycle.ts +157 -0
- package/src/service/subagent-workflow/runtime-direct-driver.ts +1 -1
- package/src/service/workflow-watchdog.ts +168 -0
- package/src/tools/deep-reflect.ts +22 -11
- package/src/types/event-payload.ts +80 -0
- package/src/types/queue.ts +70 -0
- package/src/utils/file-lock.ts +2 -2
- package/src/utils/io.ts +11 -3
- package/tests/core/code-validator.test.ts +197 -0
- package/tests/core/evolution-migration.test.ts +325 -1
- package/tests/core/ledger-registrar.test.ts +232 -0
- package/tests/core/principle-compiler.test.ts +348 -0
- package/tests/core/queue-purge.test.ts +337 -0
- package/tests/core/reflection-context.test.ts +356 -0
- package/tests/core/template-generator.test.ts +101 -0
- package/tests/fixtures/legacy-queue-v1.json +74 -0
- package/tests/integration/principle-compiler-e2e.test.ts +335 -0
- package/tests/queue/async-lock.test.ts +200 -0
- package/tests/service/evolution-worker.queue.test.ts +296 -0
- package/tests/service/queue-io.test.ts +229 -0
- package/tests/service/queue-migration.test.ts +147 -0
- package/tests/service/workflow-watchdog.test.ts +372 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
**Analysis Date:** 2026-04-15
|
|
4
|
+
|
|
5
|
+
## Pattern Overview
|
|
6
|
+
|
|
7
|
+
**Overall:** Event-driven plugin architecture with hook-based interception
|
|
8
|
+
|
|
9
|
+
**Key Characteristics:**
|
|
10
|
+
- OpenClaw plugin framework with hook-based integration
|
|
11
|
+
- Background worker services for async evolution processing
|
|
12
|
+
- SQLite-based trajectory and state persistence
|
|
13
|
+
- Multi-layer security gates (GFI gate, empathy engine, pain tracking)
|
|
14
|
+
- Workflow managers for complex subagent orchestration
|
|
15
|
+
|
|
16
|
+
## Layers
|
|
17
|
+
|
|
18
|
+
**Plugin Entry Point:**
|
|
19
|
+
- Purpose: Initialize plugin, register hooks, commands, tools, and services
|
|
20
|
+
- Location: `src/index.ts`
|
|
21
|
+
- Contains: Plugin registration, hook handlers, command registration
|
|
22
|
+
- Depends on: OpenClaw SDK, all core modules
|
|
23
|
+
|
|
24
|
+
**Hooks Layer:**
|
|
25
|
+
- Purpose: Intercept and modify OpenClaw agent behavior
|
|
26
|
+
- Location: `src/hooks/`
|
|
27
|
+
- Contains: `prompt.ts` (before_prompt_build), `gate.ts` (before_tool_call), `pain.ts` (after_tool_call), `llm.ts` (llm_output), `lifecycle.ts` (before_reset, compaction), `subagent.ts` (subagent lifecycle)
|
|
28
|
+
- Depends on: Core services, workspace context
|
|
29
|
+
- Used by: OpenClaw event system
|
|
30
|
+
|
|
31
|
+
**Core Services:**
|
|
32
|
+
- Purpose: Business logic for evolution, pain tracking, trajectory, nocturnal training
|
|
33
|
+
- Location: `src/core/` and `src/service/`
|
|
34
|
+
- Contains: `evolution-engine.ts`, `trajectory.ts`, `nocturnal-trinity.ts`, `pain.ts`, `training-program.ts`, `pd-task-service.ts`
|
|
35
|
+
- Depends on: Database, workspace context, config
|
|
36
|
+
|
|
37
|
+
**Command Handlers:**
|
|
38
|
+
- Purpose: Implement slash commands (e.g., `/pd-init`, `/pd-status`, `/pd-nocturnal-review`)
|
|
39
|
+
- Location: `src/commands/`
|
|
40
|
+
- Contains: 20+ command implementations
|
|
41
|
+
- Depends on: Core services, workspace context
|
|
42
|
+
|
|
43
|
+
**Workflow Managers (Subagent Workflow):**
|
|
44
|
+
- Purpose: Orchestrate complex subagent workflows
|
|
45
|
+
- Location: `src/service/subagent-workflow/`
|
|
46
|
+
- Contains: `nocturnal-workflow-manager.ts`, `deep-reflect-workflow-manager.ts`, `empathy-observer-workflow-manager.ts`, `correction-observer-workflow-manager.ts`
|
|
47
|
+
- Depends on: Evolution worker, core services
|
|
48
|
+
|
|
49
|
+
**Database Layer:**
|
|
50
|
+
- Purpose: Persist trajectory data, evolution state, workflow state
|
|
51
|
+
- Location: `src/core/schema/` (migrations), `src/service/central-database.ts`
|
|
52
|
+
- Contains: SQLite schema, migration runner, query services
|
|
53
|
+
- Depends on: better-sqlite3
|
|
54
|
+
|
|
55
|
+
**UI Layer:**
|
|
56
|
+
- Purpose: React-based plugin UI for monitoring and control
|
|
57
|
+
- Location: `ui/src/`
|
|
58
|
+
- Contains: Pages (Overview, Evolution, Feedback, GateMonitor, Samples, ThinkingModels), components (Shell, ProtectedRoute), context (auth, theme)
|
|
59
|
+
- Depends on: React, React Router, lucide-react
|
|
60
|
+
|
|
61
|
+
**Utils:**
|
|
62
|
+
- Purpose: Shared utilities (I/O, logging, retry, hashing, file locking)
|
|
63
|
+
- Location: `src/utils/`
|
|
64
|
+
- Contains: `io.ts` (atomic writes), `plugin-logger.ts`, `retry.ts`, `hashing.ts`, `file-lock.ts`
|
|
65
|
+
|
|
66
|
+
## Data Flow
|
|
67
|
+
|
|
68
|
+
**Agent Execution Flow:**
|
|
69
|
+
1. OpenClaw fires `before_prompt_build` hook
|
|
70
|
+
2. `hooks/prompt.ts` builds context injection (principles, thinking OS, focus, reflection log)
|
|
71
|
+
3. OpenClaw generates response
|
|
72
|
+
4. `hooks/llm.ts` analyzes LLM output for signals
|
|
73
|
+
5. User triggers tool call
|
|
74
|
+
6. `hooks/gate.ts` intercepts `before_tool_call` - evaluates risk, may block
|
|
75
|
+
7. Tool executes
|
|
76
|
+
8. `hooks/pain.ts` intercepts `after_tool_call` - tracks pain signals, empathy penalties
|
|
77
|
+
|
|
78
|
+
**Evolution Flow:**
|
|
79
|
+
1. `EvolutionWorkerService` polls `pain_candidates.json` periodically
|
|
80
|
+
2. For each candidate, `evolution-engine.ts` evaluates and derives improvements
|
|
81
|
+
3. `trajectory.ts` records behavior patterns
|
|
82
|
+
4. Nocturnal training (`nocturnal-trinity.ts`) synthesizes improvements into rule updates
|
|
83
|
+
5. `principle-tree-ledger.ts` manages principle lifecycle
|
|
84
|
+
|
|
85
|
+
**Nocturnal Training Flow:**
|
|
86
|
+
1. Candidate scoring via `nocturnal-candidate-scoring.ts`
|
|
87
|
+
2. Target selection via `nocturnal-target-selector.ts`
|
|
88
|
+
3. Rule implementation validation via `nocturnal-rule-implementation-validator.ts`
|
|
89
|
+
4. Promotion via `promotion-gate.ts`
|
|
90
|
+
|
|
91
|
+
## Key Abstractions
|
|
92
|
+
|
|
93
|
+
**WorkspaceContext:**
|
|
94
|
+
- Purpose: Encapsulates all state and services for a single workspace
|
|
95
|
+
- Examples: `src/core/workspace-context.ts`
|
|
96
|
+
- Pattern: Factory method `WorkspaceContext.fromHookContext()`
|
|
97
|
+
|
|
98
|
+
**EvolutionEngine:**
|
|
99
|
+
- Purpose: Core evolution processing logic
|
|
100
|
+
- Examples: `src/core/evolution-engine.ts`
|
|
101
|
+
- Pattern: Reducer pattern with typed actions
|
|
102
|
+
|
|
103
|
+
**NocturnalTrinity:**
|
|
104
|
+
- Purpose: Three-phase nocturnal training (dataset, training, evaluation)
|
|
105
|
+
- Examples: `src/core/nocturnal-trinity.ts`
|
|
106
|
+
- Pattern: Phase orchestration with contract validation
|
|
107
|
+
|
|
108
|
+
**PainConfig:**
|
|
109
|
+
- Purpose: Plugin configuration management
|
|
110
|
+
- Examples: `src/core/config.ts`
|
|
111
|
+
- Pattern: Singleton per workspace with file persistence
|
|
112
|
+
|
|
113
|
+
**RuleHost:**
|
|
114
|
+
- Purpose: Secure rule execution environment
|
|
115
|
+
- Examples: `src/core/rule-host.ts`
|
|
116
|
+
- Pattern: Sandboxed evaluation with permission checks
|
|
117
|
+
|
|
118
|
+
## Entry Points
|
|
119
|
+
|
|
120
|
+
**Plugin Entry:**
|
|
121
|
+
- Location: `src/index.ts`
|
|
122
|
+
- Triggers: OpenClaw loads plugin
|
|
123
|
+
- Responsibilities: Register all hooks, commands, tools, services; initialize workspace
|
|
124
|
+
|
|
125
|
+
**Command Entry:**
|
|
126
|
+
- Location: `src/commands/*.ts`
|
|
127
|
+
- Triggers: User invokes slash command (e.g., `/pd-init`)
|
|
128
|
+
- Responsibilities: Validate input, delegate to core services, return formatted result
|
|
129
|
+
|
|
130
|
+
**Service Entry:**
|
|
131
|
+
- Location: `src/service/evolution-worker.ts`
|
|
132
|
+
- Triggers: `before_prompt_build` fires (starts background worker)
|
|
133
|
+
- Responsibilities: Process evolution queue, track pain signals, trigger training
|
|
134
|
+
|
|
135
|
+
## Error Handling
|
|
136
|
+
|
|
137
|
+
**Strategy:** Graceful degradation with logging
|
|
138
|
+
|
|
139
|
+
**Patterns:**
|
|
140
|
+
- Try-catch blocks in all hook handlers with error logging
|
|
141
|
+
- `SystemLogger.log()` for critical errors
|
|
142
|
+
- Workspace context error recording via `eventLog.recordHookExecution()`
|
|
143
|
+
- Non-critical errors caught silently (trajectory collection)
|
|
144
|
+
|
|
145
|
+
## Cross-Cutting Concerns
|
|
146
|
+
|
|
147
|
+
**Logging:** `src/utils/plugin-logger.ts` - OpenClaw logger abstraction
|
|
148
|
+
|
|
149
|
+
**Validation:** Schema validation via `@sinclair/typebox` for config and event types
|
|
150
|
+
|
|
151
|
+
**Authentication:** OpenClaw session-based, agent ID extracted from session key
|
|
152
|
+
|
|
153
|
+
**I/O Safety:** Atomic file writes via `atomicWriteFileSync()` in `src/utils/io.ts`
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
*Architecture analysis: 2026-04-15*
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Codebase Concerns
|
|
2
|
+
|
|
3
|
+
**Analysis Date:** 2026-04-15
|
|
4
|
+
|
|
5
|
+
## Tech Debt
|
|
6
|
+
|
|
7
|
+
**Large Monolithic Files:**
|
|
8
|
+
- Issue: `evolution-worker.ts` is 2689 lines, `nocturnal-trinity.ts` is 2429 lines. These exceed reasonable single-file thresholds and make debugging/profiling difficult.
|
|
9
|
+
- Files: `src/service/evolution-worker.ts`, `src/core/nocturnal-trinity.ts`
|
|
10
|
+
- Impact: Hard to trace bugs, no granular profiling, high risk of regression on modification
|
|
11
|
+
- Fix approach: Break into smaller focused modules (e.g., queue-processor.ts, workflow-watchdog.ts, sleep-cycle.ts)
|
|
12
|
+
|
|
13
|
+
**Type Safety Workarounds:**
|
|
14
|
+
- Issue: Extensive use of `as any`, `as unknown`, and double casts (`as unknown as`) throughout the codebase
|
|
15
|
+
- Files: `src/hooks/prompt.ts`, `src/hooks/subagent.ts`, `src/service/evolution-worker.ts`, `src/commands/promote-impl.ts`, `src/commands/rollback.ts`, `src/commands/pain.ts`
|
|
16
|
+
- Impact: Type errors are silenced rather than fixed, runtime type mismatches can go undetected
|
|
17
|
+
- Fix approach: Define proper shared type interfaces, use discriminated unions
|
|
18
|
+
|
|
19
|
+
**Busy-Wait Retry Loops:**
|
|
20
|
+
- Issue: `src/utils/io.ts` uses busy-wait spin loops (`while (Date.now() < end)`) for Windows file lock retries
|
|
21
|
+
- Files: `src/utils/io.ts` (lines 32-33)
|
|
22
|
+
- Impact: Consumes CPU while waiting; fails to yield to event loop
|
|
23
|
+
- Fix approach: Use `setTimeout` delay or `fs.promises` with proper async retry
|
|
24
|
+
|
|
25
|
+
**Unhandled Promise Rejections:**
|
|
26
|
+
- Issue: Comments in `evolution-worker.ts` (line 182) reference unhandled rejections leaving workflows in limbo. Pattern of catch blocks that re-throw or log but don't always propagate.
|
|
27
|
+
- Files: `src/service/evolution-worker.ts`
|
|
28
|
+
- Impact: Workflows stuck in inconsistent state, silent failures
|
|
29
|
+
- Fix approach: Ensure all async operations have proper error handlers; use `process.on('unhandledRejection')` logging
|
|
30
|
+
|
|
31
|
+
**TODO Comments Not Addressed:**
|
|
32
|
+
- Issue: One active TODO in `src/hooks/bash-risk.ts:18` — "Extract types from gate.ts related to bash risk analysis"
|
|
33
|
+
- Files: `src/hooks/bash-risk.ts`
|
|
34
|
+
|
|
35
|
+
## Known Bugs
|
|
36
|
+
|
|
37
|
+
**Stale Active Workflows (#185):**
|
|
38
|
+
- Symptoms: Workflows marked 'active' but subagent never responds, blocking queue processing
|
|
39
|
+
- Files: `src/service/evolution-worker.ts` (runWorkflowWatchdog)
|
|
40
|
+
- Trigger: Subagent crash or network failure during workflow execution
|
|
41
|
+
- Workaround: Watchdog marks them as 'terminal_error' after 2x TTL
|
|
42
|
+
|
|
43
|
+
**Orphaned Sessions (#188):**
|
|
44
|
+
- Symptoms: Child session cleanup fails when subagent runtime unavailable
|
|
45
|
+
- Files: `src/service/evolution-worker.ts` (cleanup path)
|
|
46
|
+
- Trigger: Gateway-safe fallback fails
|
|
47
|
+
- Workaround: Manual cleanup required
|
|
48
|
+
|
|
49
|
+
**Sleep Reflection Timeout Recovery (#214, #219):**
|
|
50
|
+
- Symptoms: `sleep_reflection` tasks stuck in 'in_progress' after worker crash
|
|
51
|
+
- Files: `src/service/evolution-worker.ts` (lines 1122-1198)
|
|
52
|
+
- Trigger: Worker crashes after claiming task but before writing result
|
|
53
|
+
- Fix: Timeout recovery logic reclaims stuck tasks after `task_timeout_ms`
|
|
54
|
+
|
|
55
|
+
## Security Considerations
|
|
56
|
+
|
|
57
|
+
**Credential Detection in Logs:**
|
|
58
|
+
- Risk: Sensitive data (passwords, tokens, api_keys) may leak into event logs or trajectory data
|
|
59
|
+
- Files: `src/hooks/trajectory-collector.ts`, `src/core/nocturnal-arbiter.ts`, `src/core/nocturnal-compliance.ts`
|
|
60
|
+
- Current mitigation: `SENSITIVE_KEY_PATTERN` regex filters known patterns
|
|
61
|
+
- Recommendations: Extend pattern to cover more formats; add redaction before any async write
|
|
62
|
+
|
|
63
|
+
**Gateway Token Auth:**
|
|
64
|
+
- Risk: HTTP route in `principles-console-route.ts` uses Bearer token auth
|
|
65
|
+
- Files: `src/http/principles-console-route.ts`
|
|
66
|
+
- Current mitigation: Token comparison with configured value
|
|
67
|
+
- Recommendations: Use constant-time comparison to prevent timing attacks
|
|
68
|
+
|
|
69
|
+
**No eval() or Dynamic Code Execution:**
|
|
70
|
+
- Status: Clean — no `eval()`, `new Function()`, or `dangerouslySetInnerHTML` found in codebase
|
|
71
|
+
|
|
72
|
+
## Performance Bottlenecks
|
|
73
|
+
|
|
74
|
+
**Session Persistence Timer Per Session:**
|
|
75
|
+
- Problem: `session-tracker.ts` creates a `setTimeout` per session for delayed persistence writes
|
|
76
|
+
- Files: `src/core/session-tracker.ts`
|
|
77
|
+
- Cause: Timer per workspace/session scales poorly with many concurrent sessions
|
|
78
|
+
- Improvement path: Use a single periodic sweep for all dirty sessions
|
|
79
|
+
|
|
80
|
+
**Event Log Buffer Flush:**
|
|
81
|
+
- Problem: 20-event buffer or 30-second flush interval — events can be lost on crash
|
|
82
|
+
- Files: `src/core/event-log.ts`
|
|
83
|
+
- Cause: Trade-off between I/O frequency and durability
|
|
84
|
+
- Improvement path: Flush immediately on critical events (hook failures, errors)
|
|
85
|
+
|
|
86
|
+
**Evolution Queue File Read on Every Cycle:**
|
|
87
|
+
- Problem: `evolution-worker.ts` reads and parses the entire queue JSON file on each heartbeat
|
|
88
|
+
- Files: `src/service/evolution-worker.ts` (queue loading at lines 1085-1110)
|
|
89
|
+
- Cause: Full file read/parse despite incremental changes
|
|
90
|
+
- Improvement path: Use SQLite or incremental updates
|
|
91
|
+
|
|
92
|
+
**Focus History Compression Timestamp:**
|
|
93
|
+
- Problem: `focus-history.ts` writes `Date.now().toString()` on every compression
|
|
94
|
+
- Files: `src/core/focus-history.ts` (line 962)
|
|
95
|
+
- Impact: File modified on every compress even if content unchanged
|
|
96
|
+
|
|
97
|
+
## Fragile Areas
|
|
98
|
+
|
|
99
|
+
**Workflow Store Queue Migration:**
|
|
100
|
+
- Files: `src/service/evolution-worker.ts` (migrateQueueToV2), `src/service/subagent-workflow/workflow-store.ts`
|
|
101
|
+
- Why fragile: Legacy queue format detection via type guards, migration happens on every cycle
|
|
102
|
+
- Safe modification: Add version field, run migrations once at startup not per cycle
|
|
103
|
+
|
|
104
|
+
**JSON.parse Without Try-Catch on Queue Items:**
|
|
105
|
+
- Files: `src/service/evolution-worker.ts` (line 1148: `JSON.parse(failureEvent.payload_json)`)
|
|
106
|
+
- Why fragile: Payload may be malformed, parse throws and is caught broadly
|
|
107
|
+
- Safe modification: Validate JSON structure before parse
|
|
108
|
+
|
|
109
|
+
**Nocturnal Trinity Runtime Adapter:**
|
|
110
|
+
- Files: `src/core/nocturnal-trinity.ts` (TrinityRuntimeAdapter)
|
|
111
|
+
- Why fragile: Uses `api.runtime.agent.runEmbeddedPiAgent()` which has specific requirements (provider/model must be explicit)
|
|
112
|
+
- Safe modification: Ensure all trinity calls pass explicit provider/model
|
|
113
|
+
|
|
114
|
+
## Dependencies at Risk
|
|
115
|
+
|
|
116
|
+
**better-sqlite3 (^12.9.0):**
|
|
117
|
+
- Risk: Native module requiring platform-specific rebuilds; may break on Node.js major version upgrades
|
|
118
|
+
- Impact: Database operations fail, session/trajectory storage breaks
|
|
119
|
+
- Migration plan: Consider `sql.js` (pure JS) or `node:sqlite` (built-in) for portability
|
|
120
|
+
|
|
121
|
+
**@sinclair/typebox (^0.34.48):**
|
|
122
|
+
- Risk: Used for runtime schema validation; newer versions may change behavior
|
|
123
|
+
- Impact: Validation mismatches could allow invalid data through
|
|
124
|
+
|
|
125
|
+
## Test Coverage Gaps
|
|
126
|
+
|
|
127
|
+
**Untested Service Layer:**
|
|
128
|
+
- What's not tested: `evolution-worker.ts` (2689 lines), `nocturnal-service.ts` (1584 lines)
|
|
129
|
+
- Files: `src/service/evolution-worker.ts`, `src/service/nocturnal-service.ts`
|
|
130
|
+
- Risk: High — service layer contains critical business logic
|
|
131
|
+
- Priority: High
|
|
132
|
+
|
|
133
|
+
**Untested Workflow Managers:**
|
|
134
|
+
- What's not tested: `empathy-observer-workflow-manager.ts`, `deep-reflect-workflow-manager.ts`, `correction-observer-workflow-manager.ts`
|
|
135
|
+
- Files: `src/service/subagent-workflow/`
|
|
136
|
+
- Risk: Workflow spawning and result handling is untested
|
|
137
|
+
|
|
138
|
+
**No Integration Tests for Queue Processing:**
|
|
139
|
+
- What's not tested: Queue enqueue/dequeue cycle, migration path, error recovery
|
|
140
|
+
- Files: `src/service/evolution-worker.ts` (queue operations)
|
|
141
|
+
- Risk: Queue corruption or migration bugs go undetected
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
*Concerns audit: 2026-04-15*
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Coding Conventions
|
|
2
|
+
|
|
3
|
+
**Analysis Date:** 2026-04-15
|
|
4
|
+
|
|
5
|
+
## Naming Patterns
|
|
6
|
+
|
|
7
|
+
**Files:**
|
|
8
|
+
- PascalCase for modules: `detection-service.ts`, `risk-calculator.ts`
|
|
9
|
+
- kebab-case for utilities with multiple exports: `retry.ts`, `hashing.ts`
|
|
10
|
+
- `.test.ts` suffix for test files co-located in `tests/` directory
|
|
11
|
+
|
|
12
|
+
**Directories:**
|
|
13
|
+
- Flat structure under `src/`: `commands/`, `core/`, `hooks/`, `service/`, `utils/`
|
|
14
|
+
- Tests mirror source structure in `tests/` parallel directory
|
|
15
|
+
|
|
16
|
+
**Functions:**
|
|
17
|
+
- camelCase: `normalizePath`, `handleBeforeToolCall`, `computeDynamicTimeout`
|
|
18
|
+
- Verb prefixes for actions: `handle*`, `compute*`, `extract*`, `serialize*`
|
|
19
|
+
- Getter-style for services: `DetectionService.get()`, `WorkspaceContext.fromHookContext()`
|
|
20
|
+
|
|
21
|
+
**Types & Interfaces:**
|
|
22
|
+
- PascalCase: `DeepReflectionSettings`, `PainSettings`, `GfiGateSettings`
|
|
23
|
+
- Suffix for type variants: `*Types`, `*Contract`, `*Schema`
|
|
24
|
+
- Barrel exports via `index.ts` in each directory
|
|
25
|
+
|
|
26
|
+
## Code Style
|
|
27
|
+
|
|
28
|
+
**Formatting:**
|
|
29
|
+
- ESLint with `@typescript-eslint` plugin
|
|
30
|
+
- No Prettier config detected (not enforced)
|
|
31
|
+
- 2-space indentation
|
|
32
|
+
- No trailing semicolons in ESLint config (but not explicitly disabled)
|
|
33
|
+
|
|
34
|
+
**Key ESLint Rules:**
|
|
35
|
+
```javascript
|
|
36
|
+
'no-empty': 'error',
|
|
37
|
+
'no-console': 'warn',
|
|
38
|
+
'@typescript-eslint/no-explicit-any': 'warn',
|
|
39
|
+
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
|
|
40
|
+
'@typescript-eslint/no-non-null-assertion': 'warn',
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Linting (test files relaxed):**
|
|
44
|
+
```javascript
|
|
45
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
46
|
+
'no-empty': 'warn',
|
|
47
|
+
'no-console': 'off',
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Import Organization:**
|
|
51
|
+
1. Node.js built-ins (`path`, `fs`, `os`)
|
|
52
|
+
2. External packages (`vitest`, `better-sqlite3`)
|
|
53
|
+
3. Internal modules (`../../src/core/...`, `./hooks/...`)
|
|
54
|
+
4. Type-only imports use `import type` syntax
|
|
55
|
+
|
|
56
|
+
**Path Aliases:**
|
|
57
|
+
- No `paths` aliasing in `tsconfig.json`
|
|
58
|
+
- Relative imports with `.js` extension for ESM compatibility: `from '../../src/utils/io.js'`
|
|
59
|
+
|
|
60
|
+
## Error Handling
|
|
61
|
+
|
|
62
|
+
**Patterns:**
|
|
63
|
+
- Return `undefined` for "not found" / "allowed" cases (not exceptions)
|
|
64
|
+
- Throw typed errors from `src/config/errors.ts`
|
|
65
|
+
- Result objects with `allowed: boolean` for gate checks
|
|
66
|
+
- Log warnings via `plugin-logger.ts` for non-critical failures
|
|
67
|
+
|
|
68
|
+
**Example - Gate pattern:**
|
|
69
|
+
```typescript
|
|
70
|
+
// Return block result, not exceptions
|
|
71
|
+
export function handleBeforeToolCall(event, ctx): BlockResult | undefined {
|
|
72
|
+
if (someCondition) {
|
|
73
|
+
return { block: true, blockReason: '...' };
|
|
74
|
+
}
|
|
75
|
+
return undefined; // Allowed
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**SQLite errors:**
|
|
80
|
+
- Use `better-sqlite3` with synchronous API
|
|
81
|
+
- Wrap in try/catch for migration failures
|
|
82
|
+
|
|
83
|
+
## Logging
|
|
84
|
+
|
|
85
|
+
**Framework:** `src/utils/plugin-logger.ts`
|
|
86
|
+
|
|
87
|
+
**Patterns:**
|
|
88
|
+
- Structured logging with levels: `warn`, `error`, `info`, `debug`
|
|
89
|
+
- Context passed as object: `logger.warn({ context: 'Gate' }, 'message')`
|
|
90
|
+
- No `console.log` in production paths (warn-only via ESLint)
|
|
91
|
+
|
|
92
|
+
## Comments
|
|
93
|
+
|
|
94
|
+
**When to Comment:**
|
|
95
|
+
- Complex cross-platform logic (Windows EPERM handling in `atomicWriteFileSync`)
|
|
96
|
+
- Magic numbers explained: `const RENAME_MAX_RETRIES = 3`
|
|
97
|
+
- Task markers in tests: `// Task 4: Default Values Consistency Tests`
|
|
98
|
+
|
|
99
|
+
**JSDoc:**
|
|
100
|
+
- Used in config files and public APIs
|
|
101
|
+
- Not enforced on internal functions
|
|
102
|
+
|
|
103
|
+
## Function Design
|
|
104
|
+
|
|
105
|
+
**Size:**
|
|
106
|
+
- Prefer small, focused functions
|
|
107
|
+
- Complex modules split into helpers (e.g., `rule-host-helpers.ts`)
|
|
108
|
+
|
|
109
|
+
**Parameters:**
|
|
110
|
+
- Max 3-4 parameters before grouping into options object
|
|
111
|
+
- Destructure for clarity: `function ({ workspaceDir, stateDir })`
|
|
112
|
+
|
|
113
|
+
**Return Values:**
|
|
114
|
+
- Explicit return types in public APIs
|
|
115
|
+
- `undefined` for "not applicable" vs `null` for "intentionally empty"
|
|
116
|
+
|
|
117
|
+
## Module Design
|
|
118
|
+
|
|
119
|
+
**Exports:**
|
|
120
|
+
- Named exports preferred over default exports
|
|
121
|
+
- Barrel `index.ts` files aggregate directory exports
|
|
122
|
+
- Factory functions for singleton services: `DetectionService.get(dir)`
|
|
123
|
+
|
|
124
|
+
**Service Pattern:**
|
|
125
|
+
```typescript
|
|
126
|
+
// Singleton pattern for stateful services
|
|
127
|
+
class DetectionService {
|
|
128
|
+
private static instances = new Map<string, DetectionFunnel>();
|
|
129
|
+
|
|
130
|
+
static get(stateDir: string): DetectionFunnel {
|
|
131
|
+
if (!instances.has(stateDir)) {
|
|
132
|
+
instances.set(stateDir, new DetectionFunnel(...));
|
|
133
|
+
}
|
|
134
|
+
return instances.get(stateDir);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
static reset(): void { instances.clear(); }
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Static Analysis:**
|
|
142
|
+
- Vitest used for unit tests
|
|
143
|
+
- ESM modules with `.js` extension in imports
|
|
144
|
+
- `"type": "module"` in `package.json`
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
*Convention analysis: 2026-04-15*
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# External Integrations
|
|
2
|
+
|
|
3
|
+
**Analysis Date:** 2026-04-15
|
|
4
|
+
|
|
5
|
+
## APIs & External Services
|
|
6
|
+
|
|
7
|
+
**Plugin Framework:**
|
|
8
|
+
- OpenClaw - Host application
|
|
9
|
+
- SDK/Client: `@openclaw/plugin-kit` (peer dependency, bundled as external)
|
|
10
|
+
- Communication: Plugin hook events (`before_prompt_build`, `before_tool_call`, `after_tool_call`, `llm_output`, `subagent_spawning`, `subagent_ended`, `before_reset`, `before_compaction`, `after_compaction`)
|
|
11
|
+
- Registration: Commands, tools, HTTP routes, background services
|
|
12
|
+
|
|
13
|
+
## Data Storage
|
|
14
|
+
|
|
15
|
+
**Databases:**
|
|
16
|
+
- SQLite (better-sqlite3 12.9.0)
|
|
17
|
+
- Connection: File-based at `.state/trajectory.db`
|
|
18
|
+
- Schema managed via migration runner in `src/core/schema/migrations/`
|
|
19
|
+
- Migrations: 4 migrations (001-init-trajectory, 002-init-central, 003-init-workflow, 004-add-thinking-and-gfi)
|
|
20
|
+
|
|
21
|
+
**File Storage:**
|
|
22
|
+
- Local filesystem (workspace-relative paths)
|
|
23
|
+
- Templates copied to workspace on init (`templates/` directory)
|
|
24
|
+
- State persisted to `.state/` directory
|
|
25
|
+
- Pain samples stored in `memory/pain/`
|
|
26
|
+
|
|
27
|
+
**Caching:**
|
|
28
|
+
- None detected (in-memory caching only)
|
|
29
|
+
|
|
30
|
+
## Authentication & Identity
|
|
31
|
+
|
|
32
|
+
**Auth Provider:**
|
|
33
|
+
- OpenClaw native (session-based)
|
|
34
|
+
- Implementation: Session key extraction via `extractAgentIdFromSessionKey()` in `src/utils/session-key.ts`
|
|
35
|
+
- Agent identification via `agentId` from OpenClaw context
|
|
36
|
+
|
|
37
|
+
## Monitoring & Observability
|
|
38
|
+
|
|
39
|
+
**Error Tracking:**
|
|
40
|
+
- Plugin logger (`src/utils/plugin-logger.ts`)
|
|
41
|
+
- System logger (`src/core/system-logger.ts`)
|
|
42
|
+
- Hook execution recording via `WorkspaceContext.eventLog.recordHookExecution()`
|
|
43
|
+
|
|
44
|
+
**Logs:**
|
|
45
|
+
- File-based logs: `.state/memory/logs/SYSTEM.log`
|
|
46
|
+
- Console output for errors during build/dev
|
|
47
|
+
|
|
48
|
+
## CI/CD & Deployment
|
|
49
|
+
|
|
50
|
+
**Hosting:**
|
|
51
|
+
- OpenClaw plugin ecosystem
|
|
52
|
+
- Published as npm package `principles-disciple`
|
|
53
|
+
|
|
54
|
+
**CI Pipeline:**
|
|
55
|
+
- Not detected (no GitHub Actions or similar)
|
|
56
|
+
|
|
57
|
+
## Environment Configuration
|
|
58
|
+
|
|
59
|
+
**Required env vars:**
|
|
60
|
+
- None required (configuration via OpenClaw plugin config API)
|
|
61
|
+
|
|
62
|
+
**Secrets location:**
|
|
63
|
+
- OpenClaw plugin configuration (not file-based)
|
|
64
|
+
|
|
65
|
+
## Webhooks & Callbacks
|
|
66
|
+
|
|
67
|
+
**Incoming (via OpenClaw hooks):**
|
|
68
|
+
- `before_prompt_build` - Prompt building stage
|
|
69
|
+
- `before_tool_call` - Security gate before tool execution
|
|
70
|
+
- `after_tool_call` - Pain/trust tracking after tool execution
|
|
71
|
+
- `llm_output` - LLM response analysis
|
|
72
|
+
- `subagent_spawning` - Subagent lifecycle
|
|
73
|
+
- `subagent_ended` - Subagent completion
|
|
74
|
+
- `before_reset` / `before_compaction` / `after_compaction` - Workspace lifecycle
|
|
75
|
+
|
|
76
|
+
**Outgoing:**
|
|
77
|
+
- HTTP routes registered via `api.registerHttpRoute()` in `src/http/principles-console-route.ts`
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
*Integration audit: 2026-04-15*
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Technology Stack
|
|
2
|
+
|
|
3
|
+
**Analysis Date:** 2026-04-15
|
|
4
|
+
|
|
5
|
+
## Languages
|
|
6
|
+
|
|
7
|
+
**Primary:**
|
|
8
|
+
- TypeScript 6.0.2 - Core plugin development
|
|
9
|
+
- JSX/TSX - UI components
|
|
10
|
+
|
|
11
|
+
**Secondary:**
|
|
12
|
+
- JavaScript (ES2022) - Build scripts and configuration
|
|
13
|
+
|
|
14
|
+
## Runtime
|
|
15
|
+
|
|
16
|
+
**Environment:**
|
|
17
|
+
- Node.js 20 (build target via esbuild)
|
|
18
|
+
|
|
19
|
+
**Package Manager:**
|
|
20
|
+
- pnpm 9.x
|
|
21
|
+
- Lockfile: `pnpm-lock.yaml` (present)
|
|
22
|
+
|
|
23
|
+
## Frameworks
|
|
24
|
+
|
|
25
|
+
**Core:**
|
|
26
|
+
- OpenClaw Plugin SDK (peer dependency) - Plugin architecture framework
|
|
27
|
+
- React 19.2.0 - UI layer
|
|
28
|
+
- React Router 7.9.4 - UI routing
|
|
29
|
+
|
|
30
|
+
**Database:**
|
|
31
|
+
- better-sqlite3 12.9.0 - Local SQLite database for trajectory and state persistence
|
|
32
|
+
|
|
33
|
+
**UI Components:**
|
|
34
|
+
- lucide-react 1.7.0 - Icon library
|
|
35
|
+
|
|
36
|
+
**Build:**
|
|
37
|
+
- esbuild 0.28.0 - Bundling plugin code
|
|
38
|
+
- TypeScript 6.0.2 - Type checking and compilation
|
|
39
|
+
|
|
40
|
+
**Testing:**
|
|
41
|
+
- Vitest 4.1.0 - Test runner
|
|
42
|
+
- @vitest/coverage-v8 4.1.0 - Coverage reporting
|
|
43
|
+
- jsdom 29.0.1 - DOM environment for React testing
|
|
44
|
+
- @testing-library/react 16.3.0 - React component testing
|
|
45
|
+
|
|
46
|
+
**Linting:**
|
|
47
|
+
- ESLint 10.1.0 - Code linting
|
|
48
|
+
- @typescript-eslint packages 8.58.0 - TypeScript ESLint support
|
|
49
|
+
|
|
50
|
+
## Key Dependencies
|
|
51
|
+
|
|
52
|
+
**Critical:**
|
|
53
|
+
- `@sinclair/typebox` 0.34.48 - JSON schema type generation
|
|
54
|
+
- `micromatch` 4.0.8 - Glob pattern matching for file paths
|
|
55
|
+
|
|
56
|
+
**Database:**
|
|
57
|
+
- `@types/better-sqlite3` 7.6.13 - TypeScript types for SQLite
|
|
58
|
+
|
|
59
|
+
**HTTP/WebSocket:**
|
|
60
|
+
- `ws` 8.18.0 - WebSocket support
|
|
61
|
+
- `@types/ws` 8.5.13 - TypeScript types for WebSocket
|
|
62
|
+
|
|
63
|
+
## Configuration
|
|
64
|
+
|
|
65
|
+
**Environment:**
|
|
66
|
+
- Plugin configuration via `openclaw.plugin.json`
|
|
67
|
+
- Workspace-level settings in `.state/pain_settings.json`
|
|
68
|
+
- No `.env` files (configuration is code-driven)
|
|
69
|
+
|
|
70
|
+
**Build:**
|
|
71
|
+
- `tsconfig.json` - TypeScript configuration (target: ES2022, module: ESNext)
|
|
72
|
+
- `esbuild.config.js` - Bundle configuration
|
|
73
|
+
- `vitest.config.ts` - Test configuration with layered projects (unit/integration)
|
|
74
|
+
|
|
75
|
+
## Platform Requirements
|
|
76
|
+
|
|
77
|
+
**Development:**
|
|
78
|
+
- Node.js 20+
|
|
79
|
+
- pnpm 9+
|
|
80
|
+
|
|
81
|
+
**Production:**
|
|
82
|
+
- OpenClaw >=2026.4.4 (peer dependency)
|
|
83
|
+
- Node.js 20 runtime
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
*Stack analysis: 2026-04-15*
|