@open-agent-toolkit/cli 0.2.66 → 0.2.68

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 (118) hide show
  1. package/assets/bundle-metadata.json +1 -1
  2. package/assets/docs/cli-utilities/configuration.md +14 -1
  3. package/assets/docs/cli-utilities/project-log.md +63 -4
  4. package/assets/docs/contributing/code.md +8 -4
  5. package/assets/docs/contributing/skills.md +29 -17
  6. package/assets/docs/docs-tooling/commands.md +3 -1
  7. package/assets/docs/provider-sync/manifest-and-drift.md +2 -18
  8. package/assets/docs/provider-sync/scope-and-surface.md +3 -2
  9. package/assets/docs/reference/cli-reference.md +1 -1
  10. package/assets/docs/workflows/projects/evidence-layers.md +6 -3
  11. package/assets/docs/workflows/projects/implementation-execution.md +4 -3
  12. package/assets/docs/workflows/projects/lifecycle.md +17 -0
  13. package/assets/docs/workflows/projects/orchestration-model.md +6 -4
  14. package/assets/docs/workflows/projects/picking-up-projects.md +18 -0
  15. package/assets/docs/workflows/skills/repo-improve.md +7 -3
  16. package/assets/public-package-versions.json +4 -4
  17. package/assets/skills/create-agnostic-skill/SKILL.md +19 -37
  18. package/assets/skills/create-agnostic-skill/references/docs/skills-guide.md +58 -15
  19. package/assets/skills/create-agnostic-skill/references/skill-template.md +17 -15
  20. package/assets/skills/oat-agent-instructions-apply/SKILL.md +1 -1
  21. package/assets/skills/oat-agent-instructions-apply/references/instruction-file-templates/glob-scoped-rule.md +1 -4
  22. package/assets/skills/oat-dispatch-subagents/SKILL.md +4 -2
  23. package/assets/skills/oat-doctor/SKILL.md +1 -4
  24. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +3 -2
  25. package/assets/skills/oat-project-complete/SKILL.md +158 -30
  26. package/assets/skills/oat-project-complete/scripts/finalize-synced-archive.mjs +26 -7
  27. package/assets/skills/oat-project-complete/scripts/validate-durable-archive-receipt.mjs +183 -0
  28. package/assets/skills/oat-project-dispatch-subagents/SKILL.md +9 -7
  29. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +3 -2
  30. package/assets/skills/oat-project-implement/SKILL.md +1 -1
  31. package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +11 -10
  32. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +3 -2
  33. package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +3 -2
  34. package/assets/skills/oat-project-plan-writing/SKILL.md +7 -6
  35. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +3 -2
  36. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +3 -2
  37. package/assets/skills/oat-project-retro/SKILL.md +1 -1
  38. package/assets/skills/oat-project-retro/references/apply-procedure.md +11 -0
  39. package/assets/skills/oat-project-review-provide/SKILL.md +14 -13
  40. package/assets/skills/oat-project-review-provide-remote/SKILL.md +7 -6
  41. package/assets/skills/oat-project-summary/SKILL.md +24 -2
  42. package/assets/skills/oat-repo-improve/SKILL.md +9 -2
  43. package/assets/skills/oat-repo-improve/references/plan-template.md +4 -6
  44. package/assets/skills/oat-repo-knowledge-index/SKILL.md +11 -9
  45. package/assets/skills/oat-wave-execute/SKILL.md +20 -6
  46. package/assets/skills/oat-wave-program/SKILL.md +9 -4
  47. package/dist/commands/config/index.d.ts +2 -1
  48. package/dist/commands/config/index.d.ts.map +1 -1
  49. package/dist/commands/config/index.js +133 -38
  50. package/dist/commands/docs/index-generate/index.d.ts.map +1 -1
  51. package/dist/commands/docs/index-generate/index.js +68 -12
  52. package/dist/commands/docs/init/index.d.ts +11 -0
  53. package/dist/commands/docs/init/index.d.ts.map +1 -1
  54. package/dist/commands/docs/init/index.js +19 -1
  55. package/dist/commands/gate/index.d.ts.map +1 -1
  56. package/dist/commands/gate/index.js +10 -2
  57. package/dist/commands/instructions/instructions.utils.d.ts.map +1 -1
  58. package/dist/commands/instructions/instructions.utils.js +42 -9
  59. package/dist/commands/internal/validate-skill-version-bumps.d.ts.map +1 -1
  60. package/dist/commands/internal/validate-skill-version-bumps.js +5 -5
  61. package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -1
  62. package/dist/commands/project/dispatch-ceiling/index.js +32 -18
  63. package/dist/commands/project/log/append.d.ts +48 -0
  64. package/dist/commands/project/log/append.d.ts.map +1 -1
  65. package/dist/commands/project/log/append.js +207 -30
  66. package/dist/commands/project/log/check.d.ts +87 -1
  67. package/dist/commands/project/log/check.d.ts.map +1 -1
  68. package/dist/commands/project/log/check.js +139 -5
  69. package/dist/commands/project/log/grammar.d.ts +165 -0
  70. package/dist/commands/project/log/grammar.d.ts.map +1 -1
  71. package/dist/commands/project/log/grammar.js +219 -1
  72. package/dist/commands/project/log/rollup.d.ts +16 -1
  73. package/dist/commands/project/log/rollup.d.ts.map +1 -1
  74. package/dist/commands/project/log/rollup.js +22 -2
  75. package/dist/commands/project/log/synthesize.d.ts +16 -0
  76. package/dist/commands/project/log/synthesize.d.ts.map +1 -1
  77. package/dist/commands/project/log/synthesize.js +85 -9
  78. package/dist/commands/status/index.d.ts.map +1 -1
  79. package/dist/commands/status/index.js +24 -2
  80. package/dist/commands/sync/apply.d.ts.map +1 -1
  81. package/dist/commands/sync/apply.js +6 -4
  82. package/dist/config/dispatch-matrix.d.ts.map +1 -1
  83. package/dist/config/dispatch-matrix.js +13 -5
  84. package/dist/config/oat-config.d.ts +15 -0
  85. package/dist/config/oat-config.d.ts.map +1 -1
  86. package/dist/config/oat-config.js +61 -7
  87. package/dist/config/own-keys.d.ts +22 -0
  88. package/dist/config/own-keys.d.ts.map +1 -0
  89. package/dist/config/own-keys.js +32 -0
  90. package/dist/config/resolve.d.ts +11 -0
  91. package/dist/config/resolve.d.ts.map +1 -1
  92. package/dist/config/resolve.js +35 -11
  93. package/dist/config/sync-config.d.ts.map +1 -1
  94. package/dist/config/sync-config.js +16 -0
  95. package/dist/drift/detector.d.ts.map +1 -1
  96. package/dist/drift/detector.js +52 -1
  97. package/dist/drift/skill-view-diagnostic.d.ts.map +1 -1
  98. package/dist/drift/skill-view-diagnostic.js +2 -23
  99. package/dist/engine/compute-plan.d.ts.map +1 -1
  100. package/dist/engine/compute-plan.js +22 -72
  101. package/dist/engine/managed-copy-hash.d.ts +69 -0
  102. package/dist/engine/managed-copy-hash.d.ts.map +1 -0
  103. package/dist/engine/managed-copy-hash.js +175 -0
  104. package/dist/fs/assets.d.ts +11 -0
  105. package/dist/fs/assets.d.ts.map +1 -1
  106. package/dist/fs/assets.js +1 -1
  107. package/dist/manifest/hash.d.ts +110 -0
  108. package/dist/manifest/hash.d.ts.map +1 -1
  109. package/dist/manifest/hash.js +111 -13
  110. package/dist/providers/ceiling/registry.d.ts.map +1 -1
  111. package/dist/providers/ceiling/registry.js +6 -1
  112. package/dist/providers/identity/dispatch-report.d.ts.map +1 -1
  113. package/dist/providers/identity/dispatch-report.js +4 -1
  114. package/dist/release/public-package-contract.d.ts.map +1 -1
  115. package/dist/release/public-package-contract.js +21 -0
  116. package/dist/validation/skills.d.ts.map +1 -1
  117. package/dist/validation/skills.js +305 -40
  118. package/package.json +2 -2
@@ -12,6 +12,17 @@
12
12
  * caller has to satisfy.
13
13
  */
14
14
  export type AssetsRootSource = 'packaged' | 'override';
15
+ /**
16
+ * Top-level directories `packages/cli/scripts/bundle-assets.sh` creates for
17
+ * every bundle, listed in the order that script creates them. The producer
18
+ * makes all of them unconditionally — even when a category has no entries — so
19
+ * their presence is the cheapest structural contract that tells a complete
20
+ * bundle apart from a metadata-only or truncated one.
21
+ *
22
+ * This is deliberately a shape check and nothing more: no per-file manifest,
23
+ * no checksums, and no walk of the bundled documents.
24
+ */
25
+ export declare const REQUIRED_BUNDLE_DIRECTORIES: readonly ['skills', 'agents', 'templates', 'scripts', 'docs', 'migration', 'config'];
15
26
  /**
16
27
  * Fail closed on any bundle a consumer must not read as a legitimate install.
17
28
  *
@@ -1 +1 @@
1
- {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/fs/assets.ts"],"names":[],"mappings":"AAeA;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,UAAU,CAAC;AA4IvD;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,eAAe,SAAc,EAC7B,MAAM,GAAE,gBAA6B,GACpC,OAAO,CAAC,IAAI,CAAC,CAsCf;AAQD;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,MAAM,CAAC,CA8BjB"}
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/fs/assets.ts"],"names":[],"mappings":"AAeA;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,UAAU,CAAC;AA0CvD;;;;;;;;;GASG;AACH,eAAO,MAAM,2BAA2B,YACtC,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,SAAS,EACT,MAAM,EACN,WAAW,EACX,QAAQ,CACA,CAAC;AAgFX;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,eAAe,SAAc,EAC7B,MAAM,GAAE,gBAA6B,GACpC,OAAO,CAAC,IAAI,CAAC,CAsCf;AAQD;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,MAAM,CAAC,CA8BjB"}
package/dist/fs/assets.js CHANGED
@@ -45,7 +45,7 @@ function assetsRemedy(source, packagedRemedy = PACKAGED_BUNDLE_REMEDY) {
45
45
  * This is deliberately a shape check and nothing more: no per-file manifest,
46
46
  * no checksums, and no walk of the bundled documents.
47
47
  */
48
- const REQUIRED_BUNDLE_DIRECTORIES = [
48
+ export const REQUIRED_BUNDLE_DIRECTORIES = [
49
49
  'skills',
50
50
  'agents',
51
51
  'templates',
@@ -1,5 +1,115 @@
1
+ import { type Hash } from 'node:crypto';
1
2
  export declare function computeStringHash(content: string): string;
2
3
  export declare function computeFileHash(filePath: string): Promise<string>;
3
4
  export declare function computeContentHash(contentPath: string, isFile: boolean): Promise<string>;
5
+ /**
6
+ * The digests of a directory tree: the sorted `(relativePath, content)` list of
7
+ * every regular file under it, hashed with SHA-256.
8
+ *
9
+ * ## Length framing (wave-7 final review, Critical 4)
10
+ *
11
+ * `framed` is the digest every caller compares. The stream opens with a fixed
12
+ * domain tag and then, for every file in order, each field carries its own byte
13
+ * length ahead of its bytes — `<byteLength> NUL <bytes>` for the relative path,
14
+ * then the same for the content. That makes the stream a self-delimiting
15
+ * encoding of the sorted file list, so two distinct file lists cannot produce
16
+ * the same stream. Files are ordered by their UTF-8 path bytes rather than by
17
+ * `localeCompare`, which is not a total order (distinct Unicode spellings can
18
+ * compare equal) and would otherwise leave the digest dependent on directory
19
+ * enumeration order and the host's ICU data.
20
+ *
21
+ * `legacy` is the digest this module produced before that change: a bare
22
+ * `relPath NUL content NUL …` stream, ordered by `localeCompare`. A relative
23
+ * path cannot contain NUL but file *content* can, so the stream did not
24
+ * determine the file set. The review's witness:
25
+ * `{references/p.md: "P", references/q.md: "Q"}` and the
26
+ * single file `{references/p.md: "P\0references/q.md\0Q"}` both hashed to
27
+ * `2bb17da7d373d82dd09024613a5bc31764837c2590441dfbc0eda55d3bcd283c`. A forged
28
+ * provider view could therefore delete `SKILL.md`, fuse its bytes into a
29
+ * surviving file, and still reproduce the canonical digest — reading `in_sync`
30
+ * with `oat sync` planning `skip`, permanently healthy-looking and
31
+ * unrepairable.
32
+ *
33
+ * The domain tag is what keeps the two encodings apart, and it is load-bearing
34
+ * rather than decorative. A recorded `contentHash` carries no version, so a
35
+ * legacy value is compared against framed values — including by the raw fast
36
+ * path in `drift/detector.ts` that runs before any marker or sentinel check.
37
+ * Without separation those namespaces overlap: the canonical tree
38
+ * `{"8": "SKILL.md26\0# evil\n", "SKILL.md": "# skill\n"}` and the single-file
39
+ * provider tree `{"SKILL.md": "# evil\n\0SKILL.md\0# skill\n\0"}` emit the
40
+ * identical byte string under the legacy and framed encoders respectively
41
+ * (`1b83055cfb0680a8f70cdb66ba4902a6a48627f5584b0ae3bbebf9fc44830b70`), so an
42
+ * undecorated forged view would have been accepted. The tag opens the framed
43
+ * stream with a NUL byte; a legacy stream opens with a relative path and paths
44
+ * cannot contain NUL, so the two encoders' input spaces are disjoint and no
45
+ * framed digest equals a legacy digest under SHA-256 collision resistance —
46
+ * the same assumption every other comparison here already rests on.
47
+ *
48
+ * `legacy` is retained for exactly one purpose: `drift/detector.ts` uses it to
49
+ * recognize a manifest written before the framing change and re-decide with
50
+ * `framed`. It is never an acceptance basis for provider content on its own.
51
+ * The migration is needed because framing changes every recorded
52
+ * `contentHash`, and `oat sync` plans `skip` for a faithful tree while
53
+ * `ensureSkipEntryManaged` (`engine/execute-plan.ts`) does not restamp an entry
54
+ * it already owns — so a legacy value is never rewritten by a no-op sync.
55
+ * Measured on the built CLI: a directory-copy entry whose `contentHash` no
56
+ * longer matches reports `drifted/modified` from `oat status`, `oat sync`
57
+ * answers `skip` / "already in sync", and the manifest keeps the old value.
58
+ *
59
+ * ## Bounds this digest still does not cover
60
+ *
61
+ * Both recorded rather than closed (wave-7 final review, Important 5, and
62
+ * `BL-260909-use-handle-bound-traversal`): file mode bits and empty
63
+ * directories. A provider view differing from canonical only in those respects
64
+ * still digests equal. Framing addresses file-set ambiguity, not the set of
65
+ * attributes hashed.
66
+ */
67
+ export interface DirectoryDigests {
68
+ framed: string;
69
+ legacy: string;
70
+ }
71
+ /**
72
+ * Opens a framed directory digest with the domain tag.
73
+ *
74
+ * Exported alongside `compareDirectoryRelativePaths` and
75
+ * `updateFramedDirectoryDigest` so `engine/managed-copy-hash.ts` shares this
76
+ * exact encoding rather than mirroring it. The three must agree byte for byte:
77
+ * a faithful managed copy has to reproduce the canonical `framed` digest that
78
+ * `engine/execute-plan.ts` records as the manifest `contentHash`, and
79
+ * `managed-copy-hash.test.ts` pins that equality.
80
+ */
81
+ export declare function createFramedDirectoryDigest(): Hash;
82
+ /** Total order over distinct relative paths, by UTF-8 bytes. */
83
+ export declare function compareDirectoryRelativePaths(left: string, right: string): number;
84
+ /**
85
+ * Contributes one file to a framed directory digest.
86
+ */
87
+ export declare function updateFramedDirectoryDigest(hash: Hash, relativePath: string, content: Buffer): void;
88
+ /**
89
+ * Both digests of a directory tree, derived from one traversal that reads each
90
+ * file exactly once.
91
+ *
92
+ * The single capture is load-bearing, not an optimization. Computing the two
93
+ * encodings from two separate traversals would let the canonical tree change
94
+ * between them, so the pre-framing bridge in `drift/detector.ts` could pair
95
+ * `framed` from one canonical state with `legacy` from another and accept a
96
+ * provider view that the pre-framing detector rejected. Both digests must
97
+ * describe the same captured file set. The residual per-file race — the tree
98
+ * mutating partway through a single traversal — is the pre-existing bound
99
+ * every filesystem reader in this package shares, recorded on
100
+ * `BL-260909-use-handle-bound-traversal`.
101
+ *
102
+ * Only the bridge needs `legacy`, and it asks only after a comparison has
103
+ * already failed, so buffering the tree here does not touch the hot path:
104
+ * `computeDirectoryHash` still streams file by file.
105
+ */
106
+ export declare function computeDirectoryDigests(dirPath: string): Promise<DirectoryDigests>;
107
+ /**
108
+ * The framed digest of a directory tree.
109
+ *
110
+ * Streams file by file rather than capturing the tree, because this is the
111
+ * digest every ordinary caller computes. `hash.test.ts` pins that it agrees
112
+ * with `computeDirectoryDigests(...).framed`.
113
+ */
4
114
  export declare function computeDirectoryHash(dirPath: string): Promise<string>;
5
115
  //# sourceMappingURL=hash.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/manifest/hash.ts"],"names":[],"mappings":"AAMA,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIzD;AAqBD,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBvE;AAED,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAyC3E"}
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/manifest/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAMpD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIzD;AAqBD,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBvE;AAED,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,MAAM,CAAC,CAIjB;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,IAAI,IAAI,CAIlD;AAED,gEAAgE;AAChE,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,MAAM,CAER;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,GACd,IAAI,CAMN;AAgFD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,gBAAgB,CAAC,CAe3B;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB3E"}
@@ -42,7 +42,43 @@ export async function computeContentHash(contentPath, isFile) {
42
42
  ? computeFileHash(contentPath)
43
43
  : computeDirectoryHash(contentPath);
44
44
  }
45
- export async function computeDirectoryHash(dirPath) {
45
+ const FRAMED_DIRECTORY_DIGEST_DOMAIN = '\0oat-directory-digest-v2\0';
46
+ /**
47
+ * Opens a framed directory digest with the domain tag.
48
+ *
49
+ * Exported alongside `compareDirectoryRelativePaths` and
50
+ * `updateFramedDirectoryDigest` so `engine/managed-copy-hash.ts` shares this
51
+ * exact encoding rather than mirroring it. The three must agree byte for byte:
52
+ * a faithful managed copy has to reproduce the canonical `framed` digest that
53
+ * `engine/execute-plan.ts` records as the manifest `contentHash`, and
54
+ * `managed-copy-hash.test.ts` pins that equality.
55
+ */
56
+ export function createFramedDirectoryDigest() {
57
+ const hash = createHash('sha256');
58
+ hash.update(FRAMED_DIRECTORY_DIGEST_DOMAIN);
59
+ return hash;
60
+ }
61
+ /** Total order over distinct relative paths, by UTF-8 bytes. */
62
+ export function compareDirectoryRelativePaths(left, right) {
63
+ return Buffer.compare(Buffer.from(left, 'utf8'), Buffer.from(right, 'utf8'));
64
+ }
65
+ /**
66
+ * Contributes one file to a framed directory digest.
67
+ */
68
+ export function updateFramedDirectoryDigest(hash, relativePath, content) {
69
+ const pathBytes = Buffer.from(relativePath, 'utf8');
70
+ hash.update(`${pathBytes.length}\0`);
71
+ hash.update(pathBytes);
72
+ hash.update(`${content.length}\0`);
73
+ hash.update(content);
74
+ }
75
+ function updateLegacyDirectoryDigest(hash, relativePath, content) {
76
+ hash.update(relativePath);
77
+ hash.update('\0');
78
+ hash.update(content);
79
+ hash.update('\0');
80
+ }
81
+ async function collectDirectoryFiles(dirPath) {
46
82
  const root = resolve(dirPath);
47
83
  const files = [];
48
84
  try {
@@ -57,19 +93,81 @@ export async function computeDirectoryHash(dirPath) {
57
93
  }
58
94
  throw new CliError(`Failed to compute hash for ${dirPath}: ${error instanceof Error ? error.message : 'unknown error'}`, 2);
59
95
  }
60
- files.sort((left, right) => {
61
- const leftRelative = relative(root, left);
62
- const rightRelative = relative(root, right);
63
- return leftRelative.localeCompare(rightRelative);
64
- });
65
- const hash = createHash('sha256');
96
+ return files;
97
+ }
98
+ /**
99
+ * Orders a captured file list for one encoding and folds it into a digest.
100
+ *
101
+ * Each encoding keeps its own ordering: the legacy digest has to stay
102
+ * byte-reproducible to remain recognizable, while the framed digest wants a
103
+ * total order, which `localeCompare` does not provide (distinct Unicode
104
+ * spellings can compare equal, leaving the result dependent on directory
105
+ * enumeration order and the host's ICU data).
106
+ */
107
+ function digestDirectoryRecords(records, encoding) {
108
+ const ordered = [...records].sort(encoding === 'framed'
109
+ ? (left, right) => compareDirectoryRelativePaths(left.relativePath, right.relativePath)
110
+ : (left, right) => left.relativePath.localeCompare(right.relativePath));
111
+ const hash = encoding === 'framed'
112
+ ? createFramedDirectoryDigest()
113
+ : createHash('sha256');
114
+ for (const record of ordered) {
115
+ if (encoding === 'framed') {
116
+ updateFramedDirectoryDigest(hash, record.relativePath, record.content);
117
+ }
118
+ else {
119
+ updateLegacyDirectoryDigest(hash, record.relativePath, record.content);
120
+ }
121
+ }
122
+ return hash.digest('hex');
123
+ }
124
+ /**
125
+ * Both digests of a directory tree, derived from one traversal that reads each
126
+ * file exactly once.
127
+ *
128
+ * The single capture is load-bearing, not an optimization. Computing the two
129
+ * encodings from two separate traversals would let the canonical tree change
130
+ * between them, so the pre-framing bridge in `drift/detector.ts` could pair
131
+ * `framed` from one canonical state with `legacy` from another and accept a
132
+ * provider view that the pre-framing detector rejected. Both digests must
133
+ * describe the same captured file set. The residual per-file race — the tree
134
+ * mutating partway through a single traversal — is the pre-existing bound
135
+ * every filesystem reader in this package shares, recorded on
136
+ * `BL-260909-use-handle-bound-traversal`.
137
+ *
138
+ * Only the bridge needs `legacy`, and it asks only after a comparison has
139
+ * already failed, so buffering the tree here does not touch the hot path:
140
+ * `computeDirectoryHash` still streams file by file.
141
+ */
142
+ export async function computeDirectoryDigests(dirPath) {
143
+ const root = resolve(dirPath);
144
+ const files = await collectDirectoryFiles(dirPath);
145
+ const records = [];
66
146
  for (const file of files) {
67
- const relativePath = relative(root, file);
68
- const content = await readFile(file);
69
- hash.update(relativePath);
70
- hash.update('\0');
71
- hash.update(content);
72
- hash.update('\0');
147
+ records.push({
148
+ relativePath: relative(root, file),
149
+ content: await readFile(file),
150
+ });
151
+ }
152
+ return {
153
+ framed: digestDirectoryRecords(records, 'framed'),
154
+ legacy: digestDirectoryRecords(records, 'legacy'),
155
+ };
156
+ }
157
+ /**
158
+ * The framed digest of a directory tree.
159
+ *
160
+ * Streams file by file rather than capturing the tree, because this is the
161
+ * digest every ordinary caller computes. `hash.test.ts` pins that it agrees
162
+ * with `computeDirectoryDigests(...).framed`.
163
+ */
164
+ export async function computeDirectoryHash(dirPath) {
165
+ const root = resolve(dirPath);
166
+ const files = await collectDirectoryFiles(dirPath);
167
+ files.sort((left, right) => compareDirectoryRelativePaths(relative(root, left), relative(root, right)));
168
+ const hash = createFramedDirectoryDigest();
169
+ for (const file of files) {
170
+ updateFramedDirectoryDigest(hash, relative(root, file), await readFile(file));
73
171
  }
74
172
  return hash.digest('hex');
75
173
  }
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/providers/ceiling/registry.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,oBAAoB,GAAG,gBAAgB,GAAG,WAAW,GAAG,MAAM,CAAC;AAC3E,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,cAAc,GAAG,MAAM,GAAG,MAAM,CAAC;AAE/E,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,UAAU,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,IAAI,CAAC;CACV;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GACnB;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACjB,IAAI,CAAC;AAKT,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,OAAO,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,oBAAoB,CAAC;IAChC,aAAa,EAAE,qBAAqB,CAAC;IACrC;;;OAGG;IACH,qBAAqB,CACnB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,qBAAqB,GACzB,mBAAmB,CAAC;IACvB;;;;OAIG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC;CACtE;AAMD,wEAAwE;AACxE,eAAO,MAAM,iBAAiB,EAAE,SAAS,MAAM,EAK9C,CAAC;AA6HF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,sBAAsB,CAE1E"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/providers/ceiling/registry.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,oBAAoB,GAAG,gBAAgB,GAAG,WAAW,GAAG,MAAM,CAAC;AAC3E,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,cAAc,GAAG,MAAM,GAAG,MAAM,CAAC;AAE/E,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,UAAU,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,IAAI,CAAC;CACV;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GACnB;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACjB,IAAI,CAAC;AAKT,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,OAAO,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,oBAAoB,CAAC;IAChC,aAAa,EAAE,qBAAqB,CAAC;IACrC;;;OAGG;IACH,qBAAqB,CACnB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,qBAAqB,GACzB,mBAAmB,CAAC;IACvB;;;;OAIG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC;CACtE;AAMD,wEAAwE;AACxE,eAAO,MAAM,iBAAiB,EAAE,SAAS,MAAM,EAK9C,CAAC;AA6HF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,sBAAsB,CAM1E"}
@@ -1,4 +1,5 @@
1
1
  import { VALID_CLAUDE_DISPATCH_CEILINGS, VALID_CODEX_DISPATCH_CEILINGS, } from '../../config/oat-config.js';
2
+ import { getOwnKey } from '../../config/own-keys.js';
2
3
  import { buildCodexMaterializedTargetRoleName } from '../codex/codec/shared.js';
3
4
  import { findCursorModelPinMapping } from '../cursor/codec/catalog.js';
4
5
  import { buildCursorMaterializedRoleName } from '../cursor/codec/shared.js';
@@ -128,5 +129,9 @@ const REGISTERED_ADAPTERS = {
128
129
  * `compileToDispatchArgs → null`).
129
130
  */
130
131
  export function getCeilingAdapter(provider) {
131
- return REGISTERED_ADAPTERS[provider] ?? advisoryAdapter(provider);
132
+ // Own-key read: `provider` is user-supplied (`--provider <name>`), and a
133
+ // bare lookup for `__proto__` returns `Object.prototype`, which is neither
134
+ // nullish nor an adapter, so the `??` fallback above would be skipped and
135
+ // callers would read `undefined` for `mechanism` and `supportsCeiling`.
136
+ return getOwnKey(REGISTERED_ADAPTERS, provider) ?? advisoryAdapter(provider);
132
137
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch-report.d.ts","sourceRoot":"","sources":["../../../src/providers/identity/dispatch-report.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dispatch-report.d.ts","sourceRoot":"","sources":["../../../src/providers/identity/dispatch-report.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { getOwnKey } from '../../config/own-keys.js';
1
2
  const ROLE_BY_ACTION = {
2
3
  implementation: 'implementer',
3
4
  fix: 'fix',
@@ -180,7 +181,9 @@ function dispatchCeiling(report) {
180
181
  }
181
182
  export function buildDispatchReport(input) {
182
183
  assertActionRole(input.action, input.role);
183
- const provider = input.resolution.providers[input.resolution.provider];
184
+ // `resolution.provider` is a plain string, and the check below is a
185
+ // truthiness test that an inherited `Object.prototype` member would pass.
186
+ const provider = getOwnKey(input.resolution.providers, input.resolution.provider);
184
187
  if (!provider) {
185
188
  throw new Error(`Dispatch report resolution is missing provider data for "${input.resolution.provider}".`);
186
189
  }
@@ -1 +1 @@
1
- {"version":3,"file":"public-package-contract.d.ts","sourceRoot":"","sources":["../../src/release/public-package-contract.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,KAAK,GAAG,cAAc,GAAG,iBAAiB,CAAC;IACjD,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,uBAAuB,EAAE,yBAAyB,EAAE,CAAC;IACrD,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,4BAA4B,EAAE,MAAM,EAAE,CAAC;IACvC,2BAA2B,EAAE,MAAM,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AA6KD,wBAAgB,yBAAyB,IAAI,qBAAqB,EAAE,CAenE;AAED,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAIV;AAED,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAIV;AAED,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAMV;AAED,wBAAgB,6BAA6B,CAC3C,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EACjD,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAoBV;AAED,wBAAgB,oCAAoC,CAClD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,MAAM,EAAE,CAmBV;AAED,wBAAgB,qCAAqC,CACnD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,kBAAkB,EAAE,SAAS,MAAM,EAAE,EACrC,qBAAqB,EAAE,SAAS,MAAM,EAAE,GACvC,MAAM,EAAE,CA0BV"}
1
+ {"version":3,"file":"public-package-contract.d.ts","sourceRoot":"","sources":["../../src/release/public-package-contract.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,KAAK,GAAG,cAAc,GAAG,iBAAiB,CAAC;IACjD,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,uBAAuB,EAAE,yBAAyB,EAAE,CAAC;IACrD,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,4BAA4B,EAAE,MAAM,EAAE,CAAC;IACvC,2BAA2B,EAAE,MAAM,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAkMD,wBAAgB,yBAAyB,IAAI,qBAAqB,EAAE,CAenE;AAED,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAIV;AAED,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAIV;AAED,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAMV;AAED,wBAAgB,6BAA6B,CAC3C,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EACjD,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAoBV;AAED,wBAAgB,oCAAoC,CAClD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,MAAM,EAAE,CAmBV;AAED,wBAAgB,qCAAqC,CACnD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,kBAAkB,EAAE,SAAS,MAAM,EAAE,EACrC,qBAAqB,EAAE,SAAS,MAAM,EAAE,GACvC,MAAM,EAAE,CA0BV"}
@@ -46,6 +46,27 @@ const PUBLIC_PACKAGE_CONTRACTS = [
46
46
  'dist/index.js',
47
47
  'assets',
48
48
  'assets/bundle-metadata.json',
49
+ // Every name in `REQUIRED_BUNDLE_DIRECTORIES` (src/fs/assets.ts) keeps at
50
+ // least one concrete packed path in this list. `npm pack` drops empty
51
+ // directories, so without these entries a producer regression that
52
+ // emptied one of them published a tarball whose every command exits 2
53
+ // from `validateBundleStructure` while every release check stayed green:
54
+ // the bare `assets` entry above is satisfied by any single file anywhere
55
+ // under `assets/`, and the directory itself still existed in the build
56
+ // workspace. Naming a file under each directory closes that at both
57
+ // layers — `findMissingBuildArtifacts` for the build workspace and
58
+ // `findMissingPackedPaths` for the packed tarball.
59
+ //
60
+ // Two checks in `public-package-contract.test.ts` hold this list to the
61
+ // runtime one: `guards a packed path under every required bundle
62
+ // directory` derives its expectation from `REQUIRED_BUNDLE_DIRECTORIES`
63
+ // rather than restating it, and `fails release validation when a
64
+ // required bundle directory is empty in the tarball` is the negative
65
+ // pack control.
66
+ 'assets/agents/oat-reviewer.md',
67
+ 'assets/scripts/generate-oat-state.sh',
68
+ 'assets/docs/index.md',
69
+ 'assets/config/dispatch-matrix-recommendation.json',
49
70
  'assets/migration/pjm-restructure.md',
50
71
  'assets/templates/decision.md',
51
72
  'assets/templates/repo-agents.md',
@@ -1 +1 @@
1
- {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/validation/skills.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,uCAAuC;IACtD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sCAAsC;IACrD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,CACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,KAChD,OAAO,CAAC,cAAc,CAAC,CAAC;AAE7B,UAAU,6BAA6B;IACrC,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAwhCD,wBAAsB,gCAAgC,CACpD,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,uCAAuC,EAChD,YAAY,GAAE,6BAAkC,GAC/C,OAAO,CAAC,sCAAsC,CAAC,CAoBjD;AAyED,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,wBAA6B,EACtC,YAAY,GAAE,6BAAkC,GAC/C,OAAO,CAAC,uBAAuB,CAAC,CAyIlC"}
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/validation/skills.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,uCAAuC;IACtD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sCAAsC;IACrD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,CACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,KAChD,OAAO,CAAC,cAAc,CAAC,CAAC;AAE7B,UAAU,6BAA6B;IACrC,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAm0CD,wBAAsB,gCAAgC,CACpD,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,uCAAuC,EAChD,YAAY,GAAE,6BAAkC,GAC/C,OAAO,CAAC,sCAAsC,CAAC,CAsBjD;AAsGD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,wBAA6B,EACtC,YAAY,GAAE,6BAAkC,GAC/C,OAAO,CAAC,uBAAuB,CAAC,CAyIlC"}