@tienne/gestalt 0.84.1 → 0.85.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 +1 -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/review/SKILL.md +29 -5
- 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/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 +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/.mcp.json +1 -1
- package/plugin/mcp.json +1 -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/review/SKILL.md +29 -5
- 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
|
@@ -119,7 +119,7 @@ Orca 런타임이 붙지 않아 워커 디스패치는 못 합니다.
|
|
|
119
119
|
- 게슈탈트 실행 세션 ID(UUID 원문 — 워커는 다른 프로세스라 `active`가 다르게 해석될 수 있다)
|
|
120
120
|
- 이 워커가 맡은 게슈탈트 taskId
|
|
121
121
|
- `taskContext.taskPrompt` 내용
|
|
122
|
-
- 완료 후 `ges_execute action=execute_task`로 결과를 제출하라는
|
|
122
|
+
- 완료 후 `ges_execute action=execute_task`로 결과를 제출하라는 지시. 바꾼 파일은 전부 `artifacts`에 적고 파일을 안 바꾸는 태스크면 `noCodeChange: true`를 같이 낸다. `verification_failed`가 오면 고쳐서 다시 제출하고 끝내지 못했으면 `status: "failed"`로 낸다. `serverError: true`가 함께 오면 고치지 말고 잠시 뒤 같은 결과를 다시 내고 계속 실패하면 `status: "failed"`로 낸다
|
|
123
123
|
- **다른 태스크는 건드리지 말라는 경계** — 워커가 ready 집합을 보고 남의 태스크까지 하려 들면 충돌한다
|
|
124
124
|
|
|
125
125
|
동시 워커 수는 `maxConcurrent`로 제한한다. 지정이 없으면 ready 집합 크기와 4 중 작은 값을 쓴다. 워커마다 에이전트 프로세스와 게슈탈트 MCP 서버가 하나씩 뜨므로 무제한으로 띄우지 않는다.
|
|
@@ -149,7 +149,7 @@ Orca 런타임이 붙지 않아 워커 디스패치는 못 합니다.
|
|
|
149
149
|
|
|
150
150
|
## 6단계: 막힌 것은 사람에게 올린다
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
lateral persona를 다 써서 게슈탈트 세션이 `awaiting_human`으로 멈췄으면 그 사실을 `orchestration gate-create`로 올려 사람 눈에 보이게 한다. evolve 응답의 `status: 'awaiting_human'`으로 알 수 있다. `status` 조회에 `openGate`가 실려 있어도 같은 뜻이다. 질문에는 `gate.question`과 `gate.options`의 `id`, `label`을 그대로 옮긴다.
|
|
153
153
|
|
|
154
154
|
```bash
|
|
155
155
|
<실행파일> orchestration gate-create --task <task_id> --question "<막힌 지점과 필요한 판단>" --json
|
|
@@ -158,6 +158,18 @@ Orca 런타임이 붙지 않아 워커 디스패치는 못 합니다.
|
|
|
158
158
|
|
|
159
159
|
카드 코멘트를 남기면 터미널을 열지 않고도 `worktree ps`나 모바일에서 상태가 보인다. 의미 있는 체크포인트마다 코멘트를 갱신한다.
|
|
160
160
|
|
|
161
|
+
Orca 쪽에서 사람이 답해 해소되면(`gate-resolve`) 그 답을 게슈탈트에 넘겨야 세션이 움직인다. Orca 쪽 해소만으로는 게슈탈트 세션이 `awaiting_human`에 그대로 남는다. 그동안 `ges_execute`는 `status`, `resume`, `gate_resolve`, `evolution_viz` 말고는 다 거절한다.
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
{
|
|
165
|
+
"action": "gate_resolve",
|
|
166
|
+
"sessionId": "<UUID>",
|
|
167
|
+
"gateResolution": { "gateId": "<gate.gateId>", "optionId": "<사람이 고른 id>", "decision": "<사람의 결정>", "rationale": "<그 이유>" }
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
`decision`과 `rationale`은 사람이 적은 말을 쓴다. 비어 있으면 서버가 거절한다. 코디네이터가 지어 채우면 지어낸 판단이 Memory에 남는다. 응답의 `nextAction`이 `evolve_patch`나 `evaluate`면 execute 스킬로 돌려보낸다. `terminated`가 오면(`restart`, `abort`) 세션이 종료된 것이니 디스패치를 멈춘다.
|
|
172
|
+
|
|
161
173
|
## Do-NOT
|
|
162
174
|
|
|
163
175
|
- **execute 스킬을 대체하지 않는다.** 계획 수립(Planning), 평가(Evaluate), 개선(Evolve)은 execute가 한다. 이 스킬은 Phase 2 실행을 다른 백엔드로 돌리는 것뿐이다.
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: execute
|
|
3
|
-
version:
|
|
4
|
-
description:
|
|
3
|
+
version: '1.3.0'
|
|
4
|
+
description: 'Gestalt-driven execution planner that transforms a Spec into a validated ExecutionPlan. Requires a Spec that already exists. Given only a problem statement, use solve instead — it drives interview → spec → execute as one loop.'
|
|
5
5
|
triggers:
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
6
|
+
- 'execute'
|
|
7
|
+
- 'plan execution'
|
|
8
|
+
- 'create execution plan'
|
|
9
9
|
inputs:
|
|
10
10
|
spec:
|
|
11
11
|
type: object
|
|
12
12
|
required: true
|
|
13
|
-
description:
|
|
13
|
+
description: 'A validated Spec specification from the spec generation step'
|
|
14
14
|
outputs:
|
|
15
15
|
- executionPlan
|
|
16
16
|
---
|
|
@@ -61,6 +61,7 @@ Success condition: `score ≥ 0.85` AND `goalAlignment ≥ 0.80`
|
|
|
61
61
|
- **Flow A — Structural Fix**: fix lint/build/test failures → re-evaluate
|
|
62
62
|
- **Flow B — Contextual Evolution**: patch Spec ACs/constraints → re-execute impacted tasks → re-evaluate
|
|
63
63
|
- **Flow C — Lateral Thinking**: when stagnation detected, rotate through Multistability / Simplicity / Reification / Invariance personas
|
|
64
|
+
- **Flow D — Human Decision**: when all four personas are exhausted, the session pauses as `awaiting_human` — ask the human, then `gate_resolve` and follow `nextAction`
|
|
64
65
|
|
|
65
66
|
## Phase 0 — 규칙 확보 (필수 — 스킵 불가)
|
|
66
67
|
|
|
@@ -109,16 +110,15 @@ ges_status() → {
|
|
|
109
110
|
|
|
110
111
|
**`ruleSourceErrors`가 비어 있지 않으면 멈춘다.** 판정과 사용자에게 알릴 문구는 [`../_shared/rule-sources.md`](../_shared/rule-sources.md)의 "선언이 깨졌을 때" 절이 원본이다. **`ruleSources`가 비어 있지 않아도 일부가 빠진 상태일 수 있으니 배열 길이로 판정하지 않는다.**
|
|
111
112
|
|
|
112
|
-
|
|
113
113
|
`scope`가 비어 있지 않으면 **이번 Spec에 해당하는 소스만** 읽는다. 백엔드 태스크만 있는 Spec에서 디자인 토큰을 물어볼 이유가 없다. 여기는 건드릴 파일이 정해진 자리라 태그를 그 파일에서 뽑는다.
|
|
114
114
|
|
|
115
115
|
**`solve`로 들어와 소스 읽기를 건너뛰는 경우에도 이 판정은 한다.** 건너뛰는 건 읽기지 판정이 아니다. 앞 스킬은 파일을 모른 채 넘겼으므로 여기서 세 가지가 정해진다.
|
|
116
116
|
|
|
117
|
-
| 앞에서 넘어온 것
|
|
118
|
-
|
|
117
|
+
| 앞에서 넘어온 것 | 여기서 |
|
|
118
|
+
| -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
119
119
|
| 넓게 잡아 읽어둔 `convention` 소스 중 파일을 보니 안 걸리는 것 | `repoRules.sources`에서 뺀다. 거기서 빠지면 서브에이전트 프롬프트와 완료 보고 양쪽에서 함께 빠진다 |
|
|
120
|
-
| 판정을 미뤄둔 `stop`과 `delegate` 소스
|
|
121
|
-
| 새로 걸리는 소스
|
|
120
|
+
| 판정을 미뤄둔 `stop`과 `delegate` 소스 | 여기서 판정한다. 걸리면 읽거나 멈추거나 넘긴다 |
|
|
121
|
+
| 새로 걸리는 소스 | 그것만 더 읽는다 |
|
|
122
122
|
|
|
123
123
|
`trust: "delegate"`인 소스가 이번 작업 범위에 걸리면 그 부분은 게슈탈트가 직접 만들지 않고 넘긴다. 어디까지 넘기는지 사용자에게 알리고 진행한다.
|
|
124
124
|
|
|
@@ -145,41 +145,52 @@ API 키 없이 MCP 서버 실행 시 자동 활성화. LLM 작업을 caller가
|
|
|
145
145
|
### Action별 사용법
|
|
146
146
|
|
|
147
147
|
**`start`** — 실행 계획 세션 시작
|
|
148
|
+
|
|
148
149
|
```json
|
|
149
150
|
{ "action": "start", "spec": { ... } }
|
|
150
151
|
```
|
|
152
|
+
|
|
151
153
|
→ `{ status, sessionId, specId, executeContext, message }`
|
|
152
154
|
|
|
153
155
|
**`plan_step`** — 각 계획 단계 결과 제출
|
|
156
|
+
|
|
154
157
|
```json
|
|
155
158
|
{ "action": "plan_step", "sessionId": "...", "stepResult": { "principle": "figure_ground", "classifiedACs": [...] } }
|
|
156
159
|
```
|
|
160
|
+
|
|
157
161
|
→ `{ status, sessionId, stepsCompleted, isLastStep, executeContext?, message }`
|
|
158
162
|
|
|
163
|
+
continuity에서 DAG가 무효면 `error`가 함께 실린 `status: "plan_rewound"` 응답이 온다. [DAG가 무효일 때](#dag가-무효일-때--closure로-되감기)를 본다.
|
|
164
|
+
|
|
159
165
|
**`plan_complete`** — 최종 실행 계획 조립
|
|
166
|
+
|
|
160
167
|
```json
|
|
161
168
|
{ "action": "plan_complete", "sessionId": "..." }
|
|
162
169
|
```
|
|
170
|
+
|
|
163
171
|
→ `{ status, sessionId, executionPlan, message }`
|
|
164
172
|
|
|
173
|
+
저장된 계획의 DAG가 무효면 확정하지 않고 같은 `plan_rewound` 응답을 돌려준다.
|
|
174
|
+
|
|
165
175
|
**`status`** — 세션 상태 확인
|
|
176
|
+
|
|
166
177
|
```json
|
|
167
178
|
{ "action": "status", "sessionId": "..." }
|
|
168
179
|
```
|
|
169
180
|
|
|
170
181
|
### ExecuteContext 필드
|
|
171
182
|
|
|
172
|
-
| 필드
|
|
173
|
-
|
|
174
|
-
| `systemPrompt`
|
|
175
|
-
| `planningPrompt`
|
|
176
|
-
| `
|
|
177
|
-
| `principleStrategy` | string | 해당 원리의 전략 설명
|
|
178
|
-
| `phase`
|
|
179
|
-
| `stepNumber`
|
|
180
|
-
| `totalSteps`
|
|
181
|
-
| `spec`
|
|
182
|
-
| `previousSteps`
|
|
183
|
+
| 필드 | 타입 | 설명 |
|
|
184
|
+
| ------------------- | ------ | ----------------------------------------------------------------------------------------------- |
|
|
185
|
+
| `systemPrompt` | string | 실행 계획 시스템 프롬프트 |
|
|
186
|
+
| `planningPrompt` | string | 현재 단계의 계획 프롬프트 |
|
|
187
|
+
| `currentStage` | string | 현재 단계를 풀어 쓴 문구 (예: `빠진 요구사항 채우기`). 서버 내부의 원리 이름 대신 응답에 실린다 |
|
|
188
|
+
| `principleStrategy` | string | 해당 원리의 전략 설명 |
|
|
189
|
+
| `phase` | string | 현재 단계 (`planning`) |
|
|
190
|
+
| `stepNumber` | number | 현재 스텝 번호 (1-4) |
|
|
191
|
+
| `totalSteps` | number | 전체 스텝 수 (4) |
|
|
192
|
+
| `spec` | Spec | 원본 Spec 스펙 |
|
|
193
|
+
| `previousSteps` | array | 이전 단계 결과들 |
|
|
183
194
|
|
|
184
195
|
### Planning Principle 순서
|
|
185
196
|
|
|
@@ -195,6 +206,31 @@ API 키 없이 MCP 서버 실행 시 자동 활성화. LLM 작업을 caller가
|
|
|
195
206
|
- Continuity 단계에서는 서버 측 DAG 검증이 추가로 수행됨
|
|
196
207
|
- 모든 AC가 분류되어야 하고 모든 Task가 그룹에 포함되어야 함
|
|
197
208
|
|
|
209
|
+
### DAG가 무효일 때 — closure로 되감기
|
|
210
|
+
|
|
211
|
+
순환은 closure 단계 `atomicTasks`의 `dependsOn`에서 생긴다. continuity만 다시 내서는 못 고친다. 그래서 `dagValidation.isValid: false`를 보고하거나 서버가 순환이나 충돌을 찾으면 `plan_step`(continuity)과 `plan_complete` 둘 다 계획을 확정하지 않는다. 대신 세션을 figure_ground까지만 남기고 되감은 뒤 이렇게 돌려준다.
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"error": "Dependency DAG is invalid (...)",
|
|
216
|
+
"status": "plan_rewound",
|
|
217
|
+
"sessionId": "...",
|
|
218
|
+
"rewoundToStep": 2,
|
|
219
|
+
"hasCycles": true,
|
|
220
|
+
"cycleDetails": ["Cycle detected involving tasks: task-0 → task-1"],
|
|
221
|
+
"conflictDetails": [],
|
|
222
|
+
"executeContext": { "currentStage": "빠진 요구사항 채우기", "stepNumber": 2, "...": "..." },
|
|
223
|
+
"nextAction": "plan_step"
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
- `cycleDetails`와 `conflictDetails`를 보고 문제가 된 태스크의 `dependsOn`을 고친다.
|
|
228
|
+
- 응답의 `executeContext`로 closure부터 다시 낸다. 그다음 proximity와 continuity를 차례로 다시 제출한다.
|
|
229
|
+
- `isValid: false`를 그대로 두고 continuity만 다시 내면 또 되감긴다. 호출자 보고가 무효여도 막는다.
|
|
230
|
+
- 이 응답에는 `error` 필드가 함께 실린다. `plan_complete`나 `execute_start`로 넘어가지 않는다.
|
|
231
|
+
- 되감은 뒤의 closure 프롬프트에는 순환 정보도 직전 `atomicTasks`도 없다. 서브에이전트로 다시 낼 때는 응답의 `cycleDetails`와 `conflictDetails`, 직전에 제출한 `atomicTasks`를 함께 넘기고 순환을 만든 `dependsOn`을 고치라고 적는다.
|
|
232
|
+
- 같은 세션에서 `plan_rewound`를 연속 두 번 받으면 closure를 다시 제출하지 않는다. `cycleDetails`를 사용자에게 보여주고 어떻게 할지 묻는다. 서버는 횟수를 세지 않으므로 스킬이 센다.
|
|
233
|
+
|
|
198
234
|
### Reasoning Model 서브에이전트로 플래닝 추론
|
|
199
235
|
|
|
200
236
|
Phase 1 플래닝(`plan_step` 4단계 + `plan_complete`)은 Spec을 태스크 DAG로 분해하는 깊은 one-shot 추론이라, 게슈탈트에서 상위 추론 모델이 진짜 값을 하는 지점이다. 각 `plan_step`의 `stepResult`(classifiedACs / atomicTasks / taskGroups / dagValidation)를 만드는 추론은 현재 세션이 직접 하지 말고 별도 Agent 서브에이전트로 스폰한다.
|
|
@@ -207,7 +243,7 @@ Phase 1 플래닝(`plan_step` 4단계 + `plan_complete`)은 Spec을 태스크 DA
|
|
|
207
243
|
ges_status() → { reasoningModel: "fable", reasoningModelFallback: "opus", ... }
|
|
208
244
|
```
|
|
209
245
|
|
|
210
|
-
**스폰.** 각 `plan_step`(그리고 `plan_complete` 조립을 위한 추론이 필요하면 그 단계)에서 Agent 도구로 서브에이전트를 띄우되 `model` 파라미터에 `reasoningModel` 값을 넘긴다. 서브에이전트에는 해당 단계의 `executeContext`(`systemPrompt`, `planningPrompt`, `
|
|
246
|
+
**스폰.** 각 `plan_step`(그리고 `plan_complete` 조립을 위한 추론이 필요하면 그 단계)에서 Agent 도구로 서브에이전트를 띄우되 `model` 파라미터에 `reasoningModel` 값을 넘긴다. 서브에이전트에는 해당 단계의 `executeContext`(`systemPrompt`, `planningPrompt`, `currentStage`, `spec`, `previousSteps`)를 전달하고 그 단계의 `stepResult`를 산출하게 한다. 결과를 `plan_step`으로 제출한다.
|
|
211
247
|
|
|
212
248
|
**폴백은 스킬 런타임에서 발동한다.** 서버는 폴백 대상(`reasoningModelFallback`)만 알려줄 뿐, 모델 가용성을 감지하거나 재시도하지 않는다. Agent 도구가 `reasoningModel`(예: `fable`)을 지원하지 않아 스폰이 거부/실패하면, 그때 스킬이 직접 `model`을 `reasoningModelFallback`(예: `opus`)로 바꿔 1회 재시도한다. 폴백 판단과 재시도는 전적으로 이 스킬 런타임의 책임이다.
|
|
213
249
|
|
|
@@ -220,9 +256,18 @@ ges_status() → { reasoningModel: "fable", reasoningModelFallback: "opus", ..
|
|
|
220
256
|
`plan_complete` 이후 호출. 태스크 목록을 받아 실행 준비.
|
|
221
257
|
|
|
222
258
|
```json
|
|
223
|
-
{ "action": "execute_start", "sessionId": "..." }
|
|
259
|
+
{ "action": "execute_start", "sessionId": "...", "cwd": "/path/to/project" }
|
|
224
260
|
```
|
|
225
|
-
|
|
261
|
+
|
|
262
|
+
→ `{ status, sessionId, executionPlan, artifactCheck, message }`
|
|
263
|
+
|
|
264
|
+
`cwd`에는 프로젝트 루트를 넘긴다. 서버가 이 디렉토리에서 git 작업 트리가 실행 시작 시점에 어떤 상태였는지 잡아 두고 나중에 `completed` 보고의 `artifacts`를 그 상태와 대조한다. `cwd`를 비우면 세션의 `codeGraphRepoRoot`를 쓰고 그것도 없으면 서버 프로세스의 cwd를 쓴다. git 레포가 아니면 대조 없이 진행한다. 대조 중에는 그 레포의 `filter.*.clean` 설정이 실행되므로 믿지 않는 레포를 `cwd`로 넘기지 않는다.
|
|
265
|
+
|
|
266
|
+
응답에는 `artifactCheck: { repoRoot, baseline, error? }`가 붙는다. `repoRoot`는 실제로 대조에 쓸 디렉토리다. `baseline`은 아래 셋 중 하나다. `execute_task` 응답의 `artifactCheck`는 `verified` 같은 문자열 하나라 꼴이 다르다.
|
|
267
|
+
|
|
268
|
+
- `captured`: 시작 시점 상태를 잡았다. 이후 `completed` 보고를 대조한다
|
|
269
|
+
- `no_baseline`: git 레포가 아니라 대조하지 않는다
|
|
270
|
+
- `baseline_failed`: git 호출이 실패해 대조하지 않는다. 실패 내용은 `error`에 담긴다
|
|
226
271
|
|
|
227
272
|
---
|
|
228
273
|
|
|
@@ -236,6 +281,7 @@ ges_status() → { reasoningModel: "fable", reasoningModelFallback: "opus", ..
|
|
|
236
281
|
// Call 1: 매칭 컨텍스트 요청
|
|
237
282
|
{ "action": "role_match", "sessionId": "..." }
|
|
238
283
|
```
|
|
284
|
+
|
|
239
285
|
→ `{ matchContext }` — 어떤 에이전트가 적합한지 판단하기 위한 프롬프트
|
|
240
286
|
|
|
241
287
|
`matchContext.tierHint`는 `"frugal"`이다. `matchContext.availableAgents`에는 에이전트 20여 개의 description이 통째로 들어 있다. 그걸 세션 컨텍스트에 들이는 대신 **서브에이전트에 넘겨 1차 후보를 좁힌다.**
|
|
@@ -259,11 +305,22 @@ Agent {
|
|
|
259
305
|
"action": "role_match",
|
|
260
306
|
"sessionId": "...",
|
|
261
307
|
"matchResult": [
|
|
262
|
-
{
|
|
263
|
-
|
|
308
|
+
{
|
|
309
|
+
"agentName": "technical-writer",
|
|
310
|
+
"domain": ["documentation"],
|
|
311
|
+
"relevanceScore": 0.9,
|
|
312
|
+
"reasoning": "..."
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
"agentName": "architect",
|
|
316
|
+
"domain": ["architecture"],
|
|
317
|
+
"relevanceScore": 0.7,
|
|
318
|
+
"reasoning": "..."
|
|
319
|
+
}
|
|
264
320
|
]
|
|
265
321
|
}
|
|
266
322
|
```
|
|
323
|
+
|
|
267
324
|
→ `{ perspectivePrompts }` — 각 에이전트별 관점 생성 프롬프트
|
|
268
325
|
|
|
269
326
|
**`role_consensus` — 다중 관점 합의 (2-Call)**
|
|
@@ -279,6 +336,7 @@ Agent {
|
|
|
279
336
|
]
|
|
280
337
|
}
|
|
281
338
|
```
|
|
339
|
+
|
|
282
340
|
→ `{ synthesisContext }` — 관점 통합 프롬프트
|
|
283
341
|
|
|
284
342
|
```json
|
|
@@ -293,6 +351,7 @@ Agent {
|
|
|
293
351
|
}
|
|
294
352
|
}
|
|
295
353
|
```
|
|
354
|
+
|
|
296
355
|
→ `{ roleGuidance }` — execute_task 시 참조할 최종 guidance
|
|
297
356
|
|
|
298
357
|
---
|
|
@@ -320,13 +379,13 @@ Agent {
|
|
|
320
379
|
|
|
321
380
|
```
|
|
322
381
|
// 같은 메시지에서 동시 호출 — Agent 1
|
|
323
|
-
Agent(task: "task-0 실행: {task-0 title}\n컨텍스트: {taskContext}\n완료 후 execute_task로 결과
|
|
382
|
+
Agent(task: "task-0 실행: {task-0 title}\n컨텍스트: {taskContext}\n완료 후 execute_task로 결과 제출. 바꾼 파일은 전부 artifacts에 적는다. 파일을 안 바꾸는 태스크면 noCodeChange: true를 같이 낸다. verification_failed가 오면 고쳐서 다시 제출하고 끝내지 못했으면 status: \"failed\"로 낸다. serverError: true가 함께 오면 고치지 말고 잠시 뒤 같은 결과를 다시 내고 계속 실패하면 status: \"failed\"로 낸다")
|
|
324
383
|
|
|
325
384
|
// 같은 메시지에서 동시 호출 — Agent 2
|
|
326
|
-
Agent(task: "task-1 실행: {task-1 title}\n컨텍스트: {taskContext}\n완료 후 execute_task로 결과
|
|
385
|
+
Agent(task: "task-1 실행: {task-1 title}\n컨텍스트: {taskContext}\n완료 후 execute_task로 결과 제출. 바꾼 파일은 전부 artifacts에 적는다. 파일을 안 바꾸는 태스크면 noCodeChange: true를 같이 낸다. verification_failed가 오면 고쳐서 다시 제출하고 끝내지 못했으면 status: \"failed\"로 낸다. serverError: true가 함께 오면 고치지 말고 잠시 뒤 같은 결과를 다시 내고 계속 실패하면 status: \"failed\"로 낸다")
|
|
327
386
|
|
|
328
387
|
// 같은 메시지에서 동시 호출 — Agent 3
|
|
329
|
-
Agent(task: "task-2 실행: {task-2 title}\n컨텍스트: {taskContext}\n완료 후 execute_task로 결과
|
|
388
|
+
Agent(task: "task-2 실행: {task-2 title}\n컨텍스트: {taskContext}\n완료 후 execute_task로 결과 제출. 바꾼 파일은 전부 artifacts에 적는다. 파일을 안 바꾸는 태스크면 noCodeChange: true를 같이 낸다. verification_failed가 오면 고쳐서 다시 제출하고 끝내지 못했으면 status: \"failed\"로 낸다. serverError: true가 함께 오면 고치지 말고 잠시 뒤 같은 결과를 다시 내고 계속 실패하면 status: \"failed\"로 낸다")
|
|
330
389
|
```
|
|
331
390
|
|
|
332
391
|
**각 Agent의 execute_task 제출:**
|
|
@@ -345,6 +404,7 @@ Agent(task: "task-2 실행: {task-2 title}\n컨텍스트: {taskContext}\n완료
|
|
|
345
404
|
```
|
|
346
405
|
|
|
347
406
|
실패 시:
|
|
407
|
+
|
|
348
408
|
```json
|
|
349
409
|
{
|
|
350
410
|
"action": "execute_task",
|
|
@@ -379,10 +439,54 @@ role_match/role_consensus로 얻은 `roleGuidance`를 참조해 태스크를 수
|
|
|
379
439
|
}
|
|
380
440
|
}
|
|
381
441
|
```
|
|
382
|
-
|
|
442
|
+
|
|
443
|
+
→ `{ status, nextTaskId?, allTasksCompleted, artifactCheck?, driftResult? }`
|
|
383
444
|
|
|
384
445
|
`driftResult`가 반환되면 Spec과의 drift 경고 — 계속 진행하되 다음 태스크에서 방향 보정.
|
|
385
446
|
|
|
447
|
+
**artifacts 대조.** `status: "completed"`로 보고하면 서버가 `artifacts`의 파일이 실행 시작 뒤로 실제로 바뀌었는지 확인한다. 수정하거나 새로 만들거나 커밋하거나 지운 파일은 모두 바뀐 것으로 친다. 상대 경로는 `execute_start`의 `cwd` 기준이다. 디렉토리나 gitignore에 걸린 경로는 확인할 수 없으니 바꾼 소스 파일을 하나씩 적는다. `failed`와 `skipped`는 대조하지 않는다. 대조는 `execute_task`에만 있고 `evolve_re_execute`와 `evolve_fix`로 낸 결과는 대조하지 않는다.
|
|
448
|
+
|
|
449
|
+
`artifacts`가 빈 `completed`는 거절된다. 조사나 판단처럼 원래 파일을 안 바꾸는 태스크는 `noCodeChange: true`를 같이 낸다. `artifacts`가 하나라도 있으면 `noCodeChange`와 상관없이 대조한다.
|
|
450
|
+
|
|
451
|
+
```json
|
|
452
|
+
{
|
|
453
|
+
"action": "execute_task",
|
|
454
|
+
"sessionId": "...",
|
|
455
|
+
"taskResult": {
|
|
456
|
+
"taskId": "task-1",
|
|
457
|
+
"status": "completed",
|
|
458
|
+
"output": "기존 인증 흐름 조사 결과 요약",
|
|
459
|
+
"artifacts": [],
|
|
460
|
+
"noCodeChange": true
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
통과하면 응답에 `artifactCheck`가 붙는다.
|
|
466
|
+
|
|
467
|
+
- `verified`: 대조를 통과한 경우
|
|
468
|
+
- `no_code_change`: `noCodeChange: true`로 대조를 건너뛴 경우
|
|
469
|
+
- `no_baseline`: git 레포가 아니라 시작 시점 상태가 없는 경우
|
|
470
|
+
- `baseline_failed`: `execute_start` 때 git 호출이 실패해 시작 시점 상태를 못 잡은 경우
|
|
471
|
+
- `baseline_truncated`: 시작 시점에 커밋 안 된 파일이 2000개를 넘어 이벤트에 해시를 다 못 남겼고 이 세션을 다른 서버 프로세스가 이벤트에서 불러와 대조하지 못한 경우. 해시는 실행을 시작한 프로세스 메모리에만 있고 이벤트에는 사유만 남는다. 그래서 서버가 재시작됐거나 MCP 서버를 따로 띄우는 dispatch 워커가 보고하면 대조 없이 통과한다. 시작한 프로세스는 상태를 잡았으므로 `execute_start` 응답의 `artifactCheck.baseline`은 이때도 `captured`로 나간다. dispatch를 쓸 땐 시작 전에 커밋 안 된 파일을 줄여 둔다
|
|
472
|
+
|
|
473
|
+
**`verification_failed`를 받으면.** 바뀌지 않은 파일이 하나라도 있으면 서버는 결과를 기록하지 않고 이렇게 돌려준다.
|
|
474
|
+
|
|
475
|
+
```json
|
|
476
|
+
{
|
|
477
|
+
"status": "verification_failed",
|
|
478
|
+
"recorded": false,
|
|
479
|
+
"problems": [{ "path": "src/auth.ts", "status": "unchanged", "hint": "실행 시작 뒤로 내용이 그대로입니다" }],
|
|
480
|
+
"nextAction": "execute_task"
|
|
481
|
+
}
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
`problems[].status`는 `unchanged`, `missing`, `outside_repo`, `ignored`, `directory`, `invalid_path`(경로에 개행이나 NUL 문자), `not_regular_file`(FIFO나 소켓처럼 일반 파일이 아님) 중 하나다. 태스크는 아직 끝나지 않은 상태로 남는다. 파일을 실제로 고쳤는지 확인하고 수정을 마치거나 `artifacts` 목록을 바로잡아 같은 태스크를 다시 제출한다. 끝내지 못했으면 `status: "failed"`로 낸다.
|
|
485
|
+
|
|
486
|
+
응답에 `serverError: true`가 있으면 보고 내용 문제가 아니라 서버 쪽 git 호출이 실패한 것이다. 이때는 고칠 것이 없으니 잠시 뒤 같은 결과를 그대로 다시 낸다. 계속 실패하면 `status: "failed"`로 내고 `output`에 오류 내용을 적는다.
|
|
487
|
+
|
|
488
|
+
> 기준점은 태스크마다가 아니라 `execute_start` 때 한 번 잡는다. 앞선 태스크가 바꾼 파일을 뒤 태스크가 `artifacts`에 적어도 통과한다.
|
|
489
|
+
|
|
386
490
|
---
|
|
387
491
|
|
|
388
492
|
## Phase 3 — Evaluate
|
|
@@ -390,12 +494,19 @@ role_match/role_consensus로 얻은 `roleGuidance`를 참조해 태스크를 수
|
|
|
390
494
|
모든 태스크 완료 후 3-Call 평가 진행.
|
|
391
495
|
|
|
392
496
|
**Call 1 — Structural 단계 시작**
|
|
497
|
+
|
|
393
498
|
```json
|
|
394
499
|
{ "action": "evaluate", "sessionId": "..." }
|
|
395
500
|
```
|
|
501
|
+
|
|
396
502
|
→ `{ stage: "structural", structuralContext }` — lint/build/test 실행 지시
|
|
397
503
|
|
|
504
|
+
`structuralContext.commands`의 `command` 문자열을 고치지 말고 그대로 실행한다. 패키지 매니저는 서버가 package.json의 `packageManager` 필드나 lockfile로 골라뒀다. scripts에 없는 lint, build는 목록에서 빠지고 test는 항상 남는다. 제출할 때도 같은 문자열을 그대로 싣는다 — 명령이 다르거나 빠지면 서버가 거부한다. 종료 코드가 0이 아닌 명령이 있으면 `allPassed`를 `true`로 보내도 실패로 처리된다.
|
|
505
|
+
|
|
506
|
+
거부 메시지가 `Submitted commands do not match`로 시작하면 `structuralContext.commands`의 명령을 그대로 다시 실행해서 그 실행의 종료 코드와 출력으로 다시 제출한다. 이전 실행 결과에 명령 문자열만 바꿔 싣지 않는다. 다른 거부 메시지면 다시 제출하지 말고 Call 1부터 다시 시작한다.
|
|
507
|
+
|
|
398
508
|
**Call 2 — Structural 결과 제출**
|
|
509
|
+
|
|
399
510
|
```json
|
|
400
511
|
{
|
|
401
512
|
"action": "evaluate",
|
|
@@ -410,24 +521,25 @@ role_match/role_consensus로 얻은 `roleGuidance`를 참조해 태스크를 수
|
|
|
410
521
|
}
|
|
411
522
|
}
|
|
412
523
|
```
|
|
413
|
-
|
|
414
|
-
→ structural
|
|
524
|
+
|
|
525
|
+
→ structural 실패 시 `{ stage: "complete", shortCircuited: true, nextAction: "evolve_fix" }` → Evolve Flow A 진입
|
|
526
|
+
→ structural 통과 시 `{ stage: "contextual", contextualContext }` — AC별 LLM 검증 지시
|
|
415
527
|
|
|
416
528
|
**Call 3 — Contextual 결과 제출**
|
|
529
|
+
|
|
417
530
|
```json
|
|
418
531
|
{
|
|
419
532
|
"action": "evaluate",
|
|
420
533
|
"sessionId": "...",
|
|
421
534
|
"evaluationResult": {
|
|
422
|
-
"verifications": [
|
|
423
|
-
{ "acIndex": 0, "satisfied": true, "evidence": "...", "gaps": [] }
|
|
424
|
-
],
|
|
535
|
+
"verifications": [{ "acIndex": 0, "satisfied": true, "evidence": "...", "gaps": [] }],
|
|
425
536
|
"overallScore": 0.92,
|
|
426
537
|
"goalAlignment": 0.88,
|
|
427
538
|
"recommendations": []
|
|
428
539
|
}
|
|
429
540
|
}
|
|
430
541
|
```
|
|
542
|
+
|
|
431
543
|
→ `{ status: "completed" }` (score ≥ 0.85, goalAlignment ≥ 0.80)
|
|
432
544
|
→ 미달 시 `{ evolveContext }` → Evolve Flow B 진입
|
|
433
545
|
|
|
@@ -477,7 +589,7 @@ role_match/role_consensus로 얻은 `roleGuidance`를 참조해 태스크를 수
|
|
|
477
589
|
{
|
|
478
590
|
"action": "evolve_re_execute",
|
|
479
591
|
"sessionId": "...",
|
|
480
|
-
"reExecuteTaskResult": { "taskId": "task-3", "status": "completed", "output": "...", "artifacts": [] }
|
|
592
|
+
"reExecuteTaskResult": { "taskId": "task-3", "status": "completed", "output": "...", "artifacts": ["src/auth/oauth.ts"] }
|
|
481
593
|
}
|
|
482
594
|
|
|
483
595
|
// 4. Re-evaluate
|
|
@@ -510,25 +622,64 @@ role_match/role_consensus로 얻은 `roleGuidance`를 참조해 태스크를 수
|
|
|
510
622
|
{ "action": "evolve_lateral", "sessionId": "..." }
|
|
511
623
|
```
|
|
512
624
|
|
|
513
|
-
| Stagnation 패턴
|
|
625
|
+
| Stagnation 패턴 | Persona | 전략 |
|
|
626
|
+
| ------------------- | -------------- | ---------------- |
|
|
627
|
+
| hard_cap | Multistability | 다른 각도로 보기 |
|
|
628
|
+
| oscillation | Simplicity | 단순하게 줄이기 |
|
|
629
|
+
| no_drift | Reification | 빠진 조각 채우기 |
|
|
630
|
+
| diminishing_returns | Invariance | 성공 패턴 복제 |
|
|
631
|
+
|
|
632
|
+
4개 persona를 다 써도 점수가 안 오르면 세션은 끝나지 않고 `awaiting_human`으로 멈춘다. 응답에 `gate`가 실려 온다.
|
|
633
|
+
|
|
634
|
+
```json
|
|
635
|
+
→ { status: "awaiting_human", gate: { gateId, question, options: [...], context }, escalationContext, nextAction: "gate_resolve", nextActionParams: { sessionId, gateResolution: { gateId } } }
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
### Flow D — 사람 판단 대기 (`awaiting_human`)
|
|
639
|
+
|
|
640
|
+
여기서 스킬은 스스로 고르지 않는다. **반드시 사람에게 묻고 답을 기다린다.**
|
|
641
|
+
|
|
642
|
+
1. `gate.question`과 `gate.context`(막힌 태스크, 시도한 persona, 최고 점수, 남은 문제)를 보여준다.
|
|
643
|
+
2. `gate.options`를 선택지로 띄운다. 호스트에 선택형 질문 도구가 있으면(AskUserQuestion 등) 그걸 쓴다. 없으면 번호 목록으로 보여주고 답을 받는다. `restart`와 `abort`는 세션이 종료된다는 점을 함께 알린다.
|
|
644
|
+
3. 고른 선택지에 더해 **결정(`decision`)과 이유(`rationale`)를 한 줄씩** 받는다. 둘 다 비면 서버가 거절한다. 사람이 이유를 안 적었으면 다시 묻는다. 대신 지어내지 않는다 — 이 두 줄이 그대로 Memory에 남는다.
|
|
645
|
+
4. `gate_resolve`를 부른다.
|
|
646
|
+
|
|
647
|
+
```json
|
|
648
|
+
{
|
|
649
|
+
"action": "gate_resolve",
|
|
650
|
+
"sessionId": "...",
|
|
651
|
+
"gateResolution": {
|
|
652
|
+
"gateId": "gate-...",
|
|
653
|
+
"optionId": "patch_spec",
|
|
654
|
+
"decision": "사람이 내린 결정",
|
|
655
|
+
"rationale": "그렇게 정한 이유"
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
5. 응답의 `nextAction`을 따른다.
|
|
661
|
+
|
|
662
|
+
| `optionId` | 응답 | 다음 |
|
|
514
663
|
|---|---|---|
|
|
515
|
-
|
|
|
516
|
-
|
|
|
517
|
-
|
|
|
518
|
-
|
|
|
664
|
+
| `patch_spec` | `gate_resolved`, 세션 `executing` | 사람이 말한 대로 AC나 제약을 고쳐 `evolve_patch` (Flow B) |
|
|
665
|
+
| `manual_task` | `gate_resolved`, 세션 `executing` | 사람이 태스크를 처리했는지 확인한 뒤 `evaluate` |
|
|
666
|
+
| `restart` | `terminated` | 세션 종료. 태스크를 더 잘게 쪼갠 새 스펙으로 `start`를 안내 |
|
|
667
|
+
| `abort` | `terminated` | 세션 종료. 막힌 지점과 시도한 접근을 보고 |
|
|
668
|
+
|
|
669
|
+
이어간 뒤 다음 평가가 한 번만 성공 기준에 못 미쳐도 persona를 되풀이하지 않고 곧바로 새 `awaiting_human` 응답이 온다. 진화 이력과 이미 써본 persona 기록이 남아 있어서다. 그때도 1번부터 다시 한다.
|
|
519
670
|
|
|
520
|
-
|
|
671
|
+
`awaiting_human`인 동안에는 `status`, `resume`, `gate_resolve`, `evolution_viz` 말고는 전부 에러로 거절된다. 세션을 이어받았는데 `resume`이 `awaiting_human`을 돌려주면 1번부터 다시 한다.
|
|
521
672
|
|
|
522
673
|
### 종료 조건
|
|
523
674
|
|
|
524
|
-
| 조건
|
|
525
|
-
|
|
526
|
-
| `success`
|
|
527
|
-
| `stagnation`
|
|
528
|
-
| `oscillation`
|
|
529
|
-
| `hard_cap`
|
|
530
|
-
| `caller`
|
|
531
|
-
| `human_escalation` | 4개 lateral persona 소진 |
|
|
675
|
+
| 조건 | 트리거 |
|
|
676
|
+
| ------------------ | ------------------------------------------------------------- |
|
|
677
|
+
| `success` | score ≥ 0.85 AND goalAlignment ≥ 0.80 |
|
|
678
|
+
| `stagnation` | 2회 연속 delta < 0.05 |
|
|
679
|
+
| `oscillation` | 2회 연속 점수 역전 |
|
|
680
|
+
| `hard_cap` | structural 3회 + contextual 3회 실패 |
|
|
681
|
+
| `caller` | `{ action: "evolve", terminateReason: "caller" }` |
|
|
682
|
+
| `human_escalation` | 4개 lateral persona 소진 후 사람이 `restart`나 `abort`를 고름 |
|
|
532
683
|
|
|
533
684
|
---
|
|
534
685
|
|
|
@@ -551,7 +702,13 @@ activeForm: "실행 계획 수립 중"
|
|
|
551
702
|
`TaskUpdate`로 현재 Planning 단계를 업데이트한다.
|
|
552
703
|
|
|
553
704
|
```
|
|
554
|
-
description: "Planning 중 | 단계 {stepsCompleted}/4 | {
|
|
705
|
+
description: "Planning 중 | 단계 {stepsCompleted}/4 | {executeContext.currentStage}"
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
`plan_rewound`를 받으면 `stepsCompleted`가 없으므로 이렇게 바꾼다.
|
|
709
|
+
|
|
710
|
+
```
|
|
711
|
+
description: "Planning 되감김 | 단계 {rewoundToStep - 1}/4 | {executeContext.currentStage}"
|
|
555
712
|
```
|
|
556
713
|
|
|
557
714
|
### Execution 시작 후 (`execute_start` 응답 수신 후)
|
|
@@ -584,12 +741,14 @@ activeForm: "병렬 실행 중: 그룹 {groupIndex}/{totalGroups} — {agentCoun
|
|
|
584
741
|
`TaskUpdate`로 진행 상황과 현재 실행 태스크명을 업데이트한다.
|
|
585
742
|
|
|
586
743
|
순차 실행 중:
|
|
744
|
+
|
|
587
745
|
```
|
|
588
746
|
description: "{completedCount}/{totalTasks} 완료 | 실패: {failedCount}개 | 그룹 {groupIndex}/{totalGroups}"
|
|
589
747
|
activeForm: "실행 중: {taskContext.currentTask.title}"
|
|
590
748
|
```
|
|
591
749
|
|
|
592
750
|
병렬 그룹 실행 중 (각 Agent의 execute_task 완료 시):
|
|
751
|
+
|
|
593
752
|
```
|
|
594
753
|
description: "{completedCount}/{totalTasks} 완료 | 실패: {failedCount}개 | 그룹 {groupIndex}/{totalGroups}"
|
|
595
754
|
activeForm: "병렬 실행 중: 그룹 {groupIndex}/{totalGroups} — {agentCount}개 Agent 실행 중"
|
|
@@ -609,6 +768,14 @@ activeForm: "병렬 실행 중: 그룹 {groupIndex}/{totalGroups} — {agentCoun
|
|
|
609
768
|
- 평가 완료(success): `TaskUpdate({ status: "completed", description: "완료 | score: {overallScore} | alignment: {goalAlignment}" })`
|
|
610
769
|
- Evolve 진입: description에 "개선 중 (generation {N})" 추가
|
|
611
770
|
|
|
771
|
+
### 사람 판단 대기 시 (`awaiting_human`)
|
|
772
|
+
|
|
773
|
+
```
|
|
774
|
+
description: "사람 판단 대기 | 최고 점수: {gate.context.bestScore}"
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
`gate_resolve`가 `gate_resolved`를 돌려주면 진화 단계 표시로 돌아간다.
|
|
778
|
+
|
|
612
779
|
### 오류/에스컬레이션 시
|
|
613
780
|
|
|
614
781
|
```
|
|
@@ -128,7 +128,15 @@ The interview only has value if the human's actual intent is captured. A self-an
|
|
|
128
128
|
1. **Start**: Create a session, detect project type (greenfield/brownfield), ask the first question
|
|
129
129
|
2. **Iterate**: Present each generated question to the user → wait for answer → submit answer to Gestalt
|
|
130
130
|
3. **Score**: Continuously assess resolution across multiple dimensions
|
|
131
|
-
4. **Complete**:
|
|
131
|
+
4. **Complete**: Call `complete` only after `resolutionScore.isReady === true` (overall ≥ 0.8). The server rejects `complete` on a session that has no score or is below threshold
|
|
132
|
+
|
|
133
|
+
### 0.8 미만에서 끝내기
|
|
134
|
+
|
|
135
|
+
사용자가 0.8 미만에서 넘어가겠다고 직접 답한 경우에만 `force: true`로 `complete`를 부른다. 15라운드를 다 채워 `respond`가 더 받지 않으면 그 마지막 답의 점수는 반영되지 않은 상태다. 먼저 `score`로 그 점수를 넣고 `isReady`를 확인한다. 그래도 0.8 미만이면 에이전트가 현재 점수와 덜 채워진 차원을 보여주고 넘어갈지 묻는다. 라운드 수만으로 `force`를 넘기지 않는다. 사용자가 먼저 "그냥 넘어가자"고 했을 때도 같은 내용을 보여주고 한 번 더 확인한 뒤에 부른다.
|
|
136
|
+
|
|
137
|
+
사용자가 넘어가지 않겠다고 하면 세션을 `in_progress`로 둔다. 15라운드 전이면 같은 세션에서 덜 채워진 차원을 다시 묻는다. 15라운드를 다 채웠으면 덜 채워진 차원을 사용자와 함께 정리해 새 인터뷰로 이어가거나 거기서 멈춘다.
|
|
138
|
+
|
|
139
|
+
에이전트가 스스로 `force`를 판단하지 않는다. 거절 메시지에 "force=true로 넘기세요"가 나와도 그건 사용자에게 물어볼 근거이지 바로 넘길 근거가 아니다. 이렇게 끝낸 세션에는 `forcedComplete`가 기록된다. Spec을 뽑을 때도 `ges_generate_spec`에 `force`를 따로 넘겨야 한다.
|
|
132
140
|
|
|
133
141
|
## Gestalt Principles Applied
|
|
134
142
|
|
|
@@ -154,9 +162,12 @@ API 키 없이 MCP 서버 실행 시 자동 활성화. LLM 작업을 caller가
|
|
|
154
162
|
| `resolutionScore.priorityClarity` | number (0-1) | 필수* | 우선순위 명확도 |
|
|
155
163
|
| `resolutionScore.contextClarity` | number (0-1) | 선택 | 컨텍스트 명확도 |
|
|
156
164
|
| `resolutionScore.contradictions` | string[] | 선택 | 발견된 모순 목록 |
|
|
165
|
+
| `force` | boolean | 선택 (기본 `false`) | `complete` 전용. 0.8 미만이어도 완료한다. 사용자가 직접 정했을 때만 넘긴다 |
|
|
157
166
|
|
|
158
167
|
\* resolutionScore 객체를 제공할 경우 필수
|
|
159
168
|
|
|
169
|
+
답변 라운드가 0인 세션에 기준을 넘는 resolutionScore를 넣으면 `score`와 `respond`가 거절한다. 공백만 보낸 답은 답변으로 세지 않는다. 기준 미만 점수는 받는다.
|
|
170
|
+
|
|
160
171
|
### Action별 응답 구조 (Passthrough)
|
|
161
172
|
|
|
162
173
|
**`start`** → `{ status, sessionId, projectType, detectedFiles, gestaltContext, roundNumber, message }`
|
|
@@ -166,7 +177,9 @@ API 키 없이 MCP 서버 실행 시 자동 활성화. LLM 작업을 caller가
|
|
|
166
177
|
**`score`** (점수 미제공 시) → `{ status, resolutionScore, scoringPrompt, message }`
|
|
167
178
|
**`score`** (점수 제공 시) → `{ status, resolutionScore }`
|
|
168
179
|
|
|
169
|
-
**`complete`** → `{ status, sessionId, totalRounds, finalResolutionScore, message }`
|
|
180
|
+
**`complete`** → `{ status, sessionId, totalRounds, finalResolutionScore, forced, message }`
|
|
181
|
+
|
|
182
|
+
`forced`는 기준 미만 세션을 `force`로 끝냈을 때만 `true`다. 이미 준비된 세션에 `force`를 넘겨도 `false`로 남는다.
|
|
170
183
|
|
|
171
184
|
### GestaltContext 필드
|
|
172
185
|
|