@davidorex/pi-context 0.30.0 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/CHANGELOG.md +127 -0
  2. package/README.md +27 -11
  3. package/dist/block-api.d.ts +13 -0
  4. package/dist/block-api.d.ts.map +1 -1
  5. package/dist/block-api.js +28 -3
  6. package/dist/block-api.js.map +1 -1
  7. package/dist/content-hash.d.ts +13 -0
  8. package/dist/content-hash.d.ts.map +1 -1
  9. package/dist/content-hash.js +16 -0
  10. package/dist/content-hash.js.map +1 -1
  11. package/dist/context-dir.d.ts +12 -0
  12. package/dist/context-dir.d.ts.map +1 -1
  13. package/dist/context-dir.js +14 -0
  14. package/dist/context-dir.js.map +1 -1
  15. package/dist/context-sdk.d.ts +71 -33
  16. package/dist/context-sdk.d.ts.map +1 -1
  17. package/dist/context-sdk.js +547 -149
  18. package/dist/context-sdk.js.map +1 -1
  19. package/dist/context.d.ts +213 -2
  20. package/dist/context.d.ts.map +1 -1
  21. package/dist/context.js +119 -5
  22. package/dist/context.js.map +1 -1
  23. package/dist/index.d.ts +595 -9
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +2225 -55
  26. package/dist/index.js.map +1 -1
  27. package/dist/lens-view.d.ts +0 -5
  28. package/dist/lens-view.d.ts.map +1 -1
  29. package/dist/lens-view.js +43 -1
  30. package/dist/lens-view.js.map +1 -1
  31. package/dist/migration-registry-loader.d.ts +36 -12
  32. package/dist/migration-registry-loader.d.ts.map +1 -1
  33. package/dist/migration-registry-loader.js +79 -17
  34. package/dist/migration-registry-loader.js.map +1 -1
  35. package/dist/migrations-store.d.ts +45 -18
  36. package/dist/migrations-store.d.ts.map +1 -1
  37. package/dist/migrations-store.js +56 -22
  38. package/dist/migrations-store.js.map +1 -1
  39. package/dist/ops-registry.d.ts +16 -0
  40. package/dist/ops-registry.d.ts.map +1 -1
  41. package/dist/ops-registry.js +352 -117
  42. package/dist/ops-registry.js.map +1 -1
  43. package/dist/pending-blocked-store.d.ts +83 -0
  44. package/dist/pending-blocked-store.d.ts.map +1 -0
  45. package/dist/pending-blocked-store.js +93 -0
  46. package/dist/pending-blocked-store.js.map +1 -0
  47. package/dist/promote-item.d.ts.map +1 -1
  48. package/dist/promote-item.js +41 -12
  49. package/dist/promote-item.js.map +1 -1
  50. package/dist/roadmap-plan.d.ts +121 -99
  51. package/dist/roadmap-plan.d.ts.map +1 -1
  52. package/dist/roadmap-plan.js +281 -345
  53. package/dist/roadmap-plan.js.map +1 -1
  54. package/dist/schema-merge.d.ts +26 -0
  55. package/dist/schema-merge.d.ts.map +1 -0
  56. package/dist/schema-merge.js +176 -0
  57. package/dist/schema-merge.js.map +1 -0
  58. package/dist/status-vocab.d.ts +12 -2
  59. package/dist/status-vocab.d.ts.map +1 -1
  60. package/dist/status-vocab.js +14 -1
  61. package/dist/status-vocab.js.map +1 -1
  62. package/package.json +2 -1
  63. package/samples/blocks/milestone.json +3 -0
  64. package/samples/blocks/session-notes.json +1 -0
  65. package/samples/conception.json +358 -15
  66. package/samples/migrations.json +8 -0
  67. package/samples/schemas/context-contracts.schema.json +4 -0
  68. package/samples/schemas/conventions.schema.json +4 -0
  69. package/samples/schemas/decisions.schema.json +4 -0
  70. package/samples/schemas/features.schema.json +4 -0
  71. package/samples/schemas/framework-gaps.schema.json +5 -1
  72. package/samples/schemas/issues.schema.json +30 -2
  73. package/samples/schemas/layer-plans.schema.json +6 -2
  74. package/samples/schemas/milestone.schema.json +79 -0
  75. package/samples/schemas/phase.schema.json +4 -0
  76. package/samples/schemas/rationale.schema.json +4 -0
  77. package/samples/schemas/requirements.schema.json +4 -0
  78. package/samples/schemas/research.schema.json +5 -1
  79. package/samples/schemas/session-notes.schema.json +89 -0
  80. package/samples/schemas/spec-reviews.schema.json +4 -0
  81. package/samples/schemas/story.schema.json +8 -0
  82. package/samples/schemas/tasks.schema.json +4 -0
  83. package/samples/schemas/verification.schema.json +4 -0
  84. package/samples/schemas/work-orders.schema.json +6 -2
  85. package/schemas/config.schema.json +101 -3
  86. package/schemas/migrations.schema.json +25 -0
  87. package/schemas/pending-blocked.schema.json +190 -0
  88. package/skill-narrative.md +14 -10
  89. package/skills/pi-context/SKILL.md +127 -49
  90. package/skills/pi-context/references/bundled-resources.md +7 -2
@@ -3,12 +3,16 @@
3
3
  "$id": "pi-context://schemas/layer-plans",
4
4
  "version": "1.0.1",
5
5
  "title": "Layer Restructure Plans",
6
- "description": "Plans for restructuring the .project/ directory from flat-block storage into a layered artifact-ownership model. Each plan names its conceptual source (e.g. Muni five-layer), describes each layer's purpose and its current-vs-target block mapping, and sequences the enactment into phases with exit criteria. Layer plans are themselves L2 specification-layer artifacts — they are spec-level decisions about how the framework organizes project state.",
6
+ "description": "Plans for restructuring substrate storage into a layered artifact-ownership model. Each plan names its conceptual source (e.g. a layered architecture model), describes each layer's purpose and its current-vs-target block mapping, and sequences the enactment into phases with exit criteria. Layer plans are themselves L2 specification-layer artifacts — they are spec-level decisions about how the framework organizes project state.",
7
7
  "type": "object",
8
8
  "required": [
9
9
  "plans"
10
10
  ],
11
11
  "properties": {
12
+ "schema_version": {
13
+ "type": "string",
14
+ "description": "Semver of the block schema this envelope was last written against. Stamped by the write path to the schema's current version; when it differs from the installed schema's version, the read/write gates walk the block through the registered migration chain (or fail loud when no chain reaches the current version). Absent on blocks not yet written by a stamping write path."
15
+ },
12
16
  "plans": {
13
17
  "type": "array",
14
18
  "items": {
@@ -45,7 +49,7 @@
45
49
  },
46
50
  "model": {
47
51
  "type": "string",
48
- "description": "Conceptual source — e.g. 'Muni five-layer'"
52
+ "description": "Conceptual source — e.g. 'a layered architecture model'"
49
53
  },
50
54
  "description": {
51
55
  "type": "string",
@@ -0,0 +1,79 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "pi-context://schemas/milestone",
4
+ "version": "1.0.0",
5
+ "title": "Milestones",
6
+ "description": "Array-block of project milestones. A milestone is a pure phase-rollup checkpoint with no work of its own: its `status` (planned | reached) is DERIVED, never authored — a milestone is `reached` iff at least one phase is positioned in it (a phase_positioned_in_milestone edge) and the parent phase of every such edge buckets to complete, else `planned`. Phase membership lives in relations.json phase_positioned_in_milestone edges (phase -> milestone), not inline. `release` is an optional grouping string pending the normalized release entity.",
7
+ "type": "object",
8
+ "required": [
9
+ "milestones"
10
+ ],
11
+ "additionalProperties": false,
12
+ "properties": {
13
+ "schema_version": {
14
+ "type": "string",
15
+ "description": "Semver of the block schema this envelope was last written against. Stamped by the write path to the schema's current version; when it differs from the installed schema's version, the read/write gates walk the block through the registered migration chain (or fail loud when no chain reaches the current version). Absent on blocks not yet written by a stamping write path."
16
+ },
17
+ "milestones": {
18
+ "type": "array",
19
+ "items": {
20
+ "type": "object",
21
+ "additionalProperties": false,
22
+ "required": [
23
+ "id",
24
+ "name",
25
+ "status"
26
+ ],
27
+ "properties": {
28
+ "id": {
29
+ "type": "string",
30
+ "pattern": "^MILE-\\d{3,}$",
31
+ "description": "Stable canonical id; MILE-NNN (3+ digits), mirroring the STORY-/TASK-NNN convention."
32
+ },
33
+ "name": {
34
+ "type": "string"
35
+ },
36
+ "status": {
37
+ "type": "string",
38
+ "enum": [
39
+ "planned",
40
+ "reached"
41
+ ],
42
+ "description": "DERIVED phase-rollup, not authored: `reached` iff >=1 phase_positioned_in_milestone edge (in which the phase is the parent and the milestone the child) and the parent phase of every such edge buckets to complete; else `planned`. A milestone carries no work of its own; authored status is rejected by canon (substrate-derived-state)."
43
+ },
44
+ "release": {
45
+ "type": "string",
46
+ "description": "Optional release grouping label. Interim flat string pending the normalized release entity, which will subsume / edge this field."
47
+ },
48
+ "created_by": {
49
+ "type": "string"
50
+ },
51
+ "created_at": {
52
+ "type": "string"
53
+ },
54
+ "modified_by": {
55
+ "type": "string"
56
+ },
57
+ "modified_at": {
58
+ "type": "string"
59
+ },
60
+ "oid": {
61
+ "type": "string",
62
+ "pattern": "^[0-9a-f]{32}$",
63
+ "description": "Content-independent substrate-stable item identity (content-addressed substrate identity, Cycle 3). Minted once at item birth via mintOid(substrate_id); immutable across content versions. Optional in the schema so pre-Cycle-3 items validate; stamped on next write."
64
+ },
65
+ "content_hash": {
66
+ "type": "string",
67
+ "pattern": "^[0-9a-f]{64}$",
68
+ "description": "SHA-256 (hex) of the RFC-8785-canonical content projection of this item (metadata fields excluded). Recomputed on every stamping write; moves with content, stable across metadata-only churn."
69
+ },
70
+ "content_parent": {
71
+ "type": "string",
72
+ "pattern": "^[0-9a-f]{64}$",
73
+ "description": "content_hash of the immediately-prior version of this item; set on a content-changing update, absent on the first (v1) version. Forms the per-item content version chain."
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+ }
@@ -10,6 +10,10 @@
10
10
  ],
11
11
  "additionalProperties": false,
12
12
  "properties": {
13
+ "schema_version": {
14
+ "type": "string",
15
+ "description": "Semver of the block schema this envelope was last written against. Stamped by the write path to the schema's current version; when it differs from the installed schema's version, the read/write gates walk the block through the registered migration chain (or fail loud when no chain reaches the current version). Absent on blocks not yet written by a stamping write path."
16
+ },
13
17
  "phases": {
14
18
  "type": "array",
15
19
  "items": {
@@ -9,6 +9,10 @@
9
9
  "rationales"
10
10
  ],
11
11
  "properties": {
12
+ "schema_version": {
13
+ "type": "string",
14
+ "description": "Semver of the block schema this envelope was last written against. Stamped by the write path to the schema's current version; when it differs from the installed schema's version, the read/write gates walk the block through the registered migration chain (or fail loud when no chain reaches the current version). Absent on blocks not yet written by a stamping write path."
15
+ },
12
16
  "rationales": {
13
17
  "type": "array",
14
18
  "items": {
@@ -9,6 +9,10 @@
9
9
  "requirements"
10
10
  ],
11
11
  "properties": {
12
+ "schema_version": {
13
+ "type": "string",
14
+ "description": "Semver of the block schema this envelope was last written against. Stamped by the write path to the schema's current version; when it differs from the installed schema's version, the read/write gates walk the block through the registered migration chain (or fail loud when no chain reaches the current version). Absent on blocks not yet written by a stamping write path."
15
+ },
12
16
  "requirements": {
13
17
  "type": "array",
14
18
  "items": {
@@ -9,6 +9,10 @@
9
9
  "research"
10
10
  ],
11
11
  "properties": {
12
+ "schema_version": {
13
+ "type": "string",
14
+ "description": "Semver of the block schema this envelope was last written against. Stamped by the write path to the schema's current version; when it differs from the installed schema's version, the read/write gates walk the block through the registered migration chain (or fail loud when no chain reaches the current version). Absent on blocks not yet written by a stamping write path."
15
+ },
12
16
  "research": {
13
17
  "type": "array",
14
18
  "items": {
@@ -55,7 +59,7 @@
55
59
  "L4",
56
60
  "L5"
57
61
  ],
58
- "description": "Which Muni layer the research informs. L1 identity/domain; L2 specification; L3 work; L4 execution; L5 memory."
62
+ "description": "Which architecture layer the research informs. L1 identity/domain; L2 specification; L3 work; L4 execution; L5 memory."
59
63
  },
60
64
  "type": {
61
65
  "type": "string",
@@ -0,0 +1,89 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "pi-context://schemas/session-notes",
4
+ "version": "1.0.0",
5
+ "title": "Session Notes",
6
+ "description": "Per-session handoff records: focus, discoveries, questions, decisions made, current status, and next steps captured at session end for cross-session continuity.",
7
+ "type": "object",
8
+ "required": [
9
+ "schema_version",
10
+ "sessions"
11
+ ],
12
+ "additionalProperties": false,
13
+ "properties": {
14
+ "schema_version": {
15
+ "type": "string"
16
+ },
17
+ "sessions": {
18
+ "type": "array",
19
+ "items": {
20
+ "type": "object",
21
+ "required": [
22
+ "id",
23
+ "timestamp",
24
+ "focus",
25
+ "current_status",
26
+ "next_steps"
27
+ ],
28
+ "additionalProperties": false,
29
+ "properties": {
30
+ "id": {
31
+ "type": "string",
32
+ "pattern": "^SESSION-\\d{3}$"
33
+ },
34
+ "timestamp": {
35
+ "type": "string",
36
+ "description": "ISO-8601 with local offset"
37
+ },
38
+ "focus": {
39
+ "type": "string",
40
+ "description": "1-2 sentence summary of what the session covered"
41
+ },
42
+ "discoveries": {
43
+ "type": "array",
44
+ "items": {
45
+ "type": "string"
46
+ }
47
+ },
48
+ "questions": {
49
+ "type": "array",
50
+ "items": {
51
+ "type": "string"
52
+ }
53
+ },
54
+ "decisions_made": {
55
+ "type": "array",
56
+ "items": {
57
+ "type": "string"
58
+ }
59
+ },
60
+ "current_status": {
61
+ "type": "string",
62
+ "description": "Prose summary of where the project stands at session end"
63
+ },
64
+ "next_steps": {
65
+ "type": "array",
66
+ "items": {
67
+ "type": "string"
68
+ }
69
+ },
70
+ "oid": {
71
+ "type": "string",
72
+ "pattern": "^[0-9a-f]{32}$",
73
+ "description": "Content-independent substrate-stable item identity (content-addressed substrate identity, Cycle 3). Minted once at item birth via mintOid(substrate_id); immutable across content versions. Optional in the schema so pre-Cycle-3 items validate; stamped on next write."
74
+ },
75
+ "content_hash": {
76
+ "type": "string",
77
+ "pattern": "^[0-9a-f]{64}$",
78
+ "description": "SHA-256 (hex) of the RFC-8785-canonical content projection of this item (metadata fields excluded). Recomputed on every stamping write; moves with content, stable across metadata-only churn."
79
+ },
80
+ "content_parent": {
81
+ "type": "string",
82
+ "pattern": "^[0-9a-f]{64}$",
83
+ "description": "content_hash of the immediately-prior version of this item; set on a content-changing update, absent on the first (v1) version. Forms the per-item content version chain."
84
+ }
85
+ }
86
+ }
87
+ }
88
+ }
89
+ }
@@ -9,6 +9,10 @@
9
9
  "reviews"
10
10
  ],
11
11
  "properties": {
12
+ "schema_version": {
13
+ "type": "string",
14
+ "description": "Semver of the block schema this envelope was last written against. Stamped by the write path to the schema's current version; when it differs from the installed schema's version, the read/write gates walk the block through the registered migration chain (or fail loud when no chain reaches the current version). Absent on blocks not yet written by a stamping write path."
15
+ },
12
16
  "reviews": {
13
17
  "type": "array",
14
18
  "items": {
@@ -10,6 +10,10 @@
10
10
  ],
11
11
  "additionalProperties": false,
12
12
  "properties": {
13
+ "schema_version": {
14
+ "type": "string",
15
+ "description": "Semver of the block schema this envelope was last written against. Stamped by the write path to the schema's current version; when it differs from the installed schema's version, the read/write gates walk the block through the registered migration chain (or fail loud when no chain reaches the current version). Absent on blocks not yet written by a stamping write path."
16
+ },
13
17
  "stories": {
14
18
  "type": "array",
15
19
  "items": {
@@ -29,6 +33,10 @@
29
33
  "title": {
30
34
  "type": "string"
31
35
  },
36
+ "user_kind": {
37
+ "type": "string",
38
+ "description": "Which user the story speaks for (e.g. cli-user, operator, agent) — the 'As a <user_kind>' subject of the story statement."
39
+ },
32
40
  "status": {
33
41
  "type": "string",
34
42
  "enum": [
@@ -9,6 +9,10 @@
9
9
  "tasks"
10
10
  ],
11
11
  "properties": {
12
+ "schema_version": {
13
+ "type": "string",
14
+ "description": "Semver of the block schema this envelope was last written against. Stamped by the write path to the schema's current version; when it differs from the installed schema's version, the read/write gates walk the block through the registered migration chain (or fail loud when no chain reaches the current version). Absent on blocks not yet written by a stamping write path."
15
+ },
12
16
  "tasks": {
13
17
  "type": "array",
14
18
  "items": {
@@ -9,6 +9,10 @@
9
9
  "verifications"
10
10
  ],
11
11
  "properties": {
12
+ "schema_version": {
13
+ "type": "string",
14
+ "description": "Semver of the block schema this envelope was last written against. Stamped by the write path to the schema's current version; when it differs from the installed schema's version, the read/write gates walk the block through the registered migration chain (or fail loud when no chain reaches the current version). Absent on blocks not yet written by a stamping write path."
15
+ },
12
16
  "verifications": {
13
17
  "type": "array",
14
18
  "items": {
@@ -3,13 +3,17 @@
3
3
  "$id": "pi-context://schemas/work-orders",
4
4
  "version": "1.0.1",
5
5
  "title": "Work Orders",
6
- "description": "Orchestrator-authored work-order spec for the privileged JIT-agent that drives the in-pi bounded code-change loop. A work-order names the target agent, the typed input/output contracts, the substrate-block context handoff, the bounded scope within which the agent may operate, and the deterministic real-check criteria gating acceptance (deterministic verification; never LLM self-report — verdict comes from real checks the agent cannot fake). Substrate-block handoff to the consuming agent uses the ContextBlockRef shape: each context_blocks entry is either a string for whole-block injection, or an object { name, item?, depth?, focus? } for item-specific injection. To handoff a single work-order item to the consuming agent, the agent's .agent.yaml contextBlocks declares { name: \"work-orders\", item: \"WO-NNN\" }; the compiler injects the resolved item under template key _work_orders_item (with companion _work_orders_raw / _work_orders_depth / _work_orders_focus). Authorship: orchestrator is sole spec author; capability-widening edits are writer.kind=human.",
6
+ "description": "Orchestrator-authored work-order spec for the privileged JIT-agent that drives the bounded code-change loop. A work-order names the target agent, the typed input/output contracts, the substrate-block context handoff, the bounded scope within which the agent may operate, and the deterministic real-check criteria gating acceptance (deterministic verification; never LLM self-report — verdict comes from real checks the agent cannot fake). Substrate-block handoff to the consuming agent uses the ContextBlockRef shape: each context_blocks entry is either a string for whole-block injection, or an object { name, item?, depth?, focus? } for item-specific injection. To handoff a single work-order item to the consuming agent, the agent's .agent.yaml contextBlocks declares { name: \"work-orders\", item: \"WO-NNN\" }; the compiler injects the resolved item under template key _work_orders_item (with companion _work_orders_raw / _work_orders_depth / _work_orders_focus). Authorship: orchestrator is sole spec author; capability-widening edits are writer.kind=human.",
7
7
  "type": "object",
8
8
  "required": [
9
9
  "work_orders"
10
10
  ],
11
11
  "additionalProperties": false,
12
12
  "properties": {
13
+ "schema_version": {
14
+ "type": "string",
15
+ "description": "Semver of the block schema this envelope was last written against. Stamped by the write path to the schema's current version; when it differs from the installed schema's version, the read/write gates walk the block through the registered migration chain (or fail loud when no chain reaches the current version). Absent on blocks not yet written by a stamping write path."
16
+ },
13
17
  "work_orders": {
14
18
  "type": "array",
15
19
  "items": {
@@ -57,7 +61,7 @@
57
61
  },
58
62
  "context_blocks": {
59
63
  "type": "array",
60
- "description": "Substrate-block references the privileged agent's .agent.yaml will consume via contextBlocks. Each entry: string for whole-block injection (_<name>), OR object { name, item?, depth?, focus? } for item-specific injection (per the existing ContextBlockRef shape in packages/pi-jit-agents/src/types.ts).",
64
+ "description": "Substrate-block references the privileged agent's .agent.yaml will consume via contextBlocks. Each entry: string for whole-block injection (_<name>), OR object { name, item?, depth?, focus? } for item-specific injection (per the ContextBlockRef shape defined by your agent layer).",
61
65
  "items": {
62
66
  "oneOf": [
63
67
  {
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "pi-context://schemas/config",
4
- "version": "1.5.0",
4
+ "version": "1.8.0",
5
5
  "title": "pi-context substrate config",
6
- "description": "Self-bootstrapping config block. Validates the config that configures the substrate. ConfigBlock is the canonical registry for block kinds, status buckets, relation types, display strings, layers, naming aliases, hierarchy declarations, and lens specs.",
6
+ "description": "Self-bootstrapping config block. Validates the config that configures the substrate. ConfigBlock is the canonical registry for block kinds, status buckets, relation types, display strings, layers, naming aliases, hierarchy declarations, lens specs, and the state-derivation registry that drives currentState (focus / in-flight / next-actions / blocked / milestone-rollup).",
7
7
  "type": "object",
8
8
  "required": ["schema_version", "block_kinds"],
9
9
  "additionalProperties": false,
@@ -67,6 +67,79 @@
67
67
  "enum": ["complete", "in_progress", "blocked", "todo", "unknown"]
68
68
  }
69
69
  },
70
+ "state_derivation": {
71
+ "type": "object",
72
+ "description": "Config-declared derivation registry for currentState — the kind/relation/rank/status/head-size couplings that previously lived as hardcoded literals in the deriver. A substrate without it reports 'state-derivation not configured'.",
73
+ "additionalProperties": false,
74
+ "properties": {
75
+ "in_flight": {
76
+ "type": "object",
77
+ "description": "Which block kinds at which status bucket count as in-flight (drives inFlight + focus). Stock: kinds ['tasks'], bucket 'in_progress'.",
78
+ "additionalProperties": false,
79
+ "required": ["kinds", "bucket"],
80
+ "properties": {
81
+ "kinds": { "type": "array", "items": { "type": "string" } },
82
+ "bucket": { "type": "string" }
83
+ }
84
+ },
85
+ "focus_fallback": {
86
+ "type": "object",
87
+ "description": "Focus fallback when nothing is in-flight: an item of `kind` at status `bucket`. Stock: kind 'phase', bucket 'in_progress'.",
88
+ "additionalProperties": false,
89
+ "required": ["kind", "bucket"],
90
+ "properties": {
91
+ "kind": { "type": "string" },
92
+ "bucket": { "type": "string" }
93
+ }
94
+ },
95
+ "next_ranked": {
96
+ "type": "array",
97
+ "description": "Ordered cross-kind push order for nextActions. Each entry selects items of `kind` at `bucket`, labels them `label`, and emits its `reason_template` (with `{rank_value}`/`{id}` tokens substituted) as each item's `reason`; optional `rank_field` + `rank_order` rank within the entry (absent → topo over the dep/gate graph). Stock: tasks (topo) then issues (priority-ranked) then framework-gaps (priority-ranked).",
98
+ "items": {
99
+ "type": "object",
100
+ "additionalProperties": false,
101
+ "required": ["kind", "label", "bucket"],
102
+ "properties": {
103
+ "kind": { "type": "string" },
104
+ "label": { "type": "string" },
105
+ "bucket": { "type": "string" },
106
+ "rank_field": { "type": "string" },
107
+ "rank_order": { "type": "array", "items": { "type": "string" } },
108
+ "reason_template": { "type": "string", "description": "The `reason` string emitted for each item this entry surfaces. Tokens substituted literally: `{rank_value}` → the item's rank_field value (or 'unset' when absent; meaningful only for a field-ranked entry); `{id}` → the item id. Stock field-ranked (framework-gaps): 'open gap (priority {rank_value})'; stock topo (tasks): 'unblocked planned task'." }
109
+ }
110
+ }
111
+ },
112
+ "blocked_by": {
113
+ "type": "object",
114
+ "description": "The relation_types whose edges contribute blockers. Stock: ['task_depends_on_task', 'task_gated_by_item'].",
115
+ "additionalProperties": false,
116
+ "required": ["relation_types"],
117
+ "properties": {
118
+ "relation_types": { "type": "array", "items": { "type": "string" } }
119
+ }
120
+ },
121
+ "rollups": {
122
+ "type": "array",
123
+ "description": "Membership rollups (milestones). Each: items of `kind` whose members are parents of `membership_relation` edges; reached → `complete_status` when all members complete, else `incomplete_status`. Stock: milestone over phase_positioned_in_milestone, reached/planned.",
124
+ "items": {
125
+ "type": "object",
126
+ "additionalProperties": false,
127
+ "required": ["kind", "membership_relation", "complete_status", "incomplete_status"],
128
+ "properties": {
129
+ "kind": { "type": "string" },
130
+ "membership_relation": { "type": "string" },
131
+ "complete_status": { "type": "string" },
132
+ "incomplete_status": { "type": "string" }
133
+ }
134
+ }
135
+ },
136
+ "head_size": {
137
+ "type": "integer",
138
+ "minimum": 0,
139
+ "description": "Truncation cap for the nextActions head. Stock: 15."
140
+ }
141
+ }
142
+ },
70
143
  "display_strings": {
71
144
  "type": "object",
72
145
  "description": "Validation-code / opaque-slug → display label map.",
@@ -85,7 +158,8 @@
85
158
  "category": { "type": "string", "enum": ["ordering", "data_flow", "membership"] },
86
159
  "cycle_allowed": { "type": "boolean" },
87
160
  "source_kinds": { "type": "array", "items": { "type": "string" }, "description": "Block_kind canonical_ids this relation's source (edge.parent) may be; literal \"*\" = any kind. Optional; absence => endpoint-kind unchecked." },
88
- "target_kinds": { "type": "array", "items": { "type": "string" }, "description": "Block_kind canonical_ids this relation's target (edge.child) may be; literal \"*\" = any kind. Optional; absence => endpoint-kind unchecked." }
161
+ "target_kinds": { "type": "array", "items": { "type": "string" }, "description": "Block_kind canonical_ids this relation's target (edge.child) may be; literal \"*\" = any kind. Optional; absence => endpoint-kind unchecked." },
162
+ "role_direction": { "type": "string", "enum": ["as_parent", "as_child"], "description": "Which stored endpoint holds the relation's PRIMARY semantic role — the single orientation source of truth. Category interprets the role (ordering=antecedent, membership=container, data_flow=source); this names where it sits: as_parent=edge.parent, as_child=edge.child. Optional: set only for relations with a per-role consumer (deriver/rollup/roadmap/promote/write/read); role-less relations omit it." }
89
163
  }
90
164
  }
91
165
  },
@@ -194,6 +268,30 @@
194
268
  "description": "Blocks the project has opted into via /context install.",
195
269
  "items": { "type": "string" }
196
270
  },
271
+ "installed_from": {
272
+ "type": "object",
273
+ "description": "Install baseline of the installed schemas: catalog source + per-schema content fingerprint recorded at install time so installed-vs-catalog drift can be detected. Blocks are user data and are not baselined. Written by /context install; preserved verbatim (including `at`) on an idempotent re-install whose catalog + assets are unchanged.",
274
+ "required": ["catalog", "catalog_version", "at", "assets"],
275
+ "additionalProperties": false,
276
+ "properties": {
277
+ "catalog": { "type": "string", "description": "pi-context package \"name@version\" the install baseline was taken from." },
278
+ "catalog_version": { "type": "string", "description": "samples/conception.json schema_version at baseline time." },
279
+ "at": { "type": "string", "description": "ISO-8601 timestamp of when this baseline content was established." },
280
+ "assets": {
281
+ "type": "object",
282
+ "description": "Per installed schema (keyed by canonical_id): content fingerprint + the schema file's own declared version.",
283
+ "additionalProperties": {
284
+ "type": "object",
285
+ "required": ["content_hash", "version"],
286
+ "additionalProperties": false,
287
+ "properties": {
288
+ "content_hash": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
289
+ "version": { "type": "string" }
290
+ }
291
+ }
292
+ }
293
+ }
294
+ },
197
295
  "tool_operations": {
198
296
  "type": "array",
199
297
  "description": "Operation-granular tool grant vocabulary. Each entry names a Pi tool (or coarser operation) that can be granted to a privileged JIT-agent. Operation-granular, opt-in from empty default.",
@@ -116,6 +116,31 @@
116
116
  "enum": ["string", "number", "boolean", "array", "object"]
117
117
  }
118
118
  }
119
+ },
120
+ {
121
+ "type": "object",
122
+ "required": ["op", "path"],
123
+ "additionalProperties": false,
124
+ "properties": {
125
+ "op": { "type": "string", "enum": ["map_each"] },
126
+ "path": { "type": "string", "description": "Dotted '$'-prefixed path to the array whose elements are mapped." },
127
+ "table": {
128
+ "type": "object",
129
+ "description": "When present: each string element is replaced by table[element], or by {relation_type: element, item_endpoint: fallback} when unmatched.",
130
+ "additionalProperties": { "type": "object" }
131
+ },
132
+ "fallback": {
133
+ "type": "string",
134
+ "enum": ["parent", "child"],
135
+ "description": "item_endpoint used for an unmatched string element under `table`; defaults to 'parent' when absent."
136
+ },
137
+ "field": { "type": "string", "description": "When present (and `table` absent): set this field on every object element." },
138
+ "value": { "description": "Value assigned to `field` on each object element." }
139
+ },
140
+ "oneOf": [
141
+ { "required": ["table"], "not": { "required": ["field"] } },
142
+ { "required": ["field", "value"], "not": { "required": ["table"] } }
143
+ ]
119
144
  }
120
145
  ]
121
146
  }