yaaw-se 0.2.0 → 0.2.1

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 (57) hide show
  1. package/README.md +10 -0
  2. package/dist/cli/commands/doctor.d.ts +1 -0
  3. package/dist/cli/commands/doctor.js +1 -1
  4. package/dist/cli/commands/doctor.js.map +1 -1
  5. package/dist/cli/commands/install.d.ts +2 -1
  6. package/dist/cli/commands/install.js +8 -4
  7. package/dist/cli/commands/install.js.map +1 -1
  8. package/dist/cli/commands/status.d.ts +19 -0
  9. package/dist/cli/commands/status.js +5 -0
  10. package/dist/cli/commands/status.js.map +1 -1
  11. package/dist/cli/main.js +4 -2
  12. package/dist/cli/main.js.map +1 -1
  13. package/dist/installer/migrations/index.d.ts +1 -1
  14. package/dist/installer/migrations/index.js +1 -1
  15. package/dist/installer/plan.js +10 -0
  16. package/dist/installer/plan.js.map +1 -1
  17. package/dist/installer/status.d.ts +19 -0
  18. package/dist/installer/status.js +52 -2
  19. package/dist/installer/status.js.map +1 -1
  20. package/dist/installer/transaction.js +2 -1
  21. package/dist/installer/transaction.js.map +1 -1
  22. package/dist/installer/types.d.ts +4 -0
  23. package/dist/installer/verify.js +3 -1
  24. package/dist/installer/verify.js.map +1 -1
  25. package/dist/payload/payload-files.json +67 -57
  26. package/dist/payload/payload.json +1 -1
  27. package/dist/payload/yaaw-core/system/core/artifact-model.md +7 -1
  28. package/dist/payload/yaaw-core/system/core/authority.md +6 -0
  29. package/dist/payload/yaaw-core/system/core/execution-context.md +10 -0
  30. package/dist/payload/yaaw-core/system/core/framework-integrity.md +60 -0
  31. package/dist/payload/yaaw-core/system/core/invalidation.md +9 -2
  32. package/dist/payload/yaaw-core/system/core/io-contract.md +5 -0
  33. package/dist/payload/yaaw-core/system/core/recovery.md +7 -2
  34. package/dist/payload/yaaw-core/system/core/routing.md +17 -13
  35. package/dist/payload/yaaw-core/system/core/state-model.md +8 -0
  36. package/dist/payload/yaaw-core/system/core/transitions.md +6 -1
  37. package/dist/payload/yaaw-core/system/registries/role-io.json +148 -5
  38. package/dist/payload/yaaw-core/system/registries/routing-policy.json +63 -6
  39. package/dist/payload/yaaw-core/system/registries/transitions.json +171 -22
  40. package/dist/payload/yaaw-core/system/roles/implementer.md +3 -0
  41. package/dist/payload/yaaw-core/system/roles/orchestrator.md +11 -10
  42. package/dist/payload/yaaw-core/system/roles/planner.md +3 -0
  43. package/dist/payload/yaaw-core/system/roles/prd.md +3 -0
  44. package/dist/payload/yaaw-core/system/roles/reviewer.md +3 -0
  45. package/dist/payload/yaaw-core/system/schemas/handoff.schema.json +210 -25
  46. package/dist/payload/yaaw-core/system/schemas/observed-state.schema.json +160 -15
  47. package/dist/payload/yaaw-core/system/templates/handoff.json +21 -2
  48. package/dist/payload/yaaw-core/system/templates/observed-state.json +12 -0
  49. package/dist/payload/yaaw-core/system/tools/framework-integrity.mjs +151 -0
  50. package/dist/payload/yaaw-core/system/workflows/orchestration/determine-next-action.md +12 -7
  51. package/dist/payload/yaaw-core/system/workflows/orchestration/dispatch.md +17 -12
  52. package/dist/payload/yaaw-core/system/workflows/orchestration/inspect-state.md +9 -8
  53. package/dist/payload/yaaw-core/system/workflows/orchestration/reconcile-state.md +6 -0
  54. package/dist/payload/yaaw-core/system/workflows/orchestration/route.md +8 -7
  55. package/dist/payload/yaaw-core/system/workflows/review/record-review.md +8 -7
  56. package/dist/payload/yaaw-core/system/workflows/review/review-ticket.md +5 -1
  57. package/package.json +1 -1
@@ -2,38 +2,223 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "yaaw.handoff/v2",
4
4
  "type": "object",
5
- "required": ["schema", "role", "workflow", "desired_intent", "active_artifact", "references", "reads", "writes", "forbidden_writes", "revisions", "expertise", "host_expertise", "expected_output", "result_vocabulary", "repository_requirement", "repository", "transition_sequence"],
5
+ "required": [
6
+ "schema",
7
+ "framework",
8
+ "role",
9
+ "workflow",
10
+ "desired_intent",
11
+ "active_artifact",
12
+ "references",
13
+ "reads",
14
+ "writes",
15
+ "forbidden_writes",
16
+ "revisions",
17
+ "expertise",
18
+ "host_expertise",
19
+ "expected_output",
20
+ "result_vocabulary",
21
+ "repository_requirement",
22
+ "repository",
23
+ "transition_sequence"
24
+ ],
6
25
  "properties": {
7
- "schema": {"const": "yaaw.handoff/v2"},
8
- "role": {"enum": ["prd", "planner", "implementer", "reviewer", "orchestrator"]},
9
- "workflow": {"type": "string", "minLength": 1},
10
- "desired_intent": {"type": ["string", "null"]},
11
- "active_artifact": {"type": ["string", "null"]},
12
- "references": {"type": "array", "items": {"type": "string"}},
13
- "reads": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
14
- "writes": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
15
- "forbidden_writes": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
16
- "revisions": {"type": "object", "additionalProperties": {"type": "integer", "minimum": 0}},
17
- "expertise": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
18
- "host_expertise": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
19
- "expected_output": {"type": "string", "minLength": 1},
20
- "result_vocabulary": {"type": "array", "items": {"type": "string"}, "minItems": 1, "uniqueItems": true},
21
- "repository_requirement": {"enum": ["NONE", "INSPECT", "IDENTITY"]},
26
+ "schema": {
27
+ "const": "yaaw.handoff/v2"
28
+ },
29
+ "role": {
30
+ "enum": [
31
+ "prd",
32
+ "planner",
33
+ "implementer",
34
+ "reviewer",
35
+ "orchestrator"
36
+ ]
37
+ },
38
+ "workflow": {
39
+ "type": "string",
40
+ "minLength": 1
41
+ },
42
+ "desired_intent": {
43
+ "type": [
44
+ "string",
45
+ "null"
46
+ ]
47
+ },
48
+ "active_artifact": {
49
+ "type": [
50
+ "string",
51
+ "null"
52
+ ]
53
+ },
54
+ "references": {
55
+ "type": "array",
56
+ "items": {
57
+ "type": "string"
58
+ }
59
+ },
60
+ "reads": {
61
+ "type": "array",
62
+ "items": {
63
+ "type": "string"
64
+ },
65
+ "uniqueItems": true
66
+ },
67
+ "writes": {
68
+ "type": "array",
69
+ "items": {
70
+ "type": "string"
71
+ },
72
+ "uniqueItems": true
73
+ },
74
+ "forbidden_writes": {
75
+ "type": "array",
76
+ "items": {
77
+ "type": "string"
78
+ },
79
+ "uniqueItems": true
80
+ },
81
+ "revisions": {
82
+ "type": "object",
83
+ "additionalProperties": {
84
+ "type": "integer",
85
+ "minimum": 0
86
+ }
87
+ },
88
+ "expertise": {
89
+ "type": "array",
90
+ "items": {
91
+ "type": "string"
92
+ },
93
+ "uniqueItems": true
94
+ },
95
+ "host_expertise": {
96
+ "type": "array",
97
+ "items": {
98
+ "type": "string"
99
+ },
100
+ "uniqueItems": true
101
+ },
102
+ "expected_output": {
103
+ "type": "string",
104
+ "minLength": 1
105
+ },
106
+ "result_vocabulary": {
107
+ "type": "array",
108
+ "items": {
109
+ "type": "string"
110
+ },
111
+ "minItems": 1,
112
+ "uniqueItems": true
113
+ },
114
+ "repository_requirement": {
115
+ "enum": [
116
+ "NONE",
117
+ "INSPECT",
118
+ "IDENTITY"
119
+ ]
120
+ },
22
121
  "repository": {
23
122
  "type": "object",
24
- "required": ["status", "workspace_scope", "git_root_relation", "head_commit", "dirty", "worktree_digest", "error"],
123
+ "required": [
124
+ "status",
125
+ "workspace_scope",
126
+ "git_root_relation",
127
+ "head_commit",
128
+ "dirty",
129
+ "worktree_digest",
130
+ "error"
131
+ ],
25
132
  "properties": {
26
- "status": {"enum": ["READY", "UNVERSIONED", "UNAVAILABLE", "ROOT_MISMATCH", "IDENTITY_FAILED"]},
27
- "workspace_scope": {"type": "string", "minLength": 1},
28
- "git_root_relation": {"enum": ["same", "ancestor", "none", "unknown"]},
29
- "head_commit": {"type": ["string", "null"]},
30
- "dirty": {"type": ["boolean", "null"]},
31
- "worktree_digest": {"type": ["string", "null"]},
32
- "error": {"type": ["string", "null"]}
133
+ "status": {
134
+ "enum": [
135
+ "READY",
136
+ "UNVERSIONED",
137
+ "UNAVAILABLE",
138
+ "ROOT_MISMATCH",
139
+ "IDENTITY_FAILED"
140
+ ]
141
+ },
142
+ "workspace_scope": {
143
+ "type": "string",
144
+ "minLength": 1
145
+ },
146
+ "git_root_relation": {
147
+ "enum": [
148
+ "same",
149
+ "ancestor",
150
+ "none",
151
+ "unknown"
152
+ ]
153
+ },
154
+ "head_commit": {
155
+ "type": [
156
+ "string",
157
+ "null"
158
+ ]
159
+ },
160
+ "dirty": {
161
+ "type": [
162
+ "boolean",
163
+ "null"
164
+ ]
165
+ },
166
+ "worktree_digest": {
167
+ "type": [
168
+ "string",
169
+ "null"
170
+ ]
171
+ },
172
+ "error": {
173
+ "type": [
174
+ "string",
175
+ "null"
176
+ ]
177
+ }
33
178
  },
34
179
  "additionalProperties": false
35
180
  },
36
- "transition_sequence": {"type": "integer", "minimum": 0}
181
+ "transition_sequence": {
182
+ "type": "integer",
183
+ "minimum": 0
184
+ },
185
+ "framework": {
186
+ "type": "object",
187
+ "required": [
188
+ "yaaw_version",
189
+ "system_schema",
190
+ "installation_schema",
191
+ "project_schema",
192
+ "manifest_digest",
193
+ "integrity_status"
194
+ ],
195
+ "properties": {
196
+ "yaaw_version": {
197
+ "type": "string",
198
+ "minLength": 1
199
+ },
200
+ "system_schema": {
201
+ "type": "integer",
202
+ "minimum": 1
203
+ },
204
+ "installation_schema": {
205
+ "type": "integer",
206
+ "minimum": 1
207
+ },
208
+ "project_schema": {
209
+ "type": "integer",
210
+ "minimum": 1
211
+ },
212
+ "manifest_digest": {
213
+ "type": "string",
214
+ "minLength": 1
215
+ },
216
+ "integrity_status": {
217
+ "const": "HEALTHY"
218
+ }
219
+ },
220
+ "additionalProperties": false
221
+ }
37
222
  },
38
223
  "additionalProperties": false
39
224
  }
@@ -2,28 +2,173 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "yaaw.observed-state/v2",
4
4
  "type": "object",
5
- "required": ["schema", "repository", "transition_sequence", "claims", "artifacts", "inconsistencies", "candidate_actions"],
5
+ "required": [
6
+ "schema",
7
+ "framework",
8
+ "repository",
9
+ "transition_sequence",
10
+ "claims",
11
+ "artifacts",
12
+ "inconsistencies",
13
+ "candidate_actions"
14
+ ],
6
15
  "properties": {
7
- "schema": {"const": "yaaw.observed-state/v2"},
16
+ "schema": {
17
+ "const": "yaaw.observed-state/v2"
18
+ },
8
19
  "repository": {
9
20
  "type": "object",
10
- "required": ["status", "workspace_scope", "git_root_relation", "head_commit", "dirty", "worktree_digest", "error"],
21
+ "required": [
22
+ "status",
23
+ "workspace_scope",
24
+ "git_root_relation",
25
+ "head_commit",
26
+ "dirty",
27
+ "worktree_digest",
28
+ "error"
29
+ ],
11
30
  "properties": {
12
- "status": {"enum": ["READY", "UNVERSIONED", "UNAVAILABLE", "ROOT_MISMATCH", "IDENTITY_FAILED"]},
13
- "workspace_scope": {"type": "string", "minLength": 1},
14
- "git_root_relation": {"enum": ["same", "ancestor", "none", "unknown"]},
15
- "head_commit": {"type": ["string", "null"]},
16
- "dirty": {"type": ["boolean", "null"]},
17
- "worktree_digest": {"type": ["string", "null"]},
18
- "error": {"type": ["string", "null"]}
31
+ "status": {
32
+ "enum": [
33
+ "READY",
34
+ "UNVERSIONED",
35
+ "UNAVAILABLE",
36
+ "ROOT_MISMATCH",
37
+ "IDENTITY_FAILED"
38
+ ]
39
+ },
40
+ "workspace_scope": {
41
+ "type": "string",
42
+ "minLength": 1
43
+ },
44
+ "git_root_relation": {
45
+ "enum": [
46
+ "same",
47
+ "ancestor",
48
+ "none",
49
+ "unknown"
50
+ ]
51
+ },
52
+ "head_commit": {
53
+ "type": [
54
+ "string",
55
+ "null"
56
+ ]
57
+ },
58
+ "dirty": {
59
+ "type": [
60
+ "boolean",
61
+ "null"
62
+ ]
63
+ },
64
+ "worktree_digest": {
65
+ "type": [
66
+ "string",
67
+ "null"
68
+ ]
69
+ },
70
+ "error": {
71
+ "type": [
72
+ "string",
73
+ "null"
74
+ ]
75
+ }
19
76
  },
20
77
  "additionalProperties": false
21
78
  },
22
- "transition_sequence": {"type": "integer", "minimum": 0},
23
- "claims": {"type": "object"},
24
- "artifacts": {"type": "object"},
25
- "inconsistencies": {"type": "array", "items": {"type": "string"}},
26
- "candidate_actions": {"type": "array", "items": {"type": "string"}}
79
+ "transition_sequence": {
80
+ "type": "integer",
81
+ "minimum": 0
82
+ },
83
+ "claims": {
84
+ "type": "object"
85
+ },
86
+ "artifacts": {
87
+ "type": "object"
88
+ },
89
+ "inconsistencies": {
90
+ "type": "array",
91
+ "items": {
92
+ "type": "string"
93
+ }
94
+ },
95
+ "candidate_actions": {
96
+ "type": "array",
97
+ "items": {
98
+ "type": "string"
99
+ }
100
+ },
101
+ "framework": {
102
+ "type": "object",
103
+ "required": [
104
+ "yaaw_version",
105
+ "system_schema",
106
+ "installation_schema",
107
+ "project_schema",
108
+ "manifest_digest",
109
+ "integrity_status",
110
+ "modified",
111
+ "missing",
112
+ "local_overrides",
113
+ "repair_required"
114
+ ],
115
+ "properties": {
116
+ "yaaw_version": {
117
+ "type": "string",
118
+ "minLength": 1
119
+ },
120
+ "system_schema": {
121
+ "type": "integer",
122
+ "minimum": 1
123
+ },
124
+ "installation_schema": {
125
+ "type": "integer",
126
+ "minimum": 1
127
+ },
128
+ "project_schema": {
129
+ "type": "integer",
130
+ "minimum": 1
131
+ },
132
+ "manifest_digest": {
133
+ "type": "string",
134
+ "minLength": 1
135
+ },
136
+ "integrity_status": {
137
+ "type": "string",
138
+ "enum": [
139
+ "HEALTHY",
140
+ "MODIFIED",
141
+ "MISSING",
142
+ "LOCAL_OVERRIDE",
143
+ "MANIFEST_INVALID",
144
+ "UNKNOWN",
145
+ "CONTRACT_INCONSISTENT"
146
+ ]
147
+ },
148
+ "modified": {
149
+ "type": "array",
150
+ "items": {
151
+ "type": "string"
152
+ }
153
+ },
154
+ "missing": {
155
+ "type": "array",
156
+ "items": {
157
+ "type": "string"
158
+ }
159
+ },
160
+ "local_overrides": {
161
+ "type": "array",
162
+ "items": {
163
+ "type": "string"
164
+ }
165
+ },
166
+ "repair_required": {
167
+ "type": "boolean"
168
+ }
169
+ },
170
+ "additionalProperties": false
171
+ }
27
172
  },
28
173
  "additionalProperties": false
29
174
  }
@@ -1,5 +1,13 @@
1
1
  {
2
2
  "schema": "yaaw.handoff/v2",
3
+ "framework": {
4
+ "yaaw_version": "VERSION",
5
+ "system_schema": 2,
6
+ "installation_schema": 1,
7
+ "project_schema": 1,
8
+ "manifest_digest": "sha256:MANIFEST",
9
+ "integrity_status": "HEALTHY"
10
+ },
3
11
  "role": "implementer",
4
12
  "workflow": "implementation.implement-ticket",
5
13
  "desired_intent": "IMPLEMENT",
@@ -8,11 +16,22 @@
8
16
  "reads": [],
9
17
  "writes": [],
10
18
  "forbidden_writes": [],
11
- "revisions": {"product": 1, "engineering": 1, "spec": 1, "ticket": 1},
19
+ "revisions": {
20
+ "product": 1,
21
+ "engineering": 1,
22
+ "spec": 1,
23
+ "ticket": 1
24
+ },
12
25
  "expertise": [],
13
26
  "host_expertise": [],
14
27
  "expected_output": "implementation_evidence",
15
- "result_vocabulary": ["SUCCESS", "REVIEW_REQUIRED", "REPLAN_REQUIRED", "PRECONDITION_UNSATISFIED", "BLOCKED"],
28
+ "result_vocabulary": [
29
+ "SUCCESS",
30
+ "REVIEW_REQUIRED",
31
+ "REPLAN_REQUIRED",
32
+ "PRECONDITION_UNSATISFIED",
33
+ "BLOCKED"
34
+ ],
16
35
  "repository_requirement": "IDENTITY",
17
36
  "repository": {
18
37
  "status": "READY",
@@ -1,5 +1,17 @@
1
1
  {
2
2
  "schema": "yaaw.observed-state/v2",
3
+ "framework": {
4
+ "yaaw_version": "VERSION",
5
+ "system_schema": 2,
6
+ "installation_schema": 1,
7
+ "project_schema": 1,
8
+ "manifest_digest": "sha256:MANIFEST",
9
+ "integrity_status": "HEALTHY",
10
+ "modified": [],
11
+ "missing": [],
12
+ "local_overrides": [],
13
+ "repair_required": false
14
+ },
3
15
  "repository": {
4
16
  "status": "UNVERSIONED",
5
17
  "workspace_scope": ".",
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env node
2
+ import { createHash } from "node:crypto";
3
+ import { lstat, readFile } from "node:fs/promises";
4
+ import { isAbsolute, join, relative, resolve } from "node:path";
5
+
6
+ function digest(bytes) {
7
+ return createHash("sha256").update(bytes).digest("hex");
8
+ }
9
+
10
+ async function exists(path) {
11
+ try { await lstat(path); return true; } catch { return false; }
12
+ }
13
+
14
+ function within(root, target) {
15
+ const rel = relative(root, target);
16
+ return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
17
+ }
18
+
19
+ function normalizeRel(value) {
20
+ return String(value).replaceAll("\\", "/");
21
+ }
22
+
23
+ function isFrameworkManaged(rel, record) {
24
+ const path = normalizeRel(rel);
25
+ return record?.owner === "package:system" || path.startsWith(".yaaw-core/system/");
26
+ }
27
+
28
+ async function safeFile(root, rel) {
29
+ const normalized = normalizeRel(rel);
30
+ if (!normalized || isAbsolute(normalized) || normalized.split("/").includes("..")) {
31
+ throw new Error(`unsafe manifest path: ${rel}`);
32
+ }
33
+ const target = resolve(root, normalized);
34
+ if (!within(root, target)) throw new Error(`manifest path escapes workspace: ${rel}`);
35
+ const info = await lstat(target);
36
+ if (info.isSymbolicLink()) throw new Error(`managed framework path is a symlink: ${rel}`);
37
+ if (!info.isFile()) throw new Error(`managed framework path is not a file: ${rel}`);
38
+ return target;
39
+ }
40
+
41
+ function workspaceArg(argv) {
42
+ const index = argv.indexOf("--workspace");
43
+ if (index >= 0 && argv[index + 1]) return argv[index + 1];
44
+ return process.cwd();
45
+ }
46
+
47
+ async function inspect(workspace) {
48
+ const root = resolve(workspace);
49
+ const manifestPath = join(root, ".yaaw-core", "install", "manifest.json");
50
+ let manifestBytes;
51
+ let manifest;
52
+ try {
53
+ manifestBytes = await readFile(manifestPath);
54
+ manifest = JSON.parse(manifestBytes.toString("utf8"));
55
+ } catch (error) {
56
+ return {
57
+ schema: "yaaw.framework-integrity/v1",
58
+ status: "MANIFEST_INVALID",
59
+ package_version: null,
60
+ manifest_digest: null,
61
+ modified: [],
62
+ missing: [],
63
+ local_overrides: [],
64
+ unsafe: [String(error?.message ?? error)],
65
+ repair_required: true
66
+ };
67
+ }
68
+
69
+ const supportedManifest = manifest?.schema === "yaaw.installation/v1" || manifest?.schema === "yaaw.installation/v2";
70
+ if (
71
+ !supportedManifest ||
72
+ manifest?.project?.root !== "." ||
73
+ !manifest?.managedFiles ||
74
+ typeof manifest.managedFiles !== "object"
75
+ ) {
76
+ return {
77
+ schema: "yaaw.framework-integrity/v1",
78
+ status: "MANIFEST_INVALID",
79
+ package_version: manifest?.yaawVersion ?? null,
80
+ manifest_digest: `sha256:${digest(manifestBytes)}`,
81
+ modified: [],
82
+ missing: [],
83
+ local_overrides: [],
84
+ unsafe: ["unsupported or incomplete installation manifest"],
85
+ repair_required: true
86
+ };
87
+ }
88
+
89
+ const modified = [];
90
+ const missing = [];
91
+ const localOverrides = [];
92
+ const unsafe = [];
93
+
94
+ for (const [rel, record] of Object.entries(manifest.managedFiles)) {
95
+ if (!isFrameworkManaged(rel, record)) continue;
96
+ const normalized = normalizeRel(rel);
97
+ if (record?.localOverride === true) localOverrides.push(normalized);
98
+ const target = resolve(root, normalized);
99
+ if (!(await exists(target))) {
100
+ missing.push(normalized);
101
+ continue;
102
+ }
103
+ try {
104
+ const safe = await safeFile(root, normalized);
105
+ const actual = digest(await readFile(safe));
106
+ if (actual !== record.sha256) modified.push(normalized);
107
+ } catch (error) {
108
+ unsafe.push(`${normalized}: ${String(error?.message ?? error)}`);
109
+ }
110
+ }
111
+
112
+ let status = "HEALTHY";
113
+ if (unsafe.length) status = "MANIFEST_INVALID";
114
+ else if (missing.length) status = "MISSING";
115
+ else if (modified.length) status = "MODIFIED";
116
+ else if (localOverrides.length) status = "LOCAL_OVERRIDE";
117
+
118
+ return {
119
+ schema: "yaaw.framework-integrity/v1",
120
+ status,
121
+ package_version: manifest.yaawVersion ?? null,
122
+ system_schema: manifest.systemSchema ?? 1,
123
+ installation_schema: manifest.installationSchema ?? 1,
124
+ project_schema: manifest.projectSchema ?? manifest.projectStateSchema ?? 1,
125
+ manifest_digest: `sha256:${digest(manifestBytes)}`,
126
+ modified,
127
+ missing,
128
+ local_overrides: localOverrides,
129
+ unsafe,
130
+ repair_required: status !== "HEALTHY"
131
+ };
132
+ }
133
+
134
+ try {
135
+ const result = await inspect(workspaceArg(process.argv.slice(2)));
136
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
137
+ process.exitCode = result.status === "HEALTHY" ? 0 : 2;
138
+ } catch (error) {
139
+ process.stdout.write(JSON.stringify({
140
+ schema: "yaaw.framework-integrity/v1",
141
+ status: "UNKNOWN",
142
+ package_version: null,
143
+ manifest_digest: null,
144
+ modified: [],
145
+ missing: [],
146
+ local_overrides: [],
147
+ unsafe: [String(error?.message ?? error)],
148
+ repair_required: true
149
+ }, null, 2) + "\n");
150
+ process.exitCode = 2;
151
+ }
@@ -7,13 +7,18 @@ Turn reconciled observed reality into one explicit, fresh dispatch contract.
7
7
  Current observed-state snapshot, reconciled state, `.yaaw-core/system/core/routing.md`, workflow/execution/artifact/role-I/O/expertise registries, and optional current intent.
8
8
 
9
9
  ## Procedure
10
- 1. Choose exactly one next canonical workflow or terminal state using explicit routing precedence. Do not load candidate workflow bodies while choosing.
11
- 2. Resolve its repository requirement from `.yaaw-core/system/registries/execution-policy.json`.
12
- 3. If requirement is `IDENTITY` and repository status is not `READY`, return `PRECONDITION_UNSATISFIED:REPOSITORY_IDENTITY_UNAVAILABLE` or `BLOCKED` as appropriate; do not dispatch.
13
- 4. Resolve exact read/write/forbidden-write artifact classes from `.yaaw-core/system/registries/role-io.json` and exact current artifact references.
14
- 5. Select only YAAW expertise relevant to the selected workflow/artifact. Host expertise is admitted only through `.yaaw-core/system/rules/research-admission.md`.
15
- 6. Write `.yaaw-core/runtime/handoff.json` conforming to handoff v2 with desired intent, role, workflow ID, exact references/revisions, read/write sets, expertise, expected output/result vocabulary, repository requirement/basis, and transition sequence.
16
- 7. If the result is human-input, BLOCKED, or COMPLETE, write no executable handoff and return the stop result.
10
+ 1. Require the current observed framework integrity status to be `HEALTHY`. Otherwise return the typed framework stop and write no executable handoff.
11
+ 2. Choose exactly one next canonical workflow or terminal state using explicit routing precedence. Do not load candidate workflow bodies while choosing.
12
+ 3. Resolve its repository requirement from `.yaaw-core/system/registries/execution-policy.json`.
13
+ 4. If requirement is `IDENTITY` and repository status is not `READY`, return `PRECONDITION_UNSATISFIED:REPOSITORY_IDENTITY_UNAVAILABLE` or `BLOCKED` as appropriate; do not dispatch.
14
+ 5. Resolve exact read/write/forbidden-write artifact classes from `.yaaw-core/system/registries/role-io.json` and exact current artifact references.
15
+ 6. Select only YAAW expertise relevant to the selected workflow/artifact. Host expertise is admitted only through `.yaaw-core/system/rules/research-admission.md`.
16
+ 7. Write `.yaaw-core/runtime/handoff.json` conforming to handoff v2 with desired intent, role, workflow ID, exact references/revisions, read/write sets, expertise, expected output/result vocabulary, repository requirement/basis, and transition sequence.
17
+ 8. If the result is human-input, BLOCKED, or COMPLETE, write no executable handoff and return the stop result.
17
18
 
18
19
  ## Boundary
19
20
  Do not perform target role semantic work here.
21
+
22
+ ## Framework write guard
23
+
24
+ Before persisting a handoff, verify that its write set is a subset of the selected role's canonical artifact writes and contains no installer-managed artifact or `.yaaw-core/system/**` path. A framework defect is a stop condition, never a target workflow.