@payconductor/houndsman 0.13.0 → 0.14.0

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 (106) hide show
  1. package/README.md +6 -1
  2. package/package.json +1 -1
  3. package/src/cli/commands/compare-command.ts +112 -0
  4. package/src/cli/commands/context-command.ts +1 -0
  5. package/src/cli/commands/findings-command.ts +11 -1
  6. package/src/cli/commands/hunt-command.ts +20 -3
  7. package/src/cli/commands/review-command.ts +38 -0
  8. package/src/cli/commands/status-command.ts +3 -2
  9. package/src/cli/help.ts +3 -1
  10. package/src/cli/index.ts +3 -1
  11. package/src/cli/progress.ts +7 -2
  12. package/src/core/ai/ai-client.ts +38 -2
  13. package/src/core/ai/features/brief-enricher.ts +1 -1
  14. package/src/core/ai/features/business-analyzer.ts +61 -0
  15. package/src/core/ai/features/business-summarizer.ts +44 -0
  16. package/src/core/ai/index.ts +8 -0
  17. package/src/core/ai/prompts/brief.ts +33 -7
  18. package/src/core/ai/prompts/business.ts +76 -0
  19. package/src/core/ai/provider-capabilities.ts +12 -0
  20. package/src/core/ai/schemas.ts +70 -2
  21. package/src/core/ai/usage-recorder.ts +53 -1
  22. package/src/core/brief.ts +246 -12
  23. package/src/core/builtins.ts +108 -0
  24. package/src/core/business-summary.ts +583 -0
  25. package/src/core/commands/compare.ts +233 -0
  26. package/src/core/commands/context.ts +6 -2
  27. package/src/core/commands/findings.ts +38 -30
  28. package/src/core/commands/review.ts +6 -0
  29. package/src/core/commands/scaffold.ts +27 -0
  30. package/src/core/commands/status.ts +9 -4
  31. package/src/core/compare.ts +243 -0
  32. package/src/core/concurrency.ts +30 -0
  33. package/src/core/config.ts +31 -3
  34. package/src/core/defaults.ts +50 -4
  35. package/src/core/domain/budget.ts +62 -4
  36. package/src/core/domain/classification.ts +12 -2
  37. package/src/core/engine/carryover.ts +4 -0
  38. package/src/core/engine/finalize-pipeline.ts +347 -0
  39. package/src/core/engine/prepare-pipeline.ts +1294 -0
  40. package/src/core/engine/review-context.ts +51 -0
  41. package/src/core/engine/review-options.ts +47 -0
  42. package/src/core/engine/review-scope.ts +14 -1
  43. package/src/core/engine/review-session.ts +11 -13
  44. package/src/core/engine/run-artifacts.ts +196 -0
  45. package/src/core/engine/run-format.ts +4 -0
  46. package/src/core/findings-state.ts +13 -1
  47. package/src/core/github-review.ts +5 -2
  48. package/src/core/hunt/hunt-runner.ts +90 -0
  49. package/src/core/hunt/index.ts +2 -0
  50. package/src/core/hunt/maki-intent-prompt.ts +50 -0
  51. package/src/core/hunt/maki-prompt.ts +13 -1
  52. package/src/core/hunt/pool.ts +4 -26
  53. package/src/core/logging/index.ts +6 -1
  54. package/src/core/logging/progress.ts +85 -1
  55. package/src/core/orchestrator.ts +33 -1289
  56. package/src/core/paths.ts +6 -3
  57. package/src/core/pr-context.ts +2 -4
  58. package/src/core/prepare-report.ts +61 -0
  59. package/src/core/project-config.ts +8 -1
  60. package/src/core/propagation.ts +127 -0
  61. package/src/core/registry-check.ts +60 -21
  62. package/src/core/renderers/manifest-writer.ts +13 -0
  63. package/src/core/renderers/resume-renderer.ts +151 -11
  64. package/src/core/report-builder.ts +108 -278
  65. package/src/core/storage/file/file-storage.ts +7 -3
  66. package/src/core/storage/sqlite/mappers.ts +10 -0
  67. package/src/core/storage/sqlite/schema.ts +104 -23
  68. package/src/core/storage/sqlite/sqlite-storage.ts +22 -9
  69. package/src/core/storage/types.ts +16 -4
  70. package/src/core/storage/work-area.ts +59 -1
  71. package/src/core/types.ts +31 -0
  72. package/src/core/watchdog-registry.ts +21 -3
  73. package/src/index.ts +29 -4
  74. package/src/server/client/ArtifactsPanel.tsx +4 -2
  75. package/src/server/client/FindingCard.tsx +21 -1
  76. package/src/server/client/RunsSection.tsx +5 -0
  77. package/src/server/client/utils/constants.ts +21 -11
  78. package/src/server/client/utils/markdown.ts +1 -1
  79. package/src/server/client/utils/types.ts +14 -2
  80. package/src/server/run-repository.ts +35 -14
  81. package/src/server/styles.css +2 -0
  82. package/src/skill/OUTPUT-FORMAT.md +36 -10
  83. package/src/skill/README.md +18 -14
  84. package/src/skill/SETUP.md +1 -0
  85. package/src/skill/SKILL.md +13 -4
  86. package/src/skill/example-resume.md +43 -0
  87. package/src/skill/hunt.md +145 -58
  88. package/src/tests/__snapshots__/baseline.test.ts.snap +187 -178
  89. package/src/tests/ai-core.test.ts +46 -0
  90. package/src/tests/ai-features.test.ts +95 -4
  91. package/src/tests/baseline.test.ts +29 -121
  92. package/src/tests/brief-scope.test.ts +250 -0
  93. package/src/tests/business-summary.test.ts +258 -0
  94. package/src/tests/compare.test.ts +233 -0
  95. package/src/tests/fixtures/fake-model-provider.ts +2 -1
  96. package/src/tests/hunt-maki.test.ts +58 -0
  97. package/src/tests/markdown.test.ts +3 -3
  98. package/src/tests/progress.test.ts +29 -1
  99. package/src/tests/propagation.test.ts +119 -0
  100. package/src/tests/review-resume.test.ts +60 -1
  101. package/src/tests/review-scope.test.ts +38 -29
  102. package/src/tests/review-scripts.test.ts +106 -218
  103. package/src/tests/server.test.ts +7 -4
  104. package/src/tests/storage.test.ts +194 -9
  105. package/src/core/renderers/report-renderer.ts +0 -66
  106. package/src/skill/example-review.md +0 -66
@@ -1,30 +1,8 @@
1
1
  /**
2
- * Pool de concorrência mínimo (harness local).
2
+ * Pool de concorrência do harness local.
3
3
  *
4
- * Mantém no máximo `limit` promessas ativas e preserva a ordem dos resultados.
5
- * Não trata erros: o chamador decide se cada item falha isoladamente.
4
+ * O algoritmo é genérico e vive em `core/concurrency.ts`; este módulo mantém o
5
+ * caminho histórico (`core/hunt/pool`) usado pelo runner do maki.
6
6
  */
7
7
 
8
- /** Executa `mapper` para cada item com concorrência limitada. */
9
- export async function mapPool<T, R>(
10
- items: readonly T[],
11
- limit: number,
12
- mapper: (item: T, index: number) => Promise<R>,
13
- ): Promise<R[]> {
14
- const results = new Array<R>(items.length);
15
- if (items.length === 0) return results;
16
-
17
- let next = 0;
18
- const workers = Array.from(
19
- { length: Math.max(1, Math.min(limit, items.length)) },
20
- async () => {
21
- while (true) {
22
- const index = next++;
23
- if (index >= items.length) return;
24
- results[index] = await mapper(items[index], index);
25
- }
26
- },
27
- );
28
- await Promise.all(workers);
29
- return results;
30
- }
8
+ export { mapPool } from "../concurrency";
@@ -16,4 +16,9 @@ export type {
16
16
  } from "./logger";
17
17
  export { Logger, SilentLogger } from "./logger";
18
18
  export type { ProgressBoardOptions } from "./progress";
19
- export { formatDuration, PhaseReporter, ProgressBoard } from "./progress";
19
+ export {
20
+ formatDuration,
21
+ ParallelPhaseReporter,
22
+ PhaseReporter,
23
+ ProgressBoard,
24
+ } from "./progress";
@@ -83,13 +83,97 @@ export class PhaseReporter {
83
83
  }
84
84
  }
85
85
 
86
+ /**
87
+ * Relógio de fases **concorrentes** (prepare com etapas em paralelo).
88
+ *
89
+ * No TTY mantém um único spinner com a etapa mais recente e a contagem das
90
+ * demais; em pipe preserva o formato `→`/`✔` por etapa do `PhaseReporter`.
91
+ */
92
+ export class ParallelPhaseReporter {
93
+ private readonly logger: LoggerLike;
94
+ private readonly active = new Map<string, string>();
95
+ private spinner: SpinnerLike | null = null;
96
+
97
+ constructor(logger: LoggerLike) {
98
+ this.logger = logger;
99
+ }
100
+
101
+ /** Abre uma fase (pode haver várias ativas ao mesmo tempo). */
102
+ begin(stage: string, message: string): void {
103
+ try {
104
+ this.active.set(stage, message);
105
+ if (this.spinner) {
106
+ this.restart();
107
+ return;
108
+ }
109
+ const spinner = this.logger.spinner(this.summary());
110
+ if (spinner) {
111
+ this.spinner = spinner.start();
112
+ return;
113
+ }
114
+ this.logger.step(message);
115
+ } catch {
116
+ // Progresso nunca derruba a revisão.
117
+ }
118
+ }
119
+
120
+ /** Fecha uma fase com a duração medida. */
121
+ end(stage: string, message: string, durationMs: number): void {
122
+ try {
123
+ this.active.delete(stage);
124
+ const text = `${message} (${formatDuration(durationMs)})`;
125
+ if (this.spinner) {
126
+ this.spinner.stop();
127
+ this.spinner = null;
128
+ this.logger.success(text);
129
+ this.startSpinner();
130
+ return;
131
+ }
132
+ this.logger.success(text);
133
+ } catch {
134
+ // Progresso nunca derruba a revisão.
135
+ }
136
+ }
137
+
138
+ /** Encerra o spinner pendente (sem mensagem de sucesso). */
139
+ stop(): void {
140
+ try {
141
+ this.spinner?.stop();
142
+ } catch {
143
+ // Progresso nunca derruba a revisão.
144
+ }
145
+ this.spinner = null;
146
+ }
147
+
148
+ /** Texto agregado das fases ativas. */
149
+ private summary(): string {
150
+ const messages = [...this.active.values()];
151
+ if (messages.length <= 1) return messages[0] ?? "";
152
+ return `${messages[0]} (+${messages.length - 1} em paralelo)`;
153
+ }
154
+
155
+ /** Reinicia o spinner com o texto agregado atualizado. */
156
+ private restart(): void {
157
+ if (!this.spinner) return;
158
+ this.spinner.stop();
159
+ this.spinner = null;
160
+ this.startSpinner();
161
+ }
162
+
163
+ /** (Re)abre o spinner quando ainda há fases ativas. */
164
+ private startSpinner(): void {
165
+ if (this.active.size === 0) return;
166
+ const spinner = this.logger.spinner(this.summary());
167
+ this.spinner = spinner ? spinner.start() : null;
168
+ }
169
+ }
170
+
86
171
  /** Tarefa concorrente exibida pelo board. */
87
172
  type BoardTask = {
88
173
  id: string;
89
174
  detail: string;
90
175
  startedMs: number;
91
176
  };
92
-
93
177
  export type ProgressBoardOptions = {
94
178
  logger: LoggerLike;
95
179
  /** Intervalo de repintura do loader em TTY (ms). */