mdkg 0.0.8 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/CONTRIBUTING.md +124 -0
  3. package/README.md +49 -14
  4. package/dist/cli.js +113 -32
  5. package/dist/commands/checkpoint.js +19 -2
  6. package/dist/commands/event.js +12 -0
  7. package/dist/commands/init.js +4 -0
  8. package/dist/commands/init_manifest.js +131 -0
  9. package/dist/commands/new.js +57 -21
  10. package/dist/commands/pack.js +14 -0
  11. package/dist/commands/query_output.js +2 -0
  12. package/dist/commands/search.js +8 -0
  13. package/dist/commands/show.js +7 -0
  14. package/dist/commands/skill.js +80 -12
  15. package/dist/commands/task.js +42 -12
  16. package/dist/commands/upgrade.js +286 -0
  17. package/dist/commands/validate.js +31 -3
  18. package/dist/commands/workspace.js +105 -13
  19. package/dist/core/config.js +217 -22
  20. package/dist/core/migrate.js +39 -5
  21. package/dist/core/version.js +31 -0
  22. package/dist/core/workspace_path.js +41 -0
  23. package/dist/graph/agent_file_types.js +392 -0
  24. package/dist/graph/edges.js +13 -10
  25. package/dist/graph/frontmatter.js +33 -0
  26. package/dist/graph/indexer.js +1 -0
  27. package/dist/graph/node.js +43 -16
  28. package/dist/graph/skills_indexer.js +14 -1
  29. package/dist/graph/template_schema.js +13 -126
  30. package/dist/graph/validate_graph.js +302 -2
  31. package/dist/init/AGENT_START.md +14 -2
  32. package/dist/init/CLI_COMMAND_MATRIX.md +49 -1
  33. package/dist/init/README.md +14 -0
  34. package/dist/init/core/rule-6-templates-and-schemas.md +1 -3
  35. package/dist/init/init-manifest.json +197 -0
  36. package/dist/init/legacy/v0.0.9-init-manifest.json +197 -0
  37. package/dist/init/skills/default/verify-close-and-checkpoint/SKILL.md +12 -11
  38. package/dist/init/templates/default/dispute.md +31 -0
  39. package/dist/init/templates/default/feedback.md +27 -0
  40. package/dist/init/templates/default/proposal.md +35 -0
  41. package/dist/init/templates/default/receipt.md +31 -0
  42. package/dist/init/templates/default/spec.md +43 -0
  43. package/dist/init/templates/default/work.md +44 -0
  44. package/dist/init/templates/default/work_order.md +32 -0
  45. package/dist/pack/export_json.js +3 -0
  46. package/dist/pack/export_md.js +9 -0
  47. package/dist/pack/export_xml.js +9 -0
  48. package/dist/pack/order.js +7 -0
  49. package/dist/pack/pack.js +1 -0
  50. package/dist/templates/loader.js +2 -2
  51. package/dist/util/argparse.js +2 -0
  52. package/dist/util/id.js +19 -0
  53. package/package.json +10 -2
  54. package/scripts/postinstall.js +89 -0
@@ -15,6 +15,9 @@ function buildFrontmatter(node) {
15
15
  if (node.aliases.length > 0) {
16
16
  frontmatter.aliases = node.aliases;
17
17
  }
18
+ for (const [key, value] of Object.entries(node.attributes ?? {})) {
19
+ frontmatter[key] = value;
20
+ }
18
21
  return frontmatter;
19
22
  }
20
23
  function exportJson(pack) {
@@ -7,6 +7,12 @@ function formatList(label, values) {
7
7
  }
8
8
  return `${label}: ${values.join(", ")}`;
9
9
  }
10
+ function formatAttribute(label, value) {
11
+ if (Array.isArray(value)) {
12
+ return formatList(label, value);
13
+ }
14
+ return `${label}: ${String(value)}`;
15
+ }
10
16
  function renderHeader(meta, nodes) {
11
17
  const lines = [];
12
18
  lines.push("# mdkg pack");
@@ -56,6 +62,9 @@ function renderNode(node) {
56
62
  if (node.refs.length > 0) {
57
63
  lines.push(formatList("refs", node.refs));
58
64
  }
65
+ for (const [key, value] of Object.entries(node.attributes ?? {})) {
66
+ lines.push(formatAttribute(key, value));
67
+ }
59
68
  if (node.body.trim().length > 0) {
60
69
  lines.push("");
61
70
  lines.push(node.body);
@@ -21,6 +21,12 @@ function listItems(tag, itemTag, items, indent) {
21
21
  lines.push(`${indent}</${tag}>`);
22
22
  return lines;
23
23
  }
24
+ function attributeLines(key, value, indent) {
25
+ if (Array.isArray(value)) {
26
+ return listItems(key, "item", value, indent);
27
+ }
28
+ return [`${indent}<${key}>${escapeXml(String(value))}</${key}>`];
29
+ }
24
30
  function exportXml(pack) {
25
31
  const lines = [];
26
32
  lines.push("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
@@ -78,6 +84,9 @@ function exportXml(pack) {
78
84
  lines.push(...listItems("artifacts", "artifact", node.artifacts, " "));
79
85
  lines.push(...listItems("refs", "ref", node.refs, " "));
80
86
  lines.push(...listItems("aliases", "alias", node.aliases, " "));
87
+ for (const [key, value] of Object.entries(node.attributes ?? {})) {
88
+ lines.push(...attributeLines(key, value, " "));
89
+ }
81
90
  lines.push(" </frontmatter>");
82
91
  lines.push(` <body>${escapeXml(node.body)}</body>`);
83
92
  lines.push(" </node>");
@@ -8,6 +8,13 @@ const FALLBACK_TYPES = [
8
8
  "rule",
9
9
  "prd",
10
10
  "prop",
11
+ "spec",
12
+ "work",
13
+ "work_order",
14
+ "receipt",
15
+ "feedback",
16
+ "dispute",
17
+ "proposal",
11
18
  "epic",
12
19
  "feat",
13
20
  "task",
package/dist/pack/pack.js CHANGED
@@ -124,6 +124,7 @@ function buildPackNode(root, index, qid) {
124
124
  artifacts: node.artifacts,
125
125
  refs: node.refs,
126
126
  aliases: node.aliases,
127
+ attributes: node.attributes ?? {},
127
128
  body,
128
129
  };
129
130
  }
@@ -48,8 +48,8 @@ function renderTokenValue(value) {
48
48
  }
49
49
  return value;
50
50
  }
51
- function renderTemplate(template, context, allowedKeysInput) {
52
- const allowedKeys = new Set(allowedKeysInput ?? Object.keys(template.frontmatter));
51
+ function renderTemplate(template, context) {
52
+ const allowedKeys = new Set(Object.keys(template.frontmatter));
53
53
  const rendered = {};
54
54
  for (const [key, value] of Object.entries(template.frontmatter)) {
55
55
  if (isTokenPlaceholder(value)) {
@@ -4,6 +4,7 @@ exports.parseArgs = parseArgs;
4
4
  const NORMALIZE_VALUE_FLAGS = new Set(["--ws", "--type", "--status", "--template", "--epic"]);
5
5
  const VALUE_FLAGS = new Set([
6
6
  "--root",
7
+ "--id",
7
8
  "--ws",
8
9
  "--type",
9
10
  "--status",
@@ -78,6 +79,7 @@ const BOOLEAN_FLAGS = new Set([
78
79
  "--concise",
79
80
  "--version",
80
81
  "--dry-run",
82
+ "--apply",
81
83
  "--json",
82
84
  "--xml",
83
85
  "--toon",
package/dist/util/id.js CHANGED
@@ -1,13 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isCanonicalId = isCanonicalId;
4
+ exports.isPortableId = isPortableId;
4
5
  exports.isCanonicalIdRef = isCanonicalIdRef;
6
+ exports.isPortableIdRef = isPortableIdRef;
5
7
  const NUMERIC_ID_RE = /^[a-z]+-[0-9]+$/;
6
8
  const WORKSPACE_RE = /^[a-z][a-z0-9_]*$/;
9
+ const PORTABLE_ID_RE = /^[a-z][a-z0-9_]*(?:[._-][a-z0-9_]+)*$/;
7
10
  const SPECIAL_IDS = new Set(["rule-guide", "rule-soul", "rule-human"]);
8
11
  function isCanonicalId(value) {
9
12
  return NUMERIC_ID_RE.test(value) || SPECIAL_IDS.has(value);
10
13
  }
14
+ function isPortableId(value) {
15
+ return isCanonicalId(value) || PORTABLE_ID_RE.test(value);
16
+ }
11
17
  function isCanonicalIdRef(value) {
12
18
  const normalized = value.toLowerCase();
13
19
  const parts = normalized.split(":");
@@ -21,3 +27,16 @@ function isCanonicalIdRef(value) {
21
27
  const id = parts[1] ?? "";
22
28
  return WORKSPACE_RE.test(workspace) && isCanonicalId(id);
23
29
  }
30
+ function isPortableIdRef(value) {
31
+ const normalized = value.toLowerCase();
32
+ const parts = normalized.split(":");
33
+ if (parts.length === 1) {
34
+ return isPortableId(parts[0] ?? "");
35
+ }
36
+ if (parts.length !== 2) {
37
+ return false;
38
+ }
39
+ const workspace = parts[0] ?? "";
40
+ const id = parts[1] ?? "";
41
+ return WORKSPACE_RE.test(workspace) && isPortableId(id);
42
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mdkg",
3
- "version": "0.0.8",
3
+ "version": "0.1.0",
4
4
  "description": "Markdown Knowledge Graph",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -12,8 +12,13 @@
12
12
  "test": "npm run build && npm run build:test && node --test dist/tests/**/*.test.js",
13
13
  "test:coverage": "npm run build && npm run build:test && node --test --experimental-test-coverage dist/tests/**/*.test.js",
14
14
  "smoke:consumer": "npm run build && node scripts/smoke-consumer.js",
15
+ "smoke:matrix": "npm run build && node scripts/smoke-command-matrix.js",
16
+ "smoke:upgrade": "npm run build && node scripts/smoke-upgrade.js",
15
17
  "cli:snapshot": "npm run build && node scripts/cli_help_snapshot.js",
16
- "cli:check": "npm run build && node scripts/cli_help_snapshot.js --check"
18
+ "cli:check": "npm run build && node scripts/cli_help_snapshot.js --check",
19
+ "prepack": "npm run build && node scripts/assert-publish-ready.js",
20
+ "prepublishOnly": "npm run test && npm run cli:check && node dist/cli.js validate && npm run smoke:consumer && npm run smoke:matrix && npm run smoke:upgrade && node scripts/assert-publish-ready.js",
21
+ "postinstall": "node scripts/postinstall.js"
17
22
  },
18
23
  "devDependencies": {
19
24
  "@types/node": "^18.19.0",
@@ -28,7 +33,10 @@
28
33
  "dist/pack/",
29
34
  "dist/templates/",
30
35
  "dist/util/",
36
+ "scripts/postinstall.js",
31
37
  "README.md",
38
+ "CHANGELOG.md",
39
+ "CONTRIBUTING.md",
32
40
  "LICENSE"
33
41
  ],
34
42
  "engines": {
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+ const { spawnSync } = require("node:child_process");
6
+
7
+ function readPackageVersion() {
8
+ try {
9
+ const pkgPath = path.resolve(__dirname, "..", "package.json");
10
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
11
+ return typeof pkg.version === "string" ? pkg.version : "unknown";
12
+ } catch {
13
+ return "unknown";
14
+ }
15
+ }
16
+
17
+ function npmCommand(platform = process.platform) {
18
+ return platform === "win32" ? "npm.cmd" : "npm";
19
+ }
20
+
21
+ function npmPrefixGlobal(env = process.env, platform = process.platform, spawn = spawnSync) {
22
+ if (env.npm_config_prefix) {
23
+ return env.npm_config_prefix;
24
+ }
25
+ const result = spawn(npmCommand(platform), ["prefix", "-g"], {
26
+ encoding: "utf8",
27
+ stdio: "pipe",
28
+ });
29
+ if (result.status !== 0) {
30
+ return undefined;
31
+ }
32
+ const prefix = String(result.stdout || "").trim();
33
+ return prefix || undefined;
34
+ }
35
+
36
+ function globalBinFromPrefix(prefix, platform = process.platform) {
37
+ if (!prefix) {
38
+ return undefined;
39
+ }
40
+ return platform === "win32" ? prefix : path.join(prefix, "bin");
41
+ }
42
+
43
+ function pathIncludesDir(dir, env = process.env, platform = process.platform) {
44
+ if (!dir) {
45
+ return false;
46
+ }
47
+ const currentPath = env.PATH || "";
48
+ return currentPath
49
+ .split(path.delimiter)
50
+ .filter(Boolean)
51
+ .some((entry) => path.resolve(entry) === path.resolve(dir));
52
+ }
53
+
54
+ function buildPostinstallMessage(env = process.env, platform = process.platform, spawn = spawnSync) {
55
+ const version = readPackageVersion();
56
+ const lines = [
57
+ `mdkg ${version} installed.`,
58
+ "",
59
+ "Start here:",
60
+ " mdkg --help",
61
+ ];
62
+
63
+ const prefix = npmPrefixGlobal(env, platform, spawn);
64
+ const globalBin = globalBinFromPrefix(prefix, platform);
65
+ if (platform !== "win32" && globalBin && !pathIncludesDir(globalBin, env, platform)) {
66
+ lines.push(
67
+ "",
68
+ "If your shell cannot find mdkg, add npm's global bin directory to PATH:",
69
+ "",
70
+ "# zsh",
71
+ `echo 'export PATH="${globalBin}:$PATH"' >> ~/.zshrc`,
72
+ "",
73
+ "# bash",
74
+ `echo 'export PATH="${globalBin}:$PATH"' >> ~/.bashrc`
75
+ );
76
+ }
77
+
78
+ return lines.join("\n");
79
+ }
80
+
81
+ if (require.main === module) {
82
+ console.log(buildPostinstallMessage());
83
+ }
84
+
85
+ module.exports = {
86
+ buildPostinstallMessage,
87
+ globalBinFromPrefix,
88
+ pathIncludesDir,
89
+ };