Skip to content

Commit db66ea2

Browse files
authored
Merge pull request #20 from pankaj4u4m/spec
Spec
2 parents ecbba8d + a1a200d commit db66ea2

288 files changed

Lines changed: 29719 additions & 6738 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

GEMINI.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
## General Agent Guidelines
44
- **No Shortcuts:** Never assume the structure of data or APIs. Always verify the source of truth (e.g., `api.ts` for frontend, `schemas.py` or `models.py` for backend) before implementation.
55
- **Strict Verification:** Always run the project's build, lint, and type-check commands after making changes. A task is not complete until it passes all validation steps.
6-
- **Atelier Integration:** Use `mcp_atelier_trace` after every significant fix to record the outcome and help the system learn.
6+
- **Atelier Integration:** Use `mcp_atelier_record` after every significant fix to record the outcome and help the system learn.
77

88
## Frontend Engineering Standards (TypeScript/React)
99

Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ typecheck: ## Run mypy strict type-checking
7575
uv run mypy --strict $(PY_PATHS)
7676

7777
verify: lint format-check typecheck test ## Verify code, runtime smoke tests, and agent integrations
78-
bash scripts/verify_atelier_mcp_stdio.sh
7978
bash scripts/verify_atelier_service.sh
8079
bash scripts/verify_atelier_postgres.sh
8180
bash scripts/verify_agent_clis.sh

QUICK_REFERENCE.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ _For agents/automation, see [AGENT_README.md](AGENT_README.md) instead._
1212

1313
- **Starting a coding task?** → Use `/atelier:context` or pick `atelier:code` agent
1414
- **Same error failed 2+ times?** → Use `/atelier:rescue`
15-
- **Done with the task?** → Use `/atelier:trace`
15+
- **Done with the task?** → Use `/atelier:record`
1616
- **Just reading code?** → Use `atelier:explore` agent (read-only)
1717
- **Reviewing someone's PR?** → Use `atelier:review` agent (no editing)
1818

@@ -27,7 +27,7 @@ Core Loop
2727
─────────────────────────────────────────────────
2828
/atelier:context Gather task context and procedures
2929
/atelier:implement Execute task (optional: /atelier:rescue on failure)
30-
/atelier:trace Record outcome (files, commands, errors, results)
30+
/atelier:record Record outcome (files, commands, errors, results)
3131
```
3232

3333
Intelligence
@@ -50,7 +50,7 @@ Operations
5050
5151
- `/atelier:context` — **Step 1: Gather Context**. Retrieve procedures, facts, and rules before starting.
5252
- **Step 2: Implement** — Execute the task. Use `/atelier:rescue` if stuck on the same error twice.
53-
- `/atelier:trace` — **Step 3: Record Trace**. Save what happened for the reasoning store once done.
53+
- `/atelier:record` — **Step 3: Record**. Save what happened for the reasoning store once done.
5454
5555
### Intelligence Skills (as needed)
5656
@@ -73,7 +73,7 @@ Operations
7373
7474
```
7575
atelier:code Main coding agent
76-
├─ Loop: context → plan → implement → rescue → verify → trace
76+
├─ Loop: context → plan → implement → rescue → verify → record
7777
├─ Tools: All (editing + MCP + shell)
7878
└─ Hard rules: No secrets, no plan contradictions
7979

@@ -98,10 +98,10 @@ atelier:repair Repair specialist (on repeated failures)
9898
```
9999
CORE WORKFLOW
100100
─────────────────────────────────────────────────
101-
task Fetch ReasonBlocks, memory, ledger, and environment context
101+
context Fetch ReasonBlocks, memory, ledger, and environment context
102102
route Dispatch route decide/verify operations
103103
rescue Get recovery procedure
104-
trace Save observable outcome for learning
104+
record Save observable outcome for learning
105105
verify Verify high-risk domain before success
106106

107107
CONTEXT + MEMORY [Atelier augmentation]
@@ -163,7 +163,7 @@ ID Title Domain
163163
```
164164
atelier context --task "..." --domain beseam.shopify.publish --files src/...
165165
atelier rescue --task "..." --error "..." --files ... --recent-actions "tried X" "tried Y"
166-
atelier trace record --agent atelier:code --domain ... --status success --files-touched [...]
166+
atelier runs record --agent atelier:code --domain ... --status success --files-touched [...]
167167
atelier verify rubric_shopify_publish --checks '{"check_1": true, ...}'
168168
atelier block list --domain beseam.shopify.publish
169169
atelier eval list
@@ -253,7 +253,7 @@ DO NOT:
253253
❌ Ignore high-severity Atelier warnings
254254
❌ Invent plan steps that contradict ReasonBlocks
255255
❌ Store secrets, API keys, tokens in traces
256-
❌ Call record_trace without observable facts
256+
❌ Call record without observable facts
257257
❌ Edit code after review agent reports "block"
258258
❌ Approve a rubric_gate "block" verdict
259259
❌ Re-propose same hypothesis twice in repair
@@ -270,7 +270,7 @@ Q: Same error just failed twice
270270
A: Use /atelier:rescue
271271

272272
Q: I'm done with the task
273-
A: Use /atelier:trace
273+
A: Use /atelier:record
274274

275275
Q: I need to review someone's patch
276276
A: Use atelier:review agent

README.md

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -48,23 +48,21 @@ Check the installed runtime:
4848
```bash
4949
atelier --version
5050
atelier-mcp --version
51-
atelier servicectl status
52-
atelier stack status
51+
atelier background status
5352
```
5453

5554
→ User install guide: [docs/installation.md](docs/installation.md)
5655

5756
## What Runs After Install
5857

59-
The installed product always gives you **CLI + MCP + background processing**.
58+
The installed product gives you **CLI + MCP + Background Services**.
6059

61-
If Docker is available and `ATELIER_NO_STACK=1` is not set, the installer also
62-
tries to start the optional visualization stack on ports `3125` and `8787`.
60+
Atelier automatically registers itself with your OS background manager (**systemd** on Linux, **launchd** on macOS). This ensures it starts on boot and restarts automatically if it crashes.
6361

6462
- `atelier ...` works with no HTTP server.
6563
- `atelier-mcp` works with no HTTP server.
66-
- `atelier servicectl ...` manages offline/background work.
67-
- `atelier stack ...` remains optional at runtime even if the installer started it for convenience.
64+
- `atelier background ...` manages the OS-level services (controller + stack).
65+
- `atelier stack ...` manages the visualization containers manually.
6866

6967
Pure CLI mode still emits Atelier telemetry events unless you disable it with `atelier telemetry off` or `ATELIER_TELEMETRY=0`.
7068

@@ -74,67 +72,72 @@ Atelier follows a simple **3-step process** for reliable coding:
7472

7573
1. **Context**: Retrieve procedures and facts before starting.
7674
2. **Implement**: Execute the task (with optional rescue/route).
77-
3. **Trace**: Record the outcome once done.
75+
3. **Record**: Record the outcome once done.
7876

7977
Passive tracking works automatically. Active context features require `ATELIER_DEV_MODE=1`.
8078

8179
```bash
8280
# Fetch context for an agent task (Requires Dev Mode)
83-
atelier context \
84-
--task "Fix generated output that drifts back after refresh" \
85-
--domain source.truth \
86-
--file src/content/generate.py
81+
atelier tools call context --dev --args '{
82+
"task": "Fix generated output that drifts back after refresh",
83+
"domain": "source.truth",
84+
"files": ["src/content/generate.py"]
85+
}' --json
8786

8887
# Verify required checks after a task completes (Requires Dev Mode)
89-
echo '{"canonical_identifier_used": true, "pre_change_state_captured": true, "read_after_write_completed": true}' \
90-
| atelier verify rubric_state_change_safety
88+
atelier tools call verify --dev --args '{
89+
"rubric_id": "rubric_state_change_safety",
90+
"checks": {
91+
"canonical_identifier_used": true,
92+
"pre_change_state_captured": true,
93+
"read_after_write_completed": true
94+
}
95+
}' --json
9196
```
9297

9398
Common runtime commands:
9499

95100
```bash
96-
atelier servicectl status
101+
atelier background status
97102
atelier worker list
98-
atelier trace list
99-
atelier search "read after write verification"
103+
atelier runs list
104+
atelier tools call search --dev --args '{"query":"read after write verification"}' --json
100105
```
101106

102107
→ Installed quickstart: [docs/quickstart.md](docs/quickstart.md)
103108

104109
## Optional UI Stack
105110

106-
The UI is optional. If the installer already started it for you, you can leave it
107-
running, inspect it, or stop it. If Docker was unavailable during install, start
108-
it manually when you want visualization or a browser-based view of the runtime.
111+
The UI is optional. The installer registers it as a background service by default if Docker is available. You can manage it alongside the controller:
109112

110113
```bash
111-
atelier stack start
112-
atelier stack status
113-
atelier stack stop
114+
# View logs for the visualization stack
115+
atelier background logs stack
116+
117+
# Restart the entire environment
118+
atelier background restart
114119
```
115120

116121
Then open:
117122

118123
- frontend: [http://localhost:3125](http://localhost:3125)
119124
- service API: [http://localhost:8787](http://localhost:8787)
120125

121-
Useful stack commands:
122-
123-
```bash
124-
atelier stack status
125-
atelier stack logs
126-
atelier stack stop
127-
```
126+
## Background Processing & Auto-Update
128127

129-
## Background Processing
128+
Atelier includes an offline processing controller that runs as a background service. It handles session imports, maintenance jobs, and **automatic code updates**.
130129

131-
`servicectl` is the installed offline processing controller. It runs detached and periodically enqueues and processes maintenance work. It works on the default SQLite install and on Postgres-backed deployments.
130+
The controller periodically checks your git repository for updates. When found, it automatically pulls the latest code, syncs dependencies, and restarts the services.
132131

133132
```bash
134-
atelier servicectl status
135-
atelier servicectl logs
136-
atelier servicectl stop
137-
atelier servicectl start
133+
# Check service health and auto-update status
134+
atelier background status
135+
136+
# View background logs (from journald/launchd)
137+
atelier background logs controller
138+
139+
# Manually trigger a restart
140+
atelier background restart
138141
```
139142

140143
You can also queue and process work manually:

bin/atelier-status

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -155,14 +155,37 @@ run_files = sorted(
155155
)
156156
157157
# ── Extract Live Savings and DB Cost ──────────────────────────────────────
158-
savings_map = {}
158+
# savings_map: total cost_saved_usd per session (all levers combined)
159+
# routing_map: model_routing savings per session
160+
# compaction_map: session_compaction savings per session
161+
savings_map = {}
162+
routing_map = {}
163+
compaction_map = {}
164+
routing_total = 0.0
165+
compaction_total = 0.0
166+
167+
def _lever_bucket(lever: str) -> str:
168+
l = (lever or "").lower()
169+
if "routing" in l: return "routing"
170+
if "compact" in l: return "compaction"
171+
return "other"
172+
159173
try:
160174
with open(os.path.join(ROOT, "live_savings_events.jsonl")) as f:
161175
for line in f:
162176
d = json.loads(line)
163177
rid = d.get("session_id")
178+
cost = float(d.get("cost_saved_usd", 0.0) or 0.0)
179+
lever = str(d.get("lever") or d.get("tool_name") or "")
180+
bucket = _lever_bucket(lever)
164181
if rid:
165-
savings_map[rid] = savings_map.get(rid, 0.0) + float(d.get("cost_saved_usd", 0.0))
182+
savings_map[rid] = savings_map.get(rid, 0.0) + cost
183+
if bucket == "routing":
184+
routing_map[rid] = routing_map.get(rid, 0.0) + cost
185+
routing_total += cost
186+
elif bucket == "compaction":
187+
compaction_map[rid] = compaction_map.get(rid, 0.0) + cost
188+
compaction_total += cost
166189
except Exception:
167190
pass
168191
@@ -258,16 +281,26 @@ if LINE_MODE:
258281
if cost_v == 0 and "input_tokens" in snap:
259282
# Heuristic for imported traces
260283
cost_v = (snap.get("input_tokens",0)*3 + snap.get("output_tokens",0)*15) / 1000000.0
261-
262-
saved_v = savings_map.get(session_id, 0.0)
284+
285+
saved_v = savings_map.get(session_id, 0.0)
286+
routing_v = routing_map.get(session_id, 0.0)
287+
compaction_v = compaction_map.get(session_id, 0.0)
288+
289+
saved_seg = ""
290+
if saved_v > 0:
291+
line_breakdown = []
292+
if compaction_v > 0: line_breakdown.append(f"compact={usd(compaction_v)}")
293+
if routing_v > 0: line_breakdown.append(f"routing={usd(routing_v)}")
294+
breakdown_suffix = f" ({', '.join(line_breakdown)})" if line_breakdown else ""
295+
saved_seg = f" {SEP} {GREEN}saved={usd(saved_v)}{breakdown_suffix}{RESET}"
263296
264297
line = (
265298
f"{BADGE} {BRAND}run {session_id[:8]}{RESET} {SEP} {DIM}{agent}{RESET} {SEP} "
266299
f"{domain} {SEP} {task} {SEP} {status_color(status)} "
267300
f"{SEP} ev={events} err={errors} blk={blockers}"
268301
f" {SEP} files={files_n} tools={tools_n}"
269302
+ (f" {SEP} cost={usd(cost_v)}" if cost_v > 0 else "")
270-
+ (f" {SEP} {GREEN}saved={usd(saved_v)}{RESET}" if saved_v > 0 else "")
303+
+ saved_seg
271304
+ (f" {SEP} {dur_str}" if dur_str else "")
272305
+ f" {SEP} {DIM}{age_str}{RESET}"
273306
)
@@ -364,9 +397,13 @@ box_line(
364397
f"{DIM}tools={k(total_tools)} files={total_files} errs={total_errors}{RESET}"
365398
)
366399
if total_cost > 0 or saved_usd > 0:
400+
breakdown_parts = []
401+
if compaction_total > 0: breakdown_parts.append(f"compact {usd(compaction_total)}")
402+
if routing_total > 0: breakdown_parts.append(f"routing {usd(routing_total)}")
403+
breakdown_str = f" {DIM}({' · '.join(breakdown_parts)}){RESET}" if breakdown_parts else ""
367404
box_line(
368405
f"{DIM}cost{RESET} {usd(total_cost)} "
369-
+ (f"{GREEN}saved{RESET} {usd(saved_usd)}" if saved_usd > 0 else "")
406+
+ (f"{GREEN}saved{RESET} {usd(saved_usd)}{breakdown_str}" if saved_usd > 0 else "")
370407
+ (f" {DIM}tokens{RESET} {k(total_tokens)}" if total_tokens else "")
371408
)
372409
@@ -391,17 +428,26 @@ for d in all_run_entries[:N_RUNS]:
391428
if cost_v == 0 and "input_tokens" in d:
392429
cost_v = (d.get("input_tokens",0)*3 + d.get("output_tokens",0)*15) / 1000000.0
393430
394-
saved_v = savings_map.get(session_id, 0.0)
431+
saved_v = savings_map.get(session_id, 0.0)
432+
routing_v = routing_map.get(session_id, 0.0)
433+
compaction_v = compaction_map.get(session_id, 0.0)
395434
396435
# Professional 2-line layout
397436
# [icon] Task ................. ID
398437
dots = "." * max(1, (W - len(re.sub(r'\033\[[^m]*m', '', task)) - 16))
399438
box_line(f" {status_icon(status)} {BOLD}{task}{RESET} {DIM}{dots} {session_id[:8]}{RESET}")
400-
439+
401440
metrics = []
402-
if cost_v > 0: metrics.append(f"cost={usd(cost_v)}")
403-
if saved_v > 0: metrics.append(f"{GREEN}saved={usd(saved_v)}{RESET}")
404-
if dur_str: metrics.append(dur_str)
441+
if cost_v > 0:
442+
metrics.append(f"cost={usd(cost_v)}")
443+
if saved_v > 0:
444+
run_breakdown = []
445+
if compaction_v > 0: run_breakdown.append(f"c={usd(compaction_v)}")
446+
if routing_v > 0: run_breakdown.append(f"r={usd(routing_v)}")
447+
run_breakdown_str = f" {DIM}({' '.join(run_breakdown)}){RESET}" if run_breakdown else ""
448+
metrics.append(f"{GREEN}saved={usd(saved_v)}{run_breakdown_str}")
449+
if dur_str:
450+
metrics.append(dur_str)
405451
metrics_str = f" {SEP} ".join(metrics)
406452
407453
meta_line = f" {DIM}{age_str}{RESET} {SEP} {agent} {SEP} {domain}"

docs-archive/internal/engineering/telemetry-implementation-plan.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ src/atelier/gateway/adapters/
7676
cli.py # ADD: SIGINT/SIGTERM handlers, command lifecycle events
7777
mcp_server.py # ADD: session start/end, tool_called wrapper events
7878
http_api.py # ADD: request middleware emitting api_request events
79-
wrappers.py # ADD: lifecycle hooks for atelier-task / atelier-context / etc.
79+
wrappers.py # ADD: lifecycle hooks for atelier-context / etc.
8080
8181
src/atelier/core/runtime/
8282
engine.py # ADD: lift loop_detection / monitor signals to product events

docs-archive/sdk/cli.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Developer-mode commands require `ATELIER_DEV_MODE=1`:
2525
- `atelier edit`
2626
- `atelier route`
2727

28-
Older docs may refer to `atelier lint`, `atelier check-plan`, `atelier task`, or
28+
Older docs may refer to `atelier lint`, `atelier check-plan`, `atelier context`, or
2929
`atelier pack`. Those are not the current public CLI surface.
3030

3131
## Common Commands

0 commit comments

Comments
 (0)