@piecemaker-legal/piecemaker 2.0.11 → 2.0.13

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.
Files changed (123) hide show
  1. package/dist/assets/{FindReplaceDialog-KU5TEIBJ-BucOHLdm.js → FindReplaceDialog-KU5TEIBJ-DiS1F6O4.js} +1 -1
  2. package/dist/assets/{FootnotePropertiesDialog-W3YHM4BV-D5UqbelV.js → FootnotePropertiesDialog-W3YHM4BV-BMRWztwh.js} +1 -1
  3. package/dist/assets/{HyperlinkDialog-ZYH7ZHRF-8yEhLigd.js → HyperlinkDialog-ZYH7ZHRF-D5r9CZf2.js} +4 -4
  4. package/dist/assets/{ImagePositionDialog-HEWYR6Q3-wGIBYxCm.js → ImagePositionDialog-HEWYR6Q3-EeK_GFbX.js} +1 -1
  5. package/dist/assets/{ImagePropertiesDialog-RAB47C6M-D86PckZ2.js → ImagePropertiesDialog-RAB47C6M-BgrZEZLp.js} +1 -1
  6. package/dist/assets/{PageSetupDialog-AIGIXO3E-DLETP-7v.js → PageSetupDialog-AIGIXO3E-DdFpkcLH.js} +1 -1
  7. package/dist/assets/{SplitCellDialog-IFBKYCD6-CwdQBXeb.js → SplitCellDialog-IFBKYCD6-B2J0yPH6.js} +1 -1
  8. package/dist/assets/{TablePropertiesDialog-TMLKGOOW-j2nA7KJs.js → TablePropertiesDialog-TMLKGOOW-iTyD5Vwt.js} +1 -1
  9. package/dist/assets/{WatermarkDialog-KRL7WMIS-XFJ9gTkC.js → WatermarkDialog-KRL7WMIS-CdwIWeEi.js} +1 -1
  10. package/dist/assets/{abnfDiagram-VCTEODGH-DiCrND_Y.js → abnfDiagram-VCTEODGH-CCQgv7yc.js} +1 -1
  11. package/dist/assets/{arc-DOjgbMYz.js → arc-B-Y10mRQ.js} +1 -1
  12. package/dist/assets/{architectureDiagram-5GKGNRK7-brzIFVhl.js → architectureDiagram-5GKGNRK7-C-mYZ4DW.js} +1 -1
  13. package/dist/assets/{blockDiagram-I7D4REHJ-C8JhTjQQ.js → blockDiagram-I7D4REHJ-Bby14xNO.js} +1 -1
  14. package/dist/assets/{c4Diagram-7LVT6UL2-jfYxccyk.js → c4Diagram-7LVT6UL2-CoqTzQi7.js} +1 -1
  15. package/dist/assets/channel-BxbXkYrr.js +1 -0
  16. package/dist/assets/{chunk-2Q5K7J3B-CrlEShp9.js → chunk-2Q5K7J3B-CYlmti0k.js} +1 -1
  17. package/dist/assets/{chunk-5VM5RSS4-DzPlUHGq.js → chunk-5VM5RSS4-W35KZUQj.js} +1 -1
  18. package/dist/assets/{chunk-F27PBJKO-Cp9cpeWU.js → chunk-F27PBJKO-BVIu5FJA.js} +1 -1
  19. package/dist/assets/{chunk-IMKFNOWR-BifUldEN.js → chunk-IMKFNOWR-DRf1mnVb.js} +1 -1
  20. package/dist/assets/{chunk-JWPE2WC7-ggPEIkWu.js → chunk-JWPE2WC7-CUJ1N2G9.js} +1 -1
  21. package/dist/assets/{chunk-POPQ4Y6H-3h_nayRX.js → chunk-POPQ4Y6H-p6IVobio.js} +1 -1
  22. package/dist/assets/{chunk-SVP7TREG-CH29aG6J.js → chunk-SVP7TREG-DOM_pdOM.js} +1 -1
  23. package/dist/assets/{chunk-TICWLB2K-PluJUM5k.js → chunk-TICWLB2K-VqAu84r8.js} +1 -1
  24. package/dist/assets/{chunk-XXDRQBXY-DXU39Vwg.js → chunk-XXDRQBXY-vaUsyH7g.js} +1 -1
  25. package/dist/assets/classDiagram-ZZMXUADV-COu_XNpX.js +1 -0
  26. package/dist/assets/classDiagram-v2-VYDZK3BY-COu_XNpX.js +1 -0
  27. package/dist/assets/{cose-bilkent-JH36ORCC-Dz6roYrN.js → cose-bilkent-JH36ORCC-B_sTVfyq.js} +1 -1
  28. package/dist/assets/{cynefin-OW5HDTMX-BLzrpSit.js → cynefin-OW5HDTMX-DvnWaxw0.js} +1 -1
  29. package/dist/assets/{cynefinDiagram-5FMLGOSQ-kfxnERDZ.js → cynefinDiagram-5FMLGOSQ-DriBDRYQ.js} +1 -1
  30. package/dist/assets/{dagre-GXQ25YYZ-DP57bp-N.js → dagre-GXQ25YYZ-BAwYXMGG.js} +1 -1
  31. package/dist/assets/{diagram-S7CK7UJ4-DAlsrQVW.js → diagram-S7CK7UJ4-DX03OYpD.js} +1 -1
  32. package/dist/assets/{diagram-UQ7AKVKN-By5yrMer.js → diagram-UQ7AKVKN-rdUs_hF8.js} +1 -1
  33. package/dist/assets/{diagram-VSXAHHWV-Dx89kryN.js → diagram-VSXAHHWV-CobmLXkM.js} +1 -1
  34. package/dist/assets/{diagram-VX7I27RA-B9fARitZ.js → diagram-VX7I27RA-B18D7USE.js} +1 -1
  35. package/dist/assets/{diagram-Z3DM3KII-DC15CEH1.js → diagram-Z3DM3KII-CRrNHL6r.js} +1 -1
  36. package/dist/assets/{ebnfDiagram-PWID7BFC-BKQzghGF.js → ebnfDiagram-PWID7BFC-HXzGHTn6.js} +1 -1
  37. package/dist/assets/{erDiagram-RLTQ6QDP-CPY6RM7G.js → erDiagram-RLTQ6QDP-lbfD5sxC.js} +1 -1
  38. package/dist/assets/{flowDiagram-HODETNUW-4dL4GJcf.js → flowDiagram-HODETNUW-Dd0lb1Fm.js} +1 -1
  39. package/dist/assets/{ganttDiagram-EL5Y4UJY-D4-cVcfb.js → ganttDiagram-EL5Y4UJY-CKBO9TRh.js} +1 -1
  40. package/dist/assets/{gitGraphDiagram-WWUBYQGX-BMeVIEiX.js → gitGraphDiagram-WWUBYQGX-Ds_AlKrJ.js} +1 -1
  41. package/dist/assets/index-C5slQNvE.css +1 -0
  42. package/dist/assets/{index-DNtFDOni.js → index-C9XXF765.js} +146 -146
  43. package/dist/assets/{infoDiagram-27XIBGKW-D5qMSUEU.js → infoDiagram-27XIBGKW-BbNgbn6W.js} +1 -1
  44. package/dist/assets/{ishikawaDiagram-5VMMS53U-BDnyKRHm.js → ishikawaDiagram-5VMMS53U-B9FZGWPM.js} +1 -1
  45. package/dist/assets/{journeyDiagram-3NMN7TZE-dGz5ZGzq.js → journeyDiagram-3NMN7TZE-9z26Mgkz.js} +1 -1
  46. package/dist/assets/{kanban-definition-UXKFOSKX-D7UAz7o_.js → kanban-definition-UXKFOSKX-dQoIQkFu.js} +1 -1
  47. package/dist/assets/{layout-DKrmEGrz.js → layout-C03dZv1L.js} +1 -1
  48. package/dist/assets/{linear-CrTdMY-p.js → linear-BAgwn459.js} +1 -1
  49. package/dist/assets/{mermaid.core-CXQOT5G6.js → mermaid.core-Bb-zdGYl.js} +6 -6
  50. package/dist/assets/{mindmap-definition-YA3MSWOX-VgEiYfay.js → mindmap-definition-YA3MSWOX-BZ77-g1t.js} +1 -1
  51. package/dist/assets/{pegDiagram-XKGWAZYB-9IqT8gGx.js → pegDiagram-XKGWAZYB-vlBCwMpy.js} +1 -1
  52. package/dist/assets/{pieDiagram-E7YTZNPT-D98pRE-t.js → pieDiagram-E7YTZNPT-DGaLzhN2.js} +1 -1
  53. package/dist/assets/{quadrantDiagram-AXDQQJYC-b9PwkYzL.js → quadrantDiagram-AXDQQJYC-J517wJ3s.js} +1 -1
  54. package/dist/assets/{railroadDiagram-O6MQD6OU-Dz87hsPE.js → railroadDiagram-O6MQD6OU-MiMqTB2q.js} +1 -1
  55. package/dist/assets/{requirementDiagram-BXWQKSXE-CkcV73dK.js → requirementDiagram-BXWQKSXE-ClFWrfsX.js} +1 -1
  56. package/dist/assets/{sankeyDiagram-P5KCCOFB-UBN31Yrs.js → sankeyDiagram-P5KCCOFB-BQjzvuzZ.js} +1 -1
  57. package/dist/assets/{sequenceDiagram-WJ2MYXX4-CpQxd5Za.js → sequenceDiagram-WJ2MYXX4-BVI9Mtfy.js} +1 -1
  58. package/dist/assets/{sizeCapture-INFHLROL-mCsFmyzw.js → sizeCapture-INFHLROL-npWe2anw.js} +1 -1
  59. package/dist/assets/{stateDiagram-D77RDMKH-B0MTBN-3.js → stateDiagram-D77RDMKH-BE4pwhgm.js} +1 -1
  60. package/dist/assets/{stateDiagram-v2-MP3YSRHH-DzBPN39W.js → stateDiagram-v2-MP3YSRHH-PdR5r-x_.js} +1 -1
  61. package/dist/assets/{swimlanes-42K2YHIH-Dzydjm0e.js → swimlanes-42K2YHIH-DJMuv4Fv.js} +1 -1
  62. package/dist/assets/swimlanesDiagram-VR7AAH4N-Cxv8b9_h.js +8 -0
  63. package/dist/assets/{timeline-definition-24CTP7MA-Dz0toOLu.js → timeline-definition-24CTP7MA-BLHKdXUW.js} +1 -1
  64. package/dist/assets/{vennDiagram-4TSXK5OY-DOWp7dkf.js → vennDiagram-4TSXK5OY-vpWJbaKf.js} +1 -1
  65. package/dist/assets/{wardleyDiagram-VM6X3IG4-CUxsztUB.js → wardleyDiagram-VM6X3IG4-BC1q3_Z5.js} +1 -1
  66. package/dist/assets/{xychartDiagram-S5SC5T6Z-DS96vNED.js → xychartDiagram-S5SC5T6Z--yDqjI6l.js} +1 -1
  67. package/dist/index.html +2 -2
  68. package/dist/sw.js +1 -1
  69. package/dist-server/plugins/piecemaker-dossier/src/knowledge.js +61 -1
  70. package/dist-server/plugins/piecemaker-dossier/src/knowledge.js.map +1 -1
  71. package/dist-server/plugins/piecemaker-dossier/src/scan-result.js +0 -48
  72. package/dist-server/plugins/piecemaker-dossier/src/scan-result.js.map +1 -1
  73. package/dist-server/server/piecemaker/desktop-update/service.js +2 -1
  74. package/dist-server/server/piecemaker/desktop-update/service.js.map +1 -1
  75. package/dist-server/server/piecemaker/knowledge/pipeline.js +25 -29
  76. package/dist-server/server/piecemaker/knowledge/pipeline.js.map +1 -1
  77. package/dist-server/server/piecemaker/knowledge/service.js +1 -16
  78. package/dist-server/server/piecemaker/knowledge/service.js.map +1 -1
  79. package/dist-server/server/piecemaker/project-registry.js +5 -5
  80. package/dist-server/server/piecemaker/project-registry.js.map +1 -1
  81. package/package.json +1 -1
  82. package/server/piecemaker/anonymizer/hudsucker-fixture.cjs +1 -1
  83. package/server/piecemaker/anonymizer/hudsucker-proxy/src/main.rs +2 -1
  84. package/server/piecemaker/anonymizer/rewrite.cjs +2 -2
  85. package/server/piecemaker/anonymizer/service.cjs +3 -2
  86. package/server/piecemaker/anonymizer/sqlite-dictionary.cjs +3 -31
  87. package/server/piecemaker/desktop-update/service.ts +2 -1
  88. package/server/piecemaker/index.ts +1 -1
  89. package/server/piecemaker/knowledge/pipeline.ts +24 -31
  90. package/server/piecemaker/knowledge/service.ts +1 -14
  91. package/server/piecemaker/project-registry.ts +6 -6
  92. package/server/piecemaker/vendor/installer/bin/piecemaker.mjs +9 -162
  93. package/server/piecemaker/vendor/installer/lib/commandes.mjs +1 -2
  94. package/server/piecemaker/vendor/installer/lib/conversion-client.mjs +62 -3
  95. package/server/piecemaker/vendor/installer/steps/06-hooks.mjs +23 -69
  96. package/server/piecemaker/vendor/installer/steps/12-mcp-piecemaker.mjs +3 -3
  97. package/server/piecemaker/vendor/mcp/README.md +1 -1
  98. package/server/piecemaker/vendor/mcp/piecemaker/server.mjs +12 -75
  99. package/server/piecemaker/vendor/piecemaker-plugin/hooks/hooks.json +0 -40
  100. package/server/piecemaker/vendor/piecemaker-plugin/scripts/compile-recherche.mjs +2 -2
  101. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/case-folders.cjs +26 -7
  102. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/commits.cjs +0 -28
  103. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/hook-io.mjs +0 -13
  104. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/institutional-terms.cjs +3 -3
  105. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/mapping.cjs +10 -143
  106. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/protection.cjs +1 -1
  107. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/session-timing.cjs +0 -65
  108. package/server/piecemaker/vendor/piecemaker-plugin/scripts/protect-originals.mjs +11 -2
  109. package/server/piecemaker/vendor/piecemaker-plugin/skills/conversion-md/SKILL.md +9 -5
  110. package/server/piecemaker/vendor/websocket-server/admin-routes.cjs +2 -150
  111. package/server/piecemaker/vendor/websocket-server/claude-hooks.cjs +3 -0
  112. package/server/piecemaker/vendor/websocket-server/originals-pipeline.cjs +23 -372
  113. package/server/piecemaker/vendor/websocket-server/renamed-originals.cjs +136 -0
  114. package/server/piecemaker/vendor/websocket-server/scripts/convert_and_scan_pipeline.py +115 -96
  115. package/dist/assets/channel-Dajzu2W1.js +0 -1
  116. package/dist/assets/classDiagram-ZZMXUADV-dDEP_giv.js +0 -1
  117. package/dist/assets/classDiagram-v2-VYDZK3BY-dDEP_giv.js +0 -1
  118. package/dist/assets/index-Dc9wNuS4.css +0 -1
  119. package/dist/assets/swimlanesDiagram-VR7AAH4N-BXQpbUMD.js +0 -8
  120. package/server/piecemaker/vendor/piecemaker-plugin/scripts/billing-track.mjs +0 -194
  121. package/server/piecemaker/vendor/piecemaker-plugin/scripts/commit-track.mjs +0 -71
  122. package/server/piecemaker/vendor/piecemaker-plugin/scripts/session-commit-worker.mjs +0 -260
  123. package/server/piecemaker/vendor/piecemaker-plugin/scripts/session-commit.mjs +0 -83
@@ -8,11 +8,6 @@
8
8
  *
9
9
  * Usage:
10
10
  * piecemaker menu interactif
11
- * piecemaker chronology affiche la chronologie du dossier courant
12
- * piecemaker chronology write --path <pièce> --correction-json <json>
13
- * crée une correction de chronologie pour une pièce
14
- * piecemaker chronology edit --path <pièce> --correction-json <json>
15
- * modifie une correction de chronologie existante
16
11
  * piecemaker conversion convertit et pseudonymise les pièces manquantes
17
12
  * piecemaker install ouvre le menu des composants
18
13
  * piecemaker doctor diagnostic seul
@@ -33,16 +28,15 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
33
28
  import { banner, title, log, write, blank, summary, spinner, badge, c } from '../lib/ui.mjs';
34
29
  import { select, confirm, multiSelect, pause, nonInteractive } from '../lib/prompt.mjs';
35
30
  import { GIT_REPO_ROOT, HOME_DIR, REPO_ROOT, commandExists, findPython } from '../lib/platform.mjs';
36
- import { COMMANDS, CHRONOLOGY_ACTIONS } from '../lib/commandes.mjs';
31
+ import { COMMANDS } from '../lib/commandes.mjs';
37
32
  import { loadConfig, readEnv, markStep, loadState, CONFIG_FILE } from '../lib/state.mjs';
38
33
  import { scheduleStepResume, selectStepsToResume } from '../lib/resume-steps.mjs';
39
- import { appServerPort, readLocalScanJob, startLocalScan } from '../lib/conversion-client.mjs';
34
+ import { adoptRunningServerPort, appServerPort, localServerReachable, readLocalScanJob, startLocalScan } from '../lib/conversion-client.mjs';
40
35
  import { checkForUpdate, updateRepository } from '../lib/service.mjs';
41
36
 
42
37
  const require = createRequire(import.meta.url);
43
38
  const CLAUDE_ASSETS_MODULE = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../websocket-server/claude-assets.cjs');
44
39
  const CLAUDE_HOOKS_MODULE = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../websocket-server/claude-hooks.cjs');
45
- const DOCUMENT_INDEX_MODULE = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../websocket-server/document-index.cjs');
46
40
  const ORIGINALS_PIPELINE_MODULE = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../websocket-server/originals-pipeline.cjs');
47
41
  const APP_CLI_LIB = path.join(GIT_REPO_ROOT, 'scripts', 'piecemaker', 'cli', 'lib');
48
42
 
@@ -129,11 +123,8 @@ function parseArgs(argv) {
129
123
  check: false,
130
124
  dryRun: false,
131
125
  conversionDocuments: [],
132
- correctionJson: null,
133
126
  force: false,
134
- chronologyAction: 'read',
135
127
  json: false,
136
- piecePath: null,
137
128
  resumeSteps: null,
138
129
  step: null,
139
130
  yes: false,
@@ -142,18 +133,13 @@ function parseArgs(argv) {
142
133
  for (let i = 0; i < argv.length; i++) {
143
134
  const arg = argv[i];
144
135
  if (!arg.startsWith('-') && !flags.command && COMMANDS.has(arg)) flags.command = arg;
145
- else if (!arg.startsWith('-') && flags.command === 'chronology' && flags.chronologyAction === 'read' && CHRONOLOGY_ACTIONS.has(arg)) flags.chronologyAction = arg;
146
- else if (!arg.startsWith('-') && flags.command === 'chronology' && !flags.caseTarget) flags.caseTarget = arg;
147
136
  else if (!arg.startsWith('-') && flags.command === 'conversion') flags.conversionDocuments.push(arg);
148
137
  else if (arg === '--all') flags.all = true;
149
- else if (arg === '--action') flags.chronologyAction = argv[++i];
150
138
  else if (arg === '--case') flags.caseTarget = argv[++i];
151
139
  else if (arg === '--check') flags.check = true;
152
- else if (arg === '--correction-json') flags.correctionJson = argv[++i];
153
140
  else if (arg === '--dry-run') flags.dryRun = true;
154
141
  else if (arg === '--force') flags.force = true;
155
142
  else if (arg === '--json') flags.json = true;
156
- else if (arg === '--path') flags.piecePath = argv[++i];
157
143
  else if (arg === '--yes' || arg === '-y') flags.yes = true;
158
144
  else if (arg === '--step') flags.step = argv[++i];
159
145
  else if (arg === '--resume-steps') {
@@ -313,20 +299,15 @@ async function runCheck(steps, ctx) {
313
299
  function printHelp() {
314
300
  write(` ${c.bold('piecemaker')} — PieceMaker local`);
315
301
  blank();
316
- write(' chronology [read] affiche la chronologie pseudonymisée du dossier courant');
317
- write(' chronology write --path <pièce> --correction-json <json> crée une correction de chronologie');
318
- write(' chronology edit --path <pièce> --correction-json <json> modifie une correction existante');
319
302
  write(' conversion [pièce…] convertit et pseudonymise les pièces manquantes ou indiquées');
320
303
  write(' install ouvre le menu d’installation/réparation');
321
304
  write(' doctor, check diagnostic seul, n’installe rien');
322
305
  write(' update met à jour PieceMaker');
323
306
  blank();
324
307
  write(' --all installe tout sans menu');
325
- write(' --case <chemin> cible un dossier enregistré (chronology/conversion)');
326
- write(' --path <pièce> chemin relatif de la pièce (chronology write/edit)');
327
- write(' --correction-json <json> correction à appliquer (chronology write/edit)');
308
+ write(' --case <chemin> cible un dossier enregistré (conversion)');
328
309
  write(' --force retraite les pièces');
329
- write(' --json produit une sortie JSON sans décor (chronology/conversion)');
310
+ write(' --json produit une sortie JSON sans décor (conversion)');
330
311
  write(' --check diagnostic seul, n\'installe rien');
331
312
  write(' --step <id> rejoue une seule étape');
332
313
  write(' --resume-steps <ids> rejoue les étapes indiquées sans interaction (usage interne)');
@@ -375,135 +356,6 @@ async function installerMenu(steps, ctx, { allowBack = false } = {}) {
375
356
  }
376
357
  }
377
358
 
378
- function formatChronologyText(chronology) {
379
- const lines = [];
380
- lines.push(`Chronologie : ${chronology.stats.documents} pièce(s), ${chronology.stats.dated} datée(s), ${chronology.stats.entities} entité(s).`);
381
- lines.push('');
382
- for (const doc of chronology.documents) {
383
- lines.push(`${doc.dateIso || '(date manquante)'} ${doc.nature || '(nature inconnue)'} ${doc.name}`);
384
- }
385
- const missing = chronology.documents.filter((doc) => !doc.dateIso);
386
- if (missing.length) {
387
- lines.push('');
388
- lines.push('Dates manquantes :');
389
- for (const doc of missing) lines.push(` - ${doc.name}`);
390
- }
391
- return `${lines.join('\n')}\n`;
392
- }
393
-
394
- function locateChronologyCase(flags) {
395
- const { locateProjectCase } = require('../../piecemaker-plugin/scripts/lib/case-folders.cjs');
396
- const located = locateProjectCase(flags.caseTarget || process.cwd());
397
- if (!located) {
398
- throw new Error('Lancez la commande depuis un dossier juridique enregistré ou passez --case <chemin>.');
399
- }
400
- return located;
401
- }
402
-
403
- async function runChronologyReadCommand(flags) {
404
- if (!fs.existsSync(DOCUMENT_INDEX_MODULE)) {
405
- throw new Error('Le module de chronologie PieceMaker est introuvable.');
406
- }
407
- const located = locateChronologyCase(flags);
408
- const { buildChronology } = require(DOCUMENT_INDEX_MODULE);
409
- const chronology = await buildChronology(located.caseRoot, { deanonymizeLabels: false, includeManualDecisions: true });
410
- const output = flags.json
411
- ? `${JSON.stringify(chronology, null, 2)}\n`
412
- : formatChronologyText(chronology);
413
- process.stdout.write(output);
414
- return 0;
415
- }
416
-
417
- function resolveChronologyPiecePath(caseRoot, relativePath) {
418
- const relative = String(relativePath || '').replaceAll('\\', '/').replace(/^\.\//, '');
419
- if (!relative) throw new Error('Chemin de pièce manquant.');
420
- const absolute = path.resolve(caseRoot, ...relative.split('/'));
421
- if (absolute !== caseRoot && !absolute.startsWith(`${caseRoot}${path.sep}`)) {
422
- throw new Error('Pièce hors du dossier juridique.');
423
- }
424
- if (!fs.existsSync(absolute)) throw new Error('Pièce introuvable.');
425
- return relative;
426
- }
427
-
428
- async function runChronologyCorrectionCommand(flags) {
429
- if (!fs.existsSync(DOCUMENT_INDEX_MODULE)) {
430
- throw new Error('Le module de chronologie PieceMaker est introuvable.');
431
- }
432
- const located = locateChronologyCase(flags);
433
- const relative = resolveChronologyPiecePath(located.caseRoot, flags.piecePath);
434
-
435
- let correction;
436
- try {
437
- correction = JSON.parse(flags.correctionJson || '{}');
438
- } catch (error) {
439
- throw new Error(`Correction JSON invalide : ${error.message}`);
440
- }
441
-
442
- const { stateKey } = require('../../piecemaker-plugin/scripts/lib/anonymization-state.cjs');
443
- const { applyDocumentIndexCorrection, readDocumentIndex, documentIndexFile } = require(DOCUMENT_INDEX_MODULE);
444
- const key = stateKey(relative);
445
- const existing = readDocumentIndex(located.caseRoot).overrides[key] || null;
446
-
447
- if (flags.chronologyAction === 'write' && existing) {
448
- throw new Error('Une correction existe déjà pour cette pièce ; utilisez edit_chronology pour la modifier.');
449
- }
450
- if (flags.chronologyAction === 'edit' && !existing) {
451
- throw new Error('Aucune correction existante pour cette pièce ; utilisez write_chronology pour en créer une.');
452
- }
453
-
454
- const mutation = applyDocumentIndexCorrection(located.caseRoot, relative, correction);
455
-
456
- let history;
457
- try {
458
- const { createCommit } = require('../../piecemaker-plugin/scripts/lib/commits.cjs');
459
- history = await createCommit({
460
- casesRoot: located.casesRoot,
461
- caseName: located.caseName,
462
- homeDir: HOME_DIR,
463
- envFile: path.join(REPO_ROOT, '.env'),
464
- label: flags.chronologyAction === 'write'
465
- ? 'Création d’une correction de chronologie'
466
- : 'Modification d’une correction de chronologie',
467
- description: `Mise à jour déterministe de la pièce ${mutation.documentKey.slice(0, 12).toUpperCase()}.`,
468
- event: 'assistant-chronology-correction',
469
- paths: [path.relative(located.caseRoot, documentIndexFile(located.caseRoot)).split(path.sep).join('/')],
470
- waitForLockMs: 10_000,
471
- });
472
- } catch (error) {
473
- history = { created: false, error: error.message };
474
- }
475
-
476
- const result = {
477
- ok: true,
478
- action: flags.chronologyAction,
479
- path: relative,
480
- documentKey: mutation.documentKey,
481
- override: mutation.override,
482
- entityDecisions: mutation.entityDecisions,
483
- editRevision: mutation.editRevision,
484
- history: {
485
- created: Boolean(history?.created),
486
- hash: history?.commit || null,
487
- error: history?.error || null,
488
- },
489
- };
490
-
491
- if (flags.json) {
492
- process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
493
- } else {
494
- const verb = flags.chronologyAction === 'write' ? 'Correction créée' : 'Correction modifiée';
495
- log.ok(`${verb} pour ${relative}.`);
496
- }
497
- return 0;
498
- }
499
-
500
- async function runChronologyCommand(flags) {
501
- if (flags.chronologyAction === 'write' || flags.chronologyAction === 'edit') {
502
- return runChronologyCorrectionCommand(flags);
503
- }
504
- return runChronologyReadCommand(flags);
505
- }
506
-
507
359
  function normalizedConversionRequest(value, caseRoot) {
508
360
  const raw = String(value || '').trim();
509
361
  if (!raw) throw new Error('Nom de pièce vide.');
@@ -570,6 +422,8 @@ async function waitForConversionJob({ folder, id }, { json = false } = {}) {
570
422
  }
571
423
 
572
424
  async function ensureServerForConversion({ json = false } = {}) {
425
+ await adoptRunningServerPort();
426
+ if (await localServerReachable()) return;
573
427
  const servicesModule = path.join(APP_CLI_LIB, 'services.mjs');
574
428
  if (!fs.existsSync(servicesModule)) {
575
429
  throw new Error(`Le serveur applicatif doit être démarré par la commande « piecemaker » avant la conversion (port ${appServerPort()}).`);
@@ -625,7 +479,6 @@ async function runConversionCommand(flags) {
625
479
  }
626
480
 
627
481
  async function runOperationalCommand(command, knownUpdate = null, flags = {}) {
628
- if (command === 'chronology') return runChronologyCommand(flags);
629
482
  if (command === 'conversion') return runConversionCommand(flags);
630
483
  if (command === 'update') {
631
484
  const pending = knownUpdate ?? checkForUpdate();
@@ -749,20 +602,14 @@ async function main() {
749
602
  return 1;
750
603
  }
751
604
 
752
- if (!['chronology', 'conversion'].includes(flags.command) && (flags.caseTarget || flags.json)) {
605
+ if (flags.command !== 'conversion' && (flags.caseTarget || flags.json)) {
753
606
  banner();
754
- log.error('Les options --case et --json sont réservées aux commandes chronology et conversion.');
755
- return 1;
756
- }
757
-
758
- if (flags.command === 'chronology' && !CHRONOLOGY_ACTIONS.has(flags.chronologyAction)) {
759
- log.error('Action inconnue : utilisez « piecemaker chronology read|write|edit ».');
607
+ log.error('Les options --case et --json sont réservées à la commande conversion.');
760
608
  return 1;
761
609
  }
762
610
 
763
611
  // Les sorties JSON sont directement consommées par les assistants.
764
- if ((flags.command === 'chronology' && flags.json)
765
- || (flags.command === 'conversion' && flags.json)) {
612
+ if (flags.command === 'conversion' && flags.json) {
766
613
  return runOperationalCommand(flags.command, null, flags);
767
614
  }
768
615
 
@@ -7,5 +7,4 @@
7
7
  * est importable sans effet de bord.
8
8
  */
9
9
 
10
- export const COMMANDS = new Set(['chronology', 'conversion', 'install', 'doctor', 'check', 'update']);
11
- export const CHRONOLOGY_ACTIONS = new Set(['read', 'write', 'edit']);
10
+ export const COMMANDS = new Set(['conversion', 'install', 'doctor', 'check', 'update']);
@@ -4,20 +4,79 @@
4
4
  * La conversion et l'analyse PII n'ont qu'un seul point d'entrée : la route
5
5
  * `knowledge/scan` du serveur applicatif. Le CLI en est un client, sur la
6
6
  * boucle locale, via le montage `/api/piecemaker/local` placé avant
7
- * l'authentification. Le serveur applicatif écoute en clair sur le port du
8
- * CLI (`PIECEMAKER_APP_PORT`, 3003 par défaut) : aucun certificat n'entre en
9
- * jeu et la requête ne sort jamais de 127.0.0.1.
7
+ * l'authentification. Le serveur applicatif écoute en clair sur la boucle
8
+ * locale : celui qui tourne déjà (application de bureau comprise, annoncé par
9
+ * `local-server.json` dans le dossier de données), sinon le port du CLI
10
+ * (`PIECEMAKER_APP_PORT`, 3003 par défaut). Aucun certificat n'entre en jeu et
11
+ * la requête ne sort jamais de 127.0.0.1.
10
12
  */
11
13
 
14
+ import fs from 'node:fs';
12
15
  import http from 'node:http';
16
+ import os from 'node:os';
17
+ import { join } from 'node:path';
18
+
19
+ import { GIT_REPO_ROOT } from './platform.mjs';
13
20
 
14
21
  const LOCAL_BASE = '/api/piecemaker/local';
22
+ const LOOPBACK_HOSTS = new Set(['127.0.0.1', 'localhost', '::1', '0.0.0.0', '::']);
15
23
 
16
24
  export function appServerPort() {
17
25
  const parsed = Number.parseInt(process.env.PIECEMAKER_APP_PORT || '', 10);
18
26
  return Number.isInteger(parsed) && parsed > 0 ? parsed : 3003;
19
27
  }
20
28
 
29
+ function runningServerMarkerPath() {
30
+ if (process.env.CLOUDCLI_HOME) return join(process.env.CLOUDCLI_HOME, 'local-server.json');
31
+ try {
32
+ const config = JSON.parse(fs.readFileSync(join(GIT_REPO_ROOT, 'product.config.json'), 'utf8'));
33
+ return join(os.homedir(), config.dataDirectoryName, 'local-server.json');
34
+ } catch {
35
+ return null;
36
+ }
37
+ }
38
+
39
+ function processAlive(pid) {
40
+ try {
41
+ process.kill(pid, 0);
42
+ return true;
43
+ } catch (error) {
44
+ return error.code === 'EPERM';
45
+ }
46
+ }
47
+
48
+ export function runningServerPort(markerPath = runningServerMarkerPath()) {
49
+ if (!markerPath) return null;
50
+ try {
51
+ const marker = JSON.parse(fs.readFileSync(markerPath, 'utf8'));
52
+ const port = Number(marker?.port);
53
+ const pid = Number(marker?.pid);
54
+ if (!Number.isInteger(port) || port <= 0 || !LOOPBACK_HOSTS.has(marker?.host)) return null;
55
+ if (!Number.isInteger(pid) || pid <= 0 || !processAlive(pid)) return null;
56
+ return port;
57
+ } catch {
58
+ return null;
59
+ }
60
+ }
61
+
62
+ export function localServerReachable(port = appServerPort()) {
63
+ return new Promise((resolve) => {
64
+ const request = http.get({ hostname: '127.0.0.1', port, path: '/api/auth/status', timeout: 2_000 }, (response) => {
65
+ response.resume();
66
+ resolve(response.statusCode < 500);
67
+ });
68
+ request.on('timeout', () => request.destroy());
69
+ request.on('error', () => resolve(false));
70
+ });
71
+ }
72
+
73
+ export async function adoptRunningServerPort({ markerPath, reachable = localServerReachable } = {}) {
74
+ if (process.env.PIECEMAKER_APP_PORT) return appServerPort();
75
+ const port = runningServerPort(markerPath);
76
+ if (port && await reachable(port)) process.env.PIECEMAKER_APP_PORT = String(port);
77
+ return appServerPort();
78
+ }
79
+
21
80
  function requestJson({ method, path, body }) {
22
81
  const payload = body === undefined ? null : Buffer.from(JSON.stringify(body));
23
82
  return new Promise((resolve, reject) => {
@@ -1,8 +1,7 @@
1
1
  /**
2
- * Étape 06 — hooks Claude Code (protection, commits, facturation).
2
+ * Étape 06 — hooks Claude Code (protection des pièces, recherche, documents IA).
3
3
  *
4
- * Écrit la configuration d'exécution des hooks dans ~/.piecemaker/config.json,
5
- * puis prouve que chaque script tourne proprement en lui envoyant une charge
4
+ * Prouve que chaque script tourne proprement en lui envoyant une charge
6
5
  * utile synthétique sur stdin — le contrat exact qu'utilise Claude Code (voir
7
6
  * piecemaker-plugin/scripts/lib/hook-io.mjs).
8
7
  *
@@ -17,8 +16,7 @@ import os from 'node:os';
17
16
  import path from 'node:path';
18
17
  import { createRequire } from 'node:module';
19
18
  import { log, spinner } from '../lib/ui.mjs';
20
- import { REPO_ROOT, HOME_DIR, runCapture, ensureDir } from '../lib/platform.mjs';
21
- import { updateConfig } from '../lib/state.mjs';
19
+ import { HOME_DIR, REPO_ROOT, runCapture } from '../lib/platform.mjs';
22
20
 
23
21
  const require = createRequire(import.meta.url);
24
22
  const {
@@ -30,21 +28,17 @@ const {
30
28
 
31
29
  export const meta = {
32
30
  id: '06-hooks',
33
- label: 'Hooks Claude Code (protection, commits & facturation)',
34
- description: 'Configure les garde-fous, les commits PostToolUse et le suivi de facturation',
31
+ label: 'Hooks Claude Code (protection des pièces)',
32
+ description: 'Configure les garde-fous et les hooks de recherche et de classement des documents IA',
35
33
  };
36
34
 
37
35
  const PLUGIN_ROOT = path.join(REPO_ROOT, 'piecemaker-plugin');
38
36
  const SCRIPTS_DIR = path.join(PLUGIN_ROOT, 'scripts');
39
37
  const HOOKS_JSON = path.join(PLUGIN_ROOT, 'hooks', 'hooks.json');
40
- const BILLING_DIR = path.join(HOME_DIR, 'billing');
41
- const SYNTHESE_DIR = path.join(BILLING_DIR, 'synthese');
42
38
 
43
39
  const HOOK_SCRIPTS = {
44
40
  protect: path.join(SCRIPTS_DIR, 'protect-originals.mjs'),
45
- commit: path.join(SCRIPTS_DIR, 'commit-track.mjs'),
46
41
  classify: path.join(SCRIPTS_DIR, 'classify-ai-documents.mjs'),
47
- billing: path.join(SCRIPTS_DIR, 'billing-track.mjs'),
48
42
  statusline: path.join(SCRIPTS_DIR, 'statusline.mjs'),
49
43
  };
50
44
 
@@ -73,29 +67,12 @@ function runHookSelfTest(label, scriptPath, payload) {
73
67
  return { label, ok: false, note: 'sortie stdout non-JSON — contrat de hook invalide' };
74
68
  }
75
69
  }
76
- return { label, ok: true, note: result.stdout ? 'sortie JSON valide' : 'exit 0 (aucune sortie)' };
70
+ return { label, ok: true, stdout: result.stdout, note: result.stdout ? 'sortie JSON valide' : 'exit 0 (aucune sortie)' };
77
71
  }
78
72
 
79
73
  export async function install(ctx) {
80
- log.step('Répertoires de facturation...');
81
- if (!ctx.dryRun) {
82
- ensureDir(BILLING_DIR);
83
- ensureDir(SYNTHESE_DIR);
84
- }
85
- log.ok(`${BILLING_DIR}`);
86
-
87
74
  if (ctx.dryRun) {
88
- log.info('[simulation] configuration commits/facturation non écrite');
89
75
  log.info('[simulation] hooks PieceMaker fusionnés directement dans ~/.claude/settings.json');
90
- } else {
91
- updateConfig({
92
- commits: { enabled: true, timeoutMs: 8000 },
93
- billing: { enabled: true },
94
- });
95
- log.ok('Configuration écrite dans ~/.piecemaker/config.json (commits, billing)');
96
- }
97
-
98
- if (ctx.dryRun) {
99
76
  return { status: 'skipped', note: 'Mode simulation — hooks non vérifiés.' };
100
77
  }
101
78
 
@@ -109,10 +86,14 @@ export async function install(ctx) {
109
86
  // Un vrai dossier juridique factice, sans point de tête : les hooks
110
87
  // ignorent les répertoires cachés, un bac de test caché ne prouverait donc
111
88
  // rien du garde-fou. Comme seul un projet publié est un dossier juridique,
112
- // on le publie le temps du test sous une source dédiée, retirée ensuite.
113
- testDir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'piecemaker-hook-selftest-')));
89
+ // on le publie le temps du test sous une source dédiée, retirée ensuite,
90
+ // et comme anonymisé : le garde-fou n'agit que sous un bouclier vert.
91
+ // Les dossiers temporaires du système ne sont jamais des dossiers
92
+ // juridiques : le bac vit donc dans le répertoire PieceMaker.
93
+ fs.mkdirSync(HOME_DIR, { recursive: true });
94
+ testDir = fs.realpathSync(fs.mkdtempSync(path.join(HOME_DIR, 'hook-selftest-')));
114
95
  fs.writeFileSync(path.join(testDir, 'piece-selftest.pdf'), 'PIECE DE TEST', 'utf8');
115
- publishProjectSource('installer-selftest', [testDir]);
96
+ publishProjectSource('installer-selftest', [testDir], [testDir]);
116
97
  selftestRegistered = true;
117
98
 
118
99
  // 1. protect-originals.mjs — une pièce du bac de test : protégée par
@@ -127,38 +108,15 @@ export async function install(ctx) {
127
108
  tool_input: { file_path: path.join(testDir, 'piece-selftest.pdf') },
128
109
  tool_use_id: 'toolu_installer_originals_selftest',
129
110
  });
111
+ if (protectedResult.ok && !/"permissionDecision"\s*:\s*"deny"/.test(protectedResult.stdout || '')) {
112
+ protectedResult.ok = false;
113
+ protectedResult.note = 'la pièce du bac de test n\'a pas été bloquée';
114
+ } else if (protectedResult.ok) {
115
+ protectedResult.note = 'pièce protégée bloquée';
116
+ }
130
117
  testResults.push(protectedResult);
131
118
 
132
- // 2. commit-track.mjs — réponse d'outil en échec : exerce le contrat
133
- // d'entrée/sortie sans créer de vrai commit pendant l'installation.
134
- const commitResult = runHookSelfTest('commit-track.mjs', HOOK_SCRIPTS.commit, {
135
- hook_event_name: 'PostToolUse',
136
- session_id: 'installer-selftest',
137
- cwd: REPO_ROOT,
138
- transcript_path: '',
139
- permission_mode: 'default',
140
- tool_name: 'Edit',
141
- tool_input: { file_path: path.join(REPO_ROOT, 'README.md') },
142
- tool_response: { success: false },
143
- tool_use_id: 'toolu_installer_commit_selftest',
144
- });
145
- testResults.push(commitResult);
146
-
147
- // 3. billing-track.mjs — une vraie charge utile Stop : ajoute une ligne
148
- // (clairement identifiée) au registre du mois et écrit une synthèse,
149
- // ce qui prouve le chemin d'écriture de bout en bout.
150
- const billingResult = runHookSelfTest('billing-track.mjs', HOOK_SCRIPTS.billing, {
151
- hook_event_name: 'Stop',
152
- session_id: 'installer-selftest',
153
- cwd: REPO_ROOT,
154
- transcript_path: path.join(testDir, 'transcript-selftest.jsonl'),
155
- permission_mode: 'default',
156
- last_assistant_message: 'Test d\'installation PieceMaker — vérification du hook de facturation.',
157
- stop_reason: 'end_turn',
158
- });
159
- testResults.push(billingResult);
160
-
161
- // 4. classify-ai-documents.mjs — un document « créé par l'IA » dans le bac
119
+ // 2. classify-ai-documents.mjs — un document « créé par l'IA » dans le bac
162
120
  // de test enregistré doit ressortir classé « espace de travail » dans
163
121
  // `.piecemaker/protection.json`, sans quoi l'IA ne pourrait pas se
164
122
  // relire. On vérifie l'effet de bord, pas seulement le code de sortie.
@@ -201,7 +159,6 @@ export async function install(ctx) {
201
159
  if (r.ok) log.ok(`${r.label} : ${r.note}`);
202
160
  else log.error(`${r.label} : ${r.note}`);
203
161
  }
204
- log.detail(`Une ligne de test a été ajoutée à ${path.join(BILLING_DIR, `${new Date().toISOString().slice(0, 7)}.jsonl`)} (session "installer-selftest") — supprimez-la si besoin.`);
205
162
  if (!fs.existsSync(HOOKS_JSON)) {
206
163
  log.warn(`hooks/hooks.json introuvable dans le plugin : ${HOOKS_JSON}`);
207
164
  }
@@ -232,12 +189,9 @@ export async function install(ctx) {
232
189
  return { status: 'done', note: '' };
233
190
  }
234
191
 
235
- export async function check(ctx) {
192
+ export async function check() {
236
193
  const scriptsExist = Object.values(HOOK_SCRIPTS).every((p) => fs.existsSync(p));
237
194
  const hooksJsonExists = fs.existsSync(HOOKS_JSON);
238
- const dirsExist = fs.existsSync(BILLING_DIR) && fs.existsSync(SYNTHESE_DIR);
239
- const cfg = ctx.config || {};
240
- const configOk = Boolean(cfg.commits && cfg.billing);
241
195
  const hooksRegistered = claudeHooksStatus(REPO_ROOT, os.homedir()).ok;
242
196
  const statusLine = claudeStatusLineStatus(REPO_ROOT, os.homedir());
243
197
  const statusLineOk = statusLine.ok || statusLine.conflict; // une statusLine personnelle n'est pas une anomalie
@@ -245,8 +199,8 @@ export async function check(ctx) {
245
199
  if (!scriptsExist || !hooksJsonExists) {
246
200
  return { status: 'failed', note: 'Fichiers du plugin manquants (scripts ou hooks.json) — réinstallez piecemaker-plugin/.' };
247
201
  }
248
- if (!dirsExist || !configOk || !hooksRegistered) {
249
- return { status: 'partial', note: 'Scripts présents mais configuration, enregistrement Claude ou répertoires de facturation incomplets — relancez cette étape.' };
202
+ if (!hooksRegistered) {
203
+ return { status: 'partial', note: 'Scripts présents mais hooks non enregistrés dans Claude Code — relancez cette étape.' };
250
204
  }
251
205
  if (!statusLineOk) {
252
206
  return { status: 'partial', note: `statusLine Claude Code absente ou périmée (${statusLine.reason}) — relancez cette étape.` };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Étape 12 — serveur MCP « piecemaker » (conversion, chronologie).
2
+ * Étape 12 — serveur MCP « piecemaker » (conversion).
3
3
  *
4
4
  * Les commandes de conversion sont aujourd'hui présentées au
5
5
  * modèle par du texte injecté dans les templates, sans rien qui relie ce
@@ -21,8 +21,8 @@ import { REPO_ROOT, commandExists, run, runCapture } from '../lib/platform.mjs';
21
21
 
22
22
  export const meta = {
23
23
  id: '12-mcp-piecemaker',
24
- label: 'Serveur MCP piecemaker (conversion, chronologie)',
25
- description: 'Enregistre dans Claude Code le serveur MCP qui expose la conversion et la chronologie',
24
+ label: 'Serveur MCP piecemaker (conversion)',
25
+ description: 'Enregistre dans Claude Code le serveur MCP qui expose la conversion',
26
26
  };
27
27
 
28
28
  const SERVER_NAME = 'piecemaker';
@@ -1,7 +1,7 @@
1
1
  # MCP PieceMaker
2
2
 
3
3
  Point d'entrée du serveur MCP `piecemaker` (`piecemaker/server.mjs`), qui expose
4
- les outils `chronologie` et `conversion` en pilotant
4
+ l'outil `conversion` en pilotant
5
5
  `installer/bin/piecemaker.mjs`.
6
6
 
7
7
  - `REPO_ROOT`, calculé deux niveaux au-dessus de ce fichier, résout vers