@tienne/gestalt 0.84.2 → 0.86.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.
- package/CLAUDE.md +4 -4
- package/README.ko.md +72 -22
- package/README.md +73 -23
- package/dist/benchmarks/runners/passthrough-benchmark-runner.d.ts.map +1 -1
- package/dist/benchmarks/runners/passthrough-benchmark-runner.js +8 -7
- package/dist/benchmarks/runners/passthrough-benchmark-runner.js.map +1 -1
- package/dist/bin/gestalt.js +2 -2
- package/dist/package.json +4 -3
- package/dist/plugin/review-agents/harness-reviewer/AGENT.md +21 -1
- package/dist/plugin/skills/dispatch/SKILL.md +14 -2
- package/dist/plugin/skills/execute/SKILL.md +219 -52
- package/dist/plugin/skills/interview/SKILL.md +15 -2
- package/dist/plugin/skills/solve/SKILL.md +20 -5
- package/dist/plugin/skills/spec/SKILL.md +2 -0
- package/dist/src/cli/commands/interview.d.ts.map +1 -1
- package/dist/src/cli/commands/interview.js +16 -4
- package/dist/src/cli/commands/interview.js.map +1 -1
- package/dist/src/cli/commands/memory-merge.d.ts +2 -0
- package/dist/src/cli/commands/memory-merge.d.ts.map +1 -0
- package/dist/src/cli/commands/memory-merge.js +13 -0
- package/dist/src/cli/commands/memory-merge.js.map +1 -0
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +7 -0
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/core/constants.d.ts +4 -0
- package/dist/src/core/constants.d.ts.map +1 -1
- package/dist/src/core/constants.js +8 -0
- package/dist/src/core/constants.js.map +1 -1
- package/dist/src/core/errors.d.ts +3 -0
- package/dist/src/core/errors.d.ts.map +1 -1
- package/dist/src/core/errors.js +7 -0
- package/dist/src/core/errors.js.map +1 -1
- package/dist/src/core/file-lock.d.ts +37 -0
- package/dist/src/core/file-lock.d.ts.map +1 -0
- package/dist/src/core/file-lock.js +143 -0
- package/dist/src/core/file-lock.js.map +1 -0
- package/dist/src/core/json-file.d.ts +40 -0
- package/dist/src/core/json-file.d.ts.map +1 -0
- package/dist/src/core/json-file.js +82 -0
- package/dist/src/core/json-file.js.map +1 -0
- package/dist/src/core/types.d.ts +86 -9
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/events/store.d.ts +6 -0
- package/dist/src/events/store.d.ts.map +1 -1
- package/dist/src/events/store.js +12 -0
- package/dist/src/events/store.js.map +1 -1
- package/dist/src/events/types.d.ts +7 -0
- package/dist/src/events/types.d.ts.map +1 -1
- package/dist/src/events/types.js +7 -0
- package/dist/src/events/types.js.map +1 -1
- package/dist/src/execute/artifact-verifier.d.ts +12 -0
- package/dist/src/execute/artifact-verifier.d.ts.map +1 -0
- package/dist/src/execute/artifact-verifier.js +211 -0
- package/dist/src/execute/artifact-verifier.js.map +1 -0
- package/dist/src/execute/drift-detector.d.ts +2 -0
- package/dist/src/execute/drift-detector.d.ts.map +1 -1
- package/dist/src/execute/drift-detector.js +9 -13
- package/dist/src/execute/drift-detector.js.map +1 -1
- package/dist/src/execute/orchestrators/evaluation.d.ts +5 -1
- package/dist/src/execute/orchestrators/evaluation.d.ts.map +1 -1
- package/dist/src/execute/orchestrators/evaluation.js +48 -41
- package/dist/src/execute/orchestrators/evaluation.js.map +1 -1
- package/dist/src/execute/orchestrators/evolution.d.ts +17 -3
- package/dist/src/execute/orchestrators/evolution.d.ts.map +1 -1
- package/dist/src/execute/orchestrators/evolution.js +102 -53
- package/dist/src/execute/orchestrators/evolution.js.map +1 -1
- package/dist/src/execute/orchestrators/execution.d.ts +17 -2
- package/dist/src/execute/orchestrators/execution.d.ts.map +1 -1
- package/dist/src/execute/orchestrators/execution.js +99 -3
- package/dist/src/execute/orchestrators/execution.js.map +1 -1
- package/dist/src/execute/orchestrators/planning.d.ts +18 -4
- package/dist/src/execute/orchestrators/planning.d.ts.map +1 -1
- package/dist/src/execute/orchestrators/planning.js +62 -21
- package/dist/src/execute/orchestrators/planning.js.map +1 -1
- package/dist/src/execute/orchestrators/types.d.ts +12 -1
- package/dist/src/execute/orchestrators/types.d.ts.map +1 -1
- package/dist/src/execute/passthrough-engine.d.ts +12 -5
- package/dist/src/execute/passthrough-engine.d.ts.map +1 -1
- package/dist/src/execute/passthrough-engine.js +10 -4
- package/dist/src/execute/passthrough-engine.js.map +1 -1
- package/dist/src/execute/repository.d.ts +11 -1
- package/dist/src/execute/repository.d.ts.map +1 -1
- package/dist/src/execute/repository.js +138 -19
- package/dist/src/execute/repository.js.map +1 -1
- package/dist/src/execute/session.d.ts +26 -4
- package/dist/src/execute/session.d.ts.map +1 -1
- package/dist/src/execute/session.js +165 -48
- package/dist/src/execute/session.js.map +1 -1
- package/dist/src/execute/structural-commands.d.ts +23 -0
- package/dist/src/execute/structural-commands.d.ts.map +1 -0
- package/dist/src/execute/structural-commands.js +139 -0
- package/dist/src/execute/structural-commands.js.map +1 -0
- package/dist/src/harness-review/collect.d.ts +1 -1
- package/dist/src/harness-review/collect.d.ts.map +1 -1
- package/dist/src/harness-review/collect.js +6 -1
- package/dist/src/harness-review/collect.js.map +1 -1
- package/dist/src/harness-review/rule-overlap.d.ts +3 -0
- package/dist/src/harness-review/rule-overlap.d.ts.map +1 -0
- package/dist/src/harness-review/rule-overlap.js +78 -0
- package/dist/src/harness-review/rule-overlap.js.map +1 -0
- package/dist/src/harness-review/types.d.ts +1 -1
- package/dist/src/harness-review/types.d.ts.map +1 -1
- package/dist/src/harness-review/types.js +1 -0
- package/dist/src/harness-review/types.js.map +1 -1
- package/dist/src/humanize/overlap.d.ts +116 -0
- package/dist/src/humanize/overlap.d.ts.map +1 -0
- package/dist/src/humanize/overlap.js +680 -0
- package/dist/src/humanize/overlap.js.map +1 -0
- package/dist/src/interview/engine.d.ts +1 -1
- package/dist/src/interview/engine.d.ts.map +1 -1
- package/dist/src/interview/engine.js +3 -3
- package/dist/src/interview/engine.js.map +1 -1
- package/dist/src/interview/passthrough-engine.d.ts +1 -1
- package/dist/src/interview/passthrough-engine.d.ts.map +1 -1
- package/dist/src/interview/passthrough-engine.js +20 -3
- package/dist/src/interview/passthrough-engine.js.map +1 -1
- package/dist/src/interview/repository.d.ts +8 -0
- package/dist/src/interview/repository.d.ts.map +1 -1
- package/dist/src/interview/repository.js +16 -1
- package/dist/src/interview/repository.js.map +1 -1
- package/dist/src/interview/session.d.ts +15 -2
- package/dist/src/interview/session.d.ts.map +1 -1
- package/dist/src/interview/session.js +67 -23
- package/dist/src/interview/session.js.map +1 -1
- package/dist/src/knowledge-base/embedding.d.ts +6 -1
- package/dist/src/knowledge-base/embedding.d.ts.map +1 -1
- package/dist/src/knowledge-base/embedding.js +19 -6
- package/dist/src/knowledge-base/embedding.js.map +1 -1
- package/dist/src/local-pr/registry.d.ts +1 -21
- package/dist/src/local-pr/registry.d.ts.map +1 -1
- package/dist/src/local-pr/registry.js +7 -113
- package/dist/src/local-pr/registry.js.map +1 -1
- package/dist/src/mcp/input-guard.d.ts +17 -0
- package/dist/src/mcp/input-guard.d.ts.map +1 -1
- package/dist/src/mcp/input-guard.js +1 -1
- package/dist/src/mcp/input-guard.js.map +1 -1
- package/dist/src/mcp/schemas.d.ts +62 -7
- package/dist/src/mcp/schemas.d.ts.map +1 -1
- package/dist/src/mcp/schemas.js +28 -1
- package/dist/src/mcp/schemas.js.map +1 -1
- package/dist/src/mcp/server.d.ts.map +1 -1
- package/dist/src/mcp/server.js +26 -40
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/mcp/tools/execute/evaluate.d.ts.map +1 -1
- package/dist/src/mcp/tools/execute/evaluate.js +15 -9
- package/dist/src/mcp/tools/execute/evaluate.js.map +1 -1
- package/dist/src/mcp/tools/execute/evolve.d.ts +1 -0
- package/dist/src/mcp/tools/execute/evolve.d.ts.map +1 -1
- package/dist/src/mcp/tools/execute/evolve.js +102 -37
- package/dist/src/mcp/tools/execute/evolve.js.map +1 -1
- package/dist/src/mcp/tools/execute/execution.d.ts.map +1 -1
- package/dist/src/mcp/tools/execute/execution.js +66 -7
- package/dist/src/mcp/tools/execute/execution.js.map +1 -1
- package/dist/src/mcp/tools/execute/planning.d.ts.map +1 -1
- package/dist/src/mcp/tools/execute/planning.js +34 -2
- package/dist/src/mcp/tools/execute/planning.js.map +1 -1
- package/dist/src/mcp/tools/execute/roles.d.ts.map +1 -1
- package/dist/src/mcp/tools/execute/roles.js +13 -5
- package/dist/src/mcp/tools/execute/roles.js.map +1 -1
- package/dist/src/mcp/tools/execute/utility.d.ts.map +1 -1
- package/dist/src/mcp/tools/execute/utility.js +26 -0
- package/dist/src/mcp/tools/execute/utility.js.map +1 -1
- package/dist/src/mcp/tools/execute/utils.d.ts +1 -0
- package/dist/src/mcp/tools/execute/utils.d.ts.map +1 -1
- package/dist/src/mcp/tools/execute/utils.js +15 -0
- package/dist/src/mcp/tools/execute/utils.js.map +1 -1
- package/dist/src/mcp/tools/execute-passthrough.d.ts.map +1 -1
- package/dist/src/mcp/tools/execute-passthrough.js +21 -1
- package/dist/src/mcp/tools/execute-passthrough.js.map +1 -1
- package/dist/src/mcp/tools/interview-passthrough.d.ts +2 -1
- package/dist/src/mcp/tools/interview-passthrough.d.ts.map +1 -1
- package/dist/src/mcp/tools/interview-passthrough.js +4 -3
- package/dist/src/mcp/tools/interview-passthrough.js.map +1 -1
- package/dist/src/mcp/tools/interview.d.ts.map +1 -1
- package/dist/src/mcp/tools/interview.js +2 -1
- package/dist/src/mcp/tools/interview.js.map +1 -1
- package/dist/src/mcp/tools/review-passthrough.js +15 -19
- package/dist/src/mcp/tools/review-passthrough.js.map +1 -1
- package/dist/src/mcp/tools/spec-passthrough.d.ts.map +1 -1
- package/dist/src/mcp/tools/spec-passthrough.js +16 -8
- package/dist/src/mcp/tools/spec-passthrough.js.map +1 -1
- package/dist/src/mcp/tools/status.d.ts.map +1 -1
- package/dist/src/mcp/tools/status.js +4 -0
- package/dist/src/mcp/tools/status.js.map +1 -1
- package/dist/src/memory/memory-context-injector.d.ts +22 -8
- package/dist/src/memory/memory-context-injector.d.ts.map +1 -1
- package/dist/src/memory/memory-context-injector.js +85 -13
- package/dist/src/memory/memory-context-injector.js.map +1 -1
- package/dist/src/memory/memory-merge.d.ts +19 -0
- package/dist/src/memory/memory-merge.d.ts.map +1 -0
- package/dist/src/memory/memory-merge.js +120 -0
- package/dist/src/memory/memory-merge.js.map +1 -0
- package/dist/src/memory/project-memory-store.d.ts +15 -11
- package/dist/src/memory/project-memory-store.d.ts.map +1 -1
- package/dist/src/memory/project-memory-store.js +97 -120
- package/dist/src/memory/project-memory-store.js.map +1 -1
- package/dist/src/memory/semantic-search.d.ts +4 -1
- package/dist/src/memory/semantic-search.d.ts.map +1 -1
- package/dist/src/memory/semantic-search.js +66 -19
- package/dist/src/memory/semantic-search.js.map +1 -1
- package/dist/src/resilience/lateral.d.ts +8 -1
- package/dist/src/resilience/lateral.d.ts.map +1 -1
- package/dist/src/resilience/lateral.js +52 -4
- package/dist/src/resilience/lateral.js.map +1 -1
- package/package.json +4 -3
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/.mcp.json +1 -1
- package/plugin/mcp.json +1 -1
- package/plugin/review-agents/harness-reviewer/AGENT.md +21 -1
- package/plugin/skills/dispatch/SKILL.md +14 -2
- package/plugin/skills/execute/SKILL.md +219 -52
- package/plugin/skills/interview/SKILL.md +15 -2
- package/plugin/skills/solve/SKILL.md +20 -5
- package/plugin/skills/spec/SKILL.md +2 -0
- package/dist/src/interview/mini-interview-engine.d.ts +0 -33
- package/dist/src/interview/mini-interview-engine.d.ts.map +0 -1
- package/dist/src/interview/mini-interview-engine.js +0 -102
- package/dist/src/interview/mini-interview-engine.js.map +0 -1
- package/dist/src/memory/user-profile-store.d.ts +0 -13
- package/dist/src/memory/user-profile-store.d.ts.map +0 -1
- package/dist/src/memory/user-profile-store.js +0 -85
- package/dist/src/memory/user-profile-store.js.map +0 -1
|
@@ -25,7 +25,7 @@ outputs:
|
|
|
25
25
|
> `ges_*` 도구가 없거나 호출이 실패하면 직접 흉내내 진행하지 않고 무엇이 왜 안 되는지 말하고 멈춥니다.
|
|
26
26
|
|
|
27
27
|
- **인터뷰**: 사람이 직접 답변 (큰 관점 정리 포함, 자동화하지 않음)
|
|
28
|
-
- **스펙 생성 이후**: AI가 자율로 드라이빙 — 사람 개입 없이 루프를
|
|
28
|
+
- **스펙 생성 이후**: AI가 자율로 드라이빙 — 사람 개입 없이 루프를 돌린다. lateral persona를 다 써서 `awaiting_human`으로 멈췄을 때만 사람에게 묻는다
|
|
29
29
|
|
|
30
30
|
---
|
|
31
31
|
|
|
@@ -84,12 +84,14 @@ Phase 3의 레포 안 탐색까지 앞당기지는 않는다. 그건 실행 대
|
|
|
84
84
|
|
|
85
85
|
→ resolutionScore.isReady === true 또는 overallScore ≥ 0.8이 될 때까지 반복한다.
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
완료 (`isReady === true`일 때만):
|
|
88
88
|
|
|
89
89
|
```json
|
|
90
90
|
{ "action": "complete", "sessionId": "..." }
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
+
0.8 미만이면 서버가 `complete`를 거절한다. 자율 루프라도 `force`는 에이전트가 정하지 않는다. 15라운드를 다 채운 경우에는 마지막 답의 점수가 빠져 있으니 먼저 `score`로 넣고 `isReady`를 확인한다. 그래도 0.8 미만이면 사용자에게 현재 점수를 보여주고 넘어가기로 직접 답했을 때만 `{ "action": "complete", "sessionId": "...", "force": true }`로 부른다. 이렇게 끝낸 세션은 `complete` 응답에 `forced: true`가 온다. 그 값을 근거로 Phase 2에서 `ges_generate_spec`에도 `force: true`를 넘긴다.
|
|
94
|
+
|
|
93
95
|
### 진행 패널
|
|
94
96
|
|
|
95
97
|
세 Phase를 도는 동안 사용자가 어디까지 왔는지 볼 자리를 만든다. 패널은 best-effort다 — 패널을 못 만들거나 못 고쳐도 인터뷰와 스펙과 실행은 그대로 간다.
|
|
@@ -143,7 +145,7 @@ description: "Phase 2/3 — 스펙 완료 | AC {N}개"
|
|
|
143
145
|
|
|
144
146
|
## Phase 3 — Execute 루프 (자율)
|
|
145
147
|
|
|
146
|
-
스펙을 받아 실행 → 평가 → 개선 루프를 자율로 드라이빙한다. **사람 개입 없이 루프를 돈다.**
|
|
148
|
+
스펙을 받아 실행 → 평가 → 개선 루프를 자율로 드라이빙한다. **사람 개입 없이 루프를 돈다.** 예외는 lateral persona를 다 써서 세션이 사람 판단을 기다릴 때 하나다 (→ [사람 판단 대기](#사람-판단-대기-awaiting_human)).
|
|
147
149
|
|
|
148
150
|
execute 스킬의 전체 파이프라인(Planning → Execution → Evaluate → Evolve)을 그대로 따른다. 단, 각 단계 사이에서 사람에게 확인을 구하지 않는다.
|
|
149
151
|
|
|
@@ -168,9 +170,21 @@ activeForm: "{현재 단계: 실행 중 / 평가 중 / 개선 중}"
|
|
|
168
170
|
| 조건 | 대응 |
|
|
169
171
|
|------|------|
|
|
170
172
|
| `success` (score ≥ 0.85, goalAlignment ≥ 0.80) | 루프 종료 → 완료 보고 |
|
|
171
|
-
| `
|
|
173
|
+
| `awaiting_human` (lateral 4개 소진) | 루프를 멈추고 사람에게 묻는다 → `gate_resolve` → `nextAction`대로 이어간다 (아래 참고) |
|
|
174
|
+
| `human_escalation` (사람이 `restart`나 `abort`를 고름) | 루프 종료 → 막힌 지점과 시도한 접근법 보고 |
|
|
172
175
|
| `caller` (사용자가 명시적으로 중단) | 즉시 종료 |
|
|
173
176
|
|
|
177
|
+
### 사람 판단 대기 (`awaiting_human`)
|
|
178
|
+
|
|
179
|
+
lateral persona 4개를 다 써도 점수가 안 오르면 세션은 끝나지 않고 `awaiting_human`으로 멈춘다. 여기는 인터뷰와 같다. **반드시 사람에게 묻고 답을 기다린다.** 스스로 고르지 않는다.
|
|
180
|
+
|
|
181
|
+
1. `gate.question`과 막힌 지점(`gate.context`)을 보여주고 `gate.options`를 선택지로 띄운다.
|
|
182
|
+
2. 고른 선택지와 함께 결정과 이유를 한 줄씩 받는다. 비어 있으면 서버가 거절한다. 대신 채우지 않는다 — 그대로 Memory에 남는 말이다.
|
|
183
|
+
3. `ges_execute { action: "gate_resolve", sessionId, gateResolution: { gateId, optionId, decision, rationale } }`를 부른다.
|
|
184
|
+
4. `patch_spec`이면 `evolve_patch`로, `manual_task`면 사람이 처리한 걸 확인하고 `evaluate`로 루프를 이어간다. `restart`나 `abort`면 세션이 종료되니 루프를 끝내고 아래 에스컬레이션 보고를 한다.
|
|
185
|
+
|
|
186
|
+
자세한 흐름은 execute 스킬의 Flow D와 같다.
|
|
187
|
+
|
|
174
188
|
### 완료 보고
|
|
175
189
|
|
|
176
190
|
루프 종료 시 사람에게 결과를 보고한다:
|
|
@@ -216,7 +230,8 @@ description: "에스컬레이션 | 최고 점수: {bestScore} | {시도한 perso
|
|
|
216
230
|
execute → evaluate → evolve → re-execute → evaluate → ...
|
|
217
231
|
↓
|
|
218
232
|
success → 완료 보고
|
|
219
|
-
|
|
233
|
+
awaiting_human → 사람에게 묻고 gate_resolve → 이어가거나 종료
|
|
234
|
+
human_escalation (restart/abort) → 막힌 지점 보고
|
|
220
235
|
```
|
|
221
236
|
|
|
222
237
|
인터뷰에서 사람과 큰 관점을 충분히 정리한 뒤, 그 이후는 AI가 목표를 향해 스스로 루프를 돈다.
|
|
@@ -41,6 +41,8 @@ This skill transforms completed interview data into a structured project specifi
|
|
|
41
41
|
|
|
42
42
|
- Interview session must be in `completed` status
|
|
43
43
|
- Resolution score must be ≥ 0.8 (unless `force` is true)
|
|
44
|
+
- 0.8 미만 세션은 인터뷰 `complete`에 `force: true`를 넘겨야만 `completed`가 된다. 이때 세션에 `forcedComplete`가 남는다
|
|
45
|
+
- `ges_generate_spec`이 해상도 기준으로 거절하면 `ges_status({ sessionId })`로 `forcedComplete`를 본다. `true`면 사용자가 인터뷰에서 넘어가기로 한 세션이니 `force: true`로 다시 부른다. `false`인데 0.8 미만이면 `force`를 스스로 넘기지 않는다. 현재 점수를 보여주고 사용자에게 묻는다
|
|
44
46
|
|
|
45
47
|
## 규칙 확보 (1단계 호출 전)
|
|
46
48
|
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
export interface MiniInterviewQuestion {
|
|
2
|
-
dimension: string;
|
|
3
|
-
prompt: string;
|
|
4
|
-
rationale: string;
|
|
5
|
-
}
|
|
6
|
-
export interface MiniInterviewContext {
|
|
7
|
-
systemPrompt: string;
|
|
8
|
-
questions: MiniInterviewQuestion[];
|
|
9
|
-
scoringPrompt: string;
|
|
10
|
-
sourceTopic: string;
|
|
11
|
-
message: string;
|
|
12
|
-
}
|
|
13
|
-
export interface ResolutionDimensionScore {
|
|
14
|
-
goalClarity: number;
|
|
15
|
-
constraintClarity: number;
|
|
16
|
-
successCriteria: number;
|
|
17
|
-
priorityClarity: number;
|
|
18
|
-
contextClarity?: number;
|
|
19
|
-
contradictions?: string[];
|
|
20
|
-
}
|
|
21
|
-
export declare class MiniInterviewEngine {
|
|
22
|
-
/**
|
|
23
|
-
* Given an initial ambiguity score from text-based spec generation,
|
|
24
|
-
* determine if a mini-interview is needed and build the clarification context.
|
|
25
|
-
*/
|
|
26
|
-
needsMiniInterview(score: ResolutionDimensionScore): boolean;
|
|
27
|
-
buildClarificationContext(topic: string, text: string, score: ResolutionDimensionScore): MiniInterviewContext;
|
|
28
|
-
buildReScoringContext(topic: string, text: string, answers: Array<{
|
|
29
|
-
question: string;
|
|
30
|
-
answer: string;
|
|
31
|
-
}>): string;
|
|
32
|
-
}
|
|
33
|
-
//# sourceMappingURL=mini-interview-engine.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mini-interview-engine.d.ts","sourceRoot":"","sources":["../../../src/interview/mini-interview-engine.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,qBAAqB,EAAE,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAsFD,qBAAa,mBAAmB;IAC9B;;;OAGG;IACH,kBAAkB,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO;IAK5D,yBAAyB,CACvB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,wBAAwB,GAC9B,oBAAoB;IAgBvB,qBAAqB,CACnB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,GACnD,MAAM;CAGV"}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { RESOLUTION_THRESHOLD } from '../core/constants.js';
|
|
2
|
-
import { INTERVIEW_SYSTEM_PROMPT } from '../llm/prompts.js';
|
|
3
|
-
// ─── Helpers ────────────────────────────────────────────────────
|
|
4
|
-
function getDimensionsNeedingClarification(score) {
|
|
5
|
-
const clarityFloor = 1 - RESOLUTION_THRESHOLD;
|
|
6
|
-
const dims = [];
|
|
7
|
-
if (score.goalClarity < clarityFloor)
|
|
8
|
-
dims.push('goalClarity');
|
|
9
|
-
if (score.constraintClarity < clarityFloor)
|
|
10
|
-
dims.push('constraintClarity');
|
|
11
|
-
if (score.successCriteria < clarityFloor)
|
|
12
|
-
dims.push('successCriteria');
|
|
13
|
-
if (score.priorityClarity < clarityFloor)
|
|
14
|
-
dims.push('priorityClarity');
|
|
15
|
-
if (score.contextClarity !== undefined && score.contextClarity < clarityFloor) {
|
|
16
|
-
dims.push('contextClarity');
|
|
17
|
-
}
|
|
18
|
-
return dims;
|
|
19
|
-
}
|
|
20
|
-
function dimensionToLabel(dim) {
|
|
21
|
-
const labels = {
|
|
22
|
-
goalClarity: 'Project goal and objectives',
|
|
23
|
-
constraintClarity: 'Technical or business constraints',
|
|
24
|
-
successCriteria: 'Measurable success criteria',
|
|
25
|
-
priorityClarity: 'Feature prioritization and MVP scope',
|
|
26
|
-
contextClarity: 'Existing system or project context',
|
|
27
|
-
};
|
|
28
|
-
return labels[dim] ?? dim;
|
|
29
|
-
}
|
|
30
|
-
function buildMiniQuestionPrompt(topic, ambiguousText, dimensions) {
|
|
31
|
-
const dimLabels = dimensions.map((d) => `- ${dimensionToLabel(d)}`).join('\n');
|
|
32
|
-
return `Given this text description:
|
|
33
|
-
---
|
|
34
|
-
${ambiguousText}
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
Topic: "${topic}"
|
|
38
|
-
|
|
39
|
-
The following dimensions still need clarification:
|
|
40
|
-
${dimLabels}
|
|
41
|
-
|
|
42
|
-
Generate ONE targeted question per dimension to resolve the remaining ambiguity.
|
|
43
|
-
Respond with ONLY a JSON array:
|
|
44
|
-
[
|
|
45
|
-
{
|
|
46
|
-
"dimension": "goalClarity|constraintClarity|successCriteria|priorityClarity|contextClarity",
|
|
47
|
-
"prompt": "Your clarifying question here",
|
|
48
|
-
"rationale": "Why this question resolves the ambiguity"
|
|
49
|
-
}
|
|
50
|
-
]`;
|
|
51
|
-
}
|
|
52
|
-
function buildMiniScoringPrompt(topic, originalText, answers) {
|
|
53
|
-
const qa = answers.map((a, i) => `Q${i + 1}: ${a.question}\nA${i + 1}: ${a.answer}`).join('\n\n');
|
|
54
|
-
return `Re-score the ambiguity of this project description after the follow-up Q&A.
|
|
55
|
-
|
|
56
|
-
Original description: "${originalText}"
|
|
57
|
-
Topic: "${topic}"
|
|
58
|
-
|
|
59
|
-
Follow-up Q&A:
|
|
60
|
-
${qa}
|
|
61
|
-
|
|
62
|
-
Score each dimension from 0.0 (completely ambiguous) to 1.0 (crystal clear).
|
|
63
|
-
|
|
64
|
-
Respond with ONLY a JSON object:
|
|
65
|
-
{
|
|
66
|
-
"goalClarity": 0.0-1.0,
|
|
67
|
-
"constraintClarity": 0.0-1.0,
|
|
68
|
-
"successCriteria": 0.0-1.0,
|
|
69
|
-
"priorityClarity": 0.0-1.0,
|
|
70
|
-
"contradictions": [],
|
|
71
|
-
"reasoning": "Brief analysis"
|
|
72
|
-
}`;
|
|
73
|
-
}
|
|
74
|
-
// ─── Engine ─────────────────────────────────────────────────────
|
|
75
|
-
export class MiniInterviewEngine {
|
|
76
|
-
/**
|
|
77
|
-
* Given an initial ambiguity score from text-based spec generation,
|
|
78
|
-
* determine if a mini-interview is needed and build the clarification context.
|
|
79
|
-
*/
|
|
80
|
-
needsMiniInterview(score) {
|
|
81
|
-
const dims = getDimensionsNeedingClarification(score);
|
|
82
|
-
return dims.length > 0;
|
|
83
|
-
}
|
|
84
|
-
buildClarificationContext(topic, text, score) {
|
|
85
|
-
const dims = getDimensionsNeedingClarification(score);
|
|
86
|
-
return {
|
|
87
|
-
systemPrompt: INTERVIEW_SYSTEM_PROMPT,
|
|
88
|
-
questions: dims.map((d) => ({
|
|
89
|
-
dimension: d,
|
|
90
|
-
prompt: '', // Caller LLM fills this in using the clarification prompt
|
|
91
|
-
rationale: '',
|
|
92
|
-
})),
|
|
93
|
-
scoringPrompt: buildMiniQuestionPrompt(topic, text, dims),
|
|
94
|
-
sourceTopic: topic,
|
|
95
|
-
message: `${dims.length} dimension(s) need clarification: ${dims.map(dimensionToLabel).join(', ')}. Use the scoringPrompt to generate clarifying questions.`,
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
buildReScoringContext(topic, text, answers) {
|
|
99
|
-
return buildMiniScoringPrompt(topic, text, answers);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
//# sourceMappingURL=mini-interview-engine.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mini-interview-engine.js","sourceRoot":"","sources":["../../../src/interview/mini-interview-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { UserProfile } from '../core/types.js';
|
|
2
|
-
export declare class UserProfileStore {
|
|
3
|
-
private profilePath;
|
|
4
|
-
constructor(profilePath?: string);
|
|
5
|
-
read(): UserProfile;
|
|
6
|
-
private write;
|
|
7
|
-
setPreference(key: string, value: unknown): UserProfile;
|
|
8
|
-
addCrossRepoPattern(pattern: string): UserProfile;
|
|
9
|
-
setPreferredModel(model: string): UserProfile;
|
|
10
|
-
setUserId(userId: string): UserProfile;
|
|
11
|
-
merge(partial: Partial<UserProfile>): UserProfile;
|
|
12
|
-
}
|
|
13
|
-
//# sourceMappingURL=user-profile-store.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"user-profile-store.d.ts","sourceRoot":"","sources":["../../../src/memory/user-profile-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAkBpD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,WAAW,CAAS;gBAEhB,WAAW,CAAC,EAAE,MAAM;IAIhC,IAAI,IAAI,WAAW;IAYnB,OAAO,CAAC,KAAK;IASb,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,WAAW;IAOvD,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW;IASjD,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW;IAO7C,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW;IAOtC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW;CAgBlD"}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { dirname } from 'node:path';
|
|
3
|
-
import { gestaltPath } from '../core/home.js';
|
|
4
|
-
const PROFILE_FILENAME = 'profile.json';
|
|
5
|
-
function getProfilePath() {
|
|
6
|
-
return gestaltPath(PROFILE_FILENAME);
|
|
7
|
-
}
|
|
8
|
-
function createEmptyProfile() {
|
|
9
|
-
const now = new Date().toISOString();
|
|
10
|
-
return {
|
|
11
|
-
crossRepoPatterns: [],
|
|
12
|
-
personalPreferences: {},
|
|
13
|
-
createdAt: now,
|
|
14
|
-
updatedAt: now,
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
export class UserProfileStore {
|
|
18
|
-
profilePath;
|
|
19
|
-
constructor(profilePath) {
|
|
20
|
-
this.profilePath = profilePath ?? getProfilePath();
|
|
21
|
-
}
|
|
22
|
-
read() {
|
|
23
|
-
if (!existsSync(this.profilePath)) {
|
|
24
|
-
return createEmptyProfile();
|
|
25
|
-
}
|
|
26
|
-
try {
|
|
27
|
-
const raw = readFileSync(this.profilePath, 'utf-8');
|
|
28
|
-
return JSON.parse(raw);
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
return createEmptyProfile();
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
write(profile) {
|
|
35
|
-
const dir = dirname(this.profilePath);
|
|
36
|
-
if (!existsSync(dir)) {
|
|
37
|
-
mkdirSync(dir, { recursive: true });
|
|
38
|
-
}
|
|
39
|
-
profile.updatedAt = new Date().toISOString();
|
|
40
|
-
writeFileSync(this.profilePath, JSON.stringify(profile, null, 2), 'utf-8');
|
|
41
|
-
}
|
|
42
|
-
setPreference(key, value) {
|
|
43
|
-
const profile = this.read();
|
|
44
|
-
profile.personalPreferences[key] = value;
|
|
45
|
-
this.write(profile);
|
|
46
|
-
return profile;
|
|
47
|
-
}
|
|
48
|
-
addCrossRepoPattern(pattern) {
|
|
49
|
-
const profile = this.read();
|
|
50
|
-
if (!profile.crossRepoPatterns.includes(pattern)) {
|
|
51
|
-
profile.crossRepoPatterns.push(pattern);
|
|
52
|
-
}
|
|
53
|
-
this.write(profile);
|
|
54
|
-
return profile;
|
|
55
|
-
}
|
|
56
|
-
setPreferredModel(model) {
|
|
57
|
-
const profile = this.read();
|
|
58
|
-
profile.preferredModel = model;
|
|
59
|
-
this.write(profile);
|
|
60
|
-
return profile;
|
|
61
|
-
}
|
|
62
|
-
setUserId(userId) {
|
|
63
|
-
const profile = this.read();
|
|
64
|
-
profile.userId = userId;
|
|
65
|
-
this.write(profile);
|
|
66
|
-
return profile;
|
|
67
|
-
}
|
|
68
|
-
merge(partial) {
|
|
69
|
-
const profile = this.read();
|
|
70
|
-
const merged = {
|
|
71
|
-
...profile,
|
|
72
|
-
...partial,
|
|
73
|
-
crossRepoPatterns: [
|
|
74
|
-
...new Set([...profile.crossRepoPatterns, ...(partial.crossRepoPatterns ?? [])]),
|
|
75
|
-
],
|
|
76
|
-
personalPreferences: {
|
|
77
|
-
...profile.personalPreferences,
|
|
78
|
-
...(partial.personalPreferences ?? {}),
|
|
79
|
-
},
|
|
80
|
-
};
|
|
81
|
-
this.write(merged);
|
|
82
|
-
return merged;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
//# sourceMappingURL=user-profile-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"user-profile-store.js","sourceRoot":"","sources":["../../../src/memory/user-profile-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAExC,SAAS,cAAc;IACrB,OAAO,WAAW,CAAC,gBAAgB,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,kBAAkB;IACzB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO;QACL,iBAAiB,EAAE,EAAE;QACrB,mBAAmB,EAAE,EAAE;QACvB,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,GAAG;KACf,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,gBAAgB;IACnB,WAAW,CAAS;IAE5B,YAAY,WAAoB;QAC9B,IAAI,CAAC,WAAW,GAAG,WAAW,IAAI,cAAc,EAAE,CAAC;IACrD,CAAC;IAED,IAAI;QACF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAClC,OAAO,kBAAkB,EAAE,CAAC;QAC9B,CAAC;QACD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACpD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAC;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,kBAAkB,EAAE,CAAC;QAC9B,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,OAAoB;QAChC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACtC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC7C,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC7E,CAAC;IAED,aAAa,CAAC,GAAW,EAAE,KAAc;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,OAAO,CAAC,mBAAmB,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACzC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,mBAAmB,CAAC,OAAe;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACjD,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1C,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,iBAAiB,CAAC,KAAa;QAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,OAAO,CAAC,cAAc,GAAG,KAAK,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,SAAS,CAAC,MAAc;QACtB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,OAA6B;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAgB;YAC1B,GAAG,OAAO;YACV,GAAG,OAAO;YACV,iBAAiB,EAAE;gBACjB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,OAAO,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,CAAC;aACjF;YACD,mBAAmB,EAAE;gBACnB,GAAG,OAAO,CAAC,mBAAmB;gBAC9B,GAAG,CAAC,OAAO,CAAC,mBAAmB,IAAI,EAAE,CAAC;aACvC;SACF,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACnB,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
|