@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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +100 -5
- package/bin/cadence.js +1 -0
- package/dist/audit.js +1 -1
- package/dist/cli.js +132 -14
- package/dist/config.js +27 -0
- package/dist/git.js +38 -0
- package/dist/hook.js +99 -4
- package/dist/lead.js +36 -21
- package/dist/orchestrate/briefs.js +21 -1
- package/dist/orchestrate/command.js +31 -18
- package/dist/orchestrate/cycle.js +76 -44
- package/dist/orchestrate/pool.js +20 -6
- package/dist/orchestrate/state.js +4 -0
- package/dist/plan.js +26 -3
- package/dist/repos.js +72 -0
- package/package.json +1 -1
- package/skills/session-close/SKILL.md +6 -5
- package/skills/session-start/SKILL.md +5 -4
- package/templates/orchestrate/fix-minors.md +1 -0
- package/templates/orchestrate/fix.md +1 -0
- package/templates/orchestrate/implement.md +1 -0
- package/templates/orchestrate/precheck.md +1 -0
- package/templates/orchestrate/review-recheck.md +1 -0
- package/templates/orchestrate/review-small.md +1 -0
- package/templates/orchestrate/review.md +1 -0
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.
|
|
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
|
|
12
|
-
|
|
13
|
-
that
|
|
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
|
|
16
|
-
|
|
17
|
-
that
|
|
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,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.
|