audit-tools 0.32.9 → 0.32.11

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 (67) hide show
  1. package/README.md +4 -2
  2. package/dist/audit/cli/args.d.ts.map +1 -1
  3. package/dist/audit/cli/args.js +9 -8
  4. package/dist/audit/cli/args.js.map +1 -1
  5. package/dist/audit/cli/hybridDispatch.d.ts +3 -1
  6. package/dist/audit/cli/hybridDispatch.d.ts.map +1 -1
  7. package/dist/audit/cli/hybridDispatch.js +11 -2
  8. package/dist/audit/cli/hybridDispatch.js.map +1 -1
  9. package/dist/audit/cli/nextStepCommand.d.ts.map +1 -1
  10. package/dist/audit/cli/nextStepCommand.js +27 -8
  11. package/dist/audit/cli/nextStepCommand.js.map +1 -1
  12. package/dist/audit/cli/nextStepHelpers.d.ts +11 -0
  13. package/dist/audit/cli/nextStepHelpers.d.ts.map +1 -1
  14. package/dist/audit/cli/nextStepHelpers.js +21 -4
  15. package/dist/audit/cli/nextStepHelpers.js.map +1 -1
  16. package/dist/audit/cli/prompts.d.ts +36 -2
  17. package/dist/audit/cli/prompts.d.ts.map +1 -1
  18. package/dist/audit/cli/prompts.js +40 -3
  19. package/dist/audit/cli/prompts.js.map +1 -1
  20. package/dist/audit/cli/rollingAuditDispatch.d.ts +18 -1
  21. package/dist/audit/cli/rollingAuditDispatch.d.ts.map +1 -1
  22. package/dist/audit/cli/rollingAuditDispatch.js +22 -1
  23. package/dist/audit/cli/rollingAuditDispatch.js.map +1 -1
  24. package/dist/audit/cli/semanticReviewStep.d.ts.map +1 -1
  25. package/dist/audit/cli/semanticReviewStep.js +24 -3
  26. package/dist/audit/cli/semanticReviewStep.js.map +1 -1
  27. package/dist/audit/cli/steps.d.ts +2 -2
  28. package/dist/audit/validation/sessionConfig.d.ts.map +1 -1
  29. package/dist/audit/validation/sessionConfig.js +7 -1
  30. package/dist/audit/validation/sessionConfig.js.map +1 -1
  31. package/dist/remediate/index.d.ts +0 -1
  32. package/dist/remediate/index.d.ts.map +1 -1
  33. package/dist/remediate/index.js +0 -14
  34. package/dist/remediate/index.js.map +1 -1
  35. package/dist/remediate/steps/dispatch.d.ts +2 -0
  36. package/dist/remediate/steps/dispatch.d.ts.map +1 -1
  37. package/dist/remediate/steps/dispatch.js +18 -4
  38. package/dist/remediate/steps/dispatch.js.map +1 -1
  39. package/dist/remediate/steps/nextStep.d.ts.map +1 -1
  40. package/dist/remediate/steps/nextStep.js +41 -40
  41. package/dist/remediate/steps/nextStep.js.map +1 -1
  42. package/dist/shared/dispatch/rollingDispatch.d.ts.map +1 -1
  43. package/dist/shared/dispatch/rollingDispatch.js +9 -1
  44. package/dist/shared/dispatch/rollingDispatch.js.map +1 -1
  45. package/dist/shared/index.d.ts +2 -2
  46. package/dist/shared/index.d.ts.map +1 -1
  47. package/dist/shared/index.js +2 -2
  48. package/dist/shared/index.js.map +1 -1
  49. package/dist/shared/providers/openAiCompatibleProvider.d.ts.map +1 -1
  50. package/dist/shared/providers/openAiCompatibleProvider.js +42 -15
  51. package/dist/shared/providers/openAiCompatibleProvider.js.map +1 -1
  52. package/dist/shared/quota/apiPool.d.ts +29 -4
  53. package/dist/shared/quota/apiPool.d.ts.map +1 -1
  54. package/dist/shared/quota/apiPool.js +114 -25
  55. package/dist/shared/quota/apiPool.js.map +1 -1
  56. package/dist/shared/quota/claimLease.d.ts.map +1 -1
  57. package/dist/shared/quota/claimLease.js +8 -1
  58. package/dist/shared/quota/claimLease.js.map +1 -1
  59. package/dist/shared/types/sessionConfig.d.ts +42 -0
  60. package/dist/shared/types/sessionConfig.d.ts.map +1 -1
  61. package/dist/shared/types/sessionConfig.js +39 -0
  62. package/dist/shared/types/sessionConfig.js.map +1 -1
  63. package/docs/audit-pkg/contracts.md +5 -4
  64. package/docs/audit-pkg/operator-guide.md +9 -10
  65. package/package.json +1 -1
  66. package/skills/audit-code/SKILL.md +11 -2
  67. package/wrapper/audit-code-wrapper-install-hosts.mjs +16 -8
@@ -2,7 +2,7 @@ import { existsSync, statSync } from "node:fs";
2
2
  import { mkdir, readFile, rename } from "node:fs/promises";
3
3
  import { dirname, join, resolve } from "node:path";
4
4
  import { StateStore } from "../state/store.js";
5
- import { readOptionalJsonFile, writeJsonFile, writeTextFile, buildAuditDeliverablePair, formatValidationIssues, isRecord, withFsRetry, RunLogger, DISPATCH_PROMPT_HANDOFF_NOTE, renderQuotaCoverageNudge, renderTokenBudgetView, coerceJsonObjectArg, driveRolling, resolveLedgerBudgets, setQuotaStateDir, interpretFreeFormIntent, advance, decideFrictionTriage, buildFrictionTriageBlock, planHybridDispatch, readSettledPools, addSettledPool, sourceByPoolId, classifyProvider, selectDispatchDriver, renderDispatchDriverInstruction, HostSessionQuotaSource, buildProviderModelKey, captureStepBoundaryFriction, LENSES, SEVERITIES } from "audit-tools/shared";
5
+ import { readOptionalJsonFile, writeJsonFile, writeTextFile, buildAuditDeliverablePair, formatValidationIssues, isRecord, withFsRetry, RunLogger, DISPATCH_PROMPT_HANDOFF_NOTE, renderQuotaCoverageNudge, renderTokenBudgetView, coerceJsonObjectArg, driveRolling, resolveLedgerBudgets, setQuotaStateDir, interpretFreeFormIntent, advance, decideFrictionTriage, buildFrictionTriageBlock, planHybridDispatch, readSettledPools, addSettledPool, sourceByPoolId, classifyProvider, selectDispatchDriver, renderDispatchDriverInstruction, HostSessionQuotaSource, buildProviderModelKey, captureStepBoundaryFriction, LENSES, SEVERITIES, resolveHostProviderName, resolveHostDispatchCapability as sharedResolveHostDispatchCapability, isDemotableInProcessProvider } from "audit-tools/shared";
6
6
  import { applyPlanPipeline, buildCoverageLedger } from "../phases/plan.js";
7
7
  import { groundExtractedFindings } from "../phases/grounding.js";
8
8
  import { runTriagePhase } from "../phases/triage.js";
@@ -38,36 +38,18 @@ import { ambiguityReviewPrompt, clarificationPrompt, collectIntakeClarifications
38
38
  // from the canonical enum (the very drift `types/lens.ts` exists to prevent).
39
39
  const VALID_LENSES_PROSE = LENSES.map((lens) => `\`${lens}\``).join(", ");
40
40
  const VALID_SEVERITIES_PROSE = SEVERITIES.map((sev) => `\`${sev}\``).join(", ");
41
- /**
42
- * The host's resolved provider identity for quota-key / driver-classification
43
- * purposes: the configured `sessionConfig.provider`, defaulting to the
44
- * conversation host (`claude-code`) when unset or `auto`. Single-sourced so the
45
- * `?? "claude-code"` default and the `auto`-exclusion live in ONE place rather
46
- * than being re-spelled (with an ad-hoc cast) at each dispatch call site.
47
- */
48
- function resolveHostProviderName(sessionConfig) {
49
- const provider = sessionConfig?.provider;
50
- if (provider === undefined || provider === "auto")
51
- return "claude-code";
52
- return provider;
53
- }
54
41
  export function resolveHostDispatchCapability(options) {
55
- if (options.hostCanDispatchSubagents !== undefined) {
56
- return options.hostCanDispatchSubagents;
57
- }
58
- if (options.sessionConfig?.host_can_dispatch_subagents !== undefined) {
59
- return options.sessionConfig.host_can_dispatch_subagents;
60
- }
61
- const envValue = (options.env ?? process.env).REMEDIATE_HOST_CAN_DISPATCH;
62
- if (envValue === "true")
63
- return true;
64
- if (envValue === "false")
65
- return false;
66
- // Conversation-first default: an interactive agent host (e.g. Claude Code) can
67
- // dispatch callable subagents, so default to parallel wave dispatch. A host that
68
- // genuinely cannot dispatch opts out via host_can_dispatch_subagents:false,
69
- // REMEDIATE_HOST_CAN_DISPATCH=false, or --host-can-dispatch-subagents=false.
70
- return true;
42
+ // Conversation-first default (single-sourced in shared): an interactive agent host
43
+ // (e.g. Claude Code) can dispatch callable subagents, so default to parallel wave
44
+ // dispatch. A host that genuinely cannot dispatch opts out via
45
+ // host_can_dispatch_subagents:false, REMEDIATE_HOST_CAN_DISPATCH=false, or
46
+ // --no-host-can-dispatch-subagents. Remediate supplies its own env var name.
47
+ return sharedResolveHostDispatchCapability({
48
+ explicit: options.hostCanDispatchSubagents,
49
+ sessionConfig: options.sessionConfig,
50
+ envVarName: "REMEDIATE_HOST_CAN_DISPATCH",
51
+ env: options.env,
52
+ });
71
53
  }
72
54
  /**
73
55
  * Whether the run is unattended (autonomous). Host-agnostic — ONE flag drives
@@ -1173,15 +1155,25 @@ async function buildImplementDispatchStep(ctx) {
1173
1155
  hostModels: resolvedHostModels,
1174
1156
  hostModelId: resolvedHostModelId,
1175
1157
  };
1176
- // A8 in-process provider driver: when the rolling engine is enabled AND the
1177
- // operator EXPLICITLY configured a programmatic backend provider (openai-compatible
1178
- // / codex / opencode / …), the orchestrator drives the FULL rolling implement
1179
- // dispatch ITSELF the configured provider is the per-node worker, cwd-confined to
1180
- // each node's worktree, sharing the same `acceptNodeWorktree` core (commit verify
1181
- // → merge, verify-fail triage) as the host-subagent driver. Checked BEFORE the
1182
- // host-subagent branch so an explicit backend (e.g. a NIM pool for headless
1183
- // autonomy) drives the work rather than the conversation host's subagents.
1184
- if (rollingEngineEnabled && resolvesToInProcessDispatchProvider(sessionConfigImpl)) {
1158
+ // A8 in-process provider driver: when the rolling engine is enabled, the run is
1159
+ // HEADLESS (no attended host that can dispatch subagents), AND the operator
1160
+ // EXPLICITLY configured a programmatic backend provider (openai-compatible / codex /
1161
+ // opencode / …), the orchestrator drives the FULL rolling implement dispatch ITSELF —
1162
+ // the configured provider is the per-node worker, cwd-confined to each node's
1163
+ // worktree, sharing the same `acceptNodeWorktree` core (commit verify merge,
1164
+ // verify-fail triage) as the host-subagent driver. Defect-1: gated on `!canDispatchImpl`
1165
+ // so an ATTENDED host demotes the backend to a source pool (the hybrid branch below,
1166
+ // host + backend + NIM concurrent) rather than the backend monopolizing the frontier;
1167
+ // only a truly headless run (e.g. a NIM pool for headless autonomy, host_can_dispatch:false)
1168
+ // lets the backend self-drive.
1169
+ // Defect-1: DEMOTE (attended concurrent fan-out) applies only to the demotable
1170
+ // backends (codex/opencode/openai-compatible). A non-demotable in-process provider
1171
+ // (subprocess-template/local-subprocess — no standalone source pool) keeps
1172
+ // self-driving regardless of attendance, so the monopoly branch still fires for it.
1173
+ const demoteBackendToSource = canDispatchImpl && isDemotableInProcessProvider(sessionConfigImpl?.provider);
1174
+ if (rollingEngineEnabled &&
1175
+ !demoteBackendToSource &&
1176
+ resolvesToInProcessDispatchProvider(sessionConfigImpl)) {
1185
1177
  const driven = await driveRollingImplementDispatch({
1186
1178
  root,
1187
1179
  artifactsDir,
@@ -1223,7 +1215,12 @@ async function buildImplementDispatchStep(ctx) {
1223
1215
  // bounded rate-limited/settle mechanism below (DC-4) rather than routing
1224
1216
  // through HostSessionQuotaSource.recordLimit/isEscalated, so onEscalation is
1225
1217
  // unused here — the source only feeds buildConfirmedPools' sizing.
1226
- const hybridProviderName = resolveHostProviderName(sessionConfigImpl);
1218
+ // Defect-1: the host-session quota key must follow the CONVERSATION HOST, not a
1219
+ // demoted backend — key it to claude-code when the configured primary is a
1220
+ // demotable backend that this attended run is fanning out onto as a source.
1221
+ const hybridProviderName = demoteBackendToSource
1222
+ ? "claude-code"
1223
+ : resolveHostProviderName(sessionConfigImpl);
1227
1224
  const hybridHostSessionModelKey = buildProviderModelKey(hybridProviderName, sessionConfigImpl
1228
1225
  ?.block_quota?.host_model ??
1229
1226
  resolvedHostModelId ??
@@ -1239,6 +1236,10 @@ async function buildImplementDispatchStep(ctx) {
1239
1236
  hostModels: resolvedHostModels,
1240
1237
  hostModelId: resolvedHostModelId,
1241
1238
  hostSession: hybridHostSession,
1239
+ // Defect-1: reached here because the headless in-process branch above was
1240
+ // skipped (attended host) — demote the configured primary backend into the
1241
+ // source-pool set so the split fans across host + backend + NIM.
1242
+ demotePrimaryInProcess: demoteBackendToSource,
1242
1243
  });
1243
1244
  const backendPools = confirmedPools.filter(isInProcessPool);
1244
1245
  let rolling;