@sentropic/focus 0.3.0 → 0.5.0-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +9 -0
  2. package/dist/cli/index.d.ts.map +1 -1
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/model.d.ts +73 -1
  7. package/dist/model.d.ts.map +1 -1
  8. package/dist/registry/definitions.d.ts +159 -0
  9. package/dist/registry/definitions.d.ts.map +1 -0
  10. package/dist/registry/definitions.js +501 -0
  11. package/dist/registry/definitions.js.map +1 -0
  12. package/dist/render/html.d.ts.map +1 -1
  13. package/dist/render/html.js +12 -1
  14. package/dist/render/html.js.map +1 -1
  15. package/dist/render/md.d.ts.map +1 -1
  16. package/dist/render/md.js +12 -1
  17. package/dist/render/md.js.map +1 -1
  18. package/dist/render/presentation.d.ts +4 -0
  19. package/dist/render/presentation.d.ts.map +1 -0
  20. package/dist/render/presentation.js +25 -0
  21. package/dist/render/presentation.js.map +1 -0
  22. package/dist/render/terminal.d.ts.map +1 -1
  23. package/dist/render/terminal.js +12 -1
  24. package/dist/render/terminal.js.map +1 -1
  25. package/dist/track/index.d.ts.map +1 -1
  26. package/dist/track/index.js +24 -10
  27. package/dist/track/index.js.map +1 -1
  28. package/dist/validation/index.d.ts +59 -0
  29. package/dist/validation/index.d.ts.map +1 -0
  30. package/dist/validation/index.js +490 -0
  31. package/dist/validation/index.js.map +1 -0
  32. package/dist/validation/readability.d.ts +28 -0
  33. package/dist/validation/readability.d.ts.map +1 -0
  34. package/dist/validation/readability.js +244 -0
  35. package/dist/validation/readability.js.map +1 -0
  36. package/package.json +25 -8
  37. package/registry/entries.v1.json +127 -0
  38. package/schemas/decision-dossier-document.v1.schema.json +193 -0
  39. package/skills/focus/SKILL.md +132 -0
@@ -0,0 +1,193 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "urn:sentropic:focus:DecisionDossierDocument:1.0.0",
4
+ "title": "DecisionDossierDocument",
5
+ "description": "Read-only decision-dossier snapshot published by @sentropic/focus. Closed: unknown fields refuse. Snapshot interactions are disabled metadata (enabled:false); live decisions, signatures and amendments require separately qualified runtime capabilities.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["ref", "subject", "title", "hash", "cursor", "sections", "interactions", "provenance", "amendmentTrace"],
9
+ "properties": {
10
+ "ref": { "type": "string" },
11
+ "subject": { "type": "string" },
12
+ "title": { "type": "string" },
13
+ "hash": { "type": "string" },
14
+ "cursor": { "type": "string" },
15
+ "sections": { "type": "array", "items": { "$ref": "#/$defs/section" } },
16
+ "interactions": { "type": "array", "items": { "$ref": "#/$defs/interaction" } },
17
+ "provenance": { "$ref": "#/$defs/provenance" },
18
+ "amendmentTrace": { "type": "array", "items": { "$ref": "#/$defs/amendmentStep" } },
19
+ "readability": { "$ref": "#/$defs/readability" }
20
+ },
21
+ "$defs": {
22
+ "readability": {
23
+ "type": "object",
24
+ "additionalProperties": false,
25
+ "properties": {
26
+ "ownerRequestQuote": { "type": "string" },
27
+ "noOwnerRequest": { "type": "boolean" },
28
+ "stakes": { "type": "string" },
29
+ "stakesLevel": { "enum": ["low", "medium", "high"] },
30
+ "readingBudgetMinutes": { "type": "number" },
31
+ "glossary": { "type": "array", "items": { "$ref": "#/$defs/glossaryEntry" } }
32
+ }
33
+ },
34
+ "glossaryEntry": {
35
+ "type": "object",
36
+ "additionalProperties": false,
37
+ "required": ["term", "definition"],
38
+ "properties": {
39
+ "term": { "type": "string" },
40
+ "definition": { "type": "string" }
41
+ }
42
+ },
43
+ "section": {
44
+ "oneOf": [
45
+ { "$ref": "#/$defs/proseNode" },
46
+ { "$ref": "#/$defs/questionNode" },
47
+ { "$ref": "#/$defs/optionSetNode" },
48
+ { "$ref": "#/$defs/outcomeNode" },
49
+ { "$ref": "#/$defs/amendmentTraceNode" },
50
+ { "$ref": "#/$defs/diagramNode" }
51
+ ]
52
+ },
53
+ "proseNode": {
54
+ "type": "object",
55
+ "additionalProperties": false,
56
+ "required": ["kind", "id", "targetRef", "markdown"],
57
+ "properties": {
58
+ "kind": { "const": "prose" },
59
+ "id": { "type": "string" },
60
+ "targetRef": { "type": "string" },
61
+ "markdown": { "type": "string" },
62
+ "questionId": { "type": "string" }
63
+ }
64
+ },
65
+ "questionNode": {
66
+ "type": "object",
67
+ "additionalProperties": false,
68
+ "required": ["kind", "id", "targetRef", "question", "state"],
69
+ "properties": {
70
+ "kind": { "const": "question" },
71
+ "id": { "type": "string" },
72
+ "targetRef": { "type": "string" },
73
+ "question": { "type": "string" },
74
+ "recommendedAnswer": { "type": "string" },
75
+ "answer": { "type": "string" },
76
+ "state": { "enum": ["open", "answered", "validated"] },
77
+ "context": { "type": "string" },
78
+ "readingTimeMinutes": { "type": "number" },
79
+ "recommendedOptionId": { "type": "string" }
80
+ }
81
+ },
82
+ "optionNode": {
83
+ "type": "object",
84
+ "additionalProperties": false,
85
+ "required": ["kind", "id", "targetRef", "label", "annotation"],
86
+ "properties": {
87
+ "kind": { "const": "option" },
88
+ "id": { "type": "string" },
89
+ "targetRef": { "type": "string" },
90
+ "label": { "type": "string" },
91
+ "body": { "type": "string" },
92
+ "annotation": { "enum": ["none", "accept", "reject", "comment"] },
93
+ "annotationComment": { "type": "string" },
94
+ "consequence": { "type": "string" }
95
+ }
96
+ },
97
+ "optionSetNode": {
98
+ "type": "object",
99
+ "additionalProperties": false,
100
+ "required": ["kind", "id", "targetRef", "options"],
101
+ "properties": {
102
+ "kind": { "const": "optionSet" },
103
+ "id": { "type": "string" },
104
+ "targetRef": { "type": "string" },
105
+ "title": { "type": "string" },
106
+ "options": { "type": "array", "items": { "$ref": "#/$defs/optionNode" } },
107
+ "questionId": { "type": "string" }
108
+ }
109
+ },
110
+ "outcomeNode": {
111
+ "type": "object",
112
+ "additionalProperties": false,
113
+ "required": ["kind", "id", "targetRef", "modality", "statement"],
114
+ "properties": {
115
+ "kind": { "const": "outcome" },
116
+ "id": { "type": "string" },
117
+ "targetRef": { "type": "string" },
118
+ "modality": { "enum": ["decision", "orientation", "amendment", "comment"] },
119
+ "statement": { "type": "string" },
120
+ "questionId": { "type": "string" }
121
+ }
122
+ },
123
+ "amendmentTraceNode": {
124
+ "type": "object",
125
+ "additionalProperties": false,
126
+ "required": ["kind", "id", "targetRef", "steps"],
127
+ "properties": {
128
+ "kind": { "const": "amendmentTrace" },
129
+ "id": { "type": "string" },
130
+ "targetRef": { "type": "string" },
131
+ "steps": { "type": "array", "items": { "$ref": "#/$defs/amendmentStep" } }
132
+ }
133
+ },
134
+ "diagramNode": {
135
+ "type": "object",
136
+ "additionalProperties": false,
137
+ "required": ["kind", "id", "targetRef", "syntax", "source", "alt"],
138
+ "properties": {
139
+ "kind": { "const": "diagram" },
140
+ "id": { "type": "string" },
141
+ "targetRef": { "type": "string" },
142
+ "syntax": { "enum": ["mermaid", "plantuml"] },
143
+ "source": { "type": "string" },
144
+ "alt": { "type": "string" },
145
+ "scene": {
146
+ "type": "object",
147
+ "description": "diagram-core SemanticDocument, profile generic@1, without views, geometry or layout hints. Opaque JSON until the design-system publishes its authoritative schema; no Focus-specific scene model."
148
+ }
149
+ }
150
+ },
151
+ "interaction": {
152
+ "type": "object",
153
+ "additionalProperties": false,
154
+ "required": ["name", "targetRef", "label", "enabled"],
155
+ "properties": {
156
+ "name": { "type": "string" },
157
+ "targetRef": { "type": "string" },
158
+ "label": { "type": "string" },
159
+ "enabled": { "const": false }
160
+ }
161
+ },
162
+ "comprehensionEvidence": {
163
+ "type": "object",
164
+ "additionalProperties": false,
165
+ "required": ["subject", "dossierHash"],
166
+ "properties": {
167
+ "subject": { "type": "string" },
168
+ "dossierHash": { "type": "string" },
169
+ "signature": { "type": "string" }
170
+ }
171
+ },
172
+ "provenance": {
173
+ "type": "object",
174
+ "additionalProperties": false,
175
+ "required": ["source", "readAt"],
176
+ "properties": {
177
+ "source": { "type": "string" },
178
+ "readAt": { "type": "string" },
179
+ "comprehensionEvidence": { "$ref": "#/$defs/comprehensionEvidence" }
180
+ }
181
+ },
182
+ "amendmentStep": {
183
+ "type": "object",
184
+ "additionalProperties": false,
185
+ "required": ["at", "author", "summary"],
186
+ "properties": {
187
+ "at": { "type": "string" },
188
+ "author": { "type": "string" },
189
+ "summary": { "type": "string" }
190
+ }
191
+ }
192
+ }
193
+ }
@@ -0,0 +1,132 @@
1
+ ---
2
+ name: focus
3
+ version: 1.0.0
4
+ description: Prepare and review readable decision dossiers that trace the owner's request, expose real stakes and offer short explicit choices. Read-only snapshots; no decisions, signatures, amendments or Track writes.
5
+ category: decision
6
+ tools: []
7
+ ---
8
+
9
+ # Focus — help the owner make a real decision
10
+
11
+ Method capability: `sentropic.focus.decision-dossier`. Prepare a
12
+ `DecisionDossierDocument` using schema
13
+ `urn:sentropic:focus:DecisionDossierDocument:1.0.0`
14
+ (`schemas/decision-dossier-document.v1.schema.json`). This instruction-only
15
+ skill grants no tools or write authority.
16
+
17
+ A dossier serves the owner's intention. Ask the owner to choose a path or
18
+ manage a real problem whose risk concerns them. Handle routine technical
19
+ implementation within existing authority. Double review must find missing
20
+ context, hidden commitments and risks; it must also cut jargon and unnecessary
21
+ questions. It is not a reason to produce a longer dossier.
22
+
23
+ ## Prepare a dossier the owner can read on its own
24
+
25
+ - Write `title` and `subject` as non-empty single lines of at most 100
26
+ characters. Name the concrete subject and what the owner must decide:
27
+ “Garden shed — choose its location”, not “Ratify the plan”. Review their
28
+ meaning against the request; the gate checks length and form, not meaning.
29
+ - Quote the owner's literal request in `readability.ownerRequestQuote`.
30
+ Preserve their words and trace how the questions serve them. Never invent
31
+ a quotation. If no request exists, set `noOwnerRequest: true`; this blocks
32
+ presentation until the request is established. Do not combine it with a quote.
33
+ - State the scope and why it matters to the owner in `readability.stakes`:
34
+ cost, disruption, consequences, reversibility. Declare `stakesLevel`: `low`
35
+ for a small reversible inconvenience, `medium` for meaningful cost or
36
+ disruption, `high` for lasting, contractual or major personal impact.
37
+ - Set `readingBudgetMinutes` proportionately: at most 2 / 8 / 30 minutes for
38
+ low / medium / high stakes, including shared context and glossary. These
39
+ caps are defaults, not permission to inflate the stakes or fill the budget.
40
+ - Each question needs representative `context`, 2–4 short options, a
41
+ `recommendedOptionId`, and a short reason in `recommendedAnswer`. Context
42
+ must explain the situation, scope and trade-off without making the reader
43
+ chase another document or decode an identifier.
44
+ Keep questions and recommendations to one line of at most 300 characters,
45
+ option-set titles to 100. No nested lists or inline a/b branches.
46
+ - Each option needs a one-line `consequence` for the owner. Labels are at most
47
+ 100 characters, consequences 160, optional bodies/comments 300. Keep them
48
+ flat: no nested lists, inline a/b branches or multiple decisions in one
49
+ option. Move essential explanation to question context.
50
+ - Estimate `readingTimeMinutes` for each question, context and options together:
51
+ positive and at most 2 minutes. The gate checks a 180-word/minute lower bound.
52
+ Allow time to understand the trade-off, not just pronounce the words. Shorten
53
+ or split long questions; never understate the time to pass the gate.
54
+ - Every option set names its `questionId`; every decision, orientation or
55
+ amendment outcome names the question it resolves. Choice-bearing prose also
56
+ names its question. Audit *every* implied commitment, including defaults,
57
+ rollout, spending and permissions. Split independent commitments into explicit
58
+ questions. A reference alone does not prove that the question covers the text.
59
+ - Prefer plain words to codes such as `L06b`, `MH-L3`, `R5` or build identifiers,
60
+ and to unexplained acronyms. If necessary, define each term in
61
+ `readability.glossary` with a meaning the owner understands. The renderers show
62
+ this glossary. Each definition must stand alone in plain words, with no
63
+ self-reference or other code, even one defined elsewhere in the glossary.
64
+
65
+ Bad: “Ratify L06b under MH-L3? A: migrate, with a/b variants. B: defer.”
66
+ The request, stakes, consequences and recommendation are missing; several
67
+ choices are hidden behind codes.
68
+
69
+ Good (about one minute):
70
+ > Your request: “Keep the garden shed handy without spoiling the terrace view.”
71
+ > Stakes: the wrong spot means a longer walk every week or a blocked view for years.
72
+ > Question: where should the shed go? The permit covers both spots; only comfort differs.
73
+ > Side wall: a short walk and a clear terrace view.
74
+ > Back of garden: a longer walk, invisible from the house.
75
+ > Recommendation: side wall, because it meets both parts of your request.
76
+
77
+ Encode the good example as one question, two linked options, the recommended
78
+ option's id and reason, the literal quote and stakes, a declared stakes level,
79
+ and reading estimates. Let the renderer arrange the supplied questions/options;
80
+ never hand-author four parallel walls of text or imply that snapshot cards are
81
+ clickable.
82
+
83
+ ## Validate before presentation
84
+
85
+ Use `validateDecisionDossierForPresentation` (or its throwing counterpart
86
+ `assertDecisionDossierForPresentation`) from `@sentropic/focus/validate`.
87
+ The three public renderers enforce this gate before invoking host hooks.
88
+ Refusals carry a field path, code and an actionable explanation. Correct the
89
+ content and present the complete dossier; do not silently omit refused material.
90
+
91
+ New fields stay optional in schema version 1 so historical data still parses
92
+ through `validateDecisionDossierDocument`. Structural validity is insufficient
93
+ for presentation. Legacy Track projections lacking readability information are
94
+ blocked; never synthesize an owner request to make them pass. New Track dossiers
95
+ carry `subject`, `readability`, `questionId` for shared context/outcome, and
96
+ question context, reading time and recommendation on `qa`. Each option summary
97
+ is its consequence; `options[].questionId` overrides the shared question link
98
+ when a dossier contains several questions.
99
+
100
+ The gate checks structure, code definitions, reading lengths and explicit links.
101
+ It cannot prove a quotation is authentic, prose is clear, stakes are honest,
102
+ or every semantic choice has been exposed. Author and reviewer must verify
103
+ those properties against the request. Review should reduce the owner's reading
104
+ burden while preserving the real stakes and every relevant choice.
105
+
106
+ ## Host parameters and presentation availability
107
+
108
+ Closed parameters: `mode: "snapshot"`; `preferredPresentation` is `terminal`,
109
+ `markdown`, `html` or `mcp-app`; `locale` is `en` or `fr`. Defaults:
110
+ `snapshot` / `markdown` / `en`. Unknown keys refuse. Parameters choose presentation
111
+ and instruction selection; they do not change content or authority.
112
+
113
+ Terminal and Markdown are always available. HTML requires the host sanitization
114
+ hook. `mcp-app` requires registered, selected **and qualified** `sentropic.h2a.ui`.
115
+ Otherwise refuse with `unsupported_presentation` before reading any instruction;
116
+ never silently change the requested presentation.
117
+
118
+ ## Snapshot and provenance boundaries
119
+
120
+ `interactions[].enabled` is always `false`; never act on an affordance or present
121
+ it as available. Live decisions, signatures, amendments and Track writes require
122
+ separately qualified capabilities and current human authority.
123
+
124
+ Carry `provenance.comprehensionEvidence` (subject, dossier hash, signature)
125
+ verbatim. Never regenerate it or substitute a relay principal for the named
126
+ subject. `provenance.source` is an opaque read-backend binding; never infer
127
+ authority or invent filesystem paths from it.
128
+
129
+ Markdown conversion and HTML sanitization are explicit host hooks. Unsupported
130
+ nodes, unknown fields, enabled interactions, duplicate ids, unresolved targets
131
+ and forged evidence refuse with field diagnostics; never render an incomplete
132
+ dossier as complete.