ralphctl 0.17.0 → 0.17.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.
@@ -6024,7 +6024,7 @@ var createNpmVersionChecker = (deps) => {
6024
6024
  // package.json
6025
6025
  var package_default = {
6026
6026
  name: "ralphctl",
6027
- version: "0.17.0",
6027
+ version: "0.17.1",
6028
6028
  description: "Agent harness for long-running AI coding tasks \u2014 orchestrates Claude Code, GitHub Copilot, and OpenAI Codex across repositories",
6029
6029
  homepage: "https://github.com/lukas-grigis/ralphctl",
6030
6030
  type: "module",
@@ -15319,7 +15319,7 @@ var validateSignalsFile = async (outputDir, contract) => {
15319
15319
  }
15320
15320
  const wrapper = current;
15321
15321
  const inner = wrapper.signals;
15322
- const defaulted = defaultMissingTimestamps(inner);
15322
+ const defaulted = renameNarrativeBodyToText(defaultMissingTimestamps(inner));
15323
15323
  const parsed = contract.signalsSchema.safeParse(defaulted);
15324
15324
  if (!parsed.success) {
15325
15325
  return Result.error(
@@ -15337,6 +15337,18 @@ var describeJsonError = (cause) => {
15337
15337
  if (cause instanceof Error) return cause.message;
15338
15338
  return String(cause);
15339
15339
  };
15340
+ var NARRATIVE_SIGNAL_KINDS = /* @__PURE__ */ new Set(["learning", "note", "decision"]);
15341
+ var renameNarrativeBodyToText = (inner) => {
15342
+ if (!Array.isArray(inner)) return inner;
15343
+ return inner.map((sig) => {
15344
+ if (typeof sig !== "object" || sig === null) return sig;
15345
+ const s = sig;
15346
+ if (typeof s.type !== "string" || !NARRATIVE_SIGNAL_KINDS.has(s.type)) return sig;
15347
+ if (typeof s.text === "string" || typeof s.body !== "string") return sig;
15348
+ const { body, ...rest } = s;
15349
+ return { ...rest, text: body };
15350
+ });
15351
+ };
15340
15352
  var defaultMissingTimestamps = (inner) => {
15341
15353
  if (!Array.isArray(inner)) return inner;
15342
15354
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -15427,6 +15439,16 @@ var refineExampleSignals = [
15427
15439
  type: "decision",
15428
15440
  text: "Scoped export to CSV only for v1; XLSX deferred to a follow-up ticket.",
15429
15441
  timestamp: EXAMPLE_TS
15442
+ },
15443
+ {
15444
+ type: "learning",
15445
+ text: "The export path already streams; the ticket must not assume an in-memory buffer.",
15446
+ timestamp: EXAMPLE_TS
15447
+ },
15448
+ {
15449
+ type: "note",
15450
+ text: "The user ruled column ordering out of scope \u2014 captured as a deferred item rather than an AC.",
15451
+ timestamp: EXAMPLE_TS
15430
15452
  }
15431
15453
  ];
15432
15454
  var refineOutputContract = {
@@ -16840,6 +16862,21 @@ var planExampleSignals = [
16840
16862
  type: "task-plan",
16841
16863
  tasksJson: '[{"name":"Wire export endpoint","ticketRef":"<ticket-uuid>","projectPath":"/abs/repo","steps":["..."],"verificationCriteria":["..."]}]',
16842
16864
  timestamp: EXAMPLE_TS2
16865
+ },
16866
+ {
16867
+ type: "decision",
16868
+ text: "Split the export work into endpoint + serializer tasks so the shared file is owned by exactly one task.",
16869
+ timestamp: EXAMPLE_TS2
16870
+ },
16871
+ {
16872
+ type: "learning",
16873
+ text: "The repo runs its integration suite from a separate config; the root test command does not cover it.",
16874
+ timestamp: EXAMPLE_TS2
16875
+ },
16876
+ {
16877
+ type: "note",
16878
+ text: "Two approved tickets touch the same route file; sequenced them via blockedBy rather than splitting the file.",
16879
+ timestamp: EXAMPLE_TS2
16843
16880
  }
16844
16881
  ];
16845
16882
  var planOutputContract = {
@@ -18770,6 +18807,16 @@ var generatorExampleSignals = [
18770
18807
  appliesTo: "config / io layer",
18771
18808
  timestamp: EXAMPLE_TS3
18772
18809
  },
18810
+ {
18811
+ type: "decision",
18812
+ text: "Centralised the parse in one helper rather than patching both call sites, to avoid future drift.",
18813
+ timestamp: EXAMPLE_TS3
18814
+ },
18815
+ {
18816
+ type: "note",
18817
+ text: "Left the unrelated typo at src/baz.ts:8 alone \u2014 out of scope for this task.",
18818
+ timestamp: EXAMPLE_TS3
18819
+ },
18773
18820
  { type: "task-verified", output: "$ <project test command>\n... 42 passed", timestamp: EXAMPLE_TS3 },
18774
18821
  {
18775
18822
  type: COMMIT_MESSAGE_KIND,
@@ -20454,6 +20501,16 @@ var evaluatorExampleSignals = [
20454
20501
  ],
20455
20502
  critique: "Correctness: add edge-case handling for empty input at src/foo.ts:23.",
20456
20503
  timestamp: EXAMPLE_TS4
20504
+ },
20505
+ {
20506
+ type: "learning",
20507
+ text: "The suite needs a built fixture; a cold checkout fails the C1 command for reasons unrelated to the task.",
20508
+ timestamp: EXAMPLE_TS4
20509
+ },
20510
+ {
20511
+ type: "note",
20512
+ text: "C2 was checked by reading the call site \u2014 the criterion is manual, so no command was run.",
20513
+ timestamp: EXAMPLE_TS4
20457
20514
  }
20458
20515
  ];
20459
20516
  var evaluatorOutputContract = {
@@ -28020,7 +28077,17 @@ var readinessExampleSignals = [
28020
28077
  content: "# Verify\n\nRun `<verify command>` (typecheck + lint + test).",
28021
28078
  timestamp: EXAMPLE_TS6
28022
28079
  },
28023
- { type: "skill-suggestions", names: ["typescript-strict", "code-style-conventions"], timestamp: EXAMPLE_TS6 }
28080
+ { type: "skill-suggestions", names: ["typescript-strict", "code-style-conventions"], timestamp: EXAMPLE_TS6 },
28081
+ {
28082
+ type: "learning",
28083
+ text: "The verify command lives in a workspace package script, not the repo root manifest.",
28084
+ timestamp: EXAMPLE_TS6
28085
+ },
28086
+ {
28087
+ type: "note",
28088
+ text: "No lint config found, so the proposed verify skill covers typecheck + test only.",
28089
+ timestamp: EXAMPLE_TS6
28090
+ }
28024
28091
  ];
28025
28092
  var readinessOutputContract = {
28026
28093
  schemaVersion: 1,
@@ -29632,6 +29699,21 @@ var ideateExampleSignals = [
29632
29699
  type: "ideated-tickets",
29633
29700
  outputJson: '{"requirements":"# Export CSV\\n\\n## Problem\\n\u2026","tasks":[{"name":"Wire endpoint","projectPath":"/abs/repo","steps":["\u2026"],"verificationCriteria":["\u2026"]}]}',
29634
29701
  timestamp: EXAMPLE_TS9
29702
+ },
29703
+ {
29704
+ type: "decision",
29705
+ text: "Scoped export to CSV only for v1; XLSX deferred to a follow-up ticket.",
29706
+ timestamp: EXAMPLE_TS9
29707
+ },
29708
+ {
29709
+ type: "learning",
29710
+ text: "The repo runs its integration suite from a separate config; the root test command does not cover it.",
29711
+ timestamp: EXAMPLE_TS9
29712
+ },
29713
+ {
29714
+ type: "note",
29715
+ text: "The user ruled out changing the existing download endpoint, so the new route is additive.",
29716
+ timestamp: EXAMPLE_TS9
29635
29717
  }
29636
29718
  ];
29637
29719
  var ideateOutputContract = {
package/dist/cli.mjs CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  // src/index.ts
4
4
  process.env.NODE_ENV ??= "production";
5
- var { runCli } = await import("./cli-CCNZ2VKB.mjs");
5
+ var { runCli } = await import("./cli-WTLOGLWF.mjs");
6
6
  await runCli(process.argv);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "packageVersion": "0.17.0",
4
- "generatedAt": "2026-07-27T15:30:39.020Z",
3
+ "packageVersion": "0.17.1",
4
+ "generatedAt": "2026-07-28T04:40:58.689Z",
5
5
  "assets": [
6
6
  "agent-definitions/ralphctl-evaluator.md",
7
7
  "agent-definitions/ralphctl-generator.md",
@@ -258,11 +258,12 @@ The `outputJson` field is a JSON-encoded string. When decoded it has exactly two
258
258
 
259
259
  **Required signals:** exactly one `ideated-tickets`.
260
260
 
261
- **Optional signals** (emit when relevant):
261
+ **Optional signals** (emit when relevant). Each carries its prose in a `text` field — never
262
+ `body`; the output contract below shows the exact shape:
262
263
 
263
264
  - `note` — for status updates or observations worth surfacing.
264
265
  - `learning` — for non-obvious repo facts discovered during exploration.
265
- - `decision` — for architectural choices made during planning (body capped at 500 chars).
266
+ - `decision` — for architectural choices made during planning.
266
267
 
267
268
  Emit nothing else. No prose responses, no explanatory comments outside the signals file.
268
269
 
@@ -437,10 +437,11 @@ Once the user has answered "Approved, write it" in Step 4 AND every checklist it
437
437
  satisfied, write the `task-plan` signal into `signals.json` per the output contract below.
438
438
  The task array goes into the signal's `tasksJson` field as a JSON-encoded string.
439
439
 
440
- **Optional signals** (emit when relevant):
440
+ **Optional signals** (emit when relevant). Each carries its prose in a `text` field — never
441
+ `body`; the output contract below shows the exact shape:
441
442
 
442
443
  - `note` — for status updates or observations worth surfacing.
443
444
  - `learning` — for non-obvious repo facts discovered during exploration.
444
- - `decision` — for architectural choices made during planning (body capped at 500 chars).
445
+ - `decision` — for architectural choices made during planning.
445
446
 
446
447
  {{OUTPUT_CONTRACT_SECTION}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ralphctl",
3
- "version": "0.17.0",
3
+ "version": "0.17.1",
4
4
  "description": "Agent harness for long-running AI coding tasks — orchestrates Claude Code, GitHub Copilot, and OpenAI Codex across repositories",
5
5
  "homepage": "https://github.com/lukas-grigis/ralphctl",
6
6
  "type": "module",