mdkg 0.3.9 → 0.4.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema_version": 1,
3
3
  "tool": "mdkg",
4
- "package_version": "0.3.9",
4
+ "package_version": "0.4.1",
5
5
  "source": {
6
6
  "help_targets": "scripts/cli_help_targets.js",
7
7
  "command_matrix": "CLI_COMMAND_MATRIX.md"
@@ -5230,12 +5230,24 @@
5230
5230
  "required": false,
5231
5231
  "description": "--parent --prev --next --relates --blocked-by --blocks"
5232
5232
  },
5233
+ {
5234
+ "name": "--contract-profile",
5235
+ "value": "<name>",
5236
+ "required": false,
5237
+ "description": "--contract-profile <name> Optional MANIFEST/WORK/WORK_ORDER/RECEIPT validation profile metadata"
5238
+ },
5233
5239
  {
5234
5240
  "name": "--epic",
5235
5241
  "value": "<id>",
5236
5242
  "required": false,
5237
5243
  "description": "--epic <id> Epic id"
5238
5244
  },
5245
+ {
5246
+ "name": "--evidence-policy-ref",
5247
+ "value": "<ref>",
5248
+ "required": false,
5249
+ "description": "--evidence-policy-ref <ref> Optional MANIFEST/WORK_ORDER/RECEIPT evidence policy ref"
5250
+ },
5239
5251
  {
5240
5252
  "name": "--help",
5241
5253
  "value": null,
@@ -5278,6 +5290,18 @@
5278
5290
  "required": false,
5279
5291
  "description": "--priority <0..9> Work item priority"
5280
5292
  },
5293
+ {
5294
+ "name": "--receipt-kind",
5295
+ "value": "<kind>",
5296
+ "required": false,
5297
+ "description": "--receipt-kind <kind> Optional RECEIPT kind metadata"
5298
+ },
5299
+ {
5300
+ "name": "--redaction-class",
5301
+ "value": "<class>",
5302
+ "required": false,
5303
+ "description": "--redaction-class <class> Optional RECEIPT redaction class metadata"
5304
+ },
5281
5305
  {
5282
5306
  "name": "--refs",
5283
5307
  "value": null,
@@ -5326,6 +5350,12 @@
5326
5350
  "required": false,
5327
5351
  "description": "--template <set> Template set"
5328
5352
  },
5353
+ {
5354
+ "name": "--validation-policy-ref",
5355
+ "value": "<ref>",
5356
+ "required": false,
5357
+ "description": "--validation-policy-ref <ref> Optional MANIFEST/WORK_ORDER/RECEIPT validation policy ref"
5358
+ },
5329
5359
  {
5330
5360
  "name": "--version",
5331
5361
  "value": null,
@@ -8242,7 +8272,7 @@
8242
8272
  "visibility": "public",
8243
8273
  "summary": "mdkg validate command",
8244
8274
  "usage": [
8245
- " mdkg validate [--out <path>] [--json-out <path>] [--quiet] [--changed-only] [--summary] [--limit <n>] [--json]"
8275
+ " mdkg validate [--out <path>] [--json-out <path>] [--quiet] [--changed-only] [--summary] [--limit <n>] [--profile <name>] [--json]"
8246
8276
  ],
8247
8277
  "args": [],
8248
8278
  "flags": [
@@ -8276,6 +8306,12 @@
8276
8306
  "required": false,
8277
8307
  "description": "--out writes the compatibility text report; --json-out writes a clean full JSON receipt."
8278
8308
  },
8309
+ {
8310
+ "name": "--profile",
8311
+ "value": "omni-room",
8312
+ "required": false,
8313
+ "description": "--profile omni-room applies explicit contract-profile validation after generic validation; this is separate from mdkg pack --profile."
8314
+ },
8279
8315
  {
8280
8316
  "name": "--root",
8281
8317
  "value": null,
@@ -8326,7 +8362,7 @@
8326
8362
  }
8327
8363
  ],
8328
8364
  "examples": [
8329
- " mdkg validate [--out <path>] [--json-out <path>] [--quiet] [--changed-only] [--summary] [--limit <n>] [--json]"
8365
+ " mdkg validate [--out <path>] [--json-out <path>] [--quiet] [--changed-only] [--summary] [--limit <n>] [--profile <name>] [--json]"
8330
8366
  ],
8331
8367
  "docs": {
8332
8368
  "help_target": "mdkg help validate",
@@ -8348,7 +8384,7 @@
8348
8384
  " mdkg work order new|status|update ...",
8349
8385
  " mdkg work receipt new|verify|update ...",
8350
8386
  " mdkg work artifact add ...",
8351
- " mdkg work validate [<id-or-qid>] [--type <workflow-type>] [--json]"
8387
+ " mdkg work validate [<id-or-qid>] [--type <workflow-type>] [--profile <name>] [--json]"
8352
8388
  ],
8353
8389
  "args": [
8354
8390
  {
@@ -8528,7 +8564,7 @@
8528
8564
  "visibility": "public",
8529
8565
  "summary": "mdkg work contract command",
8530
8566
  "usage": [
8531
- " mdkg work contract new \"<title>\" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--required-capabilities <...>] [--pricing-model <...>] [--json]"
8567
+ " mdkg work contract new \"<title>\" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--contract-profile <name>] [--required-capabilities <...>] [--pricing-model <...>] [--json]"
8532
8568
  ],
8533
8569
  "args": [
8534
8570
  {
@@ -8542,7 +8578,7 @@
8542
8578
  "name": "--agent-id",
8543
8579
  "value": "<agent.id>",
8544
8580
  "required": false,
8545
- "description": "mdkg work contract new \"<title>\" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--required-capabilities <...>] [--pricing-model <...>] [--json]"
8581
+ "description": "mdkg work contract new \"<title>\" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--contract-profile <name>] [--required-capabilities <...>] [--pricing-model <...>] [--json]"
8546
8582
  },
8547
8583
  {
8548
8584
  "name": "--help",
@@ -8554,25 +8590,25 @@
8554
8590
  "name": "--id",
8555
8591
  "value": "<work.id>",
8556
8592
  "required": false,
8557
- "description": "mdkg work contract new \"<title>\" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--required-capabilities <...>] [--pricing-model <...>] [--json]"
8593
+ "description": "mdkg work contract new \"<title>\" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--contract-profile <name>] [--required-capabilities <...>] [--pricing-model <...>] [--json]"
8558
8594
  },
8559
8595
  {
8560
8596
  "name": "--inputs",
8561
8597
  "value": "<...>",
8562
8598
  "required": false,
8563
- "description": "mdkg work contract new \"<title>\" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--required-capabilities <...>] [--pricing-model <...>] [--json]"
8599
+ "description": "mdkg work contract new \"<title>\" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--contract-profile <name>] [--required-capabilities <...>] [--pricing-model <...>] [--json]"
8564
8600
  },
8565
8601
  {
8566
8602
  "name": "--kind",
8567
8603
  "value": "<kind>",
8568
8604
  "required": false,
8569
- "description": "mdkg work contract new \"<title>\" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--required-capabilities <...>] [--pricing-model <...>] [--json]"
8605
+ "description": "mdkg work contract new \"<title>\" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--contract-profile <name>] [--required-capabilities <...>] [--pricing-model <...>] [--json]"
8570
8606
  },
8571
8607
  {
8572
8608
  "name": "--outputs",
8573
8609
  "value": "<...>",
8574
8610
  "required": false,
8575
- "description": "mdkg work contract new \"<title>\" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--required-capabilities <...>] [--pricing-model <...>] [--json]"
8611
+ "description": "mdkg work contract new \"<title>\" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--contract-profile <name>] [--required-capabilities <...>] [--pricing-model <...>] [--json]"
8576
8612
  },
8577
8613
  {
8578
8614
  "name": "--root",
@@ -8623,7 +8659,7 @@
8623
8659
  }
8624
8660
  ],
8625
8661
  "examples": [
8626
- " mdkg work contract new \"<title>\" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--required-capabilities <...>] [--pricing-model <...>] [--json]"
8662
+ " mdkg work contract new \"<title>\" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--contract-profile <name>] [--required-capabilities <...>] [--pricing-model <...>] [--json]"
8627
8663
  ],
8628
8664
  "docs": {
8629
8665
  "help_target": "mdkg help work contract",
@@ -8641,7 +8677,7 @@
8641
8677
  "visibility": "public",
8642
8678
  "summary": "mdkg work order command",
8643
8679
  "usage": [
8644
- " mdkg work order new \"<title>\" --id <order.id> --work-id <work.id> --requester <ref> [--request-ref <ref>] [--trigger-ref <ref>] [--payload-hash <sha256:...>] [--input-refs <...>] [--queue-refs <...>] [--requested-outputs <...>] [--json]",
8680
+ " mdkg work order new \"<title>\" --id <order.id> --work-id <work.id> --requester <ref> [--contract-profile <name>] [--validation-policy-ref <ref>] [--evidence-policy-ref <ref>] [--request-ref <ref>] [--trigger-ref <ref>] [--payload-hash <sha256:...>] [--input-refs <...>] [--queue-refs <...>] [--requested-outputs <...>] [--json]",
8645
8681
  " mdkg work order status <id-or-qid> [--json]",
8646
8682
  " mdkg work order update <id-or-qid> [--status <status>] [--add-input-refs <...>] [--add-queue-refs <...>] [--add-artifacts <...>] [--json]"
8647
8683
  ],
@@ -8668,13 +8704,13 @@
8668
8704
  "name": "--id",
8669
8705
  "value": "<order.id>",
8670
8706
  "required": false,
8671
- "description": "mdkg work order new \"<title>\" --id <order.id> --work-id <work.id> --requester <ref> [--request-ref <ref>] [--trigger-ref <ref>] [--payload-hash <sha256:...>] [--input-refs <...>] [--queue-refs <...>] [--requested-outputs <...>] [--json]"
8707
+ "description": "mdkg work order new \"<title>\" --id <order.id> --work-id <work.id> --requester <ref> [--contract-profile <name>] [--validation-policy-ref <ref>] [--evidence-policy-ref <ref>] [--request-ref <ref>] [--trigger-ref <ref>] [--payload-hash <sha256:...>] [--input-refs <...>] [--queue-refs <...>] [--requested-outputs <...>] [--json]"
8672
8708
  },
8673
8709
  {
8674
8710
  "name": "--requester",
8675
8711
  "value": "<ref>",
8676
8712
  "required": false,
8677
- "description": "mdkg work order new \"<title>\" --id <order.id> --work-id <work.id> --requester <ref> [--request-ref <ref>] [--trigger-ref <ref>] [--payload-hash <sha256:...>] [--input-refs <...>] [--queue-refs <...>] [--requested-outputs <...>] [--json]"
8713
+ "description": "mdkg work order new \"<title>\" --id <order.id> --work-id <work.id> --requester <ref> [--contract-profile <name>] [--validation-policy-ref <ref>] [--evidence-policy-ref <ref>] [--request-ref <ref>] [--trigger-ref <ref>] [--payload-hash <sha256:...>] [--input-refs <...>] [--queue-refs <...>] [--requested-outputs <...>] [--json]"
8678
8714
  },
8679
8715
  {
8680
8716
  "name": "--root",
@@ -8692,7 +8728,7 @@
8692
8728
  "name": "--work-id",
8693
8729
  "value": "<work.id>",
8694
8730
  "required": false,
8695
- "description": "mdkg work order new \"<title>\" --id <order.id> --work-id <work.id> --requester <ref> [--request-ref <ref>] [--trigger-ref <ref>] [--payload-hash <sha256:...>] [--input-refs <...>] [--queue-refs <...>] [--requested-outputs <...>] [--json]"
8731
+ "description": "mdkg work order new \"<title>\" --id <order.id> --work-id <work.id> --requester <ref> [--contract-profile <name>] [--validation-policy-ref <ref>] [--evidence-policy-ref <ref>] [--request-ref <ref>] [--trigger-ref <ref>] [--payload-hash <sha256:...>] [--input-refs <...>] [--queue-refs <...>] [--requested-outputs <...>] [--json]"
8696
8732
  }
8697
8733
  ],
8698
8734
  "output_formats": [
@@ -8726,7 +8762,7 @@
8726
8762
  }
8727
8763
  ],
8728
8764
  "examples": [
8729
- " mdkg work order new \"<title>\" --id <order.id> --work-id <work.id> --requester <ref> [--request-ref <ref>] [--trigger-ref <ref>] [--payload-hash <sha256:...>] [--input-refs <...>] [--queue-refs <...>] [--requested-outputs <...>] [--json]",
8765
+ " mdkg work order new \"<title>\" --id <order.id> --work-id <work.id> --requester <ref> [--contract-profile <name>] [--validation-policy-ref <ref>] [--evidence-policy-ref <ref>] [--request-ref <ref>] [--trigger-ref <ref>] [--payload-hash <sha256:...>] [--input-refs <...>] [--queue-refs <...>] [--requested-outputs <...>] [--json]",
8730
8766
  " mdkg work order status <id-or-qid> [--json]",
8731
8767
  " mdkg work order update <id-or-qid> [--status <status>] [--add-input-refs <...>] [--add-queue-refs <...>] [--add-artifacts <...>] [--json]"
8732
8768
  ],
@@ -8746,7 +8782,7 @@
8746
8782
  "visibility": "public",
8747
8783
  "summary": "mdkg work receipt command",
8748
8784
  "usage": [
8749
- " mdkg work receipt new \"<title>\" --id <receipt.id> --work-order-id <order.id> --outcome success|partial|failure [--receipt-status recorded|verified|rejected|superseded] [--redaction-policy refs_and_hashes_only|redacted_summary|external_private] [--evidence-hashes <sha256:...>] [--json]",
8785
+ " mdkg work receipt new \"<title>\" --id <receipt.id> --work-order-id <order.id> --outcome success|partial|failure [--receipt-status recorded|verified|rejected|superseded] [--redaction-policy refs_and_hashes_only|redacted_summary|external_private] [--contract-profile <name>] [--receipt-kind <kind>] [--redaction-class <class>] [--validation-policy-ref <ref>] [--evidence-policy-ref <ref>] [--evidence-hashes <sha256:...>] [--json]",
8750
8786
  " mdkg work receipt verify <id-or-qid> [--json]",
8751
8787
  " mdkg work receipt update <id-or-qid> [--receipt-status <status>] [--add-artifacts <...>] [--add-proof-refs <...>] [--add-attestation-refs <...>] [--add-evidence-hashes <sha256:...>] [--json]"
8752
8788
  ],
@@ -8773,13 +8809,13 @@
8773
8809
  "name": "--id",
8774
8810
  "value": "<receipt.id>",
8775
8811
  "required": false,
8776
- "description": "mdkg work receipt new \"<title>\" --id <receipt.id> --work-order-id <order.id> --outcome success|partial|failure [--receipt-status recorded|verified|rejected|superseded] [--redaction-policy refs_and_hashes_only|redacted_summary|external_private] [--evidence-hashes <sha256:...>] [--json]"
8812
+ "description": "mdkg work receipt new \"<title>\" --id <receipt.id> --work-order-id <order.id> --outcome success|partial|failure [--receipt-status recorded|verified|rejected|superseded] [--redaction-policy refs_and_hashes_only|redacted_summary|external_private] [--contract-profile <name>] [--receipt-kind <kind>] [--redaction-class <class>] [--validation-policy-ref <ref>] [--evidence-policy-ref <ref>] [--evidence-hashes <sha256:...>] [--json]"
8777
8813
  },
8778
8814
  {
8779
8815
  "name": "--outcome",
8780
8816
  "value": "success|partial|failure",
8781
8817
  "required": false,
8782
- "description": "mdkg work receipt new \"<title>\" --id <receipt.id> --work-order-id <order.id> --outcome success|partial|failure [--receipt-status recorded|verified|rejected|superseded] [--redaction-policy refs_and_hashes_only|redacted_summary|external_private] [--evidence-hashes <sha256:...>] [--json]"
8818
+ "description": "mdkg work receipt new \"<title>\" --id <receipt.id> --work-order-id <order.id> --outcome success|partial|failure [--receipt-status recorded|verified|rejected|superseded] [--redaction-policy refs_and_hashes_only|redacted_summary|external_private] [--contract-profile <name>] [--receipt-kind <kind>] [--redaction-class <class>] [--validation-policy-ref <ref>] [--evidence-policy-ref <ref>] [--evidence-hashes <sha256:...>] [--json]"
8783
8819
  },
8784
8820
  {
8785
8821
  "name": "--root",
@@ -8797,7 +8833,7 @@
8797
8833
  "name": "--work-order-id",
8798
8834
  "value": "<order.id>",
8799
8835
  "required": false,
8800
- "description": "mdkg work receipt new \"<title>\" --id <receipt.id> --work-order-id <order.id> --outcome success|partial|failure [--receipt-status recorded|verified|rejected|superseded] [--redaction-policy refs_and_hashes_only|redacted_summary|external_private] [--evidence-hashes <sha256:...>] [--json]"
8836
+ "description": "mdkg work receipt new \"<title>\" --id <receipt.id> --work-order-id <order.id> --outcome success|partial|failure [--receipt-status recorded|verified|rejected|superseded] [--redaction-policy refs_and_hashes_only|redacted_summary|external_private] [--contract-profile <name>] [--receipt-kind <kind>] [--redaction-class <class>] [--validation-policy-ref <ref>] [--evidence-policy-ref <ref>] [--evidence-hashes <sha256:...>] [--json]"
8801
8837
  }
8802
8838
  ],
8803
8839
  "output_formats": [
@@ -8837,7 +8873,7 @@
8837
8873
  }
8838
8874
  ],
8839
8875
  "examples": [
8840
- " mdkg work receipt new \"<title>\" --id <receipt.id> --work-order-id <order.id> --outcome success|partial|failure [--receipt-status recorded|verified|rejected|superseded] [--redaction-policy refs_and_hashes_only|redacted_summary|external_private] [--evidence-hashes <sha256:...>] [--json]",
8876
+ " mdkg work receipt new \"<title>\" --id <receipt.id> --work-order-id <order.id> --outcome success|partial|failure [--receipt-status recorded|verified|rejected|superseded] [--redaction-policy refs_and_hashes_only|redacted_summary|external_private] [--contract-profile <name>] [--receipt-kind <kind>] [--redaction-class <class>] [--validation-policy-ref <ref>] [--evidence-policy-ref <ref>] [--evidence-hashes <sha256:...>] [--json]",
8841
8877
  " mdkg work receipt update <id-or-qid> [--receipt-status <status>] [--add-artifacts <...>] [--add-proof-refs <...>] [--add-attestation-refs <...>] [--add-evidence-hashes <sha256:...>] [--json]",
8842
8878
  " mdkg work receipt verify <id-or-qid> [--json]"
8843
8879
  ],
@@ -8964,7 +9000,7 @@
8964
9000
  "visibility": "public",
8965
9001
  "summary": "mdkg work validate command",
8966
9002
  "usage": [
8967
- " mdkg work validate [<id-or-qid>] [--type manifest|spec|work|work_order|receipt|feedback|dispute|proposal] [--json]"
9003
+ " mdkg work validate [<id-or-qid>] [--type manifest|spec|work|work_order|receipt|feedback|dispute|proposal] [--profile <name>] [--json]"
8968
9004
  ],
8969
9005
  "args": [
8970
9006
  {
@@ -8980,6 +9016,12 @@
8980
9016
  "required": false,
8981
9017
  "description": "--help, -h Show help"
8982
9018
  },
9019
+ {
9020
+ "name": "--profile",
9021
+ "value": "omni-room",
9022
+ "required": false,
9023
+ "description": "--profile omni-room applies explicit contract-profile validation after generic mirror validation; this is separate from mdkg pack --profile."
9024
+ },
8983
9025
  {
8984
9026
  "name": "--root",
8985
9027
  "value": null,
@@ -9026,7 +9068,7 @@
9026
9068
  }
9027
9069
  ],
9028
9070
  "examples": [
9029
- " mdkg work validate [<id-or-qid>] [--type manifest|spec|work|work_order|receipt|feedback|dispute|proposal] [--json]"
9071
+ " mdkg work validate [<id-or-qid>] [--type manifest|spec|work|work_order|receipt|feedback|dispute|proposal] [--profile <name>] [--json]"
9030
9072
  ],
9031
9073
  "docs": {
9032
9074
  "help_target": "mdkg help work validate",
@@ -9128,5 +9170,5 @@
9128
9170
  }
9129
9171
  }
9130
9172
  ],
9131
- "contract_hash": "3c13c572c740f1e40db33fa5867fa227a8347df0750ef3beb0696d5931761a6c"
9173
+ "contract_hash": "65408d40dd065dfadcaa9bfe3626df5703dce2fe08ce1dd500e371899a8c4f7a"
9132
9174
  }
@@ -12,6 +12,7 @@ const node_1 = require("../graph/node");
12
12
  const agent_file_types_1 = require("../graph/agent_file_types");
13
13
  const indexer_1 = require("../graph/indexer");
14
14
  const loader_1 = require("../templates/loader");
15
+ const frontmatter_1 = require("../graph/frontmatter");
15
16
  const date_1 = require("../util/date");
16
17
  const errors_1 = require("../util/errors");
17
18
  const qid_1 = require("../util/qid");
@@ -25,6 +26,7 @@ const event_support_1 = require("./event_support");
25
26
  const DEC_ID_RE = /^dec-[0-9]+$/;
26
27
  const DEC_STATUS = new Set(["proposed", "accepted", "rejected", "superseded"]);
27
28
  const SKILL_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
29
+ const CONTRACT_METADATA_RE = /^[a-z][a-z0-9_]*(?:-[a-z0-9_]+)*$/;
28
30
  const CORE_TYPES = new Set(["rule"]);
29
31
  const DESIGN_TYPES = new Set(["prd", "edd", "dec", "prop"]);
30
32
  const LEGACY_NEW_SPEC_WARNING = "warning: mdkg new spec is legacy; use mdkg new manifest. This alias creates MANIFEST.md with type: manifest during the compatibility release.";
@@ -77,6 +79,16 @@ function normalizeRef(value, key) {
77
79
  function normalizeRefList(raw, key) {
78
80
  return parseCsvList(raw).map((value) => normalizeRef(value, key));
79
81
  }
82
+ function normalizeContractMetadataToken(raw, key) {
83
+ if (raw === undefined) {
84
+ return undefined;
85
+ }
86
+ const normalized = raw.toLowerCase();
87
+ if (!CONTRACT_METADATA_RE.test(normalized)) {
88
+ throw new errors_1.UsageError(`${key} must be lowercase snake/kebab style`);
89
+ }
90
+ return normalized;
91
+ }
80
92
  function normalizeIdRefList(raw, key) {
81
93
  return parseCsvList(raw).map((value) => normalizeIdRef(value, key));
82
94
  }
@@ -176,6 +188,18 @@ function ensureExists(index, value, ws, label) {
176
188
  throw new errors_1.UsageError(`${label} cannot target read-only subgraph node ${node.qid}`);
177
189
  }
178
190
  }
191
+ function mergeRenderedFrontmatter(content, filePath, additions) {
192
+ const entries = Object.entries(additions).filter((entry) => entry[1] !== undefined);
193
+ if (entries.length === 0) {
194
+ return content;
195
+ }
196
+ const { frontmatter, body } = (0, frontmatter_1.parseFrontmatter)(content, filePath);
197
+ for (const [key, value] of entries) {
198
+ frontmatter[key] = value;
199
+ }
200
+ const lines = ["---", ...(0, frontmatter_1.formatFrontmatter)(frontmatter), "---", body.trimStart()];
201
+ return lines.join("\n").endsWith("\n") ? lines.join("\n") : `${lines.join("\n")}\n`;
202
+ }
179
203
  function runNewCommandLocked(options) {
180
204
  const title = options.title.trim();
181
205
  if (!title) {
@@ -274,6 +298,24 @@ function runNewCommandLocked(options) {
274
298
  if (options.cases && type !== "test") {
275
299
  throw new errors_1.UsageError("--cases is only valid for test nodes");
276
300
  }
301
+ const contractProfile = normalizeContractMetadataToken(options.contractProfile, "--contract-profile");
302
+ const validationPolicyRef = options.validationPolicyRef
303
+ ? normalizeRef(options.validationPolicyRef, "--validation-policy-ref")
304
+ : undefined;
305
+ const evidencePolicyRef = options.evidencePolicyRef
306
+ ? normalizeRef(options.evidencePolicyRef, "--evidence-policy-ref")
307
+ : undefined;
308
+ const receiptKind = normalizeContractMetadataToken(options.receiptKind, "--receipt-kind");
309
+ const redactionClass = normalizeContractMetadataToken(options.redactionClass, "--redaction-class");
310
+ if (contractProfile && !["manifest", "work", "work_order", "receipt"].includes(type)) {
311
+ throw new errors_1.UsageError("--contract-profile is only valid for manifest, work, work_order, and receipt");
312
+ }
313
+ if ((validationPolicyRef || evidencePolicyRef) && !["manifest", "work_order", "receipt"].includes(type)) {
314
+ throw new errors_1.UsageError("--validation-policy-ref and --evidence-policy-ref are only valid for manifest, work_order, and receipt");
315
+ }
316
+ if ((receiptKind || redactionClass) && type !== "receipt") {
317
+ throw new errors_1.UsageError("--receipt-kind and --redaction-class are only valid for receipt");
318
+ }
277
319
  const epic = options.epic ? normalizeIdRef(options.epic, "--epic") : undefined;
278
320
  const parent = options.parent ? normalizeIdRef(options.parent, "--parent") : undefined;
279
321
  const prev = options.prev ? normalizeIdRef(options.prev, "--prev") : undefined;
@@ -331,7 +373,7 @@ function runNewCommandLocked(options) {
331
373
  if (template.source === "bundled") {
332
374
  console.error(`warning: using bundled template fallback for ${type}; run \`mdkg upgrade --apply\` to vendor missing local templates`);
333
375
  }
334
- const content = (0, loader_1.renderTemplate)(template, {
376
+ const renderedContent = (0, loader_1.renderTemplate)(template, {
335
377
  id,
336
378
  type,
337
379
  title,
@@ -360,6 +402,13 @@ function runNewCommandLocked(options) {
360
402
  created: today,
361
403
  updated: today,
362
404
  });
405
+ const content = mergeRenderedFrontmatter(renderedContent, filePath, {
406
+ contract_profile: contractProfile,
407
+ validation_policy_ref: validationPolicyRef,
408
+ evidence_policy_ref: evidencePolicyRef,
409
+ receipt_kind: receiptKind,
410
+ redaction_class: redactionClass,
411
+ });
363
412
  try {
364
413
  (0, atomic_1.writeFileExclusive)(filePath, content);
365
414
  }
@@ -21,6 +21,7 @@ const visibility_1 = require("../graph/visibility");
21
21
  const sqlite_index_1 = require("../graph/sqlite_index");
22
22
  const errors_1 = require("../util/errors");
23
23
  const skill_mirror_1 = require("./skill_mirror");
24
+ const VALIDATION_PROFILES = new Set(["omni-room"]);
24
25
  exports.RECOMMENDED_HEADINGS = {
25
26
  task: [
26
27
  "Overview",
@@ -143,6 +144,69 @@ function collectManifestCompatibilityWarnings(qid, filePath, node) {
143
144
  }
144
145
  return [];
145
146
  }
147
+ function collectContractProfileWarnings(qid, node) {
148
+ if (!(0, agent_file_types_1.isAgentFileType)(node.type)) {
149
+ return [];
150
+ }
151
+ const warnings = [];
152
+ if (node.frontmatter.profile !== undefined) {
153
+ warnings.push(`${qid}: contract-profile.ambiguous-field warning: profile is ambiguous and is not a supported alias; use contract_profile for mdkg contract surfaces`);
154
+ }
155
+ const contractProfile = node.frontmatter.contract_profile;
156
+ if (typeof contractProfile === "string" && !agent_file_types_1.KNOWN_CONTRACT_PROFILES.has(contractProfile)) {
157
+ warnings.push(`${qid}: contract-profile.unknown warning: unknown contract_profile ${contractProfile}; generic validation accepts well-shaped values, but explicit profile validation may reject it`);
158
+ }
159
+ if (node.type === "receipt") {
160
+ const receiptKind = node.frontmatter.receipt_kind;
161
+ if (typeof receiptKind === "string" && !agent_file_types_1.KNOWN_RECEIPT_KINDS.has(receiptKind)) {
162
+ warnings.push(`${qid}: receipt-kind.unknown warning: unknown receipt_kind ${receiptKind}; generic validation accepts well-shaped values, but explicit profile validation may reject it`);
163
+ }
164
+ const redactionClass = node.frontmatter.redaction_class;
165
+ if (typeof redactionClass === "string" && !agent_file_types_1.KNOWN_REDACTION_CLASSES.has(redactionClass)) {
166
+ warnings.push(`${qid}: redaction-class.unknown warning: unknown redaction_class ${redactionClass}; generic validation accepts well-shaped values, but explicit profile validation may reject it`);
167
+ }
168
+ if (typeof redactionClass === "string" && node.frontmatter.redaction_policy === undefined) {
169
+ warnings.push(`${qid}: redaction-class.missing-policy warning: redaction_class should be paired with redaction_policy so receipt handling and sensitivity are both explicit`);
170
+ }
171
+ }
172
+ return warnings;
173
+ }
174
+ function normalizeValidationProfile(profile) {
175
+ if (profile === undefined) {
176
+ return undefined;
177
+ }
178
+ if (!VALIDATION_PROFILES.has(profile)) {
179
+ throw new errors_1.UsageError("--profile must be one of omni-room");
180
+ }
181
+ return profile;
182
+ }
183
+ function collectContractProfileErrors(qid, node, profile) {
184
+ if (!(0, agent_file_types_1.isAgentFileType)(node.type)) {
185
+ return [];
186
+ }
187
+ const errors = [];
188
+ if (node.frontmatter.profile !== undefined) {
189
+ errors.push(`${qid}: contract-profile.ambiguous-field error: profile is ambiguous and is not a supported alias; use contract_profile for ${profile} validation`);
190
+ }
191
+ const contractProfile = node.frontmatter.contract_profile;
192
+ if (typeof contractProfile === "string" && contractProfile !== profile) {
193
+ errors.push(`${qid}: contract-profile.incompatible error: contract_profile ${contractProfile} is incompatible with validation profile ${profile}`);
194
+ }
195
+ if (node.type === "receipt") {
196
+ const receiptKind = node.frontmatter.receipt_kind;
197
+ if (typeof receiptKind === "string" && !agent_file_types_1.KNOWN_RECEIPT_KINDS.has(receiptKind)) {
198
+ errors.push(`${qid}: receipt-kind.incompatible error: receipt_kind ${receiptKind} is incompatible with validation profile ${profile}`);
199
+ }
200
+ const redactionClass = node.frontmatter.redaction_class;
201
+ if (typeof redactionClass === "string" && !agent_file_types_1.KNOWN_REDACTION_CLASSES.has(redactionClass)) {
202
+ errors.push(`${qid}: redaction-class.incompatible error: redaction_class ${redactionClass} is incompatible with validation profile ${profile}`);
203
+ }
204
+ if (typeof redactionClass === "string" && node.frontmatter.redaction_policy === undefined) {
205
+ errors.push(`${qid}: redaction-class.missing-policy error: redaction_class requires redaction_policy for validation profile ${profile}`);
206
+ }
207
+ }
208
+ return errors;
209
+ }
146
210
  function collectChangedPaths(root) {
147
211
  const result = (0, child_process_1.spawnSync)("git", ["-C", root, "status", "--porcelain", "--", ".mdkg"], {
148
212
  encoding: "utf8",
@@ -234,6 +298,20 @@ function warningDiagnostic(message, nodes) {
234
298
  remediation: "Rename legacy SPEC.md files to MANIFEST.md and update transitional type: spec frontmatter to type: manifest before the compatibility release closes.",
235
299
  };
236
300
  }
301
+ const contractProfileMatch = /(contract-profile|receipt-kind|redaction-class)\.([a-z-]+)/.exec(message);
302
+ if (contractProfileMatch) {
303
+ return {
304
+ id: `${contractProfileMatch[1]}.${contractProfileMatch[2]}`,
305
+ category: "contract-profile",
306
+ severity: "warning",
307
+ message,
308
+ qid,
309
+ node_type: nodeType,
310
+ path: pathValue,
311
+ ref: qid,
312
+ remediation: "Use contract_profile and explicit policy/kind/class fields only when they are intentional generic mdkg contract metadata.",
313
+ };
314
+ }
237
315
  if (message.includes("sqlite") || message.includes("index")) {
238
316
  return {
239
317
  id: "cache.index",
@@ -485,6 +563,7 @@ function validateEventsJsonl(root, config, errors) {
485
563
  }
486
564
  }
487
565
  function collectValidateReceipt(options) {
566
+ const validationProfile = normalizeValidationProfile(options.profile);
488
567
  const config = (0, config_1.loadConfig)(options.root);
489
568
  const templateSchemaInfo = (0, template_schema_1.loadTemplateSchemasWithInfo)(options.root, config, node_1.ALLOWED_TYPES);
490
569
  const templateSchemas = templateSchemaInfo.schemas;
@@ -543,6 +622,10 @@ function collectValidateReceipt(options) {
543
622
  }
544
623
  warnings.push(...collectRawContentWarnings(qid, node));
545
624
  warnings.push(...collectManifestCompatibilityWarnings(qid, filePath, node));
625
+ warnings.push(...collectContractProfileWarnings(qid, node));
626
+ if (validationProfile) {
627
+ errors.push(...collectContractProfileErrors(qid, node, validationProfile));
628
+ }
546
629
  }
547
630
  catch (err) {
548
631
  const message = err instanceof Error ? err.message : "unknown error";
@@ -641,6 +724,7 @@ function collectValidateReceipt(options) {
641
724
  warning_diagnostics: filteredWarningDiagnostics,
642
725
  warning_summary: buildWarningSummary(filteredWarningDiagnostics),
643
726
  errors: uniqueErrors,
727
+ ...(validationProfile ? { validation_profile: validationProfile } : {}),
644
728
  ...(outPath ? { report_path: outPath } : {}),
645
729
  ...(options.changedOnly
646
730
  ? { warning_filter: { mode: "changed-only", changed_paths: Array.from(changedPaths).sort() } }
@@ -44,6 +44,7 @@ const RECEIPT_STATUSES = new Set(["recorded", "verified", "rejected", "supersede
44
44
  const OUTCOMES = new Set(["success", "partial", "failure"]);
45
45
  const REDACTION_POLICIES = new Set(["refs_and_hashes_only", "redacted_summary", "external_private"]);
46
46
  const WORKFLOW_VALIDATE_TYPES = new Set(agent_file_types_1.AGENT_FILE_TYPES);
47
+ const CONTRACT_METADATA_RE = /^[a-z][a-z0-9_]*(?:-[a-z0-9_]+)*$/;
47
48
  function parseCsvList(raw) {
48
49
  if (!raw) {
49
50
  return [];
@@ -84,6 +85,16 @@ function normalizeEnum(value, flag, allowed) {
84
85
  }
85
86
  return normalized;
86
87
  }
88
+ function normalizeContractMetadataToken(value, flag) {
89
+ if (value === undefined) {
90
+ return undefined;
91
+ }
92
+ const normalized = value.toLowerCase();
93
+ if (!CONTRACT_METADATA_RE.test(normalized)) {
94
+ throw new errors_1.UsageError(`${flag} must be lowercase snake/kebab style`);
95
+ }
96
+ return normalized;
97
+ }
87
98
  function normalizeSha256Ref(value, flag) {
88
99
  if (value === undefined) {
89
100
  return undefined;
@@ -251,6 +262,10 @@ function workflowDiagnosticCode(message) {
251
262
  if (manifestCompatMatch) {
252
263
  return `manifest.compat.${manifestCompatMatch[1]}`;
253
264
  }
265
+ const contractProfileMatch = /(contract-profile|receipt-kind|redaction-class)\.([a-z-]+)/.exec(message);
266
+ if (contractProfileMatch) {
267
+ return `${contractProfileMatch[1]}.${contractProfileMatch[2]}`;
268
+ }
254
269
  if (message.includes("references missing") || message.includes("references missing node")) {
255
270
  return "reference.missing";
256
271
  }
@@ -325,7 +340,7 @@ function buildWorkValidateReceipt(options) {
325
340
  .sort((a, b) => a.qid.localeCompare(b.qid));
326
341
  }
327
342
  const candidatePaths = workflowCandidatePaths({ root: options.root, config, ws, type, target });
328
- const validation = (0, validate_1.collectValidateReceipt)({ root: options.root });
343
+ const validation = (0, validate_1.collectValidateReceipt)({ root: options.root, profile: options.profile });
329
344
  const warnings = filterWorkflowMessages(validation.warnings, targets, candidatePaths);
330
345
  const errors = filterWorkflowMessages(validation.errors, targets, candidatePaths);
331
346
  const diagnostics = [
@@ -346,6 +361,7 @@ function buildWorkValidateReceipt(options) {
346
361
  action: "work.validate",
347
362
  ok: errors.length === 0,
348
363
  type: type ?? "all",
364
+ ...(options.profile ? { validation_profile: options.profile } : {}),
349
365
  ...(target ? { target: (0, query_output_1.toNodeSummaryJson)(target) } : {}),
350
366
  checked_count: target ? 1 : candidatePaths.filter((value) => !path_1.default.isAbsolute(value)).length,
351
367
  nodes: targets.map((node) => (0, query_output_1.toNodeSummaryJson)(node)),
@@ -625,6 +641,19 @@ function writeFrontmatterFile(filePath, frontmatter, body) {
625
641
  const content = ["---", ...lines, "---", body.trimStart()].join("\n");
626
642
  (0, atomic_1.atomicWriteFile)(filePath, content.endsWith("\n") ? content : `${content}\n`);
627
643
  }
644
+ function mergeRenderedFrontmatter(content, filePath, additions) {
645
+ const entries = Object.entries(additions).filter((entry) => entry[1] !== undefined);
646
+ if (entries.length === 0) {
647
+ return content;
648
+ }
649
+ const { frontmatter, body } = (0, frontmatter_1.parseFrontmatter)(content, filePath);
650
+ for (const [key, value] of entries) {
651
+ frontmatter[key] = value;
652
+ }
653
+ const lines = ["---", ...(0, frontmatter_1.formatFrontmatter)(frontmatter, frontmatter_1.DEFAULT_FRONTMATTER_KEY_ORDER), "---", body.trimStart()];
654
+ const merged = lines.join("\n");
655
+ return merged.endsWith("\n") ? merged : `${merged}\n`;
656
+ }
628
657
  function createAgentWorkflowNode(options) {
629
658
  const config = (0, config_1.loadConfig)(options.root);
630
659
  const ws = normalizeWorkspace(options.ws);
@@ -641,7 +670,7 @@ function createAgentWorkflowNode(options) {
641
670
  const slug = slugifyTitle(options.title);
642
671
  const filePath = path_1.default.resolve(options.root, workspace.path, workspace.mdkg_dir, "work", `${id}-${slug}`, agent_file_types_1.AGENT_FILE_BASENAMES[options.type]);
643
672
  const template = (0, loader_1.loadTemplate)(options.root, config, options.type);
644
- const content = (0, loader_1.renderTemplate)(template, {
673
+ const renderedContent = (0, loader_1.renderTemplate)(template, {
645
674
  id,
646
675
  type: options.type,
647
676
  title: options.title,
@@ -649,6 +678,7 @@ function createAgentWorkflowNode(options) {
649
678
  updated: today,
650
679
  ...options.overrides,
651
680
  });
681
+ const content = mergeRenderedFrontmatter(renderedContent, filePath, options.overrides);
652
682
  try {
653
683
  (0, atomic_1.writeFileExclusive)(filePath, content);
654
684
  }
@@ -745,6 +775,9 @@ function createWorkOrderForWork(options) {
745
775
  request_ref: requestRef,
746
776
  trigger_ref: triggerRef,
747
777
  payload_hash: payloadHash,
778
+ contract_profile: normalizeContractMetadataToken(options.contractProfile, "--contract-profile"),
779
+ validation_policy_ref: options.validationPolicyRef,
780
+ evidence_policy_ref: options.evidencePolicyRef,
748
781
  input_refs: inputRefs,
749
782
  queue_refs: queueRefs,
750
783
  requested_outputs: requestedOutputs,
@@ -766,6 +799,7 @@ function runWorkContractNewCommandLocked(options) {
766
799
  ? [agentId]
767
800
  : [];
768
801
  const requiredCapabilities = parseCsvList(options.requiredCapabilities);
802
+ const contractProfile = normalizeContractMetadataToken(options.contractProfile, "--contract-profile");
769
803
  const receipt = createAgentWorkflowNode({
770
804
  root: options.root,
771
805
  ws,
@@ -776,6 +810,7 @@ function runWorkContractNewCommandLocked(options) {
776
810
  overrides: {
777
811
  agent_id: agentId,
778
812
  kind,
813
+ contract_profile: contractProfile,
779
814
  pricing_model: normalizeEnum(options.pricingModel ?? "quoted", "--pricing-model", PRICING_MODELS),
780
815
  required_capabilities: requiredCapabilities.length > 0 ? requiredCapabilities : [kind],
781
816
  inputs: parseCsvList(options.inputs),
@@ -807,6 +842,9 @@ function runWorkOrderNewCommandLocked(options) {
807
842
  queueRefs: options.queueRefs,
808
843
  requestedOutputs: options.requestedOutputs,
809
844
  constraintRefs: options.constraintRefs,
845
+ contractProfile: options.contractProfile,
846
+ validationPolicyRef: options.validationPolicyRef,
847
+ evidencePolicyRef: options.evidencePolicyRef,
810
848
  now: options.now,
811
849
  });
812
850
  printReceipt("order created", created.receipt, options.json);
@@ -979,6 +1017,11 @@ function runWorkReceiptNewCommandLocked(options) {
979
1017
  outcome: normalizeEnum(options.outcome, "--outcome", OUTCOMES),
980
1018
  cost_ref: options.costRef ?? "cost.redacted",
981
1019
  redaction_policy: normalizeEnum(options.redactionPolicy ?? "refs_and_hashes_only", "--redaction-policy", REDACTION_POLICIES),
1020
+ contract_profile: normalizeContractMetadataToken(options.contractProfile, "--contract-profile"),
1021
+ receipt_kind: normalizeContractMetadataToken(options.receiptKind, "--receipt-kind"),
1022
+ redaction_class: normalizeContractMetadataToken(options.redactionClass, "--redaction-class"),
1023
+ validation_policy_ref: options.validationPolicyRef,
1024
+ evidence_policy_ref: options.evidencePolicyRef,
982
1025
  artifacts: parseCsvList(options.artifacts),
983
1026
  proof_refs: parseCsvList(options.proofRefs),
984
1027
  attestation_refs: parseCsvList(options.attestationRefs),