@piecemaker-legal/piecemaker 2.0.10 → 2.0.12
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/assets/{FindReplaceDialog-KU5TEIBJ-CQ76sPaJ.js → FindReplaceDialog-KU5TEIBJ-BBxf1he7.js} +1 -1
- package/dist/assets/{FootnotePropertiesDialog-W3YHM4BV-BpgYQvvd.js → FootnotePropertiesDialog-W3YHM4BV-BYqp6U4x.js} +1 -1
- package/dist/assets/{HyperlinkDialog-ZYH7ZHRF-z08UbYbL.js → HyperlinkDialog-ZYH7ZHRF-BVC9zOMs.js} +4 -4
- package/dist/assets/{ImagePositionDialog-HEWYR6Q3-CFzOnzAt.js → ImagePositionDialog-HEWYR6Q3-Xn2mC64y.js} +1 -1
- package/dist/assets/{ImagePropertiesDialog-RAB47C6M-D-ThGU-b.js → ImagePropertiesDialog-RAB47C6M-CFcdqEif.js} +1 -1
- package/dist/assets/{PageSetupDialog-AIGIXO3E-_PYIO8eb.js → PageSetupDialog-AIGIXO3E-DECaeRS9.js} +1 -1
- package/dist/assets/{SplitCellDialog-IFBKYCD6-Cb9uQOB8.js → SplitCellDialog-IFBKYCD6-ByYa04H_.js} +1 -1
- package/dist/assets/{TablePropertiesDialog-TMLKGOOW-12vmjb6B.js → TablePropertiesDialog-TMLKGOOW-BuyqZB5A.js} +1 -1
- package/dist/assets/{WatermarkDialog-KRL7WMIS-C-d8rzt2.js → WatermarkDialog-KRL7WMIS-ByZ1Acr2.js} +1 -1
- package/dist/assets/{abnfDiagram-VCTEODGH-B4OsX7eF.js → abnfDiagram-VCTEODGH-BtttzdZA.js} +1 -1
- package/dist/assets/{arc-BK1oUIk7.js → arc-DN4m1tLs.js} +1 -1
- package/dist/assets/{architectureDiagram-5GKGNRK7-CfaFI6L7.js → architectureDiagram-5GKGNRK7-Bt-zFumG.js} +1 -1
- package/dist/assets/{blockDiagram-I7D4REHJ-DQEI2azY.js → blockDiagram-I7D4REHJ-D14V8v4j.js} +1 -1
- package/dist/assets/{c4Diagram-7LVT6UL2-DbravpVi.js → c4Diagram-7LVT6UL2-BynDo1-W.js} +1 -1
- package/dist/assets/channel-C4gJXzYa.js +1 -0
- package/dist/assets/{chunk-2Q5K7J3B-BLpZ9huC.js → chunk-2Q5K7J3B-B8gKhSj9.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-BLlEdmX9.js → chunk-5VM5RSS4-GvOpglRR.js} +1 -1
- package/dist/assets/{chunk-F27PBJKO-D-ZNhI6q.js → chunk-F27PBJKO-CAgZy0qc.js} +1 -1
- package/dist/assets/{chunk-IMKFNOWR-vzSiKnhh.js → chunk-IMKFNOWR-gf8Ux8Zd.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-DfF0k4nb.js → chunk-JWPE2WC7-D4zFFRMp.js} +1 -1
- package/dist/assets/{chunk-POPQ4Y6H-BnwCYsPP.js → chunk-POPQ4Y6H-Ct8X_LaT.js} +1 -1
- package/dist/assets/{chunk-SVP7TREG-DRxc8fhq.js → chunk-SVP7TREG-g5iH1bs5.js} +1 -1
- package/dist/assets/{chunk-TICWLB2K-Dd2Q-md-.js → chunk-TICWLB2K-89-VFKTn.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-DBjkEUp_.js → chunk-XXDRQBXY-CaQbdObb.js} +1 -1
- package/dist/assets/classDiagram-ZZMXUADV-Cm08FeYk.js +1 -0
- package/dist/assets/classDiagram-v2-VYDZK3BY-Cm08FeYk.js +1 -0
- package/dist/assets/{cose-bilkent-JH36ORCC-By6PS4oe.js → cose-bilkent-JH36ORCC-BiYOGJAU.js} +1 -1
- package/dist/assets/{cynefin-OW5HDTMX-YxWpjc5W.js → cynefin-OW5HDTMX-F6mJ-4tj.js} +1 -1
- package/dist/assets/{cynefinDiagram-5FMLGOSQ-DrtXzz3p.js → cynefinDiagram-5FMLGOSQ-q-Rggn6r.js} +1 -1
- package/dist/assets/{dagre-GXQ25YYZ-BDpTLKqZ.js → dagre-GXQ25YYZ-COqImSUH.js} +1 -1
- package/dist/assets/{diagram-S7CK7UJ4-C4LvqeCs.js → diagram-S7CK7UJ4-BAg1dyEc.js} +1 -1
- package/dist/assets/{diagram-UQ7AKVKN-BTpnMeHp.js → diagram-UQ7AKVKN-DFJS8qCV.js} +1 -1
- package/dist/assets/{diagram-VSXAHHWV-DucHHWev.js → diagram-VSXAHHWV-BfldL35r.js} +1 -1
- package/dist/assets/{diagram-VX7I27RA-DYHZNmmH.js → diagram-VX7I27RA-kLjovpYe.js} +1 -1
- package/dist/assets/{diagram-Z3DM3KII-BHIH2BGN.js → diagram-Z3DM3KII-Dhwvi3Iu.js} +1 -1
- package/dist/assets/{ebnfDiagram-PWID7BFC-CGiEkwj0.js → ebnfDiagram-PWID7BFC-Bp4YE1i7.js} +1 -1
- package/dist/assets/{erDiagram-RLTQ6QDP-AJMHi2Us.js → erDiagram-RLTQ6QDP-BKDdaSWz.js} +1 -1
- package/dist/assets/{flowDiagram-HODETNUW-BqzANBh2.js → flowDiagram-HODETNUW-zHProVxL.js} +1 -1
- package/dist/assets/{ganttDiagram-EL5Y4UJY-B0xPDY2_.js → ganttDiagram-EL5Y4UJY-B-B-BI6j.js} +1 -1
- package/dist/assets/{gitGraphDiagram-WWUBYQGX-CzPX5CNO.js → gitGraphDiagram-WWUBYQGX-BTHMg5CH.js} +1 -1
- package/dist/assets/index-C5slQNvE.css +1 -0
- package/dist/assets/{index-Bk2iXKnJ.js → index-CJP4dZ-c.js} +146 -146
- package/dist/assets/{infoDiagram-27XIBGKW-Cjc44H0O.js → infoDiagram-27XIBGKW-mabp4H9I.js} +1 -1
- package/dist/assets/{ishikawaDiagram-5VMMS53U-BWhr2v7r.js → ishikawaDiagram-5VMMS53U-CLNhcCrM.js} +1 -1
- package/dist/assets/{journeyDiagram-3NMN7TZE-Bl4r6RrP.js → journeyDiagram-3NMN7TZE-CGEi2RB6.js} +1 -1
- package/dist/assets/{kanban-definition-UXKFOSKX-FV-T0Vy1.js → kanban-definition-UXKFOSKX-B2fLX1fK.js} +1 -1
- package/dist/assets/{layout-CTfb1sAF.js → layout-CloKWsFq.js} +1 -1
- package/dist/assets/{linear-Dfgi6vlo.js → linear-BFyydI0c.js} +1 -1
- package/dist/assets/{mermaid.core-DOCGsdlo.js → mermaid.core-Dxl3LVAh.js} +6 -6
- package/dist/assets/{mindmap-definition-YA3MSWOX-CymQ86ir.js → mindmap-definition-YA3MSWOX-FT4pm55s.js} +1 -1
- package/dist/assets/{pegDiagram-XKGWAZYB-1VMq_vi0.js → pegDiagram-XKGWAZYB-okyIfJWM.js} +1 -1
- package/dist/assets/{pieDiagram-E7YTZNPT-C5GgXtJU.js → pieDiagram-E7YTZNPT-NF61CQz8.js} +1 -1
- package/dist/assets/{quadrantDiagram-AXDQQJYC-C6zpryYf.js → quadrantDiagram-AXDQQJYC-uVfvZzzt.js} +1 -1
- package/dist/assets/{railroadDiagram-O6MQD6OU-D-sv4SWi.js → railroadDiagram-O6MQD6OU-Dp8IpeoH.js} +1 -1
- package/dist/assets/{requirementDiagram-BXWQKSXE-CkjY-z4B.js → requirementDiagram-BXWQKSXE-D8VV0oQe.js} +1 -1
- package/dist/assets/{sankeyDiagram-P5KCCOFB-De-d8Q6L.js → sankeyDiagram-P5KCCOFB-D-xhxjob.js} +1 -1
- package/dist/assets/{sequenceDiagram-WJ2MYXX4-DCsGSJa9.js → sequenceDiagram-WJ2MYXX4-BAQBK95h.js} +1 -1
- package/dist/assets/{sizeCapture-INFHLROL-xINZhgER.js → sizeCapture-INFHLROL-C6rk9SVx.js} +1 -1
- package/dist/assets/{stateDiagram-D77RDMKH-CuLUTWSL.js → stateDiagram-D77RDMKH-DshqaEOj.js} +1 -1
- package/dist/assets/{stateDiagram-v2-MP3YSRHH-Cnbs-M92.js → stateDiagram-v2-MP3YSRHH-BohZIrk5.js} +1 -1
- package/dist/assets/{swimlanes-42K2YHIH-BwxARD7N.js → swimlanes-42K2YHIH-DgcPDy4l.js} +1 -1
- package/dist/assets/swimlanesDiagram-VR7AAH4N-CuM3Su0K.js +8 -0
- package/dist/assets/{timeline-definition-24CTP7MA-BIOvnn-l.js → timeline-definition-24CTP7MA-OgpIe-gQ.js} +1 -1
- package/dist/assets/{vennDiagram-4TSXK5OY-BSD6Pfmt.js → vennDiagram-4TSXK5OY-BZzGd6jt.js} +1 -1
- package/dist/assets/{wardleyDiagram-VM6X3IG4-7Zz2iRkF.js → wardleyDiagram-VM6X3IG4-1tg-H7l_.js} +1 -1
- package/dist/assets/{xychartDiagram-S5SC5T6Z-Ctx17Y1D.js → xychartDiagram-S5SC5T6Z-ByTsX8g0.js} +1 -1
- package/dist/index.html +2 -2
- package/dist/sw.js +1 -1
- package/dist-server/plugins/piecemaker-dossier/src/knowledge.js +61 -1
- package/dist-server/plugins/piecemaker-dossier/src/knowledge.js.map +1 -1
- package/dist-server/plugins/piecemaker-dossier/src/scan-result.js +0 -48
- package/dist-server/plugins/piecemaker-dossier/src/scan-result.js.map +1 -1
- package/dist-server/server/piecemaker/agent-instructions.js +148 -0
- package/dist-server/server/piecemaker/agent-instructions.js.map +1 -0
- package/dist-server/server/piecemaker/index.js +4 -0
- package/dist-server/server/piecemaker/index.js.map +1 -1
- package/dist-server/server/piecemaker/knowledge/pipeline.js +25 -29
- package/dist-server/server/piecemaker/knowledge/pipeline.js.map +1 -1
- package/dist-server/server/piecemaker/knowledge/service.js +1 -16
- package/dist-server/server/piecemaker/knowledge/service.js.map +1 -1
- package/dist-server/server/piecemaker/project-registry.js +5 -5
- package/dist-server/server/piecemaker/project-registry.js.map +1 -1
- package/package.json +1 -1
- package/scripts/piecemaker/cli/lib/plugins.mjs +1 -0
- package/server/piecemaker/agent-instructions.ts +148 -0
- package/server/piecemaker/anonymizer/dictionary.cjs +34 -3
- package/server/piecemaker/anonymizer/hudsucker-fixture.cjs +1 -1
- package/server/piecemaker/anonymizer/hudsucker-proxy/src/main.rs +2 -1
- package/server/piecemaker/anonymizer/hudsucker-smoke.cjs +343 -0
- package/server/piecemaker/anonymizer/rewrite.cjs +2 -2
- package/server/piecemaker/anonymizer/rewriter-bridge.cjs +7 -4
- package/server/piecemaker/anonymizer/rewriter-worker.cjs +85 -0
- package/server/piecemaker/anonymizer/service.cjs +10 -8
- package/server/piecemaker/anonymizer/sqlite-dictionary.cjs +15 -32
- package/server/piecemaker/index.ts +5 -1
- package/server/piecemaker/knowledge/pipeline.ts +24 -31
- package/server/piecemaker/knowledge/service.ts +1 -14
- package/server/piecemaker/project-registry.ts +6 -6
- package/server/piecemaker/router.cjs +0 -1
- package/server/piecemaker/vendor/installer/bin/piecemaker.mjs +9 -162
- package/server/piecemaker/vendor/installer/lib/commandes.mjs +1 -2
- package/server/piecemaker/vendor/installer/lib/conversion-client.mjs +62 -3
- package/server/piecemaker/vendor/installer/steps/02-dependances-node.mjs +5 -5
- package/server/piecemaker/vendor/installer/steps/06-hooks.mjs +23 -69
- package/server/piecemaker/vendor/installer/steps/12-mcp-piecemaker.mjs +3 -3
- package/server/piecemaker/vendor/mcp/README.md +1 -1
- package/server/piecemaker/vendor/mcp/piecemaker/server.mjs +12 -75
- package/server/piecemaker/vendor/piecemaker-plugin/hooks/hooks.json +0 -40
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/compile-recherche.mjs +2 -2
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/case-folder-structure.cjs +2 -90
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/case-folders.cjs +26 -7
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/commits.cjs +0 -28
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/hook-io.mjs +0 -13
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/institutional-terms.cjs +3 -3
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/mapping.cjs +10 -143
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/protection.cjs +1 -1
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/session-timing.cjs +0 -65
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/substitution.cjs +189 -41
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/protect-originals.mjs +11 -2
- package/server/piecemaker/vendor/piecemaker-plugin/skills/ajout-de-fonctionnalites/SKILL.md +4 -18
- package/server/piecemaker/vendor/piecemaker-plugin/skills/conversion-md/SKILL.md +9 -5
- package/server/piecemaker/vendor/websocket-server/admin-routes.cjs +3 -179
- package/server/piecemaker/vendor/websocket-server/case-registry.cjs +0 -10
- package/server/piecemaker/vendor/websocket-server/claude-hooks.cjs +3 -0
- package/server/piecemaker/vendor/websocket-server/originals-pipeline.cjs +23 -372
- package/server/piecemaker/vendor/websocket-server/renamed-originals.cjs +136 -0
- package/server/piecemaker/vendor/websocket-server/scripts/convert_and_scan_pipeline.py +115 -96
- package/dist/assets/channel-DVyNr2Yg.js +0 -1
- package/dist/assets/classDiagram-ZZMXUADV-2pGPHl5H.js +0 -1
- package/dist/assets/classDiagram-v2-VYDZK3BY-2pGPHl5H.js +0 -1
- package/dist/assets/index-Dc9wNuS4.css +0 -1
- package/dist/assets/swimlanesDiagram-VR7AAH4N-D7p8qZI2.js +0 -8
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/billing-track.mjs +0 -194
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/commit-track.mjs +0 -71
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/session-commit-worker.mjs +0 -260
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/session-commit.mjs +0 -83
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
* le skill `docx-cli` est disponible : il travaille par le binaire `docx`
|
|
17
17
|
* (`docx read pièce.docx`, `docx find`…), qui contournerait entièrement un
|
|
18
18
|
* garde-fou limité à Read/Grep/Glob.
|
|
19
|
+
*
|
|
20
|
+
* Le hook n'agit que dans un dossier au bouclier vert : anonymisation terminée
|
|
21
|
+
* (publiée par le serveur dans `~/.piecemaker/anonymized-projects.json`) et
|
|
22
|
+
* protection non levée. Ailleurs, il laisse tout passer.
|
|
19
23
|
*/
|
|
20
24
|
|
|
21
25
|
import fs from 'node:fs';
|
|
@@ -27,6 +31,7 @@ const require = createRequire(import.meta.url);
|
|
|
27
31
|
const { locateProjectCase } = require('./lib/case-folders.cjs');
|
|
28
32
|
const {
|
|
29
33
|
isMappingFile,
|
|
34
|
+
isProtectionBypassed,
|
|
30
35
|
isSecretFile,
|
|
31
36
|
isProtectedFile,
|
|
32
37
|
markdownCounterpart,
|
|
@@ -153,6 +158,10 @@ function caseRootHasMapping(located) {
|
|
|
153
158
|
}
|
|
154
159
|
}
|
|
155
160
|
|
|
161
|
+
function shieldActive(located) {
|
|
162
|
+
return Boolean(located?.anonymized) && !isProtectionBypassed(located.caseRoot);
|
|
163
|
+
}
|
|
164
|
+
|
|
156
165
|
async function main() {
|
|
157
166
|
const payload = await readHookPayload(2000);
|
|
158
167
|
if (!payload) return null;
|
|
@@ -163,7 +172,7 @@ async function main() {
|
|
|
163
172
|
if (toolName === 'Bash') {
|
|
164
173
|
for (const candidate of commandPaths(payload.tool_input?.command, cwd)) {
|
|
165
174
|
const located = locateProjectCase(candidate);
|
|
166
|
-
if (!located) continue;
|
|
175
|
+
if (!shieldActive(located)) continue;
|
|
167
176
|
if (isMappingFile(candidate)) return deny(mappingReason(candidate));
|
|
168
177
|
if (isSecretFile(candidate)) return deny(secretReason(candidate));
|
|
169
178
|
if (isProtectedFile(candidate, located.caseRoot)) {
|
|
@@ -178,7 +187,7 @@ async function main() {
|
|
|
178
187
|
const target = absolutePath(payload.tool_input?.file_path || payload.tool_input?.path, cwd);
|
|
179
188
|
if (!target) return null;
|
|
180
189
|
const located = locateProjectCase(target);
|
|
181
|
-
if (!located) return null;
|
|
190
|
+
if (!shieldActive(located)) return null;
|
|
182
191
|
|
|
183
192
|
// Un répertoire n'est pas une pièce : `Grep`/`Glob` en visent un couramment,
|
|
184
193
|
// et c'est `isBroadCaseSearch` qui décide s'il est sûr de le parcourir.
|
|
@@ -14,9 +14,9 @@ skill sert de guide pour ranger un ajout personnel au bon endroit.
|
|
|
14
14
|
|
|
15
15
|
| Type d'ajout | Emplacement | Portée |
|
|
16
16
|
| --- | --- | --- |
|
|
17
|
-
| Instructions ou préférences globales (style, rappels, habitudes) |
|
|
18
|
-
| Skill personnelle réutilisable | Nouveau dossier
|
|
19
|
-
| Gabarit personnel (acte, courrier type…) |
|
|
17
|
+
| Instructions ou préférences globales (style, rappels, habitudes) | `~/.piecemaker/custom/perso.md` | Toutes les affaires — ce fichier est importé automatiquement dans chaque dossier via `~/.piecemaker/CLAUDE.md`. |
|
|
18
|
+
| Skill personnelle réutilisable | Nouveau dossier `~/.claude/skills/<nom>/SKILL.md` | Toutes les sessions Claude Code — découverte automatique, jamais écrasée par PieceMaker (un fichier créé à la main n'est jamais remplacé par l'application). |
|
|
19
|
+
| Gabarit personnel (acte, courrier type…) | `~/.piecemaker/templates/` | Disponible pour toute rédaction, indépendamment du dépôt de l'application. |
|
|
20
20
|
| Élément propre à une seule affaire (parties, juridiction, échéances) | Section « Ce dossier » du `CLAUDE.md` / `AGENTS.md` de ce dossier | Uniquement ce dossier-là. |
|
|
21
21
|
|
|
22
22
|
Ces emplacements sont hors du dépôt PieceMaker : une mise à jour de PieceMaker
|
|
@@ -26,7 +26,7 @@ PieceMaker — la garantie va dans les deux sens.
|
|
|
26
26
|
|
|
27
27
|
## Format minimal d'une skill personnelle
|
|
28
28
|
|
|
29
|
-
Un fichier
|
|
29
|
+
Un fichier `~/.claude/skills/<nom>/SKILL.md` avec un en-tête
|
|
30
30
|
puis du texte libre :
|
|
31
31
|
|
|
32
32
|
```markdown
|
|
@@ -50,17 +50,3 @@ Instructions pour l'assistant, en français, centrées sur la tâche.
|
|
|
50
50
|
3. **Créer ou éditer le fichier correspondant**, en respectant le format
|
|
51
51
|
attendu (front matter pour une skill, section « Ce dossier » pour un
|
|
52
52
|
élément local, etc.).
|
|
53
|
-
4. **Pour un nouveau dossier d'affaire** qui n'a pas encore de wrapper : sur
|
|
54
|
-
demande, proposer et créer `CLAUDE.md` et `AGENTS.md` à la racine du
|
|
55
|
-
dossier, avec exactement ce contenu (chemin absolu, jamais `~`) :
|
|
56
|
-
|
|
57
|
-
```
|
|
58
|
-
@/Users/tsardet/.piecemaker/CLAUDE.md
|
|
59
|
-
|
|
60
|
-
# Ce dossier
|
|
61
|
-
<!-- Éléments propres à ce dossier : parties, juridiction, échéances, particularités. À compléter. -->
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Si l'un de ces deux fichiers existe déjà dans le dossier, ne jamais
|
|
65
|
-
l'écraser : le lire, et s'il ne contient pas déjà cette ligne d'import,
|
|
66
|
-
l'ajouter en tête sans supprimer le contenu existant.
|
|
@@ -46,12 +46,16 @@ Bridge (`taskpane/modules/python-bridge.js` →
|
|
|
46
46
|
|
|
47
47
|
## Enchaînement avec le scan PII
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
`
|
|
51
|
-
|
|
49
|
+
Le scan PII passe uniquement par PieceMaker (outil `conversion` du serveur MCP
|
|
50
|
+
`piecemaker`, ou le scan du dossier dans l'interface) : ne pas lancer
|
|
51
|
+
`websocket-server/scripts/convert_and_scan_pipeline.py` à la main. Ce script
|
|
52
|
+
appelle `smart_converter.py` puis le worker
|
|
52
53
|
`websocket-server/scripts/presidio-gliner/scanner_worker.py` (GLiNER chargé
|
|
53
|
-
une fois pour tout le lot)
|
|
54
|
-
|
|
54
|
+
une fois pour tout le lot) ; il exige `--database` (les codes déjà attribués
|
|
55
|
+
par tous les dossiers y sont réservés), reçoit le mapping du dossier sur son
|
|
56
|
+
entrée standard et renvoie le mapping fusionné en lignes `MAPPING:` que
|
|
57
|
+
PieceMaker écrit en base. Aucun fichier de mapping n'est écrit. Sortie
|
|
58
|
+
persistante : un Markdown par fichier. Dans le
|
|
55
59
|
pipeline d'administration d'un dossier, `-o` vise le sous-dossier
|
|
56
60
|
`Fichiers convertis PieceMaker/` du dossier (racine réservée aux originaux) ;
|
|
57
61
|
le manifeste technique caché `.piecemaker/anonymization-state.json` reste, lui, à
|
|
@@ -7,7 +7,6 @@ const { performance } = require('node:perf_hooks');
|
|
|
7
7
|
const {
|
|
8
8
|
listProjectCases,
|
|
9
9
|
projectCaseEntry,
|
|
10
|
-
readRegistryConfig,
|
|
11
10
|
resolveCaseReference,
|
|
12
11
|
validateSelectedCaseFolder,
|
|
13
12
|
} = require('./case-registry.cjs');
|
|
@@ -20,24 +19,16 @@ const {
|
|
|
20
19
|
createHistoryBranch,
|
|
21
20
|
historyBranches,
|
|
22
21
|
historyMonths,
|
|
23
|
-
isTechnicalCaseDirectoryName,
|
|
24
22
|
listCases,
|
|
25
23
|
listHistory,
|
|
26
24
|
listHistoryPeriod,
|
|
27
|
-
resolveCasesRoot,
|
|
28
25
|
resolveCommitIdentity,
|
|
29
26
|
restoreRevision,
|
|
30
27
|
revisionDetails,
|
|
31
28
|
safeCaseFiles,
|
|
32
29
|
worktreeDetails,
|
|
33
30
|
} = require('../piecemaker-plugin/scripts/lib/commits.cjs');
|
|
34
|
-
const {
|
|
35
|
-
listOriginals,
|
|
36
|
-
readCaseMapping,
|
|
37
|
-
rebuildCaseMapping,
|
|
38
|
-
saveCaseMapping,
|
|
39
|
-
writeCaseMapping,
|
|
40
|
-
} = require('./originals-pipeline.cjs');
|
|
31
|
+
const { listOriginals } = require('./originals-pipeline.cjs');
|
|
41
32
|
const { invalidateOriginals, listOriginalsCached } = require('../../originals-cache.cjs');
|
|
42
33
|
const {
|
|
43
34
|
documentKey,
|
|
@@ -67,12 +58,6 @@ const {
|
|
|
67
58
|
unregisterClaudeAsset,
|
|
68
59
|
} = require('./claude-assets.cjs');
|
|
69
60
|
const { claudeHooksStatus } = require('./claude-hooks.cjs');
|
|
70
|
-
const {
|
|
71
|
-
DEFAULT_CASE_FOLDER_STRUCTURE,
|
|
72
|
-
configuredCaseFolderStructure,
|
|
73
|
-
ensureCaseFolderStructure,
|
|
74
|
-
normalizeCaseFolderStructure,
|
|
75
|
-
} = require('./case-folder-structure.cjs');
|
|
76
61
|
|
|
77
62
|
const MAX_MARKDOWN_BYTES = 1024 * 1024;
|
|
78
63
|
const SECRET_KEYS = new Set([
|
|
@@ -88,46 +73,6 @@ const ENV_KEYS = new Set([
|
|
|
88
73
|
'SMART_CONVERTER_PATH',
|
|
89
74
|
]);
|
|
90
75
|
|
|
91
|
-
function validateNewCaseName(value) {
|
|
92
|
-
const name = String(value || '').trim();
|
|
93
|
-
if (!name || name.length > 120 || name === '.' || name === '..' || path.basename(name) !== name
|
|
94
|
-
|| name.startsWith('.') || /[\x00-\x1f\x7f]/.test(name) || isTechnicalCaseDirectoryName(name)) {
|
|
95
|
-
throw new Error('Nom de dossier juridique invalide.');
|
|
96
|
-
}
|
|
97
|
-
return name;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
async function createLegalCase({ casesRoot, homeDir, name, config = {} }) {
|
|
101
|
-
const root = resolveCasesRoot(casesRoot);
|
|
102
|
-
const safeName = validateNewCaseName(name);
|
|
103
|
-
const directory = path.join(root, safeName);
|
|
104
|
-
if (fs.existsSync(directory)) throw new Error(`Le dossier juridique « ${safeName} » existe déjà.`);
|
|
105
|
-
fs.mkdirSync(directory);
|
|
106
|
-
try {
|
|
107
|
-
const structure = ensureCaseFolderStructure(directory, config);
|
|
108
|
-
writeProtection(directory, { unprotected: [] });
|
|
109
|
-
const mapping = writeCaseMapping(directory, { mapping: {}, reverse_mapping: {} });
|
|
110
|
-
await createCommit({
|
|
111
|
-
casesRoot: root,
|
|
112
|
-
caseName: safeName,
|
|
113
|
-
homeDir,
|
|
114
|
-
label: 'Création du dossier juridique',
|
|
115
|
-
event: 'admin-case-create',
|
|
116
|
-
// Le mapping vit dans le sous-dossier des fichiers produits : le commit doit
|
|
117
|
-
// viser son chemin relatif au dossier, pas seulement son nom de base.
|
|
118
|
-
paths: [path.relative(directory, mapping.file).split(path.sep).join('/')],
|
|
119
|
-
waitForLockMs: 10_000,
|
|
120
|
-
});
|
|
121
|
-
const folder = await caseOverview(root, homeDir, safeName);
|
|
122
|
-
folder.branches = await historyBranches(root, homeDir, safeName);
|
|
123
|
-
folder.structure = structure;
|
|
124
|
-
return folder;
|
|
125
|
-
} catch (error) {
|
|
126
|
-
fs.rmSync(directory, { recursive: true, force: true });
|
|
127
|
-
throw error;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
76
|
/** Native folder-picker commands. Arguments stay separate from the shell. */
|
|
132
77
|
function folderPickerCommands(platform, initialFolder) {
|
|
133
78
|
const start = path.resolve(initialFolder || os.homedir());
|
|
@@ -197,19 +142,13 @@ async function selectLocalFolder(platform = process.platform, initialFolder = os
|
|
|
197
142
|
|
|
198
143
|
async function registerLegalCase({
|
|
199
144
|
folder,
|
|
200
|
-
configFile,
|
|
201
145
|
homeDir,
|
|
202
146
|
} = {}) {
|
|
203
147
|
const root = validateSelectedCaseFolder(folder);
|
|
204
148
|
const entry = projectCaseEntry(root);
|
|
205
149
|
if (!entry) throw new Error('Ce dossier n’est pas un projet enregistré.');
|
|
206
|
-
const structure = ensureCaseFolderStructure(root, readRegistryConfig(configFile));
|
|
207
150
|
const protection = readProtection(root);
|
|
208
151
|
if (!protection.exists) writeProtection(root, { unprotected: [] });
|
|
209
|
-
const currentMapping = readCaseMapping(root);
|
|
210
|
-
const mapping = currentMapping.exists
|
|
211
|
-
? currentMapping
|
|
212
|
-
: writeCaseMapping(root, { mapping: {}, reverse_mapping: {} });
|
|
213
152
|
|
|
214
153
|
const folderOverview = await caseOverview(path.dirname(root), homeDir, path.basename(root));
|
|
215
154
|
folderOverview.path = entry.id;
|
|
@@ -219,9 +158,7 @@ async function registerLegalCase({
|
|
|
219
158
|
return {
|
|
220
159
|
folder: folderOverview,
|
|
221
160
|
installed: {
|
|
222
|
-
mapping: path.relative(root, mapping.file).split(path.sep).join('/'),
|
|
223
161
|
protection: path.relative(root, protection.file).split(path.sep).join('/'),
|
|
224
|
-
structure: structure.directories,
|
|
225
162
|
},
|
|
226
163
|
};
|
|
227
164
|
}
|
|
@@ -230,7 +167,6 @@ function defaultConfig(repoRoot, homeDir = path.join(os.homedir(), '.piecemaker'
|
|
|
230
167
|
return {
|
|
231
168
|
pythonPath: null,
|
|
232
169
|
venvPath: path.join(homeDir, 'venv'),
|
|
233
|
-
caseFolderStructure: { ...DEFAULT_CASE_FOLDER_STRUCTURE },
|
|
234
170
|
};
|
|
235
171
|
}
|
|
236
172
|
|
|
@@ -701,8 +637,6 @@ async function configurationOverview({ repoRoot, homeDir, userHome, getRuntimeSt
|
|
|
701
637
|
].filter(Boolean);
|
|
702
638
|
const hookFiles = [
|
|
703
639
|
'protect-originals.mjs',
|
|
704
|
-
'commit-track.mjs',
|
|
705
|
-
'billing-track.mjs',
|
|
706
640
|
].map((name) => path.join(repoRoot, 'piecemaker-plugin', 'scripts', name));
|
|
707
641
|
const hooksReady = hookFiles.every((file) => fs.existsSync(file))
|
|
708
642
|
&& fs.existsSync(path.join(repoRoot, 'piecemaker-plugin', 'hooks', 'hooks.json'));
|
|
@@ -1997,13 +1931,8 @@ function createAdminRouter({
|
|
|
1997
1931
|
const router = express.Router();
|
|
1998
1932
|
const configFile = path.join(homeDir, 'config.json');
|
|
1999
1933
|
const envFile = path.join(repoRoot, '.env');
|
|
2000
|
-
const registryConfig = () => readRegistryConfig(configFile);
|
|
2001
1934
|
const selectedCase = (reference) => {
|
|
2002
|
-
|
|
2003
|
-
// Migration idempotente des dossiers enregistrés avant l'introduction de
|
|
2004
|
-
// l'arborescence métier. Le manifeste fige les noms utilisés par ce dossier.
|
|
2005
|
-
ensureCaseFolderStructure(legalCase.root, registryConfig());
|
|
2006
|
-
return legalCase;
|
|
1935
|
+
return resolveCaseReference(reference);
|
|
2007
1936
|
};
|
|
2008
1937
|
|
|
2009
1938
|
// Migration : l'identité de commit ne vivait que dans le `.env` du clone
|
|
@@ -2101,7 +2030,6 @@ function createAdminRouter({
|
|
|
2101
2030
|
|
|
2102
2031
|
router.get('/settings', (req, res) => {
|
|
2103
2032
|
const config = { ...defaultConfig(repoRoot, homeDir), ...readJson(configFile, {}) };
|
|
2104
|
-
config.caseFolderStructure = configuredCaseFolderStructure(config);
|
|
2105
2033
|
const env = readEnvFile(envFile);
|
|
2106
2034
|
const publicEnv = {};
|
|
2107
2035
|
const secrets = {};
|
|
@@ -2115,19 +2043,10 @@ function createAdminRouter({
|
|
|
2115
2043
|
router.put('/settings', (req, res) => {
|
|
2116
2044
|
try {
|
|
2117
2045
|
const current = { ...defaultConfig(repoRoot, homeDir), ...readJson(configFile, {}) };
|
|
2118
|
-
current.caseFolderStructure = configuredCaseFolderStructure(current);
|
|
2119
2046
|
const patch = req.body?.config || {};
|
|
2120
2047
|
const next = { ...current };
|
|
2121
2048
|
|
|
2122
2049
|
if (patch.pythonPath !== undefined) next.pythonPath = String(patch.pythonPath || '').trim() || null;
|
|
2123
|
-
if (patch.caseFolderStructure !== undefined) {
|
|
2124
|
-
next.caseFolderStructure = normalizeCaseFolderStructure({
|
|
2125
|
-
...current.caseFolderStructure,
|
|
2126
|
-
...(patch.caseFolderStructure && typeof patch.caseFolderStructure === 'object'
|
|
2127
|
-
? patch.caseFolderStructure
|
|
2128
|
-
: {}),
|
|
2129
|
-
});
|
|
2130
|
-
}
|
|
2131
2050
|
|
|
2132
2051
|
// L'identité de commit est aussi mémorisée dans config.json : le hook
|
|
2133
2052
|
// d'édition (lancé depuis le cache du plugin) ne peut pas lire le `.env`
|
|
@@ -2399,18 +2318,12 @@ function createAdminRouter({
|
|
|
2399
2318
|
folder.location = legalCase.root;
|
|
2400
2319
|
folder.registered = legalCase.registered;
|
|
2401
2320
|
// Les Markdown convertis vivent déjà dans l'historique ; ce cadre ne
|
|
2402
|
-
// présente que les pièces originales
|
|
2403
|
-
const mapping = readCaseMapping(legalCase.root);
|
|
2321
|
+
// présente que les pièces originales.
|
|
2404
2322
|
const [originals, branches] = await Promise.all([
|
|
2405
2323
|
listOriginalsCached(legalCase.root),
|
|
2406
2324
|
historyBranches(legalCase.casesRoot, homeDir, legalCase.caseName),
|
|
2407
2325
|
]);
|
|
2408
2326
|
folder.originals = originals;
|
|
2409
|
-
folder.mapping = {
|
|
2410
|
-
exists: mapping.exists,
|
|
2411
|
-
name: path.basename(mapping.file),
|
|
2412
|
-
entries: Object.keys(mapping.mapping).length,
|
|
2413
|
-
};
|
|
2414
2327
|
folder.branches = branches;
|
|
2415
2328
|
finishAdminTiming(res, 'case', startedAt, {
|
|
2416
2329
|
changes: folder.changes,
|
|
@@ -2691,94 +2604,6 @@ function createAdminRouter({
|
|
|
2691
2604
|
}
|
|
2692
2605
|
});
|
|
2693
2606
|
|
|
2694
|
-
// Le mapping du dossier est le seul fichier de l'administration qui contient
|
|
2695
|
-
// des données personnelles en clair : il n'est jamais journalisé, seulement
|
|
2696
|
-
// rendu au navigateur local qui l'a demandé.
|
|
2697
|
-
router.get('/mapping', (req, res) => {
|
|
2698
|
-
try {
|
|
2699
|
-
const legalCase = selectedCase(req.query.case);
|
|
2700
|
-
const mapping = readCaseMapping(legalCase.root);
|
|
2701
|
-
res.json({
|
|
2702
|
-
case: legalCase.id,
|
|
2703
|
-
name: path.basename(mapping.file),
|
|
2704
|
-
exists: mapping.exists,
|
|
2705
|
-
mapping: mapping.mapping,
|
|
2706
|
-
reverse_mapping: mapping.reverse_mapping,
|
|
2707
|
-
informations_dossier: mapping.informations_dossier,
|
|
2708
|
-
});
|
|
2709
|
-
} catch (error) {
|
|
2710
|
-
res.status(400).json({ error: error.message });
|
|
2711
|
-
}
|
|
2712
|
-
});
|
|
2713
|
-
|
|
2714
|
-
router.put('/mapping', async (req, res) => {
|
|
2715
|
-
try {
|
|
2716
|
-
if (!req.body?.mapping || typeof req.body.mapping !== 'object' || Array.isArray(req.body.mapping)) {
|
|
2717
|
-
throw new Error('Le mapping doit être un objet { entité: code }.');
|
|
2718
|
-
}
|
|
2719
|
-
const legalCase = selectedCase(req.body?.case);
|
|
2720
|
-
const saved = saveCaseMapping(legalCase.root, {
|
|
2721
|
-
mapping: req.body.mapping,
|
|
2722
|
-
reverse_mapping: req.body.reverse_mapping,
|
|
2723
|
-
...(req.body.informations_dossier !== undefined
|
|
2724
|
-
? { informations_dossier: req.body.informations_dossier }
|
|
2725
|
-
: {}),
|
|
2726
|
-
});
|
|
2727
|
-
const commit = await createCommit({
|
|
2728
|
-
casesRoot: legalCase.casesRoot,
|
|
2729
|
-
caseName: legalCase.caseName,
|
|
2730
|
-
homeDir,
|
|
2731
|
-
label: 'Modification du mapping d’anonymisation',
|
|
2732
|
-
event: 'admin-mapping-edit',
|
|
2733
|
-
paths: [path.relative(legalCase.root, saved.file).split(path.sep).join('/')],
|
|
2734
|
-
waitForLockMs: 10_000,
|
|
2735
|
-
});
|
|
2736
|
-
if (commit.skipped === 'busy') throw new Error('Mapping enregistré, mais historique occupé : commit automatique non créé.');
|
|
2737
|
-
res.json({
|
|
2738
|
-
ok: true,
|
|
2739
|
-
case: legalCase.id,
|
|
2740
|
-
name: path.basename(saved.file),
|
|
2741
|
-
exists: true,
|
|
2742
|
-
mapping: saved.mapping,
|
|
2743
|
-
reverse_mapping: saved.reverse_mapping,
|
|
2744
|
-
informations_dossier: saved.informations_dossier,
|
|
2745
|
-
commit: { created: commit.created, hash: commit.commit || null },
|
|
2746
|
-
});
|
|
2747
|
-
} catch (error) {
|
|
2748
|
-
res.status(400).json({ error: error.message });
|
|
2749
|
-
}
|
|
2750
|
-
});
|
|
2751
|
-
|
|
2752
|
-
router.post('/mapping/rebuild', async (req, res) => {
|
|
2753
|
-
try {
|
|
2754
|
-
const legalCase = selectedCase(req.body?.case);
|
|
2755
|
-
const rebuilt = await rebuildCaseMapping(legalCase.root);
|
|
2756
|
-
const commit = await createCommit({
|
|
2757
|
-
casesRoot: legalCase.casesRoot,
|
|
2758
|
-
caseName: legalCase.caseName,
|
|
2759
|
-
homeDir,
|
|
2760
|
-
label: 'Régénération du mapping d’anonymisation',
|
|
2761
|
-
event: 'admin-mapping-rebuild',
|
|
2762
|
-
paths: [path.relative(legalCase.root, rebuilt.file).split(path.sep).join('/')],
|
|
2763
|
-
waitForLockMs: 10_000,
|
|
2764
|
-
});
|
|
2765
|
-
if (commit.skipped === 'busy') throw new Error('Mapping régénéré, mais historique occupé : commit automatique non créé.');
|
|
2766
|
-
res.json({
|
|
2767
|
-
ok: true,
|
|
2768
|
-
case: legalCase.id,
|
|
2769
|
-
name: path.basename(rebuilt.file),
|
|
2770
|
-
added: rebuilt.added,
|
|
2771
|
-
total: rebuilt.total,
|
|
2772
|
-
mapping: rebuilt.mapping,
|
|
2773
|
-
reverse_mapping: rebuilt.reverse_mapping,
|
|
2774
|
-
informations_dossier: rebuilt.informations_dossier,
|
|
2775
|
-
commit: { created: commit.created, hash: commit.commit || null },
|
|
2776
|
-
});
|
|
2777
|
-
} catch (error) {
|
|
2778
|
-
res.status(400).json({ error: error.message });
|
|
2779
|
-
}
|
|
2780
|
-
});
|
|
2781
|
-
|
|
2782
2607
|
router.get('/history', async (req, res) => {
|
|
2783
2608
|
const startedAt = performance.now();
|
|
2784
2609
|
try {
|
|
@@ -2924,7 +2749,6 @@ module.exports = {
|
|
|
2924
2749
|
applyPluginComponentSelection,
|
|
2925
2750
|
checkOllamaModelUpdate,
|
|
2926
2751
|
configurationOverview,
|
|
2927
|
-
createLegalCase,
|
|
2928
2752
|
createAdminRouter,
|
|
2929
2753
|
createManagedFile,
|
|
2930
2754
|
deleteManagedAsset,
|
|
@@ -8,15 +8,6 @@ const {
|
|
|
8
8
|
} = require('../piecemaker-plugin/scripts/lib/commits.cjs');
|
|
9
9
|
const { registeredProjectFolders } = require('../piecemaker-plugin/scripts/lib/case-folders.cjs');
|
|
10
10
|
|
|
11
|
-
function readRegistryConfig(configFile) {
|
|
12
|
-
try {
|
|
13
|
-
const parsed = JSON.parse(fs.readFileSync(configFile, 'utf8'));
|
|
14
|
-
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {};
|
|
15
|
-
} catch {
|
|
16
|
-
return {};
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
11
|
function caseFolderId(folder) {
|
|
21
12
|
const digest = crypto.createHash('sha256').update(path.resolve(folder)).digest('hex').slice(0, 20);
|
|
22
13
|
return `folder-${digest}`;
|
|
@@ -71,7 +62,6 @@ module.exports = {
|
|
|
71
62
|
caseFolderId,
|
|
72
63
|
listProjectCases,
|
|
73
64
|
projectCaseEntry,
|
|
74
|
-
readRegistryConfig,
|
|
75
65
|
resolveCaseReference,
|
|
76
66
|
validateSelectedCaseFolder,
|
|
77
67
|
};
|