@vibe-agent-toolkit/agent-skills 0.1.39-rc.8 → 0.1.39

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 (108) hide show
  1. package/dist/files-config.d.ts +61 -0
  2. package/dist/files-config.d.ts.map +1 -1
  3. package/dist/files-config.js +262 -6
  4. package/dist/files-config.js.map +1 -1
  5. package/dist/index.d.ts +4 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +4 -2
  8. package/dist/index.js.map +1 -1
  9. package/dist/plugin-distribution-layout.d.ts +70 -0
  10. package/dist/plugin-distribution-layout.d.ts.map +1 -0
  11. package/dist/plugin-distribution-layout.js +97 -0
  12. package/dist/plugin-distribution-layout.js.map +1 -0
  13. package/dist/skill-packager.d.ts +43 -1
  14. package/dist/skill-packager.d.ts.map +1 -1
  15. package/dist/skill-packager.js +131 -53
  16. package/dist/skill-packager.js.map +1 -1
  17. package/dist/skill-source/git-clone.d.ts +2 -2
  18. package/dist/skill-source/git-clone.d.ts.map +1 -1
  19. package/dist/skill-source/git-clone.js +33 -10
  20. package/dist/skill-source/git-clone.js.map +1 -1
  21. package/dist/skill-source/sources/url-source.d.ts.map +1 -1
  22. package/dist/skill-source/sources/url-source.js +23 -8
  23. package/dist/skill-source/sources/url-source.js.map +1 -1
  24. package/dist/skill-source/sources/workspace-source.d.ts.map +1 -1
  25. package/dist/skill-source/sources/workspace-source.js +16 -8
  26. package/dist/skill-source/sources/workspace-source.js.map +1 -1
  27. package/dist/skill-source/stage.js +6 -2
  28. package/dist/skill-source/stage.js.map +1 -1
  29. package/dist/skill-test/build-hook.d.ts +58 -0
  30. package/dist/skill-test/build-hook.d.ts.map +1 -0
  31. package/dist/skill-test/build-hook.js +63 -0
  32. package/dist/skill-test/build-hook.js.map +1 -0
  33. package/dist/skill-test/configure-writer.d.ts +19 -11
  34. package/dist/skill-test/configure-writer.d.ts.map +1 -1
  35. package/dist/skill-test/configure-writer.js +23 -15
  36. package/dist/skill-test/configure-writer.js.map +1 -1
  37. package/dist/skill-test/declared-env.d.ts +72 -0
  38. package/dist/skill-test/declared-env.d.ts.map +1 -0
  39. package/dist/skill-test/declared-env.js +85 -0
  40. package/dist/skill-test/declared-env.js.map +1 -0
  41. package/dist/skill-test/eval-inputs.d.ts +159 -0
  42. package/dist/skill-test/eval-inputs.d.ts.map +1 -0
  43. package/dist/skill-test/eval-inputs.js +158 -0
  44. package/dist/skill-test/eval-inputs.js.map +1 -0
  45. package/dist/skill-test/evals-template.d.ts.map +1 -1
  46. package/dist/skill-test/evals-template.js +27 -10
  47. package/dist/skill-test/evals-template.js.map +1 -1
  48. package/dist/skill-test/exit-codes.d.ts +44 -5
  49. package/dist/skill-test/exit-codes.d.ts.map +1 -1
  50. package/dist/skill-test/exit-codes.js +63 -9
  51. package/dist/skill-test/exit-codes.js.map +1 -1
  52. package/dist/skill-test/experimenter-prompt.d.ts +22 -0
  53. package/dist/skill-test/experimenter-prompt.d.ts.map +1 -1
  54. package/dist/skill-test/experimenter-prompt.js +39 -2
  55. package/dist/skill-test/experimenter-prompt.js.map +1 -1
  56. package/dist/skill-test/grading-adapter.d.ts +42 -0
  57. package/dist/skill-test/grading-adapter.d.ts.map +1 -1
  58. package/dist/skill-test/grading-adapter.js +63 -1
  59. package/dist/skill-test/grading-adapter.js.map +1 -1
  60. package/dist/skill-test/grading-schema.d.ts +73 -5
  61. package/dist/skill-test/grading-schema.d.ts.map +1 -1
  62. package/dist/skill-test/grading-schema.js +20 -5
  63. package/dist/skill-test/grading-schema.js.map +1 -1
  64. package/dist/skill-test/harness-location.d.ts +35 -4
  65. package/dist/skill-test/harness-location.d.ts.map +1 -1
  66. package/dist/skill-test/harness-location.js +111 -16
  67. package/dist/skill-test/harness-location.js.map +1 -1
  68. package/dist/skill-test/index.d.ts +7 -4
  69. package/dist/skill-test/index.d.ts.map +1 -1
  70. package/dist/skill-test/index.js +7 -4
  71. package/dist/skill-test/index.js.map +1 -1
  72. package/dist/skill-test/lock.d.ts +23 -0
  73. package/dist/skill-test/lock.d.ts.map +1 -1
  74. package/dist/skill-test/lock.js +35 -1
  75. package/dist/skill-test/lock.js.map +1 -1
  76. package/dist/skill-test/plugin-env.d.ts +20 -0
  77. package/dist/skill-test/plugin-env.d.ts.map +1 -0
  78. package/dist/skill-test/plugin-env.js +24 -0
  79. package/dist/skill-test/plugin-env.js.map +1 -0
  80. package/dist/skill-test/plugin-layout.d.ts +41 -0
  81. package/dist/skill-test/plugin-layout.d.ts.map +1 -0
  82. package/dist/skill-test/plugin-layout.js +49 -0
  83. package/dist/skill-test/plugin-layout.js.map +1 -0
  84. package/dist/skill-test/preflight.d.ts.map +1 -1
  85. package/dist/skill-test/preflight.js +1 -2
  86. package/dist/skill-test/preflight.js.map +1 -1
  87. package/dist/skill-test/run-harness.d.ts +197 -11
  88. package/dist/skill-test/run-harness.d.ts.map +1 -1
  89. package/dist/skill-test/run-harness.js +401 -65
  90. package/dist/skill-test/run-harness.js.map +1 -1
  91. package/dist/skill-test/staging.d.ts +20 -1
  92. package/dist/skill-test/staging.d.ts.map +1 -1
  93. package/dist/skill-test/staging.js +71 -17
  94. package/dist/skill-test/staging.js.map +1 -1
  95. package/dist/skill-test/vendor-manifest.d.ts +3 -3
  96. package/dist/skill-test/vendor-manifest.d.ts.map +1 -1
  97. package/dist/skill-test/vendor-manifest.js +13 -3
  98. package/dist/skill-test/vendor-manifest.js.map +1 -1
  99. package/dist/validators/packaging-validator.d.ts.map +1 -1
  100. package/dist/validators/packaging-validator.js +134 -1
  101. package/dist/validators/packaging-validator.js.map +1 -1
  102. package/dist/validators/skill-validator.d.ts.map +1 -1
  103. package/dist/validators/skill-validator.js +18 -14
  104. package/dist/validators/skill-validator.js.map +1 -1
  105. package/dist/walk-link-graph.d.ts.map +1 -1
  106. package/dist/walk-link-graph.js +26 -1
  107. package/dist/walk-link-graph.js.map +1 -1
  108. package/package.json +6 -5
@@ -1,6 +1,8 @@
1
1
  import { AuthPreflightError } from '@vibe-agent-toolkit/utils';
2
+ import { BuildHookError } from './build-hook.js';
3
+ import { UnknownEnvTokenError } from './declared-env.js';
2
4
  import { PromptInvariantError } from './experimenter-prompt.js';
3
- import { GradingSkewError } from './grading-adapter.js';
5
+ import { GradingNonceError, GradingSkewError } from './grading-adapter.js';
4
6
  import { HarnessLocationError } from './harness-location.js';
5
7
  /** Exit codes for `vat skill test` (spec §6d). */
6
8
  export const SkillTestExitCode = {
@@ -8,21 +10,58 @@ export const SkillTestExitCode = {
8
10
  Internal: 1,
9
11
  Preflight: 2,
10
12
  Bootstrap: 3,
13
+ /**
14
+ * At least one eval FAILED and the caller opted into eval-gating via
15
+ * `--fail-on-eval-failure`. Distinct from the harness-broke codes (1/2):
16
+ * the harness ran to completion and produced a valid grading.json — the
17
+ * skill's expectations simply did not all pass. Returned DIRECTLY by the
18
+ * harness verdict (see verdictExitCode in run-harness.ts), not via
19
+ * mapErrorToExitCode, because it is an outcome, not a thrown error.
20
+ */
21
+ EvalFailure: 4,
11
22
  };
12
23
  /**
13
24
  * A required input is absent in a way vat can scaffold (missing evals.json).
14
- * Exit 3, NOT a failure. `expectedPath` is the real, persistent location where
15
- * the harness wrote the annotated starter template for the user to fill in.
25
+ * Exit 3, NOT a failure. `expectedPath` is the persistent location of the
26
+ * annotated starter template.
27
+ *
28
+ * In a real run the harness has already written that template, and the message
29
+ * says so. Under `--dry-run` nothing is written — a dry run must never touch the
30
+ * filesystem — so the message instead describes what a real run *would* scaffold
31
+ * and where, while surfacing the same exit-3 "bootstrap needed" signal.
16
32
  */
17
33
  export class BootstrapNeededError extends Error {
18
34
  expectedPath;
19
35
  exitCode = 3;
20
- constructor(expectedPath) {
21
- super(`Wrote an evals.json template at ${expectedPath} — fill it in and re-run.`);
36
+ constructor(expectedPath, opts) {
37
+ super(opts?.dryRun === true
38
+ ? `[dry-run] No evals.json found. A real run would scaffold an annotated template at ${expectedPath} — fill it in and re-run. (dry-run: nothing was written.)`
39
+ : `Wrote an evals.json template at ${expectedPath} — fill it in and re-run.`);
22
40
  this.expectedPath = expectedPath;
23
41
  this.name = 'BootstrapNeededError';
24
42
  }
25
43
  }
44
+ /** Thrown when building a declared skill (pool packageSkill or plugin build) fails. Exit 2 (preflight class). */
45
+ export class SkillBuildError extends Error {
46
+ exitCode = 2;
47
+ constructor(message) {
48
+ super(message);
49
+ this.name = 'SkillBuildError';
50
+ }
51
+ }
52
+ /**
53
+ * The §12 security acknowledgment is required but absent, thrown BEFORE any
54
+ * build/pre-stage command (which executes untrusted repo code) runs for a
55
+ * buildable subject. Exit 2 (preflight class). Mirrors the harness Step-6 ack
56
+ * message wording so the two enforcement points read identically.
57
+ */
58
+ export class SecurityAckError extends Error {
59
+ exitCode = 2;
60
+ constructor() {
61
+ super('Security acknowledgment required. Pass --i-understand-this-runs-skill-code to proceed.');
62
+ this.name = 'SecurityAckError';
63
+ }
64
+ }
26
65
  /** Internal harness failure (incl. experimenter exiting without valid grading.json). Exit 1. */
27
66
  export class InternalHarnessError extends Error {
28
67
  exitCode = 1;
@@ -35,19 +74,34 @@ export class InternalHarnessError extends Error {
35
74
  * Map any thrown error to the process exit code. Errors that carry their own
36
75
  * `exitCode` (Bootstrap/Auth/HarnessLocation/Internal) are authoritative;
37
76
  * a PromptInvariantError is a user-correctable preflight problem (a supplied
38
- * prompt override is missing a required safety instruction) → 2; GradingSkewError
39
- * is a parse failure → 1; everything unknown 1.
77
+ * prompt override is missing a required safety instruction) → 2; a BuildHookError
78
+ * is a pre-stage build failure → 2; a SkillBuildError is a declared-skill build
79
+ * failure → 2; a SecurityAckError is a missing security ack before a build → 2;
80
+ * an UnknownEnvTokenError is a bad ${token} in a
81
+ * declared env value → 2; GradingSkewError (parse failure) and GradingNonceError
82
+ * (forged/mismatched grading nonce) are both → 1; everything unknown → 1.
83
+ *
84
+ * Note: SkillTestExitCode.EvalFailure (4) is NOT produced here — it is an
85
+ * outcome of a completed run (an eval failed under `--fail-on-eval-failure`),
86
+ * not a thrown error, so the harness returns it directly (see verdictExitCode).
40
87
  */
41
88
  export function mapErrorToExitCode(err) {
42
89
  if (err instanceof BootstrapNeededError)
43
90
  return SkillTestExitCode.Bootstrap;
44
91
  if (err instanceof AuthPreflightError ||
92
+ err instanceof BuildHookError ||
45
93
  err instanceof HarnessLocationError ||
46
- err instanceof PromptInvariantError) {
94
+ err instanceof PromptInvariantError ||
95
+ err instanceof SecurityAckError ||
96
+ err instanceof SkillBuildError ||
97
+ err instanceof UnknownEnvTokenError) {
47
98
  return SkillTestExitCode.Preflight;
48
99
  }
49
- if (err instanceof GradingSkewError || err instanceof InternalHarnessError)
100
+ if (err instanceof GradingNonceError ||
101
+ err instanceof GradingSkewError ||
102
+ err instanceof InternalHarnessError) {
50
103
  return SkillTestExitCode.Internal;
104
+ }
51
105
  return SkillTestExitCode.Internal;
52
106
  }
53
107
  //# sourceMappingURL=exit-codes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"exit-codes.js","sourceRoot":"","sources":["../../src/skill-test/exit-codes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,kDAAkD;AAClD,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,EAAE,EAAE,CAAC;IACL,QAAQ,EAAE,CAAC;IACX,SAAS,EAAE,CAAC;IACZ,SAAS,EAAE,CAAC;CACJ,CAAC;AAIX;;;;GAIG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAEjB;IADnB,QAAQ,GAAG,CAAU,CAAC;IAC/B,YAA4B,YAAoB;QAC9C,KAAK,CAAC,mCAAmC,YAAY,2BAA2B,CAAC,CAAC;QADxD,iBAAY,GAAZ,YAAY,CAAQ;QAE9C,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,gGAAgG;AAChG,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,QAAQ,GAAG,CAAU,CAAC;IAC/B,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAY;IAC7C,IAAI,GAAG,YAAY,oBAAoB;QAAE,OAAO,iBAAiB,CAAC,SAAS,CAAC;IAC5E,IACE,GAAG,YAAY,kBAAkB;QACjC,GAAG,YAAY,oBAAoB;QACnC,GAAG,YAAY,oBAAoB,EACnC,CAAC;QACD,OAAO,iBAAiB,CAAC,SAAS,CAAC;IACrC,CAAC;IACD,IAAI,GAAG,YAAY,gBAAgB,IAAI,GAAG,YAAY,oBAAoB;QAAE,OAAO,iBAAiB,CAAC,QAAQ,CAAC;IAC9G,OAAO,iBAAiB,CAAC,QAAQ,CAAC;AACpC,CAAC"}
1
+ {"version":3,"file":"exit-codes.js","sourceRoot":"","sources":["../../src/skill-test/exit-codes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,kDAAkD;AAClD,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,EAAE,EAAE,CAAC;IACL,QAAQ,EAAE,CAAC;IACX,SAAS,EAAE,CAAC;IACZ,SAAS,EAAE,CAAC;IACZ;;;;;;;OAOG;IACH,WAAW,EAAE,CAAC;CACN,CAAC;AAIX;;;;;;;;;GASG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAEjB;IADnB,QAAQ,GAAG,CAAU,CAAC;IAC/B,YAA4B,YAAoB,EAAE,IAA2B;QAC3E,KAAK,CACH,IAAI,EAAE,MAAM,KAAK,IAAI;YACnB,CAAC,CAAC,qFAAqF,YAAY,2DAA2D;YAC9J,CAAC,CAAC,mCAAmC,YAAY,2BAA2B,CAC/E,CAAC;QALwB,iBAAY,GAAZ,YAAY,CAAQ;QAM9C,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,iHAAiH;AACjH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,QAAQ,GAAG,CAAU,CAAC;IAC/B,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,QAAQ,GAAG,CAAU,CAAC;IAC/B;QACE,KAAK,CAAC,wFAAwF,CAAC,CAAC;QAChG,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED,gGAAgG;AAChG,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,QAAQ,GAAG,CAAU,CAAC;IAC/B,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAY;IAC7C,IAAI,GAAG,YAAY,oBAAoB;QAAE,OAAO,iBAAiB,CAAC,SAAS,CAAC;IAC5E,IACE,GAAG,YAAY,kBAAkB;QACjC,GAAG,YAAY,cAAc;QAC7B,GAAG,YAAY,oBAAoB;QACnC,GAAG,YAAY,oBAAoB;QACnC,GAAG,YAAY,gBAAgB;QAC/B,GAAG,YAAY,eAAe;QAC9B,GAAG,YAAY,oBAAoB,EACnC,CAAC;QACD,OAAO,iBAAiB,CAAC,SAAS,CAAC;IACrC,CAAC;IACD,IACE,GAAG,YAAY,iBAAiB;QAChC,GAAG,YAAY,gBAAgB;QAC/B,GAAG,YAAY,oBAAoB,EACnC,CAAC;QACD,OAAO,iBAAiB,CAAC,QAAQ,CAAC;IACpC,CAAC;IACD,OAAO,iBAAiB,CAAC,QAAQ,CAAC;AACpC,CAAC"}
@@ -6,6 +6,7 @@ export interface BuildPromptOptions {
6
6
  evalsPath: string;
7
7
  gradingOut: string;
8
8
  frictionOut: string;
9
+ workspacesRoot: string;
9
10
  baseline: boolean;
10
11
  }
11
12
  /**
@@ -16,5 +17,26 @@ export interface BuildPromptOptions {
16
17
  */
17
18
  export declare const DEFAULT_EXPERIMENTER_PROMPT: string;
18
19
  export declare function buildExperimenterPrompt(opts: BuildPromptOptions): string;
20
+ /**
21
+ * Sentinel the persisted (audit) copy of the prompt shows in place of the real
22
+ * nonce, so the on-disk artifact never leaks the secret to skill code.
23
+ */
24
+ export declare const REDACTED_NONCE_PLACEHOLDER = "<run-nonce redacted>";
25
+ /**
26
+ * Append the per-run integrity-nonce directive to the effective prompt. The
27
+ * experimenter must copy `nonce` verbatim into grading.json's top-level
28
+ * `runNonce` field; the harness then rejects any grading.json whose nonce is
29
+ * absent or wrong (see run-harness.ts). This is defense-in-depth against
30
+ * untrusted skill code forging a passing grading.json in the shared sandbox —
31
+ * without the secret nonce (delivered only via stdin, never written to disk) a
32
+ * forged grading cannot be authenticated.
33
+ *
34
+ * Appended AFTER assertPromptInvariants and AFTER any user `experimenterPrompt`
35
+ * override, so the nonce requirement is ALWAYS enforced and a committed config
36
+ * cannot opt out of it.
37
+ */
38
+ export declare function appendIntegrityNonceDirective(prompt: string, nonce: string): string;
39
+ /** Redact the per-run nonce from a prompt for the on-disk audit copy. */
40
+ export declare function redactNonce(prompt: string, nonce: string): string;
19
41
  export declare function assertPromptInvariants(prompt: string): void;
20
42
  //# sourceMappingURL=experimenter-prompt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"experimenter-prompt.d.ts","sourceRoot":"","sources":["../../src/skill-test/experimenter-prompt.ts"],"names":[],"mappings":"AAAA,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,QAsB5B,CAAC;AAKb,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAOxE;AAmBD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAI3D"}
1
+ {"version":3,"file":"experimenter-prompt.d.ts","sourceRoot":"","sources":["../../src/skill-test/experimenter-prompt.ts"],"names":[],"mappings":"AAAA,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,QA2B5B,CAAC;AAKb,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAQxE;AAED;;;GAGG;AACH,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AAEjE;;;;;;;;;;;;GAYG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAQnF;AAED,yEAAyE;AACzE,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjE;AAmBD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAI3D"}
@@ -15,11 +15,16 @@ export const DEFAULT_EXPERIMENTER_PROMPT = [
15
15
  '',
16
16
  'For each eval in {{EVALS_PATH}}:',
17
17
  ' 1. Dispatch ONE executor subagent. Tell it ONLY the task prompt and the staged subject path {{SUBJECT_PATH}}.',
18
- ' Never tell the executor it is being tested.',
18
+ ' When the eval declares input `files`, ALSO tell the executor its working directory is {{WORKSPACES_ROOT}}/<id>',
19
+ ' (substitute the eval\'s own id) — the project it should operate on. Never tell the executor it is being tested.',
19
20
  ' 2. Grade the executor output against the eval\'s `expectations` using skill-creator\'s grader.md rubric.',
21
+ ' If the eval includes an `expected_output`, treat it as the author\'s prose description of a',
22
+ ' correct result and use it as CONTEXT when judging — but the pass/fail verdict is still decided',
23
+ ' per `expectations` entry; `expected_output` informs your judgment, it is not itself a checklist item.',
20
24
  ' 3. Append each graded expectation to the SINGLE top-level `expectations` array in {{GRADING_OUT}} IMMEDIATELY',
21
25
  ' (incremental flush — a mid-run kill must leave partial results).',
22
- ' 4. Record any packaging-fidelity friction to {{FRICTION_OUT}} using the vat friction schema.',
26
+ ' 4. Record any packaging-fidelity friction to {{FRICTION_OUT}} using the vat friction.json schema.',
27
+ ' If a file referenced by the skill is absent from the staged tree, record a `missing-bundled-file` friction entry.',
23
28
  '',
24
29
  '{{GRADING_OUT}} MUST be ONE flat JSON object in skill-creator\'s grading.json shape (references/schemas.md):',
25
30
  'a top-level `expectations` array — one entry {"text","passed","evidence"} per expectation across ALL evals —',
@@ -38,10 +43,42 @@ export function buildExperimenterPrompt(opts) {
38
43
  return DEFAULT_EXPERIMENTER_PROMPT
39
44
  .replace('{{EVALS_PATH}}', opts.evalsPath)
40
45
  .replace('{{SUBJECT_PATH}}', opts.subjectPath)
46
+ .replaceAll('{{WORKSPACES_ROOT}}', opts.workspacesRoot)
41
47
  .replaceAll('{{GRADING_OUT}}', opts.gradingOut)
42
48
  .replace('{{FRICTION_OUT}}', opts.frictionOut)
43
49
  .replace('{{BASELINE_BLOCK}}', opts.baseline ? BASELINE_BLOCK : '');
44
50
  }
51
+ /**
52
+ * Sentinel the persisted (audit) copy of the prompt shows in place of the real
53
+ * nonce, so the on-disk artifact never leaks the secret to skill code.
54
+ */
55
+ export const REDACTED_NONCE_PLACEHOLDER = '<run-nonce redacted>';
56
+ /**
57
+ * Append the per-run integrity-nonce directive to the effective prompt. The
58
+ * experimenter must copy `nonce` verbatim into grading.json's top-level
59
+ * `runNonce` field; the harness then rejects any grading.json whose nonce is
60
+ * absent or wrong (see run-harness.ts). This is defense-in-depth against
61
+ * untrusted skill code forging a passing grading.json in the shared sandbox —
62
+ * without the secret nonce (delivered only via stdin, never written to disk) a
63
+ * forged grading cannot be authenticated.
64
+ *
65
+ * Appended AFTER assertPromptInvariants and AFTER any user `experimenterPrompt`
66
+ * override, so the nonce requirement is ALWAYS enforced and a committed config
67
+ * cannot opt out of it.
68
+ */
69
+ export function appendIntegrityNonceDirective(prompt, nonce) {
70
+ return [
71
+ prompt,
72
+ '',
73
+ 'INTEGRITY (required, do this LAST): the grading.json you write MUST include a',
74
+ `top-level string field "runNonce" whose value is EXACTLY: ${nonce}`,
75
+ 'Copy it verbatim. vat rejects a grading.json whose runNonce is missing or wrong.',
76
+ ].join('\n');
77
+ }
78
+ /** Redact the per-run nonce from a prompt for the on-disk audit copy. */
79
+ export function redactNonce(prompt, nonce) {
80
+ return prompt.replaceAll(nonce, REDACTED_NONCE_PLACEHOLDER);
81
+ }
45
82
  const REQUIRED_PATTERNS = [
46
83
  { test: /\bSTOP\b/, label: 'must instruct the experimenter to STOP' },
47
84
  { test: /grading\.json|\{\{GRADING_OUT\}\}/i, label: 'must write grading.json' },
@@ -1 +1 @@
1
- {"version":3,"file":"experimenter-prompt.js","sourceRoot":"","sources":["../../src/skill-test/experimenter-prompt.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,OAAe;QACzB,KAAK,CAAC,2CAA2C,OAAO,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAUD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,yGAAyG;IACzG,EAAE;IACF,kCAAkC;IAClC,iHAAiH;IACjH,kDAAkD;IAClD,4GAA4G;IAC5G,iHAAiH;IACjH,uEAAuE;IACvE,gGAAgG;IAChG,EAAE;IACF,8GAA8G;IAC9G,8GAA8G;IAC9G,gHAAgH;IAChH,wEAAwE;IACxE,qGAAqG;IACrG,EAAE;IACF,mFAAmF;IACnF,EAAE;IACF,6GAA6G;IAC7G,4FAA4F;IAC5F,oBAAoB;CACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,cAAc,GAClB,sIAAsI,CAAC;AAEzI,MAAM,UAAU,uBAAuB,CAAC,IAAwB;IAC9D,OAAO,2BAA2B;SAC/B,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC;SACzC,OAAO,CAAC,kBAAkB,EAAE,IAAI,CAAC,WAAW,CAAC;SAC7C,UAAU,CAAC,iBAAiB,EAAE,IAAI,CAAC,UAAU,CAAC;SAC9C,OAAO,CAAC,kBAAkB,EAAE,IAAI,CAAC,WAAW,CAAC;SAC7C,OAAO,CAAC,oBAAoB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,iBAAiB,GAAsC;IAC3D,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,wCAAwC,EAAE;IACrE,EAAE,IAAI,EAAE,oCAAoC,EAAE,KAAK,EAAE,yBAAyB,EAAE;IAChF,EAAE,IAAI,EAAE,sCAAsC,EAAE,KAAK,EAAE,0BAA0B,EAAE;IACnF,EAAE,IAAI,EAAE,yBAAyB,EAAE,KAAK,EAAE,oDAAoD,EAAE;IAChG,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,iDAAiD,EAAE;IACrF,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,yBAAyB,EAAE;IACxD;QACE,IAAI,EAAE,+BAA+B;QACrC,KAAK,EAAE,4EAA4E;KACpF;IACD;QACE,IAAI,EAAE,qCAAqC;QAC3C,KAAK,EAAE,0DAA0D;KAClE;CACF,CAAC;AAEF,MAAM,UAAU,sBAAsB,CAAC,MAAc;IACnD,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,iBAAiB,EAAE,CAAC;QAChD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAChE,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"experimenter-prompt.js","sourceRoot":"","sources":["../../src/skill-test/experimenter-prompt.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,48 @@ export interface NormalizedGrading {
17
17
  passed: boolean;
18
18
  evidence?: string;
19
19
  }[];
20
+ /** Per-run integrity nonce the experimenter copied from its prompt (if present). */
21
+ runNonce?: string;
20
22
  }
23
+ /**
24
+ * Thrown when grading.json's per-run integrity nonce is absent or does not match
25
+ * the nonce the harness stamped into the experimenter prompt for THIS run. A
26
+ * missing/wrong nonce means the grading was not produced by the experimenter we
27
+ * prompted — most likely a grading.json forged or left behind by untrusted skill
28
+ * code in the shared sandbox — so the verdict cannot be trusted.
29
+ */
30
+ export declare class GradingNonceError extends Error {
31
+ constructor(message: string);
32
+ }
33
+ /**
34
+ * Assert grading.json carries the exact per-run nonce the harness expected.
35
+ * Called before the verdict is trusted. Throws {@link GradingNonceError} on a
36
+ * missing or mismatched nonce.
37
+ */
38
+ export declare function assertGradingNonce(actual: string | undefined, expected: string): void;
21
39
  export declare function parseGradingJson(raw: unknown): NormalizedGrading;
40
+ /** The authoritative eval verdict, recomputed from per-expectation `passed` flags. */
41
+ export interface GradingVerdict {
42
+ passed: number;
43
+ total: number;
44
+ allPassed: boolean;
45
+ }
46
+ /**
47
+ * Reconcile the grader's self-reported `summary` against the authoritative
48
+ * per-expectation `passed` flags and return the recomputed verdict.
49
+ *
50
+ * The grader emits BOTH an aggregate `summary.{passed,total}` AND one
51
+ * `expectations[]` entry per graded expectation (each with its own `passed`).
52
+ * The schema (docs/skill-test-grading-schema.md) defines `summary` as the exact
53
+ * aggregate of `expectations`, so the two MUST agree. We never trust the
54
+ * self-reported summary alone — a grader that emits `summary {5,5}` alongside a
55
+ * failing expectation would otherwise be a false green.
56
+ *
57
+ * Throws {@link GradingSkewError} when:
58
+ * - there are zero expectations (the grader graded NOTHING — an error, never a
59
+ * pass); or
60
+ * - the summary disagrees with the recomputed counts (a grader bug, surfaced
61
+ * loudly rather than silently flowing a wrong verdict downstream).
62
+ */
63
+ export declare function reconcileGrading(report: NormalizedGrading): GradingVerdict;
22
64
  //# sourceMappingURL=grading-adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"grading-adapter.d.ts","sourceRoot":"","sources":["../../src/skill-test/grading-adapter.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAQ5B;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACtE;AAaD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,CAuBhE"}
1
+ {"version":3,"file":"grading-adapter.d.ts","sourceRoot":"","sources":["../../src/skill-test/grading-adapter.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAQ5B;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACrE,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAS5B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAOrF;AAaD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,CAwBhE;AAED,sFAAsF;AACtF,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,cAAc,CAqB1E"}
@@ -13,6 +13,35 @@ export class GradingSkewError extends Error {
13
13
  this.name = 'GradingSkewError';
14
14
  }
15
15
  }
16
+ /**
17
+ * Thrown when grading.json's per-run integrity nonce is absent or does not match
18
+ * the nonce the harness stamped into the experimenter prompt for THIS run. A
19
+ * missing/wrong nonce means the grading was not produced by the experimenter we
20
+ * prompted — most likely a grading.json forged or left behind by untrusted skill
21
+ * code in the shared sandbox — so the verdict cannot be trusted.
22
+ */
23
+ export class GradingNonceError extends Error {
24
+ constructor(message) {
25
+ super(`grading.json integrity check failed: ${message}. The harness stamps a secret ` +
26
+ 'per-run nonce into the experimenter prompt (never written to disk) and requires ' +
27
+ 'grading.json to echo it; a missing or wrong nonce means the grading was not ' +
28
+ 'produced by the prompted experimenter and is rejected.');
29
+ this.name = 'GradingNonceError';
30
+ }
31
+ }
32
+ /**
33
+ * Assert grading.json carries the exact per-run nonce the harness expected.
34
+ * Called before the verdict is trusted. Throws {@link GradingNonceError} on a
35
+ * missing or mismatched nonce.
36
+ */
37
+ export function assertGradingNonce(actual, expected) {
38
+ if (actual === undefined) {
39
+ throw new GradingNonceError('grading.json has no top-level `runNonce`');
40
+ }
41
+ if (actual !== expected) {
42
+ throw new GradingNonceError('grading.json `runNonce` does not match this run');
43
+ }
44
+ }
16
45
  /**
17
46
  * Detect the common per-eval nested mistake: `{ evals: [ { expectations, ... } ] }`
18
47
  * with no top-level `expectations`. The grader (an LLM) reaches for this when the
@@ -36,7 +65,7 @@ export function parseGradingJson(raw) {
36
65
  const path = firstIssue?.path.join('.') ?? '(root)';
37
66
  throw new GradingSkewError(`missing/invalid field at "${path}" (${firstIssue?.message ?? 'unknown'})`);
38
67
  }
39
- const { summary, expectations } = result.data;
68
+ const { summary, expectations, runNonce } = result.data;
40
69
  return {
41
70
  summary: { passed: summary.passed, total: summary.total },
42
71
  expectations: expectations.map(e => ({
@@ -44,6 +73,39 @@ export function parseGradingJson(raw) {
44
73
  passed: e.passed,
45
74
  ...(e.evidence === undefined ? {} : { evidence: e.evidence }),
46
75
  })),
76
+ ...(runNonce === undefined ? {} : { runNonce }),
47
77
  };
48
78
  }
79
+ /**
80
+ * Reconcile the grader's self-reported `summary` against the authoritative
81
+ * per-expectation `passed` flags and return the recomputed verdict.
82
+ *
83
+ * The grader emits BOTH an aggregate `summary.{passed,total}` AND one
84
+ * `expectations[]` entry per graded expectation (each with its own `passed`).
85
+ * The schema (docs/skill-test-grading-schema.md) defines `summary` as the exact
86
+ * aggregate of `expectations`, so the two MUST agree. We never trust the
87
+ * self-reported summary alone — a grader that emits `summary {5,5}` alongside a
88
+ * failing expectation would otherwise be a false green.
89
+ *
90
+ * Throws {@link GradingSkewError} when:
91
+ * - there are zero expectations (the grader graded NOTHING — an error, never a
92
+ * pass); or
93
+ * - the summary disagrees with the recomputed counts (a grader bug, surfaced
94
+ * loudly rather than silently flowing a wrong verdict downstream).
95
+ */
96
+ export function reconcileGrading(report) {
97
+ const computedPassed = report.expectations.filter(e => e.passed).length;
98
+ const computedTotal = report.expectations.length;
99
+ if (computedTotal === 0) {
100
+ throw new GradingSkewError('the grader recorded zero expectations — nothing was graded, so this can never be a pass. ' +
101
+ 'A valid grading.json lists every graded expectation in top-level `expectations`');
102
+ }
103
+ const { passed, total } = report.summary;
104
+ if (passed !== computedPassed || total !== computedTotal) {
105
+ throw new GradingSkewError(`the grader's summary disagrees with its expectations: summary={passed:${passed},total:${total}} ` +
106
+ `but expectations recompute to {passed:${computedPassed},total:${computedTotal}}. ` +
107
+ '`summary` must be the exact aggregate of `expectations` (one entry per graded expectation)');
108
+ }
109
+ return { passed: computedPassed, total: computedTotal, allPassed: computedPassed === computedTotal };
110
+ }
49
111
  //# sourceMappingURL=grading-adapter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"grading-adapter.js","sourceRoot":"","sources":["../../src/skill-test/grading-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D;;;;;GAKG;AACH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAe;QACzB,KAAK,CACH,4BAA4B,OAAO,gDAAgD;YACjF,0EAA0E;YAC1E,yFAAyF,CAC5F,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAOD;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,GAAY;IACtC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC1D,MAAM,GAAG,GAAG,GAA8B,CAAC;IAC3C,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,cAAc,IAAI,GAAG,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAY;IAC3C,MAAM,MAAM,GAAG,mBAAmB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAClD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,IAAI,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,gBAAgB,CACxB,oFAAoF;gBAClF,kFAAkF;gBAClF,qCAAqC,CACxC,CAAC;QACJ,CAAC;QACD,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC;QACpD,MAAM,IAAI,gBAAgB,CAAC,6BAA6B,IAAI,MAAM,UAAU,EAAE,OAAO,IAAI,SAAS,GAAG,CAAC,CAAC;IACzG,CAAC;IACD,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;IAC9C,OAAO;QACL,OAAO,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE;QACzD,YAAY,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACnC,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,GAAG,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;SAC9D,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"grading-adapter.js","sourceRoot":"","sources":["../../src/skill-test/grading-adapter.ts"],"names":[],"mappings":"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"}
@@ -41,8 +41,12 @@ export declare const GradedExpectationSchema: z.ZodObject<{
41
41
  evidence: z.ZodOptional<z.ZodString>;
42
42
  }, z.ZodTypeAny, "passthrough">>;
43
43
  export type GradedExpectation = z.infer<typeof GradedExpectationSchema>;
44
- /** Aggregate pass/fail counts. `failed`/`pass_rate` are documented but optional. */
45
- export declare const GradingSummarySchema: z.ZodObject<{
44
+ /**
45
+ * Aggregate pass/fail counts. `failed`/`pass_rate` are documented but optional.
46
+ * Counts are non-negative integers (a float or negative count is a grader bug),
47
+ * and `passed` can never exceed `total`.
48
+ */
49
+ export declare const GradingSummarySchema: z.ZodEffects<z.ZodObject<{
46
50
  passed: z.ZodNumber;
47
51
  total: z.ZodNumber;
48
52
  failed: z.ZodOptional<z.ZodNumber>;
@@ -57,6 +61,16 @@ export declare const GradingSummarySchema: z.ZodObject<{
57
61
  total: z.ZodNumber;
58
62
  failed: z.ZodOptional<z.ZodNumber>;
59
63
  pass_rate: z.ZodOptional<z.ZodNumber>;
64
+ }, z.ZodTypeAny, "passthrough">>, z.objectOutputType<{
65
+ passed: z.ZodNumber;
66
+ total: z.ZodNumber;
67
+ failed: z.ZodOptional<z.ZodNumber>;
68
+ pass_rate: z.ZodOptional<z.ZodNumber>;
69
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
70
+ passed: z.ZodNumber;
71
+ total: z.ZodNumber;
72
+ failed: z.ZodOptional<z.ZodNumber>;
73
+ pass_rate: z.ZodOptional<z.ZodNumber>;
60
74
  }, z.ZodTypeAny, "passthrough">>;
61
75
  export type GradingSummary = z.infer<typeof GradingSummarySchema>;
62
76
  /**
@@ -78,7 +92,7 @@ export declare const GradingReportSchema: z.ZodObject<{
78
92
  passed: z.ZodBoolean;
79
93
  evidence: z.ZodOptional<z.ZodString>;
80
94
  }, z.ZodTypeAny, "passthrough">>, "many">;
81
- summary: z.ZodObject<{
95
+ summary: z.ZodEffects<z.ZodObject<{
82
96
  passed: z.ZodNumber;
83
97
  total: z.ZodNumber;
84
98
  failed: z.ZodOptional<z.ZodNumber>;
@@ -93,7 +107,25 @@ export declare const GradingReportSchema: z.ZodObject<{
93
107
  total: z.ZodNumber;
94
108
  failed: z.ZodOptional<z.ZodNumber>;
95
109
  pass_rate: z.ZodOptional<z.ZodNumber>;
110
+ }, z.ZodTypeAny, "passthrough">>, z.objectOutputType<{
111
+ passed: z.ZodNumber;
112
+ total: z.ZodNumber;
113
+ failed: z.ZodOptional<z.ZodNumber>;
114
+ pass_rate: z.ZodOptional<z.ZodNumber>;
115
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
116
+ passed: z.ZodNumber;
117
+ total: z.ZodNumber;
118
+ failed: z.ZodOptional<z.ZodNumber>;
119
+ pass_rate: z.ZodOptional<z.ZodNumber>;
96
120
  }, z.ZodTypeAny, "passthrough">>;
121
+ /**
122
+ * Per-run integrity nonce the experimenter is told to copy verbatim from its
123
+ * prompt (see experimenter-prompt.ts). Optional in the schema (a grading.json
124
+ * validated by external tooling need not carry it), but the harness REQUIRES
125
+ * it to match the run's secret nonce before trusting the verdict — this is how
126
+ * a forged grading.json written by untrusted skill code is rejected.
127
+ */
128
+ runNonce: z.ZodOptional<z.ZodString>;
97
129
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
98
130
  expectations: z.ZodArray<z.ZodObject<{
99
131
  text: z.ZodString;
@@ -108,7 +140,7 @@ export declare const GradingReportSchema: z.ZodObject<{
108
140
  passed: z.ZodBoolean;
109
141
  evidence: z.ZodOptional<z.ZodString>;
110
142
  }, z.ZodTypeAny, "passthrough">>, "many">;
111
- summary: z.ZodObject<{
143
+ summary: z.ZodEffects<z.ZodObject<{
112
144
  passed: z.ZodNumber;
113
145
  total: z.ZodNumber;
114
146
  failed: z.ZodOptional<z.ZodNumber>;
@@ -123,7 +155,25 @@ export declare const GradingReportSchema: z.ZodObject<{
123
155
  total: z.ZodNumber;
124
156
  failed: z.ZodOptional<z.ZodNumber>;
125
157
  pass_rate: z.ZodOptional<z.ZodNumber>;
158
+ }, z.ZodTypeAny, "passthrough">>, z.objectOutputType<{
159
+ passed: z.ZodNumber;
160
+ total: z.ZodNumber;
161
+ failed: z.ZodOptional<z.ZodNumber>;
162
+ pass_rate: z.ZodOptional<z.ZodNumber>;
163
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
164
+ passed: z.ZodNumber;
165
+ total: z.ZodNumber;
166
+ failed: z.ZodOptional<z.ZodNumber>;
167
+ pass_rate: z.ZodOptional<z.ZodNumber>;
126
168
  }, z.ZodTypeAny, "passthrough">>;
169
+ /**
170
+ * Per-run integrity nonce the experimenter is told to copy verbatim from its
171
+ * prompt (see experimenter-prompt.ts). Optional in the schema (a grading.json
172
+ * validated by external tooling need not carry it), but the harness REQUIRES
173
+ * it to match the run's secret nonce before trusting the verdict — this is how
174
+ * a forged grading.json written by untrusted skill code is rejected.
175
+ */
176
+ runNonce: z.ZodOptional<z.ZodString>;
127
177
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
128
178
  expectations: z.ZodArray<z.ZodObject<{
129
179
  text: z.ZodString;
@@ -138,7 +188,7 @@ export declare const GradingReportSchema: z.ZodObject<{
138
188
  passed: z.ZodBoolean;
139
189
  evidence: z.ZodOptional<z.ZodString>;
140
190
  }, z.ZodTypeAny, "passthrough">>, "many">;
141
- summary: z.ZodObject<{
191
+ summary: z.ZodEffects<z.ZodObject<{
142
192
  passed: z.ZodNumber;
143
193
  total: z.ZodNumber;
144
194
  failed: z.ZodOptional<z.ZodNumber>;
@@ -153,7 +203,25 @@ export declare const GradingReportSchema: z.ZodObject<{
153
203
  total: z.ZodNumber;
154
204
  failed: z.ZodOptional<z.ZodNumber>;
155
205
  pass_rate: z.ZodOptional<z.ZodNumber>;
206
+ }, z.ZodTypeAny, "passthrough">>, z.objectOutputType<{
207
+ passed: z.ZodNumber;
208
+ total: z.ZodNumber;
209
+ failed: z.ZodOptional<z.ZodNumber>;
210
+ pass_rate: z.ZodOptional<z.ZodNumber>;
211
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
212
+ passed: z.ZodNumber;
213
+ total: z.ZodNumber;
214
+ failed: z.ZodOptional<z.ZodNumber>;
215
+ pass_rate: z.ZodOptional<z.ZodNumber>;
156
216
  }, z.ZodTypeAny, "passthrough">>;
217
+ /**
218
+ * Per-run integrity nonce the experimenter is told to copy verbatim from its
219
+ * prompt (see experimenter-prompt.ts). Optional in the schema (a grading.json
220
+ * validated by external tooling need not carry it), but the harness REQUIRES
221
+ * it to match the run's secret nonce before trusting the verdict — this is how
222
+ * a forged grading.json written by untrusted skill code is rejected.
223
+ */
224
+ runNonce: z.ZodOptional<z.ZodString>;
157
225
  }, z.ZodTypeAny, "passthrough">>;
158
226
  export type GradingReport = z.infer<typeof GradingReportSchema>;
159
227
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"grading-schema.d.ts","sourceRoot":"","sources":["../../src/skill-test/grading-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,sFAAsF;AACtF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;gCAMpB,CAAC;AAEjB,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,oFAAoF;AACpF,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;gCAOjB,CAAC;AAEjB,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAKhB,CAAC;AAEjB,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;;;;;CAAyD,CAAC"}
1
+ {"version":3,"file":"grading-schema.d.ts","sourceRoot":"","sources":["../../src/skill-test/grading-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,sFAAsF;AACtF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;gCAMpB,CAAC;AAEjB,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;gCAU7B,CAAC;AAEL,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAI5B;;;;;;OAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IANH;;;;;;OAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IANH;;;;;;OAMG;;gCAGS,CAAC;AAEjB,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;;;;;CAAyD,CAAC"}
@@ -35,15 +35,22 @@ export const GradedExpectationSchema = z
35
35
  evidence: z.string().optional(),
36
36
  })
37
37
  .passthrough();
38
- /** Aggregate pass/fail counts. `failed`/`pass_rate` are documented but optional. */
38
+ /**
39
+ * Aggregate pass/fail counts. `failed`/`pass_rate` are documented but optional.
40
+ * Counts are non-negative integers (a float or negative count is a grader bug),
41
+ * and `passed` can never exceed `total`.
42
+ */
39
43
  export const GradingSummarySchema = z
40
44
  .object({
41
- passed: z.number(),
42
- total: z.number(),
43
- failed: z.number().optional(),
45
+ passed: z.number().int().nonnegative(),
46
+ total: z.number().int().nonnegative(),
47
+ failed: z.number().int().nonnegative().optional(),
44
48
  pass_rate: z.number().optional(),
45
49
  })
46
- .passthrough();
50
+ .passthrough()
51
+ .refine(s => s.passed <= s.total, {
52
+ message: 'summary.passed must not exceed summary.total',
53
+ });
47
54
  /**
48
55
  * The full grading.json contract. Required: top-level `expectations[]` and
49
56
  * `summary`. Everything else passes through untouched (forward-compatible with
@@ -53,6 +60,14 @@ export const GradingReportSchema = z
53
60
  .object({
54
61
  expectations: z.array(GradedExpectationSchema),
55
62
  summary: GradingSummarySchema,
63
+ /**
64
+ * Per-run integrity nonce the experimenter is told to copy verbatim from its
65
+ * prompt (see experimenter-prompt.ts). Optional in the schema (a grading.json
66
+ * validated by external tooling need not carry it), but the harness REQUIRES
67
+ * it to match the run's secret nonce before trusting the verdict — this is how
68
+ * a forged grading.json written by untrusted skill code is rejected.
69
+ */
70
+ runNonce: z.string().optional(),
56
71
  })
57
72
  .passthrough();
58
73
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"grading-schema.js","sourceRoot":"","sources":["../../src/skill-test/grading-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,sFAAsF;AACtF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC;KACrC,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE;IACnB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC;KACD,WAAW,EAAE,CAAC;AAIjB,oFAAoF;AACpF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC;KAClC,MAAM,CAAC;IACN,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC;KACD,WAAW,EAAE,CAAC;AAIjB;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC;KACjC,MAAM,CAAC;IACN,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,uBAAuB,CAAC;IAC9C,OAAO,EAAE,oBAAoB;CAC9B,CAAC;KACD,WAAW,EAAE,CAAC;AAIjB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,eAAe,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,CAAC"}
1
+ {"version":3,"file":"grading-schema.js","sourceRoot":"","sources":["../../src/skill-test/grading-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,sFAAsF;AACtF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC;KACrC,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE;IACnB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC;KACD,WAAW,EAAE,CAAC;AAIjB;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC;KAClC,MAAM,CAAC;IACN,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IACtC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IACrC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;IACjD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC;KACD,WAAW,EAAE;KACb,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,EAAE;IAChC,OAAO,EAAE,8CAA8C;CACxD,CAAC,CAAC;AAIL;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC;KACjC,MAAM,CAAC;IACN,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,uBAAuB,CAAC;IAC9C,OAAO,EAAE,oBAAoB;IAC7B;;;;;;OAMG;IACH,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC;KACD,WAAW,EAAE,CAAC;AAIjB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,eAAe,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,CAAC"}
@@ -15,13 +15,44 @@ export declare function resolveHarnessRoot(skillNames: string[], tmpRoot?: strin
15
15
  * Refuse a --workdir whose ancestry contains CLAUDE.md or .claude/ — cwd
16
16
  * discovery would re-pollute the run (spec §7). Defense in depth with
17
17
  * --setting-sources "".
18
+ *
19
+ * `stopAt` (optional) bounds the ancestry walk: when the walk reaches that
20
+ * directory it stops *before* inspecting it (exclusive boundary), mirroring
21
+ * `assertSafeHarnessRoot`'s `trustedRoot`. Default (undefined) walks to the
22
+ * filesystem root, preserving the strictest production behavior. Tests use it
23
+ * to scope the walk to a sandbox — necessary on Windows, where the OS tmp dir
24
+ * lives inside the user's home and would otherwise surface an ambient
25
+ * ~/.claude during the walk.
18
26
  */
19
- export declare function assertSafeWorkdir(dir: string): void;
27
+ export declare function assertSafeWorkdir(dir: string, stopAt?: string): void;
20
28
  /**
21
- * FS-bound hardening for the shared-tmp harness root (spec §7): the root must
22
- * be 0700 and owned by the current uid, and no path component may be a symlink.
29
+ * Prepare the harness root directory so that `assertSafeHarnessRoot` will
30
+ * pass on the next call. If the path does not exist, this is a no-op (the
31
+ * caller creates it at 0700 via mkdirSyncReal). If it exists:
32
+ *
33
+ * - Symlink → throw HarnessLocationError (security gate; never relax).
34
+ * - Real directory whose mode != 0700 → chmod to 0700. Removing group/other
35
+ * access is strictly safer, never a relaxation.
36
+ *
37
+ * Mode checks/changes are only performed on non-win32 (matching
38
+ * assertSafeHarnessRoot's platform guard).
39
+ */
40
+ export declare function prepareHarnessRoot(dir: string): void;
41
+ /**
42
+ * FS-bound hardening for the shared-tmp harness root (spec §7). Validates EVERY
43
+ * path component from the leaf up to (but excluding) `trustedRoot`: no component
44
+ * may be a symlink, and on POSIX each must be owned by the current uid. This
45
+ * closes the shared-/tmp TOCTOU where the recursively-created intermediate parent
46
+ * (`<tmp>/vat-skill-test`) — not just the leaf — could be pre-created as a symlink
47
+ * or under another user's ownership. The leaf must additionally be 0700.
48
+ *
49
+ * `trustedRoot` (default: the OS tmp dir) is the boundary: it is system-owned
50
+ * (sticky-bit /tmp) so ownership/mode checks are not applied to it. When the leaf
51
+ * is not a descendant of `trustedRoot` (an explicit --out elsewhere), validation
52
+ * degrades to the leaf alone.
53
+ *
23
54
  * Integration-tested (requires real lstat/stat). On Windows, uid checks are
24
55
  * skipped (process.getuid is undefined) but the symlink refusal still applies.
25
56
  */
26
- export declare function assertSafeHarnessRoot(dir: string, currentUid: number): void;
57
+ export declare function assertSafeHarnessRoot(dir: string, currentUid: number, trustedRoot?: string): void;
27
58
  //# sourceMappingURL=harness-location.d.ts.map