# TAKT Architecture Knowledge

## Core Structure

WorkflowEngine is a state machine. It manages step transitions via EventEmitter.

```
CLI → WorkflowEngine → Runner (4 types) → RuleEvaluator → next step
```

| Runner | Purpose | When to Use |
|--------|---------|-------------|
| StepExecutor | Standard 3-phase execution | Default |
| ParallelRunner | Concurrent sub-steps | parallel block |
| ArpeggioRunner | Data-driven batch processing | arpeggio block |
| TeamLeaderRunner | Task decomposition → parallel sub-agents | team_leader block |

Runners are mutually exclusive. Do not specify multiple runner types on a single step.

### 3-Phase Execution Model

Normal steps execute in up to 3 phases. Sessions persist across phases.

| Phase | Purpose | Tools | Condition |
|-------|---------|-------|-----------|
| Phase 1 | Main work | Step's allowed_tools | Always |
| Phase 2 | Report output | Write only | When output_contracts defined |
| Phase 3 | Status judgment | None (judgment only) | When tag-based rules exist |

## Rule Evaluation

RuleEvaluator determines the next step via 5-stage fallback. Earlier match takes priority.

| Priority | Method | Target |
|----------|--------|--------|
| 1 | aggregate | parallel parent (all/any) |
| 2 | Phase 3 tag | `[STEP:N]` output |
| 3 | Phase 1 tag | `[STEP:N]` output (fallback) |
| 4 | ai() judge | ai("condition") rules |
| 5 | AI fallback | AI evaluates all conditions |

When multiple tags appear in output, the **last match** wins.

### Condition Syntax

| Syntax | Parsing | Regex |
|--------|---------|-------|
| `ai("...")` | AI condition evaluation | `AI_CONDITION_REGEX` |
| `all("...")` / `any("...")` | Aggregate condition | `AGGREGATE_CONDITION_REGEX` |
| Plain string | Tag or AI fallback | — |

Adding new special syntax requires updating both workflowParser.ts regex and RuleEvaluator.

## Provider Integration

Abstracted through the Provider interface. SDK-specific details are encapsulated within each provider.

```
Provider.setup(AgentSetup) → ProviderAgent
ProviderAgent.call(prompt, options) → AgentResponse
```

| Criteria | Judgment |
|----------|----------|
| SDK-specific error handling leaking outside Provider | REJECT |
| Errors not propagated to AgentResponse.error | REJECT |
| Session key collision between providers | REJECT |
| Session key format `{persona}:{provider}` | OK |

### Model Resolution

Models resolve through 5-level priority. Higher takes precedence.

1. persona_providers model specification
2. Step model field
3. CLI `--model` override
4. config.yaml (when resolved provider matches)
5. Provider default

## Facet Assembly

The faceted-prompting module is independent from TAKT core.

```
compose(facets, options) → ComposedPrompt { systemPrompt, userMessage }
```

| Criteria | Judgment |
|----------|----------|
| Import from faceted-prompting to TAKT core | REJECT |
| TAKT core depending on faceted-prompting | OK |
| Facet path resolution logic outside faceted-prompting | Warning |

### 3-Layer Facet Resolution Priority

Project `.takt/` → User `~/.takt/` → Builtin `builtins/{lang}/`

Same-named facets are overridden by higher-priority layers. Customize builtins by overriding in upper layers.

## Testing Patterns

Uses vitest. Test file naming conventions distinguish test types.

| Prefix | Type | Content |
|--------|------|---------|
| None | Unit test | Individual function/class verification |
| `it-` | Integration test | Workflow execution simulation |
| `engine-` | Engine test | WorkflowEngine scenario verification |

### Mock Provider

`--provider mock` returns deterministic responses. Scenario queues compose multi-turn tests.

```typescript
// NG - Calling real API in tests
const response = await callClaude(prompt)

// OK - Set up scenario with mock provider
setMockScenario([
  { persona: 'coder', status: 'done', content: '[STEP:1]\nDone.' },
  { persona: 'reviewer', status: 'done', content: '[STEP:1]\napproved' },
])
```

### Test Isolation

| Criteria | Judgment |
|----------|----------|
| Tests sharing global state | REJECT |
| Environment variables not cleared in test setup | Warning |
| E2E tests assuming real API | Isolate via `provider` config |

## Error Propagation

Provider errors propagate through: `AgentResponse.error` → session log → console output.

| Criteria | Judgment |
|----------|----------|
| SDK error results in empty `blocked` status | REJECT |
| Error details not recorded in session log | REJECT |
| No ABORT transition defined for error cases | Warning |

## Session Management

Agent sessions are stored per-cwd. Session resume is skipped during worktree/clone execution.

| Criteria | Judgment |
|----------|----------|
| Session resuming when `cwd !== projectCwd` | REJECT (cross-project contamination) |
| Session key missing provider identifier | REJECT (cross-provider contamination) |
| Session broken between phases | REJECT (context loss) |
