@shrkcrft/inspector 0.1.0-alpha.22 → 0.1.0-alpha.24

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 (65) hide show
  1. package/dist/command-recommender.d.ts.map +1 -1
  2. package/dist/command-recommender.js +110 -1
  3. package/dist/context-tuning.d.ts +14 -0
  4. package/dist/context-tuning.d.ts.map +1 -0
  5. package/dist/context-tuning.js +38 -0
  6. package/dist/coverage-report.d.ts.map +1 -1
  7. package/dist/coverage-report.js +31 -8
  8. package/dist/git-helpers.d.ts.map +1 -1
  9. package/dist/git-helpers.js +10 -1
  10. package/dist/index.d.ts +2 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +2 -0
  13. package/dist/knowledge-stale.d.ts +23 -0
  14. package/dist/knowledge-stale.d.ts.map +1 -1
  15. package/dist/knowledge-stale.js +58 -9
  16. package/dist/monorepo-onboarding.d.ts.map +1 -1
  17. package/dist/monorepo-onboarding.js +122 -12
  18. package/dist/onboarding.d.ts.map +1 -1
  19. package/dist/onboarding.js +79 -18
  20. package/dist/pack-doctor.d.ts +8 -1
  21. package/dist/pack-doctor.d.ts.map +1 -1
  22. package/dist/pack-doctor.js +110 -3
  23. package/dist/pack-quality-score.d.ts.map +1 -1
  24. package/dist/pack-quality-score.js +18 -13
  25. package/dist/pack-release-check.d.ts.map +1 -1
  26. package/dist/pack-release-check.js +23 -20
  27. package/dist/pack-signature-status.d.ts +9 -3
  28. package/dist/pack-signature-status.d.ts.map +1 -1
  29. package/dist/pack-signature-status.js +13 -2
  30. package/dist/plan-simulation.d.ts.map +1 -1
  31. package/dist/plan-simulation.js +26 -12
  32. package/dist/registry-lifecycle.d.ts +8 -0
  33. package/dist/registry-lifecycle.d.ts.map +1 -1
  34. package/dist/registry-lifecycle.js +10 -2
  35. package/dist/resolve-project-config.d.ts +26 -0
  36. package/dist/resolve-project-config.d.ts.map +1 -0
  37. package/dist/resolve-project-config.js +136 -0
  38. package/dist/resolve-verification-commands.d.ts +7 -0
  39. package/dist/resolve-verification-commands.d.ts.map +1 -1
  40. package/dist/resolve-verification-commands.js +53 -4
  41. package/dist/review-packet.d.ts +8 -0
  42. package/dist/review-packet.d.ts.map +1 -1
  43. package/dist/review-packet.js +11 -12
  44. package/dist/sharkcraft-inspector.d.ts.map +1 -1
  45. package/dist/sharkcraft-inspector.js +28 -2
  46. package/dist/spec/__tests__/spec-evidence.test.d.ts +2 -0
  47. package/dist/spec/__tests__/spec-evidence.test.d.ts.map +1 -0
  48. package/dist/spec/__tests__/spec-evidence.test.js +81 -0
  49. package/dist/spec/spec-evidence.d.ts +62 -0
  50. package/dist/spec/spec-evidence.d.ts.map +1 -0
  51. package/dist/spec/spec-evidence.js +215 -0
  52. package/dist/spec/spec-review.d.ts +1 -0
  53. package/dist/spec/spec-review.d.ts.map +1 -1
  54. package/dist/spec/spec-review.js +5 -0
  55. package/dist/symbol-index.d.ts +9 -0
  56. package/dist/symbol-index.d.ts.map +1 -1
  57. package/dist/symbol-index.js +6 -0
  58. package/dist/task-packet.d.ts.map +1 -1
  59. package/dist/task-packet.js +6 -1
  60. package/dist/task-ranker.d.ts +2 -1
  61. package/dist/task-ranker.d.ts.map +1 -1
  62. package/dist/task-ranker.js +30 -5
  63. package/dist/test-runner.d.ts.map +1 -1
  64. package/dist/test-runner.js +3 -0
  65. package/package.json +17 -17
@@ -42,14 +42,20 @@ export interface IPackSignatureStatusReport {
42
42
  export declare function buildPackSignatureStatusReport(inspection: ISharkcraftInspection): IPackSignatureStatusReport;
43
43
  /**
44
44
  * Pack signature explanation. Surfaces the distinct lifecycle
45
- * states (`unsigned`, `stale`, `invalid`, `valid`, `secret-missing`,
46
- * `not-required`) per pack with a one-line "why this matters".
45
+ * states (`unsigned`, `stale`, `invalid`, `valid`, `present-unverified`,
46
+ * `dev-signature`, `secret-missing`, `not-required`) per pack with a one-line
47
+ * "why this matters".
47
48
  *
48
49
  * Read-only. Reads `inspection.packs.discoveredPacks[i].signatureStatus`
49
50
  * which already reflects the verifier's outcome when the inspector was
50
51
  * constructed with `verifyPackSignatures: true`.
52
+ *
53
+ * `valid` is reserved STRICTLY for a real HMAC pass (verifier === 'verified').
54
+ * A pack whose signature timestamp is merely fresher than its contribution
55
+ * files — but whose HMAC was not checked this run — is `present-unverified`,
56
+ * never `valid`: freshness is not verification.
51
57
  */
52
- export type PackSignatureExplainState = 'valid' | 'unsigned' | 'stale' | 'invalid' | 'secret-missing' | 'not-required' | 'unknown';
58
+ export type PackSignatureExplainState = 'valid' | 'unsigned' | 'stale' | 'invalid' | 'present-unverified' | 'dev-signature' | 'secret-missing' | 'not-required' | 'unknown';
53
59
  export interface IPackSignatureExplainEntry {
54
60
  readonly packageName: string;
55
61
  readonly packageVersion: string;
@@ -1 +1 @@
1
- {"version":3,"file":"pack-signature-status.d.ts","sourceRoot":"","sources":["../src/pack-signature-status.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,eAAO,MAAM,4BAA4B,wCAAwC,CAAC;AAElF,oBAAY,uBAAuB;IACjC,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,OAAO,YAAY;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IACzC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,MAAM,EAAE,OAAO,4BAA4B,CAAC;IACrD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAC/C,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,sEAAsE;QACtE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AA+BD,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,qBAAqB,GAChC,0BAA0B,CA6G5B;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,yBAAyB,GACjC,OAAO,GACP,UAAU,GACV,OAAO,GACP,SAAS,GACT,gBAAgB,GAChB,cAAc,GACd,SAAS,CAAC;AAEd,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,yBAAyB,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,MAAM,EAAE,sCAAsC,CAAC;IACxD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,SAAS,0BAA0B,EAAE,CAAC;CACvD;AAED,MAAM,WAAW,kCAAkC;IACjD,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,qBAAqB,EACjC,OAAO,GAAE,kCAAuC,GAC/C,2BAA2B,CA6D7B"}
1
+ {"version":3,"file":"pack-signature-status.d.ts","sourceRoot":"","sources":["../src/pack-signature-status.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,eAAO,MAAM,4BAA4B,wCAAwC,CAAC;AAElF,oBAAY,uBAAuB;IACjC,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,OAAO,YAAY;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IACzC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,MAAM,EAAE,OAAO,4BAA4B,CAAC;IACrD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAC/C,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,sEAAsE;QACtE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AA+BD,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,qBAAqB,GAChC,0BAA0B,CA6G5B;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,yBAAyB,GACjC,OAAO,GACP,UAAU,GACV,OAAO,GACP,SAAS,GACT,oBAAoB,GACpB,eAAe,GACf,gBAAgB,GAChB,cAAc,GACd,SAAS,CAAC;AAEd,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,yBAAyB,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,MAAM,EAAE,sCAAsC,CAAC;IACxD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,SAAS,0BAA0B,EAAE,CAAC;CACvD;AAED,MAAM,WAAW,kCAAkC;IACjD,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,qBAAqB,EACjC,OAAO,GAAE,kCAAuC,GAC/C,2BAA2B,CAuE7B"}
@@ -191,6 +191,12 @@ export function explainPackSignatureStatus(inspection, options = {}) {
191
191
  explanation = 'Manifest signature failed HMAC verification — pack contents may have been tampered with.';
192
192
  nextCommand = 'shrk packs verify --required';
193
193
  }
194
+ else if (verifier === 'dev-signature') {
195
+ state = 'dev-signature';
196
+ explanation =
197
+ 'Manifest carries a dev signature — verified only against the well-known public dev secret, NOT release-trusted. Re-sign with the release secret before publishing.';
198
+ nextCommand = secretAvailable ? signCmd : 'shrk packs verify --required --allow-dev-signature';
199
+ }
194
200
  else if (verifier === 'missing-signature' || (!verifier && fresh?.status === 'missing')) {
195
201
  state = 'unsigned';
196
202
  explanation = 'Manifest has no signature block.';
@@ -207,8 +213,13 @@ export function explainPackSignatureStatus(inspection, options = {}) {
207
213
  nextCommand = signCmd;
208
214
  }
209
215
  else if (fresh?.status === 'present') {
210
- state = 'valid';
211
- explanation = 'Signature timestamp is newer than every contribution file.';
216
+ // Freshness only — the HMAC was NOT checked this run. Reserve `valid`
217
+ // strictly for a real verifier pass so a bogus-HMAC-but-fresh-timestamp
218
+ // pack is never mislabelled as verified.
219
+ state = 'present-unverified';
220
+ explanation =
221
+ 'Signature present and newer than every contribution file, but the HMAC was NOT checked this run.';
222
+ nextCommand = 'shrk packs verify --required';
212
223
  }
213
224
  else {
214
225
  state = mode === 'required' ? 'unknown' : 'not-required';
@@ -1 +1 @@
1
- {"version":3,"file":"plan-simulation.d.ts","sourceRoot":"","sources":["../src/plan-simulation.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAmB,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAK3E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,eAAO,MAAM,sBAAsB,kCAAkC,CAAC;AAEtE,oBAAY,8BAA8B;IACxC,KAAK,UAAU;IACf,cAAc,oBAAoB;IAClC,QAAQ,aAAa;IACrB,gBAAgB,sBAAsB;IACtC,UAAU,gBAAgB;CAC3B;AAED,oBAAY,kBAAkB;IAC5B,KAAK,UAAU;IACf,eAAe,sBAAsB;IACrC,gBAAgB,sBAAsB;IACtC,aAAa,mBAAmB;IAChC,eAAe,qBAAqB;IACpC,gBAAgB,sBAAsB;IACtC,oBAAoB,2BAA2B;CAChD;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,8BAA8B,CAAC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB;;qCAEiC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;gCAC4B;IAC5B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,cAAc,EAAE,OAAO,CAAC;IACxB,8CAA8C;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gDAAgD;IAChD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,sBAAsB,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IAC5C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACtC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,uBAAuB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,gBAAgB,EAAE,OAAO,CAAC;IAC1B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,sBAAsB,EAAE,OAAO,CAAC;IAChC,sBAAsB,EAAE,OAAO,CAAC;IAChC,uBAAuB,EAAE,OAAO,CAAC;IACjC,oBAAoB,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,yBAAyB,EAAE,SAAS,0BAA0B,EAAE,CAAC;IACjE,8BAA8B,EAAE,SAAS,0BAA0B,EAAE,CAAC;IACtE,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,cAAc,EAAE,kBAAkB,CAAC;IACnC,qBAAqB,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC,iEAAiE;IACjE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mDAAmD;IACnD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAYD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAoG5K;AA+GD,wBAAsB,YAAY,CAChC,UAAU,EAAE,qBAAqB,EACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC,CAkUhC;AAOD,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAwDzE;AAOD,wBAAgB,4BAA4B,CAAC,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAkD7E;AAWD,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAWzE"}
1
+ {"version":3,"file":"plan-simulation.d.ts","sourceRoot":"","sources":["../src/plan-simulation.ts"],"names":[],"mappings":"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"}
@@ -282,9 +282,11 @@ export async function simulatePlan(inspection, planPath, options = {}) {
282
282
  }
283
283
  // Re-render the template to recover virtual contents (when available).
284
284
  let liveChanges = [];
285
+ let templateRequiredValidations = [];
285
286
  if (plan.templateId) {
286
287
  const template = inspection.templateRegistry.get(plan.templateId);
287
288
  if (template) {
289
+ templateRequiredValidations = template.metadata?.requiredValidations ?? [];
288
290
  try {
289
291
  const dry = planGeneration(template, {
290
292
  templateId: plan.templateId,
@@ -485,20 +487,32 @@ export async function simulatePlan(inspection, planPath, options = {}) {
485
487
  likelyTests.push(`${f.relativePath} → expected ${candidate}`);
486
488
  }
487
489
  }
488
- // Required validations. Prefer the project's OWN configured verification
489
- // commands (config.verificationCommands), so on e.g. an Nx repo that lists
490
- // `nx build <app>` plan-simulate emits that instead of misleading generic
491
- // gates. Falls back to the engine defaults only when nothing is configured.
490
+ // Required validations. The template's OWN declared validations come first
491
+ // (so an Nx lib template can surface `nx build <app>` rather than the generic
492
+ // boilerplate, and two templates can show different lists). We then add the
493
+ // project's authoritative gate set its configured verificationCommands
494
+ // via resolveVerificationCommands. The engine's generic defaults are used
495
+ // ONLY as a fallback when the template declared nothing of its own.
492
496
  // No pipelineIds are passed: a saved plan carries no task query to rank
493
497
  // pipelines against, so resolution is config-driven, not pipeline-matched.
494
- const requiredValidations = new Set(resolveVerificationCommands(inspection, {
495
- knowledgeDefaults: [
496
- 'bun x tsc -p tsconfig.base.json --noEmit',
497
- 'bun test',
498
- 'shrk doctor',
499
- 'shrk check boundaries',
500
- ],
501
- }));
498
+ const requiredValidations = new Set();
499
+ for (const v of templateRequiredValidations) {
500
+ const cmd = v.trim();
501
+ if (cmd.length > 0)
502
+ requiredValidations.add(cmd);
503
+ }
504
+ const resolvedValidations = resolveVerificationCommands(inspection, {
505
+ knowledgeDefaults: templateRequiredValidations.length > 0
506
+ ? []
507
+ : [
508
+ 'bun x tsc -p tsconfig.base.json --noEmit',
509
+ 'bun test',
510
+ 'shrk doctor',
511
+ 'shrk check boundaries',
512
+ ],
513
+ });
514
+ for (const cmd of resolvedValidations)
515
+ requiredValidations.add(cmd);
502
516
  if (publicApiTouched || barrelExportTouched)
503
517
  requiredValidations.add('shrk api report --all --public-only');
504
518
  if (pluginKeysTouched)
@@ -33,6 +33,12 @@ export interface IRegistryIgnored {
33
33
  export interface IRegistryLifecycleReport {
34
34
  schema: 'sharkcraft.registry-lifecycle/v1';
35
35
  filesScanned: number;
36
+ /** Total candidate files found before the cap (>= filesScanned). */
37
+ totalFiles: number;
38
+ /** True when the scan hit the file cap and did NOT see every candidate file. */
39
+ truncated: boolean;
40
+ /** Project-relative subtree the scan was scoped to, when `--scope` was used. */
41
+ scope?: string;
36
42
  registersFound: number;
37
43
  matchedPairs: ReadonlyArray<IRegistryPair>;
38
44
  missingRemovers: ReadonlyArray<IRegistryMissingRemover>;
@@ -48,6 +54,8 @@ export interface IRegistryLifecycleReport {
48
54
  export declare function buildRegistryLifecycleReport(input: {
49
55
  projectRoot: string;
50
56
  limit?: number;
57
+ /** Project-relative subtree to scope the scan to (sub-second on a subtree). */
58
+ scope?: string;
51
59
  }): IRegistryLifecycleReport;
52
60
  export declare function renderRegistryLifecycleReportText(report: IRegistryLifecycleReport): string;
53
61
  //# sourceMappingURL=registry-lifecycle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry-lifecycle.d.ts","sourceRoot":"","sources":["../src/registry-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,kCAAkC,CAAC;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IAC3C,eAAe,EAAE,aAAa,CAAC,uBAAuB,CAAC,CAAC;IACxD;;;;OAIG;IACH,gBAAgB,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAClD,OAAO,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACzC,eAAe,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACxC;AAiMD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,wBAAwB,CAsF3B;AAED,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,CA8B1F"}
1
+ {"version":3,"file":"registry-lifecycle.d.ts","sourceRoot":"","sources":["../src/registry-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,kCAAkC,CAAC;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,SAAS,EAAE,OAAO,CAAC;IACnB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IAC3C,eAAe,EAAE,aAAa,CAAC,uBAAuB,CAAC,CAAC;IACxD;;;;OAIG;IACH,gBAAgB,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAClD,OAAO,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACzC,eAAe,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACxC;AAiMD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,wBAAwB,CA2F3B;AAED,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,CAkC1F"}
@@ -230,8 +230,10 @@ function findRemoverInContent(content, candidates) {
230
230
  }
231
231
  export function buildRegistryLifecycleReport(input) {
232
232
  const { projectRoot } = input;
233
+ const scope = input.scope && input.scope.length > 0 ? input.scope : undefined;
234
+ const walkRoot = scope ? join(projectRoot, scope) : projectRoot;
233
235
  const files = [];
234
- walk(projectRoot, projectRoot, files);
236
+ walk(walkRoot, projectRoot, files);
235
237
  const limit = input.limit ?? 2000;
236
238
  const scanFiles = files.slice(0, limit);
237
239
  const matchedPairs = [];
@@ -309,6 +311,9 @@ export function buildRegistryLifecycleReport(input) {
309
311
  return {
310
312
  schema: 'sharkcraft.registry-lifecycle/v1',
311
313
  filesScanned: scanFiles.length,
314
+ totalFiles: files.length,
315
+ truncated: files.length > scanFiles.length,
316
+ ...(scope ? { scope } : {}),
312
317
  registersFound,
313
318
  matchedPairs,
314
319
  missingRemovers,
@@ -320,7 +325,10 @@ export function buildRegistryLifecycleReport(input) {
320
325
  export function renderRegistryLifecycleReportText(report) {
321
326
  const lines = [];
322
327
  lines.push('=== Registry lifecycle ===');
323
- lines.push(` files scanned ${report.filesScanned}`);
328
+ if (report.scope)
329
+ lines.push(` scope ${report.scope}`);
330
+ lines.push(` files scanned ${report.filesScanned}` +
331
+ (report.truncated ? ` ! capped (${report.totalFiles} candidates — re-run with --scope <dir> for the rest)` : ''));
324
332
  lines.push(` registers found ${report.registersFound}`);
325
333
  lines.push(` matched pairs ${report.matchedPairs.length}`);
326
334
  lines.push(` missing removers ${report.missingRemovers.length}`);
@@ -0,0 +1,26 @@
1
+ import { type AppError, type Result } from '@shrkcrft/core';
2
+ import { type LoadedConfig } from '@shrkcrft/config';
3
+ /**
4
+ * A {@link LoadedConfig} whose four data planes have had pack contributions
5
+ * merged in (local-wins), plus the human-readable notes from that merge.
6
+ */
7
+ export interface IResolvedProjectConfig extends LoadedConfig {
8
+ /**
9
+ * Notes from the pack-plane merge — missing/invalid pack files, dropped
10
+ * collisions, pack-discovery failures. Empty when there are no packs (or no
11
+ * pack contributions to the four planes). Surfaced by the readers that
12
+ * consume the merged planes (`shrk check wiring`, `registry`, `policy-lint`,
13
+ * `reuse`, `gate`).
14
+ */
15
+ readonly planeDiagnostics: readonly string[];
16
+ }
17
+ /**
18
+ * Load the project config, then merge pack-contributed `wiringRules` /
19
+ * `registries` / `policyRules` / `reusePrimitives` over the local config
20
+ * (local-wins). Returns the loader error untouched on failure, so callers keep
21
+ * the same "invalid config vs. valid-with-no-rules" distinction they had with
22
+ * {@link loadProjectConfig}. A pack-discovery failure degrades to a diagnostic
23
+ * — it never fails config resolution.
24
+ */
25
+ export declare function resolveProjectConfig(cwd: string): Promise<Result<IResolvedProjectConfig, AppError>>;
26
+ //# sourceMappingURL=resolve-project-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-project-config.d.ts","sourceRoot":"","sources":["../src/resolve-project-config.ts"],"names":[],"mappings":"AAuBA,OAAO,EAGL,KAAK,QAAQ,EAMb,KAAK,MAAM,EACZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAOL,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAG1B;;;GAGG;AACH,MAAM,WAAW,sBAAuB,SAAQ,YAAY;IAC1D;;;;;;OAMG;IACH,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C;AAoHD;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,sBAAsB,EAAE,QAAQ,CAAC,CAAC,CAoEnD"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Pack-aware project-config resolution.
3
+ *
4
+ * The four "cross-file invariant as DATA" planes — `wiringRules`, `registries`,
5
+ * `policyRules`, `reusePrimitives` — can be authored inline in a repo's
6
+ * `sharkcraft.config.ts`. They can ALSO be SHIPPED by a framework pack (e.g. a
7
+ * NestJS pack contributing "every @Injectable must be registered in a module"
8
+ * as a wiring rule) via the new `wiringRuleFiles` / `registryFiles` /
9
+ * `policyRuleFiles` / `reusePrimitiveFiles` manifest slots.
10
+ *
11
+ * The merge CANNOT live in `loadProjectConfig`: config sits at layer 3 and packs
12
+ * at layer 6, so config cannot import the pack discovery. The inspector (layer
13
+ * 10, above packs) is the lowest layer that can see both, so the merge seam
14
+ * lives here.
15
+ *
16
+ * Precedence is LOCAL-WINS: a repo's own declaration always beats a pack's, and
17
+ * a pack element whose key collides with a local (or an earlier pack) one is
18
+ * dropped with a diagnostic. Pack elements are validated with the SAME exported
19
+ * zod schemas the config loader uses, so a malformed pack element is skipped
20
+ * (with a diagnostic) rather than crashing config resolution.
21
+ */
22
+ import { existsSync } from 'node:fs';
23
+ import * as nodePath from 'node:path';
24
+ import { importModuleViaLoader, ok, } from '@shrkcrft/core';
25
+ import { loadProjectConfig, PolicyRuleSchema, RegistrationIdiomSchema, RegistryDeclarationSchema, ReusePrimitiveSchema, WiringRuleSchema, } from '@shrkcrft/config';
26
+ import { discoverPacks } from '@shrkcrft/packs';
27
+ /**
28
+ * Generic per-plane load + validate + merge. Seeds the merged map from the
29
+ * LOCAL array (keyed by `keyOf`), then folds in pack elements only when their
30
+ * key is free. Missing files, non-array default exports, schema-invalid
31
+ * elements, and key collisions all become diagnostics and are skipped — never a
32
+ * throw.
33
+ */
34
+ async function mergePlane(localArr, packContribs, schema, keyOf, planeLabel, diagnostics) {
35
+ const merged = new Map();
36
+ const localKeys = new Set();
37
+ for (const item of localArr) {
38
+ const key = keyOf(item);
39
+ merged.set(key, item);
40
+ localKeys.add(key);
41
+ }
42
+ for (const contrib of packContribs) {
43
+ const full = nodePath.resolve(contrib.packageRoot, contrib.rel);
44
+ if (!existsSync(full)) {
45
+ diagnostics.push(`pack ${contrib.packageName}: missing ${planeLabel} file ${contrib.rel}`);
46
+ continue;
47
+ }
48
+ let mod;
49
+ try {
50
+ mod = await importModuleViaLoader(full);
51
+ }
52
+ catch (e) {
53
+ diagnostics.push(`pack ${contrib.packageName}: failed to load ${planeLabel} file ${contrib.rel} — ${e.message}`);
54
+ continue;
55
+ }
56
+ const arr = mod.default;
57
+ if (!Array.isArray(arr)) {
58
+ diagnostics.push(`pack ${contrib.packageName}: ${planeLabel} file ${contrib.rel} default export is not an array — skipped`);
59
+ continue;
60
+ }
61
+ for (const raw of arr) {
62
+ const parsed = schema.safeParse(raw);
63
+ if (!parsed.success) {
64
+ const summary = (parsed.error?.issues ?? [])
65
+ .map((iss) => `${iss.path.join('.') || '<root>'}: ${iss.message}`)
66
+ .join('; ') || 'invalid element';
67
+ diagnostics.push(`pack ${contrib.packageName}: invalid ${planeLabel} element in ${contrib.rel} — ${summary} — skipped`);
68
+ continue;
69
+ }
70
+ const item = parsed.data;
71
+ const key = keyOf(item);
72
+ if (merged.has(key)) {
73
+ diagnostics.push(localKeys.has(key)
74
+ ? `pack ${contrib.packageName}: ${planeLabel} "${key}" already provided by local config — skipped`
75
+ : `pack ${contrib.packageName}: ${planeLabel} "${key}" already provided — skipped`);
76
+ continue;
77
+ }
78
+ merged.set(key, item);
79
+ }
80
+ }
81
+ return [...merged.values()];
82
+ }
83
+ /** Collect every pack contribution file for one manifest slot across valid packs. */
84
+ function gatherPackContribs(validPacks, slot) {
85
+ const out = [];
86
+ for (const pack of validPacks) {
87
+ // Mirror sharkcraft-inspector's pack-merge: read the slot off the
88
+ // contributions bag with a narrow cast (the new slots are all string[]).
89
+ const contributions = pack.manifest?.contributions;
90
+ const files = contributions?.[slot];
91
+ for (const rel of files ?? []) {
92
+ out.push({ packageName: pack.packageName, packageRoot: pack.packageRoot, rel });
93
+ }
94
+ }
95
+ return out;
96
+ }
97
+ /**
98
+ * Load the project config, then merge pack-contributed `wiringRules` /
99
+ * `registries` / `policyRules` / `reusePrimitives` over the local config
100
+ * (local-wins). Returns the loader error untouched on failure, so callers keep
101
+ * the same "invalid config vs. valid-with-no-rules" distinction they had with
102
+ * {@link loadProjectConfig}. A pack-discovery failure degrades to a diagnostic
103
+ * — it never fails config resolution.
104
+ */
105
+ export async function resolveProjectConfig(cwd) {
106
+ const loaded = await loadProjectConfig(cwd);
107
+ if (!loaded.ok)
108
+ return loaded;
109
+ const diagnostics = [];
110
+ const base = loaded.value;
111
+ let validPacks = [];
112
+ try {
113
+ const packs = await discoverPacks({ projectRoot: base.projectRoot });
114
+ validPacks = packs.validPacks;
115
+ }
116
+ catch (e) {
117
+ diagnostics.push(`pack discovery failed — pack-contributed planes skipped: ${e.message}`);
118
+ }
119
+ const wiringRules = await mergePlane(base.config.wiringRules ?? [], gatherPackContribs(validPacks, 'wiringRuleFiles'), WiringRuleSchema, (r) => r.id, 'wiringRule', diagnostics);
120
+ const registries = await mergePlane(base.config.registries ?? [], gatherPackContribs(validPacks, 'registryFiles'), RegistryDeclarationSchema, (r) => r.name, 'registry', diagnostics);
121
+ const registrationGraph = await mergePlane(base.config.registrationGraph ?? [], gatherPackContribs(validPacks, 'registrationGraphFiles'), RegistrationIdiomSchema, (r) => r.name, 'registrationIdiom', diagnostics);
122
+ const policyRules = await mergePlane(base.config.policyRules ?? [], gatherPackContribs(validPacks, 'policyRuleFiles'), PolicyRuleSchema, (r) => r.id, 'policyRule', diagnostics);
123
+ const reusePrimitives = await mergePlane(base.config.reusePrimitives ?? [], gatherPackContribs(validPacks, 'reusePrimitiveFiles'), ReusePrimitiveSchema, (r) => r.symbol, 'reusePrimitive', diagnostics);
124
+ return ok({
125
+ ...base,
126
+ config: {
127
+ ...base.config,
128
+ wiringRules,
129
+ registries,
130
+ registrationGraph,
131
+ policyRules,
132
+ reusePrimitives,
133
+ },
134
+ planeDiagnostics: diagnostics,
135
+ });
136
+ }
@@ -17,6 +17,13 @@ import type { ISharkcraftInspection } from './sharkcraft-inspector.js';
17
17
  * keeping the real post-change gates. Rules carry no verification field, so
18
18
  * they are intentionally not a source here.
19
19
  *
20
+ * Package-manager templating: any command may use a `<pm-run>` or `<pm>`
21
+ * placeholder that is substituted with the project's detected package manager
22
+ * at consume time (e.g. a pack playbook ships `<pm-run> test` and it resolves
23
+ * to `bun run test` / `npm run test` / `pnpm test` per the target repo). The
24
+ * substitution runs before the placeholder-exclusion check, so a templated
25
+ * gate survives while a truly generative `<task>` step is still dropped.
26
+ *
20
27
  * Deterministic, order-preserving, deduped. No commands are executed.
21
28
  */
22
29
  export declare function resolveVerificationCommands(inspection: ISharkcraftInspection, options?: {
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-verification-commands.d.ts","sourceRoot":"","sources":["../src/resolve-verification-commands.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,qBAAqB,EACjC,OAAO,GAAE;IACP,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C,GACL,MAAM,EAAE,CA2BV"}
1
+ {"version":3,"file":"resolve-verification-commands.d.ts","sourceRoot":"","sources":["../src/resolve-verification-commands.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,qBAAqB,EACjC,OAAO,GAAE;IACP,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C,GACL,MAAM,EAAE,CA8BV"}
@@ -1,4 +1,5 @@
1
1
  import { PipelineStepType } from '@shrkcrft/pipelines';
2
+ import { PackageManager, WorkspaceProfile, } from '@shrkcrft/workspace';
2
3
  /**
3
4
  * Resolve the verification commands an agent should run after a task, grounded
4
5
  * in the pack rather than a generic default. Precedence (first non-empty wins):
@@ -17,9 +18,17 @@ import { PipelineStepType } from '@shrkcrft/pipelines';
17
18
  * keeping the real post-change gates. Rules carry no verification field, so
18
19
  * they are intentionally not a source here.
19
20
  *
21
+ * Package-manager templating: any command may use a `<pm-run>` or `<pm>`
22
+ * placeholder that is substituted with the project's detected package manager
23
+ * at consume time (e.g. a pack playbook ships `<pm-run> test` and it resolves
24
+ * to `bun run test` / `npm run test` / `pnpm test` per the target repo). The
25
+ * substitution runs before the placeholder-exclusion check, so a templated
26
+ * gate survives while a truly generative `<task>` step is still dropped.
27
+ *
20
28
  * Deterministic, order-preserving, deduped. No commands are executed.
21
29
  */
22
30
  export function resolveVerificationCommands(inspection, options = {}) {
31
+ const ws = inspection.workspace;
23
32
  const fromPipelines = [];
24
33
  for (const id of options.pipelineIds ?? []) {
25
34
  const pipeline = inspection.pipelineRegistry.get(id);
@@ -31,7 +40,7 @@ export function resolveVerificationCommands(inspection, options = {}) {
31
40
  if (step.required === false)
32
41
  continue;
33
42
  for (const raw of step.cliCommands ?? []) {
34
- const cmd = raw.trim();
43
+ const cmd = substitutePmPlaceholders(raw.trim(), ws);
35
44
  if (cmd.length > 0 && !cmd.includes('<'))
36
45
  fromPipelines.push(cmd);
37
46
  }
@@ -42,13 +51,53 @@ export function resolveVerificationCommands(inspection, options = {}) {
42
51
  const cfg = inspection.config;
43
52
  const fromConfig = [];
44
53
  for (const vc of cfg?.verificationCommands ?? []) {
45
- const cmd = vc?.command?.trim();
46
- if (cmd && cmd.length > 0)
54
+ const cmd = substitutePmPlaceholders(vc?.command?.trim() ?? '', ws);
55
+ if (cmd.length > 0)
47
56
  fromConfig.push(cmd);
48
57
  }
49
58
  if (fromConfig.length > 0)
50
59
  return dedupe(fromConfig);
51
- return dedupe(options.knowledgeDefaults ?? []);
60
+ return dedupe((options.knowledgeDefaults ?? []).map((c) => substitutePmPlaceholders(c, ws)));
61
+ }
62
+ /**
63
+ * Replace package-manager placeholders in a single command with the project's
64
+ * detected toolchain. `<pm-run>` → the run-prefix (`bun run`, `npm run`,
65
+ * `pnpm`, `yarn`); `<pm>` → the bare manager name (`bun`, `npm`, `pnpm`,
66
+ * `yarn`). A no-op (and zero workspace access) when the command carries no
67
+ * `<pm` token, so non-templated callers and stubbed inspections are unaffected.
68
+ */
69
+ function substitutePmPlaceholders(command, ws) {
70
+ if (!command.includes('<pm'))
71
+ return command;
72
+ const manager = effectivePackageManager(ws);
73
+ return command
74
+ .replaceAll('<pm-run>', packageManagerRunPrefix(manager))
75
+ .replaceAll('<pm>', bareManager(manager));
76
+ }
77
+ function effectivePackageManager(ws) {
78
+ const detected = ws?.packageManager?.manager;
79
+ if (detected && detected !== PackageManager.Unknown)
80
+ return detected;
81
+ if (ws?.profiles?.includes(WorkspaceProfile.HasBun))
82
+ return PackageManager.Bun;
83
+ return PackageManager.Npm;
84
+ }
85
+ function packageManagerRunPrefix(manager) {
86
+ switch (manager) {
87
+ case PackageManager.Bun:
88
+ return 'bun run';
89
+ case PackageManager.Pnpm:
90
+ return 'pnpm';
91
+ case PackageManager.Yarn:
92
+ return 'yarn';
93
+ case PackageManager.Npm:
94
+ return 'npm run';
95
+ default:
96
+ return 'npm run';
97
+ }
98
+ }
99
+ function bareManager(manager) {
100
+ return manager === PackageManager.Unknown ? 'npm' : manager;
52
101
  }
53
102
  function dedupe(items) {
54
103
  return [...new Set(items)];
@@ -44,6 +44,14 @@ export interface IBuildReviewPacketOptions {
44
44
  since?: string;
45
45
  staged?: boolean;
46
46
  files?: readonly string[];
47
+ /**
48
+ * Working-tree default only: when undefined/true, non-ignored untracked
49
+ * files are included — so a just-generated, never-staged source file is
50
+ * visible to the review (and to the missing-test heuristic). Set false to
51
+ * restore the legacy tracked-only `git diff` view. Ignored when
52
+ * `since`/`staged`/`files` is set.
53
+ */
54
+ untracked?: boolean;
47
55
  }
48
56
  export declare function buildReviewPacket(inspection: ISharkcraftInspection, options?: IBuildReviewPacketOptions): IReviewPacket;
49
57
  //# sourceMappingURL=review-packet.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"review-packet.d.ts","sourceRoot":"","sources":["../src/review-packet.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAIvE,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,kEAAkE;IAClE,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,8CAA8C;IAC9C,aAAa,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACxE,2CAA2C;IAC3C,iBAAiB,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3D,iBAAiB,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5D,2DAA2D;IAC3D,kBAAkB,EAAE,SAAS;QAC3B,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,eAAe,EAAE,MAAM,CAAC;QACxB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;KACjB,EAAE,CAAC;IACJ,+DAA+D;IAC/D,qBAAqB,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,4DAA4D;IAC5D,oBAAoB,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,mEAAmE;IACnE,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,yBAAyB;IACxC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAyCD,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,qBAAqB,EACjC,OAAO,GAAE,yBAA8B,GACtC,aAAa,CA+Ef"}
1
+ {"version":3,"file":"review-packet.d.ts","sourceRoot":"","sources":["../src/review-packet.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAKvE,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,kEAAkE;IAClE,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,8CAA8C;IAC9C,aAAa,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACxE,2CAA2C;IAC3C,iBAAiB,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3D,iBAAiB,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5D,2DAA2D;IAC3D,kBAAkB,EAAE,SAAS;QAC3B,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,eAAe,EAAE,MAAM,CAAC;QACxB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;KACjB,EAAE,CAAC;IACJ,+DAA+D;IAC/D,qBAAqB,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,4DAA4D;IAC5D,oBAAoB,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,mEAAmE;IACnE,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,yBAAyB;IACxC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAwCD,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,qBAAqB,EACjC,OAAO,GAAE,yBAA8B,GACtC,aAAa,CA+Ef"}
@@ -1,24 +1,23 @@
1
- import { spawnSync } from 'node:child_process';
2
1
  import { evaluateBoundaries, loadTsconfigPaths, scanImports } from '@shrkcrft/boundaries';
3
2
  import { matchAffectedConventions } from '@shrkcrft/paths';
4
3
  import { resolveVerificationCommands } from "./resolve-verification-commands.js";
5
4
  import { rankAll } from "./task-ranker.js";
5
+ import { getChangedFiles } from "./git-helpers.js";
6
6
  function gitDiffFiles(cwd, opts) {
7
7
  if (opts.files && opts.files.length > 0)
8
8
  return [...opts.files];
9
- const args = ['diff', '--name-only'];
10
9
  if (opts.staged)
11
- args.push('--cached');
10
+ return getChangedFiles(cwd, { staged: true });
12
11
  if (opts.since)
13
- args.push(opts.since);
14
- const res = spawnSync('git', args, { cwd, encoding: 'utf8' });
15
- if (res.status !== 0)
16
- return [];
17
- return (res.stdout ?? '')
18
- .toString()
19
- .split('\n')
20
- .map((s) => s.trim())
21
- .filter((s) => s.length > 0);
12
+ return getChangedFiles(cwd, { since: opts.since });
13
+ // Default working-tree view: include non-ignored untracked files so a
14
+ // just-generated, never-staged source file is visible to review (and to the
15
+ // "is each new src/ file tested?" heuristic below). Mirrors `shrk changes
16
+ // summary` and every other working-tree caller; `.gitignore` stays honored.
17
+ // `{ untracked: false }` restores the legacy tracked-only `git diff` view.
18
+ if (opts.untracked === false)
19
+ return getChangedFiles(cwd, {});
20
+ return getChangedFiles(cwd, { includeWorktree: true });
22
21
  }
23
22
  function buildPseudoTask(files) {
24
23
  // Use the top-level dir of each file as a pseudo-task description so the
@@ -1 +1 @@
1
- {"version":3,"file":"sharkcraft-inspector.d.ts","sourceRoot":"","sources":["../src/sharkcraft-inspector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sharkcraft-inspector.d.ts","sourceRoot":"","sources":["../src/sharkcraft-inspector.ts"],"names":[],"mappings":"AAOA,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,KAAK,iBAAiB,EAAqB,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,yBAAyB,EAC9B,cAAc,EAIf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,KAAK,mBAAmB,EAAyB,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACxG,OAAO,EAAE,KAAK,mBAAmB,EAAyB,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACxG,OAAO,EAAiB,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAwC,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAA6B,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAqC,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAW3F,OAAO,EAGL,KAAK,iBAAiB,EAEvB,MAAM,yBAAyB,CAAC;AAGjC;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAAC,GACvC,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAqDjD;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACjC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,EAAE,yBAAyB,EAAE,CAAC;IAC9C,KAAK,EAAE,oBAAoB,CAAC;IAC5B,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC/C,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClD,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClD,KAAK,EAAE,cAAc,CAAC;IACtB,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAChD,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClD,8CAA8C;IAC9C,iBAAiB,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAChD,sDAAsD;IACtD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,4DAA4D;IAC5D,YAAY,EAAE,OAAO,CAAC;IACtB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,CAAC,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACrD;AAoJD,wBAAsB,iBAAiB,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAwZpG;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,qBAAqB,GAAG,aAAa,CAiQ1E"}
@@ -14,6 +14,7 @@ import { BoundaryRegistry, loadBoundaryRulesFromFile } from '@shrkcrft/boundarie
14
14
  import { DoctorSeverity } from "./doctor-result.js";
15
15
  import { diagnoseActionHints } from "./action-hint-diagnostics.js";
16
16
  import { buildCodeIntelligenceChecks } from "./code-intelligence-doctor.js";
17
+ import { loadSearchTuning } from "./search-tuning-registry.js";
17
18
  import { buildDelegateRecipeChecks } from "./delegate-doctor.js";
18
19
  import { computeFileFingerprint, createInspectorCache, } from "./inspector-cache.js";
19
20
  import { DEFAULT_SLOW_LOADER_THRESHOLD_MS, LARGE_FILE_THRESHOLD_BYTES, } from "./loader-diagnostics.js";
@@ -422,8 +423,23 @@ export async function inspectSharkcraft(options = {}) {
422
423
  await loadFile(rel, 'knowledge');
423
424
  for (const rel of c.ruleFiles ?? [])
424
425
  await loadFile(rel, 'rules');
425
- for (const rel of c.pathFiles ?? [])
426
+ const loadedPathRels = new Set();
427
+ for (const rel of c.pathFiles ?? []) {
428
+ loadedPathRels.add(rel);
426
429
  await loadFile(rel, 'paths');
430
+ }
431
+ // `pathConventionFiles` is a manifest slot distinct from `pathFiles` (see the
432
+ // plugin-api comment "separate from pathFiles"), but it still feeds the path
433
+ // domain. Previously NO loader consumed it, so a pack shipping conventions
434
+ // here loaded nothing. Load it through the same path loader, skipping any rel
435
+ // already handled by `pathFiles` so a file listed in both slots doesn't
436
+ // double-load (entry ids are also deduped by `loadFile`).
437
+ for (const rel of c.pathConventionFiles ?? []) {
438
+ if (loadedPathRels.has(rel))
439
+ continue;
440
+ loadedPathRels.add(rel);
441
+ await loadFile(rel, 'paths');
442
+ }
427
443
  for (const rel of c.docsFiles ?? [])
428
444
  await loadFile(rel, 'docs');
429
445
  for (const rel of c.templateFiles ?? [])
@@ -550,7 +566,7 @@ export async function inspectSharkcraft(options = {}) {
550
566
  if (tracked.skipped)
551
567
  warnings.push(...tracked.warnings);
552
568
  }
553
- return {
569
+ const inspection = {
554
570
  projectRoot: workspace.projectRoot,
555
571
  workspace,
556
572
  hasSharkcraftFolder: workspace.hasSharkcraftFolder,
@@ -581,6 +597,16 @@ export async function inspectSharkcraft(options = {}) {
581
597
  cacheEnabled: cache.enabled,
582
598
  cacheDir: cache.dir,
583
599
  };
600
+ // Warm the pack search-tuning cache (best-effort; existsSync-gated + cached
601
+ // per projectRoot) so the synchronous buildTaskPacket → rankAll path can read
602
+ // listSearchTuning and apply pack boostIds — the same tuning `shrk search` uses.
603
+ try {
604
+ await loadSearchTuning(inspection);
605
+ }
606
+ catch {
607
+ /* tuning is best-effort */
608
+ }
609
+ return inspection;
584
610
  }
585
611
  export function runDoctor(inspection) {
586
612
  const checks = [];
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=spec-evidence.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-evidence.test.d.ts","sourceRoot":"","sources":["../../../src/spec/__tests__/spec-evidence.test.ts"],"names":[],"mappings":""}