parallax-opencode 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +217 -0
- package/agents/parallax.md +100 -0
- package/dist/cli.d.ts +19 -0
- package/dist/cli.js +236 -0
- package/dist/detect.d.ts +23 -0
- package/dist/detect.js +65 -0
- package/dist/discord-rpc.d.ts +79 -0
- package/dist/discord-rpc.js +297 -0
- package/dist/plugin.d.ts +99 -0
- package/dist/plugin.js +609 -0
- package/dist/score.d.ts +41 -0
- package/dist/score.js +160 -0
- package/dist/trace.d.ts +62 -0
- package/dist/trace.js +206 -0
- package/dist/types.d.ts +94 -0
- package/dist/types.js +10 -0
- package/dist-standalone/parallax-engine.d.ts +99 -0
- package/dist-standalone/parallax-engine.js +35239 -0
- package/package.json +65 -0
- package/postinstall.mjs +14 -0
- package/scripts/install.mjs +129 -0
- package/scripts/publish.mjs +82 -0
- package/skills/parallax/SKILL.md +76 -0
- package/skills/parallax-debug/SKILL.md +163 -0
- package/skills/parallax-plan/SKILL.md +191 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Master0fFate
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
[](https://github.com/Master0fFate/parallax-opencode)
|
|
2
|
+
|
|
3
|
+
# PARALLAX ENGINE
|
|
4
|
+
|
|
5
|
+
**The first AI coding assistant that shows its work.**
|
|
6
|
+
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
[](https://opencode.ai)
|
|
9
|
+
[](https://www.npmjs.com/package/parallax-opencode)
|
|
10
|
+
[]()
|
|
11
|
+
[]()
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Quick Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# One command -- installs agent, plugin, skills, and dependencies
|
|
19
|
+
npx parallax-opencode
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
After install, restart OpenCode and press **Tab** in the TUI to cycle to the Parallax agent.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## What Makes Parallax Different
|
|
27
|
+
|
|
28
|
+
Every AI coding tool (Cursor, Copilot, Windsurf) gives you code. None of them show you **how they got there**.
|
|
29
|
+
|
|
30
|
+
Parallax captures the complete reasoning trace of every session -- the ambiguity assessment, the invariants analysis, every verification result, every decision -- and makes it visible, exportable, and replayable.
|
|
31
|
+
|
|
32
|
+
Instead of "trust me, I wrote good code," Parallax says:
|
|
33
|
+
|
|
34
|
+
> "Here is my complete reasoning trace. Review it. Score it. Compare it with another approach. See for yourself."
|
|
35
|
+
|
|
36
|
+
### The 4 Invariants
|
|
37
|
+
|
|
38
|
+
Every action is checked against four questions:
|
|
39
|
+
|
|
40
|
+
| Question | Why It Matters |
|
|
41
|
+
|---|---|
|
|
42
|
+
| Where does state live? | Ownership & truth, consistency, blast radius |
|
|
43
|
+
| Where does feedback live? | Observability, debugging, monitoring |
|
|
44
|
+
| What breaks if I delete this? | Coupling & fragility, safe refactoring |
|
|
45
|
+
| When does timing matter? | Async & ordering, race conditions, correctness |
|
|
46
|
+
|
|
47
|
+
### The Coherence Score
|
|
48
|
+
|
|
49
|
+
After every session, Parallax computes an evidence-based quality score (0-100):
|
|
50
|
+
|
|
51
|
+
- **Protocol Coverage (30%)** -- Were all 5 protocol phases completed?
|
|
52
|
+
- **Verification Integrity (35%)** -- Pass rate on first attempt?
|
|
53
|
+
- **Edge Case Coverage (20%)** -- How many edge categories were analyzed?
|
|
54
|
+
- **Timing Discipline (15%)** -- Were phases in correct order?
|
|
55
|
+
|
|
56
|
+
Track your scores over time and see improvement:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
parallax trace trend
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### The Trace Protocol
|
|
63
|
+
|
|
64
|
+
Every session produces a structured JSON trace file:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
parallax trace list
|
|
68
|
+
parallax trace show <session-id>
|
|
69
|
+
parallax trace score <session-id>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Traces are stored in `.parallax/traces/` and can be attached to PRs, bug reports, or shared for review.
|
|
73
|
+
|
|
74
|
+
### The Friction Loop
|
|
75
|
+
|
|
76
|
+
1. After every write, Parallax auto-verifies (debounced)
|
|
77
|
+
2. 3 retries before blocking further writes
|
|
78
|
+
3. Parses verification output and reports specific failures
|
|
79
|
+
4. Only the friction loop enforces quality -- the rest is instrumentation
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Comparison
|
|
84
|
+
|
|
85
|
+
| Feature | Plain OpenCode | Cursor | Copilot | Parallax |
|
|
86
|
+
|---|---|---|---|---|
|
|
87
|
+
| Structured reasoning trace | No | No | No | **Yes** |
|
|
88
|
+
| Exportable session history | No | No | No | **Yes** |
|
|
89
|
+
| Evidence-based quality score | No | No | No | **Yes** |
|
|
90
|
+
| Protocol enforcement | No | No | No | **Yes** |
|
|
91
|
+
| Mode switching (plan/build/debug) | No | No | No | **Yes** |
|
|
92
|
+
| CLI for trace analysis | No | No | No | **Yes** |
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Architecture
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
Parallax Agent (system prompt)
|
|
100
|
+
|
|
|
101
|
+
+-- Plugin hooks
|
|
102
|
+
| event --> track session ID
|
|
103
|
+
| tool.execute.before --> block writes if friction exhausted
|
|
104
|
+
| tool.execute.after --> debounced auto-verify + trace recording
|
|
105
|
+
| system.transform --> inject protocol status + mode skill
|
|
106
|
+
| session.compacting --> preserve state + export trace
|
|
107
|
+
|
|
|
108
|
+
+-- Custom tools (7)
|
|
109
|
+
| parallax_verify auto-verify after writes
|
|
110
|
+
| parallax_analyze multi-perspective analysis
|
|
111
|
+
| parallax_checkin mark protocol step complete
|
|
112
|
+
| parallax_plan switch to PLAN mode
|
|
113
|
+
| parallax_build switch to BUILD mode
|
|
114
|
+
| parallax_debug switch to DEBUG mode
|
|
115
|
+
| parallax_trace_export export session trace to file
|
|
116
|
+
|
|
|
117
|
+
+-- CLI (parallax)
|
|
118
|
+
init create .parallax/ directory
|
|
119
|
+
trace list list all session traces
|
|
120
|
+
trace show <id> show trace details
|
|
121
|
+
trace score <id> show coherence score
|
|
122
|
+
trace export <id> export trace to JSON
|
|
123
|
+
trace trend show score trend
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Three Modes
|
|
127
|
+
|
|
128
|
+
| Mode | Tool | When |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| **PLAN** | `parallax_plan` | Vague requirements, before writing code |
|
|
131
|
+
| **BUILD** | `parallax_build` | Executing, writing code (default) |
|
|
132
|
+
| **DEBUG** | `parallax_debug` | Post-build quality and security audit |
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Manual Install (no npm)
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# Copy files directly
|
|
140
|
+
cp dist-standalone/parallax-engine.js ~/.config/opencode/plugins/
|
|
141
|
+
cp agents/parallax.md ~/.config/opencode/agents/
|
|
142
|
+
cp -r skills/parallax ~/.config/opencode/skills/
|
|
143
|
+
cp -r skills/parallax-plan ~/.config/opencode/skills/
|
|
144
|
+
cp -r skills/parallax-debug ~/.config/opencode/skills/
|
|
145
|
+
|
|
146
|
+
# Install runtime dependency
|
|
147
|
+
cd ~/.config/opencode && npm init -y && npm install @opencode-ai/plugin
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Project Status
|
|
153
|
+
|
|
154
|
+
**Current phase: v0.2.0** -- Foundation + Trace Protocol
|
|
155
|
+
|
|
156
|
+
| Phase | Status | What |
|
|
157
|
+
|---|---|---|
|
|
158
|
+
| 0: Honest Foundation | Complete | MIT license, TS consolidation, 30 tests |
|
|
159
|
+
| 1: Trace Protocol | Complete | Trace recording, export, CLI, coherence score |
|
|
160
|
+
| 2: Quality Scoring | Complete | Score formula, trend tracking |
|
|
161
|
+
| 3: Git Integration | Planned | Commit trace links, PR-ready reports |
|
|
162
|
+
| 4: GitHub Excellence | In progress | README, CI/CD, docs |
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Commands
|
|
167
|
+
|
|
168
|
+
### Plugin Tools (in OpenCode)
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
parallax_verify Run project verification
|
|
172
|
+
parallax_analyze {topic} Structured multi-perspective analysis
|
|
173
|
+
parallax_checkin {step} Mark protocol step complete
|
|
174
|
+
parallax_plan Switch to PLAN mode
|
|
175
|
+
parallax_build Switch to BUILD mode
|
|
176
|
+
parallax_debug Switch to DEBUG mode
|
|
177
|
+
parallax_trace_export Export session trace to JSON
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### CLI (terminal)
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
parallax init Create .parallax/ directory
|
|
184
|
+
parallax trace list List all traces
|
|
185
|
+
parallax trace show <id> Show trace details
|
|
186
|
+
parallax trace score <id> Show coherence score breakdown
|
|
187
|
+
parallax trace export <id> Export trace as pretty JSON
|
|
188
|
+
parallax trace trend Show score trend over time
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Files
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
parallax_plugin/
|
|
197
|
+
agents/parallax.md # Primary agent definition
|
|
198
|
+
src/plugin.ts # Canonical plugin (TypeScript)
|
|
199
|
+
src/types.ts # Shared type definitions
|
|
200
|
+
src/detect.ts # Project detection
|
|
201
|
+
src/trace.ts # Trace recording and export
|
|
202
|
+
src/score.ts # Coherence score computation
|
|
203
|
+
src/cli.ts # CLI entry point
|
|
204
|
+
src/tests/ # 30 tests across 5 files
|
|
205
|
+
dist/ # Compiled output
|
|
206
|
+
dist-standalone/ # Standalone plugin file
|
|
207
|
+
skills/ # Protocol skills
|
|
208
|
+
scripts/ # Install and publish scripts
|
|
209
|
+
package.json # npm package metadata
|
|
210
|
+
LICENSE # MIT
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## License
|
|
216
|
+
|
|
217
|
+
MIT © [@Master0fFate](https://github.com/Master0fFate)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Parallax
|
|
3
|
+
description: "PARALLAX ENGINE: Multi-perspective AI coding agent with friction-loop verification, the 4 invariants framework, and parallax planning protocol. Views every problem from every angle before acting. Best for complex engineering work requiring depth and correctness."
|
|
4
|
+
mode: primary
|
|
5
|
+
color: "#6c63ff"
|
|
6
|
+
permission:
|
|
7
|
+
edit: allow
|
|
8
|
+
bash: ask
|
|
9
|
+
read: allow
|
|
10
|
+
grep: allow
|
|
11
|
+
glob: allow
|
|
12
|
+
list: allow
|
|
13
|
+
webfetch: allow
|
|
14
|
+
todowrite: allow
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
You are PARALLAX -- a systems thinking partner for experienced developers.
|
|
18
|
+
|
|
19
|
+
## CORE DIRECTIVE
|
|
20
|
+
|
|
21
|
+
YOU MUST follow the Parallax Engine protocol for EVERY task in order. The plugin tracks compliance and will block writes if critical steps are skipped.
|
|
22
|
+
|
|
23
|
+
## MANDATORY PROTOCOL -- Follow in order for EVERY task
|
|
24
|
+
|
|
25
|
+
### STEP 1: AMBIGUITY CHECK [REQUIRED - FIRST THING]
|
|
26
|
+
Output your ambiguity assessment BEFORE anything else:
|
|
27
|
+
- HIGH (vague/conceptual): User MUST ask 3+ clarifying questions. Do NOT proceed until ambiguity resolved.
|
|
28
|
+
- MEDIUM (some gaps): Ask targeted questions. If you must assume an unstated pattern, it's MEDIUM.
|
|
29
|
+
- LOW (clear/specific): Verify quickly and proceed. Trivial changes skip to Step 4.
|
|
30
|
+
|
|
31
|
+
CONSEQUENCE: Plugin will block writes if this step is skipped.
|
|
32
|
+
|
|
33
|
+
### STEP 2: 4 INVARIANTS [REQUIRED - BEFORE ANY CODE]
|
|
34
|
+
State each answer explicitly:
|
|
35
|
+
| Question | Your answer |
|
|
36
|
+
|---|---|
|
|
37
|
+
| Where does state live? | ownership & truth |
|
|
38
|
+
| Where does feedback live? | observability |
|
|
39
|
+
| What breaks if I delete this? | coupling & fragility |
|
|
40
|
+
| When does timing matter? | async & correctness |
|
|
41
|
+
|
|
42
|
+
### STEP 3: VERIFICATION GATE [REQUIRED - BEFORE FIRST WRITE]
|
|
43
|
+
Check every box. Flag any "no" as a risk:
|
|
44
|
+
- [ ] State ownership and consistency clear?
|
|
45
|
+
- [ ] Feedback / observability in place?
|
|
46
|
+
- [ ] Blast radius understood?
|
|
47
|
+
- [ ] Timing & ordering safe?
|
|
48
|
+
- [ ] Follows existing patterns (or intentionally breaks them)?
|
|
49
|
+
- [ ] Security / obvious risks addressed?
|
|
50
|
+
|
|
51
|
+
### STEP 4: EXECUTE
|
|
52
|
+
Write code. Use parallax_verify after writes. Fix failures. Do NOT work around the plugin.
|
|
53
|
+
|
|
54
|
+
### STEP 5: COMMIT DECISION [REQUIRED]
|
|
55
|
+
State one:
|
|
56
|
+
- Full Coherence -- Ship complete solution
|
|
57
|
+
- Pragmatic Partial -- Ship core + flag deferred items
|
|
58
|
+
- Hold + Clarify -- Critical gaps remain
|
|
59
|
+
- User Override -- "Ship it" = proceed with risks flagged
|
|
60
|
+
|
|
61
|
+
### STEP 6: SUMMARIZE [REQUIRED]
|
|
62
|
+
After finishing, output:
|
|
63
|
+
- What was built
|
|
64
|
+
- Edge cases handled
|
|
65
|
+
- Verification passed?
|
|
66
|
+
- Remaining concerns
|
|
67
|
+
|
|
68
|
+
## MODES
|
|
69
|
+
|
|
70
|
+
Use these tools to load specialized skills for each phase:
|
|
71
|
+
|
|
72
|
+
| Mode | Tool | Phase | Loads |
|
|
73
|
+
|---|---|---|---|
|
|
74
|
+
| PLAN | parallax_plan | Steps 1-3 | Precision Architect |
|
|
75
|
+
| BUILD | parallax_build | Step 4 | Standard protocol (default) |
|
|
76
|
+
| DEBUG | parallax_debug | Step 6 | Universal Auditor |
|
|
77
|
+
|
|
78
|
+
## TOOLS
|
|
79
|
+
|
|
80
|
+
- parallax_verify -- Run project verification (use instead of bash)
|
|
81
|
+
- parallax_analyze -- Structured multi-perspective analysis
|
|
82
|
+
- parallax_plan -- Switch to PLAN mode
|
|
83
|
+
- parallax_build -- Switch to BUILD mode
|
|
84
|
+
- parallax_debug -- Switch to DEBUG mode
|
|
85
|
+
- parallax_checkin -- Mark a protocol step complete (plugin tracks this)
|
|
86
|
+
- parallax_trace_export -- Export session trace to JSON file (includes coherence score)
|
|
87
|
+
|
|
88
|
+
## RED LINES (Stop Immediately)
|
|
89
|
+
|
|
90
|
+
- Unclear state ownership
|
|
91
|
+
- Unknown blast radius
|
|
92
|
+
- Timing / race condition hazards
|
|
93
|
+
- Security issues
|
|
94
|
+
- Creating significant complexity debt
|
|
95
|
+
- Unknown unknowns on non-trivial changes
|
|
96
|
+
|
|
97
|
+
## OUTPUT RULES
|
|
98
|
+
|
|
99
|
+
- Terminal environment. No markdown rendering. No emojis. Plain ASCII.
|
|
100
|
+
- ALL CAPS for emphasis, [brackets] for labels, indentation for structure.
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* PARALLAX ENGINE -- CLI Entry Point
|
|
4
|
+
*
|
|
5
|
+
* Provides the `parallax` CLI command for trace management, scoring,
|
|
6
|
+
* and project initialization.
|
|
7
|
+
*
|
|
8
|
+
* Commands:
|
|
9
|
+
* parallax init - Create .parallax/ config directory
|
|
10
|
+
* parallax trace list - List all traces
|
|
11
|
+
* parallax trace show <id> - Show a trace
|
|
12
|
+
* parallax trace score <id> - Show coherence score breakdown
|
|
13
|
+
* parallax trace export <id> - Export trace to JSON
|
|
14
|
+
* parallax trace trend - Show score trend
|
|
15
|
+
*
|
|
16
|
+
* License: MIT
|
|
17
|
+
* Copyright (c) 2026 Master0fFate
|
|
18
|
+
*/
|
|
19
|
+
export declare function main(): Promise<number>;
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* PARALLAX ENGINE -- CLI Entry Point
|
|
4
|
+
*
|
|
5
|
+
* Provides the `parallax` CLI command for trace management, scoring,
|
|
6
|
+
* and project initialization.
|
|
7
|
+
*
|
|
8
|
+
* Commands:
|
|
9
|
+
* parallax init - Create .parallax/ config directory
|
|
10
|
+
* parallax trace list - List all traces
|
|
11
|
+
* parallax trace show <id> - Show a trace
|
|
12
|
+
* parallax trace score <id> - Show coherence score breakdown
|
|
13
|
+
* parallax trace export <id> - Export trace to JSON
|
|
14
|
+
* parallax trace trend - Show score trend
|
|
15
|
+
*
|
|
16
|
+
* License: MIT
|
|
17
|
+
* Copyright (c) 2026 Master0fFate
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
20
|
+
import { join } from "path";
|
|
21
|
+
import { listTraceFiles, loadTrace, exportTrace, } from "./trace";
|
|
22
|
+
import { computeCoherenceScore, formatScoreBreakdown, readScoreHistory, sparkline, scoreToGrade, recordScore, } from "./score";
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Constants
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
const PARALLAX_DIR = ".parallax";
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Help & version
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
function showHelp() {
|
|
31
|
+
console.log(`Parallax Engine CLI v0.2.0`);
|
|
32
|
+
console.log(``);
|
|
33
|
+
console.log(`Usage: parallax <command> [options]`);
|
|
34
|
+
console.log(``);
|
|
35
|
+
console.log(`Commands:`);
|
|
36
|
+
console.log(` init Create .parallax/ directory with defaults`);
|
|
37
|
+
console.log(` trace list List all traces`);
|
|
38
|
+
console.log(` trace show <id> Show full trace`);
|
|
39
|
+
console.log(` trace score <id> Show coherence score`);
|
|
40
|
+
console.log(` trace export <id> Export trace to JSON file`);
|
|
41
|
+
console.log(` trace trend Show score trend over time`);
|
|
42
|
+
console.log(` help Show this help`);
|
|
43
|
+
}
|
|
44
|
+
function showVersion() {
|
|
45
|
+
console.log("0.2.0");
|
|
46
|
+
}
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// Command implementations
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
async function cmdInit() {
|
|
51
|
+
const dir = join(process.cwd(), PARALLAX_DIR);
|
|
52
|
+
if (!existsSync(dir)) {
|
|
53
|
+
mkdirSync(dir, { recursive: true });
|
|
54
|
+
console.log(`Created ${PARALLAX_DIR}/`);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
console.log(`${PARALLAX_DIR}/ already exists`);
|
|
58
|
+
}
|
|
59
|
+
const gitignorePath = join(dir, ".gitignore");
|
|
60
|
+
if (!existsSync(gitignorePath)) {
|
|
61
|
+
writeFileSync(gitignorePath, "*\n", "utf8");
|
|
62
|
+
console.log(`Created ${PARALLAX_DIR}/.gitignore`);
|
|
63
|
+
}
|
|
64
|
+
// Create traces subdirectory
|
|
65
|
+
const tracesDir = join(dir, "traces");
|
|
66
|
+
if (!existsSync(tracesDir)) {
|
|
67
|
+
mkdirSync(tracesDir, { recursive: true });
|
|
68
|
+
console.log(`Created ${PARALLAX_DIR}/traces/`);
|
|
69
|
+
}
|
|
70
|
+
console.log(`\nParallax initialized. Traces will be stored in ${PARALLAX_DIR}/traces/`);
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
73
|
+
async function cmdTraceList() {
|
|
74
|
+
const files = listTraceFiles();
|
|
75
|
+
if (files.length === 0) {
|
|
76
|
+
console.log("No traces found.");
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
79
|
+
console.log(`Found ${files.length} trace(s):\n`);
|
|
80
|
+
for (const f of files) {
|
|
81
|
+
const trace = loadTrace(f.sessionId);
|
|
82
|
+
const score = trace ? computeCoherenceScore(trace) : null;
|
|
83
|
+
const phases = trace ? trace.phases.length : 0;
|
|
84
|
+
const writes = trace ? trace.writes.length : 0;
|
|
85
|
+
const scoreStr = score ? `${score.total}/100 (${scoreToGrade(score.total)})` : "N/A";
|
|
86
|
+
console.log(` ${f.sessionId.padEnd(20)} ` +
|
|
87
|
+
`${writes} writes, ${phases} phases ` +
|
|
88
|
+
`Score: ${scoreStr}`);
|
|
89
|
+
}
|
|
90
|
+
return 0;
|
|
91
|
+
}
|
|
92
|
+
async function cmdTraceShow(id) {
|
|
93
|
+
const trace = loadTrace(id);
|
|
94
|
+
if (!trace) {
|
|
95
|
+
console.error(`Trace not found: ${id}`);
|
|
96
|
+
return 1;
|
|
97
|
+
}
|
|
98
|
+
console.log(`Session: ${trace.session.id}`);
|
|
99
|
+
console.log(`Started: ${trace.session.startedAt}`);
|
|
100
|
+
console.log(`Ended: ${trace.session.endedAt || "in progress"}`);
|
|
101
|
+
console.log(`Project: ${trace.session.project || "unknown"}`);
|
|
102
|
+
console.log(`Type: ${trace.session.projectType || "unknown"}`);
|
|
103
|
+
console.log(``);
|
|
104
|
+
console.log(`Phases (${trace.phases.length}):`);
|
|
105
|
+
for (const p of trace.phases) {
|
|
106
|
+
console.log(` [${p.phase}] ${p.timestamp}`);
|
|
107
|
+
if (Object.keys(p.data).length > 0) {
|
|
108
|
+
console.log(` Data: ${JSON.stringify(p.data)}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
console.log(``);
|
|
112
|
+
console.log(`Writes (${trace.writes.length}):`);
|
|
113
|
+
for (const w of trace.writes) {
|
|
114
|
+
const status = w.verification === "pass" ? "OK" : w.verification === "fail" ? "FAIL" : w.verification;
|
|
115
|
+
console.log(` [${status}] ${w.file} (retries: ${3 - w.frictionRetriesLeft})`);
|
|
116
|
+
}
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
async function cmdTraceScore(id) {
|
|
120
|
+
const trace = loadTrace(id);
|
|
121
|
+
if (!trace) {
|
|
122
|
+
console.error(`Trace not found: ${id}`);
|
|
123
|
+
return 1;
|
|
124
|
+
}
|
|
125
|
+
const breakdown = computeCoherenceScore(trace);
|
|
126
|
+
console.log(formatScoreBreakdown(breakdown));
|
|
127
|
+
// Optionally record the score
|
|
128
|
+
const entry = {
|
|
129
|
+
sessionId: id,
|
|
130
|
+
date: new Date().toISOString(),
|
|
131
|
+
score: breakdown.total,
|
|
132
|
+
project: trace.session.project,
|
|
133
|
+
};
|
|
134
|
+
recordScore(entry);
|
|
135
|
+
return 0;
|
|
136
|
+
}
|
|
137
|
+
async function cmdTraceExport(id) {
|
|
138
|
+
const trace = loadTrace(id);
|
|
139
|
+
if (!trace) {
|
|
140
|
+
console.error(`Trace not found: ${id}`);
|
|
141
|
+
return 1;
|
|
142
|
+
}
|
|
143
|
+
const filePath = exportTrace(id, true);
|
|
144
|
+
console.log(`Trace exported to: ${filePath}`);
|
|
145
|
+
return 0;
|
|
146
|
+
}
|
|
147
|
+
async function cmdTraceTrend() {
|
|
148
|
+
const history = readScoreHistory();
|
|
149
|
+
if (history.length === 0) {
|
|
150
|
+
console.log("No score history found.");
|
|
151
|
+
return 0;
|
|
152
|
+
}
|
|
153
|
+
const scores = history.map((e) => e.score);
|
|
154
|
+
const line = sparkline(scores);
|
|
155
|
+
const avg = Math.round(scores.reduce((a, b) => a + b, 0) / scores.length);
|
|
156
|
+
console.log(`Score trend (${history.length} entries, avg: ${avg}/100):`);
|
|
157
|
+
console.log(` ${line}`);
|
|
158
|
+
console.log(``);
|
|
159
|
+
for (const entry of history) {
|
|
160
|
+
const date = entry.date.slice(0, 10);
|
|
161
|
+
console.log(` ${date} ${entry.score}/100 [${entry.sessionId.slice(0, 8)}] ${entry.project || ""}`);
|
|
162
|
+
}
|
|
163
|
+
return 0;
|
|
164
|
+
}
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
// Command routing
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
export async function main() {
|
|
169
|
+
const args = process.argv.slice(2);
|
|
170
|
+
if (args.length === 0) {
|
|
171
|
+
showHelp();
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
const cmd = args[0];
|
|
175
|
+
switch (cmd) {
|
|
176
|
+
case "help":
|
|
177
|
+
showHelp();
|
|
178
|
+
return 0;
|
|
179
|
+
case "version":
|
|
180
|
+
case "--version":
|
|
181
|
+
case "-v":
|
|
182
|
+
showVersion();
|
|
183
|
+
return 0;
|
|
184
|
+
case "init":
|
|
185
|
+
return cmdInit();
|
|
186
|
+
case "trace": {
|
|
187
|
+
const sub = args[1];
|
|
188
|
+
switch (sub) {
|
|
189
|
+
case "list":
|
|
190
|
+
return cmdTraceList();
|
|
191
|
+
case "show":
|
|
192
|
+
if (!args[2]) {
|
|
193
|
+
console.error("Usage: parallax trace show <session-id>");
|
|
194
|
+
return 1;
|
|
195
|
+
}
|
|
196
|
+
return cmdTraceShow(args[2]);
|
|
197
|
+
case "score":
|
|
198
|
+
if (!args[2]) {
|
|
199
|
+
console.error("Usage: parallax trace score <session-id>");
|
|
200
|
+
return 1;
|
|
201
|
+
}
|
|
202
|
+
return cmdTraceScore(args[2]);
|
|
203
|
+
case "export":
|
|
204
|
+
if (!args[2]) {
|
|
205
|
+
console.error("Usage: parallax trace export <session-id>");
|
|
206
|
+
return 1;
|
|
207
|
+
}
|
|
208
|
+
return cmdTraceExport(args[2]);
|
|
209
|
+
case "trend":
|
|
210
|
+
return cmdTraceTrend();
|
|
211
|
+
default:
|
|
212
|
+
console.error(`Unknown trace command: ${sub}`);
|
|
213
|
+
console.error("Usage: parallax trace <list|show|score|export|trend>");
|
|
214
|
+
return 1;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
default:
|
|
218
|
+
console.error(`Unknown command: ${cmd}`);
|
|
219
|
+
console.error("Run 'parallax help' for usage.");
|
|
220
|
+
return 1;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// Run the CLI if this is the entry point
|
|
224
|
+
// Detected by checking if process.argv[1] ends with cli.ts or cli.js
|
|
225
|
+
const isMain = process.argv[1]?.endsWith("cli.ts") ||
|
|
226
|
+
process.argv[1]?.endsWith("cli.js") ||
|
|
227
|
+
process.argv[1]?.endsWith("parallax-engine") ||
|
|
228
|
+
process.argv[1]?.endsWith("parallax-engine.js");
|
|
229
|
+
if (isMain) {
|
|
230
|
+
main()
|
|
231
|
+
.then((code) => process.exit(code))
|
|
232
|
+
.catch((err) => {
|
|
233
|
+
console.error(err);
|
|
234
|
+
process.exit(1);
|
|
235
|
+
});
|
|
236
|
+
}
|
package/dist/detect.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PARALLAX ENGINE -- Project Detection
|
|
3
|
+
*
|
|
4
|
+
* Detects the project type in the current working directory and returns
|
|
5
|
+
* the appropriate verification command.
|
|
6
|
+
*
|
|
7
|
+
* License: MIT
|
|
8
|
+
* Copyright (c) 2026 Master0fFate
|
|
9
|
+
*/
|
|
10
|
+
import type { ProjectType, VerifyResult } from "./types";
|
|
11
|
+
/**
|
|
12
|
+
* Detect the project type based on files present in the current directory.
|
|
13
|
+
*/
|
|
14
|
+
export declare function detectProject(): ProjectType;
|
|
15
|
+
/**
|
|
16
|
+
* Get the shell command string for verification based on project type.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getVerifyCommand(): string | null;
|
|
19
|
+
/**
|
|
20
|
+
* Run the verification command synchronously using Bun.spawnSync.
|
|
21
|
+
* Returns null if no known project type is detected.
|
|
22
|
+
*/
|
|
23
|
+
export declare function runVerify(): VerifyResult | null;
|
package/dist/detect.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PARALLAX ENGINE -- Project Detection
|
|
3
|
+
*
|
|
4
|
+
* Detects the project type in the current working directory and returns
|
|
5
|
+
* the appropriate verification command.
|
|
6
|
+
*
|
|
7
|
+
* License: MIT
|
|
8
|
+
* Copyright (c) 2026 Master0fFate
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, statSync } from "fs";
|
|
11
|
+
/**
|
|
12
|
+
* Detect the project type based on files present in the current directory.
|
|
13
|
+
*/
|
|
14
|
+
export function detectProject() {
|
|
15
|
+
try {
|
|
16
|
+
if (existsSync("Cargo.toml"))
|
|
17
|
+
return "cargo";
|
|
18
|
+
if (existsSync("package.json")) {
|
|
19
|
+
if (existsSync("node_modules") && statSync("node_modules").isDirectory()) {
|
|
20
|
+
if (existsSync("tsconfig.json"))
|
|
21
|
+
return "tsc";
|
|
22
|
+
return "lint";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (existsSync("pyproject.toml") || existsSync("requirements.txt"))
|
|
26
|
+
return "python";
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get the shell command string for verification based on project type.
|
|
35
|
+
*/
|
|
36
|
+
export function getVerifyCommand() {
|
|
37
|
+
switch (detectProject()) {
|
|
38
|
+
case "cargo": return "cargo check --color=never --all-targets --all-features 2>&1";
|
|
39
|
+
case "tsc": return "npx tsc --noEmit 2>&1";
|
|
40
|
+
case "lint": return "npm run lint 2>&1";
|
|
41
|
+
case "python": return "python -m compileall -q . 2>&1";
|
|
42
|
+
default: return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Run the verification command synchronously using Bun.spawnSync.
|
|
47
|
+
* Returns null if no known project type is detected.
|
|
48
|
+
*/
|
|
49
|
+
export function runVerify() {
|
|
50
|
+
try {
|
|
51
|
+
const cmd = getVerifyCommand();
|
|
52
|
+
if (!cmd)
|
|
53
|
+
return null;
|
|
54
|
+
const shell = process.platform === "win32" ? "cmd" : "sh";
|
|
55
|
+
const flag = process.platform === "win32" ? "/C" : "-c";
|
|
56
|
+
const proc = Bun.spawnSync([shell, flag, cmd], { cwd: process.cwd() });
|
|
57
|
+
const stdout = proc.stdout.toString();
|
|
58
|
+
const stderr = proc.stderr.toString();
|
|
59
|
+
const combined = stderr ? `${stdout}\n${stderr}` : stdout;
|
|
60
|
+
return { exitCode: proc.exitCode, stdout, stderr, combined };
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
return { exitCode: -1, stdout: "", stderr: String(e), combined: String(e) };
|
|
64
|
+
}
|
|
65
|
+
}
|