@rness/cli 0.15.1 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -119,9 +119,10 @@ the files a given agent needs, for the agents the team declares in
119
119
  A new document takes the collection's first status (`Proposed` for an
120
120
  ADR, `Draft` otherwise) and the next number of the local checkout; two
121
121
  branches can pick the same one. Each skill records its session: it adds
122
- the Claude Code session id to `sessions:` in the front matter of what it
123
- writes or closes — an edit made without a skill leaves none. No skill
124
- commits.
122
+ `{ id: <session id>, agent: <model> }` to `sessions:` in the front matter
123
+ of what it writes or closes. The agent is the model it runs as, as Claude
124
+ Code names it (`Claude Opus 5.5`): no variable gives it to a skill. An
125
+ edit made without a skill leaves none. No skill commits.
125
126
  - rness owns values, not files: what is missing is added, nothing else is
126
127
  touched, and a file it cannot parse is reported, never rewritten.
127
128
  `sync --check` and `validate` report a missing value. Removing an agent
@@ -234,17 +235,22 @@ in its Settings`.
234
235
  collection fields' options: every contract status plus the ones found in
235
236
  `.rness/`, in lifecycle order, at most 50), `Collection` (one option per tab of
236
237
  `rness status`; not `Type`, which is GitHub's own issue-type field and
237
- filter), `Agent` (`working`), `Session` (`claude · 1a2b3c4d`, plus the
238
- agent type for a subagent), `Path` and `Sessions` — the document's
239
- `sessions:` (see "Agent targets"), joined by `, `, written by sync and
240
- never cleared: which sessions wrote a specification or implemented a plan,
241
- after they ended (`claude --resume <id>` reopens one on the machine it ran
242
- on). A board made before 0.15.0 gains `Sessions` at its next sync. A board per directory, named as
238
+ filter), `Agent` (`working`), `Working session` (`claude · 1a2b3c4d`,
239
+ plus the agent type for a subagent: the session working on the document
240
+ now, cleared when it ends), `Path`, and `Session history` — the
241
+ document's `sessions:` (see "Agent targets"), each `Claude Opus 5.5 ·
242
+ <id>` (the id alone for an entry without its agent), joined by `, `,
243
+ written by sync and never cleared: which sessions wrote a specification
244
+ or implemented a plan, after they ended (`claude --resume <id>` reopens
245
+ one on the machine it ran on). A board made before 0.15.0 gains
246
+ `Session history` at its next sync; one from 0.15 has its `Session` and
247
+ `Sessions` renamed in place, values and views kept (`renamed field
248
+ Session → Working session`). A board per directory, named as
243
249
  `rness status` names its tab, filtered on its `Collection`, its columns
244
250
  that collection's own steps: each collection has its own status field
245
251
  (`ADR status`, `Specs status`, …; a directory without statuses is columned
246
252
  by `Status`, which holds them all for the `All` table). `pulse sync`
247
- remakes a board built by an earlier version (its URL changes once); a `Working` table, filtered on `Agent: working`. A first view named `View 1` (GitHub's default) becomes `All` when no `All` exists, on create and on sync, showing Title, Collection, Status and Session. Options are coloured (statuses by lifecycle: blue proposed, purple approved, yellow in progress, red blocked or rejected, yellow superseded, green done, gray abandoned; collections and `working` too); a sync recolours rness's options and leaves other options' colours alone. rness does
253
+ remakes a board built by an earlier version (its URL changes once); a `Working` table, filtered on `Agent: working`. A first view named `View 1` (GitHub's default) becomes `All` when no `All` exists, on create and on sync, showing Title, Collection, Status and Working session. Options are coloured (statuses by lifecycle: blue proposed, purple approved, yellow in progress, red blocked or rejected, yellow superseded, green done, gray abandoned; collections and `working` too); a sync recolours rness's options and leaves other options' colours alone. rness does
248
254
  not set the project's visibility: the project gets GitHub's default for a
249
255
  new organization project, which is private (`public: false`). Verified
250
256
  with Claude Code 2.1.284 on 2026-09-29.
@@ -352,7 +358,7 @@ repository, the board).
352
358
  `contract`, `provider`, `org`, `agents`, `pulse`, `repos`, `scopes`.
353
359
  - A provider _written_ in `rness.json` that this version cannot talk to
354
360
  (`gitlab`) is refused by `validate`, `create`, `login` and `pulse`:
355
- `provider "gitlab" is not supported by @rness/cli 0.15.1 (supported:
361
+ `provider "gitlab" is not supported by @rness/cli 0.16.0 (supported:
356
362
  github)`. `add`, `sync` and the local commands never refuse. `null` is not a
357
363
  value: an absent key means none.
358
364
 
@@ -529,6 +535,21 @@ per repository, the files to commit there.
529
535
  Exit codes: 0 success, 1 failure, 2 usage — or a refusal without a TTY.
530
536
  `RNESS_DEBUG=1` adds stack traces; `RNESS_NO_DELEGATE=1` skips the delegation.
531
537
 
538
+ ## 0.16.0 — Working session and Session history; the agent in the history
539
+
540
+ - Agent Pulse's session fields are renamed so that the names say what
541
+ they hold: `Session` becomes `Working session` (the session working on
542
+ a document now) and `Sessions` becomes `Session history` (every session
543
+ that changed it). The first `pulse sync` with 0.16.0 renames them in
544
+ place: values, ids and views stay. Until then, marks use whichever name
545
+ the board has. See "Pulse".
546
+ - `Session history` names each session's agent: `Claude Opus 5.5 ·
547
+ 1e9cb41b-…`. The lifecycle skills now record `{ id, agent }` in
548
+ `sessions:`; a bare id, as 0.15 wrote it, still reads, and shows alone.
549
+ `rness upgrade` rewrites the four skills: commit `.claude/skills/rness/`
550
+ in each repository. See "Agent targets".
551
+ - Blocks are unchanged.
552
+
532
553
  ## 0.15.1 — upgrade names every file to commit
533
554
 
534
555
  - `rness upgrade`'s next steps name every file the new version's sync
package/dist/bin/rness.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  findDelegate,
7
7
  reportError,
8
8
  run
9
- } from "../chunk-7IVHL744.js";
9
+ } from "../chunk-ABCO6D6B.js";
10
10
 
11
11
  // src/bin/rness.ts
12
12
  import { pathToFileURL } from "url";
@@ -486,7 +486,7 @@ function parseRepoSpec(spec, org, host) {
486
486
  }
487
487
 
488
488
  // src/version.ts
489
- var VERSION = "0.15.1";
489
+ var VERSION = "0.16.0";
490
490
 
491
491
  // src/core/pm.ts
492
492
  import { execFile as execFile2 } from "child_process";
@@ -1073,10 +1073,17 @@ function statusOf(item) {
1073
1073
  function sessionsOf(item) {
1074
1074
  const listed = item.fields?.["sessions"];
1075
1075
  if (!Array.isArray(listed)) return [];
1076
- const ids = listed.filter(
1077
- (s) => typeof s === "string" && s !== ""
1078
- );
1079
- return [...new Set(ids)];
1076
+ const entries = /* @__PURE__ */ new Map();
1077
+ for (const entry of listed) {
1078
+ const fields2 = typeof entry === "string" ? { id: entry } : entry !== null && typeof entry === "object" ? entry : {};
1079
+ const { id, agent } = fields2;
1080
+ if (typeof id !== "string" || id === "" || entries.has(id)) continue;
1081
+ entries.set(
1082
+ id,
1083
+ typeof agent === "string" && agent !== "" ? { id, agent } : { id }
1084
+ );
1085
+ }
1086
+ return [...entries.values()];
1080
1087
  }
1081
1088
  function rowOf(dir, item) {
1082
1089
  const base = posix3.basename(item.rel, ".md");
@@ -1410,7 +1417,7 @@ function desiredOf(tabs, org) {
1410
1417
  status: statusOf2(row.status),
1411
1418
  type: tab.label,
1412
1419
  statusField: fields2.get(tab.label)?.name ?? null,
1413
- sessions: row.sessions?.join(", ") ?? null
1420
+ sessions: row.sessions?.map((e) => e.agent === void 0 ? e.id : `${e.agent} \xB7 ${e.id}`).join(", ") ?? null
1414
1421
  }))
1415
1422
  );
1416
1423
  }
@@ -1991,6 +1998,18 @@ async function setOptions(field, options, o) {
1991
1998
  );
1992
1999
  return toField(d.updateProjectV2Field.projectV2Field);
1993
2000
  }
2001
+ async function renameField(fieldId, name, o) {
2002
+ const d = await graphql(
2003
+ `mutation($fieldId: ID!, $name: String!) {
2004
+ updateProjectV2Field(input: { fieldId: $fieldId, name: $name }) {
2005
+ projectV2Field { ${FIELD_SELECTION} }
2006
+ }
2007
+ }`,
2008
+ { fieldId, name },
2009
+ o
2010
+ );
2011
+ return toField(d.updateProjectV2Field.projectV2Field);
2012
+ }
1994
2013
  async function listItems(projectId, o, { bodies = true } = {}) {
1995
2014
  const items = [];
1996
2015
  let cursor = null;
@@ -2490,6 +2509,13 @@ var WORKING = "working";
2490
2509
  var WORKING_VIEW = "Working";
2491
2510
  var MEMORY = ".rness";
2492
2511
  var LABEL = "rness";
2512
+ var WORKING_SESSION = "Working session";
2513
+ var SESSION_HISTORY = "Session history";
2514
+ var FORMERLY = {
2515
+ [WORKING_SESSION]: "Session",
2516
+ [SESSION_HISTORY]: "Sessions"
2517
+ };
2518
+ var valueOf = (values2, name) => values2[name] ?? values2[FORMERLY[name] ?? ""] ?? null;
2493
2519
  var LABEL_COLOR = "5319e7";
2494
2520
  var LABEL_DESCRIPTION = "A document of .rness, on Agent Pulse";
2495
2521
  var labelled = (labels) => labels.some((l) => l.toLowerCase() === LABEL.toLowerCase());
@@ -2624,6 +2650,11 @@ var GitHubBoards = class {
2624
2650
  const text = async (name) => {
2625
2651
  const field = fields2.find((f) => f.name === name);
2626
2652
  if (field !== void 0) return field;
2653
+ const was = fields2.find((f) => f.name === FORMERLY[name]);
2654
+ if (was !== void 0) {
2655
+ added.push(`renamed field ${was.name} \u2192 ${name}`);
2656
+ return renameField(was.id, name, this.#o);
2657
+ }
2627
2658
  added.push(`field ${name}`);
2628
2659
  return createField(cache.projectId, name, "TEXT", this.#o);
2629
2660
  };
@@ -2644,9 +2675,9 @@ var GitHubBoards = class {
2644
2675
  for (const f of layout.fields)
2645
2676
  own.set(f.name, await single(f.name, "Status", f.statuses, true));
2646
2677
  const agent = await single("Agent", "Agent", [WORKING]);
2647
- const session = await text("Session");
2678
+ const session = await text(WORKING_SESSION);
2648
2679
  const path = await text("Path");
2649
- const sessions = await text("Sessions");
2680
+ const sessions = await text(SESSION_HISTORY);
2650
2681
  const current = await views(cache.projectId, this.#o);
2651
2682
  const first = current[0];
2652
2683
  if (first !== void 0 && first.name === DEFAULT_VIEW && !current.some((v) => v.name === ALL_VIEW)) {
@@ -2748,14 +2779,15 @@ var GitHubBoards = class {
2748
2779
  collectionStatus: r.values[statusFieldName(r.values[COLLECTION_FIELD] ?? "")] ?? null,
2749
2780
  type: r.values[COLLECTION_FIELD] ?? null,
2750
2781
  agent: r.values["Agent"] ?? null,
2751
- session: r.values["Session"] ?? null,
2752
- sessions: r.values["Sessions"] ?? null
2782
+ session: valueOf(r.values, WORKING_SESSION),
2783
+ sessions: valueOf(r.values, SESSION_HISTORY)
2753
2784
  };
2754
2785
  });
2755
2786
  }
2756
2787
  async #set(board, itemId, name, value) {
2757
2788
  const cache = await this.#cacheOf(board);
2758
- const field = (await this.#fields(board)).find((f) => f.name === name);
2789
+ const fields2 = await this.#fields(board);
2790
+ const field = fields2.find((f) => f.name === name) ?? fields2.find((f) => f.name === FORMERLY[name]);
2759
2791
  if (field === void 0) throw new Error(`the board has no field ${name}`);
2760
2792
  let sent = null;
2761
2793
  if (value !== null && field.options === null) sent = { text: value };
@@ -2768,8 +2800,8 @@ var GitHubBoards = class {
2768
2800
  await setValue(cache.projectId, itemId, field.id, sent, this.#o);
2769
2801
  const known = cache.known.get(itemId);
2770
2802
  if (known === void 0) return;
2771
- if (value === null) delete known.values[name];
2772
- else known.values[name] = value;
2803
+ if (value === null) delete known.values[field.name];
2804
+ else known.values[field.name] = value;
2773
2805
  }
2774
2806
  async apply(board, step2) {
2775
2807
  if (step2.kind === "unchanged") return null;
@@ -2903,10 +2935,10 @@ var GitHubBoards = class {
2903
2935
  [COLLECTION_FIELD, want.type],
2904
2936
  [STATUS_FIELD, want.status],
2905
2937
  ...want.statusField === null ? [] : [[want.statusField, want.status]],
2906
- ["Sessions", want.sessions]
2938
+ [SESSION_HISTORY, want.sessions]
2907
2939
  ];
2908
2940
  for (const [name, value] of wanted)
2909
- if ((values2[name] ?? null) !== value)
2941
+ if (valueOf(values2, name) !== value)
2910
2942
  await this.#set(board, id, name, value);
2911
2943
  }
2912
2944
  async #known(board, id) {
@@ -2932,7 +2964,7 @@ var GitHubBoards = class {
2932
2964
  async mark(board, itemIds, session) {
2933
2965
  for (const id of itemIds) {
2934
2966
  await this.#set(board, id, "Agent", session === null ? null : WORKING);
2935
- await this.#set(board, id, "Session", session);
2967
+ await this.#set(board, id, WORKING_SESSION, session);
2936
2968
  }
2937
2969
  }
2938
2970
  };
@@ -3681,8 +3713,10 @@ Writing:
3681
3713
  \`org/\` it affects.
3682
3714
  - An ADR it replaces is named in Context. That one becomes \`Superseded\`,
3683
3715
  with \`superseded_by:\`, only once the new ADR is \`Accepted\`.
3684
- - Add \`\${CLAUDE_SESSION_ID}\` at the end of \`sessions:\` in the front matter,
3685
- unless it is already there.
3716
+ - Add \`{ id: \${CLAUDE_SESSION_ID}, agent: <model> }\` at the end of
3717
+ \`sessions:\` in the front matter, unless that id is already there.
3718
+ \`<model>\` is the model you run as, as Claude Code names it, after
3719
+ \`Claude\`: for example \`Claude Opus 5.5\`.
3686
3720
  - The rness hook checks every edit under \`${rness}/\`: fix what it reports.
3687
3721
 
3688
3722
  After writing: give the path and the Decision section, and say the ADR
@@ -3720,8 +3754,10 @@ Writing:
3720
3754
  - What was checked in this session (a document read, a command run) is
3721
3755
  written as verified, with the date; everything else as a proposal or an
3722
3756
  open question.
3723
- - Add \`\${CLAUDE_SESSION_ID}\` at the end of \`sessions:\` in the front matter,
3724
- unless it is already there.
3757
+ - Add \`{ id: \${CLAUDE_SESSION_ID}, agent: <model> }\` at the end of
3758
+ \`sessions:\` in the front matter, unless that id is already there.
3759
+ \`<model>\` is the model you run as, as Claude Code names it, after
3760
+ \`Claude\`: for example \`Claude Opus 5.5\`.
3725
3761
  - The rness hook checks every edit under \`${rness}/\`: fix what it reports.
3726
3762
 
3727
3763
  After writing: give the path and the summary. It stays \`Draft\` until the
@@ -3762,8 +3798,10 @@ Writing:
3762
3798
  repository has one.
3763
3799
  - Where the plan decides something the specification leaves open, a
3764
3800
  section says so.
3765
- - Add \`\${CLAUDE_SESSION_ID}\` at the end of \`sessions:\` in the front matter,
3766
- unless it is already there.
3801
+ - Add \`{ id: \${CLAUDE_SESSION_ID}, agent: <model> }\` at the end of
3802
+ \`sessions:\` in the front matter, unless that id is already there.
3803
+ \`<model>\` is the model you run as, as Claude Code names it, after
3804
+ \`Claude\`: for example \`Claude Opus 5.5\`.
3767
3805
  - The rness hook checks every edit under \`${rness}/\`: fix what it reports.
3768
3806
 
3769
3807
  After writing: give the path and the list of tasks. It becomes \`Ready\` when
@@ -3793,8 +3831,11 @@ Arguments: \`$ARGUMENTS\`.
3793
3831
  ran, what it showed, what could not run and why;
3794
3832
  - the specification: \`Implemented\` once every plan of it is
3795
3833
  \`Completed\`; \`updated\` today;
3796
- - the plan and the specification: add \`\${CLAUDE_SESSION_ID}\` at the end
3797
- of \`sessions:\` in their front matter, unless it is already there;
3834
+ - the plan and the specification: add
3835
+ \`{ id: \${CLAUDE_SESSION_ID}, agent: <model> }\` at the end of
3836
+ \`sessions:\` in their front matter, unless that id is already there;
3837
+ \`<model>\` is the model you run as, as Claude Code names it, after
3838
+ \`Claude\`: for example \`Claude Opus 5.5\`;
3798
3839
  - the smallest set of documents the work makes inaccurate: \`${rness}/docs/\`,
3799
3840
  the READMEs of the repositories it changed.
3800
3841
  6. A task not proven: the plan stays \`In progress\` \u2014 or \`Blocked\`, the
@@ -7931,7 +7972,9 @@ async function declaredBoard(c) {
7931
7972
  }
7932
7973
  var plural = (n) => `${n} item${n === 1 ? "" : "s"}`;
7933
7974
  var eachAdded = (ui, added) => {
7934
- for (const a of added) ui.line("added", a);
7975
+ for (const a of added)
7976
+ if (a.startsWith("renamed ")) ui.line("renamed", a.slice("renamed ".length));
7977
+ else ui.line("added", a);
7935
7978
  };
7936
7979
  var createdByKind = (ui, added) => {
7937
7980
  for (const kind of ["field", "option", "view"]) {
@@ -8723,4 +8766,4 @@ export {
8723
8766
  OWN_COMMANDS,
8724
8767
  catchUp
8725
8768
  };
8726
- //# sourceMappingURL=chunk-7IVHL744.js.map
8769
+ //# sourceMappingURL=chunk-ABCO6D6B.js.map