@diffohq/diffo 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +117 -20
- package/dist/client/assets/{abnfDiagram-O67JEVCF-Eku-JiMb.js → abnfDiagram-O67JEVCF-vILxBZcB.js} +1 -1
- package/dist/client/assets/{arc-lV5GSLJD.js → arc-KM37zfEu.js} +1 -1
- package/dist/client/assets/architecture-7GRP2DOG-DzlmD0Wj.js +1 -0
- package/dist/client/assets/{architectureDiagram-NJMV4G6O-DIH1VGVe.js → architectureDiagram-NJMV4G6O-CCe24XcA.js} +1 -1
- package/dist/client/assets/{blockDiagram-BEXU5L5S-CaCCdXJr.js → blockDiagram-BEXU5L5S-GL2esJ0w.js} +1 -1
- package/dist/client/assets/{c4Diagram-YGBWAQC7-DmnVa0_m.js → c4Diagram-YGBWAQC7-BcRujrvs.js} +1 -1
- package/dist/client/assets/channel-BffjfVqs.js +1 -0
- package/dist/client/assets/{chunk-3FUC2YCW-DDROCT3x.js → chunk-3FUC2YCW-Gj4X9KK9.js} +1 -1
- package/dist/client/assets/{chunk-5DYCD2WN-CL5xMelX.js → chunk-5DYCD2WN-DZs-erj_.js} +1 -1
- package/dist/client/assets/{chunk-742MDFTN-CTz8pFT1.js → chunk-742MDFTN-Db1JJZ9G.js} +1 -1
- package/dist/client/assets/{chunk-7INBJB4K-mTzp3uc7.js → chunk-7INBJB4K-B_wqJ7Xn.js} +1 -1
- package/dist/client/assets/{chunk-7M6MHVWA-AyZcKoA0.js → chunk-7M6MHVWA-DuALBizw.js} +1 -1
- package/dist/client/assets/{chunk-7PRAP22T-CEPNl3r7.js → chunk-7PRAP22T-D9QvZUm3.js} +1 -1
- package/dist/client/assets/{chunk-GTNCS2PH-DnfAIbaL.js → chunk-GTNCS2PH-JFHsSpPU.js} +1 -1
- package/dist/client/assets/{chunk-GWA4HPMP-DuzmSd5n.js → chunk-GWA4HPMP-CX_60U9Y.js} +1 -1
- package/dist/client/assets/{chunk-MBY4JIJT-BGNKEJZT.js → chunk-MBY4JIJT-BVqUStmy.js} +1 -1
- package/dist/client/assets/{chunk-NETBCI7D-CXPYvz5G.js → chunk-NETBCI7D-BoSm0O5f.js} +1 -1
- package/dist/client/assets/{chunk-O7XYJQB3-CYftULw7.js → chunk-O7XYJQB3-DG64mbS_.js} +1 -1
- package/dist/client/assets/{chunk-UA2S7LBM-DQbf9Dl1.js → chunk-UA2S7LBM-BL039fcM.js} +1 -1
- package/dist/client/assets/{chunk-WEXAMYUT-CcNQw347.js → chunk-WEXAMYUT-BPFyuzbi.js} +1 -1
- package/dist/client/assets/{chunk-XXDRQBXY-Bf1t_xv6.js → chunk-XXDRQBXY-BzCs4oPB.js} +1 -1
- package/dist/client/assets/{chunk-Z7XXMR3K-pRmpdAOe.js → chunk-Z7XXMR3K-D9UN9ldM.js} +1 -1
- package/dist/client/assets/{chunk-ZIGJFQKS-B5DDwrRj.js → chunk-ZIGJFQKS-D47UlTiy.js} +1 -1
- package/dist/client/assets/{classDiagram-v2-NBCMYWYE-DCpEkxmb.js → classDiagram-v2-NBCMYWYE-CXeBds6Z.js} +1 -1
- package/dist/client/assets/{core-Cl3AV7cB.js → core-De6Bel6T.js} +1 -1
- package/dist/client/assets/{cose-bilkent-JH36ORCC-DQEwYOPh.js → cose-bilkent-JH36ORCC-C5C9BMn5.js} +1 -1
- package/dist/client/assets/{cynefin-OW5HDTMX-B8MfDKLI.js → cynefin-OW5HDTMX-TQm3krMs.js} +1 -1
- package/dist/client/assets/{cynefinDiagram-VND7K2PF-B4WvhUhO.js → cynefinDiagram-VND7K2PF-D9L1g2S1.js} +1 -1
- package/dist/client/assets/{dagre-6A5THRUB-B9IMFM72.js → dagre-6A5THRUB-D9iVd0tg.js} +1 -1
- package/dist/client/assets/{diagram-22UHCM2B-DB0QnlzY.js → diagram-22UHCM2B-CD_1yZgj.js} +1 -1
- package/dist/client/assets/{diagram-3UASUU5V-DW2JbaXS.js → diagram-3UASUU5V-BLiXkub3.js} +1 -1
- package/dist/client/assets/{diagram-ATOU4E4O-kELWjFhd.js → diagram-ATOU4E4O-CnXY0tjf.js} +1 -1
- package/dist/client/assets/{diagram-CDSNMT55-DHJN8X6p.js → diagram-CDSNMT55-BBnDsrf_.js} +1 -1
- package/dist/client/assets/{diagram-MLGK6HIB-3hlAEcUl.js → diagram-MLGK6HIB-BUiu4OKD.js} +1 -1
- package/dist/client/assets/{diagram-MPIPVDR6-BmI2ylfG.js → diagram-MPIPVDR6-DiI9FWeO.js} +1 -1
- package/dist/client/assets/{dist-DOT26anA.js → dist-BWYGCgdo.js} +1 -1
- package/dist/client/assets/{dist-DNMzTuVG.js → dist-Co85aeoI.js} +1 -1
- package/dist/client/assets/{ebnfDiagram-ZINNZB2B-lJT30vWx.js → ebnfDiagram-ZINNZB2B-Bg_BLedv.js} +1 -1
- package/dist/client/assets/{elk-276RUBZZ-Y2ie1QZI.js → elk-276RUBZZ-BO7Zoa7U.js} +1 -1
- package/dist/client/assets/{engine-oniguruma-qcHcQ7gy.js → engine-oniguruma-DCFwTJLE.js} +1 -1
- package/dist/client/assets/{erDiagram-OPXOYQCR-BBPmg1YD.js → erDiagram-OPXOYQCR-DjBak3Ld.js} +1 -1
- package/dist/client/assets/eventmodeling-NTZA5JFV-BA4dpxhq.js +1 -0
- package/dist/client/assets/flowDiagram-KWPJA3E3-BXSGu0Q5.js +1 -0
- package/dist/client/assets/{ganttDiagram-FUAMR5RP-xPVj2AwG.js → ganttDiagram-FUAMR5RP-CEn0Np5L.js} +1 -1
- package/dist/client/assets/{gitGraph-4MIJSDKK-pvXQROBw.js → gitGraph-4MIJSDKK-DVMdaaG2.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-X574FWY7-pp7frUxm.js → gitGraphDiagram-X574FWY7-B6ZkiY7u.js} +1 -1
- package/dist/client/assets/index-6w3rS9cw.js +91 -0
- package/dist/client/assets/{index-BUmM006M.css → index-D934d4yh.css} +1 -1
- package/dist/client/assets/{info-A6RAGUB7-DLCTmODc.js → info-A6RAGUB7-Idt2RahI.js} +1 -1
- package/dist/client/assets/{infoDiagram-VRGFBTTK-BGnYOvv2.js → infoDiagram-VRGFBTTK-CA8T3csq.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-OU5B5YK6-DYbwoJB-.js → ishikawaDiagram-OU5B5YK6-DcgLwVJX.js} +1 -1
- package/dist/client/assets/{journeyDiagram-ZHPQQLJL-DHav_LIH.js → journeyDiagram-ZHPQQLJL-_AVEW5aE.js} +1 -1
- package/dist/client/assets/{kanban-definition-PNTS6WVX-Cj645S2T.js → kanban-definition-PNTS6WVX-CZ2gNo-B.js} +1 -1
- package/dist/client/assets/{line-Htxv9F4J.js → line-CHew3ngr.js} +1 -1
- package/dist/client/assets/{linear-e0hVUtYI.js → linear-Baz1Hb3u.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-DtRc-ypM.js → mermaid-parser.core-D2BrkwRE.js} +3 -3
- package/dist/client/assets/{mermaid.core-CyG7EFf-.js → mermaid.core-CCFlYVgY.js} +4 -4
- package/dist/client/assets/{mindmap-definition-NLK3R4M7-501wUG6-.js → mindmap-definition-NLK3R4M7-BXG9w5sC.js} +1 -1
- package/dist/client/assets/{packet-AYTQ26CC-CBEtSauH.js → packet-AYTQ26CC-BOvg32Rh.js} +1 -1
- package/dist/client/assets/{pegDiagram-GJSIUBJH-958m_CS_.js → pegDiagram-GJSIUBJH-COukdq7o.js} +1 -1
- package/dist/client/assets/{pie-WAS4IAKB-CtMX8NyM.js → pie-WAS4IAKB-ChHsdIQV.js} +1 -1
- package/dist/client/assets/{pieDiagram-5QR66LMP-Ch_R04up.js → pieDiagram-5QR66LMP-Deng5oun.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-O4NWA36T-WpRKg-an.js → quadrantDiagram-O4NWA36T-DmEJ83mR.js} +1 -1
- package/dist/client/assets/{radar-RG4KPBEZ-C6cMrg-A.js → radar-RG4KPBEZ-YxcXBiXc.js} +1 -1
- package/dist/client/assets/{railroad-74A4TZTK-D5TKF4bs.js → railroad-74A4TZTK-RkYX7A2D.js} +1 -1
- package/dist/client/assets/railroad-abnf-HS5TGJTU-CYF7Z2Wu.js +1 -0
- package/dist/client/assets/railroad-ebnf-LZEXJU2U-CqV11tet.js +1 -0
- package/dist/client/assets/railroad-peg-WCYAUIDC-CPusJj6I.js +1 -0
- package/dist/client/assets/{railroadDiagram-XR7U4H2S-CsGtkzal.js → railroadDiagram-XR7U4H2S-uj5HQbYy.js} +1 -1
- package/dist/client/assets/{requirementDiagram-PLB6GJNP-By5yShOx.js → requirementDiagram-PLB6GJNP-C_QtkIlI.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-IPEJSGJF-D0iqRNhC.js → sankeyDiagram-IPEJSGJF-BfxM5TKv.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-PO4LG4MO-BbN6AjiL.js → sequenceDiagram-PO4LG4MO-DXflg1u_.js} +1 -1
- package/dist/client/assets/{src-BPEEiDps.js → src-YTrwJCk8.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-GCMORJYK-69H8hCN6.js → stateDiagram-v2-GCMORJYK-BjDmED1Q.js} +1 -1
- package/dist/client/assets/{swimlanes-2SLR337P-VMJm_C1R.js → swimlanes-2SLR337P-BAvnQ6KT.js} +1 -1
- package/dist/client/assets/swimlanesDiagram-TC7HE7FX-CbFPwcec.js +8 -0
- package/dist/client/assets/{timeline-definition-EJHVYXUP-DWTI0Vqo.js → timeline-definition-EJHVYXUP-BYemcgr1.js} +1 -1
- package/dist/client/assets/{treeView-Q6P3EWNA-DoBvpaMV.js → treeView-Q6P3EWNA-CsuBtqLq.js} +1 -1
- package/dist/client/assets/{treemap-WGGIJYW6-B43_cUvq.js → treemap-WGGIJYW6-DUk1Z6g4.js} +1 -1
- package/dist/client/assets/{usecaseDiagram-POWQR4AR-C9eMeNe5.js → usecaseDiagram-POWQR4AR-j1nHXvyL.js} +1 -1
- package/dist/client/assets/{vennDiagram-UO4OBE2U-pUMZhTOS.js → vennDiagram-UO4OBE2U-B5eUL-dD.js} +1 -1
- package/dist/client/assets/{wardley-WFR3VGLG-CIzaJFvJ.js → wardley-WFR3VGLG-1YjpwPJM.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-VNRHLVJA-Cj_u7NlG.js → wardleyDiagram-VNRHLVJA-C7laBq5A.js} +1 -1
- package/dist/client/assets/{xychartDiagram-PMCCYNJV-mGddxyW6.js → xychartDiagram-PMCCYNJV-BkYPx-ts.js} +1 -1
- package/dist/client/index.html +2 -2
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/dist/client/assets/architecture-7GRP2DOG-Cjj-qeXa.js +0 -1
- package/dist/client/assets/channel-wy7dEM75.js +0 -1
- package/dist/client/assets/eventmodeling-NTZA5JFV-BDUZgpVa.js +0 -1
- package/dist/client/assets/flowDiagram-KWPJA3E3-B8jw0PgP.js +0 -1
- package/dist/client/assets/index-B10socvp.js +0 -91
- package/dist/client/assets/railroad-abnf-HS5TGJTU-DadVNrmb.js +0 -1
- package/dist/client/assets/railroad-ebnf-LZEXJU2U-Can6uT-b.js +0 -1
- package/dist/client/assets/railroad-peg-WCYAUIDC-BB7kTpaz.js +0 -1
- package/dist/client/assets/swimlanesDiagram-TC7HE7FX-C9C4mAsA.js +0 -8
package/dist/cli.mjs
CHANGED
|
@@ -83,6 +83,15 @@ function parseSuggestedReply(value) {
|
|
|
83
83
|
function startedByAgent(thread) {
|
|
84
84
|
return thread.messages[0]?.author === "agent";
|
|
85
85
|
}
|
|
86
|
+
/** The agent has this message: it replied after it, or a delivery carried it.
|
|
87
|
+
* Decides what an edit is — a draft fixed in place, or a change of mind the
|
|
88
|
+
* agent has to be told about. */
|
|
89
|
+
function seenByAgent(thread, index) {
|
|
90
|
+
const message = thread.messages[index];
|
|
91
|
+
if (!message) return false;
|
|
92
|
+
if (thread.messages.slice(index + 1).some((m) => m.author === "agent")) return true;
|
|
93
|
+
return thread.deliveredThrough !== void 0 && Date.parse(message.at) <= Date.parse(thread.deliveredThrough);
|
|
94
|
+
}
|
|
86
95
|
/** Agent-started with nothing of the reviewer's in it. Only these are excluded
|
|
87
96
|
* from the reviewer's counts, Send, and the finish flush — the moment the
|
|
88
97
|
* reviewer writes a reply into an agent thread, it carries their feedback and
|
|
@@ -283,8 +292,10 @@ const ACK_NEXT_STEP = {
|
|
|
283
292
|
* POLL_STANCE keeps the poll rules aligned: the surfaces phrase it at different
|
|
284
293
|
* lengths, but these invariants cannot drift apart.
|
|
285
294
|
*
|
|
286
|
-
* It is a map, not a tour
|
|
287
|
-
*
|
|
295
|
+
* It is a map, not a tour, written for a reader who never saw the session:
|
|
296
|
+
* the problem comes before the mechanism, and the diagram draws what happens,
|
|
297
|
+
* not which code names which — a change to text alone has no call graph worth
|
|
298
|
+
* drawing. Every other tool infers a summary by reading the diff back; the session that wrote the change still holds what no diff shows
|
|
288
299
|
* — the invariant it had to respect, the seam it chose, the alternative it
|
|
289
300
|
* rejected, what it left alone on purpose — and that is what the reviewer
|
|
290
301
|
* cannot get anywhere else. Reading order is not on the list: layers own it.
|
|
@@ -293,15 +304,15 @@ const GUIDE = {
|
|
|
293
304
|
/** When one is warranted — and that silence is a valid outcome. */
|
|
294
305
|
when: "multi-file, structural, or subtle — skip when the diff explains itself",
|
|
295
306
|
/** What it contains: ingredients, not sections — use the ones this change needs. */
|
|
296
|
-
what: "a map of the change, not a tour of it:
|
|
307
|
+
what: "a map of the change, not a tour of it: the problem it solves and what it changes, in a sentence or two a reader who never saw your session follows; the flow it changes, from what sets it off to what someone sees, as a small ```mermaid diagram when a picture beats words — functions where code carries it, people and screens when they are the flow, never a file list or which code references which; what is worth checking as they read — an invariant the change must keep, a judgment call it made, a shortcoming it knows about — said in plain words, never behind a label of your own; and what is safe to skip",
|
|
297
308
|
/** The line it must not cross. */
|
|
298
309
|
stance: "Orient reading, never pre-review: no verdicts, nothing is \"fine\"",
|
|
299
310
|
/** What layers took over: the guide never orders the read. */
|
|
300
311
|
order: "no reading order and no file list — layers and the Files tab own those; a change that reads better in order gets a layers suggestion, not a numbered guide",
|
|
301
312
|
/** How much: one screen, and only the parts that apply. */
|
|
302
313
|
budget: "about a hundred words of prose plus the diagram — one screen; use only the parts this change needs, in whatever form fits",
|
|
303
|
-
/** The diagram convention: two tags, and a plain node means existing
|
|
304
|
-
legend: "in the diagram tag new code `:::new` and changed code `:::changed`, declared by the two classDef lines below; a plain node is existing
|
|
314
|
+
/** The diagram convention: two tags, and a plain node means anything existing. */
|
|
315
|
+
legend: "in the diagram tag new code `:::new` and changed code `:::changed`, declared by the two classDef lines below; a plain node is anything existing the change now leans on",
|
|
305
316
|
/** Staleness: the guide is a thread, so updates land under it. */
|
|
306
317
|
update: "reply to your own guide thread with a short update"
|
|
307
318
|
};
|
|
@@ -323,7 +334,13 @@ const GUIDE_CLASSDEFS = ["classDef new stroke:#2e9e4f,stroke-width:2px", "classD
|
|
|
323
334
|
*/
|
|
324
335
|
const LAYERS = {
|
|
325
336
|
/** What one is. */
|
|
326
|
-
what: "one step of the change — a coherent unit you would explain in one breath — with the files that belong to it and a
|
|
337
|
+
what: "one step of the change — a coherent unit you would explain in one breath — with the files that belong to it and a short summary",
|
|
338
|
+
/** What the summary is for — a goal, not a template: the model writes it
|
|
339
|
+
* however this step reads best. The files sit right under it, so retelling
|
|
340
|
+
* them spends the reviewer's attention twice. */
|
|
341
|
+
summary: "say what this layer is about and give the reviewer enough context to review it — the part the files below cannot show on their own. Write it however fits the step, keep it short, and don't retell the diff",
|
|
342
|
+
/** Diagrams when they help: a picture of the step usually beats a paragraph. */
|
|
343
|
+
diagram: "when the step has a shape — a flow, a decision, a before/after — a small ```mermaid diagram usually says it better than prose; tag nodes as the guide does (`:::new`, `:::changed`, plain for anything existing) with the same two classDef lines",
|
|
327
344
|
/** How to order them. */
|
|
328
345
|
order: "the order you would explain it, not the order you wrote it — the file that explains the rest first, mechanical consequences last; for a feature, follow the request from entry point to effect; for a refactor, contract first, then consumers",
|
|
329
346
|
/** When to raise the flag at open — and that not raising it is the common case. */
|
|
@@ -361,7 +378,7 @@ function guideNudge(hasGuide) {
|
|
|
361
378
|
*/
|
|
362
379
|
function layersNudge(review) {
|
|
363
380
|
if (review.layers || review.layersSuggested) return null;
|
|
364
|
-
return `if this changeset reads better in order — ${LAYERS.suggest} — flag it: \`${CLI_COMMANDS.layersSuggest}\`, and offer it in your handoff ("say layers and I'll outline it"). Post the outline only when asked: \`${CLI_COMMANDS.layers}\` — each layer ${LAYERS.what}; ${LAYERS.order}. ${LAYERS.stance}. \`diffo help layers\` has the shape.`;
|
|
381
|
+
return `if this changeset reads better in order — ${LAYERS.suggest} — flag it: \`${CLI_COMMANDS.layersSuggest}\`, and offer it in your handoff ("say layers and I'll outline it"). Post the outline only when asked: \`${CLI_COMMANDS.layers}\` — each layer ${LAYERS.what}; ${LAYERS.summary}; ${LAYERS.diagram}; ${LAYERS.order}. ${LAYERS.stance}. \`diffo help layers\` has the shape.`;
|
|
365
382
|
}
|
|
366
383
|
/**
|
|
367
384
|
* Printed to stderr when a poll takes the review over and the review already
|
|
@@ -588,8 +605,9 @@ function threadBlock(thread, index) {
|
|
|
588
605
|
`id: ${thread.id}`,
|
|
589
606
|
...anchorNote(thread),
|
|
590
607
|
...snapshotBlock(thread),
|
|
608
|
+
...thread.rewound ? ["EDITED: the reviewer rewrote the message marked (edited) and withdrew everything after it, your earlier replies included. Answer the edited version. Code you changed for the withdrawn replies is still in the tree: keep it or revert it as the new message implies, and say which."] : [],
|
|
591
609
|
"Messages:",
|
|
592
|
-
...thread.messages.map((m) => `- ${m.author}: ${m.text.replace(/\n/g, "\n ")}`)
|
|
610
|
+
...thread.messages.map((m) => `- ${m.author}${m.editedAt ? " (edited)" : ""}: ${m.text.replace(/\n/g, "\n ")}`)
|
|
593
611
|
].join("\n");
|
|
594
612
|
}
|
|
595
613
|
function buildThreadPrompt(thread, ctx) {
|
|
@@ -632,11 +650,15 @@ function buildLayersRequestPrompt(ctx, existing) {
|
|
|
632
650
|
const refresh = existing !== null && existing.length > 0;
|
|
633
651
|
const titles = refresh ? existing.map((l) => `"${l.title}"`).join(", ") : "";
|
|
634
652
|
return [
|
|
635
|
-
refresh ? `The reviewer asked you to refresh the layers in \`${ctx.repo.name}\` (branch \`${ctx.repo.branch}\`): the code moved since you outlined it, and files outside the outline have been gathering under "Since your review". Re-post the whole list as the change stands now.` : `The reviewer asked for layers in \`${ctx.repo.name}\` (branch \`${ctx.repo.branch}\`): outline the changeset as steps to read in order. The Layers tab reads "
|
|
653
|
+
refresh ? `The reviewer asked you to refresh the layers in \`${ctx.repo.name}\` (branch \`${ctx.repo.branch}\`): the code moved since you outlined it, and files outside the outline have been gathering under "Since your review". Re-post the whole list as the change stands now.` : `The reviewer asked for layers in \`${ctx.repo.name}\` (branch \`${ctx.repo.branch}\`): outline the changeset as steps to read in order. The Layers tab reads "Outlining…" until you post.`,
|
|
636
654
|
"",
|
|
637
655
|
...ctx.changeset ? [specLine(ctx.changeset), ""] : [],
|
|
638
656
|
...refresh ? [`The outline they have: ${titles}. Keep a title that still fits its step, rename or drop the ones that don't — ${LAYERS.replace}.`, ""] : [],
|
|
639
|
-
`Each layer is ${LAYERS.what}.
|
|
657
|
+
`Each layer is ${LAYERS.what}. Summary: ${LAYERS.summary}. Diagram: ${LAYERS.diagram}:`,
|
|
658
|
+
"",
|
|
659
|
+
...GUIDE_CLASSDEFS.map((line) => ` ${line}`),
|
|
660
|
+
"",
|
|
661
|
+
`Order: ${LAYERS.order}. ${LAYERS.mechanical}. ${LAYERS.stance}. Files are whole files, by path relative to the repo root; list every file of the changeset somewhere, or the leftovers land in "Since your review".`,
|
|
640
662
|
"",
|
|
641
663
|
`Shape: ${LAYERS.shape}`,
|
|
642
664
|
"",
|
|
@@ -702,8 +724,8 @@ function buildFinishPrompt(threads, ctx, coverage) {
|
|
|
702
724
|
}
|
|
703
725
|
//#endregion
|
|
704
726
|
//#region src/shared/layers.ts
|
|
705
|
-
/** A summary is
|
|
706
|
-
*
|
|
727
|
+
/** A summary is short by doctrine; this is the backstop against an essay, the
|
|
728
|
+
* same cap a closing note gets. */
|
|
707
729
|
const SUMMARY_CAP = 4e3;
|
|
708
730
|
/** A note is one line by contract — anything past the first newline is dropped,
|
|
709
731
|
* and the line itself is capped so the file header stays a header. */
|
|
@@ -927,6 +949,7 @@ The loop:
|
|
|
927
949
|
outline only when the reviewer asks — in chat, or through the poll as a
|
|
928
950
|
\`"kind": "layers"\` payload: \`diffo layers --json '<Layer[]>'\`
|
|
929
951
|
(or pipe it to \`diffo layers --stdin\`). Each layer is ${LAYERS.what}.
|
|
952
|
+
Summary: ${LAYERS.summary}. Diagram: ${LAYERS.diagram}.
|
|
930
953
|
Order: ${LAYERS.order}. ${LAYERS.mechanical}. ${LAYERS.stance}.
|
|
931
954
|
${LAYERS.replace}. \`diffo help layers\` has the shape.
|
|
932
955
|
4. Listen: run \`${CLI_COMMANDS.firstPoll}\` — it blocks until the reviewer
|
|
@@ -990,9 +1013,9 @@ would have to decode.
|
|
|
990
1013
|
One shape that works — not THE shape: a rename needs no diagram, a one-file
|
|
991
1014
|
change needs no checks, and headings are optional.
|
|
992
1015
|
|
|
993
|
-
|
|
994
|
-
\`read_tool_result\` so the model can page the
|
|
995
|
-
the text is recomputed on read.
|
|
1016
|
+
A huge tool result could overflow the model's context. This caps it at the
|
|
1017
|
+
model boundary and adds \`read_tool_result\` so the model can page the
|
|
1018
|
+
rest — nothing is stored, the text is recomputed on read.
|
|
996
1019
|
|
|
997
1020
|
\`\`\`mermaid
|
|
998
1021
|
flowchart LR
|
|
@@ -1085,6 +1108,12 @@ Usage: diffo layers --suggest ["<why, in one line>"] at open: this read benefi
|
|
|
1085
1108
|
… | diffo layers --stdin the same payload, piped
|
|
1086
1109
|
|
|
1087
1110
|
Each layer is ${LAYERS.what}.
|
|
1111
|
+
Summary: ${LAYERS.summary}.
|
|
1112
|
+
Diagram: ${LAYERS.diagram}:
|
|
1113
|
+
|
|
1114
|
+
${GUIDE_CLASSDEFS[0]}
|
|
1115
|
+
${GUIDE_CLASSDEFS[1]}
|
|
1116
|
+
|
|
1088
1117
|
Order: ${LAYERS.order}.
|
|
1089
1118
|
${LAYERS.mechanical}.
|
|
1090
1119
|
${LAYERS.stance}.
|
|
@@ -1100,7 +1129,7 @@ Output: {"ok":true,"layers":4,"next_step":"…"}
|
|
|
1100
1129
|
|
|
1101
1130
|
Examples:
|
|
1102
1131
|
diffo layers --suggest "the parser change explains the rest"
|
|
1103
|
-
diffo layers --json '[{"title":"Parser contract","summary":"
|
|
1132
|
+
diffo layers --json '[{"title":"Parser contract","summary":"The contract the rest of the change leans on: bad input now comes back as null, not an exception.","files":["src/parse.ts"]},{"title":"Callers adapted","kind":"mechanical","summary":"Call sites following the new return type.","files":["src/cli.ts","src/api.ts"]}]'`,
|
|
1104
1133
|
end: `diffo end — detach from the review politely
|
|
1105
1134
|
|
|
1106
1135
|
Usage: diffo end
|
|
@@ -2991,18 +3020,56 @@ var ReviewStore = class {
|
|
|
2991
3020
|
};
|
|
2992
3021
|
});
|
|
2993
3022
|
}
|
|
3023
|
+
/**
|
|
3024
|
+
* The reviewer rewrites one of their own messages. Words the agent never saw
|
|
3025
|
+
* are a draft fixed in place. Words it did see are a change of mind, like
|
|
3026
|
+
* editing a chat message: the message is stamped edited and everything after
|
|
3027
|
+
* it is cut — the agent's answers to the old words included — so the thread
|
|
3028
|
+
* is the agent's to answer again. Cut, not kept: the old branch is not worth
|
|
3029
|
+
* a second history on the card. `withheld` holds a seen rewrite back from the
|
|
3030
|
+
* agent, the same as a withheld reply.
|
|
3031
|
+
*/
|
|
3032
|
+
editMessage(threadId, messageId, text, withheld = false) {
|
|
3033
|
+
const current = this.state.threads.find((t) => t.id === threadId);
|
|
3034
|
+
const index = current?.messages.findIndex((m) => m.id === messageId) ?? -1;
|
|
3035
|
+
if (!current || index === -1) return null;
|
|
3036
|
+
const seen = seenByAgent(current, index);
|
|
3037
|
+
const cut = current.messages.slice(index + 1);
|
|
3038
|
+
const cutAnswer = cut.some((m) => m.author === "agent");
|
|
3039
|
+
return this.update(threadId, ({ unanswered, awaitingFollowUp, ...thread }) => {
|
|
3040
|
+
const before = thread.messages[index];
|
|
3041
|
+
const edited = {
|
|
3042
|
+
...before,
|
|
3043
|
+
text,
|
|
3044
|
+
...seen || before.editedAt ? { editedAt: (/* @__PURE__ */ new Date()).toISOString() } : {}
|
|
3045
|
+
};
|
|
3046
|
+
return {
|
|
3047
|
+
...thread,
|
|
3048
|
+
...unanswered && !seen ? { unanswered } : {},
|
|
3049
|
+
...awaitingFollowUp && !cutAnswer ? { awaitingFollowUp } : {},
|
|
3050
|
+
...cutAnswer && thread.state === "addressed" ? { state: "sent" } : {},
|
|
3051
|
+
...seen && cut.length > 0 ? { rewound: true } : {},
|
|
3052
|
+
...seen && withheld ? { withheld: true } : {},
|
|
3053
|
+
messages: [...thread.messages.slice(0, index), edited]
|
|
3054
|
+
};
|
|
3055
|
+
});
|
|
3056
|
+
}
|
|
2994
3057
|
/** A delivery just handed these threads to the agent — remember through when,
|
|
2995
|
-
* so replies and the typing indicator can tell delivered words from raced ones.
|
|
3058
|
+
* so replies and the typing indicator can tell delivered words from raced ones.
|
|
3059
|
+
* The delivery also carried the word that a rewind withdrew the old replies. */
|
|
2996
3060
|
markDelivered(threadIds) {
|
|
2997
3061
|
const ids = new Set(threadIds);
|
|
2998
3062
|
if (ids.size === 0) return;
|
|
2999
3063
|
const at = (/* @__PURE__ */ new Date()).toISOString();
|
|
3000
3064
|
this.state = {
|
|
3001
3065
|
...this.state,
|
|
3002
|
-
threads: this.state.threads.map((t) => ids.has(t.id) ? {
|
|
3066
|
+
threads: this.state.threads.map(({ rewound, ...t }) => ids.has(t.id) ? {
|
|
3003
3067
|
...t,
|
|
3004
3068
|
deliveredThrough: at
|
|
3005
|
-
} :
|
|
3069
|
+
} : {
|
|
3070
|
+
...t,
|
|
3071
|
+
...rewound ? { rewound } : {}
|
|
3072
|
+
})
|
|
3006
3073
|
};
|
|
3007
3074
|
this.commit();
|
|
3008
3075
|
}
|
|
@@ -3457,7 +3524,8 @@ function normalizeThread(value, now) {
|
|
|
3457
3524
|
text: msg.text,
|
|
3458
3525
|
at: typeof msg.at === "string" ? msg.at : now,
|
|
3459
3526
|
...typeof msg.durationMs === "number" ? { durationMs: msg.durationMs } : {},
|
|
3460
|
-
...msg.author === "agent" && typeof msg.suggestedReply === "string" && msg.suggestedReply ? { suggestedReply: msg.suggestedReply } : {}
|
|
3527
|
+
...msg.author === "agent" && typeof msg.suggestedReply === "string" && msg.suggestedReply ? { suggestedReply: msg.suggestedReply } : {},
|
|
3528
|
+
...typeof msg.editedAt === "string" ? { editedAt: msg.editedAt } : {}
|
|
3461
3529
|
});
|
|
3462
3530
|
}
|
|
3463
3531
|
return {
|
|
@@ -3472,6 +3540,7 @@ function normalizeThread(value, now) {
|
|
|
3472
3540
|
...t.awaitingFollowUp === true && t.unanswered !== true ? { awaitingFollowUp: true } : {},
|
|
3473
3541
|
...t.closingNote === true ? { closingNote: true } : {},
|
|
3474
3542
|
...typeof t.sentAt === "string" ? { sentAt: t.sentAt } : {},
|
|
3543
|
+
...t.rewound === true ? { rewound: true } : {},
|
|
3475
3544
|
messages,
|
|
3476
3545
|
createdAt: typeof t.createdAt === "string" ? t.createdAt : now,
|
|
3477
3546
|
updatedAt: typeof t.updatedAt === "string" ? t.updatedAt : now
|
|
@@ -4090,6 +4159,34 @@ function createApp(ctx, store, review, queue) {
|
|
|
4090
4159
|
presence: queue?.presence() ?? "waiting"
|
|
4091
4160
|
});
|
|
4092
4161
|
});
|
|
4162
|
+
app.patch("/api/review/threads/:id/messages/:messageId", async (c) => {
|
|
4163
|
+
if (!review) return c.json({ error: "review unavailable" }, 503);
|
|
4164
|
+
const body = await c.req.json().catch(() => null);
|
|
4165
|
+
const text = typeof body?.text === "string" ? body.text.trim() : "";
|
|
4166
|
+
if (!text) return c.json({ error: "need {text}" }, 400);
|
|
4167
|
+
const id = c.req.param("id");
|
|
4168
|
+
const messageId = c.req.param("messageId");
|
|
4169
|
+
const current = review.get().threads.find((t) => t.id === id);
|
|
4170
|
+
const index = current?.messages.findIndex((m) => m.id === messageId) ?? -1;
|
|
4171
|
+
if (!current || index === -1) return c.json({ error: "no such message" }, 404);
|
|
4172
|
+
if (current.messages[index].author !== "reviewer") return c.json({ error: "only your own messages can be edited" }, 400);
|
|
4173
|
+
if (current.state === "resolved") return c.json({ error: "reopen the thread to edit it" }, 409);
|
|
4174
|
+
if (queue?.deliveredThreadIds().includes(id)) return c.json({ error: "the agent is answering this thread — edit after it replies" }, 409);
|
|
4175
|
+
const seen = seenByAgent(current, index);
|
|
4176
|
+
const deliver = body?.deliver !== false;
|
|
4177
|
+
let thread = review.editMessage(id, messageId, text, !deliver);
|
|
4178
|
+
let delivered = false;
|
|
4179
|
+
if (seen && deliver && (thread.state === "sent" || thread.state === "addressed")) {
|
|
4180
|
+
delivered = deliverThreads([id]);
|
|
4181
|
+
review.clearWithheld([id]);
|
|
4182
|
+
thread = review.get().threads.find((t) => t.id === id) ?? thread;
|
|
4183
|
+
}
|
|
4184
|
+
return c.json({
|
|
4185
|
+
thread,
|
|
4186
|
+
delivered,
|
|
4187
|
+
presence: queue?.presence() ?? "waiting"
|
|
4188
|
+
});
|
|
4189
|
+
});
|
|
4093
4190
|
app.post("/api/review/threads/:id/state", async (c) => {
|
|
4094
4191
|
if (!review) return c.json({ error: "review unavailable" }, 503);
|
|
4095
4192
|
const state = (await c.req.json().catch(() => null))?.state;
|
package/dist/client/assets/{abnfDiagram-O67JEVCF-Eku-JiMb.js → abnfDiagram-O67JEVCF-vILxBZcB.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{m as e,t}from"./mermaid-parser.core-
|
|
1
|
+
import{m as e,t}from"./mermaid-parser.core-D2BrkwRE.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-YTrwJCk8.js";import"./chunk-O7XYJQB3-DG64mbS_.js";import{n as i,r as a,t as o}from"./chunk-GTNCS2PH-JFHsSpPU.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-CCFlYVgY.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e,t}from"./path-fybaL0A-.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-
|
|
1
|
+
import{n as e,t}from"./path-fybaL0A-.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-BWYGCgdo.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i){if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./chunk-FOHPRMQF-DzxwRta7.js";import{M as e}from"./mermaid-parser.core-D2BrkwRE.js";export{e as createArchitectureServices};
|