@pieai/doc-gov 0.5.3 → 0.6.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 (3) hide show
  1. package/cli-guide.md +3 -2
  2. package/dist/cli.js +123 -39
  3. package/package.json +1 -1
package/cli-guide.md CHANGED
@@ -56,8 +56,9 @@ pnpm doc-gov migrate --profile doc-only --check
56
56
  `docs/governance/agents-routing/`, and `profiles/` stay connected in the
57
57
  expected order.
58
58
  - In a downstream project, it verifies the project router block,
59
- `docs/governance/ssot-v1.0.md`, the selected agents-routing file, and old
60
- shared SSOT/task-routing leftovers.
59
+ `docs/governance/ssot-v1.1.md`, the selected agents-routing file, the exact
60
+ `CLAUDE.md -> AGENTS.md` and `.claude/skills -> ../.agents/skills`
61
+ compatibility links, and old shared SSOT/task-routing leftovers.
61
62
  - It also checks that local paths written in backticks inside router-facing
62
63
  files such as `AGENTS.md`, `CLAUDE.md`, `README.md`, and the starter
63
64
  `AGENTS.template.md` can actually be opened, which catches stale startup
package/dist/cli.js CHANGED
@@ -895,13 +895,22 @@ import { existsSync as existsSync7, readFileSync as readFileSync7 } from "node:f
895
895
  import { isAbsolute, join as join9, resolve as resolve2 } from "node:path";
896
896
 
897
897
  // src/core/router-integrity.ts
898
- import { existsSync as existsSync6, readdirSync as readdirSync5, readFileSync as readFileSync6 } from "node:fs";
898
+ import {
899
+ existsSync as existsSync6,
900
+ lstatSync as lstatSync2,
901
+ readlinkSync,
902
+ readdirSync as readdirSync5,
903
+ readFileSync as readFileSync6
904
+ } from "node:fs";
899
905
  import { join as join8, relative as relative2 } from "node:path";
900
906
  var CENTRAL_REQUIRED_FILES = [
901
907
  "AGENTS.md",
908
+ "CLAUDE.md",
909
+ ".agents/skills",
910
+ ".claude/skills",
902
911
  "README.md",
903
912
  "docs/governance/boundary.md",
904
- "docs/governance/ssot-v1.0.md",
913
+ "docs/governance/ssot-v1.1.md",
905
914
  "docs/governance/templates/adr.md",
906
915
  "docs/governance/templates/spec.md",
907
916
  "docs/governance/templates/plan.md",
@@ -909,23 +918,23 @@ var CENTRAL_REQUIRED_FILES = [
909
918
  "docs/governance/templates/reference.md",
910
919
  "docs/governance/templates/policy.md",
911
920
  "docs/governance/templates/archive.md",
912
- "docs/governance/agents-routing/engineering-runtime-v1.0.md",
913
- "docs/governance/agents-routing/doc-only-v1.0.md",
921
+ "docs/governance/agents-routing/engineering-runtime-v1.1.md",
922
+ "docs/governance/agents-routing/doc-only-v1.1.md",
914
923
  "integrations/mattpocock-skills.md",
915
924
  "profiles/engineering-runtime/profile.md",
916
925
  "profiles/engineering-runtime/manifest.yml",
917
926
  "profiles/doc-only/profile.md",
918
927
  "profiles/doc-only/manifest.yml",
928
+ "starter/.agents/skills/.gitkeep",
919
929
  "starter/AGENTS.template.md",
920
- "starter/CLAUDE.template.md",
921
930
  "starter/lefthook.template.yml",
922
931
  "starter/.github/workflows/docs-check.yml",
923
932
  "starter/docs/reference/execution/current-work.md",
924
933
  "starter/docs/policy/best-practice-for-this-project.md",
925
934
  "starter/docs/governance/boundary.md",
926
- "starter/docs/governance/ssot-v1.0.md",
927
- "starter/docs/governance/agents-routing/engineering-runtime-v1.0.md",
928
- "starter/docs/governance/agents-routing/doc-only-v1.0.md",
935
+ "starter/docs/governance/ssot-v1.1.md",
936
+ "starter/docs/governance/agents-routing/engineering-runtime-v1.1.md",
937
+ "starter/docs/governance/agents-routing/doc-only-v1.1.md",
929
938
  "starter/docs/governance/doc-agent-rules.md",
930
939
  "starter/docs/governance/doc-types.md",
931
940
  "starter/docs/governance/templates/adr.md",
@@ -939,15 +948,17 @@ var CENTRAL_REQUIRED_FILES = [
939
948
  var PROJECT_REQUIRED_FILES = [
940
949
  "AGENTS.md",
941
950
  "CLAUDE.md",
951
+ ".agents/skills",
952
+ ".claude/skills",
942
953
  "docs/governance/boundary.md",
943
- "docs/governance/ssot-v1.0.md",
954
+ "docs/governance/ssot-v1.1.md",
944
955
  "docs/governance/doc-agent-rules.md",
945
956
  "docs/governance/doc-types.md",
946
957
  "docs/reference/execution/current-work.md"
947
958
  ];
948
959
  var PROJECT_AGENTS_ROUTING_FILES = [
949
- "docs/governance/agents-routing/engineering-runtime-v1.0.md",
950
- "docs/governance/agents-routing/doc-only-v1.0.md"
960
+ "docs/governance/agents-routing/engineering-runtime-v1.1.md",
961
+ "docs/governance/agents-routing/doc-only-v1.1.md"
951
962
  ];
952
963
  var FORBIDDEN_LEGACY_PATHS = [
953
964
  "governance",
@@ -960,9 +971,14 @@ var FORBIDDEN_PROJECT_PATHS = [
960
971
  "docs/policy/shared-rules/ssot.md",
961
972
  "docs/policy/shared-rules/task-routing.md"
962
973
  ];
974
+ var SUPERSEDED_PROJECT_CONTRACT_PATHS = [
975
+ "docs/governance/ssot-v1.0.md",
976
+ "docs/governance/agents-routing/engineering-runtime-v1.0.md",
977
+ "docs/governance/agents-routing/doc-only-v1.0.md"
978
+ ];
963
979
  var FORBIDDEN_PROJECT_ROOTS = ["integrations"];
964
980
  var FORBIDDEN_CENTRAL_ROOTS = ["shared-rules"];
965
- var ROUTER_BLOCK_BEGIN = "<!-- PGS-ROUTER:BEGIN v1.0 -->";
981
+ var ROUTER_BLOCK_BEGIN = "<!-- PGS-ROUTER:BEGIN v1.1 -->";
966
982
  var ROUTER_BLOCK_END = "<!-- PGS-ROUTER:END -->";
967
983
  var EXTERNAL_ROUTER_MARKERS = [
968
984
  "## gstack",
@@ -992,8 +1008,8 @@ var CENTRAL_REQUIRED_NEEDLES = [
992
1008
  },
993
1009
  {
994
1010
  file: "AGENTS.md",
995
- needle: "docs/governance/ssot-v1.0.md",
996
- message: "AGENTS.md must mention docs/governance/ssot-v1.0.md."
1011
+ needle: "docs/governance/ssot-v1.1.md",
1012
+ message: "AGENTS.md must mention docs/governance/ssot-v1.1.md."
997
1013
  },
998
1014
  {
999
1015
  file: "AGENTS.md",
@@ -1007,13 +1023,13 @@ var CENTRAL_REQUIRED_NEEDLES = [
1007
1023
  },
1008
1024
  {
1009
1025
  file: "AGENTS.md",
1010
- needle: "docs/governance/agents-routing/engineering-runtime-v1.0.md",
1011
- message: "AGENTS.md must mention docs/governance/agents-routing/engineering-runtime-v1.0.md."
1026
+ needle: "docs/governance/agents-routing/engineering-runtime-v1.1.md",
1027
+ message: "AGENTS.md must mention docs/governance/agents-routing/engineering-runtime-v1.1.md."
1012
1028
  },
1013
1029
  {
1014
1030
  file: "AGENTS.md",
1015
- needle: "docs/governance/agents-routing/doc-only-v1.0.md",
1016
- message: "AGENTS.md must mention docs/governance/agents-routing/doc-only-v1.0.md."
1031
+ needle: "docs/governance/agents-routing/doc-only-v1.1.md",
1032
+ message: "AGENTS.md must mention docs/governance/agents-routing/doc-only-v1.1.md."
1017
1033
  },
1018
1034
  {
1019
1035
  file: "AGENTS.md",
@@ -1031,12 +1047,12 @@ var CENTRAL_REQUIRED_NEEDLES = [
1031
1047
  message: "README.md must point readers to agents-routing under docs/governance/."
1032
1048
  },
1033
1049
  {
1034
- file: "docs/governance/agents-routing/engineering-runtime-v1.0.md",
1050
+ file: "docs/governance/agents-routing/engineering-runtime-v1.1.md",
1035
1051
  needle: "current-work.md",
1036
1052
  message: "Engineering routing must separate routing from current-work.md."
1037
1053
  },
1038
1054
  {
1039
- file: "docs/governance/agents-routing/doc-only-v1.0.md",
1055
+ file: "docs/governance/agents-routing/doc-only-v1.1.md",
1040
1056
  needle: "does not use engineering test workflows by default",
1041
1057
  message: "Doc-only routing must exclude engineering test workflows by default."
1042
1058
  },
@@ -1057,7 +1073,7 @@ var CENTRAL_REQUIRED_NEEDLES = [
1057
1073
  },
1058
1074
  {
1059
1075
  file: "profiles/engineering-runtime/manifest.yml",
1060
- needle: "docs/governance/agents-routing/engineering-runtime-v1.0.md",
1076
+ needle: "docs/governance/agents-routing/engineering-runtime-v1.1.md",
1061
1077
  message: "Engineering profile manifest must point to engineering routing."
1062
1078
  },
1063
1079
  {
@@ -1067,7 +1083,7 @@ var CENTRAL_REQUIRED_NEEDLES = [
1067
1083
  },
1068
1084
  {
1069
1085
  file: "profiles/doc-only/manifest.yml",
1070
- needle: "docs/governance/agents-routing/doc-only-v1.0.md",
1086
+ needle: "docs/governance/agents-routing/doc-only-v1.1.md",
1071
1087
  message: "Doc-only profile manifest must point to doc-only routing."
1072
1088
  },
1073
1089
  {
@@ -1092,8 +1108,8 @@ var CENTRAL_REQUIRED_NEEDLES = [
1092
1108
  },
1093
1109
  {
1094
1110
  file: "starter/AGENTS.template.md",
1095
- needle: "docs/governance/ssot-v1.0.md",
1096
- message: "Starter AGENTS template must point agents to docs/governance/ssot-v1.0.md."
1111
+ needle: "docs/governance/ssot-v1.1.md",
1112
+ message: "Starter AGENTS template must point agents to docs/governance/ssot-v1.1.md."
1097
1113
  },
1098
1114
  {
1099
1115
  file: "starter/AGENTS.template.md",
@@ -1179,8 +1195,8 @@ var PROJECT_REQUIRED_NEEDLES = [
1179
1195
  },
1180
1196
  {
1181
1197
  file: "AGENTS.md",
1182
- needle: "docs/governance/ssot-v1.0.md",
1183
- message: "AGENTS.md must mention docs/governance/ssot-v1.0.md."
1198
+ needle: "docs/governance/ssot-v1.1.md",
1199
+ message: "AGENTS.md must mention docs/governance/ssot-v1.1.md."
1184
1200
  },
1185
1201
  {
1186
1202
  file: "AGENTS.md",
@@ -1208,7 +1224,7 @@ var PROJECT_REQUIRED_NEEDLES = [
1208
1224
  message: "Governance boundary must preserve the product artifact boundary."
1209
1225
  },
1210
1226
  {
1211
- file: "docs/governance/ssot-v1.0.md",
1227
+ file: "docs/governance/ssot-v1.1.md",
1212
1228
  needle: "automatically govern every Markdown file",
1213
1229
  message: "SSOT rule must state that not every Markdown file is governed."
1214
1230
  },
@@ -1240,6 +1256,7 @@ function checkRouterIntegrity(rootDir = process.cwd()) {
1240
1256
  if (!isCentral) {
1241
1257
  issues.push(...validateProjectAgentsRouting(rootDir));
1242
1258
  }
1259
+ issues.push(...validateHostSsot(rootDir));
1243
1260
  for (const file of FORBIDDEN_LEGACY_PATHS) {
1244
1261
  if (existsSync6(join8(rootDir, file))) {
1245
1262
  issues.push({
@@ -1259,6 +1276,15 @@ function checkRouterIntegrity(rootDir = process.cwd()) {
1259
1276
  });
1260
1277
  }
1261
1278
  }
1279
+ for (const file of SUPERSEDED_PROJECT_CONTRACT_PATHS) {
1280
+ if (existsSync6(join8(rootDir, file))) {
1281
+ issues.push({
1282
+ file,
1283
+ code: "superseded-project-contract",
1284
+ message: `Superseded governance contract must not remain installed in a project: ${file}. Sync the current v1.1 contract instead.`
1285
+ });
1286
+ }
1287
+ }
1262
1288
  for (const file of FORBIDDEN_PROJECT_ROOTS) {
1263
1289
  if (existsSync6(join8(rootDir, file))) {
1264
1290
  issues.push({
@@ -1303,7 +1329,6 @@ function checkRouterIntegrity(rootDir = process.cwd()) {
1303
1329
  issues.push(...validateRouterBlock(rootDir, file));
1304
1330
  }
1305
1331
  issues.push(...validateBacktickedLocalPaths(rootDir, "AGENTS.md"));
1306
- issues.push(...validateBacktickedLocalPaths(rootDir, "CLAUDE.md"));
1307
1332
  issues.push(...validateBacktickedLocalPaths(rootDir, "README.md"));
1308
1333
  if (isCentral) {
1309
1334
  issues.push(...validateBacktickedLocalPaths(rootDir, "starter/AGENTS.template.md", "starter"));
@@ -1312,15 +1337,13 @@ function checkRouterIntegrity(rootDir = process.cwd()) {
1312
1337
  "AGENTS.md",
1313
1338
  "README.md",
1314
1339
  "starter/AGENTS.template.md",
1315
- "starter/CLAUDE.template.md",
1316
- "docs/governance/agents-routing/engineering-runtime-v1.0.md",
1317
- "docs/governance/agents-routing/doc-only-v1.0.md"
1340
+ "docs/governance/agents-routing/engineering-runtime-v1.1.md",
1341
+ "docs/governance/agents-routing/doc-only-v1.1.md"
1318
1342
  ] : [
1319
1343
  "AGENTS.md",
1320
- "CLAUDE.md",
1321
1344
  "README.md",
1322
- "docs/governance/agents-routing/engineering-runtime-v1.0.md",
1323
- "docs/governance/agents-routing/doc-only-v1.0.md"
1345
+ "docs/governance/agents-routing/engineering-runtime-v1.1.md",
1346
+ "docs/governance/agents-routing/doc-only-v1.1.md"
1324
1347
  ];
1325
1348
  for (const file of portableRouterFiles) {
1326
1349
  issues.push(...validatePortableRouterText(rootDir, file));
@@ -1330,6 +1353,62 @@ function checkRouterIntegrity(rootDir = process.cwd()) {
1330
1353
  issues
1331
1354
  };
1332
1355
  }
1356
+ function validateHostSsot(rootDir) {
1357
+ const issues = [];
1358
+ validateRegularFile("AGENTS.md");
1359
+ validateExactSymlink("CLAUDE.md", "AGENTS.md");
1360
+ validateDirectory(".agents/skills");
1361
+ validateExactSymlink(".claude/skills", "../.agents/skills");
1362
+ return issues;
1363
+ function validateRegularFile(file) {
1364
+ const stat = safeLstat(join8(rootDir, file));
1365
+ if (!stat || stat.isFile()) return;
1366
+ issues.push({
1367
+ file,
1368
+ code: "invalid-host-ssot-source",
1369
+ message: `${file} must be a regular file and the single source of truth for project instructions.`
1370
+ });
1371
+ }
1372
+ function validateDirectory(file) {
1373
+ const stat = safeLstat(join8(rootDir, file));
1374
+ if (!stat || stat.isDirectory()) return;
1375
+ issues.push({
1376
+ file,
1377
+ code: "invalid-host-ssot-source",
1378
+ message: `${file} must be a real directory and the single source of truth for project skills.`
1379
+ });
1380
+ }
1381
+ function validateExactSymlink(file, expectedRawTarget) {
1382
+ const path = join8(rootDir, file);
1383
+ const stat = safeLstat(path);
1384
+ if (!stat) return;
1385
+ if (!stat.isSymbolicLink()) {
1386
+ issues.push({
1387
+ file,
1388
+ code: "invalid-host-ssot-adapter",
1389
+ message: `${file} must be a symbolic link with the exact relative target ${expectedRawTarget}.`
1390
+ });
1391
+ return;
1392
+ }
1393
+ const rawTarget = readlinkSync(path);
1394
+ if (rawTarget !== expectedRawTarget) {
1395
+ issues.push({
1396
+ file,
1397
+ code: "noncanonical-host-ssot-adapter",
1398
+ message: `${file} must use the exact relative symlink target ${expectedRawTarget}; found ${rawTarget}.`
1399
+ });
1400
+ }
1401
+ }
1402
+ }
1403
+ function safeLstat(path) {
1404
+ try {
1405
+ return lstatSync2(path);
1406
+ } catch (error) {
1407
+ const code = error.code;
1408
+ if (code === "ENOENT" || code === "ENOTDIR") return void 0;
1409
+ throw error;
1410
+ }
1411
+ }
1333
1412
  function isCentralRepository(rootDir) {
1334
1413
  const packageJsonPath = join8(rootDir, "package.json");
1335
1414
  if (!existsSync6(packageJsonPath)) return false;
@@ -1445,8 +1524,12 @@ function validatePortableRouterText(rootDir, file) {
1445
1524
  ];
1446
1525
  }
1447
1526
  function hasNonPortablePath(content) {
1527
+ const withoutCanonicalSkillCompatibilityTarget = content.replace(
1528
+ /(^|[\s`'"])\.\.\/\.agents\/skills(?=$|[\s`'"),.;:\]}])/gm,
1529
+ "$1"
1530
+ );
1448
1531
  return /(^|[\s`'"])(\/Users\/|~\/|\$HOME(?:\/|\b)|%USERPROFILE%|[A-Za-z]:\\|\.\.\/)/.test(
1449
- content
1532
+ withoutCanonicalSkillCompatibilityTarget
1450
1533
  ) || /\b(OneDrive|CloudStorage)\b/.test(content);
1451
1534
  }
1452
1535
  function findGovernedReadmes(rootDir) {
@@ -1935,8 +2018,9 @@ function runInit(args2) {
1935
2018
  console.log(`
1936
2019
  Next steps for a brand-new project:`);
1937
2020
  console.log(` 1. Copy starter/AGENTS.template.md to AGENTS.md and fill the project name.`);
1938
- console.log(` Copy starter/CLAUDE.template.md to CLAUDE.md as the Claude adapter.`);
1939
- console.log(` 2. Copy starter/docs/governance/boundary.md, ssot-v1.0.md,`);
2021
+ console.log(` Create .agents/skills as the canonical project skill directory.`);
2022
+ console.log(` Link CLAUDE.md -> AGENTS.md and .claude/skills -> ../.agents/skills.`);
2023
+ console.log(` 2. Copy starter/docs/governance/boundary.md, ssot-v1.1.md,`);
1940
2024
  console.log(` doc-agent-rules.md, doc-types.md, and one agents-routing file.`);
1941
2025
  console.log(` 3. Copy starter/docs/policy/best-practice-for-this-project.md and replace`);
1942
2026
  console.log(` placeholder policy with this project's real AI/development rules.`);
@@ -1975,8 +2059,8 @@ function runLinks() {
1975
2059
  import { existsSync as existsSync10, readFileSync as readFileSync9 } from "node:fs";
1976
2060
  import { join as join12 } from "node:path";
1977
2061
  var PROFILE_ROUTES = {
1978
- "engineering-runtime": "docs/governance/agents-routing/engineering-runtime-v1.0.md",
1979
- "doc-only": "docs/governance/agents-routing/doc-only-v1.0.md"
2062
+ "engineering-runtime": "docs/governance/agents-routing/engineering-runtime-v1.1.md",
2063
+ "doc-only": "docs/governance/agents-routing/doc-only-v1.1.md"
1980
2064
  };
1981
2065
  function runMigrate(args2) {
1982
2066
  const checkOnly = args2.includes("--check");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pieai/doc-gov",
3
- "version": "0.5.3",
3
+ "version": "0.6.0",
4
4
  "description": "AI-native documentation governance CLI for project docs, agent routing, and lifecycle checks.",
5
5
  "keywords": [
6
6
  "ai-agents",