@sentropic/focus 0.5.0-rc.3 → 0.5.0-rc.5
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/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +12 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/editing/anchors.d.ts +14 -0
- package/dist/editing/anchors.d.ts.map +1 -0
- package/dist/editing/anchors.js +113 -0
- package/dist/editing/anchors.js.map +1 -0
- package/dist/editing/codec.d.ts +24 -0
- package/dist/editing/codec.d.ts.map +1 -0
- package/dist/editing/codec.js +143 -0
- package/dist/editing/codec.js.map +1 -0
- package/dist/editing/contract.d.ts +129 -0
- package/dist/editing/contract.d.ts.map +1 -0
- package/dist/editing/contract.js +76 -0
- package/dist/editing/contract.js.map +1 -0
- package/dist/editing/diff.d.ts +12 -0
- package/dist/editing/diff.d.ts.map +1 -0
- package/dist/editing/diff.js +125 -0
- package/dist/editing/diff.js.map +1 -0
- package/dist/editing/digest.d.ts +6 -0
- package/dist/editing/digest.d.ts.map +1 -0
- package/dist/editing/digest.js +56 -0
- package/dist/editing/digest.js.map +1 -0
- package/dist/editing/index.d.ts +7 -0
- package/dist/editing/index.d.ts.map +1 -0
- package/dist/editing/index.js +7 -0
- package/dist/editing/index.js.map +1 -0
- package/dist/editing/reconcile.d.ts +66 -0
- package/dist/editing/reconcile.d.ts.map +1 -0
- package/dist/editing/reconcile.js +167 -0
- package/dist/editing/reconcile.js.map +1 -0
- package/dist/editing/structure.d.ts +24 -0
- package/dist/editing/structure.d.ts.map +1 -0
- package/dist/editing/structure.js +71 -0
- package/dist/editing/structure.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/model.d.ts +71 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +1 -1
- package/dist/model.js.map +1 -1
- package/dist/registry/definitions.d.ts +1 -1
- package/dist/registry/definitions.d.ts.map +1 -1
- package/dist/registry/definitions.js +40 -32
- package/dist/registry/definitions.js.map +1 -1
- package/dist/render/evidence.d.ts +10 -0
- package/dist/render/evidence.d.ts.map +1 -0
- package/dist/render/evidence.js +37 -0
- package/dist/render/evidence.js.map +1 -0
- package/dist/render/html.d.ts.map +1 -1
- package/dist/render/html.js +2 -0
- package/dist/render/html.js.map +1 -1
- package/dist/render/md.d.ts.map +1 -1
- package/dist/render/md.js +3 -0
- package/dist/render/md.js.map +1 -1
- package/dist/render/terminal.d.ts.map +1 -1
- package/dist/render/terminal.js +3 -0
- package/dist/render/terminal.js.map +1 -1
- package/dist/validation/evidence-bytes.d.ts +5 -0
- package/dist/validation/evidence-bytes.d.ts.map +1 -0
- package/dist/validation/evidence-bytes.js +57 -0
- package/dist/validation/evidence-bytes.js.map +1 -0
- package/dist/validation/evidence-shape.d.ts +12 -0
- package/dist/validation/evidence-shape.d.ts.map +1 -0
- package/dist/validation/evidence-shape.js +54 -0
- package/dist/validation/evidence-shape.js.map +1 -0
- package/dist/validation/evidence-sources.d.ts +7 -0
- package/dist/validation/evidence-sources.d.ts.map +1 -0
- package/dist/validation/evidence-sources.js +56 -0
- package/dist/validation/evidence-sources.js.map +1 -0
- package/dist/validation/evidence.d.ts +5 -0
- package/dist/validation/evidence.d.ts.map +1 -0
- package/dist/validation/evidence.js +131 -0
- package/dist/validation/evidence.js.map +1 -0
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +11 -1
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/readability.d.ts.map +1 -1
- package/dist/validation/readability.js +21 -0
- package/dist/validation/readability.js.map +1 -1
- package/package.json +14 -3
- package/registry/entries.v1.json +17 -4
- package/schemas/decision-dossier-document.v2.schema.json +925 -0
- package/schemas/focus-edit-return.v1.schema.json +950 -0
- package/schemas/focus-editing-manifest.v1.schema.json +167 -0
- package/skills/focus/SKILL.md +50 -1
package/dist/cli/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* — missing args, decision not found, contract mismatch). It is READ-ONLY: NO track write, NO new
|
|
13
13
|
* track event (those are L4).
|
|
14
14
|
*
|
|
15
|
-
* stp focus <decision-id> [--format terminal|md|html] [--workspace <ws>]
|
|
15
|
+
* stp focus <decision-id> [--format terminal|md|html|json] [--workspace <ws>]
|
|
16
16
|
* [--baseline-commit <sha>] [--events-path <path>]
|
|
17
17
|
*
|
|
18
18
|
* Defaults: `--events-path` = `.track/events.jsonl`, `--format` = `terminal`. `--workspace` is
|
package/dist/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAkBH,iFAAiF;AACjF,eAAO,MAAM,OAAO,EAAE,MAAoB,CAAC;AA2G3C;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,oDAAoD;IACpD,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,iDAAiD;IACjD,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAiBD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,GAAG,GACd,MAAM,SAAS,MAAM,EAAE,EACvB,OAAM,YAAiB,KACtB,OAAO,CAAC,MAAM,CA0DhB,CAAC"}
|
package/dist/cli/index.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* — missing args, decision not found, contract mismatch). It is READ-ONLY: NO track write, NO new
|
|
13
13
|
* track event (those are L4).
|
|
14
14
|
*
|
|
15
|
-
* stp focus <decision-id> [--format terminal|md|html] [--workspace <ws>]
|
|
15
|
+
* stp focus <decision-id> [--format terminal|md|html|json] [--workspace <ws>]
|
|
16
16
|
* [--baseline-commit <sha>] [--events-path <path>]
|
|
17
17
|
*
|
|
18
18
|
* Defaults: `--events-path` = `.track/events.jsonl`, `--format` = `terminal`. `--workspace` is
|
|
@@ -21,18 +21,19 @@
|
|
|
21
21
|
import { createRequire } from "node:module";
|
|
22
22
|
import { renderHtml, renderMd, renderTerminal } from "../index.js";
|
|
23
23
|
import { DecisionNotFoundError, TrackContractMismatchError, readDecisionDossier, } from "../track/index.js";
|
|
24
|
+
import { assertDecisionDossierForPresentation } from "../validation/index.js";
|
|
24
25
|
/** The package version, read from the package manifest (single source of truth). */
|
|
25
26
|
const pkg = createRequire(import.meta.url)("../../package.json");
|
|
26
27
|
/** The `{ run, version }` contract surfaced to the `stp` subcommand registry. */
|
|
27
28
|
export const version = pkg.version;
|
|
28
29
|
/** The supported render formats. */
|
|
29
|
-
const FORMATS = ["terminal", "md", "html"];
|
|
30
|
+
const FORMATS = ["terminal", "md", "html", "json"];
|
|
30
31
|
const DEFAULT_EVENTS_PATH = ".track/events.jsonl";
|
|
31
32
|
const DEFAULT_FORMAT = "terminal";
|
|
32
33
|
/** A parse failure carrying the message to print on stderr (exit code 2 = usage error). */
|
|
33
34
|
class UsageError extends Error {
|
|
34
35
|
}
|
|
35
|
-
const USAGE = "Usage: stp focus <decision-id> [--format terminal|md|html] " +
|
|
36
|
+
const USAGE = "Usage: stp focus <decision-id> [--format terminal|md|html|json] " +
|
|
36
37
|
"[--workspace <ws>] [--baseline-commit <sha>] [--events-path <path>]\n" +
|
|
37
38
|
"Render a track decision dossier read-only. Defaults: --format terminal, " +
|
|
38
39
|
`--events-path ${DEFAULT_EVENTS_PATH}. --workspace is required.`;
|
|
@@ -162,6 +163,14 @@ export const run = async (argv, deps = {}) => {
|
|
|
162
163
|
case "html":
|
|
163
164
|
out(renderHtml(doc, defaultHtmlHooks));
|
|
164
165
|
break;
|
|
166
|
+
case "json": {
|
|
167
|
+
// No renderer: validate through the SAME presentation gate (readability included) and
|
|
168
|
+
// serialize the validated document verbatim — v1 today, v2 the day a dossier carries
|
|
169
|
+
// embedded evidence (assertDecisionDossierForPresentation is the v1|v2 union validator).
|
|
170
|
+
const validated = assertDecisionDossierForPresentation(doc);
|
|
171
|
+
out(`${JSON.stringify(validated, null, 2)}\n`);
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
165
174
|
}
|
|
166
175
|
return 0;
|
|
167
176
|
}
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEnE,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DecisionDossierDocument } from '../model.js';
|
|
2
|
+
import type { Address, EditingField, FocusEditingManifest, Paragraph, ParagraphValue, Validation } from './contract.js';
|
|
3
|
+
export declare const fieldKey: (a: Address) => string;
|
|
4
|
+
export declare function sourceNodes(doc: DecisionDossierDocument): Record<string, any>[];
|
|
5
|
+
export declare function sourceNode(doc: DecisionDossierDocument, address: Address): Record<string, any>;
|
|
6
|
+
export declare function editableFields(doc: DecisionDossierDocument): EditingField[];
|
|
7
|
+
export declare function sealManifest(value: Omit<FocusEditingManifest, 'manifestBaseHash'>): FocusEditingManifest;
|
|
8
|
+
/** Legacy seed only. A revised source MUST carry an explicit mapping instead of reseeding. */
|
|
9
|
+
export declare function seedManifest(doc: DecisionDossierDocument): FocusEditingManifest;
|
|
10
|
+
export declare function validateManifest(value: unknown, doc: DecisionDossierDocument): Validation<FocusEditingManifest>;
|
|
11
|
+
/** Explicit producer correspondence, including retirements. Never matches by text similarity. */
|
|
12
|
+
export declare function carryManifest(doc: DecisionDossierDocument, previous: FocusEditingManifest, paragraphs: Paragraph[]): FocusEditingManifest;
|
|
13
|
+
export declare function readParagraphs(doc: DecisionDossierDocument, manifest: FocusEditingManifest): ParagraphValue[];
|
|
14
|
+
//# sourceMappingURL=anchors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anchors.d.ts","sourceRoot":"","sources":["../../src/editing/anchors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAKxH,eAAO,MAAM,QAAQ,GAAI,GAAG,OAAO,KAAG,MAAyD,CAAC;AAQhG,wBAAgB,WAAW,CAAC,GAAG,EAAE,uBAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAE/E;AACD,wBAAgB,UAAU,CAAC,GAAG,EAAE,uBAAuB,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAG9F;AACD,wBAAgB,cAAc,CAAC,GAAG,EAAE,uBAAuB,GAAG,YAAY,EAAE,CAK3E;AACD,wBAAgB,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,oBAAoB,EAAE,kBAAkB,CAAC,GAAG,oBAAoB,CAExG;AACD,8FAA8F;AAC9F,wBAAgB,YAAY,CAAC,GAAG,EAAE,uBAAuB,GAAG,oBAAoB,CAU/E;AACD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,uBAAuB,GAAG,UAAU,CAAC,oBAAoB,CAAC,CA2C/G;AACD,iGAAiG;AACjG,wBAAgB,aAAa,CAAC,GAAG,EAAE,uBAAuB,EAAE,QAAQ,EAAE,oBAAoB,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,oBAAoB,CAKzI;AACD,wBAAgB,cAAc,CAAC,GAAG,EAAE,uBAAuB,EAAE,QAAQ,EAAE,oBAAoB,GAAG,cAAc,EAAE,CAM7G"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { baseDigest, canonicalJson, manifestDigest } from './digest.js';
|
|
2
|
+
import { manifestSchema, matchesSchema } from './structure.js';
|
|
3
|
+
import { isRepresentablePlainText, segmentMarkdown, segmentText } from './codec.js';
|
|
4
|
+
export const fieldKey = (a) => canonicalJson([a.nodeId, a.targetRef, a.field]);
|
|
5
|
+
/** Exactly one soft line break (LF, CRLF or CR): the only allowed overhang
|
|
6
|
+
* of a text/plain paragraph range beyond its source block. */
|
|
7
|
+
const singleLineBreak = /^(?:\r\n|\n|\r)$/;
|
|
8
|
+
/** An emptied narrative field keeps one empty unit: `""` is content (D14), so an
|
|
9
|
+
* empty source still carries its paragraph identity instead of zero units. */
|
|
10
|
+
const textSegments = (source) => source === '' ? [{ start: 0, end: 0, editable: true }] : segmentText(source);
|
|
11
|
+
export function sourceNodes(doc) {
|
|
12
|
+
return doc.sections.flatMap(s => s.kind === 'optionSet' ? [s, ...s.options] : [s]);
|
|
13
|
+
}
|
|
14
|
+
export function sourceNode(doc, address) {
|
|
15
|
+
const found = sourceNodes(doc).filter(n => n.id === address.nodeId && n.targetRef === address.targetRef);
|
|
16
|
+
if (found.length !== 1)
|
|
17
|
+
throw new Error('missing-or-ambiguous-node');
|
|
18
|
+
return found[0];
|
|
19
|
+
}
|
|
20
|
+
export function editableFields(doc) {
|
|
21
|
+
const allowed = { prose: ['markdown'], question: ['question', 'recommendedAnswer', 'context'], option: ['label', 'body', 'consequence'] };
|
|
22
|
+
return sourceNodes(doc).flatMap(n => (allowed[n.kind] ?? []).filter(field => typeof n[field] === 'string').map(field => ({
|
|
23
|
+
nodeId: n.id, targetRef: n.targetRef, field: field, contentFormat: field === 'markdown' ? 'focus.markdown.p0@1' : 'text/plain', blockKind: n.kind,
|
|
24
|
+
})));
|
|
25
|
+
}
|
|
26
|
+
export function sealManifest(value) {
|
|
27
|
+
return { ...value, manifestBaseHash: manifestDigest(value) };
|
|
28
|
+
}
|
|
29
|
+
/** Legacy seed only. A revised source MUST carry an explicit mapping instead of reseeding. */
|
|
30
|
+
export function seedManifest(doc) {
|
|
31
|
+
const baseHash = baseDigest(doc), fields = editableFields(doc);
|
|
32
|
+
const paragraphs = fields.flatMap(f => {
|
|
33
|
+
const source = sourceNode(doc, f)[f.field];
|
|
34
|
+
const segments = f.contentFormat === 'text/plain' ? textSegments(source) : segmentMarkdown(source);
|
|
35
|
+
return segments.filter(s => s.editable).map((s, order) => ({ nodeId: f.nodeId, targetRef: f.targetRef, field: f.field,
|
|
36
|
+
paragraphId: `paragraph:${baseDigest([baseHash, fieldKey(f), order]).slice(7)}`, blockKind: 'paragraph', parentId: null, order,
|
|
37
|
+
range: { start: s.start, end: s.end, unit: 'utf16' } }));
|
|
38
|
+
});
|
|
39
|
+
return sealManifest({ schemaVersion: 1, manifestId: `manifest:${baseHash.slice(7)}`, documentRef: doc.ref, baseHash, fields, paragraphs, retiredParagraphIds: [] });
|
|
40
|
+
}
|
|
41
|
+
export function validateManifest(value, doc) {
|
|
42
|
+
if (!matchesSchema(manifestSchema, value))
|
|
43
|
+
return { ok: false, issues: ['manifest-structure'] };
|
|
44
|
+
const m = value, issues = [];
|
|
45
|
+
try {
|
|
46
|
+
if (m.documentRef !== doc.ref || m.baseHash !== baseDigest(doc) || m.manifestBaseHash !== manifestDigest(m))
|
|
47
|
+
issues.push('manifest-digest-or-base');
|
|
48
|
+
const allowed = editableFields(doc), fieldIds = new Set(), ids = new Set();
|
|
49
|
+
for (const f of m.fields) {
|
|
50
|
+
const key = fieldKey(f);
|
|
51
|
+
if (fieldIds.has(key) || !allowed.some(a => canonicalJson(a) === canonicalJson(f)))
|
|
52
|
+
issues.push('unsupported-or-duplicate-field');
|
|
53
|
+
fieldIds.add(key);
|
|
54
|
+
const source = sourceNode(doc, f)[f.field];
|
|
55
|
+
const ps = m.paragraphs.filter(p => fieldKey(p) === key).sort((a, b) => a.order - b.order);
|
|
56
|
+
const segments = f.contentFormat === 'text/plain' ? textSegments(source) : segmentMarkdown(source);
|
|
57
|
+
let end = 0;
|
|
58
|
+
ps.forEach((p, index) => {
|
|
59
|
+
if (p.order !== index || p.range.start < end || p.range.end < p.range.start || p.range.end > source.length)
|
|
60
|
+
issues.push('ambiguous-range');
|
|
61
|
+
// An empty text/plain paragraph holds no characters, so it never matches a
|
|
62
|
+
// text block: it is a zero-length unit owned by a structural gap (D14).
|
|
63
|
+
// It is representable outside any block (source edge, block boundary or
|
|
64
|
+
// blank gap), never strictly inside one.
|
|
65
|
+
const emptyGapUnit = f.contentFormat === 'text/plain' && p.range.start === p.range.end &&
|
|
66
|
+
!segments.some(s => s.start < p.range.start && p.range.start < s.end);
|
|
67
|
+
// Case 3: a text/plain paragraph may keep at most one soft break at
|
|
68
|
+
// each edge ("A\n", "\nB"). Its range then extends one break beyond
|
|
69
|
+
// its block; the sliced text still round-trips via stored ranges.
|
|
70
|
+
// The extension must stay anchored on a whole source block: an
|
|
71
|
+
// internal fragment that merely round-trips (e.g. "B" of "ABC")
|
|
72
|
+
// is never a paragraph.
|
|
73
|
+
const edgeBreakUnit = f.contentFormat === 'text/plain' && p.range.start < p.range.end &&
|
|
74
|
+
isRepresentablePlainText(source.slice(p.range.start, p.range.end)) &&
|
|
75
|
+
segments.some(s => s.editable && p.range.start <= s.start && p.range.end >= s.end &&
|
|
76
|
+
(p.range.start === s.start || singleLineBreak.test(source.slice(p.range.start, s.start))) &&
|
|
77
|
+
(p.range.end === s.end || singleLineBreak.test(source.slice(s.end, p.range.end))));
|
|
78
|
+
if (!segments.some(s => s.editable && s.start === p.range.start && s.end === p.range.end) && !emptyGapUnit && !edgeBreakUnit && !(p.range.start === p.range.end && f.contentFormat !== 'text/plain'))
|
|
79
|
+
issues.push('unsupported-range');
|
|
80
|
+
end = p.range.end;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
for (const p of m.paragraphs) {
|
|
84
|
+
if (ids.has(p.paragraphId) || m.retiredParagraphIds.includes(p.paragraphId) || !fieldIds.has(fieldKey(p)))
|
|
85
|
+
issues.push('ambiguous-paragraph');
|
|
86
|
+
ids.add(p.paragraphId);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
issues.push('invalid-manifest');
|
|
91
|
+
}
|
|
92
|
+
return issues.length ? { ok: false, issues } : { ok: true, value: m };
|
|
93
|
+
}
|
|
94
|
+
/** Explicit producer correspondence, including retirements. Never matches by text similarity. */
|
|
95
|
+
export function carryManifest(doc, previous, paragraphs) {
|
|
96
|
+
const active = new Set(paragraphs.map(p => p.paragraphId));
|
|
97
|
+
const m = sealManifest({ schemaVersion: 1, manifestId: previous.manifestId, documentRef: doc.ref, baseHash: baseDigest(doc), fields: editableFields(doc),
|
|
98
|
+
paragraphs: structuredClone(paragraphs), retiredParagraphIds: [...new Set([...previous.retiredParagraphIds, ...previous.paragraphs.filter(p => !active.has(p.paragraphId)).map(p => p.paragraphId)])] });
|
|
99
|
+
const result = validateManifest(m, doc);
|
|
100
|
+
if (!result.ok)
|
|
101
|
+
throw new Error(result.issues.join(', '));
|
|
102
|
+
return m;
|
|
103
|
+
}
|
|
104
|
+
export function readParagraphs(doc, manifest) {
|
|
105
|
+
const check = validateManifest(manifest, doc);
|
|
106
|
+
if (!check.ok)
|
|
107
|
+
throw new Error(check.issues.join(', '));
|
|
108
|
+
return manifest.fields.flatMap(f => manifest.paragraphs.filter(p => fieldKey(p) === fieldKey(f)).sort((a, b) => a.order - b.order).map(p => ({
|
|
109
|
+
documentRef: doc.ref, nodeId: p.nodeId, targetRef: p.targetRef, field: p.field, paragraphId: p.paragraphId, blockKind: 'paragraph',
|
|
110
|
+
format: f.contentFormat, text: sourceNode(doc, p)[p.field].slice(p.range.start, p.range.end),
|
|
111
|
+
})));
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=anchors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anchors.js","sourceRoot":"","sources":["../../src/editing/anchors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { FocusReturn } from './contract.js';
|
|
2
|
+
export interface SourceSegment {
|
|
3
|
+
start: number;
|
|
4
|
+
end: number;
|
|
5
|
+
text: string;
|
|
6
|
+
editable: boolean;
|
|
7
|
+
}
|
|
8
|
+
/** Source-preserving CommonMark + GFM tables. No Markdown reserialization. */
|
|
9
|
+
export declare function segmentMarkdown(source: string): SourceSegment[];
|
|
10
|
+
/** Plain narrative fields: one unit per block of non-blank lines. Exact source
|
|
11
|
+
* offsets, CRLF/CR aware, no trimming and no normalization: blank lines stay
|
|
12
|
+
* structural gaps owned by the manifest, never paragraph content. */
|
|
13
|
+
export declare function segmentText(source: string): SourceSegment[];
|
|
14
|
+
/** A text/plain paragraph is one block of non-blank lines (segmentText) with
|
|
15
|
+
* at most one soft line break kept at each edge (case 3: "A\n", "\nB",
|
|
16
|
+
* "\nA\n", CRLF/CR included). Blank lines stay structural gaps owned by the
|
|
17
|
+
* manifest, never paragraph content: stripping more than one edge break still
|
|
18
|
+
* leaves an edge break behind, so "A\n\n" or "\n\nB" keep failing. A lone
|
|
19
|
+
* single break ("\n", "\r\n", "\r") is representable as its own unit. */
|
|
20
|
+
export declare function isRepresentablePlainText(text: string): boolean;
|
|
21
|
+
export declare function assertParagraphText(text: string, format: string): void;
|
|
22
|
+
export declare function encodeReturn(value: FocusReturn, format?: 'json' | 'yaml'): string;
|
|
23
|
+
export declare function decodeReturn(raw: string, format?: 'json' | 'yaml'): FocusReturn;
|
|
24
|
+
//# sourceMappingURL=codec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../../src/editing/codec.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,WAAW,aAAa;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE;AAG9F,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE,CAoB/D;AACD;;qEAEqE;AACrE,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE,CAsB3D;AAKD;;;;;yEAKyE;AACzE,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAW9D;AACD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAQtE;AACD,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,GAAE,MAAM,GAAG,MAAe,GAAG,MAAM,CAIzF;AACD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,GAAG,MAAe,GAAG,WAAW,CAevF"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { parser, GFM } from '@lezer/markdown';
|
|
2
|
+
import { parseDocument, isAlias, isMap, isSeq, isScalar, stringify } from 'yaml';
|
|
3
|
+
import { canonicalJson } from './digest.js';
|
|
4
|
+
import { validateReturnStructure } from './contract.js';
|
|
5
|
+
const sourceParser = parser.configure(GFM);
|
|
6
|
+
/** Source-preserving CommonMark + GFM tables. No Markdown reserialization. */
|
|
7
|
+
export function segmentMarkdown(source) {
|
|
8
|
+
// Lezer consumes LF. Preserve an exact offset map into the original CRLF/CR source.
|
|
9
|
+
const chars = [], offsets = [0];
|
|
10
|
+
for (let i = 0; i < source.length; i++) {
|
|
11
|
+
if (source[i] === '\r') {
|
|
12
|
+
chars.push('\n');
|
|
13
|
+
if (source[i + 1] === '\n')
|
|
14
|
+
i++;
|
|
15
|
+
}
|
|
16
|
+
else
|
|
17
|
+
chars.push(source[i]);
|
|
18
|
+
offsets.push(i + 1);
|
|
19
|
+
}
|
|
20
|
+
const tree = sourceParser.parse(chars.join(''));
|
|
21
|
+
const safe = (node) => {
|
|
22
|
+
if (!['Paragraph', 'Emphasis', 'StrongEmphasis', 'InlineCode', 'HardBreak', 'CodeMark', 'EmphasisMark', 'Escape', 'Entity'].includes(node.name))
|
|
23
|
+
return false;
|
|
24
|
+
for (let child = node.firstChild; child; child = child.nextSibling)
|
|
25
|
+
if (!safe(child))
|
|
26
|
+
return false;
|
|
27
|
+
return true;
|
|
28
|
+
};
|
|
29
|
+
const segments = [];
|
|
30
|
+
for (let node = tree.topNode.firstChild; node; node = node.nextSibling) {
|
|
31
|
+
const start = offsets[node.from], end = offsets[node.to];
|
|
32
|
+
segments.push({ start, end, text: source.slice(start, end), editable: node.name === 'Paragraph' && safe(node) });
|
|
33
|
+
}
|
|
34
|
+
return segments;
|
|
35
|
+
}
|
|
36
|
+
/** Plain narrative fields: one unit per block of non-blank lines. Exact source
|
|
37
|
+
* offsets, CRLF/CR aware, no trimming and no normalization: blank lines stay
|
|
38
|
+
* structural gaps owned by the manifest, never paragraph content. */
|
|
39
|
+
export function segmentText(source) {
|
|
40
|
+
if (source === '')
|
|
41
|
+
return [];
|
|
42
|
+
const parts = source.split(/(\r\n|\n|\r)/);
|
|
43
|
+
const lines = [];
|
|
44
|
+
let offset = 0;
|
|
45
|
+
for (let i = 0; i < parts.length; i += 2) {
|
|
46
|
+
const text = parts[i];
|
|
47
|
+
lines.push({ start: offset, end: offset + text.length, text });
|
|
48
|
+
offset += text.length + (parts[i + 1] ?? '').length;
|
|
49
|
+
}
|
|
50
|
+
const segments = [];
|
|
51
|
+
let open = null;
|
|
52
|
+
const close = (last) => {
|
|
53
|
+
segments.push({ start: lines[open].start, end: lines[last].end, text: source.slice(lines[open].start, lines[last].end), editable: true });
|
|
54
|
+
open = null;
|
|
55
|
+
};
|
|
56
|
+
lines.forEach((line, index) => {
|
|
57
|
+
if (/^[ \t]*$/.test(line.text)) {
|
|
58
|
+
if (open !== null)
|
|
59
|
+
close(index - 1);
|
|
60
|
+
}
|
|
61
|
+
else if (open === null)
|
|
62
|
+
open = index;
|
|
63
|
+
});
|
|
64
|
+
if (open !== null)
|
|
65
|
+
close(lines.length - 1);
|
|
66
|
+
return segments;
|
|
67
|
+
}
|
|
68
|
+
const lineBreak = String.raw `(?:\r\n|\n|\r)`;
|
|
69
|
+
const singleBreak = new RegExp(`^${lineBreak}$`);
|
|
70
|
+
const leadingBreak = new RegExp(`^${lineBreak}`);
|
|
71
|
+
const trailingBreak = new RegExp(`${lineBreak}$`);
|
|
72
|
+
/** A text/plain paragraph is one block of non-blank lines (segmentText) with
|
|
73
|
+
* at most one soft line break kept at each edge (case 3: "A\n", "\nB",
|
|
74
|
+
* "\nA\n", CRLF/CR included). Blank lines stay structural gaps owned by the
|
|
75
|
+
* manifest, never paragraph content: stripping more than one edge break still
|
|
76
|
+
* leaves an edge break behind, so "A\n\n" or "\n\nB" keep failing. A lone
|
|
77
|
+
* single break ("\n", "\r\n", "\r") is representable as its own unit. */
|
|
78
|
+
export function isRepresentablePlainText(text) {
|
|
79
|
+
if (text === '')
|
|
80
|
+
return true;
|
|
81
|
+
if (singleBreak.test(text))
|
|
82
|
+
return true;
|
|
83
|
+
let core = text;
|
|
84
|
+
const lead = core.match(leadingBreak);
|
|
85
|
+
if (lead)
|
|
86
|
+
core = core.slice(lead[0].length);
|
|
87
|
+
const trail = core.match(trailingBreak);
|
|
88
|
+
if (trail)
|
|
89
|
+
core = core.slice(0, -trail[0].length);
|
|
90
|
+
if (core === '')
|
|
91
|
+
return false;
|
|
92
|
+
const parts = segmentText(core);
|
|
93
|
+
return parts.length === 1 && parts[0].start === 0 && parts[0].end === core.length;
|
|
94
|
+
}
|
|
95
|
+
export function assertParagraphText(text, format) {
|
|
96
|
+
if (text === '')
|
|
97
|
+
return;
|
|
98
|
+
if (format === 'text/plain') {
|
|
99
|
+
if (isRepresentablePlainText(text))
|
|
100
|
+
return;
|
|
101
|
+
throw new Error('unsupported-paragraph-format');
|
|
102
|
+
}
|
|
103
|
+
const parts = segmentMarkdown(text);
|
|
104
|
+
if (parts.length !== 1 || !parts[0].editable || parts[0].start !== 0 || parts[0].end !== text.length)
|
|
105
|
+
throw new Error('unsupported-paragraph-format');
|
|
106
|
+
}
|
|
107
|
+
export function encodeReturn(value, format = 'json') {
|
|
108
|
+
if (!validateReturnStructure(value))
|
|
109
|
+
throw new Error('unsupported-version-or-structure');
|
|
110
|
+
canonicalJson(value);
|
|
111
|
+
return format === 'json' ? JSON.stringify(value, null, 2) + '\n' : stringify(value, { lineWidth: 0, aliasDuplicateObjects: false });
|
|
112
|
+
}
|
|
113
|
+
export function decodeReturn(raw, format = 'json') {
|
|
114
|
+
if (format !== 'json' && format !== 'yaml')
|
|
115
|
+
throw new Error('unsupported-format');
|
|
116
|
+
if (format === 'json')
|
|
117
|
+
JSON.parse(raw); // Strict JSON syntax; YAML below also checks duplicate keys.
|
|
118
|
+
const parsed = parseDocument(raw, { uniqueKeys: true, strict: true, schema: 'core' });
|
|
119
|
+
if (parsed.errors.length || parsed.warnings.length)
|
|
120
|
+
throw new Error('Invalid serialized return');
|
|
121
|
+
const visit = (node) => {
|
|
122
|
+
if (!node)
|
|
123
|
+
return;
|
|
124
|
+
if (isAlias(node) || node.tag)
|
|
125
|
+
throw new Error('Aliases and explicit tags are unsupported');
|
|
126
|
+
if (isMap(node))
|
|
127
|
+
for (const pair of node.items) {
|
|
128
|
+
if (!isScalar(pair.key) || typeof pair.key.value !== 'string')
|
|
129
|
+
throw new Error('JSON keys must be strings');
|
|
130
|
+
visit(pair.key);
|
|
131
|
+
visit(pair.value);
|
|
132
|
+
}
|
|
133
|
+
if (isSeq(node))
|
|
134
|
+
node.items.forEach(visit);
|
|
135
|
+
};
|
|
136
|
+
visit(parsed.contents);
|
|
137
|
+
const value = parsed.toJS({ maxAliasCount: 0 });
|
|
138
|
+
canonicalJson(value);
|
|
139
|
+
if (!validateReturnStructure(value))
|
|
140
|
+
throw new Error('unsupported-version-or-structure');
|
|
141
|
+
return value;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.js","sourceRoot":"","sources":["../../src/editing/codec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { DecisionDossierDocument } from '../model.js';
|
|
2
|
+
export type Format = 'text/plain' | 'focus.markdown.p0@1';
|
|
3
|
+
export interface Address {
|
|
4
|
+
nodeId: string;
|
|
5
|
+
targetRef: string;
|
|
6
|
+
field: 'markdown' | 'question' | 'recommendedAnswer' | 'context' | 'label' | 'body' | 'consequence';
|
|
7
|
+
}
|
|
8
|
+
export interface EditingField extends Address {
|
|
9
|
+
contentFormat: Format;
|
|
10
|
+
blockKind: 'prose' | 'question' | 'option';
|
|
11
|
+
}
|
|
12
|
+
export interface Paragraph extends Address {
|
|
13
|
+
paragraphId: string;
|
|
14
|
+
blockKind: 'paragraph';
|
|
15
|
+
parentId: null;
|
|
16
|
+
order: number;
|
|
17
|
+
range: {
|
|
18
|
+
start: number;
|
|
19
|
+
end: number;
|
|
20
|
+
unit: 'utf16';
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export interface FocusEditingManifest {
|
|
24
|
+
schemaVersion: 1;
|
|
25
|
+
manifestId: string;
|
|
26
|
+
documentRef: string;
|
|
27
|
+
baseHash: string;
|
|
28
|
+
manifestBaseHash: string;
|
|
29
|
+
fields: EditingField[];
|
|
30
|
+
paragraphs: Paragraph[];
|
|
31
|
+
retiredParagraphIds: string[];
|
|
32
|
+
}
|
|
33
|
+
export interface Anchors {
|
|
34
|
+
parentId: null;
|
|
35
|
+
previousParagraphId: string | null;
|
|
36
|
+
nextParagraphId: string | null;
|
|
37
|
+
}
|
|
38
|
+
export interface ParagraphValue extends Address {
|
|
39
|
+
documentRef: string;
|
|
40
|
+
paragraphId: string;
|
|
41
|
+
blockKind: 'paragraph';
|
|
42
|
+
format: Format;
|
|
43
|
+
text: string;
|
|
44
|
+
}
|
|
45
|
+
export interface ParagraphChange extends Address {
|
|
46
|
+
documentRef: string;
|
|
47
|
+
paragraphId: string;
|
|
48
|
+
blockKind: 'paragraph';
|
|
49
|
+
format: Format;
|
|
50
|
+
changeId: string;
|
|
51
|
+
operation: 'replace' | 'insert' | 'delete' | 'move';
|
|
52
|
+
before: string | null;
|
|
53
|
+
after: string | null;
|
|
54
|
+
beforeAnchors: Anchors | null;
|
|
55
|
+
anchors: Anchors;
|
|
56
|
+
}
|
|
57
|
+
export interface EditTransaction {
|
|
58
|
+
transactionId: string;
|
|
59
|
+
changes: ParagraphChange[];
|
|
60
|
+
}
|
|
61
|
+
export interface Production {
|
|
62
|
+
producerId: string;
|
|
63
|
+
generationId: string;
|
|
64
|
+
requestId: string;
|
|
65
|
+
}
|
|
66
|
+
export interface FocusReturn {
|
|
67
|
+
kind: 'focus.return';
|
|
68
|
+
schemaVersion: 1;
|
|
69
|
+
returnId: string;
|
|
70
|
+
digest: string;
|
|
71
|
+
capture: {
|
|
72
|
+
at: string;
|
|
73
|
+
};
|
|
74
|
+
scope: {
|
|
75
|
+
workspaceId: string;
|
|
76
|
+
} | null;
|
|
77
|
+
source: {
|
|
78
|
+
documentRef: string;
|
|
79
|
+
hash: string;
|
|
80
|
+
cursor: string;
|
|
81
|
+
baseHash: string;
|
|
82
|
+
manifestId: string;
|
|
83
|
+
manifestBaseHash: string;
|
|
84
|
+
};
|
|
85
|
+
production: Production | null;
|
|
86
|
+
manifest: FocusEditingManifest;
|
|
87
|
+
answers: {
|
|
88
|
+
questionId: string;
|
|
89
|
+
targetRef: string;
|
|
90
|
+
optionIds: string[];
|
|
91
|
+
text: string | null;
|
|
92
|
+
}[];
|
|
93
|
+
notes: {
|
|
94
|
+
targetRef: string;
|
|
95
|
+
text: string | null;
|
|
96
|
+
}[];
|
|
97
|
+
editReturn: {
|
|
98
|
+
schemaVersion: 1;
|
|
99
|
+
mode: 'cumulative';
|
|
100
|
+
transactions: EditTransaction[];
|
|
101
|
+
supersedesReturnId?: string;
|
|
102
|
+
supersededReturnIds: string[];
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export type Validation<T> = {
|
|
106
|
+
ok: true;
|
|
107
|
+
value: T;
|
|
108
|
+
} | {
|
|
109
|
+
ok: false;
|
|
110
|
+
issues: string[];
|
|
111
|
+
};
|
|
112
|
+
export declare const validateManifestStructure: (v: unknown) => v is FocusEditingManifest;
|
|
113
|
+
export declare const validateReturnStructure: (v: unknown) => v is FocusReturn;
|
|
114
|
+
export declare function validateReturn(value: unknown, doc: DecisionDossierDocument, manifest: FocusEditingManifest): Validation<FocusReturn>;
|
|
115
|
+
export interface FreezeInput {
|
|
116
|
+
document: DecisionDossierDocument;
|
|
117
|
+
manifest: FocusEditingManifest;
|
|
118
|
+
production: Production | null;
|
|
119
|
+
scope: FocusReturn['scope'];
|
|
120
|
+
answers: FocusReturn['answers'];
|
|
121
|
+
notes: FocusReturn['notes'];
|
|
122
|
+
transactions: EditTransaction[];
|
|
123
|
+
previous?: FocusReturn;
|
|
124
|
+
returnId: string;
|
|
125
|
+
capturedAt: string;
|
|
126
|
+
}
|
|
127
|
+
/** Capture metadata/identity is supplied by the host, never invented by the pure core. */
|
|
128
|
+
export declare function freezeReturn(input: FreezeInput): FocusReturn;
|
|
129
|
+
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/editing/contract.ts"],"names":[],"mappings":"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"}
|