@roomi-fields/grillhouse 0.0.0-stage → 0.23.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/plugin.json +9 -0
- package/METACADRE.md +41 -0
- package/agents/developpeur.md +10 -0
- package/agents/explorateur.md +9 -0
- package/agents/questionneur.md +11 -0
- package/agents/referent-technique.md +9 -0
- package/agents/regulateur.md +11 -0
- package/agents/relecteur.md +9 -0
- package/agents/testwriter.md +10 -0
- package/bin/grillhouse.mjs +125 -0
- package/cadre/templates/projet/.claude/settings.json +30 -0
- package/cadre/templates/projet/.editorconfig +47 -0
- package/cadre/templates/projet/.env.example +57 -0
- package/cadre/templates/projet/.eslintrc.cjs +56 -0
- package/cadre/templates/projet/.github/workflows/ci.yml +66 -0
- package/cadre/templates/projet/.mcp.json +13 -0
- package/cadre/templates/projet/.prettierrc +11 -0
- package/cadre/templates/projet/CHANGELOG.md +61 -0
- package/cadre/templates/projet/CLAUDE.md +46 -0
- package/cadre/templates/projet/CONTRIBUTING.md +243 -0
- package/cadre/templates/projet/CREDITS.md +41 -0
- package/cadre/templates/projet/README.md +152 -0
- package/cadre/templates/projet/_gitignore +91 -0
- package/cadre/templates/projet/_npmignore +46 -0
- package/cadre/templates/projet/deployment/README.md +98 -0
- package/cadre/templates/projet/deployment/docs/01-INSTALL.md +145 -0
- package/cadre/templates/projet/deployment/docs/02-CONFIGURATION.md +117 -0
- package/cadre/templates/projet/deployment/docs/03-API.md +264 -0
- package/cadre/templates/projet/deployment/docs/04-TROUBLESHOOTING.md +262 -0
- package/cadre/templates/projet/deployment/scripts/install.ps1 +100 -0
- package/cadre/templates/projet/deployment/scripts/start.ps1 +61 -0
- package/cadre/templates/projet/deployment/scripts/stop.ps1 +37 -0
- package/cadre/templates/projet/deployment/scripts/test.ps1 +118 -0
- package/cadre/templates/projet/docs/agents/issue-tracker.md +44 -0
- package/cadre/templates/projet/ecosystem.config.cjs +73 -0
- package/cadre/templates/projet/package.json +90 -0
- package/cadre/templates/projet/pitmaster/SUIVI.md +22 -0
- package/cadre/templates/projet/src/config.ts +68 -0
- package/cadre/templates/projet/src/errors.ts +102 -0
- package/cadre/templates/projet/src/index.ts +46 -0
- package/cadre/templates/projet/src/services/.gitkeep +8 -0
- package/cadre/templates/projet/src/types/index.ts +24 -0
- package/cadre/templates/projet/src/utils/logger.ts +106 -0
- package/cadre/templates/projet/tests/integration/.gitkeep +7 -0
- package/cadre/templates/projet/tests/unit/config.spec.ts +68 -0
- package/cadre/templates/projet/tests/unit/errors.spec.ts +132 -0
- package/cadre/templates/projet/tests/unit/types.spec.ts +73 -0
- package/cadre/templates/projet/tsconfig.eslint.json +9 -0
- package/cadre/templates/projet/tsconfig.json +41 -0
- package/cadre/templates/projet/tsdoc.json +6 -0
- package/cadre/templates/projet/vitest.config.ts +44 -0
- package/cadre/templates/turbo/paquets.json +29 -0
- package/cadre/templates/turbo/sans-paquets.json +28 -0
- package/charte.md +107 -0
- package/docs/ARCHITECTURE.md +90 -0
- package/hooks/crochet.mjs +33 -0
- package/hooks/hooks.json +58 -0
- package/hooks/register.tsx +558 -0
- package/package.json +75 -4
- package/scripts/avancement.mjs +244 -0
- package/scripts/bilan.mjs +523 -0
- package/scripts/branche-de-nuit.mjs +59 -0
- package/scripts/cadre.mjs +109 -0
- package/scripts/circuit.mjs +4375 -0
- package/scripts/code-mort.mjs +371 -0
- package/scripts/composants-affectes.mjs +598 -0
- package/scripts/consommateurs-arbitres.mjs +192 -0
- package/scripts/consommateurs.mjs +310 -0
- package/scripts/crochet.mjs +24 -0
- package/scripts/crochets.mjs +135 -0
- package/scripts/dernier-vert.mjs +208 -0
- package/scripts/dette.mjs +181 -0
- package/scripts/droits.mjs +354 -0
- package/scripts/enveloppe/codes.mjs +17 -0
- package/scripts/enveloppe/composant.mjs +11 -0
- package/scripts/enveloppe/enveloppe.mjs +628 -0
- package/scripts/enveloppe/lancer.sh +311 -0
- package/scripts/etapes.mjs +323 -0
- package/scripts/etat-du-circuit.mjs +104 -0
- package/scripts/frontieres.mjs +456 -0
- package/scripts/gardes-du-cadre.mjs +72 -0
- package/scripts/greffons.mjs +338 -0
- package/scripts/grillhouse-maj.mjs +514 -0
- package/scripts/index-interfaces.mjs +293 -0
- package/scripts/init.mjs +117 -0
- package/scripts/integration/file-attente.mjs +61 -0
- package/scripts/integration/file.mjs +494 -0
- package/scripts/integration/integrer.mjs +381 -0
- package/scripts/integration/rejeu.mjs +139 -0
- package/scripts/integration/verdict.mjs +13 -0
- package/scripts/interfaces-contre-code.mjs +547 -0
- package/scripts/ligne-etat/defaut.sh +110 -0
- package/scripts/ligne-etat/ligne-etat.mjs +93 -0
- package/scripts/migrations/0.23.0-charte-importee.mjs +47 -0
- package/scripts/migrations/0.23.0-config-vitest.mjs +105 -0
- package/scripts/migrations/0.23.0-crochets-de-seance.mjs +55 -0
- package/scripts/migrations/0.23.0-marche-du-projet.mjs +82 -0
- package/scripts/migrations.mjs +43 -0
- package/scripts/nuit.sh +269 -0
- package/scripts/paquets.mjs +79 -0
- package/scripts/poussee-cles.mjs +46 -0
- package/scripts/preparation.mjs +84 -0
- package/scripts/references-par-les-types.mjs +420 -0
- package/scripts/registre.mjs +336 -0
- package/scripts/resultats.mjs +580 -0
- package/scripts/resumes.mjs +57 -0
- package/scripts/retirer-copie.sh +127 -0
- package/scripts/session-start.sh +203 -0
- package/scripts/sortie.mjs +155 -0
- package/scripts/sous-modules.sh +316 -0
- package/scripts/structure-guard.sh +27 -0
- package/scripts/superviseur.mjs +102 -0
- package/scripts/tableau.mjs +1886 -0
- package/scripts/tests.mjs +236 -0
- package/scripts/ticket.sh +23 -0
- package/scripts/turbo-des-paquets.mjs +899 -0
- package/scripts/un-commit-par-ticket.mjs +212 -0
- package/scripts/verifier.mjs +469 -0
- package/scripts/verrou-de-fichier.mjs +130 -0
- package/scripts/verrou-de-machine.mjs +211 -0
- package/scripts/verrous/commande.mjs +180 -0
- package/scripts/verrous/ticket-du-sous-agent.mjs +39 -0
- package/scripts/verrous/verrou.mjs +165 -0
- package/scripts/vitest-config/avancement.mjs +39 -0
- package/scripts/vitest-config/avancement.reporter.mjs +56 -0
- package/scripts/vitest-config/base-de-passe.mjs +128 -0
- package/scripts/vitest-config/base.d.ts +6 -0
- package/scripts/vitest-config/base.mjs +87 -0
- package/scripts/vitest-config/changements.mjs +173 -0
- package/scripts/vitest-config/cibles.mjs +207 -0
- package/scripts/vitest-config/duree.reporter.mjs +98 -0
- package/scripts/vitest-config/machine.setup.mjs +14 -0
- package/scripts/vitest-config/mesure.d.ts +6 -0
- package/scripts/vitest-config/mesure.mjs +13 -0
- package/scripts/vitest-config/mesure.setup.mjs +12 -0
- package/scripts/vitest-config/pression.mjs +90 -0
- package/scripts/vitest-config/resultats.mjs +23 -0
- package/scripts/vitest-config/resultats.setup.mjs +19 -0
- package/scripts/vitest.nuit.config.mjs +26 -0
- package/skills/developpeur/SKILL.md +175 -0
- package/skills/explorateur/SKILL.md +84 -0
- package/skills/grill/SKILL.md +238 -0
- package/skills/grill/references/releve-structurel.md +38 -0
- package/skills/mesure/SKILL.md +168 -0
- package/skills/pitmaster/SKILL.md +382 -0
- package/skills/pitmaster/references/cadre.md +119 -0
- package/skills/pitmaster/references/consigne-agent.md +308 -0
- package/skills/pitmaster/references/erreurs.md +25 -0
- package/skills/pitmaster/references/tour.md +124 -0
- package/skills/questionneur/SKILL.md +64 -0
- package/skills/redacteur/SKILL.md +84 -0
- package/skills/redacteur/references/documents-d-un-composant.md +105 -0
- package/skills/referent-technique/SKILL.md +145 -0
- package/skills/regulateur/SKILL.md +220 -0
- package/skills/release/SKILL.md +134 -0
- package/skills/release/scripts/update-version.cjs +92 -0
- package/skills/relecteur/SKILL.md +152 -0
- package/skills/relecteur/references/LICENSE-MIT +30 -0
- package/skills/relecteur/references/SOURCE.md +8 -0
- package/skills/relecteur/references/claims-check.md +14 -0
- package/skills/relecteur/references/deletion-check.md +14 -0
- package/skills/relecteur/references/edge-case-hunter.md +80 -0
- package/skills/relecteur/references/verification-gap.md +113 -0
- package/skills/testwriter/SKILL.md +187 -0
- package/types/index.d.ts +56 -0
- package/README.md +0 -3
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The rights and the context of each role session the circuit launches, from one source (ROLES):
|
|
3
|
+
// the testwriter and the developpeur in the envelope of their component (scripts/enveloppe/lancer.sh),
|
|
4
|
+
// the reviewer, the regulator, the questionneur and the technical referent out of it
|
|
5
|
+
// (scripts/circuit.mjs). As a task of CI receives its
|
|
6
|
+
// rights from its steps and runs on an image of its own, not on the workstation of its author
|
|
7
|
+
// (GitHub Actions `permissions:` per job, the hermetic actions of Bazel), a session receives the
|
|
8
|
+
// rights the commands of its skill name, and the context its work reads.
|
|
9
|
+
//
|
|
10
|
+
// npx grillhouse droits <rôle> --racine <arbre principal> --copie <copie> --ticket <ticket>
|
|
11
|
+
// [--journal <fichier> --preuves <motif>]
|
|
12
|
+
//
|
|
13
|
+
// prints the options of claude for that session, one per line (`optionsDuRole`):
|
|
14
|
+
//
|
|
15
|
+
// - `--setting-sources project,local`: the user's own configuration stays out (their CLAUDE.md,
|
|
16
|
+
// their hooks, the skills of their account, their servers, their environment); the project's
|
|
17
|
+
// settings and charter, and the frame's plugin it enables (agents, skills, common charter,
|
|
18
|
+
// hooks), stay in.
|
|
19
|
+
// - `--settings <json>` (the settings of the role, on the command line: no file the session could
|
|
20
|
+
// change): its permissions (`allow`, the commands its skill names; `deny`, the change of its
|
|
21
|
+
// author at the ticket, AUTEUR_FIXE, for a role that writes the editing by script, the test
|
|
22
|
+
// tool run directly and the reading again of the ticket its instruction carries, and for a role
|
|
23
|
+
// that writes nothing at the ticket, the questionneur and the regulator, every write of bd,
|
|
24
|
+
// ECRIRE_AU_TICKET); the
|
|
25
|
+
// automatic memory off; the skills of Claude Code off (`disableBundledSkills`, and the few it keeps,
|
|
26
|
+
// INTEGREES), and the project's own skills (`.claude/skills/` of the copy) off
|
|
27
|
+
// (`skillOverrides`); every plugin the project enables off (`enabledPlugins`: their skills,
|
|
28
|
+
// hooks and servers are not the role's), save the frame's (`grillhouse@…`), which carries the
|
|
29
|
+
// role's agent, its skills and the frame's hooks: Claude Code applies no `skillOverrides` to the
|
|
30
|
+
// skills of a plugin, and the role's agent preloads its own (`skills` of its definition);
|
|
31
|
+
// the background tasks off (`env`, SANS_TACHE_DE_FOND: a role waits in the foreground for what
|
|
32
|
+
// it launches, and its session ends with its sheet); for a role that writes, its locks as hooks (PreToolUse: verrous/verrou.mjs on the tools of
|
|
33
|
+
// writing, verrous/commande.mjs on Bash), since the hooks of an agent's definition do not run in
|
|
34
|
+
// a folder Claude Code has not trusted, as the copy of a ticket.
|
|
35
|
+
// - `--tools <list>`: the tools its work uses; Edit and Write for a role that writes alone, the
|
|
36
|
+
// tool search for a role whose index Claude Code defers.
|
|
37
|
+
// - `--strict-mcp-config --mcp-config <json>`: the servers of the index (codegraph, rtfm) for a
|
|
38
|
+
// role that uses it, read in the project's `.mcp.json` and in the manifests of the plugins it
|
|
39
|
+
// enables, at their installed path (`~/.claude/plugins/installed_plugins.json`, the project's
|
|
40
|
+
// entry first, else the user's); none for the others.
|
|
41
|
+
//
|
|
42
|
+
// The skills' commands and the permissions answer one another: tests/unit/droits.spec.ts fails on a
|
|
43
|
+
// command a skill names that no permission covers, and on a permission no command names.
|
|
44
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
45
|
+
import os from 'node:os';
|
|
46
|
+
import path from 'node:path';
|
|
47
|
+
import { pathToFileURL } from 'node:url';
|
|
48
|
+
|
|
49
|
+
// The variable in which bd reads the author of a comment (`bd --help`: « default: $BEADS_ACTOR,
|
|
50
|
+
// git user.name, $USER »).
|
|
51
|
+
const ACTEUR = 'BEADS_ACTOR';
|
|
52
|
+
// The rules that refuse a session the change of its author at the ticket: bd's options `--actor`
|
|
53
|
+
// and `-a`/`--author`, and the variable itself.
|
|
54
|
+
export const AUTEUR_FIXE = [
|
|
55
|
+
'Bash(bd *--actor*)',
|
|
56
|
+
'Bash(bd *--author*)',
|
|
57
|
+
'Bash(bd * -a*)',
|
|
58
|
+
`Bash(*${ACTEUR}*)`,
|
|
59
|
+
];
|
|
60
|
+
// What a role that writes may not run: a file is edited by its tools of writing, which its lock
|
|
61
|
+
// judges, and the tests run by `npm test` (charter, « Les tests se lancent par npm test »).
|
|
62
|
+
const ECRIRE_PAR_SCRIPT = [
|
|
63
|
+
'Bash(python *)',
|
|
64
|
+
'Bash(python3 *)',
|
|
65
|
+
'Bash(sed -i*)',
|
|
66
|
+
'Bash(sed * -i*)',
|
|
67
|
+
'Bash(perl -i*)',
|
|
68
|
+
'Bash(perl -pi*)',
|
|
69
|
+
'Bash(perl * -i*)',
|
|
70
|
+
'Bash(perl * -pi*)',
|
|
71
|
+
];
|
|
72
|
+
// What a role that writes nothing at the ticket may not run: the circuit writes its exchange there,
|
|
73
|
+
// from its sheet.
|
|
74
|
+
const ECRIRE_AU_TICKET = [
|
|
75
|
+
'Bash(bd comments add*)',
|
|
76
|
+
'Bash(bd update*)',
|
|
77
|
+
'Bash(bd create*)',
|
|
78
|
+
'Bash(bd close*)',
|
|
79
|
+
'Bash(bd reopen*)',
|
|
80
|
+
'Bash(bd delete*)',
|
|
81
|
+
'Bash(npx grillhouse ticket*)',
|
|
82
|
+
];
|
|
83
|
+
// The variable that turns off the background tasks of Claude Code (the Bash tool's
|
|
84
|
+
// `run_in_background`, the background agents): `claude -p` waits for them before it ends, so a
|
|
85
|
+
// session ends with its sheet only without them.
|
|
86
|
+
const SANS_TACHE_DE_FOND = { CLAUDE_CODE_DISABLE_BACKGROUND_TASKS: '1' };
|
|
87
|
+
|
|
88
|
+
// The reads of git in the copy, by its path (`git -C <copie> …`), which Claude Code does not let
|
|
89
|
+
// through without a rule, as it does `git status` in the working directory.
|
|
90
|
+
const LIRE_GIT = [
|
|
91
|
+
'Bash(git -C * status*)',
|
|
92
|
+
'Bash(git -C * diff*)',
|
|
93
|
+
'Bash(git -C * log*)',
|
|
94
|
+
'Bash(git -C * ls-files*)',
|
|
95
|
+
'Bash(git -C * grep*)',
|
|
96
|
+
];
|
|
97
|
+
const TEST_DIRECT = [
|
|
98
|
+
'Bash(vitest*)',
|
|
99
|
+
'Bash(npx vitest*)',
|
|
100
|
+
'Bash(npx * vitest*)',
|
|
101
|
+
'Bash(npm exec vitest*)',
|
|
102
|
+
'Bash(npm exec * vitest*)',
|
|
103
|
+
'Bash(node_modules/.bin/vitest*)',
|
|
104
|
+
];
|
|
105
|
+
// The skills Claude Code keeps listed when its own are off (`disableBundledSkills`), measured on
|
|
106
|
+
// Claude Code 2.1.305.
|
|
107
|
+
const INTEGREES = ['design', 'doctor', 'plugin-authoring'];
|
|
108
|
+
// The frame's plugin, by the start of its identifier (`grillhouse@<place de marché>`).
|
|
109
|
+
const GREFFON_DU_CADRE = 'grillhouse@';
|
|
110
|
+
// The servers of the index (charter, « L'index d'abord »).
|
|
111
|
+
const INDEX = ['codegraph', 'rtfm'];
|
|
112
|
+
// The tools of every role, and of a role that writes.
|
|
113
|
+
const LIRE = ['Bash', 'Read', 'Skill'];
|
|
114
|
+
const ECRIRE = ['Edit', 'Write'];
|
|
115
|
+
|
|
116
|
+
// Each role the circuit launches: whether it writes (files, `ecrit`; the ticket, unless
|
|
117
|
+
// `ecritAuTicket` is false), whether it uses the index, and the commands its skill names (the
|
|
118
|
+
// frame's plugin, `mods/grillhouse/skills/<rôle>/`), as permission rules.
|
|
119
|
+
export const ROLES = {
|
|
120
|
+
testwriter: {
|
|
121
|
+
ecrit: true,
|
|
122
|
+
commandes: [
|
|
123
|
+
'Bash(bd update * --claim)',
|
|
124
|
+
'Bash(bd comments add *)',
|
|
125
|
+
'Bash(npm test *)',
|
|
126
|
+
// The removal of a file of its tests, by a script of its temporary directory.
|
|
127
|
+
'Bash(node $TMPDIR/*)',
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
developpeur: {
|
|
131
|
+
ecrit: true,
|
|
132
|
+
commandes: [
|
|
133
|
+
'Bash(bd update * --claim)',
|
|
134
|
+
'Bash(bd update * --notes*)',
|
|
135
|
+
'Bash(bd comments add *)',
|
|
136
|
+
'Bash(git -C * status*)',
|
|
137
|
+
'Bash(git -C * diff*)',
|
|
138
|
+
'Bash(npm test *)',
|
|
139
|
+
'Bash(npm run api*)',
|
|
140
|
+
],
|
|
141
|
+
},
|
|
142
|
+
relecteur: {
|
|
143
|
+
index: true,
|
|
144
|
+
commandes: [
|
|
145
|
+
...LIRE_GIT,
|
|
146
|
+
'Bash(npx grillhouse index-interfaces --publie *)',
|
|
147
|
+
'Bash(npm test *)',
|
|
148
|
+
'Bash(npm run verifier -- --gardes*)',
|
|
149
|
+
'Bash(codegraph explore *)',
|
|
150
|
+
'mcp__codegraph__codegraph_explore',
|
|
151
|
+
'mcp__rtfm__rtfm_search',
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
// It writes nothing at the ticket: the circuit writes its decision, its arbitrage and the
|
|
155
|
+
// criterion it adds, from its sheet. It reads the circuit's state by its command, the ticket's
|
|
156
|
+
// log and its proofs by their paths, a precedent by bd, the copy by git.
|
|
157
|
+
regulateur: {
|
|
158
|
+
lit: ['journal', 'preuves'],
|
|
159
|
+
ecritAuTicket: false,
|
|
160
|
+
commandes: [
|
|
161
|
+
'Bash(npx grillhouse etat-du-circuit *)',
|
|
162
|
+
'Bash(bd search *)',
|
|
163
|
+
'Bash(bd comments *)',
|
|
164
|
+
...LIRE_GIT,
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
// It asks, and decides nothing: it reads the proposal its instruction carries and the code by
|
|
168
|
+
// the index; the circuit writes its questions at the ticket.
|
|
169
|
+
questionneur: {
|
|
170
|
+
index: true,
|
|
171
|
+
ecritAuTicket: false,
|
|
172
|
+
commandes: [
|
|
173
|
+
'Bash(codegraph explore *)',
|
|
174
|
+
'mcp__codegraph__codegraph_explore',
|
|
175
|
+
'mcp__rtfm__rtfm_search',
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
// On the questions to a plan, it answers for the plan; the circuit writes its changes to the
|
|
179
|
+
// ticket and its answers at the ticket.
|
|
180
|
+
'referent-technique': {
|
|
181
|
+
index: true,
|
|
182
|
+
commandes: [
|
|
183
|
+
'Bash(bd show *)',
|
|
184
|
+
'Bash(bd comments add *)',
|
|
185
|
+
'Bash(npx grillhouse ticket *)',
|
|
186
|
+
'Bash(codegraph explore *)',
|
|
187
|
+
'mcp__codegraph__codegraph_explore',
|
|
188
|
+
'mcp__rtfm__rtfm_search',
|
|
189
|
+
],
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const lireJson = f => {
|
|
194
|
+
try {
|
|
195
|
+
return JSON.parse(readFileSync(f, 'utf8'));
|
|
196
|
+
} catch {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// The plugins the project enables, in its settings and its local settings.
|
|
202
|
+
function greffonsDuProjet(racine) {
|
|
203
|
+
const actifs = new Set();
|
|
204
|
+
for (const f of ['settings.json', 'settings.local.json']) {
|
|
205
|
+
const p = lireJson(path.join(racine, '.claude', f))?.enabledPlugins ?? {};
|
|
206
|
+
for (const [nom, actif] of Object.entries(p)) if (actif) actifs.add(nom);
|
|
207
|
+
}
|
|
208
|
+
return [...actifs].sort();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// The installed path of the plugin <nom> for the project <racine>: its entry for the project
|
|
212
|
+
// first, else the user's.
|
|
213
|
+
function cheminDuGreffon(nom, racine, home) {
|
|
214
|
+
const entrees =
|
|
215
|
+
lireJson(path.join(home, '.claude', 'plugins', 'installed_plugins.json'))?.plugins?.[nom] ?? [];
|
|
216
|
+
const e =
|
|
217
|
+
entrees.find(x => x.projectPath === racine) ?? entrees.find(x => x.scope === 'user') ?? null;
|
|
218
|
+
return e?.installPath ?? null;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// The servers of the index: the project's `.mcp.json`, then the manifests of the plugins it enables.
|
|
222
|
+
function serveursDeLIndex(racine, home) {
|
|
223
|
+
const out = {};
|
|
224
|
+
const projet = lireJson(path.join(racine, '.mcp.json'))?.mcpServers ?? {};
|
|
225
|
+
for (const n of INDEX) if (projet[n]) out[n] = projet[n];
|
|
226
|
+
for (const greffon of greffonsDuProjet(racine)) {
|
|
227
|
+
const dossier = cheminDuGreffon(greffon, racine, home);
|
|
228
|
+
if (!dossier) continue;
|
|
229
|
+
const serveurs =
|
|
230
|
+
lireJson(path.join(dossier, '.claude-plugin', 'plugin.json'))?.mcpServers ??
|
|
231
|
+
lireJson(path.join(dossier, '.mcp.json'))?.mcpServers ??
|
|
232
|
+
{};
|
|
233
|
+
for (const n of INDEX) {
|
|
234
|
+
if (out[n] || !serveurs[n]) continue;
|
|
235
|
+
out[n] = JSON.parse(JSON.stringify(serveurs[n]).replaceAll('${CLAUDE_PLUGIN_ROOT}', dossier));
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return out;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// The settings of the session of <role>, for the ticket <ticket>, its copy <copie> (where the
|
|
242
|
+
// project's own skills are read) and the main tree <racine>; `lit` names the files the regulator reads.
|
|
243
|
+
function reglagesDuRole(role, { racine, copie = racine, ticket, journal, preuves }) {
|
|
244
|
+
const r = ROLES[role];
|
|
245
|
+
if (!r) throw new Error(`rôle sans droits : ${role}`);
|
|
246
|
+
const fichiers = { journal, preuves };
|
|
247
|
+
// An absolute path of the machine opens on `//`.
|
|
248
|
+
const lectures = (r.lit ?? []).filter(k => fichiers[k]).map(k => `Read(/${fichiers[k]})`);
|
|
249
|
+
const deny = [...AUTEUR_FIXE, ...(r.ecritAuTicket === false ? ECRIRE_AU_TICKET : [])];
|
|
250
|
+
if (r.ecrit) {
|
|
251
|
+
deny.push(...ECRIRE_PAR_SCRIPT, ...TEST_DIRECT);
|
|
252
|
+
// The ticket its instruction carries, its description, notes and last handover.
|
|
253
|
+
for (const lecture of ['show', 'comments']) {
|
|
254
|
+
deny.push(`Bash(bd ${lecture} ${ticket})`, `Bash(bd ${lecture} ${ticket} *)`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const propres = path.join(copie, '.claude', 'skills');
|
|
258
|
+
const autres = [
|
|
259
|
+
...INTEGREES,
|
|
260
|
+
...(existsSync(propres)
|
|
261
|
+
? readdirSync(propres, { withFileTypes: true })
|
|
262
|
+
.filter(d => d.isDirectory())
|
|
263
|
+
.map(d => d.name)
|
|
264
|
+
: []),
|
|
265
|
+
];
|
|
266
|
+
const reglages = {
|
|
267
|
+
permissions: { allow: [...r.commandes, ...lectures], deny },
|
|
268
|
+
autoMemoryEnabled: false,
|
|
269
|
+
disableBundledSkills: true,
|
|
270
|
+
skillOverrides: Object.fromEntries(autres.map(s => [s, 'off'])),
|
|
271
|
+
enabledPlugins: Object.fromEntries(
|
|
272
|
+
greffonsDuProjet(racine)
|
|
273
|
+
.filter(g => !g.startsWith(GREFFON_DU_CADRE))
|
|
274
|
+
.map(g => [g, false])
|
|
275
|
+
),
|
|
276
|
+
env: SANS_TACHE_DE_FOND,
|
|
277
|
+
};
|
|
278
|
+
if (r.ecrit) {
|
|
279
|
+
reglages.hooks = {
|
|
280
|
+
PreToolUse: [
|
|
281
|
+
{
|
|
282
|
+
matcher: 'Write|Edit|MultiEdit|NotebookEdit',
|
|
283
|
+
hooks: [
|
|
284
|
+
{
|
|
285
|
+
type: 'command',
|
|
286
|
+
command: `"$CLAUDE_PROJECT_DIR/node_modules/.bin/grillhouse" verrou ${role}`,
|
|
287
|
+
},
|
|
288
|
+
],
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
matcher: 'Bash',
|
|
292
|
+
hooks: [
|
|
293
|
+
{
|
|
294
|
+
type: 'command',
|
|
295
|
+
command: '"$CLAUDE_PROJECT_DIR/node_modules/.bin/grillhouse" commande',
|
|
296
|
+
},
|
|
297
|
+
],
|
|
298
|
+
},
|
|
299
|
+
],
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
return reglages;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// The options of claude for the session of <role> (the header's list); <home> holds the plugins
|
|
306
|
+
// installed.
|
|
307
|
+
export function optionsDuRole(role, contexte) {
|
|
308
|
+
const { racine, home = os.homedir() } = contexte;
|
|
309
|
+
const r = ROLES[role];
|
|
310
|
+
const serveurs = r?.index ? serveursDeLIndex(racine, home) : {};
|
|
311
|
+
const outils = [...LIRE, ...(r?.ecrit ? ECRIRE : []), ...(r?.index ? ['ToolSearch'] : [])];
|
|
312
|
+
return [
|
|
313
|
+
'--setting-sources',
|
|
314
|
+
'project,local',
|
|
315
|
+
'--settings',
|
|
316
|
+
JSON.stringify(reglagesDuRole(role, contexte)),
|
|
317
|
+
'--tools',
|
|
318
|
+
outils.join(','),
|
|
319
|
+
'--strict-mcp-config',
|
|
320
|
+
'--mcp-config',
|
|
321
|
+
JSON.stringify({ mcpServers: serveurs }),
|
|
322
|
+
];
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// The command's options for <argv>, written to stdout; its exit code.
|
|
326
|
+
function commande(argv) {
|
|
327
|
+
const [role, ...reste] = argv;
|
|
328
|
+
const o = {};
|
|
329
|
+
for (let i = 0; i < reste.length; i += 2) {
|
|
330
|
+
const cle = reste[i]?.replace(/^--/, '');
|
|
331
|
+
if (
|
|
332
|
+
!['racine', 'copie', 'ticket', 'journal', 'preuves'].includes(cle) ||
|
|
333
|
+
i + 1 >= reste.length
|
|
334
|
+
) {
|
|
335
|
+
process.stderr.write(
|
|
336
|
+
`usage : droits.mjs <rôle> --racine <r> --copie <c> --ticket <t> [--journal <f> --preuves <m>]\n`
|
|
337
|
+
);
|
|
338
|
+
return 2;
|
|
339
|
+
}
|
|
340
|
+
o[cle] = reste[i + 1];
|
|
341
|
+
}
|
|
342
|
+
if (!ROLES[role] || !o.racine || !o.ticket) {
|
|
343
|
+
process.stderr.write(
|
|
344
|
+
`droits.mjs : rôle ${role ?? '(aucun)'} sans droits, ou racine et ticket absents.\n`
|
|
345
|
+
);
|
|
346
|
+
return 2;
|
|
347
|
+
}
|
|
348
|
+
process.stdout.write(`${optionsDuRole(role, o).join('\n')}\n`);
|
|
349
|
+
return 0;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (import.meta.url === pathToFileURL(process.argv[1] ?? '').href) {
|
|
353
|
+
process.exitCode = commande(process.argv.slice(2));
|
|
354
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The exit codes of the envelope and its launcher, named once. `enveloppe.mjs` and the tests
|
|
3
|
+
// import them; `lancer.sh` reads them through `node codes.mjs`, which prints them as `NAME=value`.
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
|
|
6
|
+
// A malformed call: wrong arguments, unknown role, instruction missing or without its ticket.
|
|
7
|
+
export const CODE_USAGE = 2;
|
|
8
|
+
// A launch the envelope refuses, or that bwrap cannot build.
|
|
9
|
+
export const CODE_REFUS = 3;
|
|
10
|
+
// An agent copy the launcher cannot prepare: created, moved forward, installed or built.
|
|
11
|
+
export const CODE_COPIE = 4;
|
|
12
|
+
|
|
13
|
+
if (import.meta.url === pathToFileURL(process.argv[1] ?? '').href) {
|
|
14
|
+
for (const [nom, valeur] of Object.entries({ CODE_USAGE, CODE_REFUS, CODE_COPIE })) {
|
|
15
|
+
console.log(`${nom}=${valeur}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// The component of the envelope a command runs in. The envelope names it to every command of its
|
|
2
|
+
// session, in the variable `GRILLHOUSE_ENVELOPPE`: the component's path inside the copy
|
|
3
|
+
// (`packages/a`, or `src/parser` in a one-package project). As in a sandbox of Bazel, the
|
|
4
|
+
// neighbours arrive built and read-only: a command of the frame that reads it builds and writes
|
|
5
|
+
// that component only, and reads the neighbours by their published form.
|
|
6
|
+
//
|
|
7
|
+
// This module uses Node alone, as the modules of scripts/paquets.mjs.
|
|
8
|
+
export const VARIABLE = 'GRILLHOUSE_ENVELOPPE';
|
|
9
|
+
|
|
10
|
+
// The component of the envelope named in <env>, or null outside an envelope.
|
|
11
|
+
export const composantDeLEnveloppe = (env = process.env) => env[VARIABLE] || null;
|