plan-assistant 1.3.3 → 1.4.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.
Files changed (103) hide show
  1. package/build/client/_app/immutable/chunks/{BJs6I7qC.js → 10ZXP06Q.js} +1 -1
  2. package/build/client/_app/immutable/chunks/{ChJyFfSj.js → 1eL0zcBS.js} +1 -1
  3. package/build/client/_app/immutable/chunks/74GYr5Jz.js +3 -0
  4. package/build/client/_app/immutable/chunks/{B2fFwvWw.js → B-HTmPy1.js} +1 -1
  5. package/build/client/_app/immutable/chunks/{RIGBV7Ip.js → B2hVYoEJ.js} +1 -1
  6. package/build/client/_app/immutable/chunks/{DVXd8vwC.js → B628eJGB.js} +1 -1
  7. package/build/client/_app/immutable/chunks/{CpucjHJL.js → B80ongyB.js} +1 -1
  8. package/build/client/_app/immutable/chunks/{BXCtgyOT.js → B8FhIQG1.js} +1 -1
  9. package/build/client/_app/immutable/chunks/{DoIz7SoC.js → BCgSWfby.js} +1 -1
  10. package/build/client/_app/immutable/chunks/{B-25Ue8o.js → BFl4ofgi.js} +4 -4
  11. package/build/client/_app/immutable/chunks/{DK1zqZrn.js → BIKGXasq.js} +1 -1
  12. package/build/client/_app/immutable/chunks/{DlbZX2EZ.js → BNv9nR-i.js} +1 -1
  13. package/build/client/_app/immutable/chunks/{CeIvvAVV.js → BOjlNXC_.js} +1 -1
  14. package/build/client/_app/immutable/chunks/{a5eoTq-5.js → BRBMkxQw.js} +1 -1
  15. package/build/client/_app/immutable/chunks/{_2rlQOMN.js → BT3ImTYg.js} +1 -1
  16. package/build/client/_app/immutable/chunks/{BJxAjYQA.js → BUu_XsOv.js} +1 -1
  17. package/build/client/_app/immutable/chunks/{B9WViv7H.js → BVq6bo_n.js} +1 -1
  18. package/build/client/_app/immutable/chunks/{DteI5BLO.js → BZQqs639.js} +1 -1
  19. package/build/client/_app/immutable/chunks/{nFhgrnCT.js → BZTb6H6F.js} +1 -1
  20. package/build/client/_app/immutable/chunks/{Dl-inTne.js → BrjAEg64.js} +1 -1
  21. package/build/client/_app/immutable/chunks/{DSIQf7-a.js → Bt3MWn7w.js} +26 -26
  22. package/build/client/_app/immutable/chunks/{Dnz2r_pS.js → BvzznBFq.js} +1 -1
  23. package/build/client/_app/immutable/chunks/{DshYkidx.js → C4gCk_ik.js} +1 -1
  24. package/build/client/_app/immutable/chunks/{2wZlHG5k.js → C5wtj4WQ.js} +1 -1
  25. package/build/client/_app/immutable/chunks/{Dvli4fnO.js → CEqaJ7Yk.js} +1 -1
  26. package/build/client/_app/immutable/chunks/{3E04qp8C.js → CIGAXayx.js} +1 -1
  27. package/build/client/_app/immutable/chunks/COggdvXA.js +1 -0
  28. package/build/client/_app/immutable/chunks/{C47KpwkC.js → CYQe9sJG.js} +1 -1
  29. package/build/client/_app/immutable/chunks/{BrX0OiHa.js → CYxrEvMN.js} +1 -1
  30. package/build/client/_app/immutable/chunks/{CUqNPCjK.js → CaLUaLKT.js} +1 -1
  31. package/build/client/_app/immutable/chunks/{Cwd5DdSa.js → CdHvJ4_w.js} +1 -1
  32. package/build/client/_app/immutable/chunks/{CJ-lpX9h.js → Ckyou5Od.js} +1 -1
  33. package/build/client/_app/immutable/chunks/{C1YAjCKh.js → CmrXQ7MQ.js} +1 -1
  34. package/build/client/_app/immutable/chunks/{BWYga5zO.js → Cn53TYFN.js} +1 -1
  35. package/build/client/_app/immutable/chunks/{CD_kQCcy.js → CobJHAAW.js} +1 -1
  36. package/build/client/_app/immutable/chunks/{B51GwAfL.js → CpHaxpYy.js} +1 -1
  37. package/build/client/_app/immutable/chunks/{BdoKnygS.js → CuD0M7ml.js} +2 -2
  38. package/build/client/_app/immutable/chunks/{BfABZbDO.js → DGn8gxMH.js} +1 -1
  39. package/build/client/_app/immutable/chunks/{CbTVVa30.js → DJ4TnckQ.js} +1 -1
  40. package/build/client/_app/immutable/chunks/{C_qF9Ll1.js → DL-S4jBj.js} +1 -1
  41. package/build/client/_app/immutable/chunks/{ioQlYLW1.js → DLTGIy2S.js} +1 -1
  42. package/build/client/_app/immutable/chunks/{EodvFm9d.js → DcaEnsuI.js} +1 -1
  43. package/build/client/_app/immutable/chunks/{CH1RPLU9.js → DhPQR3Px.js} +1 -1
  44. package/build/client/_app/immutable/chunks/{gzN3DgKu.js → Dik5m9U4.js} +1 -1
  45. package/build/client/_app/immutable/chunks/{DSQnKfn-.js → Dj-iuGW3.js} +1 -1
  46. package/build/client/_app/immutable/chunks/{DePvhy8M.js → MQLxN4-w.js} +1 -1
  47. package/build/client/_app/immutable/chunks/{SbhBQTvy.js → N5edR_wk.js} +1 -1
  48. package/build/client/_app/immutable/chunks/{k7j8NQjk.js → NMQ8yb5B.js} +1 -1
  49. package/build/client/_app/immutable/chunks/{DJe5QTzh.js → S5LArjpJ.js} +1 -1
  50. package/build/client/_app/immutable/chunks/{CgJVu5ra.js → SsCjYNSL.js} +1 -1
  51. package/build/client/_app/immutable/chunks/UguYSyR_.js +1 -0
  52. package/build/client/_app/immutable/chunks/{CkIr3n4I.js → aOKoOpNt.js} +1 -1
  53. package/build/client/_app/immutable/chunks/{wOfVBGZS.js → dRJp6O4P.js} +1 -1
  54. package/build/client/_app/immutable/chunks/{CJ4vuw4Q.js → nlEqX7_u.js} +1 -1
  55. package/build/client/_app/immutable/chunks/{lFo8pWTB.js → q-tJjDlp.js} +1 -1
  56. package/build/client/_app/immutable/entry/{app.CSk6y__j.js → app.BR7HPYnZ.js} +2 -2
  57. package/build/client/_app/immutable/entry/start.DbhlkFfd.js +1 -0
  58. package/build/client/_app/immutable/nodes/0.BDKx-zUI.js +1 -0
  59. package/build/client/_app/immutable/nodes/{1.Ckq5CDEF.js → 1.B_9JaBUL.js} +1 -1
  60. package/build/client/_app/immutable/nodes/{2.ZFWOqsMm.js → 2.D_8Y7w6T.js} +1 -1
  61. package/build/client/_app/immutable/nodes/3.sgWOIIcg.js +1 -0
  62. package/build/client/_app/version.json +1 -1
  63. package/build/server/chunks/{0-F8UDIQlw.js → 0-C94QRPbG.js} +2 -2
  64. package/build/server/chunks/{0-F8UDIQlw.js.map → 0-C94QRPbG.js.map} +1 -1
  65. package/build/server/chunks/1-G6vwI4Kc.js +9 -0
  66. package/build/server/chunks/{1-C7yZ906n.js.map → 1-G6vwI4Kc.js.map} +1 -1
  67. package/build/server/chunks/{2-tND4IT0j.js → 2-Cy9PX2zK.js} +2 -2
  68. package/build/server/chunks/{2-tND4IT0j.js.map → 2-Cy9PX2zK.js.map} +1 -1
  69. package/build/server/chunks/{3-DzwYMPfw.js → 3-CxxgkGJa.js} +3 -3
  70. package/build/server/chunks/{3-DzwYMPfw.js.map → 3-CxxgkGJa.js.map} +1 -1
  71. package/build/server/chunks/{_page.svelte-BXgDoamA.js → _page.svelte-DdQY1QqH.js} +62 -3
  72. package/build/server/chunks/_page.svelte-DdQY1QqH.js.map +1 -0
  73. package/build/server/chunks/_server.ts-CEtvrNT1.js +13 -0
  74. package/build/server/chunks/_server.ts-CEtvrNT1.js.map +1 -0
  75. package/build/server/chunks/{_server.ts-p_sHg72N.js → _server.ts-sRxHDQa9.js} +2 -2
  76. package/build/server/chunks/{_server.ts-p_sHg72N.js.map → _server.ts-sRxHDQa9.js.map} +1 -1
  77. package/build/server/chunks/{hooks.server-CeNxBnIX.js → hooks.server-sBuk2932.js} +12 -2
  78. package/build/server/chunks/hooks.server-sBuk2932.js.map +1 -0
  79. package/build/server/chunks/idle-timer-CouFy_WF.js +49 -0
  80. package/build/server/chunks/idle-timer-CouFy_WF.js.map +1 -0
  81. package/build/server/chunks/{sse-manager-DpUiK2jt.js → sse-manager-C9ZLI_Nx.js} +13 -2
  82. package/build/server/chunks/sse-manager-C9ZLI_Nx.js.map +1 -0
  83. package/build/server/index.js +22 -3
  84. package/build/server/index.js.map +1 -1
  85. package/build/server/manifest.js +13 -6
  86. package/build/server/manifest.js.map +1 -1
  87. package/dist/cli/commands/review.js +36 -233
  88. package/dist/cli/commands/status.js +12 -4
  89. package/dist/cli/commands/stop.js +64 -0
  90. package/dist/cli/index.js +7 -0
  91. package/dist/cli/server-client.js +209 -0
  92. package/dist/cli/session-reader.js +70 -1
  93. package/package.json +1 -1
  94. package/build/client/_app/immutable/chunks/BPkIOP5x.js +0 -1
  95. package/build/client/_app/immutable/chunks/D8WDJIkf.js +0 -3
  96. package/build/client/_app/immutable/chunks/QMxLvN9k.js +0 -1
  97. package/build/client/_app/immutable/entry/start.BnxQc9Fl.js +0 -1
  98. package/build/client/_app/immutable/nodes/0.BZ6p9IRV.js +0 -1
  99. package/build/client/_app/immutable/nodes/3.CfL49yTp.js +0 -1
  100. package/build/server/chunks/1-C7yZ906n.js +0 -9
  101. package/build/server/chunks/_page.svelte-BXgDoamA.js.map +0 -1
  102. package/build/server/chunks/hooks.server-CeNxBnIX.js.map +0 -1
  103. package/build/server/chunks/sse-manager-DpUiK2jt.js.map +0 -1
@@ -10,12 +10,12 @@ return {
10
10
  assets: new Set(["favicon.png"]),
11
11
  mimeTypes: {".png":"image/png"},
12
12
  _: {
13
- client: {start:"_app/immutable/entry/start.BnxQc9Fl.js",app:"_app/immutable/entry/app.CSk6y__j.js",imports:["_app/immutable/entry/start.BnxQc9Fl.js","_app/immutable/chunks/D8WDJIkf.js","_app/immutable/chunks/CD_kQCcy.js","_app/immutable/chunks/BfABZbDO.js","_app/immutable/entry/app.CSk6y__j.js","_app/immutable/chunks/DSQnKfn-.js","_app/immutable/chunks/CD_kQCcy.js","_app/immutable/chunks/wOfVBGZS.js","_app/immutable/chunks/Dl-inTne.js","_app/immutable/chunks/BfABZbDO.js","_app/immutable/chunks/DteI5BLO.js","_app/immutable/chunks/2wZlHG5k.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},
13
+ client: {start:"_app/immutable/entry/start.DbhlkFfd.js",app:"_app/immutable/entry/app.BR7HPYnZ.js",imports:["_app/immutable/entry/start.DbhlkFfd.js","_app/immutable/chunks/74GYr5Jz.js","_app/immutable/chunks/CobJHAAW.js","_app/immutable/chunks/DGn8gxMH.js","_app/immutable/entry/app.BR7HPYnZ.js","_app/immutable/chunks/Dj-iuGW3.js","_app/immutable/chunks/CobJHAAW.js","_app/immutable/chunks/dRJp6O4P.js","_app/immutable/chunks/BrjAEg64.js","_app/immutable/chunks/DGn8gxMH.js","_app/immutable/chunks/BZQqs639.js","_app/immutable/chunks/C5wtj4WQ.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},
14
14
  nodes: [
15
- __memo(() => import('./chunks/0-F8UDIQlw.js')),
16
- __memo(() => import('./chunks/1-C7yZ906n.js')),
17
- __memo(() => import('./chunks/2-tND4IT0j.js')),
18
- __memo(() => import('./chunks/3-DzwYMPfw.js'))
15
+ __memo(() => import('./chunks/0-C94QRPbG.js')),
16
+ __memo(() => import('./chunks/1-G6vwI4Kc.js')),
17
+ __memo(() => import('./chunks/2-Cy9PX2zK.js')),
18
+ __memo(() => import('./chunks/3-CxxgkGJa.js'))
19
19
  ],
20
20
  remotes: {
21
21
 
@@ -77,12 +77,19 @@ return {
77
77
  page: null,
78
78
  endpoint: __memo(() => import('./chunks/_server.ts-b4ynvdd4.js'))
79
79
  },
80
+ {
81
+ id: "/api/shutdown",
82
+ pattern: /^\/api\/shutdown\/?$/,
83
+ params: [],
84
+ page: null,
85
+ endpoint: __memo(() => import('./chunks/_server.ts-CEtvrNT1.js'))
86
+ },
80
87
  {
81
88
  id: "/api/sse/[sessionId]",
82
89
  pattern: /^\/api\/sse\/([^/]+?)\/?$/,
83
90
  params: [{"name":"sessionId","optional":false,"rest":false,"chained":false}],
84
91
  page: null,
85
- endpoint: __memo(() => import('./chunks/_server.ts-p_sHg72N.js'))
92
+ endpoint: __memo(() => import('./chunks/_server.ts-sRxHDQa9.js'))
86
93
  },
87
94
  {
88
95
  id: "/plan/[sessionId]",
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sources":["../../.svelte-kit/adapter-node/manifest.js"],"sourcesContent":["export const manifest = (() => {\nfunction __memo(fn) {\n\tlet value;\n\treturn () => value ??= (value = fn());\n}\n\nreturn {\n\tappDir: \"_app\",\n\tappPath: \"_app\",\n\tassets: new Set([\"favicon.png\"]),\n\tmimeTypes: {\".png\":\"image/png\"},\n\t_: {\n\t\tclient: {start:\"_app/immutable/entry/start.BnxQc9Fl.js\",app:\"_app/immutable/entry/app.CSk6y__j.js\",imports:[\"_app/immutable/entry/start.BnxQc9Fl.js\",\"_app/immutable/chunks/D8WDJIkf.js\",\"_app/immutable/chunks/CD_kQCcy.js\",\"_app/immutable/chunks/BfABZbDO.js\",\"_app/immutable/entry/app.CSk6y__j.js\",\"_app/immutable/chunks/DSQnKfn-.js\",\"_app/immutable/chunks/CD_kQCcy.js\",\"_app/immutable/chunks/wOfVBGZS.js\",\"_app/immutable/chunks/Dl-inTne.js\",\"_app/immutable/chunks/BfABZbDO.js\",\"_app/immutable/chunks/DteI5BLO.js\",\"_app/immutable/chunks/2wZlHG5k.js\"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},\n\t\tnodes: [\n\t\t\t__memo(() => import('./nodes/0.js')),\n\t\t\t__memo(() => import('./nodes/1.js')),\n\t\t\t__memo(() => import('./nodes/2.js')),\n\t\t\t__memo(() => import('./nodes/3.js'))\n\t\t],\n\t\tremotes: {\n\t\t\t\n\t\t},\n\t\troutes: [\n\t\t\t{\n\t\t\t\tid: \"/\",\n\t\t\t\tpattern: /^\\/$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 2 },\n\t\t\t\tendpoint: null\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/health\",\n\t\t\t\tpattern: /^\\/api\\/health\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/health/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[sessionId]\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_sessionId_/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[sessionId]/approve\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/approve\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_sessionId_/approve/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[sessionId]/feedback\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/feedback\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_sessionId_/feedback/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[sessionId]/versions\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/versions\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_sessionId_/versions/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[sessionId]/versions/[version]\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/versions\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false},{\"name\":\"version\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_sessionId_/versions/_version_/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sse/[sessionId]\",\n\t\t\t\tpattern: /^\\/api\\/sse\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sse/_sessionId_/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/plan/[sessionId]\",\n\t\t\t\tpattern: /^\\/plan\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 3 },\n\t\t\t\tendpoint: null\n\t\t\t}\n\t\t],\n\t\tprerendered_routes: new Set([]),\n\t\tmatchers: async () => {\n\t\t\t\n\t\t\treturn { };\n\t\t},\n\t\tserver_assets: {}\n\t}\n}\n})();\n\nexport const prerendered = new Set([]);\n\nexport const base = \"\";"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manifest.js","sources":["../../.svelte-kit/adapter-node/manifest.js"],"sourcesContent":["export const manifest = (() => {\nfunction __memo(fn) {\n\tlet value;\n\treturn () => value ??= (value = fn());\n}\n\nreturn {\n\tappDir: \"_app\",\n\tappPath: \"_app\",\n\tassets: new Set([\"favicon.png\"]),\n\tmimeTypes: {\".png\":\"image/png\"},\n\t_: {\n\t\tclient: {start:\"_app/immutable/entry/start.DbhlkFfd.js\",app:\"_app/immutable/entry/app.BR7HPYnZ.js\",imports:[\"_app/immutable/entry/start.DbhlkFfd.js\",\"_app/immutable/chunks/74GYr5Jz.js\",\"_app/immutable/chunks/CobJHAAW.js\",\"_app/immutable/chunks/DGn8gxMH.js\",\"_app/immutable/entry/app.BR7HPYnZ.js\",\"_app/immutable/chunks/Dj-iuGW3.js\",\"_app/immutable/chunks/CobJHAAW.js\",\"_app/immutable/chunks/dRJp6O4P.js\",\"_app/immutable/chunks/BrjAEg64.js\",\"_app/immutable/chunks/DGn8gxMH.js\",\"_app/immutable/chunks/BZQqs639.js\",\"_app/immutable/chunks/C5wtj4WQ.js\"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},\n\t\tnodes: [\n\t\t\t__memo(() => import('./nodes/0.js')),\n\t\t\t__memo(() => import('./nodes/1.js')),\n\t\t\t__memo(() => import('./nodes/2.js')),\n\t\t\t__memo(() => import('./nodes/3.js'))\n\t\t],\n\t\tremotes: {\n\t\t\t\n\t\t},\n\t\troutes: [\n\t\t\t{\n\t\t\t\tid: \"/\",\n\t\t\t\tpattern: /^\\/$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 2 },\n\t\t\t\tendpoint: null\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/health\",\n\t\t\t\tpattern: /^\\/api\\/health\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/health/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[sessionId]\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_sessionId_/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[sessionId]/approve\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/approve\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_sessionId_/approve/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[sessionId]/feedback\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/feedback\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_sessionId_/feedback/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[sessionId]/versions\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/versions\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_sessionId_/versions/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[sessionId]/versions/[version]\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/versions\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false},{\"name\":\"version\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_sessionId_/versions/_version_/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/shutdown\",\n\t\t\t\tpattern: /^\\/api\\/shutdown\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/shutdown/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sse/[sessionId]\",\n\t\t\t\tpattern: /^\\/api\\/sse\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sse/_sessionId_/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/plan/[sessionId]\",\n\t\t\t\tpattern: /^\\/plan\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 3 },\n\t\t\t\tendpoint: null\n\t\t\t}\n\t\t],\n\t\tprerendered_routes: new Set([]),\n\t\tmatchers: async () => {\n\t\t\t\n\t\t\treturn { };\n\t\t},\n\t\tserver_assets: {}\n\t}\n}\n})();\n\nexport const prerendered = new Set([]);\n\nexport const base = \"\";"],"names":[],"mappings":"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"}
@@ -1,179 +1,10 @@
1
- import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync } from "node:fs";
1
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync, } from "node:fs";
2
2
  import { resolve, dirname, join } from "node:path";
3
- import { fileURLToPath } from "node:url";
4
- import { spawn, execSync } from "node:child_process";
5
- import { createServer } from "node:net";
6
3
  import { watch } from "chokidar";
7
4
  import { parseMarkdownToPlan, sessionIdFromPath } from "../markdown-to-plan.js";
8
5
  import { outputJson } from "../output.js";
9
- const EXIT_APPROVED = 0;
10
- const EXIT_NEEDS_WORK = 3;
11
- const DEFAULT_BASE_PORT = 5181;
12
- const MAX_PORT = 5199;
13
- function getPackageDir() {
14
- const thisFile = fileURLToPath(import.meta.url);
15
- // dist/cli/commands/review.js -> package root
16
- return resolve(dirname(thisFile), "../../..");
17
- }
18
- async function checkHealth(port) {
19
- try {
20
- const controller = new AbortController();
21
- const timeout = setTimeout(() => controller.abort(), 500);
22
- const res = await fetch(`http://localhost:${port}/api/health`, {
23
- signal: controller.signal,
24
- });
25
- clearTimeout(timeout);
26
- if (!res.ok)
27
- return null;
28
- return (await res.json());
29
- }
30
- catch {
31
- return null;
32
- }
33
- }
34
- function lockFilePath(sessionDir) {
35
- return join(sessionDir, ".server-lock.json");
36
- }
37
- function readLock(sessionDir) {
38
- const lockPath = lockFilePath(sessionDir);
39
- if (!existsSync(lockPath))
40
- return null;
41
- try {
42
- return JSON.parse(readFileSync(lockPath, "utf-8"));
43
- }
44
- catch {
45
- return null;
46
- }
47
- }
48
- function writeLock(sessionDir, port, pid) {
49
- mkdirSync(sessionDir, { recursive: true });
50
- writeFileSync(lockFilePath(sessionDir), JSON.stringify({ port, pid }));
51
- }
52
- function clearLock(sessionDir) {
53
- try {
54
- unlinkSync(lockFilePath(sessionDir));
55
- }
56
- catch {
57
- // ignore
58
- }
59
- }
60
- function isPidAlive(pid) {
61
- try {
62
- process.kill(pid, 0);
63
- return true;
64
- }
65
- catch {
66
- return false;
67
- }
68
- }
69
- async function findExistingServer(sessionDir, basePort) {
70
- // Check lock file first (fast path, avoids port scan race)
71
- const lock = readLock(sessionDir);
72
- if (lock) {
73
- if (isPidAlive(lock.pid)) {
74
- const health = await checkHealth(lock.port);
75
- if (health && health.sessionDir === sessionDir) {
76
- return lock.port;
77
- }
78
- }
79
- // Stale lock — remove it
80
- clearLock(sessionDir);
81
- }
82
- // Fallback: scan ports (handles lock-less legacy servers)
83
- for (let port = basePort; port <= MAX_PORT; port++) {
84
- const health = await checkHealth(port);
85
- if (health && health.sessionDir === sessionDir) {
86
- return port;
87
- }
88
- }
89
- return null;
90
- }
91
- function isPortFree(port) {
92
- return new Promise((resolve) => {
93
- const server = createServer();
94
- server.once("error", () => resolve(false));
95
- server.once("listening", () => {
96
- server.close(() => resolve(true));
97
- });
98
- server.listen(port, "127.0.0.1");
99
- });
100
- }
101
- async function findFreePort(basePort) {
102
- for (let port = basePort; port <= MAX_PORT; port++) {
103
- if (await isPortFree(port))
104
- return port;
105
- }
106
- throw new Error(`No free port found in range ${basePort}-${MAX_PORT}`);
107
- }
108
- function startServer(sessionDir, port) {
109
- const packageDir = getPackageDir();
110
- const buildEntry = join(packageDir, "build", "index.js");
111
- if (!existsSync(buildEntry)) {
112
- console.error(`Error: Server build not found at ${buildEntry}\nRun 'npm run build:server' in the plan-assistant package first.`);
113
- process.exit(1);
114
- }
115
- return new Promise((resolvePromise, reject) => {
116
- const child = spawn("node", [buildEntry], {
117
- env: {
118
- ...process.env,
119
- SESSION_DIR: sessionDir,
120
- PORT: String(port),
121
- },
122
- stdio: "ignore",
123
- detached: true,
124
- });
125
- child.unref();
126
- const pid = child.pid;
127
- let attempts = 0;
128
- const maxAttempts = 30;
129
- const interval = setInterval(async () => {
130
- attempts++;
131
- try {
132
- const controller = new AbortController();
133
- const timeout = setTimeout(() => controller.abort(), 1000);
134
- const res = await fetch(`http://localhost:${port}/api/health`, {
135
- signal: controller.signal,
136
- });
137
- clearTimeout(timeout);
138
- if (res.ok) {
139
- clearInterval(interval);
140
- resolvePromise(pid);
141
- }
142
- }
143
- catch {
144
- if (attempts >= maxAttempts) {
145
- clearInterval(interval);
146
- reject(new Error("Server failed to start within 15 seconds"));
147
- }
148
- }
149
- }, 500);
150
- });
151
- }
152
- async function launchServer(sessionDir, port) {
153
- process.stdout.write(`Starting Plan Assistant server on port ${port}...`);
154
- try {
155
- const pid = await startServer(sessionDir, port);
156
- writeLock(sessionDir, port, pid);
157
- console.log(" ready.");
158
- }
159
- catch (err) {
160
- console.error(` failed: ${err}`);
161
- process.exit(1);
162
- }
163
- }
164
- function openBrowser(url) {
165
- try {
166
- const cmd = process.platform === "darwin"
167
- ? "open"
168
- : process.platform === "win32"
169
- ? "start"
170
- : "xdg-open";
171
- execSync(`${cmd} "${url}"`, { stdio: "ignore" });
172
- }
173
- catch {
174
- console.log(`Open in browser: ${url}`);
175
- }
176
- }
6
+ import { waitForFeedback } from "../session-reader.js";
7
+ import { DEFAULT_BASE_PORT, MAX_PORT, findExistingServer, checkHealth, isPortFree, findFreePort, launchServer, openBrowser, } from "../server-client.js";
177
8
  export async function review(args) {
178
9
  const markdownFile = args.positional[0];
179
10
  if (!markdownFile) {
@@ -181,6 +12,11 @@ export async function review(args) {
181
12
  console.error("Usage: plan-assistant review <markdown-file>");
182
13
  process.exit(1);
183
14
  }
15
+ // Parse host configuration (for Docker/remote sandbox environments)
16
+ const hostFlag = args.flags.host;
17
+ const displayHost = (typeof hostFlag === "string" ? hostFlag : null) ??
18
+ process.env.PLAN_ASSISTANT_HOST ??
19
+ "localhost";
184
20
  // Parse port configuration
185
21
  const portFlag = args.flags.port;
186
22
  const envPort = process.env.PLAN_ASSISTANT_PORT;
@@ -274,12 +110,32 @@ Run \`npx plan-assistant init --output <file>\` to generate a correctly-formatte
274
110
  writeFileSync(join(sessionPath, "plan.json"), JSON.stringify(plan, null, 2));
275
111
  writeFileSync(join(sessionPath, "versions", `v${version}.json`), JSON.stringify(plan, null, 2));
276
112
  // Find existing server for this session dir or start a new one
113
+ const reuse = args.flags.reuse === true;
277
114
  const basePort = requestedPort ?? DEFAULT_BASE_PORT;
278
115
  let port = await findExistingServer(sessionDir, basePort);
116
+ if (!port && reuse) {
117
+ // --reuse: find any running plan-assistant server and reuse it
118
+ for (let p = basePort; p <= MAX_PORT; p++) {
119
+ const health = await checkHealth(p);
120
+ if (health) {
121
+ port = p;
122
+ console.error(`Reusing existing server on port ${p}.`);
123
+ break;
124
+ }
125
+ }
126
+ }
279
127
  if (!port) {
280
128
  if (requestedPort) {
281
129
  if (!(await isPortFree(requestedPort))) {
282
- console.error(`Error: Port ${requestedPort} is already in use`);
130
+ // Check if it's a plan-assistant server for a better error message
131
+ const health = await checkHealth(requestedPort);
132
+ if (health) {
133
+ console.error(`Error: Port ${requestedPort} is already used by Plan Assistant (session dir: ${health.sessionDir}).` +
134
+ `\nUse \`plan-assistant stop\` to stop it, or add --reuse to share the server.`);
135
+ }
136
+ else {
137
+ console.error(`Error: Port ${requestedPort} is already in use by another process.`);
138
+ }
283
139
  process.exit(1);
284
140
  }
285
141
  port = requestedPort;
@@ -289,16 +145,20 @@ Run \`npx plan-assistant init --output <file>\` to generate a correctly-formatte
289
145
  }
290
146
  await launchServer(sessionDir, port);
291
147
  }
292
- const url = `http://localhost:${port}/plan/${sessionId}`;
148
+ const url = `http://${displayHost}:${port}/plan/${sessionId}`;
293
149
  const feedbackPath = join(sessionPath, "feedback.json");
294
150
  // Machine-readable ready event on first line
295
151
  outputJson({
296
152
  event: "ready",
297
153
  sessionId,
154
+ planVersion: version,
155
+ freshCycle: true,
298
156
  url,
299
157
  feedbackPath,
300
158
  });
301
- openBrowser(url);
159
+ if (displayHost === "localhost") {
160
+ openBrowser(url);
161
+ }
302
162
  const noWait = args.flags["no-wait"] === true;
303
163
  console.error(`\nPlan Assistant`);
304
164
  console.error(` Review: ${url}`);
@@ -338,7 +198,7 @@ Run \`npx plan-assistant init --output <file>\` to generate a correctly-formatte
338
198
  });
339
199
  // Wait for feedback unless --no-wait
340
200
  if (!noWait) {
341
- await waitForFeedback(feedbackPath, sessionId, plan.meta.title, mdWatcher);
201
+ await waitForFeedback(feedbackPath, sessionId, plan.meta.title, mdWatcher, sessionPath);
342
202
  return;
343
203
  }
344
204
  // Keep process alive (--no-wait mode)
@@ -348,60 +208,3 @@ Run \`npx plan-assistant init --output <file>\` to generate a correctly-formatte
348
208
  process.exit(0);
349
209
  });
350
210
  }
351
- async function waitForFeedback(feedbackPath, sessionId, planTitle, mdWatcher) {
352
- // Check if feedback already submitted
353
- if (existsSync(feedbackPath)) {
354
- try {
355
- const existing = JSON.parse(readFileSync(feedbackPath, "utf-8"));
356
- if (existing.status === "approved" || existing.status === "needs-work") {
357
- mdWatcher.close();
358
- outputFeedbackResult(existing, sessionId, planTitle);
359
- return;
360
- }
361
- }
362
- catch {
363
- /* ignore */
364
- }
365
- }
366
- return new Promise((resolve) => {
367
- const fbWatcher = watch(feedbackPath, {
368
- awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 100 },
369
- });
370
- const check = () => {
371
- try {
372
- if (!existsSync(feedbackPath))
373
- return;
374
- const data = JSON.parse(readFileSync(feedbackPath, "utf-8"));
375
- if (data.status === "approved" || data.status === "needs-work") {
376
- fbWatcher.close();
377
- mdWatcher.close();
378
- outputFeedbackResult(data, sessionId, planTitle);
379
- resolve();
380
- }
381
- }
382
- catch {
383
- /* ignore parse errors during writes */
384
- }
385
- };
386
- fbWatcher.on("change", check);
387
- fbWatcher.on("add", check);
388
- process.on("SIGINT", () => {
389
- fbWatcher.close();
390
- mdWatcher.close();
391
- console.error("\nStopped watching.");
392
- process.exit(0);
393
- });
394
- });
395
- }
396
- function outputFeedbackResult(feedback, sessionId, planTitle) {
397
- const unresolvedComments = feedback.comments.filter((c) => !c.resolved);
398
- outputJson({
399
- event: "feedback",
400
- sessionId,
401
- planTitle,
402
- status: feedback.status,
403
- comments: unresolvedComments,
404
- commentCount: unresolvedComments.length,
405
- });
406
- process.exit(feedback.status === "approved" ? EXIT_APPROVED : EXIT_NEEDS_WORK);
407
- }
@@ -67,12 +67,17 @@ export async function status(args) {
67
67
  await waitForFeedback(resolved.sessionDir, resolved.sessionId, meta, timeoutMs);
68
68
  return;
69
69
  }
70
- const feedback = readFeedback(resolved.sessionDir);
70
+ const rawFeedback = readFeedback(resolved.sessionDir);
71
+ // Discard feedback from a previous plan version (stale cycle)
72
+ const feedback = rawFeedback && meta.planVersion && rawFeedback.planVersion < meta.planVersion
73
+ ? null
74
+ : rawFeedback;
71
75
  const { feedbackStatus, exitCode } = computeStatus(feedback);
72
76
  const { phaseSummary, commentSummary } = computeSummary(feedback);
73
77
  outputJson({
74
78
  sessionId: resolved.sessionId,
75
79
  planTitle: meta.planTitle,
80
+ planVersion: meta.planVersion,
76
81
  status: meta.status,
77
82
  feedbackStatus,
78
83
  phaseSummary,
@@ -81,9 +86,11 @@ export async function status(args) {
81
86
  process.exit(exitCode);
82
87
  }
83
88
  async function waitForFeedback(sessionDir, sessionId, meta, timeoutMs) {
84
- // Check current state first
89
+ // Check current state first (ignore stale feedback from older plan versions)
85
90
  const current = readFeedback(sessionDir);
86
- if (current && current.status !== "reviewing") {
91
+ if (current &&
92
+ current.status !== "reviewing" &&
93
+ !(meta.planVersion && current.planVersion < meta.planVersion)) {
87
94
  const { feedbackStatus, exitCode } = computeStatus(current);
88
95
  const { phaseSummary, commentSummary } = computeSummary(current);
89
96
  outputJson({
@@ -109,7 +116,8 @@ async function waitForFeedback(sessionDir, sessionId, meta, timeoutMs) {
109
116
  if (!existsSync(feedbackPath))
110
117
  return;
111
118
  const data = JSON.parse(readFileSync(feedbackPath, "utf-8"));
112
- if (data.status !== "reviewing") {
119
+ if (data.status !== "reviewing" &&
120
+ !(meta.planVersion && data.planVersion < meta.planVersion)) {
113
121
  clearTimeout(timer);
114
122
  watcher.close();
115
123
  const { feedbackStatus, exitCode } = computeStatus(data);
@@ -0,0 +1,64 @@
1
+ import { dirname } from "node:path";
2
+ import { resolveSession } from "../session-resolver.js";
3
+ import { stopServer, checkHealth, DEFAULT_BASE_PORT, MAX_PORT, } from "../server-client.js";
4
+ import { outputJson, outputError } from "../output.js";
5
+ export async function stop(args) {
6
+ const target = args.positional[0];
7
+ if (target) {
8
+ // Stop server for a specific session
9
+ const session = resolveSession(target);
10
+ if (!session) {
11
+ outputError(`Session not found: ${target}`, "NOT_FOUND");
12
+ process.exit(1);
13
+ }
14
+ const parentDir = dirname(session.sessionDir);
15
+ const stopped = await stopServer(parentDir);
16
+ if (stopped) {
17
+ outputJson({ event: "server-stopped", sessionDir: parentDir });
18
+ console.error(`Server stopped for session ${session.sessionId}.`);
19
+ }
20
+ else {
21
+ outputJson({ event: "no-server", sessionDir: parentDir });
22
+ console.error(`No running server found for session ${session.sessionId}.`);
23
+ }
24
+ return;
25
+ }
26
+ // No argument: find and stop all plan-assistant servers in port range
27
+ let stopped = 0;
28
+ const results = [];
29
+ for (let port = DEFAULT_BASE_PORT; port <= MAX_PORT; port++) {
30
+ const health = await checkHealth(port);
31
+ if (health) {
32
+ try {
33
+ const controller = new AbortController();
34
+ const timeout = setTimeout(() => controller.abort(), 2000);
35
+ await fetch(`http://localhost:${port}/api/shutdown`, {
36
+ method: "POST",
37
+ signal: controller.signal,
38
+ });
39
+ clearTimeout(timeout);
40
+ results.push({ port, sessionDir: health.sessionDir });
41
+ stopped++;
42
+ }
43
+ catch {
44
+ // Try SIGTERM
45
+ try {
46
+ process.kill(health.pid, "SIGTERM");
47
+ results.push({ port, sessionDir: health.sessionDir });
48
+ stopped++;
49
+ }
50
+ catch {
51
+ // ignore
52
+ }
53
+ }
54
+ }
55
+ }
56
+ if (stopped === 0) {
57
+ outputJson({ event: "no-servers", stopped: 0 });
58
+ console.error("No running Plan Assistant servers found.");
59
+ }
60
+ else {
61
+ outputJson({ event: "servers-stopped", stopped, servers: results });
62
+ console.error(`Stopped ${stopped} server(s).`);
63
+ }
64
+ }
package/dist/cli/index.js CHANGED
@@ -54,6 +54,7 @@ Commands:
54
54
  plan-assistant status <session-id-or-file> Check review status
55
55
  plan-assistant feedback <session-id-or-file> Read feedback JSON
56
56
  plan-assistant list [--dir <path>] List all sessions
57
+ plan-assistant stop [<session-id-or-file>] Stop running server(s)
57
58
  plan-assistant clean [--all] [--older-than <dur>] Remove old sessions
58
59
  plan-assistant export <session-id-or-file> Export as HTML
59
60
  plan-assistant help format Show the required plan format
@@ -62,7 +63,9 @@ Commands:
62
63
  Flags:
63
64
  --pretty Human-readable output (default: JSON)
64
65
  --port <N> Port for review server (review command)
66
+ --host <H> Hostname for browser URL, e.g. host IP when running in Docker (review command)
65
67
  --no-wait Don't wait for feedback, just start server (review command)
68
+ --reuse Reuse an already-running server on another session (review command)
66
69
  --wait Block until feedback is submitted (status command)
67
70
 
68
71
  TIP: Always start with \`plan-assistant init\` to get a correctly-formatted template.
@@ -150,6 +153,10 @@ export async function main(args) {
150
153
  const { init } = await import("./commands/init.js");
151
154
  return init(parsed);
152
155
  }
156
+ case "stop": {
157
+ const { stop } = await import("./commands/stop.js");
158
+ return stop(parsed);
159
+ }
153
160
  case "clean": {
154
161
  const { clean } = await import("./commands/clean.js");
155
162
  return clean(parsed);