opencode-swarm 6.28.1 → 6.29.1

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.
package/dist/cli/index.js CHANGED
@@ -14011,14 +14011,16 @@ var init_evidence_schema = __esm(() => {
14011
14011
  });
14012
14012
  RetrospectiveEvidenceSchema = BaseEvidenceSchema.extend({
14013
14013
  type: exports_external.literal("retrospective"),
14014
- phase_number: exports_external.number().int().min(0),
14015
- total_tool_calls: exports_external.number().int().min(0),
14016
- coder_revisions: exports_external.number().int().min(0),
14017
- reviewer_rejections: exports_external.number().int().min(0),
14018
- test_failures: exports_external.number().int().min(0),
14019
- security_findings: exports_external.number().int().min(0),
14020
- integration_issues: exports_external.number().int().min(0),
14021
- task_count: exports_external.number().int().min(1),
14014
+ phase_number: exports_external.number().int().min(0).max(99),
14015
+ total_tool_calls: exports_external.number().int().min(0).max(9999),
14016
+ coder_revisions: exports_external.number().int().min(0).max(999),
14017
+ reviewer_rejections: exports_external.number().int().min(0).max(999),
14018
+ loop_detections: exports_external.number().int().min(0).max(9999).optional(),
14019
+ circuit_breaker_trips: exports_external.number().int().min(0).max(9999).optional(),
14020
+ test_failures: exports_external.number().int().min(0).max(9999),
14021
+ security_findings: exports_external.number().int().min(0).max(999),
14022
+ integration_issues: exports_external.number().int().min(0).max(999),
14023
+ task_count: exports_external.number().int().min(1).max(9999),
14022
14024
  task_complexity: exports_external.enum(["trivial", "simple", "moderate", "complex"]),
14023
14025
  top_rejection_reasons: exports_external.array(exports_external.string()).default([]),
14024
14026
  lessons_learned: exports_external.array(exports_external.string()).max(5).default([]),
@@ -17209,6 +17211,25 @@ var CuratorConfigSchema = exports_external.object({
17209
17211
  suppress_warnings: exports_external.boolean().default(true),
17210
17212
  drift_inject_max_chars: exports_external.number().min(100).max(2000).default(500)
17211
17213
  });
17214
+ var SlopDetectorConfigSchema = exports_external.object({
17215
+ enabled: exports_external.boolean().default(true),
17216
+ classThreshold: exports_external.number().int().min(1).default(3),
17217
+ commentStripThreshold: exports_external.number().int().min(1).default(5),
17218
+ diffLineThreshold: exports_external.number().int().min(10).default(200)
17219
+ });
17220
+ var IncrementalVerifyConfigSchema = exports_external.object({
17221
+ enabled: exports_external.boolean().default(true),
17222
+ command: exports_external.string().nullable().default(null),
17223
+ timeoutMs: exports_external.number().int().min(1000).max(300000).default(30000),
17224
+ triggerAgents: exports_external.array(exports_external.string()).default(["coder"])
17225
+ });
17226
+ var CompactionConfigSchema = exports_external.object({
17227
+ enabled: exports_external.boolean().default(true),
17228
+ observationThreshold: exports_external.number().min(1).max(99).default(40),
17229
+ reflectionThreshold: exports_external.number().min(1).max(99).default(60),
17230
+ emergencyThreshold: exports_external.number().min(1).max(99).default(80),
17231
+ preserveLastNTurns: exports_external.number().int().min(1).default(5)
17232
+ });
17212
17233
  var PluginConfigSchema = exports_external.object({
17213
17234
  agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional(),
17214
17235
  swarms: exports_external.record(exports_external.string(), SwarmConfigSchema).optional(),
@@ -17242,7 +17263,10 @@ var PluginConfigSchema = exports_external.object({
17242
17263
  truncation_enabled: exports_external.boolean().default(true),
17243
17264
  max_lines: exports_external.number().min(10).max(500).default(150),
17244
17265
  per_tool: exports_external.record(exports_external.string(), exports_external.number()).optional()
17245
- }).optional()
17266
+ }).optional(),
17267
+ slop_detector: SlopDetectorConfigSchema.optional(),
17268
+ incremental_verify: IncrementalVerifyConfigSchema.optional(),
17269
+ compaction_service: CompactionConfigSchema.optional()
17246
17270
  });
17247
17271
 
17248
17272
  // src/config/loader.ts
@@ -17428,6 +17452,7 @@ var swarmState = {
17428
17452
  activeAgent: new Map,
17429
17453
  delegationChains: new Map,
17430
17454
  pendingEvents: 0,
17455
+ lastBudgetPct: 0,
17431
17456
  agentSessions: new Map
17432
17457
  };
17433
17458
  function getAgentSession(sessionId) {
@@ -33774,10 +33799,7 @@ var secretscan = tool({
33774
33799
  const excludeExact = new Set(DEFAULT_EXCLUDE_DIRS);
33775
33800
  const excludeGlobs = [];
33776
33801
  const ignoreFilePatterns = loadSecretScanIgnore(scanDir);
33777
- const allUserPatterns = [
33778
- ...exclude ?? [],
33779
- ...ignoreFilePatterns
33780
- ];
33802
+ const allUserPatterns = [...exclude ?? [], ...ignoreFilePatterns];
33781
33803
  for (const exc of allUserPatterns) {
33782
33804
  if (exc.length === 0)
33783
33805
  continue;
@@ -34025,7 +34047,7 @@ function detectMinitest(cwd) {
34025
34047
  return fs5.existsSync(path13.join(cwd, "test")) && (fs5.existsSync(path13.join(cwd, "Gemfile")) || fs5.existsSync(path13.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
34026
34048
  }
34027
34049
  async function detectTestFramework(cwd) {
34028
- const baseDir = cwd || process.cwd();
34050
+ const baseDir = cwd;
34029
34051
  try {
34030
34052
  const packageJsonPath = path13.join(baseDir, "package.json");
34031
34053
  if (fs5.existsSync(packageJsonPath)) {
@@ -35640,6 +35662,39 @@ function extractCurrentPhaseFromPlan2(plan) {
35640
35662
  // src/services/status-service.ts
35641
35663
  init_utils2();
35642
35664
  init_manager2();
35665
+
35666
+ // src/services/compaction-service.ts
35667
+ function makeInitialState() {
35668
+ return {
35669
+ lastObservationAt: 0,
35670
+ lastReflectionAt: 0,
35671
+ lastEmergencyAt: 0,
35672
+ observationCount: 0,
35673
+ reflectionCount: 0,
35674
+ emergencyCount: 0,
35675
+ lastSnapshotAt: null
35676
+ };
35677
+ }
35678
+ var state = makeInitialState();
35679
+ function getCompactionMetrics() {
35680
+ return {
35681
+ compactionCount: state.observationCount + state.reflectionCount + state.emergencyCount,
35682
+ lastSnapshotAt: state.lastSnapshotAt
35683
+ };
35684
+ }
35685
+
35686
+ // src/services/context-budget-service.ts
35687
+ init_utils2();
35688
+ var DEFAULT_CONTEXT_BUDGET_CONFIG = {
35689
+ enabled: true,
35690
+ budgetTokens: 40000,
35691
+ warningPct: 70,
35692
+ criticalPct: 90,
35693
+ warningMode: "once",
35694
+ warningIntervalTurns: 20
35695
+ };
35696
+
35697
+ // src/services/status-service.ts
35643
35698
  async function getStatusData(directory, agents) {
35644
35699
  const plan = await loadPlan(directory);
35645
35700
  if (plan && plan.migration_status !== "migration_failed") {
@@ -35654,6 +35709,7 @@ async function getStatusData(directory, agents) {
35654
35709
  }
35655
35710
  }
35656
35711
  const agentCount2 = Object.keys(agents).length;
35712
+ const metrics2 = getCompactionMetrics();
35657
35713
  return {
35658
35714
  hasPlan: true,
35659
35715
  currentPhase: currentPhase2,
@@ -35661,11 +35717,15 @@ async function getStatusData(directory, agents) {
35661
35717
  totalTasks: totalTasks2,
35662
35718
  agentCount: agentCount2,
35663
35719
  isLegacy: false,
35664
- turboMode: hasActiveTurboMode()
35720
+ turboMode: hasActiveTurboMode(),
35721
+ contextBudgetPct: swarmState.lastBudgetPct > 0 ? swarmState.lastBudgetPct : null,
35722
+ compactionCount: metrics2.compactionCount,
35723
+ lastSnapshotAt: metrics2.lastSnapshotAt
35665
35724
  };
35666
35725
  }
35667
35726
  const planContent = await readSwarmFileAsync(directory, "plan.md");
35668
35727
  if (!planContent) {
35728
+ const metrics2 = getCompactionMetrics();
35669
35729
  return {
35670
35730
  hasPlan: false,
35671
35731
  currentPhase: "Unknown",
@@ -35673,7 +35733,10 @@ async function getStatusData(directory, agents) {
35673
35733
  totalTasks: 0,
35674
35734
  agentCount: Object.keys(agents).length,
35675
35735
  isLegacy: true,
35676
- turboMode: hasActiveTurboMode()
35736
+ turboMode: hasActiveTurboMode(),
35737
+ contextBudgetPct: swarmState.lastBudgetPct > 0 ? swarmState.lastBudgetPct : null,
35738
+ compactionCount: metrics2.compactionCount,
35739
+ lastSnapshotAt: metrics2.lastSnapshotAt
35677
35740
  };
35678
35741
  }
35679
35742
  const currentPhase = extractCurrentPhase(planContent) || "Unknown";
@@ -35681,6 +35744,7 @@ async function getStatusData(directory, agents) {
35681
35744
  const incompleteTasks = (planContent.match(/^- \[ \]/gm) || []).length;
35682
35745
  const totalTasks = completedTasks + incompleteTasks;
35683
35746
  const agentCount = Object.keys(agents).length;
35747
+ const metrics = getCompactionMetrics();
35684
35748
  return {
35685
35749
  hasPlan: true,
35686
35750
  currentPhase,
@@ -35688,7 +35752,10 @@ async function getStatusData(directory, agents) {
35688
35752
  totalTasks,
35689
35753
  agentCount,
35690
35754
  isLegacy: true,
35691
- turboMode: hasActiveTurboMode()
35755
+ turboMode: hasActiveTurboMode(),
35756
+ contextBudgetPct: swarmState.lastBudgetPct > 0 ? swarmState.lastBudgetPct : null,
35757
+ compactionCount: metrics.compactionCount,
35758
+ lastSnapshotAt: metrics.lastSnapshotAt
35692
35759
  };
35693
35760
  }
35694
35761
  function formatStatusMarkdown(status) {
@@ -35702,6 +35769,18 @@ function formatStatusMarkdown(status) {
35702
35769
  if (status.turboMode) {
35703
35770
  lines.push("", `**TURBO MODE**: active`);
35704
35771
  }
35772
+ if (status.contextBudgetPct !== null && status.contextBudgetPct > 0) {
35773
+ const pct = status.contextBudgetPct.toFixed(1);
35774
+ const budgetTokens = DEFAULT_CONTEXT_BUDGET_CONFIG.budgetTokens;
35775
+ const est = Math.round(status.contextBudgetPct / 100 * budgetTokens);
35776
+ lines.push("", `**Context**: ${pct}% used (est. ${est.toLocaleString()} / ${budgetTokens.toLocaleString()} tokens)`);
35777
+ if (status.compactionCount > 0) {
35778
+ lines.push(`**Compaction events**: ${status.compactionCount} triggered`);
35779
+ }
35780
+ if (status.lastSnapshotAt) {
35781
+ lines.push(`**Last snapshot**: ${status.lastSnapshotAt}`);
35782
+ }
35783
+ }
35705
35784
  return lines.join(`
35706
35785
  `);
35707
35786
  }
@@ -35794,6 +35873,132 @@ async function executeWriteRetro(args, directory) {
35794
35873
  message: "Invalid task_count: must be a positive integer >= 1"
35795
35874
  }, null, 2);
35796
35875
  }
35876
+ if (!Number.isInteger(args.total_tool_calls) || args.total_tool_calls < 0) {
35877
+ return JSON.stringify({
35878
+ success: false,
35879
+ phase,
35880
+ message: "Invalid total_tool_calls: must be a non-negative integer"
35881
+ }, null, 2);
35882
+ }
35883
+ if (!Number.isInteger(args.coder_revisions) || args.coder_revisions < 0) {
35884
+ return JSON.stringify({
35885
+ success: false,
35886
+ phase,
35887
+ message: "Invalid coder_revisions: must be a non-negative integer"
35888
+ }, null, 2);
35889
+ }
35890
+ if (!Number.isInteger(args.reviewer_rejections) || args.reviewer_rejections < 0) {
35891
+ return JSON.stringify({
35892
+ success: false,
35893
+ phase,
35894
+ message: "Invalid reviewer_rejections: must be a non-negative integer"
35895
+ }, null, 2);
35896
+ }
35897
+ if (!Number.isInteger(args.test_failures) || args.test_failures < 0) {
35898
+ return JSON.stringify({
35899
+ success: false,
35900
+ phase,
35901
+ message: "Invalid test_failures: must be a non-negative integer"
35902
+ }, null, 2);
35903
+ }
35904
+ if (!Number.isInteger(args.security_findings) || args.security_findings < 0) {
35905
+ return JSON.stringify({
35906
+ success: false,
35907
+ phase,
35908
+ message: "Invalid security_findings: must be a non-negative integer"
35909
+ }, null, 2);
35910
+ }
35911
+ if (!Number.isInteger(args.integration_issues) || args.integration_issues < 0) {
35912
+ return JSON.stringify({
35913
+ success: false,
35914
+ phase,
35915
+ message: "Invalid integration_issues: must be a non-negative integer"
35916
+ }, null, 2);
35917
+ }
35918
+ if (args.loop_detections !== undefined && (!Number.isInteger(args.loop_detections) || args.loop_detections < 0)) {
35919
+ return JSON.stringify({
35920
+ success: false,
35921
+ phase,
35922
+ message: "Invalid loop_detections: must be a non-negative integer"
35923
+ }, null, 2);
35924
+ }
35925
+ if (args.circuit_breaker_trips !== undefined && (!Number.isInteger(args.circuit_breaker_trips) || args.circuit_breaker_trips < 0)) {
35926
+ return JSON.stringify({
35927
+ success: false,
35928
+ phase,
35929
+ message: "Invalid circuit_breaker_trips: must be a non-negative integer"
35930
+ }, null, 2);
35931
+ }
35932
+ if (args.phase > 99) {
35933
+ return JSON.stringify({
35934
+ success: false,
35935
+ phase,
35936
+ message: "Invalid phase: must be <= 99"
35937
+ }, null, 2);
35938
+ }
35939
+ if (args.task_count > 9999) {
35940
+ return JSON.stringify({
35941
+ success: false,
35942
+ phase,
35943
+ message: "Invalid task_count: must be <= 9999"
35944
+ }, null, 2);
35945
+ }
35946
+ if (args.total_tool_calls > 9999) {
35947
+ return JSON.stringify({
35948
+ success: false,
35949
+ phase,
35950
+ message: "Invalid total_tool_calls: must be <= 9999"
35951
+ }, null, 2);
35952
+ }
35953
+ if (args.coder_revisions > 999) {
35954
+ return JSON.stringify({
35955
+ success: false,
35956
+ phase,
35957
+ message: "Invalid coder_revisions: must be <= 999"
35958
+ }, null, 2);
35959
+ }
35960
+ if (args.reviewer_rejections > 999) {
35961
+ return JSON.stringify({
35962
+ success: false,
35963
+ phase,
35964
+ message: "Invalid reviewer_rejections: must be <= 999"
35965
+ }, null, 2);
35966
+ }
35967
+ if (args.loop_detections !== undefined && args.loop_detections > 9999) {
35968
+ return JSON.stringify({
35969
+ success: false,
35970
+ phase,
35971
+ message: "Invalid loop_detections: must be <= 9999"
35972
+ }, null, 2);
35973
+ }
35974
+ if (args.circuit_breaker_trips !== undefined && args.circuit_breaker_trips > 9999) {
35975
+ return JSON.stringify({
35976
+ success: false,
35977
+ phase,
35978
+ message: "Invalid circuit_breaker_trips: must be <= 9999"
35979
+ }, null, 2);
35980
+ }
35981
+ if (args.test_failures > 9999) {
35982
+ return JSON.stringify({
35983
+ success: false,
35984
+ phase,
35985
+ message: "Invalid test_failures: must be <= 9999"
35986
+ }, null, 2);
35987
+ }
35988
+ if (args.security_findings > 999) {
35989
+ return JSON.stringify({
35990
+ success: false,
35991
+ phase,
35992
+ message: "Invalid security_findings: must be <= 999"
35993
+ }, null, 2);
35994
+ }
35995
+ if (args.integration_issues > 999) {
35996
+ return JSON.stringify({
35997
+ success: false,
35998
+ phase,
35999
+ message: "Invalid integration_issues: must be <= 999"
36000
+ }, null, 2);
36001
+ }
35797
36002
  const summary = args.summary;
35798
36003
  if (typeof summary !== "string" || summary.trim().length === 0) {
35799
36004
  return JSON.stringify({
@@ -35815,6 +36020,8 @@ async function executeWriteRetro(args, directory) {
35815
36020
  total_tool_calls: args.total_tool_calls,
35816
36021
  coder_revisions: args.coder_revisions,
35817
36022
  reviewer_rejections: args.reviewer_rejections,
36023
+ loop_detections: args.loop_detections,
36024
+ circuit_breaker_trips: args.circuit_breaker_trips,
35818
36025
  test_failures: args.test_failures,
35819
36026
  security_findings: args.security_findings,
35820
36027
  integration_issues: args.integration_issues,
@@ -35844,16 +36051,18 @@ async function executeWriteRetro(args, directory) {
35844
36051
  var write_retro = createSwarmTool({
35845
36052
  description: "Write a retrospective evidence bundle for a completed phase. " + "Accepts flat retro fields and writes a correctly-wrapped EvidenceBundle to " + ".swarm/evidence/retro-{phase}/evidence.json. " + "Use this instead of manually writing retro JSON to avoid schema validation failures in phase_complete.",
35846
36053
  args: {
35847
- phase: tool.schema.number().int().positive().describe("The phase number being completed (e.g., 1, 2, 3)"),
36054
+ phase: tool.schema.number().int().positive().max(99).describe("The phase number being completed (e.g., 1, 2, 3)"),
35848
36055
  summary: tool.schema.string().describe("Human-readable summary of the phase"),
35849
- task_count: tool.schema.number().int().min(1).describe("Count of tasks completed in this phase"),
36056
+ task_count: tool.schema.number().int().min(1).max(9999).describe("Count of tasks completed in this phase"),
35850
36057
  task_complexity: tool.schema.enum(["trivial", "simple", "moderate", "complex"]).describe("Complexity level of the completed tasks"),
35851
- total_tool_calls: tool.schema.number().int().min(0).describe("Total number of tool calls in this phase"),
35852
- coder_revisions: tool.schema.number().int().min(0).describe("Number of coder revisions made"),
35853
- reviewer_rejections: tool.schema.number().int().min(0).describe("Number of reviewer rejections received"),
35854
- test_failures: tool.schema.number().int().min(0).describe("Number of test failures encountered"),
35855
- security_findings: tool.schema.number().int().min(0).describe("Number of security findings"),
35856
- integration_issues: tool.schema.number().int().min(0).describe("Number of integration issues"),
36058
+ total_tool_calls: tool.schema.number().int().min(0).max(9999).describe("Total number of tool calls in this phase"),
36059
+ coder_revisions: tool.schema.number().int().min(0).max(999).describe("Number of coder revisions made"),
36060
+ reviewer_rejections: tool.schema.number().int().min(0).max(999).describe("Number of reviewer rejections received"),
36061
+ loop_detections: tool.schema.number().int().min(0).max(9999).optional().describe("Number of loop detection events in this phase"),
36062
+ circuit_breaker_trips: tool.schema.number().int().min(0).max(9999).optional().describe("Number of circuit breaker trips in this phase"),
36063
+ test_failures: tool.schema.number().int().min(0).max(9999).describe("Number of test failures encountered"),
36064
+ security_findings: tool.schema.number().int().min(0).max(999).describe("Number of security findings"),
36065
+ integration_issues: tool.schema.number().int().min(0).max(999).describe("Number of integration issues"),
35857
36066
  lessons_learned: tool.schema.array(tool.schema.string()).max(5).optional().describe("Key lessons learned from this phase (max 5)"),
35858
36067
  top_rejection_reasons: tool.schema.array(tool.schema.string()).optional().describe("Top reasons for reviewer rejections"),
35859
36068
  task_id: tool.schema.string().optional().describe("Optional custom task ID (defaults to retro-{phase})"),
@@ -35870,6 +36079,8 @@ var write_retro = createSwarmTool({
35870
36079
  total_tool_calls: Number(args.total_tool_calls),
35871
36080
  coder_revisions: Number(args.coder_revisions),
35872
36081
  reviewer_rejections: Number(args.reviewer_rejections),
36082
+ loop_detections: args.loop_detections != null ? Number(args.loop_detections) : undefined,
36083
+ circuit_breaker_trips: args.circuit_breaker_trips != null ? Number(args.circuit_breaker_trips) : undefined,
35873
36084
  test_failures: Number(args.test_failures),
35874
36085
  security_findings: Number(args.security_findings),
35875
36086
  integration_issues: Number(args.integration_issues),
@@ -35,3 +35,22 @@ export declare const LOW_CAPABILITY_MODELS: readonly ["mini", "nano", "small", "
35
35
  * @returns true if the model is considered low capability, false otherwise
36
36
  */
37
37
  export declare function isLowCapabilityModel(modelId: string): boolean;
38
+ export declare const SLOP_DETECTOR_DEFAULTS: {
39
+ readonly enabled: true;
40
+ readonly classThreshold: 3;
41
+ readonly commentStripThreshold: 5;
42
+ readonly diffLineThreshold: 200;
43
+ };
44
+ export declare const INCREMENTAL_VERIFY_DEFAULTS: {
45
+ readonly enabled: true;
46
+ readonly command: null;
47
+ readonly timeoutMs: 30000;
48
+ readonly triggerAgents: readonly ["coder"];
49
+ };
50
+ export declare const COMPACTION_DEFAULTS: {
51
+ readonly enabled: true;
52
+ readonly observationThreshold: 40;
53
+ readonly reflectionThreshold: 60;
54
+ readonly emergencyThreshold: 80;
55
+ readonly preserveLastNTurns: 5;
56
+ };
@@ -179,6 +179,8 @@ export declare const RetrospectiveEvidenceSchema: z.ZodObject<{
179
179
  total_tool_calls: z.ZodNumber;
180
180
  coder_revisions: z.ZodNumber;
181
181
  reviewer_rejections: z.ZodNumber;
182
+ loop_detections: z.ZodOptional<z.ZodNumber>;
183
+ circuit_breaker_trips: z.ZodOptional<z.ZodNumber>;
182
184
  test_failures: z.ZodNumber;
183
185
  security_findings: z.ZodNumber;
184
186
  integration_issues: z.ZodNumber;
@@ -547,6 +549,8 @@ export declare const EvidenceSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
547
549
  total_tool_calls: z.ZodNumber;
548
550
  coder_revisions: z.ZodNumber;
549
551
  reviewer_rejections: z.ZodNumber;
552
+ loop_detections: z.ZodOptional<z.ZodNumber>;
553
+ circuit_breaker_trips: z.ZodOptional<z.ZodNumber>;
550
554
  test_failures: z.ZodNumber;
551
555
  security_findings: z.ZodNumber;
552
556
  integration_issues: z.ZodNumber;
@@ -906,6 +910,8 @@ export declare const EvidenceBundleSchema: z.ZodObject<{
906
910
  total_tool_calls: z.ZodNumber;
907
911
  coder_revisions: z.ZodNumber;
908
912
  reviewer_rejections: z.ZodNumber;
913
+ loop_detections: z.ZodOptional<z.ZodNumber>;
914
+ circuit_breaker_trips: z.ZodOptional<z.ZodNumber>;
909
915
  test_failures: z.ZodNumber;
910
916
  security_findings: z.ZodNumber;
911
917
  integration_issues: z.ZodNumber;
@@ -425,6 +425,28 @@ export declare const CuratorConfigSchema: z.ZodObject<{
425
425
  drift_inject_max_chars: z.ZodDefault<z.ZodNumber>;
426
426
  }, z.core.$strip>;
427
427
  export type CuratorConfig = z.infer<typeof CuratorConfigSchema>;
428
+ export declare const SlopDetectorConfigSchema: z.ZodObject<{
429
+ enabled: z.ZodDefault<z.ZodBoolean>;
430
+ classThreshold: z.ZodDefault<z.ZodNumber>;
431
+ commentStripThreshold: z.ZodDefault<z.ZodNumber>;
432
+ diffLineThreshold: z.ZodDefault<z.ZodNumber>;
433
+ }, z.core.$strip>;
434
+ export type SlopDetectorConfig = z.infer<typeof SlopDetectorConfigSchema>;
435
+ export declare const IncrementalVerifyConfigSchema: z.ZodObject<{
436
+ enabled: z.ZodDefault<z.ZodBoolean>;
437
+ command: z.ZodDefault<z.ZodNullable<z.ZodString>>;
438
+ timeoutMs: z.ZodDefault<z.ZodNumber>;
439
+ triggerAgents: z.ZodDefault<z.ZodArray<z.ZodString>>;
440
+ }, z.core.$strip>;
441
+ export type IncrementalVerifyConfig = z.infer<typeof IncrementalVerifyConfigSchema>;
442
+ export declare const CompactionConfigSchema: z.ZodObject<{
443
+ enabled: z.ZodDefault<z.ZodBoolean>;
444
+ observationThreshold: z.ZodDefault<z.ZodNumber>;
445
+ reflectionThreshold: z.ZodDefault<z.ZodNumber>;
446
+ emergencyThreshold: z.ZodDefault<z.ZodNumber>;
447
+ preserveLastNTurns: z.ZodDefault<z.ZodNumber>;
448
+ }, z.core.$strip>;
449
+ export type CompactionConfig = z.infer<typeof CompactionConfigSchema>;
428
450
  export declare const PluginConfigSchema: z.ZodObject<{
429
451
  agents: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
430
452
  model: z.ZodOptional<z.ZodString>;
@@ -695,6 +717,25 @@ export declare const PluginConfigSchema: z.ZodObject<{
695
717
  max_lines: z.ZodDefault<z.ZodNumber>;
696
718
  per_tool: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
697
719
  }, z.core.$strip>>;
720
+ slop_detector: z.ZodOptional<z.ZodObject<{
721
+ enabled: z.ZodDefault<z.ZodBoolean>;
722
+ classThreshold: z.ZodDefault<z.ZodNumber>;
723
+ commentStripThreshold: z.ZodDefault<z.ZodNumber>;
724
+ diffLineThreshold: z.ZodDefault<z.ZodNumber>;
725
+ }, z.core.$strip>>;
726
+ incremental_verify: z.ZodOptional<z.ZodObject<{
727
+ enabled: z.ZodDefault<z.ZodBoolean>;
728
+ command: z.ZodDefault<z.ZodNullable<z.ZodString>>;
729
+ timeoutMs: z.ZodDefault<z.ZodNumber>;
730
+ triggerAgents: z.ZodDefault<z.ZodArray<z.ZodString>>;
731
+ }, z.core.$strip>>;
732
+ compaction_service: z.ZodOptional<z.ZodObject<{
733
+ enabled: z.ZodDefault<z.ZodBoolean>;
734
+ observationThreshold: z.ZodDefault<z.ZodNumber>;
735
+ reflectionThreshold: z.ZodDefault<z.ZodNumber>;
736
+ emergencyThreshold: z.ZodDefault<z.ZodNumber>;
737
+ preserveLastNTurns: z.ZodDefault<z.ZodNumber>;
738
+ }, z.core.$strip>>;
698
739
  }, z.core.$strip>;
699
740
  export type PluginConfig = z.infer<typeof PluginConfigSchema>;
700
741
  export type { AgentName, PipelineAgentName, QAAgentName, } from './constants';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Diff scope validator — compares files changed in git against the declared scope
3
+ * for a given task in plan.json. Returns a warning string if undeclared files
4
+ * were modified, or null if in-scope, no scope declared, or git unavailable.
5
+ * Never throws.
6
+ */
7
+ /**
8
+ * Validate that git-changed files match the declared scope for a task.
9
+ * Returns a warning string if undeclared files were modified, null otherwise.
10
+ * Never throws.
11
+ */
12
+ export declare function validateDiffScope(taskId: string, directory: string): Promise<string | null>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Incremental verification hook — runs a typecheck after each coder Task delegation.
3
+ * Fires in tool.execute.after when input.tool === 'Task' and the delegated agent was 'coder'.
4
+ * Advisory only — never blocks. 30-second hard timeout. Uses directory from context.
5
+ */
6
+ import type { IncrementalVerifyConfig } from '../config/schema';
7
+ export type { IncrementalVerifyConfig };
8
+ export interface IncrementalVerifyHook {
9
+ toolAfter: (input: {
10
+ tool: string;
11
+ sessionID: string;
12
+ args?: unknown;
13
+ }, output: {
14
+ output?: unknown;
15
+ args?: unknown;
16
+ }) => Promise<void>;
17
+ }
18
+ export declare function createIncrementalVerifyHook(config: IncrementalVerifyConfig, projectDir: string, injectMessage: (sessionId: string, message: string) => void): IncrementalVerifyHook;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Loop detector for Task tool delegations.
3
+ * Tracks the last 10 delegation patterns per session using a sliding window.
4
+ * Detects loops when the same (toolName + targetAgent + firstArgKey) hash
5
+ * appears 3 or more consecutive times.
6
+ */
7
+ export interface LoopDetectResult {
8
+ looping: boolean;
9
+ count: number;
10
+ pattern: string;
11
+ }
12
+ /**
13
+ * Detect delegation loops for a session.
14
+ * Only tracks Task tool calls (agent delegations).
15
+ * Returns the current loop state after recording this call.
16
+ */
17
+ export declare function detectLoop(sessionId: string, toolName: string, args: unknown): LoopDetectResult;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Slop detector — PostToolUse hook that checks for AI code quality anti-patterns.
3
+ * Fires after Write and Edit tool calls. Runs 4 heuristics and emits an advisory
4
+ * system message when findings are detected. Non-blocking, <500ms.
5
+ */
6
+ import type { SlopDetectorConfig } from '../config/schema';
7
+ export type { SlopDetectorConfig };
8
+ export interface SlopDetectorHook {
9
+ toolAfter: (input: {
10
+ tool: string;
11
+ sessionID: string;
12
+ }, output: {
13
+ output?: unknown;
14
+ args?: unknown;
15
+ }) => Promise<void>;
16
+ }
17
+ export declare function createSlopDetectorHook(config: SlopDetectorConfig, projectDir: string, injectSystemMessage: (sessionId: string, message: string) => void): SlopDetectorHook;
@@ -0,0 +1 @@
1
+ export {};