ralph-research 0.1.0 → 0.1.1

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 (90) hide show
  1. package/README.md +67 -0
  2. package/dist/adapters/extractor/command-extractor.js +46 -4
  3. package/dist/adapters/extractor/command-extractor.js.map +1 -1
  4. package/dist/adapters/fs/json-file-frontier-store.js +4 -2
  5. package/dist/adapters/fs/json-file-frontier-store.js.map +1 -1
  6. package/dist/adapters/fs/lockfile.d.ts +14 -1
  7. package/dist/adapters/fs/lockfile.js +50 -6
  8. package/dist/adapters/fs/lockfile.js.map +1 -1
  9. package/dist/adapters/fs/manifest-loader.d.ts +5 -1
  10. package/dist/adapters/fs/manifest-loader.js +15 -2
  11. package/dist/adapters/fs/manifest-loader.js.map +1 -1
  12. package/dist/adapters/git/git-client.d.ts +2 -0
  13. package/dist/adapters/git/git-client.js +19 -0
  14. package/dist/adapters/git/git-client.js.map +1 -1
  15. package/dist/app/services/manual-decision-service.js +76 -25
  16. package/dist/app/services/manual-decision-service.js.map +1 -1
  17. package/dist/app/services/project-state-service.d.ts +9 -0
  18. package/dist/app/services/project-state-service.js +69 -14
  19. package/dist/app/services/project-state-service.js.map +1 -1
  20. package/dist/app/services/run-admission-service.d.ts +20 -0
  21. package/dist/app/services/run-admission-service.js +30 -0
  22. package/dist/app/services/run-admission-service.js.map +1 -0
  23. package/dist/app/services/run-cycle-service.d.ts +5 -4
  24. package/dist/app/services/run-cycle-service.js +175 -14
  25. package/dist/app/services/run-cycle-service.js.map +1 -1
  26. package/dist/app/services/run-loop-service.d.ts +21 -0
  27. package/dist/app/services/run-loop-service.js +155 -0
  28. package/dist/app/services/run-loop-service.js.map +1 -0
  29. package/dist/cli/commands/demo.js +1 -0
  30. package/dist/cli/commands/demo.js.map +1 -1
  31. package/dist/cli/commands/doctor.d.ts +8 -0
  32. package/dist/cli/commands/doctor.js +59 -0
  33. package/dist/cli/commands/doctor.js.map +1 -0
  34. package/dist/cli/commands/init.js +1 -0
  35. package/dist/cli/commands/init.js.map +1 -1
  36. package/dist/cli/commands/inspect.js +4 -0
  37. package/dist/cli/commands/inspect.js.map +1 -1
  38. package/dist/cli/commands/run.d.ts +3 -1
  39. package/dist/cli/commands/run.js +31 -28
  40. package/dist/cli/commands/run.js.map +1 -1
  41. package/dist/cli/commands/status.js +1 -0
  42. package/dist/cli/commands/status.js.map +1 -1
  43. package/dist/cli/commands/validate.js +21 -18
  44. package/dist/cli/commands/validate.js.map +1 -1
  45. package/dist/cli/main.js +3 -10
  46. package/dist/cli/main.js.map +1 -1
  47. package/dist/core/engine/cycle-runner.d.ts +2 -0
  48. package/dist/core/engine/cycle-runner.js +502 -34
  49. package/dist/core/engine/cycle-runner.js.map +1 -1
  50. package/dist/core/engine/promotion-artifact.d.ts +23 -0
  51. package/dist/core/engine/promotion-artifact.js +58 -0
  52. package/dist/core/engine/promotion-artifact.js.map +1 -0
  53. package/dist/core/engine/workspace-manager.d.ts +10 -1
  54. package/dist/core/engine/workspace-manager.js +70 -3
  55. package/dist/core/engine/workspace-manager.js.map +1 -1
  56. package/dist/core/manifest/admission.d.ts +16 -0
  57. package/dist/core/manifest/admission.js +64 -0
  58. package/dist/core/manifest/admission.js.map +1 -0
  59. package/dist/core/manifest/schema.d.ts +47 -0
  60. package/dist/core/manifest/schema.js +18 -1
  61. package/dist/core/manifest/schema.js.map +1 -1
  62. package/dist/core/model/decision-record.d.ts +4 -0
  63. package/dist/core/model/decision-record.js +6 -0
  64. package/dist/core/model/decision-record.js.map +1 -1
  65. package/dist/core/model/metric-diagnostics.d.ts +7 -0
  66. package/dist/core/model/metric-diagnostics.js +51 -0
  67. package/dist/core/model/metric-diagnostics.js.map +1 -0
  68. package/dist/core/model/run-record.d.ts +4 -0
  69. package/dist/core/model/run-record.js +2 -0
  70. package/dist/core/model/run-record.js.map +1 -1
  71. package/dist/core/state/frontier-materializer.d.ts +12 -0
  72. package/dist/core/state/frontier-materializer.js +74 -0
  73. package/dist/core/state/frontier-materializer.js.map +1 -0
  74. package/dist/core/state/frontier-semantics.d.ts +12 -0
  75. package/dist/core/state/frontier-semantics.js +26 -0
  76. package/dist/core/state/frontier-semantics.js.map +1 -0
  77. package/dist/core/state/ratchet-engine.js +29 -21
  78. package/dist/core/state/ratchet-engine.js.map +1 -1
  79. package/dist/core/state/recovery-classifier.d.ts +17 -0
  80. package/dist/core/state/recovery-classifier.js +150 -0
  81. package/dist/core/state/recovery-classifier.js.map +1 -0
  82. package/dist/core/state/run-state-machine.js +18 -22
  83. package/dist/core/state/run-state-machine.js.map +1 -1
  84. package/dist/core/state/stopping-target.d.ts +14 -0
  85. package/dist/core/state/stopping-target.js +67 -0
  86. package/dist/core/state/stopping-target.js.map +1 -0
  87. package/dist/mcp/server.js +17 -23
  88. package/dist/mcp/server.js.map +1 -1
  89. package/package.json +2 -2
  90. package/templates/writing/ralph.yaml +7 -0
package/README.md CHANGED
@@ -26,6 +26,7 @@ This creates a temporary writing repo, runs one accepted cycle, and prints the p
26
26
  ```bash
27
27
  npx ralph-research init --template writing
28
28
  npx ralph-research run --json
29
+ npx ralph-research run --until-target --until-no-improve 3 --json
29
30
  npx ralph-research inspect run-0001 --json
30
31
  ```
31
32
 
@@ -60,6 +61,8 @@ rrx doctor
60
61
  rrx init --template writing
61
62
  rrx demo writing
62
63
  rrx run
64
+ rrx run --until-target
65
+ rrx run --until-target --until-no-improve 3
63
66
  rrx status
64
67
  rrx frontier
65
68
  rrx inspect <runId>
@@ -68,6 +71,70 @@ rrx reject <runId>
68
71
  rrx serve-mcp --stdio
69
72
  ```
70
73
 
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
+
71
138
  ## MCP
72
139
 
73
140
  The bundled MCP server currently supports stdio transport and exposes three thin tools backed by the same service layer as the CLI:
@@ -12,23 +12,29 @@ export async function extractCommandMetric(config, input) {
12
12
  if (result.exitCode !== 0) {
13
13
  throw new Error(`command metric extractor failed with exit code ${result.exitCode}: ${result.stderr || result.stdout}`);
14
14
  }
15
+ const parsedMetric = parseMetricValue(result.stdout, config);
15
16
  return {
16
17
  metricId: input.metricId,
17
18
  direction: input.direction,
18
- value: parseMetricValue(result.stdout, config),
19
+ value: parsedMetric.value,
19
20
  details: {
20
21
  parser: config.parser,
21
22
  command: config.command,
22
23
  cwd,
24
+ ...(parsedMetric.details ? parsedMetric.details : {}),
23
25
  },
24
26
  };
25
27
  }
26
28
  function parseMetricValue(stdout, config) {
27
29
  switch (config.parser) {
28
30
  case "plain_number":
29
- return parseNumericValue(stdout.trim(), "plain_number");
31
+ return {
32
+ value: parseNumericValue(stdout.trim(), "plain_number"),
33
+ };
30
34
  case "regex":
31
- return parseRegexValue(stdout, config.pattern);
35
+ return {
36
+ value: parseRegexValue(stdout, config.pattern),
37
+ };
32
38
  case "json_path":
33
39
  return parseJsonPathValue(stdout, config.valuePath);
34
40
  }
@@ -50,7 +56,11 @@ function parseJsonPathValue(stdout, valuePath) {
50
56
  }
51
57
  const json = JSON.parse(stdout);
52
58
  const value = readJsonPath(json, valuePath);
53
- return parseNumericValue(value, "json_path");
59
+ const details = extractJsonMetricDetails(json);
60
+ return {
61
+ value: parseNumericValue(value, "json_path"),
62
+ ...(Object.keys(details).length > 0 ? { details } : {}),
63
+ };
54
64
  }
55
65
  function readJsonPath(root, path) {
56
66
  if (!path.startsWith("$")) {
@@ -90,4 +100,36 @@ function parseNumericValue(value, parserName) {
90
100
  }
91
101
  return numericValue;
92
102
  }
103
+ function extractJsonMetricDetails(root) {
104
+ if (!root || typeof root !== "object" || Array.isArray(root)) {
105
+ return {};
106
+ }
107
+ const record = root;
108
+ const details = {};
109
+ if (typeof record.reason === "string") {
110
+ details.reason = record.reason;
111
+ }
112
+ if (Array.isArray(record.reasons)) {
113
+ details.reasons = record.reasons.filter((entry) => typeof entry === "string");
114
+ }
115
+ if (typeof record.metricId === "string") {
116
+ details.sourceMetricId = record.metricId;
117
+ }
118
+ if (typeof record.sourceMetricId === "string") {
119
+ details.sourceMetricId = record.sourceMetricId;
120
+ }
121
+ if (Array.isArray(record.invalidReasons)) {
122
+ details.invalidReasons = record.invalidReasons.filter((entry) => typeof entry === "string");
123
+ }
124
+ if (Array.isArray(record.flags)) {
125
+ details.flags = record.flags.filter((entry) => typeof entry === "string");
126
+ }
127
+ if (Array.isArray(record.diagnostics)) {
128
+ details.diagnostics = record.diagnostics.filter((entry) => typeof entry === "string");
129
+ }
130
+ if (record.details && typeof record.details === "object" && !Array.isArray(record.details)) {
131
+ Object.assign(details, record.details);
132
+ }
133
+ return details;
134
+ }
93
135
  //# sourceMappingURL=command-extractor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"command-extractor.js","sourceRoot":"","sources":["../../../src/adapters/extractor/command-extractor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"command-extractor.js","sourceRoot":"","sources":["../../../src/adapters/extractor/command-extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAYrC,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAoC,EACpC,KAAgC;IAEhC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACjG,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE;QAChD,GAAG;QACH,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,EAAE;QACpD,MAAM,EAAE,KAAK;QACb,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,MAAM,CAAC,UAAU,GAAG,KAAK;KACnC,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,kDAAkD,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1H,CAAC;IAED,MAAM,YAAY,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE7D,OAAO;QACL,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,KAAK,EAAE,YAAY,CAAC,KAAK;QACzB,OAAO,EAAE;YACP,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,GAAG;YACH,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;SACtD;KACF,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CACvB,MAAc,EACd,MAAoC;IAKpC,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,cAAc;YACjB,OAAO;gBACL,KAAK,EAAE,iBAAiB,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,cAAc,CAAC;aACxD,CAAC;QACJ,KAAK,OAAO;YACV,OAAO;gBACL,KAAK,EAAE,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC;aAC/C,CAAC;QACJ,KAAK,WAAW;YACd,OAAO,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IACxD,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,MAAc,EAAE,OAAgB;IACvD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,sCAAsC,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;IAC9D,OAAO,iBAAiB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,kBAAkB,CACzB,MAAc,EACd,SAAkB;IAKlB,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;IAC3F,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAY,CAAC;IAC3C,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAC;IAE/C,OAAO;QACL,KAAK,EAAE,iBAAiB,CAAC,KAAK,EAAE,WAAW,CAAC;QAC5C,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxD,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,IAAa,EAAE,IAAY;IAC/C,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,MAAM,GAAG,IAAI;SAChB,KAAK,CAAC,CAAC,CAAC;SACR,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC;SAC5B,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,OAAO,CAAC,CAAC;IAEnB,IAAI,OAAO,GAAY,IAAI,CAAC;IAC5B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,mCAAmC,KAAK,EAAE,CAAC,CAAC;QAC9E,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACzC,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;YACzB,SAAS;QACX,CAAC;QAED,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,OAAO,GAAI,OAAmC,CAAC,KAAK,CAAC,CAAC;YACtD,SAAS;QACX,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,qDAAqD,KAAK,EAAE,CAAC,CAAC;IAChG,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc,EAAE,UAAkB;IAC3D,MAAM,YAAY,GAChB,OAAO,KAAK,KAAK,QAAQ;QACvB,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ;YACzB,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YACjC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;IAEnB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,4CAA4C,CAAC,CAAC;IAC7E,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAa;IAC7C,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,MAAM,GAAG,IAA+B,CAAC;IAC/C,MAAM,OAAO,GAA4B,EAAE,CAAC;IAE5C,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACtC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IACjC,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAClC,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC;IACjG,CAAC;IACD,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACxC,OAAO,CAAC,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC3C,CAAC;IACD,IAAI,OAAO,MAAM,CAAC,cAAc,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;IACjD,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;QACzC,OAAO,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC;IAC/G,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC;IAC7F,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC;IACzG,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3F,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -1,4 +1,4 @@
1
- import { mkdir, readFile, writeFile } from "node:fs/promises";
1
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
2
2
  import { dirname, resolve } from "node:path";
3
3
  import { frontierEntrySchema } from "../../core/model/frontier-entry.js";
4
4
  import { isMissingFileError } from "../../shared/fs-errors.js";
@@ -10,8 +10,10 @@ export class JsonFileFrontierStore {
10
10
  }
11
11
  async save(entries) {
12
12
  const parsed = frontierSnapshotSchema.parse(entries);
13
+ const tempPath = `${this.path}.tmp-${process.pid}`;
13
14
  await mkdir(dirname(this.path), { recursive: true });
14
- await writeFile(this.path, `${JSON.stringify(parsed, null, 2)}\n`, "utf8");
15
+ await writeFile(tempPath, `${JSON.stringify(parsed, null, 2)}\n`, "utf8");
16
+ await rename(tempPath, this.path);
15
17
  }
16
18
  async load() {
17
19
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"json-file-frontier-store.js","sourceRoot":"","sources":["../../../src/adapters/fs/json-file-frontier-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,mBAAmB,EAAsB,MAAM,oCAAoC,CAAC;AAE7F,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,sBAAsB,GAAG,mBAAmB,CAAC,KAAK,EAAE,CAAC;AAE3D,MAAM,OAAO,qBAAqB;IACf,IAAI,CAAS;IAE9B,YAAmB,IAAY;QAC7B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAEM,KAAK,CAAC,IAAI,CAAC,OAAwB;QACxC,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrD,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7E,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC9C,OAAO,sBAAsB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"json-file-frontier-store.js","sourceRoot":"","sources":["../../../src/adapters/fs/json-file-frontier-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,EAAE,mBAAmB,EAAsB,MAAM,oCAAoC,CAAC;AAE7F,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,sBAAsB,GAAG,mBAAmB,CAAC,KAAK,EAAE,CAAC;AAE3D,MAAM,OAAO,qBAAqB;IACf,IAAI,CAAS;IAE9B,YAAmB,IAAY;QAC7B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAEM,KAAK,CAAC,IAAI,CAAC,OAAwB;QACxC,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,IAAI,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAC;QACnD,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,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,IAAI,CAAC,CAAC;IACpC,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC9C,OAAO,sBAAsB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
@@ -5,19 +5,32 @@ declare const lockfileMetadataSchema: z.ZodObject<{
5
5
  createdAt: z.ZodString;
6
6
  updatedAt: z.ZodString;
7
7
  ttlMs: z.ZodNumber;
8
+ graceMs: z.ZodDefault<z.ZodNumber>;
9
+ owner: z.ZodOptional<z.ZodObject<{
10
+ runId: z.ZodOptional<z.ZodString>;
11
+ operation: z.ZodOptional<z.ZodString>;
12
+ }, z.core.$strip>>;
8
13
  }, z.core.$strip>;
9
14
  export type LockfileMetadata = z.infer<typeof lockfileMetadataSchema>;
10
15
  export interface AcquireLockOptions {
11
16
  ttlMs?: number;
17
+ graceMs?: number;
18
+ owner?: LockfileMetadata["owner"];
12
19
  }
13
20
  export interface LockHandle {
14
21
  path: string;
15
22
  metadata: LockfileMetadata;
16
23
  }
17
24
  export declare class LockAcquisitionError extends Error {
18
- constructor(message: string);
25
+ readonly metadata: LockfileMetadata | undefined;
26
+ readonly heartbeatAgeMs: number | undefined;
27
+ constructor(message: string, options?: {
28
+ metadata?: LockfileMetadata;
29
+ heartbeatAgeMs?: number;
30
+ });
19
31
  }
20
32
  export declare function acquireLock(path: string, options?: AcquireLockOptions): Promise<LockHandle>;
33
+ export declare function renewLock(path: string, token: string): Promise<LockfileMetadata>;
21
34
  export declare function releaseLock(path: string, token?: string): Promise<void>;
22
35
  export declare function isStaleLock(path: string): Promise<boolean>;
23
36
  export declare function readLockMetadata(path: string): Promise<LockfileMetadata | null>;
@@ -3,30 +3,45 @@ import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
3
3
  import { dirname, resolve } from "node:path";
4
4
  import { z } from "zod";
5
5
  import { isMissingFileError } from "../../shared/fs-errors.js";
6
+ const DEFAULT_LOCK_TTL_MS = 5 * 60 * 1000;
7
+ const DEFAULT_LOCK_GRACE_MS = 30 * 1000;
8
+ const lockOwnerSchema = z.object({
9
+ runId: z.string().min(1).optional(),
10
+ operation: z.string().min(1).optional(),
11
+ });
6
12
  const lockfileMetadataSchema = z.object({
7
13
  pid: z.number().int().positive(),
8
14
  token: z.string().min(1),
9
15
  createdAt: z.string().datetime(),
10
16
  updatedAt: z.string().datetime(),
11
17
  ttlMs: z.number().int().positive(),
18
+ graceMs: z.number().int().nonnegative().default(DEFAULT_LOCK_GRACE_MS),
19
+ owner: lockOwnerSchema.optional(),
12
20
  });
13
21
  export class LockAcquisitionError extends Error {
14
- constructor(message) {
22
+ metadata;
23
+ heartbeatAgeMs;
24
+ constructor(message, options = {}) {
15
25
  super(message);
16
26
  this.name = "LockAcquisitionError";
27
+ this.metadata = options.metadata;
28
+ this.heartbeatAgeMs = options.heartbeatAgeMs;
17
29
  }
18
30
  }
19
- const DEFAULT_LOCK_TTL_MS = 5 * 60 * 1000;
20
31
  export async function acquireLock(path, options = {}) {
21
32
  const resolvedPath = resolve(path);
22
33
  const ttlMs = options.ttlMs ?? DEFAULT_LOCK_TTL_MS;
34
+ const graceMs = options.graceMs ?? DEFAULT_LOCK_GRACE_MS;
23
35
  await mkdir(dirname(resolvedPath), { recursive: true });
36
+ const now = new Date().toISOString();
24
37
  const metadata = {
25
38
  pid: process.pid,
26
39
  token: randomUUID(),
27
- createdAt: new Date().toISOString(),
28
- updatedAt: new Date().toISOString(),
40
+ createdAt: now,
41
+ updatedAt: now,
29
42
  ttlMs,
43
+ graceMs,
44
+ ...(options.owner ? { owner: options.owner } : {}),
30
45
  };
31
46
  try {
32
47
  await writeFile(resolvedPath, `${JSON.stringify(metadata, null, 2)}\n`, {
@@ -40,9 +55,20 @@ export async function acquireLock(path, options = {}) {
40
55
  throw error;
41
56
  }
42
57
  }
58
+ const existing = await readLockMetadata(resolvedPath);
43
59
  const stale = await isStaleLock(resolvedPath);
44
60
  if (!stale) {
45
- throw new LockAcquisitionError(`Active lock already exists at ${resolvedPath}`);
61
+ const heartbeatAgeMs = existing ? Date.now() - Date.parse(existing.updatedAt) : undefined;
62
+ const details = [
63
+ `Active lock already exists at ${resolvedPath}`,
64
+ existing ? `pid=${existing.pid}` : null,
65
+ existing?.owner?.runId ? `runId=${existing.owner.runId}` : null,
66
+ heartbeatAgeMs === undefined ? null : `heartbeatAgeMs=${heartbeatAgeMs}`,
67
+ ].filter(Boolean).join(" ");
68
+ throw new LockAcquisitionError(details, {
69
+ ...(existing ? { metadata: existing } : {}),
70
+ ...(heartbeatAgeMs === undefined ? {} : { heartbeatAgeMs }),
71
+ });
46
72
  }
47
73
  await rm(resolvedPath, { force: true });
48
74
  await writeFile(resolvedPath, `${JSON.stringify(metadata, null, 2)}\n`, {
@@ -51,6 +77,24 @@ export async function acquireLock(path, options = {}) {
51
77
  });
52
78
  return { path: resolvedPath, metadata };
53
79
  }
80
+ export async function renewLock(path, token) {
81
+ const resolvedPath = resolve(path);
82
+ const metadata = await readLockMetadata(resolvedPath);
83
+ if (!metadata) {
84
+ throw new LockAcquisitionError(`Refusing to renew lock at ${resolvedPath}: lock is missing`);
85
+ }
86
+ if (metadata.token !== token) {
87
+ throw new LockAcquisitionError(`Refusing to renew lock at ${resolvedPath}: token mismatch`, {
88
+ metadata,
89
+ });
90
+ }
91
+ const updated = {
92
+ ...metadata,
93
+ updatedAt: new Date().toISOString(),
94
+ };
95
+ await writeFile(resolvedPath, `${JSON.stringify(updated, null, 2)}\n`, "utf8");
96
+ return updated;
97
+ }
54
98
  export async function releaseLock(path, token) {
55
99
  const resolvedPath = resolve(path);
56
100
  const metadata = await readLockMetadata(resolvedPath);
@@ -68,7 +112,7 @@ export async function isStaleLock(path) {
68
112
  return false;
69
113
  }
70
114
  const ageMs = Date.now() - Date.parse(metadata.updatedAt);
71
- if (ageMs > metadata.ttlMs) {
115
+ if (ageMs > metadata.ttlMs + metadata.graceMs) {
72
116
  return true;
73
117
  }
74
118
  return !isProcessAlive(metadata.pid);
@@ -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,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;CACnC,CAAC,CAAC;AAaH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C,YAAmB,OAAe;QAChC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,UAA8B,EAAE;IAC9E,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,mBAAmB,CAAC;IAEnD,MAAM,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAExD,MAAM,QAAQ,GAAqB;QACjC,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,KAAK,EAAE,UAAU,EAAE;QACnB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,KAAK;KACN,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;YACtE,QAAQ,EAAE,MAAM;YAChB,IAAI,EAAE,IAAI;SACX,CAAC,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;YACjC,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,CAAC;IAC9C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,oBAAoB,CAAC,iCAAiC,YAAY,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,MAAM,EAAE,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,SAAS,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;QACtE,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,IAAI;KACX,CAAC,CAAC;IACH,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,KAAc;IAC5D,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,YAAY,CAAC,CAAC;IACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO;IACT,CAAC;IAED,IAAI,KAAK,IAAI,QAAQ,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;QACtC,MAAM,IAAI,oBAAoB,CAAC,+BAA+B,YAAY,kBAAkB,CAAC,CAAC;IAChG,CAAC;IAED,MAAM,EAAE,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY;IAC5C,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC1D,IAAI,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY;IACjD,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QACjD,OAAO,sBAAsB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAc;IAC1C,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,CAAC;AACzG,CAAC;AAED,SAAS,cAAc,CAAC,GAAW;IACjC,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;YAC9C,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;YACnD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,OAAO,KAAK,CAAC;YACf,CAAC;YACD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
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;AAeH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7B,QAAQ,CAA+B;IACvC,cAAc,CAAqB;IAEnD,YACE,OAAe,EACf,UAGI,EAAE;QAEN,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAC/C,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,UAA8B,EAAE;IAC9E,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,mBAAmB,CAAC;IACnD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,qBAAqB,CAAC;IAEzD,MAAM,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAErC,MAAM,QAAQ,GAAqB;QACjC,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,KAAK,EAAE,UAAU,EAAE;QACnB,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,GAAG;QACd,KAAK;QACL,OAAO;QACP,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACnD,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;YACtE,QAAQ,EAAE,MAAM;YAChB,IAAI,EAAE,IAAI;SACX,CAAC,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;YACjC,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,YAAY,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,CAAC;IAC9C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1F,MAAM,OAAO,GAAG;YACd,iCAAiC,YAAY,EAAE;YAC/C,QAAQ,CAAC,CAAC,CAAC,OAAO,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI;YACvC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI;YAC/D,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,kBAAkB,cAAc,EAAE;SACzE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,IAAI,oBAAoB,CAAC,OAAO,EAAE;YACtC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3C,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC;SAC5D,CAAC,CAAC;IACL,CAAC;IAED,MAAM,EAAE,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,SAAS,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;QACtE,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,IAAI;KACX,CAAC,CAAC;IACH,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,KAAa;IACzD,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,YAAY,CAAC,CAAC;IACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,oBAAoB,CAAC,6BAA6B,YAAY,mBAAmB,CAAC,CAAC;IAC/F,CAAC;IAED,IAAI,QAAQ,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;QAC7B,MAAM,IAAI,oBAAoB,CAAC,6BAA6B,YAAY,kBAAkB,EAAE;YAC1F,QAAQ;SACT,CAAC,CAAC;IACL,CAAC;IAED,MAAM,OAAO,GAAqB;QAChC,GAAG,QAAQ;QACX,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IACF,MAAM,SAAS,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC/E,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,KAAc;IAC5D,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,YAAY,CAAC,CAAC;IACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO;IACT,CAAC;IAED,IAAI,KAAK,IAAI,QAAQ,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;QACtC,MAAM,IAAI,oBAAoB,CAAC,+BAA+B,YAAY,kBAAkB,CAAC,CAAC;IAChG,CAAC;IAED,MAAM,EAAE,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY;IAC5C,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC1D,IAAI,KAAK,GAAG,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY;IACjD,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QACjD,OAAO,sBAAsB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAc;IAC1C,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,CAAC;AACzG,CAAC;AAED,SAAS,cAAc,CAAC,GAAW;IACjC,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;YAC9C,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;YACnD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,OAAO,KAAK,CAAC;YACf,CAAC;YACD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -2,9 +2,13 @@ import { type RalphManifest } from "../../core/manifest/schema.js";
2
2
  export interface LoadedManifest {
3
3
  path: string;
4
4
  manifest: RalphManifest;
5
+ resolvedBaselineRef: string;
5
6
  }
6
7
  export declare class ManifestLoadError extends Error {
7
8
  readonly causeValue?: unknown;
8
9
  constructor(message: string, causeValue?: unknown);
9
10
  }
10
- export declare function loadManifestFromFile(path?: string): Promise<LoadedManifest>;
11
+ export interface LoadManifestOptions {
12
+ repoRoot?: string;
13
+ }
14
+ export declare function loadManifestFromFile(path?: string, options?: LoadManifestOptions): Promise<LoadedManifest>;
@@ -2,6 +2,7 @@ import { readFile } from "node:fs/promises";
2
2
  import { resolve } from "node:path";
3
3
  import { parse } from "yaml";
4
4
  import { ZodError } from "zod";
5
+ import { compileManifestAdmission } from "../../core/manifest/admission.js";
5
6
  import { DEFAULT_MANIFEST_FILENAME, RalphManifestSchema } from "../../core/manifest/schema.js";
6
7
  export class ManifestLoadError extends Error {
7
8
  causeValue;
@@ -11,7 +12,7 @@ export class ManifestLoadError extends Error {
11
12
  this.causeValue = causeValue;
12
13
  }
13
14
  }
14
- export async function loadManifestFromFile(path = DEFAULT_MANIFEST_FILENAME) {
15
+ export async function loadManifestFromFile(path = DEFAULT_MANIFEST_FILENAME, options = {}) {
15
16
  const resolvedPath = resolve(path);
16
17
  let rawText;
17
18
  try {
@@ -28,12 +29,24 @@ export async function loadManifestFromFile(path = DEFAULT_MANIFEST_FILENAME) {
28
29
  throw new ManifestLoadError(`Failed to parse YAML from ${resolvedPath}`, error);
29
30
  }
30
31
  try {
32
+ const manifest = RalphManifestSchema.parse(parsedYaml);
33
+ const admission = await compileManifestAdmission(manifest, options);
34
+ if (!admission.executable) {
35
+ throw new ManifestLoadError(`Manifest admission failed for ${resolvedPath}`, {
36
+ executable: false,
37
+ issues: admission.issues,
38
+ });
39
+ }
31
40
  return {
32
41
  path: resolvedPath,
33
- manifest: RalphManifestSchema.parse(parsedYaml),
42
+ manifest,
43
+ resolvedBaselineRef: admission.resolvedBaselineRef,
34
44
  };
35
45
  }
36
46
  catch (error) {
47
+ if (error instanceof ManifestLoadError) {
48
+ throw error;
49
+ }
37
50
  if (error instanceof ZodError) {
38
51
  throw new ManifestLoadError(`Manifest validation failed for ${resolvedPath}`, error.flatten());
39
52
  }
@@ -1 +1 @@
1
- {"version":3,"file":"manifest-loader.js","sourceRoot":"","sources":["../../../src/adapters/fs/manifest-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAE/B,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAsB,MAAM,+BAA+B,CAAC;AAOnH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1B,UAAU,CAAW;IAErC,YAAmB,OAAe,EAAE,UAAoB;QACtD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAI,GAAG,yBAAyB;IACzE,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,iBAAiB,CAAC,8BAA8B,YAAY,EAAE,EAAE,KAAK,CAAC,CAAC;IACnF,CAAC;IAED,IAAI,UAAmB,CAAC;IACxB,IAAI,CAAC;QACH,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,iBAAiB,CAAC,6BAA6B,YAAY,EAAE,EAAE,KAAK,CAAC,CAAC;IAClF,CAAC;IAED,IAAI,CAAC;QACH,OAAO;YACL,IAAI,EAAE,YAAY;YAClB,QAAQ,EAAE,mBAAmB,CAAC,KAAK,CAAC,UAAU,CAAC;SAChD,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,iBAAiB,CAAC,kCAAkC,YAAY,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACjG,CAAC;QAED,MAAM,IAAI,iBAAiB,CAAC,kCAAkC,YAAY,EAAE,EAAE,KAAK,CAAC,CAAC;IACvF,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"manifest-loader.js","sourceRoot":"","sources":["../../../src/adapters/fs/manifest-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAE/B,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAsB,MAAM,+BAA+B,CAAC;AAQnH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1B,UAAU,CAAW;IAErC,YAAmB,OAAe,EAAE,UAAoB;QACtD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAMD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAAI,GAAG,yBAAyB,EAChC,UAA+B,EAAE;IAEjC,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,iBAAiB,CAAC,8BAA8B,YAAY,EAAE,EAAE,KAAK,CAAC,CAAC;IACnF,CAAC;IAED,IAAI,UAAmB,CAAC;IACxB,IAAI,CAAC;QACH,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,iBAAiB,CAAC,6BAA6B,YAAY,EAAE,EAAE,KAAK,CAAC,CAAC;IAClF,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,mBAAmB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACvD,MAAM,SAAS,GAAG,MAAM,wBAAwB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAEpE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;YAC1B,MAAM,IAAI,iBAAiB,CAAC,iCAAiC,YAAY,EAAE,EAAE;gBAC3E,UAAU,EAAE,KAAK;gBACjB,MAAM,EAAE,SAAS,CAAC,MAAM;aACzB,CAAC,CAAC;QACL,CAAC;QAED,OAAO;YACL,IAAI,EAAE,YAAY;YAClB,QAAQ;YACR,mBAAmB,EAAE,SAAS,CAAC,mBAAmB;SACnD,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,iBAAiB,EAAE,CAAC;YACvC,MAAM,KAAK,CAAC;QACd,CAAC;QAED,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,iBAAiB,CAAC,kCAAkC,YAAY,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACjG,CAAC;QAED,MAAM,IAAI,iBAAiB,CAAC,kCAAkC,YAAY,EAAE,EAAE,KAAK,CAAC,CAAC;IACvF,CAAC;AACH,CAAC"}
@@ -6,4 +6,6 @@ export declare class GitClient {
6
6
  constructor(repoRoot: string);
7
7
  stageAndCommitPaths(paths: string[], message: string): Promise<CommitResult>;
8
8
  getHeadSha(): Promise<string>;
9
+ applyPatchIfNeeded(patchPath: string): Promise<"applied" | "already_applied">;
10
+ private canApplyPatch;
9
11
  }
@@ -19,5 +19,24 @@ export class GitClient {
19
19
  const { stdout } = await execa("git", ["-C", this.repoRoot, "rev-parse", "HEAD"]);
20
20
  return stdout.trim();
21
21
  }
22
+ async applyPatchIfNeeded(patchPath) {
23
+ if (await this.canApplyPatch(["apply", "--check", "--3way", "--index", "-p2", patchPath])) {
24
+ await execa("git", ["-C", this.repoRoot, "apply", "--3way", "--index", "-p2", patchPath]);
25
+ return "applied";
26
+ }
27
+ if (await this.canApplyPatch(["apply", "--check", "--reverse", "--index", "-p2", patchPath])) {
28
+ return "already_applied";
29
+ }
30
+ throw new Error(`repository state diverged from durable promotion patch ${patchPath}`);
31
+ }
32
+ async canApplyPatch(args) {
33
+ try {
34
+ await execa("git", ["-C", this.repoRoot, ...args]);
35
+ return true;
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ }
22
41
  }
23
42
  //# sourceMappingURL=git-client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"git-client.js","sourceRoot":"","sources":["../../../src/adapters/git/git-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAM9B,MAAM,OAAO,SAAS;IACH,QAAQ,CAAS;IAElC,YAAmB,QAAgB;QACjC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAEM,KAAK,CAAC,mBAAmB,CAAC,KAAe,EAAE,OAAe;QAC/D,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACnF,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;QACpF,CAAC;QAED,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC;QAC7E,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QACnE,OAAO;YACL,SAAS,EAAE,MAAM,IAAI,CAAC,UAAU,EAAE;SACnC,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,UAAU;QACrB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;QAClF,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;CACF"}
1
+ {"version":3,"file":"git-client.js","sourceRoot":"","sources":["../../../src/adapters/git/git-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAM9B,MAAM,OAAO,SAAS;IACH,QAAQ,CAAS;IAElC,YAAmB,QAAgB;QACjC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAEM,KAAK,CAAC,mBAAmB,CAAC,KAAe,EAAE,OAAe;QAC/D,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACnF,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;QACpF,CAAC;QAED,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC;QAC7E,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QACnE,OAAO;YACL,SAAS,EAAE,MAAM,IAAI,CAAC,UAAU,EAAE;SACnC,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,UAAU;QACrB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;QAClF,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAAC,SAAiB;QAC/C,IAAI,MAAM,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;YAC1F,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;YAC1F,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,IAAI,MAAM,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;YAC7F,OAAO,iBAAiB,CAAC;QAC3B,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,0DAA0D,SAAS,EAAE,CAAC,CAAC;IACzF,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,IAAc;QACxC,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}