pm-brief 2026.10.21 → 2026.10.23
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/CHANGELOG.md +17 -0
- package/README.md +159 -0
- package/dist/alternatives.d.ts +45 -0
- package/dist/alternatives.d.ts.map +1 -0
- package/dist/alternatives.js +103 -0
- package/dist/alternatives.js.map +1 -0
- package/dist/handoff.d.ts +102 -0
- package/dist/handoff.d.ts.map +1 -0
- package/dist/handoff.js +352 -0
- package/dist/handoff.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/docs/examples/alternatives.md +22 -0
- package/docs/examples/handoff.json +6 -0
- package/manifest.json +1 -1
- package/package.json +7 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026.10.23 - 2026-10-23
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Enable the gated GitHub issue sync ([pm-brief-gp5o](https://github.com/unbraind/pm-brief/blob/main/.agents/pm/chores/pm-brief-gp5o.toon))
|
|
8
|
+
- Adopt pm-github 2026.10.16: default-branch-safe gated sync and daily gated closeout PRs ([pm-brief-b7dy](https://github.com/unbraind/pm-brief/blob/main/.agents/pm/chores/pm-brief-b7dy.toon))
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- The publish-attestation gate misses a publish routed through an unquoted shell variable ([pm-brief-tai3](https://github.com/unbraind/pm-brief/blob/main/.agents/pm/issues/pm-brief-tai3.toon))
|
|
13
|
+
- The release job authenticated with a stored npm token that expired, so publishing stopped while every other gate stayed green ([pm-brief-s83v](https://github.com/unbraind/pm-brief/blob/main/.agents/pm/issues/pm-brief-s83v.toon))
|
|
14
|
+
- A release run bumped and committed a new version every night while publishing was impossible, because the only externally-failable step runs last ([pm-brief-4ohy](https://github.com/unbraind/pm-brief/blob/main/.agents/pm/issues/pm-brief-4ohy.toon))
|
|
15
|
+
|
|
16
|
+
### Other
|
|
17
|
+
|
|
18
|
+
- Enable GitHub CodeQL code scanning ([pm-brief-1p5o](https://github.com/unbraind/pm-brief/blob/main/.agents/pm/chores/pm-brief-1p5o.toon))
|
|
19
|
+
|
|
3
20
|
## 2026.10.21 - 2026-10-21
|
|
4
21
|
|
|
5
22
|
### Fixed
|
package/README.md
CHANGED
|
@@ -47,6 +47,7 @@ pm brief since 2026-07-20T00:00:00Z --until 2026-07-22 --author alice
|
|
|
47
47
|
- `pm brief since <checkpoint>` renders a delta brief of what changed since a checkpoint.
|
|
48
48
|
- `pm brief diverge [base]` previews pm item collisions between two branches **before** merging.
|
|
49
49
|
- `pm brief duplicates` sweeps the merged tracker for near-duplicate items the create-time advisory cannot see across branches.
|
|
50
|
+
- `pm brief alternatives <id> <id> [more ids]` compares recorded proposals, outcomes and evidence with exact citations and no recommendation.
|
|
50
51
|
|
|
51
52
|
### Ranking and Budget Flags
|
|
52
53
|
|
|
@@ -410,3 +411,161 @@ compaction. Command-local selection limits and document budgets still apply.
|
|
|
410
411
|
trackers: projection, budget omission, every-row cursor recovery, and writer
|
|
411
412
|
rejection. Remove only the declarations, rebuild, and prove the tests fail.
|
|
412
413
|
5. Run unchanged npm and Bun release gates and document their exact results.
|
|
414
|
+
|
|
415
|
+
## Acknowledged handoff contracts
|
|
416
|
+
|
|
417
|
+
`pm brief handoff` records what each receiving agent understood against exact
|
|
418
|
+
item content revisions. A packet includes explicit questions, unresolved
|
|
419
|
+
assumptions, required evidence and the transitive declared blocker closure.
|
|
420
|
+
A changed blocker, source item or evidence item invalidates its old receipts.
|
|
421
|
+
Two receivers append independent receipts to the same tracker; identical retries
|
|
422
|
+
by the same author add nothing. Claims continue to own work ownership.
|
|
423
|
+
|
|
424
|
+
```sh
|
|
425
|
+
# Set an explicit identity for each sender or receiver.
|
|
426
|
+
export PM_AUTHOR=sender
|
|
427
|
+
# Replace the focus/evidence item ids in docs/examples/handoff.json.
|
|
428
|
+
pm brief handoff preview --input docs/examples/handoff.json --json
|
|
429
|
+
pm brief handoff create --input docs/examples/handoff.json --json
|
|
430
|
+
# Save the returned id and digest. Then write response.json, as shown below.
|
|
431
|
+
PM_AUTHOR=receiver-a pm brief handoff ack <packet-id> --input response.json --json
|
|
432
|
+
pm brief handoff show <packet-id> --receiver receiver-a
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
A receiver supplies every obligation id, including evidence that is still missing:
|
|
436
|
+
|
|
437
|
+
```json
|
|
438
|
+
{
|
|
439
|
+
"digest": "<64-character digest from the packet>",
|
|
440
|
+
"questions": { "fixture": "I will use the public tracker fixture." },
|
|
441
|
+
"assumptions": { "review": "Unresolved; I will verify the blocker before proceeding." },
|
|
442
|
+
"evidence": { "report": "The report link is missing; validation remains outstanding." }
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
Every collection is explicit; use `[]` in contracts and `{}` in responses when
|
|
447
|
+
there are no obligations. Each input collection has at most 32 entries; the
|
|
448
|
+
blocker/evidence closure has at most 64 items. Keys use ASCII letters, digits,
|
|
449
|
+
dots, underscores or hyphens and start with a letter or digit. Obligation and actor
|
|
450
|
+
keys have at most 128 characters; native item identifiers retain their full length. Obligation text and evidence references have at most 2,000 code units.
|
|
451
|
+
Native source titles and blocker references retain their full text under the aggregate budget.
|
|
452
|
+
Native TOON is the default; `--json` uses the host's
|
|
453
|
+
structured JSON output. The default conservative output ceiling is 4,000 tokens,
|
|
454
|
+
measured from UTF-8 bytes with twice pretty-JSON size plus framing headroom.
|
|
455
|
+
`--token-budget` accepts up to 64,000. Oversized output refuses with a remedy;
|
|
456
|
+
it never silently drops questions, assumptions, evidence or receiver receipts.
|
|
457
|
+
A receiver filter reduces the selected receipt set without changing storage.
|
|
458
|
+
Universal host output controls can intentionally project or paginate read commands;
|
|
459
|
+
retain their omission receipts and use normal output for a complete contract.
|
|
460
|
+
|
|
461
|
+
Evidence requirements select exact native `docs`, `files` or `tests` links by
|
|
462
|
+
`item`, `kind` and `ref` (path, or test command). `missingEvidence` remains visible
|
|
463
|
+
in the packet and each receipt. Linkage proves a reference was recorded; it does
|
|
464
|
+
not prove that a file exists, its contents are correct, or a test passed. Receiver
|
|
465
|
+
statements are self-reported understanding, including disagreement or uncertainty.
|
|
466
|
+
`valid` means the source revisions still match; `ready` additionally means all
|
|
467
|
+
required links are present. Neither field grants approval or claims the work.
|
|
468
|
+
|
|
469
|
+
Packets are native Decision items tagged `pm-brief-handoff`; their JSON bodies are
|
|
470
|
+
immutable protocol artifacts. Receipts are append-only native comments protected
|
|
471
|
+
by the host's comment lock and author/text idempotency. Native lock contention
|
|
472
|
+
is retried up to three times for reads and idempotent appends; creates are never
|
|
473
|
+
automatically retried. Persistent contention refuses with a retry remedy. Do not edit contract bodies
|
|
474
|
+
or receipt comments. Create a fresh packet after a revision changes. A receipt
|
|
475
|
+
racing a source edit is reassessed on return and every subsequent read. All source
|
|
476
|
+
metadata, bodies and linked evidence contribute to content revisions, so even an
|
|
477
|
+
unrelated source comment conservatively invalidates old understanding. Reads are
|
|
478
|
+
certified full-corpus snapshots, not a transaction spanning arbitrary source writers.
|
|
479
|
+
|
|
480
|
+
The SDK exports `previewHandoff`, `createHandoff`, `acknowledgeHandoff`,
|
|
481
|
+
`inspectHandoff`, their typed contracts, and `HandoffError` (`code`, `remedy`).
|
|
482
|
+
Pass `{ pmRoot, author, tokenBudget? }`, optionally with the active native `PmClient`.
|
|
483
|
+
CLI expected refusals exit 2 (3 for a stale packet), with a stable `handoff_<code>`
|
|
484
|
+
JSON category and a `required` remedy.
|
|
485
|
+
Categories cover invalid input, identity, missing packets/items, response coverage,
|
|
486
|
+
integrity, budget and tracker reads. Validation and budget checks precede writes.
|
|
487
|
+
The commands never change source items or claims; `preview` and `show` are read-only.
|
|
488
|
+
|
|
489
|
+
This complements [pm-context](https://github.com/unbraind/pm-context)'s
|
|
490
|
+
context delivery/usage receipts and the [since-delta candidate](https://github.com/unbraind/pm-context/pull/164)
|
|
491
|
+
(`feat/since-delta-pack`)
|
|
492
|
+
(`pm context-pack since --from <timestamp>` or `--cursor <cursor>`). That candidate
|
|
493
|
+
owns cursor progress, changed-context selection and omission receipts. Use its delta to
|
|
494
|
+
refresh changed context, then create a new handoff here. No history delta engine
|
|
495
|
+
is duplicated. pm-memory continues to own standing knowledge; `brief prompt`
|
|
496
|
+
continues to generate prose. See the [contract example](docs/examples/handoff.json).
|
|
497
|
+
|
|
498
|
+
## Decision alternatives digest
|
|
499
|
+
|
|
500
|
+
```bash
|
|
501
|
+
pm brief alternatives pm-proposal-a pm-proposal-b --token-budget 4000
|
|
502
|
+
pm brief alternatives pm-proposal-a pm-proposal-b --json
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
Select 2–32 distinct exact item IDs, including terminal items when useful. The
|
|
506
|
+
read-only digest keeps each item separate and follows input order, which conveys
|
|
507
|
+
no preference. It quotes records instead of generating or inferring conclusions.
|
|
508
|
+
Conflicting Plan decisions within one item also remain separate. Core `pm plan`
|
|
509
|
+
owns planning and choices; `pm-review` owns finding verdicts. This command composes
|
|
510
|
+
those records across items without adding a decision engine.
|
|
511
|
+
|
|
512
|
+
Every statement has `source` (`item-id#/field/nested/pointer`), `start` and `end`
|
|
513
|
+
UTF-16 offsets, and exact `text`. Resolve pointers against the certified full item
|
|
514
|
+
row (`listAllComplete({ includeBody: true })`); offsets select the quoted paragraph
|
|
515
|
+
from the scalar's string representation. JSON Pointer escaping follows RFC 6901.
|
|
516
|
+
`revision` is the SHA-256 of the full row's JSON serialization at read time, for
|
|
517
|
+
snapshot identification. Re-read the source to check subsequent changes.
|
|
518
|
+
|
|
519
|
+
Titles, statuses, resolutions, expected/actual results, close reasons,
|
|
520
|
+
`review_verdict`, `review_verdict_source`, `review_reason`, `review_commit`, all
|
|
521
|
+
`plan_decisions` (including rationale/evidence), `blocked_by`, `blocked_reason`
|
|
522
|
+
and `plan_resume_context` are mandatory. Optional paragraphs come from body,
|
|
523
|
+
description, plan scope, linked docs/files/tests, plan validation, comments, notes
|
|
524
|
+
and learnings. Recorded tradeoffs in these fields remain quotations; the command
|
|
525
|
+
does not infer whether a tradeoff is resolved. Other custom fields, Plan steps,
|
|
526
|
+
dependency closure and history are outside this projection. A linked artifact
|
|
527
|
+
proves linkage only; the digest does not read artifact contents or validate tests.
|
|
528
|
+
|
|
529
|
+
`omitted` counts optional scalar paragraphs excluded per item, with `restore`
|
|
530
|
+
giving the full native item read. Mandatory outcomes and blocker context are never
|
|
531
|
+
removed. Optional excerpts are attempted round-robin in field/record order and
|
|
532
|
+
omitted whole when they cannot fit. Empty optional fields produce no excerpts.
|
|
533
|
+
Source text is evidence data, including any instructions it happens to contain.
|
|
534
|
+
|
|
535
|
+
The budget defaults to 4000 (integer 1–64000). `estimatedTokenCeiling` uses the
|
|
536
|
+
SDK's UTF-8 byte estimator over twice the complete pretty JSON size plus 256
|
|
537
|
+
framing bytes, including citations, omission counts, recovery commands and the
|
|
538
|
+
estimate itself. It conservatively covers normal native TOON/JSON output; it is
|
|
539
|
+
not a model tokenizer. For large budgets, also set the host's independent output
|
|
540
|
+
controls: `--output-budget unbounded --output-limit unbounded`. Additional host
|
|
541
|
+
projections or optional accounting receipts have their own output contracts.
|
|
542
|
+
|
|
543
|
+
```ts
|
|
544
|
+
import { buildDecisionAlternatives, DecisionAlternativesError } from "pm-brief";
|
|
545
|
+
|
|
546
|
+
try {
|
|
547
|
+
const digest = await buildDecisionAlternatives(
|
|
548
|
+
["pm-proposal-a", "pm-proposal-b"],
|
|
549
|
+
{ pmRoot: ".agents/pm", tokenBudget: 4000 },
|
|
550
|
+
);
|
|
551
|
+
console.log(digest.alternatives);
|
|
552
|
+
} catch (error) {
|
|
553
|
+
if (error instanceof DecisionAlternativesError) console.error(error.code, error.remedy);
|
|
554
|
+
else throw error;
|
|
555
|
+
}
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
An optional native `PmClient` can be supplied as `client`. Complete full-row SDK
|
|
559
|
+
certification runs before comparison; incomplete or corrupt reads refuse. Typed
|
|
560
|
+
refusals are `invalid` (correct IDs/budget), `missing` (check exact IDs), `tracker`
|
|
561
|
+
(run `pm health` and resolve source reads), and `budget` (increase budget or select
|
|
562
|
+
fewer items). CLI refusals exit 2 and retain `alternatives_<code>` and a remedy in
|
|
563
|
+
the host's expected-error contract. See the [worked example](docs/examples/alternatives.md).
|
|
564
|
+
|
|
565
|
+
## Without git
|
|
566
|
+
|
|
567
|
+
Briefs, prompts, ranking, history deltas, governance, duplicate checks and all
|
|
568
|
+
handoff and decision alternatives commands work in plain initialized trackers without a git executable.
|
|
569
|
+
Handoff storage uses the native SDK dispatcher and can reuse a host client.
|
|
570
|
+
`brief diverge` needs a git repository and git refs. Handoff receipts have no
|
|
571
|
+
branch, commit or repository dependency.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { PmClient } from "@unbrained/pm-cli/sdk";
|
|
2
|
+
import type { ExtensionApi } from "@unbrained/pm-cli/sdk/authoring";
|
|
3
|
+
/** Exact recorded text with an item-relative JSON Pointer and UTF-16 range. */
|
|
4
|
+
export interface DecisionExcerpt {
|
|
5
|
+
source: string;
|
|
6
|
+
start: number;
|
|
7
|
+
end: number;
|
|
8
|
+
text: string;
|
|
9
|
+
}
|
|
10
|
+
/** One proposal remains independent, including all recorded outcomes and blockers. */
|
|
11
|
+
export interface DecisionAlternative {
|
|
12
|
+
id: string;
|
|
13
|
+
revision: string;
|
|
14
|
+
statements: DecisionExcerpt[];
|
|
15
|
+
omitted: number;
|
|
16
|
+
restore: string;
|
|
17
|
+
}
|
|
18
|
+
/** Extractive comparison; ordering follows the caller and never implies preference. */
|
|
19
|
+
export interface DecisionAlternativesDigest {
|
|
20
|
+
protocol: "pm-brief.alternatives/v1";
|
|
21
|
+
alternatives: DecisionAlternative[];
|
|
22
|
+
estimatedTokenCeiling: number;
|
|
23
|
+
}
|
|
24
|
+
/** Backend-neutral read context; injected native clients retain the active host dispatcher. */
|
|
25
|
+
export interface DecisionAlternativesOptions {
|
|
26
|
+
pmRoot: string;
|
|
27
|
+
client?: PmClient;
|
|
28
|
+
tokenBudget?: number;
|
|
29
|
+
}
|
|
30
|
+
/** Stable expected failure categories for SDK consumers. */
|
|
31
|
+
export type DecisionAlternativesRefusalCode = "invalid" | "missing" | "tracker" | "budget";
|
|
32
|
+
/** Typed refusal with a recovery action, never an empty successful comparison. */
|
|
33
|
+
export declare class DecisionAlternativesError extends Error {
|
|
34
|
+
/** Machine-readable failure category. */
|
|
35
|
+
readonly code: DecisionAlternativesRefusalCode;
|
|
36
|
+
/** Concrete correction to perform before retrying. */
|
|
37
|
+
readonly remedy: string;
|
|
38
|
+
/** Retain machine and human recovery information independently. */
|
|
39
|
+
constructor(code: DecisionAlternativesRefusalCode, message: string, remedy: string);
|
|
40
|
+
}
|
|
41
|
+
/** Compare explicitly selected native records read-only; never recommend, merge outcomes or invoke git. */
|
|
42
|
+
export declare function buildDecisionAlternatives(ids: string[], options: DecisionAlternativesOptions): Promise<DecisionAlternativesDigest>;
|
|
43
|
+
/** Register a native structured command so host TOON/JSON and error contracts remain authoritative. */
|
|
44
|
+
export declare function registerDecisionAlternativesCommand(api: ExtensionApi): void;
|
|
45
|
+
//# sourceMappingURL=alternatives.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alternatives.d.ts","sourceRoot":"","sources":["../alternatives.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAA+E,MAAM,uBAAuB,CAAC;AAE9H,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAEpE,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAAG,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAC7F,sFAAsF;AACtF,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AACD,uFAAuF;AACvF,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,0BAA0B,CAAC;IACrC,YAAY,EAAE,mBAAmB,EAAE,CAAC;IACpC,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AACD,+FAA+F;AAC/F,MAAM,WAAW,2BAA2B;IAAG,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,QAAQ,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE;AACxG,4DAA4D;AAC5D,MAAM,MAAM,+BAA+B,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAC3F,kFAAkF;AAClF,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,yCAAyC;IACzC,QAAQ,CAAC,IAAI,EAAE,+BAA+B,CAAC;IAC/C,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mEAAmE;IACnE,YAAY,IAAI,EAAE,+BAA+B,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAEjF;CACF;AA0BD,2GAA2G;AAC3G,wBAAsB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CA4BxI;AAED,uGAAuG;AACvG,wBAAgB,mCAAmC,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAc3E"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { PmClient, certifyCompleteListResult, createPmCliExpectedError, estimatePmOutputTokens } from "@unbrained/pm-cli/sdk";
|
|
3
|
+
/** Typed refusal with a recovery action, never an empty successful comparison. */
|
|
4
|
+
export class DecisionAlternativesError extends Error {
|
|
5
|
+
/** Machine-readable failure category. */
|
|
6
|
+
code;
|
|
7
|
+
/** Concrete correction to perform before retrying. */
|
|
8
|
+
remedy;
|
|
9
|
+
/** Retain machine and human recovery information independently. */
|
|
10
|
+
constructor(code, message, remedy) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = "DecisionAlternativesError";
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.remedy = remedy;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const REQUIRED = ["title", "status", "resolution", "expected_result", "actual_result", "close_reason", "review_verdict", "review_verdict_source", "review_reason", "review_commit", "plan_decisions", "blocked_by", "blocked_reason", "plan_resume_context"];
|
|
18
|
+
const OPTIONAL = ["body", "description", "plan_scope", "docs", "files", "tests", "plan_validation", "comments", "notes", "learnings"];
|
|
19
|
+
/** Reject malformed agent selection before reading a tracker. */
|
|
20
|
+
function validate(ids, budget) {
|
|
21
|
+
if (!Array.isArray(ids) || ids.length < 2 || ids.length > 32 || new Set(ids).size !== ids.length || ids.some(id => typeof id !== "string" || !/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(id)) || !Number.isSafeInteger(budget) || budget < 1 || budget > 64000) {
|
|
22
|
+
throw new DecisionAlternativesError("invalid", "Invalid alternative selection or token budget", "Supply 2-32 distinct exact item ids and an integer --token-budget from 1 to 64000 (default 4000)");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** Walk recorded JSON values without inventing summaries or dropping conflicting entries. */
|
|
26
|
+
function excerpts(value, source) {
|
|
27
|
+
if (value === null || value === undefined || value === "")
|
|
28
|
+
return [];
|
|
29
|
+
if (Array.isArray(value))
|
|
30
|
+
return value.flatMap((entry, i) => excerpts(entry, `${source}/${i}`));
|
|
31
|
+
if (typeof value === "object")
|
|
32
|
+
return Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).flatMap(([key, entry]) => excerpts(entry, `${source}/${key.replace(/~/g, "~0").replace(/\//g, "~1")}`));
|
|
33
|
+
const text = String(value);
|
|
34
|
+
// Whole paragraphs preserve complete recorded sentences, including punctuation.
|
|
35
|
+
return [...text.matchAll(/[^\r\n]+(?:\r?\n(?!\s*\r?\n)[^\r\n]+)*/g)].map(match => ({ source, start: match.index, end: match.index + match[0].length, text: match[0] }));
|
|
36
|
+
}
|
|
37
|
+
/** Measure citations, omission counts, recovery commands and framing with the native estimator. */
|
|
38
|
+
function measure(digest) {
|
|
39
|
+
digest.estimatedTokenCeiling = 64000;
|
|
40
|
+
digest.estimatedTokenCeiling = estimatePmOutputTokens(Buffer.byteLength(JSON.stringify(digest, null, 2)) * 2 + 256);
|
|
41
|
+
return digest.estimatedTokenCeiling;
|
|
42
|
+
}
|
|
43
|
+
/** Compare explicitly selected native records read-only; never recommend, merge outcomes or invoke git. */
|
|
44
|
+
export async function buildDecisionAlternatives(ids, options) {
|
|
45
|
+
const budget = options.tokenBudget ?? 4000;
|
|
46
|
+
validate(ids, budget);
|
|
47
|
+
let items;
|
|
48
|
+
try {
|
|
49
|
+
const client = options.client ?? new PmClient({ pmRoot: options.pmRoot, noExtensions: true });
|
|
50
|
+
items = certifyCompleteListResult(await client.listAllComplete({ includeBody: true })).items;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
throw new DecisionAlternativesError("tracker", "Cannot certify the tracker snapshot", "Run pm health and resolve unreadable or incomplete records before retrying");
|
|
54
|
+
}
|
|
55
|
+
const rows = new Map(items.map(item => [item.id, item]));
|
|
56
|
+
if (ids.some(id => !rows.has(id)))
|
|
57
|
+
throw new DecisionAlternativesError("missing", "A selected alternative does not exist", "Check the exact ids with pm list --all --full; no alternative is silently removed");
|
|
58
|
+
const optional = [];
|
|
59
|
+
const alternatives = ids.map(id => {
|
|
60
|
+
const item = rows.get(id);
|
|
61
|
+
const extra = OPTIONAL.flatMap(field => excerpts(item[field], `${id}#/${field}`));
|
|
62
|
+
optional.push(extra);
|
|
63
|
+
return { id, revision: createHash("sha256").update(JSON.stringify(item)).digest("hex"), statements: REQUIRED.flatMap(field => excerpts(item[field], `${id}#/${field}`)), omitted: extra.length, restore: `pm get ${id} --json --output-budget unbounded --output-limit unbounded` };
|
|
64
|
+
});
|
|
65
|
+
const digest = { protocol: "pm-brief.alternatives/v1", alternatives, estimatedTokenCeiling: 0 };
|
|
66
|
+
if (measure(digest) > budget)
|
|
67
|
+
throw new DecisionAlternativesError("budget", "Mandatory alternative context exceeds the token budget", "Increase --token-budget (maximum 64000) or compare fewer items; titles, statuses, outcomes and blocker context are never dropped");
|
|
68
|
+
// Round-robin optional excerpts give each proposal context without ranking it.
|
|
69
|
+
const longest = Math.max(...optional.map(rows => rows.length));
|
|
70
|
+
for (let i = 0; i < longest; i++)
|
|
71
|
+
for (let j = 0; j < alternatives.length; j++) {
|
|
72
|
+
const excerpt = optional[j][i];
|
|
73
|
+
if (!excerpt)
|
|
74
|
+
continue;
|
|
75
|
+
const alternative = alternatives[j];
|
|
76
|
+
alternative.statements.push(excerpt);
|
|
77
|
+
alternative.omitted--;
|
|
78
|
+
if (measure(digest) > budget) {
|
|
79
|
+
alternative.statements.pop();
|
|
80
|
+
alternative.omitted++;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
measure(digest);
|
|
84
|
+
return digest;
|
|
85
|
+
}
|
|
86
|
+
/** Register a native structured command so host TOON/JSON and error contracts remain authoritative. */
|
|
87
|
+
export function registerDecisionAlternativesCommand(api) {
|
|
88
|
+
api.registerCommand({
|
|
89
|
+
name: "brief alternatives",
|
|
90
|
+
description: "Compare recorded proposals and evidence with citations, without picking a winner",
|
|
91
|
+
flags: [{ long: "--token-budget", type: "string", value_name: "n", description: "Conservative TOON/JSON token ceiling including citations and omissions (default 4000, maximum 64000)" }],
|
|
92
|
+
async run(ctx) {
|
|
93
|
+
try {
|
|
94
|
+
return await buildDecisionAlternatives(ctx.args, { pmRoot: ctx.pm_root, client: ctx.sdk?.client, tokenBudget: ctx.options.tokenBudget === undefined ? undefined : Number(ctx.options.tokenBudget) });
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
const refusal = error instanceof DecisionAlternativesError ? error : new DecisionAlternativesError("tracker", "Alternative comparison could not complete", "Run pm health and check tracker permissions before retrying");
|
|
98
|
+
throw createPmCliExpectedError(`alternatives ${refusal.code}: ${refusal.message}. Remedy: ${refusal.remedy}`, { exitCode: 2, context: { code: `alternatives_${refusal.code}`, required: refusal.remedy } });
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=alternatives.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alternatives.js","sourceRoot":"","sources":["../alternatives.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { PmClient } from "@unbrained/pm-cli/sdk";
|
|
2
|
+
import type { ExtensionApi } from "@unbrained/pm-cli/sdk/authoring";
|
|
3
|
+
/** An explicit question or unresolved assumption with a stable response key. */
|
|
4
|
+
export interface HandoffPrompt {
|
|
5
|
+
id: string;
|
|
6
|
+
text: string;
|
|
7
|
+
}
|
|
8
|
+
/** Required native tracker linkage; presence proves linkage, never artifact contents or test success. */
|
|
9
|
+
export interface HandoffEvidence {
|
|
10
|
+
id: string;
|
|
11
|
+
item: string;
|
|
12
|
+
kind: "docs" | "files" | "tests";
|
|
13
|
+
ref: string;
|
|
14
|
+
}
|
|
15
|
+
/** Sender-authored obligations; every collection must be supplied, even when intentionally empty. */
|
|
16
|
+
export interface HandoffContract {
|
|
17
|
+
focus: string[];
|
|
18
|
+
questions: HandoffPrompt[];
|
|
19
|
+
assumptions: HandoffPrompt[];
|
|
20
|
+
requiredEvidence: HandoffEvidence[];
|
|
21
|
+
}
|
|
22
|
+
/** Content-addressed full item revision, including transitive declared blockers and missing targets. */
|
|
23
|
+
export interface HandoffRevision {
|
|
24
|
+
id: string;
|
|
25
|
+
revision: string | null;
|
|
26
|
+
title: string;
|
|
27
|
+
status: string;
|
|
28
|
+
blockers: string[];
|
|
29
|
+
}
|
|
30
|
+
/** Immutable stored contract; protocol and digest prevent accidental cross-packet acknowledgment. */
|
|
31
|
+
export interface HandoffDocument extends HandoffContract {
|
|
32
|
+
protocol: "pm-brief.handoff/v1";
|
|
33
|
+
sender: string;
|
|
34
|
+
createdAt: string;
|
|
35
|
+
items: HandoffRevision[];
|
|
36
|
+
}
|
|
37
|
+
/** Transport packet with live missing-evidence disclosure and a conservative byte-based token ceiling. */
|
|
38
|
+
export interface HandoffPacket {
|
|
39
|
+
id: string;
|
|
40
|
+
digest: string;
|
|
41
|
+
contract: HandoffDocument;
|
|
42
|
+
missingEvidence: string[];
|
|
43
|
+
estimatedTokenCeiling: number;
|
|
44
|
+
}
|
|
45
|
+
/** Receiver statements keyed by every question, assumption and evidence obligation. */
|
|
46
|
+
export interface HandoffResponse {
|
|
47
|
+
digest: string;
|
|
48
|
+
questions: Record<string, string>;
|
|
49
|
+
assumptions: Record<string, string>;
|
|
50
|
+
evidence: Record<string, string>;
|
|
51
|
+
}
|
|
52
|
+
/** Read-only or native mutation context; no filesystem or git backend assumptions. */
|
|
53
|
+
export interface HandoffOptions {
|
|
54
|
+
pmRoot: string;
|
|
55
|
+
author?: string;
|
|
56
|
+
client?: PmClient;
|
|
57
|
+
tokenBudget?: number;
|
|
58
|
+
}
|
|
59
|
+
/** Receipt validity is recomputed on each read; missing evidence cannot become a ready acknowledgment. */
|
|
60
|
+
export interface HandoffReceipt {
|
|
61
|
+
id: string;
|
|
62
|
+
receiver: string;
|
|
63
|
+
response: HandoffResponse;
|
|
64
|
+
acknowledgedAt: string;
|
|
65
|
+
valid: boolean;
|
|
66
|
+
ready: boolean;
|
|
67
|
+
staleItems: string[];
|
|
68
|
+
missingEvidence: string[];
|
|
69
|
+
}
|
|
70
|
+
/** Complete contract and selected receiver receipts, with no silent row omission. */
|
|
71
|
+
export interface HandoffStatus {
|
|
72
|
+
packet: HandoffPacket;
|
|
73
|
+
staleItems: string[];
|
|
74
|
+
receipts: HandoffReceipt[];
|
|
75
|
+
estimatedTokenCeiling: number;
|
|
76
|
+
}
|
|
77
|
+
/** Stable refusal categories callers can branch on without parsing prose. */
|
|
78
|
+
export type HandoffRefusalCode = "invalid" | "missing" | "identity" | "stale" | "responses" | "integrity" | "budget" | "tracker";
|
|
79
|
+
/** Expected failure with a concrete recovery action; tracker writes never precede validation. */
|
|
80
|
+
export declare class HandoffError extends Error {
|
|
81
|
+
/** Machine-readable reason for refusing an operation. */
|
|
82
|
+
readonly code: HandoffRefusalCode;
|
|
83
|
+
/** Action the caller can take before retrying. */
|
|
84
|
+
readonly remedy: string;
|
|
85
|
+
/** Preserve the typed category separately from human-readable context. */
|
|
86
|
+
constructor(code: HandoffRefusalCode, message: string, remedy: string);
|
|
87
|
+
}
|
|
88
|
+
/** Validate and normalize the SDK and CLI contract through the same runtime boundary. */
|
|
89
|
+
export declare function parseHandoffContract(value: unknown): HandoffContract;
|
|
90
|
+
/** Parse explicit receiver statements; digest binds them to exactly one packet. */
|
|
91
|
+
export declare function parseHandoffResponse(value: unknown): HandoffResponse;
|
|
92
|
+
/** Generate a bounded packet from a certified tracker read without creating records or invoking git. */
|
|
93
|
+
export declare function previewHandoff(input: HandoffContract, options: HandoffOptions): Promise<HandoffPacket>;
|
|
94
|
+
/** Create one native Decision artifact; no source item or claim is modified. */
|
|
95
|
+
export declare function createHandoff(input: HandoffContract, options: HandoffOptions): Promise<HandoffPacket>;
|
|
96
|
+
/** Read all receipts and recompute validity; receiver filters affect output only, never stored data. */
|
|
97
|
+
export declare function inspectHandoff(id: string, options: HandoffOptions, receiver?: string): Promise<HandoffStatus>;
|
|
98
|
+
/** Append an idempotent receiver receipt under the native comment lock; concurrent receivers never overwrite. */
|
|
99
|
+
export declare function acknowledgeHandoff(id: string, input: HandoffResponse, options: HandoffOptions): Promise<HandoffStatus>;
|
|
100
|
+
/** Register native structured TOON/JSON commands; expected refusals carry code and remedy at nonzero exit. */
|
|
101
|
+
export declare function registerHandoffCommands(api: ExtensionApi): void;
|
|
102
|
+
//# sourceMappingURL=handoff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handoff.d.ts","sourceRoot":"","sources":["../handoff.ts"],"names":[],"mappings":"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"}
|