@sylad/cadence 0.14.0 → 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/dist/repos.js ADDED
@@ -0,0 +1,72 @@
1
+ import { existsSync, statSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { lotWork } from './audit.js';
4
+ import { gitRoot } from './git.js';
5
+ /**
6
+ * Résout les dépôts voisins d'un lot depuis le dossier du projet (la racine de son dépôt). Chaque chemin doit exister et
7
+ * être dans un dépôt git ; un doublon, ou le dépôt du projet lui-même, n'est compté qu'une fois (le second est ignoré sans bruit).
8
+ * Les chemins qui ne vont pas sont rendus en `problems`, à refuser avant d'agir.
9
+ */
10
+ export function resolveLotRepos(base, lot) {
11
+ const repos = [];
12
+ const failures = [];
13
+ const own = gitRoot(base) ?? resolve(base);
14
+ for (const { path: rel, cite } of lot.repos ?? []) {
15
+ const dir = resolve(base, rel);
16
+ if (!existsSync(dir) || !statSync(dir).isDirectory()) {
17
+ failures.push({ rel, why: `dossier introuvable (${dir})` });
18
+ continue;
19
+ }
20
+ const root = gitRoot(dir);
21
+ if (!root) {
22
+ failures.push({ rel, why: `${dir} n'est pas dans un dépôt git` });
23
+ continue;
24
+ }
25
+ if (root === own || repos.some((r) => r.path === root))
26
+ continue;
27
+ repos.push({ rel, path: root, ...(cite ? { cite } : {}) });
28
+ }
29
+ return { repos, failures, problems: failures.map((f) => `dépôt voisin ${f.rel} : ${f.why}`) };
30
+ }
31
+ /**
32
+ * Commits à relire du lot dans un dépôt voisin, du plus récent au plus ancien : ceux qui citent le lot, selon les références
33
+ * du plan, et tombent dans la période du lot (de son démarrage à sa fin). Rien n'est déduit du dépôt ni du nom du projet. Pour un
34
+ * voisin partagé entre projets, le lot déclare `cite` : le commit doit en plus contenir cette chaîne (sous-chaîne, sans tenir
35
+ * compte de la casse, dans le sujet et le corps). Sans `cite`, les commits d'une autre application qui citent le même id comptent.
36
+ */
37
+ export function repoWork(plan, repo, lotId) {
38
+ const lot = plan.lots().find((l) => l.id === lotId);
39
+ const inPeriod = lotWork(plan, repo.path, lotId).filter((c) => (!lot?.started || c.day >= lot.started) && (!lot?.finished || c.day <= lot.finished));
40
+ if (!repo.cite)
41
+ return inPeriod;
42
+ const needle = repo.cite.toLowerCase();
43
+ return inPeriod.filter((c) => `${c.subject}\n${c.body}`.toLowerCase().includes(needle));
44
+ }
45
+ /** Sha du dernier commit du lot de chaque dépôt voisin (null : aucun), sous le chemin déclaré — ce qu'un verdict de revue enregistre. */
46
+ export function repoShas(plan, repos, lotId) {
47
+ return Object.fromEntries(repos.map((r) => [r.rel, repoWork(plan, r, lotId)[0]?.sha ?? null]));
48
+ }
49
+ const short = (c) => `${c.sha.slice(0, 7)} ${c.subject}`;
50
+ /**
51
+ * Lignes des commits du lot dans ses dépôts voisins, pour `raf commits` et `raf show` : une section par dépôt, du plus
52
+ * ancien au plus récent comme la liste du projet. Un dépôt introuvable est dit, il ne fait pas échouer la lecture.
53
+ */
54
+ export function repoSections(plan, base, lot, indent = '') {
55
+ const { repos, failures } = resolveLotRepos(base, lot);
56
+ const lines = [];
57
+ for (const { path: rel } of lot.repos ?? []) {
58
+ const found = repos.find((r) => r.rel === rel);
59
+ if (!found) {
60
+ const failed = failures.find((f) => f.rel === rel);
61
+ if (failed)
62
+ lines.push(`${indent}dépôt ${rel} : introuvable (${failed.why})`);
63
+ continue;
64
+ }
65
+ const commits = repoWork(plan, found, lot.id).reverse();
66
+ if (commits.length === 0)
67
+ lines.push(`${indent}dépôt ${rel} : aucun commit du lot`);
68
+ else
69
+ lines.push(`${indent}dépôt ${rel} :`, ...commits.map((c) => `${indent} ${short(c)}`));
70
+ }
71
+ return lines;
72
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sylad/cadence",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "description": "A small, repo-native working method: a versioned plan linked to your commits, a changelog with screenshots, session rituals and deliveries proven by their effect.",
5
5
  "license": "MIT",
6
6
  "author": "Sylvain Ladoire",
@@ -8,12 +8,13 @@ description: Close a work session on a repository that uses cadence — plan hyg
8
8
  ## Where to run
9
9
 
10
10
  Every `cadence` / `raf` command works on the git repository of the current directory. When the
11
- session runs from a parent folder that holds several projects (not itself a repository), run each
12
- command inside the project concerned: `cd <project> && cadence …`. The projects are the sub-folders
13
- that contain `docs/plan/raf.yaml`, or a `cadence.yaml` with a `plan:` key.
11
+ session runs from a parent folder that holds several projects (not itself a repository), run
12
+ `cadence session close --all` there (`--depth 2` for projects one folder deeper): one "## project"
13
+ section per sub-folder that contains `docs/plan/raf.yaml`, or a `cadence.yaml` with a `plan:` key.
14
+ Other commands (`raf …`, `cadence deliver`) still run inside the project concerned: `cd <project> && cadence …`.
14
15
 
15
- With no project named, run `cadence session close` in each project touched during the session
16
- (`git log --since` or `git status` tell which) and close each one.
16
+ With no project named, run `cadence session close --all` from the parent folder, or `cadence session close` in each project touched during the session
17
+ (`git log --since` or `git status` tell which), and close each one.
17
18
 
18
19
  ## Steps
19
20
 
@@ -12,11 +12,12 @@ proposes, and stops.
12
12
  ## Where to run
13
13
 
14
14
  Every `cadence` / `raf` command works on the git repository of the current directory. When the
15
- session runs from a parent folder that holds several projects (not itself a repository), run each
16
- command inside the project concerned: `cd <project> && cadence …`. The projects are the sub-folders
17
- that contain `docs/plan/raf.yaml`, or a `cadence.yaml` with a `plan:` key.
15
+ session runs from a parent folder that holds several projects (not itself a repository), run
16
+ `cadence session start --all` there (`--depth 2` for projects one folder deeper): one "## project"
17
+ section per sub-folder that contains `docs/plan/raf.yaml`, or a `cadence.yaml` with a `plan:` key.
18
+ Other commands (`raf …`, `cadence deliver`) still run inside the project concerned: `cd <project> && cadence …`.
18
19
 
19
- With no project named, run `cadence session start` in **each** project that has a plan and report
20
+ With no project named, run `cadence session start --all` from the parent folder (or `cadence session start` in **each** project that has a plan) and report
20
21
  one or two lines per project (in progress, drift, notes left at the last close), then propose the
21
22
  three most useful items across projects and wait. With a project named, work in that one only.
22
23
 
@@ -1,5 +1,6 @@
1
1
  Work in `{{chemin}}` on lot `{{lot}}` — "{{titre}}" — of its plan.
2
2
  A fresh review found only minor findings: the lot is compliant, and this is the one pass that treats them.
3
+ {{repos}}
3
4
  Commits of the lot so far:
4
5
  {{commits}}
5
6
 
@@ -1,5 +1,6 @@
1
1
  Work in `{{chemin}}` on lot `{{lot}}` — "{{titre}}" — of its plan. A fresh review of the commits
2
2
  of this lot found the defects below; fix them, and nothing else.
3
+ {{repos}}
3
4
  Commits of the lot so far:
4
5
  {{commits}}
5
6
 
@@ -1,6 +1,7 @@
1
1
  Work in `{{chemin}}` on lot `{{lot}}` — "{{titre}}" — of its plan
2
2
  (`docs/plan/raf.yaml`, or the file named by `plan:` in `cadence.yaml`; read the lot, its notes and sub-tasks, and the project's CLAUDE.md first).
3
3
  Goal: {{objectif}}
4
+ {{repos}}
4
5
  Rules: test first; commit each sub-part as soon as its tests pass, with explicit paths (never
5
6
  `git add -A` or `commit -a`), and a message that cites the lot (`feat({{lot}}): …`); run the project's
6
7
  full test suite and build before reporting; do not push, deliver, run `raf done`, `raf ux` or
@@ -1,6 +1,7 @@
1
1
  Pre-check for lot `{{lot}}` — "{{titre}}" — of the repository `{{chemin}}`, as the read-only pre-check reader.
2
2
  Question: is the deliverable of this lot ALREADY in the repository (done by another lot, or by a correction)?
3
3
  Goal of the lot: {{objectif}}
4
+ {{repos}}
4
5
  Read the lot, its notes and sub-tasks in the plan (`docs/plan/raf.yaml`, or the file named by `plan:` in `cadence.yaml`),
5
6
  then look for the deliverable in the code and tests (`git log`, `grep`, reading the files the lot names). Do not
6
7
  implement anything and do not run the full test suite: this is a quick look.
@@ -4,6 +4,7 @@ treated them. Check that the minor findings fixed are fixed, that the fixes brok
4
4
  rest of the lot is still sound: read the diff yourself from the commits that cite the lot
5
5
  (`raf commits {{lot}}`, or `git log`), run the checks, report real defects only. A new minor finding
6
6
  is reported, not a reason to ask for another pass. This is a code review only.
7
+ {{repos}}
7
8
  {{checks}}
8
9
  {{choix}}
9
10
  A proposed sub-task describes an observable bug (a wrong output, a crash, a measured regression); any other minor finding stays a note of this lot, not a sub-task.
@@ -2,6 +2,7 @@ Review lot `{{lot}}` — "{{titre}}" — of the repository `{{chemin}}`, followi
2
2
  This lot is small: one single pass covers the code review AND the usability review.
3
3
  You are given the repository path and the lot id only: read the diff yourself from the commits that
4
4
  cite the lot (`raf commits {{lot}}`, or `git log`), run the checks, report real defects only.
5
+ {{repos}}
5
6
  {{ux}}
6
7
  {{checks}}
7
8
  {{choix}}
@@ -1,6 +1,7 @@
1
1
  Review lot `{{lot}}` — "{{titre}}" — of the repository `{{chemin}}`, following your agent instructions.
2
2
  You are given the repository path and the lot id only: read the diff yourself from the commits that
3
3
  cite the lot (`raf commits {{lot}}`, or `git log`), run the checks, report real defects only.
4
+ {{repos}}
4
5
  {{checks}}
5
6
  {{choix}}
6
7
  A proposed sub-task describes an observable bug (a wrong output, a crash, a measured regression); any other minor finding stays a note of this lot, not a sub-task.