mdkg 0.4.0 → 0.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.
- package/CHANGELOG.md +58 -0
- package/CLI_COMMAND_MATRIX.md +69 -9
- package/README.md +26 -2
- package/dist/cli.js +183 -8
- package/dist/command-contract.json +690 -24
- package/dist/commands/git.js +593 -0
- package/dist/commands/new.js +50 -1
- package/dist/commands/validate.js +84 -0
- package/dist/commands/work.js +45 -2
- package/dist/graph/agent_file_types.js +74 -2
- package/dist/graph/frontmatter.js +5 -0
- package/dist/graph/node.js +28 -0
- package/dist/init/AGENT_START.md +6 -0
- package/dist/init/CLI_COMMAND_MATRIX.md +10 -5
- package/dist/init/README.md +14 -5
- package/dist/init/init-manifest.json +12 -12
- package/dist/init/skills/default/author-mdkg-skill/SKILL.md +10 -5
- package/dist/init/templates/default/manifest.md +3 -0
- package/dist/init/templates/default/receipt.md +5 -0
- package/dist/init/templates/default/spec.md +3 -0
- package/dist/init/templates/default/work.md +1 -0
- package/dist/init/templates/default/work_order.md +3 -0
- package/dist/init/templates/specs/base.MANIFEST.md +3 -0
- package/dist/init/templates/specs/base.SPEC.md +3 -0
- package/dist/util/argparse.js +5 -0
- package/package.json +1 -1
|
@@ -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() } }
|
package/dist/commands/work.js
CHANGED
|
@@ -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
|
|
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),
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.AGENT_ATTRIBUTE_KEY_ORDER = exports.AGENT_FILE_BASENAMES = exports.AGENT_FILE_TYPES = exports.LEGACY_SPEC_BASENAME = exports.CANONICAL_MANIFEST_BASENAME = void 0;
|
|
6
|
+
exports.KNOWN_REDACTION_CLASSES = exports.KNOWN_RECEIPT_KINDS = exports.KNOWN_CONTRACT_PROFILES = exports.AGENT_ATTRIBUTE_KEY_ORDER = exports.AGENT_FILE_BASENAMES = exports.AGENT_FILE_TYPES = exports.LEGACY_SPEC_BASENAME = exports.CANONICAL_MANIFEST_BASENAME = void 0;
|
|
7
7
|
exports.isAgentFileType = isAgentFileType;
|
|
8
8
|
exports.isManifestSemanticType = isManifestSemanticType;
|
|
9
9
|
exports.collectManifestSiblingConflicts = collectManifestSiblingConflicts;
|
|
@@ -41,6 +41,9 @@ const MANIFEST_ATTRIBUTE_KEYS = [
|
|
|
41
41
|
"role",
|
|
42
42
|
"runtime_mode",
|
|
43
43
|
"work_contracts",
|
|
44
|
+
"contract_profile",
|
|
45
|
+
"validation_policy_ref",
|
|
46
|
+
"evidence_policy_ref",
|
|
44
47
|
"requested_capabilities",
|
|
45
48
|
"skill_refs",
|
|
46
49
|
"tool_refs",
|
|
@@ -58,6 +61,7 @@ exports.AGENT_ATTRIBUTE_KEY_ORDER = {
|
|
|
58
61
|
"version",
|
|
59
62
|
"agent_id",
|
|
60
63
|
"kind",
|
|
64
|
+
"contract_profile",
|
|
61
65
|
"pricing_model",
|
|
62
66
|
"required_capabilities",
|
|
63
67
|
"skill_refs",
|
|
@@ -79,6 +83,9 @@ exports.AGENT_ATTRIBUTE_KEY_ORDER = {
|
|
|
79
83
|
"request_ref",
|
|
80
84
|
"trigger_ref",
|
|
81
85
|
"payload_hash",
|
|
86
|
+
"contract_profile",
|
|
87
|
+
"validation_policy_ref",
|
|
88
|
+
"evidence_policy_ref",
|
|
82
89
|
"input_refs",
|
|
83
90
|
"queue_refs",
|
|
84
91
|
"requested_outputs",
|
|
@@ -92,6 +99,11 @@ exports.AGENT_ATTRIBUTE_KEY_ORDER = {
|
|
|
92
99
|
"outcome",
|
|
93
100
|
"cost_ref",
|
|
94
101
|
"redaction_policy",
|
|
102
|
+
"contract_profile",
|
|
103
|
+
"receipt_kind",
|
|
104
|
+
"redaction_class",
|
|
105
|
+
"validation_policy_ref",
|
|
106
|
+
"evidence_policy_ref",
|
|
95
107
|
"proof_refs",
|
|
96
108
|
"attestation_refs",
|
|
97
109
|
"evidence_hashes",
|
|
@@ -123,6 +135,9 @@ exports.AGENT_ATTRIBUTE_KEY_ORDER = {
|
|
|
123
135
|
const SEMVER_RE = /^\d+\.\d+\.\d+(?:[-+][a-z0-9.-]+)?$/;
|
|
124
136
|
const LOWER_TOKEN_RE = /^[a-z][a-z0-9_]*(?:-[a-z0-9_]+)*$/;
|
|
125
137
|
const FIELD_DESCRIPTOR_RE = /^[a-z][a-z0-9_]*:[a-z][a-z0-9_]*(?::(?:required|optional))?$/;
|
|
138
|
+
exports.KNOWN_CONTRACT_PROFILES = new Set(["generic", "omni-room"]);
|
|
139
|
+
exports.KNOWN_RECEIPT_KINDS = new Set(["worker", "final", "cleanup", "audit"]);
|
|
140
|
+
exports.KNOWN_REDACTION_CLASSES = new Set(["public", "internal", "private", "restricted"]);
|
|
126
141
|
const ROLE_VALUES = new Set([
|
|
127
142
|
"orchestrator",
|
|
128
143
|
"subagent",
|
|
@@ -233,7 +248,7 @@ function collectManifestSiblingConflicts(filePaths, formatDir) {
|
|
|
233
248
|
const conflicts = [];
|
|
234
249
|
for (const [dirPath, basenames] of Array.from(basenamesByDir.entries()).sort()) {
|
|
235
250
|
if (basenames.has(exports.CANONICAL_MANIFEST_BASENAME) && basenames.has(exports.LEGACY_SPEC_BASENAME)) {
|
|
236
|
-
conflicts.push(`${formatDir(dirPath)}: MANIFEST.md and SPEC.md cannot both exist in the same logical
|
|
251
|
+
conflicts.push(`${formatDir(dirPath)}: MANIFEST.md and SPEC.md cannot both exist in the same logical unit; keep MANIFEST.md and remove the legacy SPEC.md alias`);
|
|
237
252
|
}
|
|
238
253
|
}
|
|
239
254
|
return conflicts;
|
|
@@ -390,6 +405,48 @@ function validatePortableOrUriScalar(value, key, filePath) {
|
|
|
390
405
|
throw formatError(filePath, `${key} must be a portable id or URI ref`);
|
|
391
406
|
}
|
|
392
407
|
}
|
|
408
|
+
function requireContractMetadataToken(value, key, filePath) {
|
|
409
|
+
if (LOWER_TOKEN_RE.test(value)) {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
const id = key === "receipt_kind"
|
|
413
|
+
? "receipt-kind.invalid"
|
|
414
|
+
: key === "redaction_class"
|
|
415
|
+
? "redaction-class.invalid"
|
|
416
|
+
: "contract-profile.invalid";
|
|
417
|
+
throw formatError(filePath, `${id}: ${key} must be lowercase snake/kebab style`);
|
|
418
|
+
}
|
|
419
|
+
function optionalContractMetadataString(frontmatter, key, filePath) {
|
|
420
|
+
const value = frontmatter[key];
|
|
421
|
+
if (value === undefined) {
|
|
422
|
+
return undefined;
|
|
423
|
+
}
|
|
424
|
+
const id = key === "receipt_kind"
|
|
425
|
+
? "receipt-kind.invalid"
|
|
426
|
+
: key === "redaction_class"
|
|
427
|
+
? "redaction-class.invalid"
|
|
428
|
+
: "contract-profile.invalid";
|
|
429
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
430
|
+
throw formatError(filePath, `${id}: ${key} must be a non-empty string`);
|
|
431
|
+
}
|
|
432
|
+
return value;
|
|
433
|
+
}
|
|
434
|
+
function validateOptionalContractProfile(frontmatter, filePath) {
|
|
435
|
+
const contractProfile = optionalContractMetadataString(frontmatter, "contract_profile", filePath);
|
|
436
|
+
if (contractProfile) {
|
|
437
|
+
requireContractMetadataToken(contractProfile, "contract_profile", filePath);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
function validateOptionalPolicyRefs(frontmatter, filePath) {
|
|
441
|
+
const validationPolicyRef = optionalRefString(frontmatter, "validation_policy_ref", filePath);
|
|
442
|
+
if (validationPolicyRef) {
|
|
443
|
+
validatePortableOrUriScalar(validationPolicyRef, "validation_policy_ref", filePath);
|
|
444
|
+
}
|
|
445
|
+
const evidencePolicyRef = optionalRefString(frontmatter, "evidence_policy_ref", filePath);
|
|
446
|
+
if (evidencePolicyRef) {
|
|
447
|
+
validatePortableOrUriScalar(evidencePolicyRef, "evidence_policy_ref", filePath);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
393
450
|
function validateOptionalFieldDescriptors(values, key, filePath) {
|
|
394
451
|
if (values.length === 0) {
|
|
395
452
|
return;
|
|
@@ -448,6 +505,8 @@ function validateAgentFrontmatter(type, frontmatter, filePath) {
|
|
|
448
505
|
requireEnum(runtimeMode, "runtime_mode", RUNTIME_MODE_VALUES, filePath);
|
|
449
506
|
const updatePolicy = expectString(frontmatter, "update_policy", filePath);
|
|
450
507
|
requireEnum(updatePolicy, "update_policy", UPDATE_POLICY_VALUES, filePath);
|
|
508
|
+
validateOptionalContractProfile(frontmatter, filePath);
|
|
509
|
+
validateOptionalPolicyRefs(frontmatter, filePath);
|
|
451
510
|
validateRelativeMarkdownPaths(optionalList(frontmatter, "work_contracts", filePath), "work_contracts", "WORK.md", filePath);
|
|
452
511
|
validateCapabilities(optionalList(frontmatter, "requested_capabilities", filePath), "requested_capabilities", filePath);
|
|
453
512
|
validatePortableRefs(optionalList(frontmatter, "skill_refs", filePath), "skill_refs", filePath);
|
|
@@ -467,6 +526,7 @@ function validateAgentFrontmatter(type, frontmatter, filePath) {
|
|
|
467
526
|
requirePortableIdRef(agentId, "agent_id", filePath);
|
|
468
527
|
const kind = expectString(frontmatter, "kind", filePath);
|
|
469
528
|
requireLowerToken(kind, "kind", filePath);
|
|
529
|
+
validateOptionalContractProfile(frontmatter, filePath);
|
|
470
530
|
const pricingModel = expectString(frontmatter, "pricing_model", filePath);
|
|
471
531
|
requireEnum(pricingModel, "pricing_model", PRICING_MODEL_VALUES, filePath);
|
|
472
532
|
const requiredCapabilities = expectList(frontmatter, "required_capabilities", filePath);
|
|
@@ -505,6 +565,8 @@ function validateAgentFrontmatter(type, frontmatter, filePath) {
|
|
|
505
565
|
validatePortableOrUriScalar(requester, "requester", filePath);
|
|
506
566
|
const orderStatus = expectString(frontmatter, "order_status", filePath);
|
|
507
567
|
requireEnum(orderStatus, "order_status", ORDER_STATUS_VALUES, filePath);
|
|
568
|
+
validateOptionalContractProfile(frontmatter, filePath);
|
|
569
|
+
validateOptionalPolicyRefs(frontmatter, filePath);
|
|
508
570
|
const requestRef = optionalRefString(frontmatter, "request_ref", filePath);
|
|
509
571
|
if (requestRef) {
|
|
510
572
|
validatePortableOrUriScalar(requestRef, "request_ref", filePath);
|
|
@@ -542,6 +604,16 @@ function validateAgentFrontmatter(type, frontmatter, filePath) {
|
|
|
542
604
|
if (redactionPolicy) {
|
|
543
605
|
requireEnum(redactionPolicy, "redaction_policy", REDACTION_POLICY_VALUES, filePath);
|
|
544
606
|
}
|
|
607
|
+
validateOptionalContractProfile(frontmatter, filePath);
|
|
608
|
+
const receiptKind = optionalContractMetadataString(frontmatter, "receipt_kind", filePath);
|
|
609
|
+
if (receiptKind) {
|
|
610
|
+
requireContractMetadataToken(receiptKind, "receipt_kind", filePath);
|
|
611
|
+
}
|
|
612
|
+
const redactionClass = optionalContractMetadataString(frontmatter, "redaction_class", filePath);
|
|
613
|
+
if (redactionClass) {
|
|
614
|
+
requireContractMetadataToken(redactionClass, "redaction_class", filePath);
|
|
615
|
+
}
|
|
616
|
+
validateOptionalPolicyRefs(frontmatter, filePath);
|
|
545
617
|
validatePortableOrUriRefs(optionalList(frontmatter, "proof_refs", filePath), "proof_refs", filePath);
|
|
546
618
|
validatePortableOrUriRefs(optionalList(frontmatter, "attestation_refs", filePath), "attestation_refs", filePath);
|
|
547
619
|
validateHashRefs(optionalList(frontmatter, "evidence_hashes", filePath), "evidence_hashes", filePath);
|
|
@@ -30,11 +30,16 @@ exports.DEFAULT_FRONTMATTER_KEY_ORDER = [
|
|
|
30
30
|
"role",
|
|
31
31
|
"runtime_mode",
|
|
32
32
|
"work_contracts",
|
|
33
|
+
"contract_profile",
|
|
34
|
+
"validation_policy_ref",
|
|
35
|
+
"evidence_policy_ref",
|
|
33
36
|
"requested_capabilities",
|
|
34
37
|
"resource_profile",
|
|
35
38
|
"update_policy",
|
|
36
39
|
"agent_id",
|
|
37
40
|
"kind",
|
|
41
|
+
"receipt_kind",
|
|
42
|
+
"redaction_class",
|
|
38
43
|
"pricing_model",
|
|
39
44
|
"required_capabilities",
|
|
40
45
|
"inputs",
|
package/dist/graph/node.js
CHANGED
|
@@ -236,8 +236,36 @@ function requireTemplateSchema(type, templateSchemas, filePath) {
|
|
|
236
236
|
return schema;
|
|
237
237
|
}
|
|
238
238
|
const OPTIONAL_COMPAT_TEMPLATE_KEYS = {
|
|
239
|
+
manifest: {
|
|
240
|
+
contract_profile: "scalar",
|
|
241
|
+
validation_policy_ref: "scalar",
|
|
242
|
+
evidence_policy_ref: "scalar",
|
|
243
|
+
profile: "scalar",
|
|
244
|
+
},
|
|
239
245
|
spec: {
|
|
240
246
|
spec_kind: "scalar",
|
|
247
|
+
contract_profile: "scalar",
|
|
248
|
+
validation_policy_ref: "scalar",
|
|
249
|
+
evidence_policy_ref: "scalar",
|
|
250
|
+
profile: "scalar",
|
|
251
|
+
},
|
|
252
|
+
work: {
|
|
253
|
+
contract_profile: "scalar",
|
|
254
|
+
profile: "scalar",
|
|
255
|
+
},
|
|
256
|
+
work_order: {
|
|
257
|
+
contract_profile: "scalar",
|
|
258
|
+
validation_policy_ref: "scalar",
|
|
259
|
+
evidence_policy_ref: "scalar",
|
|
260
|
+
profile: "scalar",
|
|
261
|
+
},
|
|
262
|
+
receipt: {
|
|
263
|
+
contract_profile: "scalar",
|
|
264
|
+
receipt_kind: "scalar",
|
|
265
|
+
redaction_class: "scalar",
|
|
266
|
+
validation_policy_ref: "scalar",
|
|
267
|
+
evidence_policy_ref: "scalar",
|
|
268
|
+
profile: "scalar",
|
|
241
269
|
},
|
|
242
270
|
};
|
|
243
271
|
function validateTemplateKeys(frontmatter, schema, filePath) {
|
package/dist/init/AGENT_START.md
CHANGED
|
@@ -57,6 +57,12 @@ Agent operating prompt:
|
|
|
57
57
|
- Use `mdkg archive add/list/show/verify/compress` for committed source and artifact sidecars under `.mdkg/archive`.
|
|
58
58
|
- Use `mdkg work ...` helpers for semantic mirror contracts, deterministic triggers, work order status, receipt verification, and artifact registration.
|
|
59
59
|
- Treat work contracts, orders, and receipts as committed semantic mirrors only; never store raw secrets, credentials, live payment state, ledger mutations, or canonical marketplace state in mdkg.
|
|
60
|
+
- Treat optional `contract_profile`, policy refs, receipt kind, and redaction
|
|
61
|
+
class fields as generic semantic mirror metadata. Use `mdkg validate --profile
|
|
62
|
+
omni-room` or `mdkg work validate --profile omni-room` only when a downstream
|
|
63
|
+
profile-specific check is intended; mdkg validates mirrors, while downstream
|
|
64
|
+
runtimes own execution, provider state, billing or ledger state, and final
|
|
65
|
+
receipt authority.
|
|
60
66
|
- Use `artifact://...` for external/runtime-managed artifacts and `archive://...` for committed mdkg archive sidecars.
|
|
61
67
|
- Use `mdkg bundle create/list/show/verify` for explicit full `.mdkg` graph snapshot bundles.
|
|
62
68
|
- Use `mdkg subgraph add/list/verify/sync/materialize` to register child bundle snapshots as read-only planning context, refresh root-owned child bundle snapshots, and optionally generate ignored inspection trees.
|
|
@@ -120,10 +120,11 @@ Project database commands:
|
|
|
120
120
|
- active `.mdkg/db/runtime/` files and `.mdkg/db` WAL/SHM/journal/lock/temp files are ignored by default
|
|
121
121
|
|
|
122
122
|
Validation commands:
|
|
123
|
-
- `mdkg validate [--out <path>] [--json-out <path>] [--quiet] [--changed-only] [--summary] [--limit <n>] [--json]`
|
|
123
|
+
- `mdkg validate [--out <path>] [--json-out <path>] [--quiet] [--changed-only] [--summary] [--limit <n>] [--profile <name>] [--json]`
|
|
124
124
|
- `--changed-only` filters warning presentation to changed `.mdkg` files while full graph errors still run
|
|
125
125
|
- `--summary` emits bounded warning samples for agent/CI logs; `--limit <n>` controls the sample size
|
|
126
126
|
- `--out <path>` writes the compatibility text report; `--json-out <path>` writes a clean full JSON receipt
|
|
127
|
+
- `--profile omni-room` applies explicit contract-profile validation after generic validation; it is separate from `mdkg pack --profile`
|
|
127
128
|
- JSON receipts include `warning_summary` and `warning_diagnostics` with warning ids, categories, severity, paths, refs, and remediation text
|
|
128
129
|
|
|
129
130
|
Node creation commands:
|
|
@@ -146,6 +147,9 @@ Agent workflow file type creation:
|
|
|
146
147
|
|
|
147
148
|
Agent workflow notes:
|
|
148
149
|
- `--id <portable-id>` is only for agent workflow file types.
|
|
150
|
+
- `--contract-profile <name>` is supported for MANIFEST, WORK, WORK_ORDER, and RECEIPT.
|
|
151
|
+
- `--validation-policy-ref <ref>` and `--evidence-policy-ref <ref>` are supported for MANIFEST, WORK_ORDER, and RECEIPT.
|
|
152
|
+
- `--receipt-kind <kind>` and `--redaction-class <class>` are supported for RECEIPT.
|
|
149
153
|
- `manifest` and `work` scaffold as validation-clean standalone docs.
|
|
150
154
|
- `work_order`, `receipt`, `feedback`, `dispute`, and `proposal` need real refs before strict `mdkg validate` passes.
|
|
151
155
|
- `goal` nodes capture recursive objective state and required checks, but normal `mdkg next` does not select them.
|
|
@@ -285,22 +289,23 @@ Subgraph orchestration:
|
|
|
285
289
|
- public/internal subgraphs require public bundle profiles
|
|
286
290
|
|
|
287
291
|
Work semantic mirrors:
|
|
288
|
-
- `mdkg work contract new "<title>" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--required-capabilities <...>] [--pricing-model <...>] [--json]`
|
|
292
|
+
- `mdkg work contract new "<title>" --id <work.id> --agent-id <agent.id> --kind <kind> --inputs <...> --outputs <...> [--contract-profile <name>] [--required-capabilities <...>] [--pricing-model <...>] [--json]`
|
|
289
293
|
- `mdkg work trigger <work-or-capability-ref> [--id <order.id>] [--title "<title>"] [--requester <ref>] [--enqueue <queue>] [--json]`
|
|
290
|
-
- `mdkg work order new "<title>" --id <order.id> --work-id <work.id> --requester <ref> [--request-ref <ref>] [--input-refs <...>] [--requested-outputs <...>] [--json]`
|
|
294
|
+
- `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>] [--input-refs <...>] [--requested-outputs <...>] [--json]`
|
|
291
295
|
- `mdkg work order status <id-or-qid> [--json]`
|
|
292
296
|
- `mdkg work order update <id-or-qid> [--status <status>] [--add-input-refs <...>] [--add-artifacts <...>] [--json]`
|
|
293
|
-
- `mdkg work receipt new "<title>" --id <receipt.id> --work-order-id <order.id> --outcome success|partial|failure [--receipt-status recorded|verified|rejected|superseded] [--json]`
|
|
297
|
+
- `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>] [--json]`
|
|
294
298
|
- `mdkg work receipt verify <id-or-qid> [--json]`
|
|
295
299
|
- `mdkg work receipt update <id-or-qid> [--receipt-status <status>] [--add-artifacts <...>] [--add-proof-refs <...>] [--add-attestation-refs <...>] [--json]`
|
|
296
300
|
- `mdkg work artifact add <order-or-receipt-id-or-qid> <file> [--id <archive.id>] [--kind source|artifact] [--json]`
|
|
297
|
-
- `mdkg work validate [<id-or-qid>] [--type manifest|spec|work|work_order|receipt|feedback|dispute|proposal] [--json]`
|
|
301
|
+
- `mdkg work validate [<id-or-qid>] [--type manifest|spec|work|work_order|receipt|feedback|dispute|proposal] [--profile <name>] [--json]`
|
|
298
302
|
- `work trigger` accepts a `WORK.md` ref directly or a `MANIFEST.md` / legacy `SPEC.md` capability ref with exactly one resolvable work contract; it creates a submitted order mirror and never executes work
|
|
299
303
|
- example: `mdkg work trigger work.example --id order.example-1 --requester user://example --json`
|
|
300
304
|
- `work trigger --enqueue <queue>` requires a valid project DB plus an explicitly created active queue, creates a submitted order mirror, and enqueues a local delivery message without executing work
|
|
301
305
|
- `work order status` is read-only and reports deterministic order state plus linked receipts
|
|
302
306
|
- `work receipt verify` is read-only and reports linkage, evidence, archive ref, hash, outcome, and redaction-policy checks
|
|
303
307
|
- `work validate` is read-only and reports typed diagnostics for agent workflow mirrors; obvious raw secret, prompt, token, or payload markers are warnings, not hard failures
|
|
308
|
+
- `work validate --profile omni-room` applies explicit contract-profile validation after generic mirror validation; it is separate from `mdkg pack --profile`
|
|
304
309
|
- work commands mutate mdkg semantic mirror files only; production order, receipt, feedback, dispute, payment, ledger, marketplace inventory, fulfillment, and execution state remains canonical outside mdkg
|
|
305
310
|
- do not store raw secrets, credentials, live payment state, ledger mutations, or canonical marketplace state in work mirrors
|
|
306
311
|
- `artifact://...` refs identify external/runtime-managed artifacts; `archive://...` refs identify committed mdkg archive sidecars
|
package/dist/init/README.md
CHANGED
|
@@ -80,8 +80,9 @@ intentionally with `mdkg new task ...` or `mdkg new test ...`.
|
|
|
80
80
|
Agent workflow docs can use semantic ids:
|
|
81
81
|
|
|
82
82
|
```bash
|
|
83
|
-
mdkg new manifest "image worker" --id agent.image-worker
|
|
84
|
-
mdkg new work "generate image" --id work.generate-image
|
|
83
|
+
mdkg new manifest "image worker" --id agent.image-worker --contract-profile generic
|
|
84
|
+
mdkg new work "generate image" --id work.generate-image --contract-profile generic
|
|
85
|
+
mdkg work validate --profile omni-room --json
|
|
85
86
|
```
|
|
86
87
|
|
|
87
88
|
`MANIFEST.md` is optional. Repos without manifest files still validate. When
|
|
@@ -92,6 +93,14 @@ release, and `mdkg spec list/show/validate` remains a deprecated alias for
|
|
|
92
93
|
read-only discovery surface for skills, manifests, WORK contracts, core docs,
|
|
93
94
|
and design docs.
|
|
94
95
|
|
|
96
|
+
Agent workflow files may include optional generic mirror fields such as
|
|
97
|
+
`contract_profile`, `validation_policy_ref`, `evidence_policy_ref`,
|
|
98
|
+
`receipt_kind`, and `redaction_class`. mdkg validates those mirrors and can run
|
|
99
|
+
profile checks such as `mdkg validate --profile omni-room` and
|
|
100
|
+
`mdkg work validate --profile omni-room`; downstream runtimes still own queue
|
|
101
|
+
execution, room ids, provider state, billing or ledger state, and final receipt
|
|
102
|
+
authority.
|
|
103
|
+
|
|
95
104
|
Read `AGENT_START.md` first when this repo includes it.
|
|
96
105
|
|
|
97
106
|
## Pack Profiles
|
|
@@ -229,10 +238,10 @@ mdkg archive verify archive://archive.example
|
|
|
229
238
|
Use work lifecycle helpers for semantic mirrors only:
|
|
230
239
|
|
|
231
240
|
```bash
|
|
232
|
-
mdkg work contract new "example capability" --id work.example --agent-id agent.example --kind example --inputs prompt:text:required --outputs result:text:required
|
|
241
|
+
mdkg work contract new "example capability" --id work.example --agent-id agent.example --kind example --contract-profile generic --inputs prompt:text:required --outputs result:text:required
|
|
233
242
|
mdkg work trigger work.example --id order.example-1 --requester user://example
|
|
234
243
|
mdkg work order status order.example-1 --json
|
|
235
|
-
mdkg work receipt new "example receipt" --id receipt.example-1 --work-order-id order.example-1 --outcome success
|
|
244
|
+
mdkg work receipt new "example receipt" --id receipt.example-1 --work-order-id order.example-1 --outcome success --contract-profile generic --receipt-kind worker --redaction-class internal
|
|
236
245
|
mdkg work receipt verify receipt.example-1 --json
|
|
237
246
|
```
|
|
238
247
|
|
|
@@ -249,7 +258,7 @@ Update and artifact commands accept local ids or local qids; subgraph qids are r
|
|
|
249
258
|
`mdkg work trigger` creates a deterministic submitted `WORK_ORDER.md` from a
|
|
250
259
|
WORK contract or a SPEC with exactly one resolvable work contract. `mdkg work
|
|
251
260
|
order status` and `mdkg work receipt verify` are read-only review helpers.
|
|
252
|
-
`mdkg work validate [<id-or-qid>] [--type spec|work|work_order|receipt|feedback|dispute|proposal] --json`
|
|
261
|
+
`mdkg work validate [<id-or-qid>] [--type manifest|spec|work|work_order|receipt|feedback|dispute|proposal] [--profile omni-room] --json`
|
|
253
262
|
is a read-only focused validator for agent workflow mirrors with typed diagnostics
|
|
254
263
|
and raw secret, prompt, token, or payload marker warnings.
|
|
255
264
|
`mdkg work trigger --enqueue <queue>` optionally writes a local project DB queue
|