ralph-research 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +127 -99
- package/dist/adapters/fs/json-file-research-project-defaults-store.d.ts +8 -0
- package/dist/adapters/fs/json-file-research-project-defaults-store.js +30 -0
- package/dist/adapters/fs/json-file-research-project-defaults-store.js.map +1 -0
- package/dist/adapters/fs/json-file-research-session-repository.d.ts +24 -0
- package/dist/adapters/fs/json-file-research-session-repository.js +199 -0
- package/dist/adapters/fs/json-file-research-session-repository.js.map +1 -0
- package/dist/adapters/fs/lockfile.d.ts +7 -0
- package/dist/adapters/fs/lockfile.js +16 -6
- package/dist/adapters/fs/lockfile.js.map +1 -1
- package/dist/adapters/fs/manifest-loader.js +8 -1
- package/dist/adapters/fs/manifest-loader.js.map +1 -1
- package/dist/adapters/proposer/codex-cli-proposer.d.ts +16 -0
- package/dist/adapters/proposer/codex-cli-proposer.js +106 -0
- package/dist/adapters/proposer/codex-cli-proposer.js.map +1 -0
- package/dist/adapters/proposer/codex-cli-session-driver.d.ts +64 -0
- package/dist/adapters/proposer/codex-cli-session-driver.js +182 -0
- package/dist/adapters/proposer/codex-cli-session-driver.js.map +1 -0
- package/dist/adapters/proposer/codex-cli-session-manager.d.ts +79 -0
- package/dist/adapters/proposer/codex-cli-session-manager.js +248 -0
- package/dist/adapters/proposer/codex-cli-session-manager.js.map +1 -0
- package/dist/adapters/proposer/codex-cli-session-outcome-extractor.d.ts +3 -0
- package/dist/adapters/proposer/codex-cli-session-outcome-extractor.js +94 -0
- package/dist/adapters/proposer/codex-cli-session-outcome-extractor.js.map +1 -0
- package/dist/adapters/proposer/proposer-factory.d.ts +22 -0
- package/dist/adapters/proposer/proposer-factory.js +19 -0
- package/dist/adapters/proposer/proposer-factory.js.map +1 -0
- package/dist/app/services/codex-cli-session-lifecycle-service.d.ts +116 -0
- package/dist/app/services/codex-cli-session-lifecycle-service.js +186 -0
- package/dist/app/services/codex-cli-session-lifecycle-service.js.map +1 -0
- package/dist/app/services/project-state-service.d.ts +17 -1
- package/dist/app/services/project-state-service.js +108 -5
- package/dist/app/services/project-state-service.js.map +1 -1
- package/dist/app/services/research-project-defaults-service.d.ts +18 -0
- package/dist/app/services/research-project-defaults-service.js +175 -0
- package/dist/app/services/research-project-defaults-service.js.map +1 -0
- package/dist/app/services/research-session-draft-service.d.ts +121 -0
- package/dist/app/services/research-session-draft-service.js +846 -0
- package/dist/app/services/research-session-draft-service.js.map +1 -0
- package/dist/app/services/research-session-entry-flow-summary-mapper.d.ts +12 -0
- package/dist/app/services/research-session-entry-flow-summary-mapper.js +33 -0
- package/dist/app/services/research-session-entry-flow-summary-mapper.js.map +1 -0
- package/dist/app/services/research-session-interactive-service.d.ts +35 -0
- package/dist/app/services/research-session-interactive-service.js +295 -0
- package/dist/app/services/research-session-interactive-service.js.map +1 -0
- package/dist/app/services/research-session-launch-service.d.ts +46 -0
- package/dist/app/services/research-session-launch-service.js +389 -0
- package/dist/app/services/research-session-launch-service.js.map +1 -0
- package/dist/app/services/research-session-orchestrator-service.d.ts +140 -0
- package/dist/app/services/research-session-orchestrator-service.js +614 -0
- package/dist/app/services/research-session-orchestrator-service.js.map +1 -0
- package/dist/app/services/research-session-recovery-service.d.ts +30 -0
- package/dist/app/services/research-session-recovery-service.js +110 -0
- package/dist/app/services/research-session-recovery-service.js.map +1 -0
- package/dist/app/services/research-session-wizard-controller.d.ts +51 -0
- package/dist/app/services/research-session-wizard-controller.js +220 -0
- package/dist/app/services/research-session-wizard-controller.js.map +1 -0
- package/dist/app/services/run-cycle-service.d.ts +2 -0
- package/dist/app/services/run-cycle-service.js +2 -0
- package/dist/app/services/run-cycle-service.js.map +1 -1
- package/dist/cli/commands/inspect.js +2 -0
- package/dist/cli/commands/inspect.js.map +1 -1
- package/dist/cli/commands/launch.d.ts +16 -0
- package/dist/cli/commands/launch.js +68 -0
- package/dist/cli/commands/launch.js.map +1 -0
- package/dist/cli/commands/proposer-display.d.ts +2 -0
- package/dist/cli/commands/proposer-display.js +18 -0
- package/dist/cli/commands/proposer-display.js.map +1 -0
- package/dist/cli/commands/resume.d.ts +14 -0
- package/dist/cli/commands/resume.js +134 -0
- package/dist/cli/commands/resume.js.map +1 -0
- package/dist/cli/commands/run.d.ts +1 -1
- package/dist/cli/commands/run.js +2 -2
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/status.js +38 -4
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/main.js +2 -29
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/program.d.ts +15 -0
- package/dist/cli/program.js +54 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/cli/tui/research-session-shell.d.ts +22 -0
- package/dist/cli/tui/research-session-shell.js +719 -0
- package/dist/cli/tui/research-session-shell.js.map +1 -0
- package/dist/core/engine/cycle-runner.d.ts +4 -0
- package/dist/core/engine/cycle-runner.js +17 -9
- package/dist/core/engine/cycle-runner.js.map +1 -1
- package/dist/core/manifest/admission.d.ts +1 -0
- package/dist/core/manifest/admission.js +50 -0
- package/dist/core/manifest/admission.js.map +1 -1
- package/dist/core/manifest/defaults.d.ts +21 -0
- package/dist/core/manifest/defaults.js +21 -0
- package/dist/core/manifest/defaults.js.map +1 -1
- package/dist/core/manifest/schema.d.ts +170 -0
- package/dist/core/manifest/schema.js +21 -1
- package/dist/core/manifest/schema.js.map +1 -1
- package/dist/core/model/codex-cli-cycle-session.d.ts +4 -0
- package/dist/core/model/codex-cli-cycle-session.js +2 -0
- package/dist/core/model/codex-cli-cycle-session.js.map +1 -0
- package/dist/core/model/codex-cli-session-lifecycle.d.ts +131 -0
- package/dist/core/model/codex-cli-session-lifecycle.js +237 -0
- package/dist/core/model/codex-cli-session-lifecycle.js.map +1 -0
- package/dist/core/model/codex-cli-session-outcome.d.ts +121 -0
- package/dist/core/model/codex-cli-session-outcome.js +70 -0
- package/dist/core/model/codex-cli-session-outcome.js.map +1 -0
- package/dist/core/model/research-project-defaults.d.ts +48 -0
- package/dist/core/model/research-project-defaults.js +46 -0
- package/dist/core/model/research-project-defaults.js.map +1 -0
- package/dist/core/model/research-session.d.ts +1143 -0
- package/dist/core/model/research-session.js +689 -0
- package/dist/core/model/research-session.js.map +1 -0
- package/dist/core/model/run-record.d.ts +58 -6
- package/dist/core/model/run-record.js +30 -0
- package/dist/core/model/run-record.js.map +1 -1
- package/dist/core/ports/research-project-defaults-store.d.ts +5 -0
- package/dist/core/ports/research-project-defaults-store.js +2 -0
- package/dist/core/ports/research-project-defaults-store.js.map +1 -0
- package/dist/core/ports/research-session-repository.d.ts +25 -0
- package/dist/core/ports/research-session-repository.js +2 -0
- package/dist/core/ports/research-session-repository.js.map +1 -0
- package/dist/core/state/research-session-recovery-classifier.d.ts +24 -0
- package/dist/core/state/research-session-recovery-classifier.js +236 -0
- package/dist/core/state/research-session-recovery-classifier.js.map +1 -0
- package/dist/core/state/research-session-resume-candidate.d.ts +8 -0
- package/dist/core/state/research-session-resume-candidate.js +62 -0
- package/dist/core/state/research-session-resume-candidate.js.map +1 -0
- package/dist/core/state/research-session-state-machine.d.ts +62 -0
- package/dist/core/state/research-session-state-machine.js +443 -0
- package/dist/core/state/research-session-state-machine.js.map +1 -0
- package/dist/core/state/run-state-machine.js +15 -1
- package/dist/core/state/run-state-machine.js.map +1 -1
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.js +192 -1
- package/dist/mcp/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,45 +1,112 @@
|
|
|
1
1
|
# ralph-research
|
|
2
2
|
|
|
3
|
-
Local-first runtime for recursive research improvement.
|
|
3
|
+
Local-first runtime for recursive research improvement over real artifacts.
|
|
4
4
|
|
|
5
|
-
`ralph-research`
|
|
5
|
+
`ralph-research` ships an actual CLI and stdio MCP server that run a bounded loop:
|
|
6
6
|
|
|
7
|
-
1.
|
|
7
|
+
1. load a manifest
|
|
8
8
|
2. generate one candidate change
|
|
9
|
-
3. evaluate it
|
|
10
|
-
4.
|
|
9
|
+
3. evaluate it with trusted signals
|
|
10
|
+
4. persist the run, decision, and frontier state
|
|
11
|
+
5. promote only verified improvements
|
|
11
12
|
|
|
12
|
-
The
|
|
13
|
+
The current product bar is reliability, not breadth. The bundled success path is the `writing` template, while the runtime itself is manifest-driven and reusable for other local workflows.
|
|
13
14
|
|
|
14
|
-
##
|
|
15
|
+
## Trust Signals
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
- Actual shipped surfaces: CLI binary `rrx` and stdio MCP server
|
|
18
|
+
- Development verification commands: `npm test`, `npm run typecheck`, `npm run build`
|
|
19
|
+
- Persisted runtime evidence: runs, decisions, frontier, and lock metadata
|
|
20
|
+
- Recovery semantics are enforced by code and persisted state, not described only in prompts
|
|
21
|
+
- Supported onboarding path is intentionally narrower than the full manifest surface
|
|
22
|
+
|
|
23
|
+
## What It Is
|
|
24
|
+
|
|
25
|
+
- A Node/TypeScript runtime with a real CLI: `rrx`
|
|
26
|
+
- A stdio MCP server backed by the same service layer as the CLI
|
|
27
|
+
- A Git-aware candidate execution loop with persisted run, decision, and frontier state
|
|
28
|
+
- A local-first system designed to be resumed, inspected, and trusted after interruptions
|
|
29
|
+
|
|
30
|
+
## What It Is Not
|
|
31
|
+
|
|
32
|
+
- Not a no-config autonomous agent for arbitrary domains out of the box
|
|
33
|
+
- Not a hosted service
|
|
34
|
+
- Not a prompt-only protocol with undocumented runtime behavior
|
|
35
|
+
- Not broader than the shipped contract: one bundled template (`writing`) and three MCP tools
|
|
36
|
+
|
|
37
|
+
## Quick Decision Guide
|
|
38
|
+
|
|
39
|
+
| If you want to... | Use |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| Check whether a repo is runnable | `rrx validate` then `rrx doctor` |
|
|
42
|
+
| Materialize the bundled example project | `rrx init --template writing` |
|
|
43
|
+
| Run a disposable end-to-end demo | `rrx demo writing` |
|
|
44
|
+
| Launch the v1 goal-driven orchestrator | `rrx "improve the holdout top-3 model"` |
|
|
45
|
+
| Launch the v1 goal-driven orchestrator explicitly | `rrx launch "improve the holdout top-3 model"` |
|
|
46
|
+
| Resume a persisted TUI research session | `rrx resume latest` |
|
|
47
|
+
| Execute one cycle | `rrx run --json` |
|
|
48
|
+
| Resume the latest recoverable run | `rrx run` |
|
|
49
|
+
| Force a fresh run id | `rrx run --fresh` |
|
|
50
|
+
| Inspect runtime and recovery state | `rrx status --json` |
|
|
51
|
+
| Inspect why one run was accepted or rejected | `rrx inspect <runId> --json` |
|
|
52
|
+
| Review the current accepted frontier | `rrx frontier --json` |
|
|
53
|
+
| Serve the same contract over MCP stdio | `rrx serve-mcp --stdio` |
|
|
54
|
+
|
|
55
|
+
## Five-Minute Start
|
|
56
|
+
|
|
57
|
+
### Option A: disposable demo
|
|
17
58
|
|
|
18
59
|
```bash
|
|
19
60
|
npx ralph-research demo writing
|
|
20
61
|
```
|
|
21
62
|
|
|
22
|
-
This creates a temporary
|
|
63
|
+
This creates a temporary Git repo, runs one accepted cycle, and prints the temp path plus the run id.
|
|
23
64
|
|
|
24
|
-
###
|
|
65
|
+
### Option B: initialize a local repo
|
|
25
66
|
|
|
26
67
|
```bash
|
|
27
68
|
npx ralph-research init --template writing
|
|
69
|
+
npx ralph-research doctor
|
|
28
70
|
npx ralph-research run --json
|
|
29
|
-
npx ralph-research
|
|
71
|
+
npx ralph-research status --json
|
|
30
72
|
npx ralph-research inspect run-0001 --json
|
|
31
73
|
```
|
|
32
74
|
|
|
33
|
-
This
|
|
75
|
+
This is the current truth contract for the bundled template: `init -> run -> inspect` should succeed quickly on a local machine.
|
|
34
76
|
|
|
35
|
-
|
|
77
|
+
`rrx "goal"` now creates or refreshes the launch draft session and drops into the v1 TUI shell. Initial launch does not start an autonomous research cycle until the shell tells it to continue.
|
|
78
|
+
|
|
79
|
+
When you submit the review step, the shell materializes a real research session and hands control to the selected agent runtime. Once that interactive run returns, `launch-draft` is removed. The remaining persisted session is the only runtime record you need to inspect or resume.
|
|
80
|
+
|
|
81
|
+
Resume semantics are intentionally narrow:
|
|
36
82
|
|
|
37
|
-
- `
|
|
38
|
-
-
|
|
39
|
-
- `
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
83
|
+
- `rrx resume <sessionId>` only works for sessions that ended after a completed cycle checkpoint
|
|
84
|
+
- interrupted sessions are resumable because the runtime has durable evidence for the next cycle boundary
|
|
85
|
+
- a clean agent exit without `goal_achieved` or a completed checkpoint is treated as terminal and is not resumable
|
|
86
|
+
|
|
87
|
+
## Runtime Model
|
|
88
|
+
|
|
89
|
+
The runtime is manifest-driven. `ralph.yaml` defines the project, proposer, experiment, metrics, ratchet, and storage root. The service layer then:
|
|
90
|
+
|
|
91
|
+
- loads and validates the manifest
|
|
92
|
+
- acquires a durable lock
|
|
93
|
+
- classifies recovery against the latest persisted run
|
|
94
|
+
- executes or resumes a candidate
|
|
95
|
+
- writes run, decision, and frontier state under the storage root
|
|
96
|
+
|
|
97
|
+
See [docs/operation-model.md](docs/operation-model.md) for the full lifecycle and recovery model.
|
|
98
|
+
|
|
99
|
+
## Current Scope
|
|
100
|
+
|
|
101
|
+
- Bundled template: `writing`
|
|
102
|
+
- Default template metric: local command metric, no API key required
|
|
103
|
+
- Optional judge path: pairwise LLM judge packs
|
|
104
|
+
- MCP tools:
|
|
105
|
+
- `run_research_cycle`
|
|
106
|
+
- `get_research_status`
|
|
107
|
+
- `get_frontier`
|
|
108
|
+
|
|
109
|
+
The runtime supports broader manifests than the bundled template demonstrates, but the shipped onboarding path is intentionally narrow until those flows are equally reliable.
|
|
43
110
|
|
|
44
111
|
## Writing Template
|
|
45
112
|
|
|
@@ -49,19 +116,51 @@ The bundled writing template is self-contained:
|
|
|
49
116
|
- `scripts/propose.mjs`: bounded rewrite
|
|
50
117
|
- `scripts/experiment.mjs`: output materialization
|
|
51
118
|
- `scripts/metric.mjs`: local heuristic metric
|
|
52
|
-
- `prompts/judge.md`: pairwise judge prompt
|
|
119
|
+
- `prompts/judge.md`: pairwise judge prompt starter
|
|
120
|
+
|
|
121
|
+
`templates/writing/ralph.yaml` uses a local command metric by default, so the first run works without model credentials.
|
|
122
|
+
|
|
123
|
+
## Progressive Runs
|
|
53
124
|
|
|
54
|
-
|
|
125
|
+
`rrx run` executes one cycle by default and auto-resumes the latest recoverable run when one exists.
|
|
126
|
+
|
|
127
|
+
Progressive stop modes are opt-in:
|
|
128
|
+
|
|
129
|
+
- `--fresh`: start a new `runId` instead of auto-resuming the latest recoverable run
|
|
130
|
+
- `--until-target`: keep iterating until `manifest.stopping.target` is met
|
|
131
|
+
- `--until-no-improve N`: stop after `N` consecutive cycles without frontier improvement
|
|
132
|
+
- `--cycles N` with a progressive flag: treat `N` as a max-cycle cap instead of an exact count
|
|
133
|
+
|
|
134
|
+
The bundled `writing` template ships with `stopping.target` commented out, so enable that block in `ralph.yaml` before using `--until-target`.
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
npx ralph-research run --until-target --until-no-improve 3 --json
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## More Docs
|
|
141
|
+
|
|
142
|
+
- [docs/operation-model.md](docs/operation-model.md): lifecycle, persisted state, recovery classes
|
|
143
|
+
- [docs/playbook.md](docs/playbook.md): situation-to-command operator guide
|
|
144
|
+
- [docs/examples.md](docs/examples.md): quickstart and manifest examples pulled from shipped templates and fixtures
|
|
145
|
+
- [docs/examples-catalog.md](docs/examples-catalog.md): broader scenario catalog grounded in shipped templates and test fixtures
|
|
146
|
+
- [docs/comparison.md](docs/comparison.md): why this runtime is narrower and more stateful than prompt-only loop systems
|
|
147
|
+
- [docs/faq.md](docs/faq.md): common runtime, recovery, and inspection questions
|
|
148
|
+
- [docs/knowledge/INDEX.md](docs/knowledge/INDEX.md): project knowledge log
|
|
55
149
|
|
|
56
150
|
## CLI
|
|
57
151
|
|
|
58
152
|
```text
|
|
153
|
+
rrx "improve the holdout top-3 model"
|
|
154
|
+
rrx launch "improve the holdout top-3 model"
|
|
155
|
+
rrx resume latest
|
|
59
156
|
rrx validate
|
|
60
157
|
rrx doctor
|
|
61
158
|
rrx init --template writing
|
|
62
159
|
rrx demo writing
|
|
63
160
|
rrx run
|
|
161
|
+
rrx run --fresh
|
|
64
162
|
rrx run --until-target
|
|
163
|
+
rrx run --until-no-improve 3
|
|
65
164
|
rrx run --until-target --until-no-improve 3
|
|
66
165
|
rrx status
|
|
67
166
|
rrx frontier
|
|
@@ -71,85 +170,14 @@ rrx reject <runId>
|
|
|
71
170
|
rrx serve-mcp --stdio
|
|
72
171
|
```
|
|
73
172
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
- `--until-target`: keep iterating until `manifest.stopping.target` is satisfied
|
|
77
|
-
- `--until-no-improve N`: stop after `N` consecutive cycles without a frontier improvement
|
|
78
|
-
- `--cycles N` with a progressive flag: treat `N` as a max-cycle cap instead of an exact count
|
|
79
|
-
|
|
80
|
-
## Stopping Targets
|
|
81
|
-
|
|
82
|
-
Use `stopping.target` when the workflow contract is "keep going until metric X reaches threshold Y":
|
|
83
|
-
|
|
84
|
-
```yaml
|
|
85
|
-
metrics:
|
|
86
|
-
catalog:
|
|
87
|
-
- id: exact_rate
|
|
88
|
-
kind: numeric
|
|
89
|
-
direction: maximize
|
|
90
|
-
extractor:
|
|
91
|
-
type: command
|
|
92
|
-
command: "python scripts/metric.py"
|
|
93
|
-
parser: plain_number
|
|
94
|
-
|
|
95
|
-
frontier:
|
|
96
|
-
strategy: single_best
|
|
97
|
-
primaryMetric: exact_rate
|
|
98
|
-
|
|
99
|
-
ratchet:
|
|
100
|
-
type: epsilon_improve
|
|
101
|
-
metric: exact_rate
|
|
102
|
-
epsilon: 0
|
|
103
|
-
|
|
104
|
-
stopping:
|
|
105
|
-
target:
|
|
106
|
-
metric: exact_rate
|
|
107
|
-
op: ">="
|
|
108
|
-
value: 0.8
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## Metric Diagnostics
|
|
112
|
-
|
|
113
|
-
If a metric script can explain why a candidate was zeroed or downgraded, prefer JSON output plus `parser: json_path` so the reason survives into `run`, `decision`, and `inspect` output:
|
|
114
|
-
|
|
115
|
-
```yaml
|
|
116
|
-
metrics:
|
|
117
|
-
catalog:
|
|
118
|
-
- id: exact_rate
|
|
119
|
-
kind: numeric
|
|
120
|
-
direction: maximize
|
|
121
|
-
extractor:
|
|
122
|
-
type: command
|
|
123
|
-
command: "python scripts/metric.py"
|
|
124
|
-
parser: json_path
|
|
125
|
-
valuePath: $.value
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
```json
|
|
129
|
-
{
|
|
130
|
-
"value": 0,
|
|
131
|
-
"metricId": "overfit_safe_exact_rate",
|
|
132
|
-
"reasons": ["all_missing_features", "normalized_order_leak"]
|
|
133
|
-
}
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
When `project.workspace=git`, rrx now warns if proposer, experiment, or metric command files are dirty in the working tree, because detached candidate worktrees only see committed baseline content.
|
|
137
|
-
|
|
138
|
-
## MCP
|
|
139
|
-
|
|
140
|
-
The bundled MCP server currently supports stdio transport and exposes three thin tools backed by the same service layer as the CLI:
|
|
141
|
-
|
|
142
|
-
- `run_research_cycle`
|
|
143
|
-
- `get_research_status`
|
|
144
|
-
- `get_frontier`
|
|
145
|
-
|
|
146
|
-
## Design Principles
|
|
173
|
+
## Core Concepts
|
|
147
174
|
|
|
148
|
-
-
|
|
149
|
-
-
|
|
150
|
-
-
|
|
151
|
-
-
|
|
152
|
-
-
|
|
175
|
+
- `Manifest`: `ralph.yaml` defines the research program
|
|
176
|
+
- `Metric`: how candidate quality is measured
|
|
177
|
+
- `Frontier`: the currently accepted best candidate set
|
|
178
|
+
- `Ratchet`: the acceptance policy that decides whether the frontier advances
|
|
179
|
+
- `Proposer`: how a bounded candidate change is generated
|
|
180
|
+
- `Judge`: how qualitative outputs are compared when numeric metrics are not enough
|
|
153
181
|
|
|
154
182
|
## Development
|
|
155
183
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ResearchProjectDefaultsRecord } from "../../core/model/research-project-defaults.js";
|
|
2
|
+
import type { ResearchProjectDefaultsStore } from "../../core/ports/research-project-defaults-store.js";
|
|
3
|
+
export declare class JsonFileResearchProjectDefaultsStore implements ResearchProjectDefaultsStore {
|
|
4
|
+
private readonly filePath;
|
|
5
|
+
constructor(filePath: string);
|
|
6
|
+
save(record: ResearchProjectDefaultsRecord): Promise<void>;
|
|
7
|
+
load(): Promise<ResearchProjectDefaultsRecord | null>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { researchProjectDefaultsRecordSchema, } from "../../core/model/research-project-defaults.js";
|
|
4
|
+
import { isMissingFileError } from "../../shared/fs-errors.js";
|
|
5
|
+
export class JsonFileResearchProjectDefaultsStore {
|
|
6
|
+
filePath;
|
|
7
|
+
constructor(filePath) {
|
|
8
|
+
this.filePath = resolve(filePath);
|
|
9
|
+
}
|
|
10
|
+
async save(record) {
|
|
11
|
+
const parsed = researchProjectDefaultsRecordSchema.parse(record);
|
|
12
|
+
const tempPath = `${this.filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
13
|
+
await mkdir(dirname(this.filePath), { recursive: true });
|
|
14
|
+
await writeFile(tempPath, `${JSON.stringify(parsed, null, 2)}\n`, "utf8");
|
|
15
|
+
await rename(tempPath, this.filePath);
|
|
16
|
+
}
|
|
17
|
+
async load() {
|
|
18
|
+
try {
|
|
19
|
+
const raw = await readFile(this.filePath, "utf8");
|
|
20
|
+
return researchProjectDefaultsRecordSchema.parse(JSON.parse(raw));
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (isMissingFileError(error)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=json-file-research-project-defaults-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-file-research-project-defaults-store.js","sourceRoot":"","sources":["../../../src/adapters/fs/json-file-research-project-defaults-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EACL,mCAAmC,GAEpC,MAAM,+CAA+C,CAAC;AAEvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,OAAO,oCAAoC;IAC9B,QAAQ,CAAS;IAElC,YAAmB,QAAgB;QACjC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAEM,KAAK,CAAC,IAAI,CAAC,MAAqC;QACrD,MAAM,MAAM,GAAG,mCAAmC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACjE,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,QAAQ,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QAErE,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,MAAM,SAAS,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC1E,MAAM,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAClD,OAAO,mCAAmC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ResearchSessionMetadata, type ResearchSessionRecord } from "../../core/model/research-session.js";
|
|
2
|
+
import type { PersistedResearchSessionBundle, ResearchSessionQuery, ResearchSessionRepository } from "../../core/ports/research-session-repository.js";
|
|
3
|
+
export declare class JsonFileResearchSessionRepository implements ResearchSessionRepository {
|
|
4
|
+
private readonly sessionsRoot;
|
|
5
|
+
constructor(sessionsRoot: string);
|
|
6
|
+
saveSession(record: ResearchSessionRecord): Promise<void>;
|
|
7
|
+
loadSession(sessionId: string): Promise<ResearchSessionRecord | null>;
|
|
8
|
+
deleteSession(sessionId: string): Promise<void>;
|
|
9
|
+
loadSessionMetadata(sessionId: string): Promise<ResearchSessionMetadata | null>;
|
|
10
|
+
loadPersistedSession(sessionId: string): Promise<PersistedResearchSessionBundle | null>;
|
|
11
|
+
querySessions(query?: ResearchSessionQuery): Promise<ResearchSessionRecord[]>;
|
|
12
|
+
querySessionMetadata(query?: ResearchSessionQuery): Promise<ResearchSessionMetadata[]>;
|
|
13
|
+
private loadAllSessions;
|
|
14
|
+
private loadAllSessionMetadata;
|
|
15
|
+
private listSessionDirectories;
|
|
16
|
+
private getPath;
|
|
17
|
+
private getLifecyclePath;
|
|
18
|
+
private getSessionsRoot;
|
|
19
|
+
private readSessionRecord;
|
|
20
|
+
private readSessionMetadata;
|
|
21
|
+
private readLifecycleRecord;
|
|
22
|
+
private assertDirectoryMatchesSession;
|
|
23
|
+
private assertLifecycleMatchesSession;
|
|
24
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { parseCodexCliSessionLifecycleRecord, } from "../../core/model/codex-cli-session-lifecycle.js";
|
|
4
|
+
import { parsePersistedResearchSessionMetadata, researchSessionRecordSchema, } from "../../core/model/research-session.js";
|
|
5
|
+
import { isMissingFileError } from "../../shared/fs-errors.js";
|
|
6
|
+
export class JsonFileResearchSessionRepository {
|
|
7
|
+
sessionsRoot;
|
|
8
|
+
constructor(sessionsRoot) {
|
|
9
|
+
this.sessionsRoot = resolve(sessionsRoot);
|
|
10
|
+
}
|
|
11
|
+
async saveSession(record) {
|
|
12
|
+
const parsed = researchSessionRecordSchema.parse(record);
|
|
13
|
+
const path = this.getPath(parsed.sessionId);
|
|
14
|
+
const tempPath = `${path}.tmp-${process.pid}-${Date.now()}`;
|
|
15
|
+
await mkdir(dirname(path), { recursive: true });
|
|
16
|
+
await writeFile(tempPath, `${JSON.stringify(parsed, null, 2)}\n`, "utf8");
|
|
17
|
+
await rename(tempPath, path);
|
|
18
|
+
}
|
|
19
|
+
async loadSession(sessionId) {
|
|
20
|
+
return this.readSessionRecord(sessionId);
|
|
21
|
+
}
|
|
22
|
+
async deleteSession(sessionId) {
|
|
23
|
+
const path = join(this.getSessionsRoot(), sessionId);
|
|
24
|
+
await rm(path, { recursive: true, force: true });
|
|
25
|
+
}
|
|
26
|
+
async loadSessionMetadata(sessionId) {
|
|
27
|
+
return this.readSessionMetadata(sessionId);
|
|
28
|
+
}
|
|
29
|
+
async loadPersistedSession(sessionId) {
|
|
30
|
+
const session = await this.readSessionRecord(sessionId);
|
|
31
|
+
if (!session) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const lifecyclePath = this.getLifecyclePath(sessionId);
|
|
35
|
+
const lifecycle = await this.readLifecycleRecord(sessionId);
|
|
36
|
+
return {
|
|
37
|
+
session,
|
|
38
|
+
lifecycle,
|
|
39
|
+
codexSessionReference: lifecycle
|
|
40
|
+
? {
|
|
41
|
+
codexSessionId: lifecycle.identity.codexSessionId,
|
|
42
|
+
lifecyclePath,
|
|
43
|
+
}
|
|
44
|
+
: null,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
async querySessions(query = {}) {
|
|
48
|
+
const records = await this.loadAllSessions();
|
|
49
|
+
const filtered = records.filter((record) => {
|
|
50
|
+
if (query.workingDirectory && record.workingDirectory !== query.workingDirectory) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
if (query.statuses && !query.statuses.includes(record.status)) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
});
|
|
58
|
+
if (query.limit === undefined) {
|
|
59
|
+
return filtered;
|
|
60
|
+
}
|
|
61
|
+
return filtered.slice(0, query.limit);
|
|
62
|
+
}
|
|
63
|
+
async querySessionMetadata(query = {}) {
|
|
64
|
+
const records = await this.loadAllSessionMetadata();
|
|
65
|
+
const filtered = records.filter((record) => {
|
|
66
|
+
if (query.workingDirectory && record.workingDirectory !== query.workingDirectory) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
if (query.statuses && !query.statuses.includes(record.status)) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
});
|
|
74
|
+
if (query.limit === undefined) {
|
|
75
|
+
return filtered;
|
|
76
|
+
}
|
|
77
|
+
return filtered.slice(0, query.limit);
|
|
78
|
+
}
|
|
79
|
+
async loadAllSessions() {
|
|
80
|
+
const directories = await this.listSessionDirectories();
|
|
81
|
+
const records = [];
|
|
82
|
+
for (const directoryName of directories) {
|
|
83
|
+
const record = await this.readSessionRecord(directoryName);
|
|
84
|
+
if (!record) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
this.assertDirectoryMatchesSession(record, directoryName);
|
|
88
|
+
records.push(record);
|
|
89
|
+
}
|
|
90
|
+
return records.sort((left, right) => left.sessionId.localeCompare(right.sessionId));
|
|
91
|
+
}
|
|
92
|
+
async loadAllSessionMetadata() {
|
|
93
|
+
const directories = await this.listSessionDirectories();
|
|
94
|
+
const records = [];
|
|
95
|
+
for (const directoryName of directories) {
|
|
96
|
+
const record = await this.readSessionMetadata(directoryName);
|
|
97
|
+
if (!record) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
this.assertDirectoryMatchesSession(record, directoryName);
|
|
101
|
+
records.push(record);
|
|
102
|
+
}
|
|
103
|
+
return records.sort((left, right) => left.sessionId.localeCompare(right.sessionId));
|
|
104
|
+
}
|
|
105
|
+
async listSessionDirectories() {
|
|
106
|
+
try {
|
|
107
|
+
const entries = await readdir(this.getSessionsRoot(), { withFileTypes: true });
|
|
108
|
+
const directories = [];
|
|
109
|
+
for (const entry of entries) {
|
|
110
|
+
if (!entry.isDirectory()) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const path = join(this.getSessionsRoot(), entry.name, "session.json");
|
|
114
|
+
const fileStats = await stat(path).catch((error) => {
|
|
115
|
+
if (isMissingFileError(error)) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
throw error;
|
|
119
|
+
});
|
|
120
|
+
if (!fileStats?.isFile()) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
directories.push(entry.name);
|
|
124
|
+
}
|
|
125
|
+
return directories.sort((left, right) => left.localeCompare(right));
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
if (isMissingFileError(error)) {
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
getPath(sessionId) {
|
|
135
|
+
return join(this.getSessionsRoot(), sessionId, "session.json");
|
|
136
|
+
}
|
|
137
|
+
getLifecyclePath(sessionId) {
|
|
138
|
+
return join(this.getSessionsRoot(), sessionId, "codex-session.json");
|
|
139
|
+
}
|
|
140
|
+
getSessionsRoot() {
|
|
141
|
+
return this.sessionsRoot;
|
|
142
|
+
}
|
|
143
|
+
async readSessionRecord(sessionId) {
|
|
144
|
+
const path = this.getPath(sessionId);
|
|
145
|
+
try {
|
|
146
|
+
const raw = await readFile(path, "utf8");
|
|
147
|
+
const record = researchSessionRecordSchema.parse(JSON.parse(raw));
|
|
148
|
+
this.assertDirectoryMatchesSession(record, sessionId);
|
|
149
|
+
return record;
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (isMissingFileError(error)) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async readSessionMetadata(sessionId) {
|
|
159
|
+
const path = this.getPath(sessionId);
|
|
160
|
+
try {
|
|
161
|
+
const raw = await readFile(path, "utf8");
|
|
162
|
+
const record = parsePersistedResearchSessionMetadata(JSON.parse(raw));
|
|
163
|
+
this.assertDirectoryMatchesSession(record, sessionId);
|
|
164
|
+
return record;
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
if (isMissingFileError(error)) {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async readLifecycleRecord(sessionId) {
|
|
174
|
+
const path = this.getLifecyclePath(sessionId);
|
|
175
|
+
try {
|
|
176
|
+
const raw = await readFile(path, "utf8");
|
|
177
|
+
const record = parseCodexCliSessionLifecycleRecord(raw);
|
|
178
|
+
this.assertLifecycleMatchesSession(record, sessionId);
|
|
179
|
+
return record;
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
if (isMissingFileError(error)) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
assertDirectoryMatchesSession(record, directoryName) {
|
|
189
|
+
if (record.sessionId !== directoryName) {
|
|
190
|
+
throw new Error(`Research session directory name "${directoryName}" must match record sessionId "${record.sessionId}"`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
assertLifecycleMatchesSession(record, directoryName) {
|
|
194
|
+
if (record.sessionId !== directoryName) {
|
|
195
|
+
throw new Error(`Research session directory name "${directoryName}" must match lifecycle sessionId "${record.sessionId}"`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=json-file-research-session-repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-file-research-session-repository.js","sourceRoot":"","sources":["../../../src/adapters/fs/json-file-research-session-repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,6 +21,12 @@ export interface LockHandle {
|
|
|
21
21
|
path: string;
|
|
22
22
|
metadata: LockfileMetadata;
|
|
23
23
|
}
|
|
24
|
+
export interface LockRuntimeState {
|
|
25
|
+
metadata: LockfileMetadata;
|
|
26
|
+
processAlive: boolean;
|
|
27
|
+
stale: boolean;
|
|
28
|
+
heartbeatAgeMs: number;
|
|
29
|
+
}
|
|
24
30
|
export declare class LockAcquisitionError extends Error {
|
|
25
31
|
readonly metadata: LockfileMetadata | undefined;
|
|
26
32
|
readonly heartbeatAgeMs: number | undefined;
|
|
@@ -33,5 +39,6 @@ export declare function acquireLock(path: string, options?: AcquireLockOptions):
|
|
|
33
39
|
export declare function renewLock(path: string, token: string): Promise<LockfileMetadata>;
|
|
34
40
|
export declare function releaseLock(path: string, token?: string): Promise<void>;
|
|
35
41
|
export declare function isStaleLock(path: string): Promise<boolean>;
|
|
42
|
+
export declare function inspectLock(path: string): Promise<LockRuntimeState | null>;
|
|
36
43
|
export declare function readLockMetadata(path: string): Promise<LockfileMetadata | null>;
|
|
37
44
|
export {};
|
|
@@ -107,15 +107,25 @@ export async function releaseLock(path, token) {
|
|
|
107
107
|
await rm(resolvedPath, { force: true });
|
|
108
108
|
}
|
|
109
109
|
export async function isStaleLock(path) {
|
|
110
|
-
const
|
|
111
|
-
if (!
|
|
110
|
+
const runtime = await inspectLock(path);
|
|
111
|
+
if (!runtime) {
|
|
112
112
|
return false;
|
|
113
113
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
return runtime.stale;
|
|
115
|
+
}
|
|
116
|
+
export async function inspectLock(path) {
|
|
117
|
+
const metadata = await readLockMetadata(path);
|
|
118
|
+
if (!metadata) {
|
|
119
|
+
return null;
|
|
117
120
|
}
|
|
118
|
-
|
|
121
|
+
const heartbeatAgeMs = Date.now() - Date.parse(metadata.updatedAt);
|
|
122
|
+
const processAlive = isProcessAlive(metadata.pid);
|
|
123
|
+
return {
|
|
124
|
+
metadata,
|
|
125
|
+
processAlive,
|
|
126
|
+
stale: heartbeatAgeMs > metadata.ttlMs + metadata.graceMs || !processAlive,
|
|
127
|
+
heartbeatAgeMs,
|
|
128
|
+
};
|
|
119
129
|
}
|
|
120
130
|
export async function readLockMetadata(path) {
|
|
121
131
|
const resolvedPath = resolve(path);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../../../src/adapters/fs/lockfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAC1C,MAAM,qBAAqB,GAAG,EAAE,GAAG,IAAI,CAAC;AAExC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACnC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACxC,CAAC,CAAC;AAEH,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAChC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAClC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,qBAAqB,CAAC;IACtE,KAAK,EAAE,eAAe,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../../../src/adapters/fs/lockfile.ts"],"names":[],"mappings":"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"}
|