@geraldmaron/construct 1.4.0 → 1.4.2

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 (65) hide show
  1. package/bin/construct +2 -1
  2. package/bin/construct-postinstall.mjs +27 -2
  3. package/config/tag-vocabulary.json +264 -0
  4. package/lib/config/schema.mjs +1 -1
  5. package/lib/doctor/diagnosis.mjs +20 -0
  6. package/lib/doctor/index.mjs +5 -0
  7. package/lib/embed/worker.mjs +5 -0
  8. package/lib/env-config.mjs +10 -2
  9. package/lib/export-validate.mjs +34 -2
  10. package/lib/hooks/guard-bash.mjs +3 -1
  11. package/lib/host/readiness.mjs +109 -0
  12. package/lib/host-disposition.mjs +10 -1
  13. package/lib/install/stage-project.mjs +41 -4
  14. package/lib/intake/prepare.mjs +2 -0
  15. package/lib/mcp/destructive-approval.mjs +57 -0
  16. package/lib/mcp/server.mjs +209 -35
  17. package/lib/mcp/tool-rate-limit.mjs +47 -0
  18. package/lib/mcp/tool-safety.mjs +94 -0
  19. package/lib/mcp/tool-surface-parity.mjs +60 -0
  20. package/lib/mcp/tools/orchestration-run.mjs +45 -7
  21. package/lib/mcp/tools/project.mjs +25 -8
  22. package/lib/mcp/tools/storage.mjs +9 -1
  23. package/lib/mcp/tools/web-search-governance.mjs +96 -0
  24. package/lib/mcp/tools/web-search.mjs +6 -44
  25. package/lib/mcp-platform-config.mjs +27 -18
  26. package/lib/oracle/daemon-entry.mjs +6 -0
  27. package/lib/orchestration/runtime.mjs +81 -42
  28. package/lib/orchestration/web-capability.mjs +59 -0
  29. package/lib/orchestration/worker.mjs +263 -19
  30. package/lib/orchestration-policy.mjs +36 -0
  31. package/lib/output-quality.mjs +61 -2
  32. package/lib/path-policy.mjs +56 -0
  33. package/lib/providers/secret-audit-wiring.mjs +35 -18
  34. package/lib/providers/secret-resolver.mjs +28 -13
  35. package/lib/registry/catalog.mjs +6 -0
  36. package/lib/registry/loader.mjs +7 -1
  37. package/lib/registry/validate.mjs +3 -3
  38. package/lib/sandbox.mjs +1 -1
  39. package/lib/service-manager.mjs +59 -9
  40. package/lib/storage/admin.mjs +7 -2
  41. package/package.json +6 -1
  42. package/registry/agent-manifest.json +117 -0
  43. package/registry/capabilities.json +1880 -0
  44. package/schemas/brand-voice.schema.json +24 -0
  45. package/schemas/capability-registry.schema.json +72 -0
  46. package/schemas/certification-run.schema.json +130 -0
  47. package/schemas/demo-recording.schema.json +46 -0
  48. package/schemas/eval-dataset.schema.json +79 -0
  49. package/schemas/execution-capability-profile.schema.json +46 -0
  50. package/schemas/execution-policy.schema.json +114 -0
  51. package/schemas/improvement-proposal.schema.json +65 -0
  52. package/schemas/mcp-tool-output.schema.json +61 -0
  53. package/schemas/platform-capabilities.schema.json +83 -0
  54. package/schemas/project-config.schema.json +227 -0
  55. package/schemas/project-demo.schema.json +60 -0
  56. package/schemas/provider-behavior-matrix.schema.json +91 -0
  57. package/schemas/scope.schema.json +197 -0
  58. package/schemas/specialist-trace.schema.json +107 -0
  59. package/schemas/team.schema.json +99 -0
  60. package/schemas/unified-registry.schema.json +548 -0
  61. package/scripts/sync-specialists.mjs +135 -12
  62. package/specialists/org/specialists/cx-researcher.json +1 -0
  63. package/specialists/prompts/cx-researcher.md +9 -8
  64. package/vendor/pandoc-ext/README.md +3 -0
  65. package/vendor/pandoc-ext/diagram.lua +687 -0
@@ -0,0 +1,548 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://geraldmaron.github.io/construct/schemas/unified-registry.schema.json",
4
+ "title": "Construct Unified Registry",
5
+ "description": "Single source of truth for teams, specialists, roles, contracts, and policies. Consolidates what was previously split across five separate files: teams.json, teams-registry.json, registry.json, contracts.json, and role-manifests.json.",
6
+ "type": "object",
7
+ "required": ["version", "teams", "specialists", "contracts", "policies"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "version": {
11
+ "enum": [2, 3],
12
+ "description": "Schema version. Version 3 is the modular org assembly."
13
+ },
14
+ "teams": {
15
+ "type": "object",
16
+ "description": "Map of team id -> team definition. Teams are the primary organizational unit with explicit decision rights, escalation paths, and charter.",
17
+ "additionalProperties": {
18
+ "$ref": "#/$defs/team"
19
+ },
20
+ "minProperties": 1
21
+ },
22
+ "specialists": {
23
+ "type": "object",
24
+ "description": "Map of specialist id (e.g., cx-engineer) -> specialist definition. Every specialist declares exactly one team.",
25
+ "additionalProperties": {
26
+ "$ref": "#/$defs/specialist"
27
+ },
28
+ "minProperties": 1
29
+ },
30
+ "contracts": {
31
+ "type": "object",
32
+ "description": "Map of contract id -> contract definition. Contracts are producer→consumer handoffs with preconditions, postconditions, and schemas.",
33
+ "additionalProperties": {
34
+ "$ref": "#/$defs/contract"
35
+ }
36
+ },
37
+ "policies": {
38
+ "type": "object",
39
+ "description": "Map of policy id -> policy definition. Policies enforce team decision rights, approval requirements, and governance gates.",
40
+ "additionalProperties": {
41
+ "$ref": "#/$defs/policy"
42
+ }
43
+ }
44
+ },
45
+ "$defs": {
46
+ "team": {
47
+ "type": "object",
48
+ "description": "Organizational team with explicit owner, decision rights, forbidden decisions, escalation path, and charter.",
49
+ "required": ["id", "name", "owner", "roles", "charter"],
50
+ "additionalProperties": false,
51
+ "properties": {
52
+ "id": {
53
+ "type": "string",
54
+ "pattern": "^[a-z][a-z0-9-]{1,40}$",
55
+ "description": "Unique team identifier (e.g., product-group, engineering-group, quality-group)."
56
+ },
57
+ "name": {
58
+ "type": "string",
59
+ "minLength": 1,
60
+ "maxLength": 80,
61
+ "description": "Human-readable team name."
62
+ },
63
+ "owner": {
64
+ "type": "string",
65
+ "pattern": "^[a-z][a-z0-9-]{1,40}$",
66
+ "description": "Role id of the team owner/lead. Must be a role that has at least one specialist assigned."
67
+ },
68
+ "roles": {
69
+ "type": "array",
70
+ "minItems": 1,
71
+ "maxItems": 20,
72
+ "description": "List of role ids that constitute this team.",
73
+ "items": {
74
+ "type": "string",
75
+ "pattern": "^[a-z][a-z0-9-]{1,40}$"
76
+ }
77
+ },
78
+ "decisionRights": {
79
+ "type": "array",
80
+ "description": "Decisions this team is authorized to make (e.g., intake-triage, design-approval, deployment, scope-change).",
81
+ "items": {
82
+ "type": "string",
83
+ "pattern": "^[a-z][a-z0-9-]{1,40}$"
84
+ }
85
+ },
86
+ "forbiddenDecisions": {
87
+ "type": "array",
88
+ "description": "Decisions this team explicitly cannot make. Attempts escalate automatically.",
89
+ "items": {
90
+ "type": "string",
91
+ "pattern": "^[a-z][a-z0-9-]{1,40}$"
92
+ }
93
+ },
94
+ "escalationPath": {
95
+ "type": "array",
96
+ "description": "Chain of escalation for unresolved decisions. First element is the team owner role, then higher-level escalations.",
97
+ "minItems": 1,
98
+ "items": {
99
+ "type": "string",
100
+ "pattern": "^[a-z][a-z0-9-]{1,40}$"
101
+ }
102
+ },
103
+ "charter": {
104
+ "type": "string",
105
+ "minLength": 20,
106
+ "maxLength": 800,
107
+ "description": "One-paragraph mission statement: what this team owns, what it doesn't own, and key constraints."
108
+ },
109
+ "contact": {
110
+ "type": "object",
111
+ "description": "How to reach this team.",
112
+ "additionalProperties": false,
113
+ "properties": {
114
+ "slack": {
115
+ "type": "string",
116
+ "description": "Slack channel (e.g., #product, #engineering)."
117
+ },
118
+ "email": {
119
+ "type": "string",
120
+ "format": "email",
121
+ "description": "Team email address."
122
+ },
123
+ "owner": {
124
+ "type": "string",
125
+ "description": "Direct contact for the team owner."
126
+ }
127
+ }
128
+ },
129
+ "evidence": {
130
+ "type": "array",
131
+ "description": "Primary sources justifying this team's structure (interviews, job specs, ADRs, organizational research).",
132
+ "items": {
133
+ "type": "string"
134
+ }
135
+ },
136
+ "sources": {
137
+ "type": "array",
138
+ "description": "Integration resources this team binds (GitHub repos, Jira/Linear projects, Slack channels) with typed selectors and optional filters. Resolved by resolveTeamSources() and threaded into embed/provider_fetch.",
139
+ "items": { "$ref": "#/$defs/sourceTarget" }
140
+ }
141
+ }
142
+ },
143
+ "sourceTarget": {
144
+ "type": "object",
145
+ "description": "A typed integration binding. Deep-validated at runtime by lib/config/source-targets.mjs validateSourceTarget.",
146
+ "required": ["id", "provider", "selector"],
147
+ "additionalProperties": false,
148
+ "properties": {
149
+ "id": {
150
+ "type": "string",
151
+ "pattern": "^[A-Za-z0-9_-]{1,64}$",
152
+ "description": "Stable id for this binding (unique within the team's sources)."
153
+ },
154
+ "provider": {
155
+ "type": "string",
156
+ "enum": ["github", "jira", "linear", "slack"],
157
+ "description": "Integration provider."
158
+ },
159
+ "selector": {
160
+ "type": "object",
161
+ "description": "Provider-specific selector (github: {repo}, jira: {project}, linear: {team}, slack: {channel, intent?}).",
162
+ "minProperties": 1
163
+ },
164
+ "filters": {
165
+ "type": "object",
166
+ "description": "Optional per-target filters threaded into fetch (e.g., jira {jql}, github {refs, limit}, slack {oldest})."
167
+ }
168
+ }
169
+ },
170
+ "specialist": {
171
+ "type": "object",
172
+ "description": "An AI specialist (cx-* agent) with skills, fence, model tier, and event watchers.",
173
+ "required": ["name", "team"],
174
+ "additionalProperties": false,
175
+ "properties": {
176
+ "name": {
177
+ "type": "string",
178
+ "pattern": "^[a-z][a-z0-9-]{1,40}$",
179
+ "description": "Specialist id without cx- prefix (e.g., engineer, qa, architect). Combined with prefix to create cx-engineer, cx-qa, etc."
180
+ },
181
+ "displayName": {
182
+ "type": "string",
183
+ "description": "Human-readable specialist name (e.g., Engineer, Quality Assurance, Architect)."
184
+ },
185
+ "description": {
186
+ "type": "string",
187
+ "description": "Short description of what this specialist does."
188
+ },
189
+ "team": {
190
+ "type": "string",
191
+ "pattern": "^[a-z][a-z0-9-]{1,40}$",
192
+ "description": "Team id this specialist belongs to. Every specialist declares exactly one team."
193
+ },
194
+ "role": {
195
+ "type": "string",
196
+ "enum": ["owner", "member", "temporary"],
197
+ "description": "Role within the team: owner (team lead), member (regular), or temporary."
198
+ },
199
+ "modelTier": {
200
+ "type": "string",
201
+ "enum": ["standard", "reasoning"],
202
+ "description": "Which model tier to use for this specialist: standard or reasoning."
203
+ },
204
+ "reasoningEffort": {
205
+ "type": "string",
206
+ "enum": ["low", "medium", "high"],
207
+ "description": "Effort level for extended thinking (if using reasoning model)."
208
+ },
209
+ "skills": {
210
+ "type": "array",
211
+ "description": "List of skill paths this specialist has (e.g., docs/prd-workflow, architecture/api-design).",
212
+ "items": {
213
+ "type": "string"
214
+ }
215
+ },
216
+ "events": {
217
+ "type": "array",
218
+ "description": "Trigger events that activate this specialist (e.g., test.fail, handoff.received, pr.opened).",
219
+ "items": {
220
+ "type": "string"
221
+ }
222
+ },
223
+ "fence": {
224
+ "type": "object",
225
+ "description": "Access control fence for this specialist.",
226
+ "additionalProperties": false,
227
+ "properties": {
228
+ "allowedPaths": {
229
+ "type": "array",
230
+ "description": "Paths/glob patterns this specialist can read/write.",
231
+ "items": {
232
+ "type": "string"
233
+ }
234
+ },
235
+ "allowedCommands": {
236
+ "type": "array",
237
+ "description": "Commands this specialist can execute (bash, bd, git, etc.).",
238
+ "items": {
239
+ "type": "string"
240
+ }
241
+ },
242
+ "allowedBdLabels": {
243
+ "type": "array",
244
+ "description": "Beads labels this specialist can use when creating/updating issues.",
245
+ "items": {
246
+ "type": "string"
247
+ }
248
+ },
249
+ "approvalRequired": {
250
+ "type": "array",
251
+ "description": "Actions requiring approval before execution (e.g., commit, push, edit:lib/**).",
252
+ "items": {
253
+ "type": "string"
254
+ }
255
+ }
256
+ }
257
+ },
258
+ "docArtifacts": {
259
+ "type": "array",
260
+ "description": "Doc artifact types this specialist can author (e.g., prd, adr, memo, incident-report).",
261
+ "items": {
262
+ "type": "string"
263
+ }
264
+ },
265
+ "watchConditions": {
266
+ "type": "array",
267
+ "description": "Conditions that should trigger proactive engagement (e.g., high-ambiguity-deep-work, flaky-tests, stale-alignment-census).",
268
+ "items": {
269
+ "type": "string"
270
+ }
271
+ },
272
+ "prompt": {
273
+ "type": "object",
274
+ "description": "Optional prompt configuration overrides for this specialist.",
275
+ "additionalProperties": false,
276
+ "properties": {
277
+ "file": {
278
+ "type": "string",
279
+ "description": "Path to specialist prompt file."
280
+ },
281
+ "customInstructions": {
282
+ "type": "string",
283
+ "description": "Custom instructions appended to the base prompt."
284
+ }
285
+ }
286
+ },
287
+ "permissions": {
288
+ "type": "object",
289
+ "description": "Fine-grained permissions (edit, bash, webfetch, etc.).",
290
+ "additionalProperties": {
291
+ "type": "string",
292
+ "enum": ["allow", "deny"]
293
+ }
294
+ }
295
+ }
296
+ },
297
+ "contract": {
298
+ "type": "object",
299
+ "description": "Service contract between producer and consumer specialists. Defines inputs, outputs, preconditions, postconditions, and team boundaries.",
300
+ "required": ["id", "producer", "consumer"],
301
+ "additionalProperties": false,
302
+ "properties": {
303
+ "id": {
304
+ "type": "string",
305
+ "pattern": "^[a-z][a-z0-9-]{1,50}$",
306
+ "description": "Unique contract identifier (e.g., construct-to-orchestrator, researcher-to-architect)."
307
+ },
308
+ "producer": {
309
+ "type": "string",
310
+ "description": "Specialist id or role that produces the output (e.g., cx-researcher, user, construct)."
311
+ },
312
+ "consumer": {
313
+ "type": "string",
314
+ "description": "Specialist id or role that consumes the output (e.g., cx-architect, cx-product-manager, construct)."
315
+ },
316
+ "trigger": {
317
+ "type": "object",
318
+ "description": "Conditions that trigger this contract.",
319
+ "additionalProperties": true
320
+ },
321
+ "input": {
322
+ "type": "object",
323
+ "description": "Input shape and requirements.",
324
+ "additionalProperties": true,
325
+ "properties": {
326
+ "shape": {
327
+ "type": "string",
328
+ "description": "Named shape (e.g., task-packet, research-brief, evidence-brief)."
329
+ },
330
+ "mustContain": {
331
+ "type": "array",
332
+ "description": "Fields that must be present in the input.",
333
+ "items": {
334
+ "type": "string"
335
+ }
336
+ }
337
+ }
338
+ },
339
+ "output": {
340
+ "type": "object",
341
+ "description": "Output shape and requirements.",
342
+ "additionalProperties": true,
343
+ "properties": {
344
+ "shape": {
345
+ "type": "string",
346
+ "description": "Named shape (e.g., routed-plan, decision, prd-handoff)."
347
+ },
348
+ "mustContain": {
349
+ "type": "array",
350
+ "description": "Fields that must be present in the output.",
351
+ "items": {
352
+ "type": "string"
353
+ }
354
+ },
355
+ "schema": {
356
+ "type": "string",
357
+ "description": "Path to JSON Schema for the output."
358
+ }
359
+ }
360
+ },
361
+ "preconditions": {
362
+ "type": "array",
363
+ "description": "Conditions that must be true before this contract executes.",
364
+ "items": {
365
+ "type": "string"
366
+ }
367
+ },
368
+ "postconditions": {
369
+ "type": "array",
370
+ "description": "Conditions that must be true after this contract completes.",
371
+ "items": {
372
+ "type": "string"
373
+ }
374
+ },
375
+ "teamBoundary": {
376
+ "type": "object",
377
+ "description": "Whether this handoff crosses a team boundary and what approval is needed.",
378
+ "additionalProperties": false,
379
+ "properties": {
380
+ "crosses": {
381
+ "type": "boolean",
382
+ "description": "Whether this contract crosses a team boundary."
383
+ },
384
+ "producerTeam": {
385
+ "type": "string",
386
+ "description": "Team id of the producer."
387
+ },
388
+ "consumerTeam": {
389
+ "type": "string",
390
+ "description": "Team id of the consumer."
391
+ },
392
+ "requiresApprovalFrom": {
393
+ "type": "array",
394
+ "description": "Team ids that must approve this cross-team handoff.",
395
+ "items": {
396
+ "type": "string"
397
+ }
398
+ }
399
+ }
400
+ },
401
+ "description": {
402
+ "type": "string",
403
+ "description": "Human-readable description of this contract."
404
+ },
405
+ "skillHints": {
406
+ "type": "array",
407
+ "description": "Optional routing hints — skill ids that inform dispatch context. Producer/consumer ids remain authoritative.",
408
+ "items": {
409
+ "type": "string",
410
+ "minLength": 1
411
+ },
412
+ "maxItems": 12
413
+ }
414
+ }
415
+ },
416
+ "policy": {
417
+ "type": "object",
418
+ "description": "Governance policy enforcing team decision rights, approval requirements, and gates.",
419
+ "required": ["id", "owner"],
420
+ "additionalProperties": false,
421
+ "properties": {
422
+ "id": {
423
+ "type": "string",
424
+ "pattern": "^[a-z][a-z0-9-]{1,50}$",
425
+ "description": "Unique policy identifier (e.g., release-gates, security-approval, design-approval)."
426
+ },
427
+ "owner": {
428
+ "type": "string",
429
+ "pattern": "^[a-z][a-z0-9-]{1,40}$",
430
+ "description": "Team id that owns and enforces this policy."
431
+ },
432
+ "description": {
433
+ "type": "string",
434
+ "description": "Human-readable description of what this policy enforces."
435
+ },
436
+ "enforcement": {
437
+ "type": "string",
438
+ "enum": ["hard", "soft"],
439
+ "description": "hard = blocks execution, soft = warns but allows."
440
+ },
441
+ "mode": {
442
+ "type": "string",
443
+ "enum": ["approval", "veto", "audit", "escalation"],
444
+ "description": "How this policy is enforced: approval (must approve), veto (can block), audit (log only), escalation (route upward)."
445
+ },
446
+ "requiresApprovalFrom": {
447
+ "type": "array",
448
+ "description": "Team ids that must approve before execution.",
449
+ "items": {
450
+ "type": "string"
451
+ }
452
+ },
453
+ "mayVetoFrom": {
454
+ "type": "array",
455
+ "description": "Team ids that can veto this decision.",
456
+ "items": {
457
+ "type": "string"
458
+ }
459
+ },
460
+ "escalatesTo": {
461
+ "type": "array",
462
+ "description": "Team ids to escalate to if blocked or disputed.",
463
+ "items": {
464
+ "type": "string"
465
+ }
466
+ },
467
+ "decisionRights": {
468
+ "type": "array",
469
+ "description": "Decisions this policy governs (e.g., deployment, scope-change, security-approval).",
470
+ "items": {
471
+ "type": "string"
472
+ }
473
+ },
474
+ "conditions": {
475
+ "type": "array",
476
+ "description": "Conditions under which this policy applies.",
477
+ "items": {
478
+ "type": "string"
479
+ }
480
+ },
481
+ "evidence": {
482
+ "type": "array",
483
+ "description": "References to source documents or decisions justifying this policy.",
484
+ "items": {
485
+ "type": "string"
486
+ }
487
+ }
488
+ }
489
+ }
490
+ },
491
+ "allOf": [
492
+ {
493
+ "description": "Validate that every specialist declares exactly one team, and that team exists.",
494
+ "not": {
495
+ "required": ["_validateSpecialistTeams"],
496
+ "properties": {
497
+ "_validateSpecialistTeams": {
498
+ "const": false
499
+ }
500
+ }
501
+ }
502
+ },
503
+ {
504
+ "description": "Validate that every team has at least one specialist assigned to it.",
505
+ "not": {
506
+ "required": ["_validateTeamAssignment"],
507
+ "properties": {
508
+ "_validateTeamAssignment": {
509
+ "const": false
510
+ }
511
+ }
512
+ }
513
+ },
514
+ {
515
+ "description": "Validate that every team owner is a role, and that role has at least one specialist.",
516
+ "not": {
517
+ "required": ["_validateTeamOwner"],
518
+ "properties": {
519
+ "_validateTeamOwner": {
520
+ "const": false
521
+ }
522
+ }
523
+ }
524
+ },
525
+ {
526
+ "description": "Validate that every contract producer and consumer exist in the specialists map.",
527
+ "not": {
528
+ "required": ["_validateContractSpecialists"],
529
+ "properties": {
530
+ "_validateContractSpecialists": {
531
+ "const": false
532
+ }
533
+ }
534
+ }
535
+ },
536
+ {
537
+ "description": "Validate that no specialist names collide across teams.",
538
+ "not": {
539
+ "required": ["_validateSpecialistNames"],
540
+ "properties": {
541
+ "_validateSpecialistNames": {
542
+ "const": false
543
+ }
544
+ }
545
+ }
546
+ }
547
+ ]
548
+ }