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.
Files changed (135) hide show
  1. package/README.md +127 -99
  2. package/dist/adapters/fs/json-file-research-project-defaults-store.d.ts +8 -0
  3. package/dist/adapters/fs/json-file-research-project-defaults-store.js +30 -0
  4. package/dist/adapters/fs/json-file-research-project-defaults-store.js.map +1 -0
  5. package/dist/adapters/fs/json-file-research-session-repository.d.ts +24 -0
  6. package/dist/adapters/fs/json-file-research-session-repository.js +199 -0
  7. package/dist/adapters/fs/json-file-research-session-repository.js.map +1 -0
  8. package/dist/adapters/fs/lockfile.d.ts +7 -0
  9. package/dist/adapters/fs/lockfile.js +16 -6
  10. package/dist/adapters/fs/lockfile.js.map +1 -1
  11. package/dist/adapters/fs/manifest-loader.js +8 -1
  12. package/dist/adapters/fs/manifest-loader.js.map +1 -1
  13. package/dist/adapters/proposer/codex-cli-proposer.d.ts +16 -0
  14. package/dist/adapters/proposer/codex-cli-proposer.js +106 -0
  15. package/dist/adapters/proposer/codex-cli-proposer.js.map +1 -0
  16. package/dist/adapters/proposer/codex-cli-session-driver.d.ts +64 -0
  17. package/dist/adapters/proposer/codex-cli-session-driver.js +182 -0
  18. package/dist/adapters/proposer/codex-cli-session-driver.js.map +1 -0
  19. package/dist/adapters/proposer/codex-cli-session-manager.d.ts +79 -0
  20. package/dist/adapters/proposer/codex-cli-session-manager.js +248 -0
  21. package/dist/adapters/proposer/codex-cli-session-manager.js.map +1 -0
  22. package/dist/adapters/proposer/codex-cli-session-outcome-extractor.d.ts +3 -0
  23. package/dist/adapters/proposer/codex-cli-session-outcome-extractor.js +94 -0
  24. package/dist/adapters/proposer/codex-cli-session-outcome-extractor.js.map +1 -0
  25. package/dist/adapters/proposer/proposer-factory.d.ts +22 -0
  26. package/dist/adapters/proposer/proposer-factory.js +19 -0
  27. package/dist/adapters/proposer/proposer-factory.js.map +1 -0
  28. package/dist/app/services/codex-cli-session-lifecycle-service.d.ts +116 -0
  29. package/dist/app/services/codex-cli-session-lifecycle-service.js +186 -0
  30. package/dist/app/services/codex-cli-session-lifecycle-service.js.map +1 -0
  31. package/dist/app/services/project-state-service.d.ts +17 -1
  32. package/dist/app/services/project-state-service.js +108 -5
  33. package/dist/app/services/project-state-service.js.map +1 -1
  34. package/dist/app/services/research-project-defaults-service.d.ts +18 -0
  35. package/dist/app/services/research-project-defaults-service.js +175 -0
  36. package/dist/app/services/research-project-defaults-service.js.map +1 -0
  37. package/dist/app/services/research-session-draft-service.d.ts +121 -0
  38. package/dist/app/services/research-session-draft-service.js +846 -0
  39. package/dist/app/services/research-session-draft-service.js.map +1 -0
  40. package/dist/app/services/research-session-entry-flow-summary-mapper.d.ts +12 -0
  41. package/dist/app/services/research-session-entry-flow-summary-mapper.js +33 -0
  42. package/dist/app/services/research-session-entry-flow-summary-mapper.js.map +1 -0
  43. package/dist/app/services/research-session-interactive-service.d.ts +35 -0
  44. package/dist/app/services/research-session-interactive-service.js +295 -0
  45. package/dist/app/services/research-session-interactive-service.js.map +1 -0
  46. package/dist/app/services/research-session-launch-service.d.ts +46 -0
  47. package/dist/app/services/research-session-launch-service.js +389 -0
  48. package/dist/app/services/research-session-launch-service.js.map +1 -0
  49. package/dist/app/services/research-session-orchestrator-service.d.ts +140 -0
  50. package/dist/app/services/research-session-orchestrator-service.js +614 -0
  51. package/dist/app/services/research-session-orchestrator-service.js.map +1 -0
  52. package/dist/app/services/research-session-recovery-service.d.ts +30 -0
  53. package/dist/app/services/research-session-recovery-service.js +110 -0
  54. package/dist/app/services/research-session-recovery-service.js.map +1 -0
  55. package/dist/app/services/research-session-wizard-controller.d.ts +51 -0
  56. package/dist/app/services/research-session-wizard-controller.js +220 -0
  57. package/dist/app/services/research-session-wizard-controller.js.map +1 -0
  58. package/dist/app/services/run-cycle-service.d.ts +2 -0
  59. package/dist/app/services/run-cycle-service.js +2 -0
  60. package/dist/app/services/run-cycle-service.js.map +1 -1
  61. package/dist/cli/commands/inspect.js +2 -0
  62. package/dist/cli/commands/inspect.js.map +1 -1
  63. package/dist/cli/commands/launch.d.ts +16 -0
  64. package/dist/cli/commands/launch.js +68 -0
  65. package/dist/cli/commands/launch.js.map +1 -0
  66. package/dist/cli/commands/proposer-display.d.ts +2 -0
  67. package/dist/cli/commands/proposer-display.js +18 -0
  68. package/dist/cli/commands/proposer-display.js.map +1 -0
  69. package/dist/cli/commands/resume.d.ts +14 -0
  70. package/dist/cli/commands/resume.js +134 -0
  71. package/dist/cli/commands/resume.js.map +1 -0
  72. package/dist/cli/commands/run.d.ts +1 -1
  73. package/dist/cli/commands/run.js +2 -2
  74. package/dist/cli/commands/run.js.map +1 -1
  75. package/dist/cli/commands/status.js +38 -4
  76. package/dist/cli/commands/status.js.map +1 -1
  77. package/dist/cli/main.js +2 -29
  78. package/dist/cli/main.js.map +1 -1
  79. package/dist/cli/program.d.ts +15 -0
  80. package/dist/cli/program.js +54 -0
  81. package/dist/cli/program.js.map +1 -0
  82. package/dist/cli/tui/research-session-shell.d.ts +22 -0
  83. package/dist/cli/tui/research-session-shell.js +719 -0
  84. package/dist/cli/tui/research-session-shell.js.map +1 -0
  85. package/dist/core/engine/cycle-runner.d.ts +4 -0
  86. package/dist/core/engine/cycle-runner.js +17 -9
  87. package/dist/core/engine/cycle-runner.js.map +1 -1
  88. package/dist/core/manifest/admission.d.ts +1 -0
  89. package/dist/core/manifest/admission.js +50 -0
  90. package/dist/core/manifest/admission.js.map +1 -1
  91. package/dist/core/manifest/defaults.d.ts +21 -0
  92. package/dist/core/manifest/defaults.js +21 -0
  93. package/dist/core/manifest/defaults.js.map +1 -1
  94. package/dist/core/manifest/schema.d.ts +170 -0
  95. package/dist/core/manifest/schema.js +21 -1
  96. package/dist/core/manifest/schema.js.map +1 -1
  97. package/dist/core/model/codex-cli-cycle-session.d.ts +4 -0
  98. package/dist/core/model/codex-cli-cycle-session.js +2 -0
  99. package/dist/core/model/codex-cli-cycle-session.js.map +1 -0
  100. package/dist/core/model/codex-cli-session-lifecycle.d.ts +131 -0
  101. package/dist/core/model/codex-cli-session-lifecycle.js +237 -0
  102. package/dist/core/model/codex-cli-session-lifecycle.js.map +1 -0
  103. package/dist/core/model/codex-cli-session-outcome.d.ts +121 -0
  104. package/dist/core/model/codex-cli-session-outcome.js +70 -0
  105. package/dist/core/model/codex-cli-session-outcome.js.map +1 -0
  106. package/dist/core/model/research-project-defaults.d.ts +48 -0
  107. package/dist/core/model/research-project-defaults.js +46 -0
  108. package/dist/core/model/research-project-defaults.js.map +1 -0
  109. package/dist/core/model/research-session.d.ts +1143 -0
  110. package/dist/core/model/research-session.js +689 -0
  111. package/dist/core/model/research-session.js.map +1 -0
  112. package/dist/core/model/run-record.d.ts +58 -6
  113. package/dist/core/model/run-record.js +30 -0
  114. package/dist/core/model/run-record.js.map +1 -1
  115. package/dist/core/ports/research-project-defaults-store.d.ts +5 -0
  116. package/dist/core/ports/research-project-defaults-store.js +2 -0
  117. package/dist/core/ports/research-project-defaults-store.js.map +1 -0
  118. package/dist/core/ports/research-session-repository.d.ts +25 -0
  119. package/dist/core/ports/research-session-repository.js +2 -0
  120. package/dist/core/ports/research-session-repository.js.map +1 -0
  121. package/dist/core/state/research-session-recovery-classifier.d.ts +24 -0
  122. package/dist/core/state/research-session-recovery-classifier.js +236 -0
  123. package/dist/core/state/research-session-recovery-classifier.js.map +1 -0
  124. package/dist/core/state/research-session-resume-candidate.d.ts +8 -0
  125. package/dist/core/state/research-session-resume-candidate.js +62 -0
  126. package/dist/core/state/research-session-resume-candidate.js.map +1 -0
  127. package/dist/core/state/research-session-state-machine.d.ts +62 -0
  128. package/dist/core/state/research-session-state-machine.js +443 -0
  129. package/dist/core/state/research-session-state-machine.js.map +1 -0
  130. package/dist/core/state/run-state-machine.js +15 -1
  131. package/dist/core/state/run-state-machine.js.map +1 -1
  132. package/dist/mcp/server.d.ts +4 -0
  133. package/dist/mcp/server.js +192 -1
  134. package/dist/mcp/server.js.map +1 -1
  135. 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` runs a bounded improvement loop over a real artifact:
5
+ `ralph-research` ships an actual CLI and stdio MCP server that run a bounded loop:
6
6
 
7
- 1. define a metric
7
+ 1. load a manifest
8
8
  2. generate one candidate change
9
- 3. evaluate it
10
- 4. keep only verified improvements
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 v0.1 focus is a writing workflow that is runnable in under five minutes on a local machine.
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
- ## Quickstart
15
+ ## Trust Signals
15
16
 
16
- ### Zero-config demo
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 writing repo, runs one accepted cycle, and prints the path plus the run id. The v0.1 demo supports the bundled `writing` template only.
63
+ This creates a temporary Git repo, runs one accepted cycle, and prints the temp path plus the run id.
23
64
 
24
- ### Template flow
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 run --until-target --until-no-improve 3 --json
71
+ npx ralph-research status --json
30
72
  npx ralph-research inspect run-0001 --json
31
73
  ```
32
74
 
33
- This path is the v0.1 success bar: `init -> run -> inspect` should work quickly and produce an acceptance reason you can inspect. The bundled template set is currently `writing` only.
75
+ This is the current truth contract for the bundled template: `init -> run -> inspect` should succeed quickly on a local machine.
34
76
 
35
- ## Core Concepts
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
- - `Manifest`: `ralph.yaml` defines the research program.
38
- - `Metric`: how candidate quality is measured.
39
- - `Frontier`: the currently accepted best candidate set.
40
- - `Ratchet`: the acceptance policy that decides whether the frontier advances.
41
- - `Proposer`: how a bounded candidate change is generated.
42
- - `Judge`: how qualitative outputs are compared when numeric metrics are not enough.
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 you can upgrade to later
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
- The default template uses a local command metric so the first run does not require API keys. When you are ready, replace the numeric metric with an `llm_judge` extractor and use the included pairwise prompt as a starting point.
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
- `rrx run --cycles N` still executes a finite loop. Progressive modes are opt-in:
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
- - local-first execution
149
- - bounded changes
150
- - recoverable state transitions
151
- - trusted signal before automation
152
- - inspectable accept/reject decisions
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 metadata = await readLockMetadata(path);
111
- if (!metadata) {
110
+ const runtime = await inspectLock(path);
111
+ if (!runtime) {
112
112
  return false;
113
113
  }
114
- const ageMs = Date.now() - Date.parse(metadata.updatedAt);
115
- if (ageMs > metadata.ttlMs + metadata.graceMs) {
116
- return true;
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
- return !isProcessAlive(metadata.pid);
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":"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"}
1
+ {"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../../../src/adapters/fs/lockfile.ts"],"names":[],"mappings":"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"}