From 741364654c2d9b7bd8d99770f0a151723c2c228f Mon Sep 17 00:00:00 2001 From: laptran Date: Sat, 13 Jun 2026 21:33:23 -0400 Subject: [PATCH] Fix task directory gap in upgrade process The additive extension model refactor moved prompts/contracts/scripts into .automaton/ but never addressed where tasks live. Two conventions existed: framework keeps tasks in .automaton/tasks/, Orchestrator creates project tasks at tasks/. Fixes: - Dashboard _find_tasks_dir() now scope-aware: framework mode prefers .automaton/tasks/, project mode prefers tasks/ at project root - migrate-project.sh: if tasks exist in .automaton/tasks/ (old model), move them to tasks/ (project root) - Orchestrator prompt: documents that tasks location depends on scope --- .../ui/__pycache__/app.cpython-314.pyc | Bin 23073 -> 23201 bytes automaton/dashboard/ui/app.py | 19 +++++++++++++----- prompts/orchestrate.md | 11 +++++++--- scripts/migrate-project.sh | 12 +++++++++++ 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/automaton/dashboard/ui/__pycache__/app.cpython-314.pyc b/automaton/dashboard/ui/__pycache__/app.cpython-314.pyc index 3d8b968803dd6bf90e5e4fb913d45896edfb799b..2aa5b2674ac1cf41e867311f0d8fe97ab4989ee4 100644 GIT binary patch delta 1990 zcmZXUe@xV67{K4>e)H1T5R~rZ*P);wBq&CJ2!eV*HsHn`dLVb_dq?0;P_cB= ztR6SrS{jv`+FHt2|6tVGY_&C8nW?j{wY60nYiT5=%Tjxv?@2KG{_*)f@AK>XywCf5 z-=Xs`bOB;BV`Czjct$ljon3|JVxOCx6t7MGg9!||$LV!Cbk_aBc143Nb>_tuU~GW3 zs2ZS(RYCx)%n5T@J|z)PuZl6A?o>CZ3Y!>nn;Ek(Cu>lnD>Z3>5Hwj)VMk()Dxg_C z=V|SvyOGRJjgeIpFc#1{wK$Mx!Liv1pvAaC3z`xW`n5eOD@$h)EQL8WEi5Z(DtS7y zYk8|!+kqRzOOEK^u5M4SpLaco%yIRE{N1jQ-zRHBu3%Ttu8||#{oIoiZ1)E|N&v5> zD4jRh>h^NGj<<^+%)S*p6$)%u^e$84GTRMej9Z#<*6U6nmh0JetKND+)6F z=cQQpS4%e2ZgrYhj)AH+IaJzT^g+X{SWPFC@)xZIvlx05_(hId1w zG_@sJ}PL4?_H=$xyo{T<%G1%zZ}ZBefp~bDxKs_+{=D zcpFbR7Q&cx#j#fnhtQe7)_8_|XsGzBgu^(Jzry$-iRTEz1jMKU3+%=piW9N4AWkHx zFOWf}cnxFTk}P;6wJiA_M9ShKhfYa3id%}(;4mI3%A6H;q)g`tql621wWu5(p=s$D zj35-xR~Z0p#rsl@3aeekryBL-fR#q=#7o6X$x~nA(S1RAlvs$Cj+LxcMJXRTOX^{~ zw`@fBIf;AlLTSllvG+@t3g?Ao4eEZy?`!h7EKtiSSe%M7yvlef6HKj<_1=(&iyw}6 zk-JiwGSuHvh<@4t(izISc7KmA6qF5gjP##!nj|HEP%k9<7scPGUb#qb7WY>0cZNCX ziPE~2l`6Q7Z&hUK=<~7}x7cPHeD2oHpx>7({aUdNVt*oo*2B4<*Ycl{S60Dd{HSse zj^gsFIw--{s}kTgo~&wvPf=H$0RhaeHZ3|$-#qM*=|LK=OYJEA>pu2upv}7`Ulk{u@sLXt$5?(QR`^x$? z+~4VG5Aj3Ty6*j?soLkz$Mm!dUpE!>jo(!-aJ&lFX zfyWyiRwbMY{9jKf`D47*IH&#&i4%mogg*)Q2nLFqK}aH434f8{0pV|fpir?go=xkA zlPJT+re!g-v|Gc8uH!pR8??Mrs4${=zC$U9+8A!=fRJR(W^XVgYq~sJgW;=8*}jtW kHnudIAQO9=4<)~-ftbsQxpx@}_jeg=FmHkhaED0pFPkd%*#H0l delta 1840 zcmZXUYitx%6vyYxKH6=!1xp_beQkH?W83Yr1?tLDq@mbS9=lMmP!Q?b4s_|#S?^8* z1%V=!h+@)k8p9V!N`gWV5ymPcs2GhgMxjC)bwW@hF($>>QW0Vlyl1wB8t21r&YXMB zf6hJk(LVtF??Gx=YD$v8pDd$i>lEMF)Tc6S7E|u1z|r42La&p`yRD~paSygB!K z8L?B$7o37c$P*gjS;0MHB3SkHvo4RlrcG+$ zp66tx%^p)i9jzhOYLCb*Atfw##60*(R(h$(mU2nW9FA?`nJxosrq84n9vyBCDN;;> zXw1NUMd+|CoY}ywZeb)*NSS`5YRFoAqIk$!@txIn#5ZJhjF=3WNiQd#Zb&$z~DB*crpHpsR+(g-xhbME&p$)&ySr6OQ*|}rj)=aS$IV$M|1$beJ zl(dJigo8WE$ZjSaz+nDdIIQ;MuQb3G9CADkd(i4E1sQ!#Cmh5L&L((W9dKrwtW&ELPtKb59T#Kens*4oI%W{^u(&ICjOWudm(2O0@4&^_S8FfvYm`r}fZi=Q_ zU6y#6ZgMme_7bQ$nvoWa?W6A(v9feAoKts}-U7ISTihSQQ7kMEa=Wv95U#4Vo{Y@c ztgT!$^=&fWA)F!f;*rW6*o^~~B|P~?r3Pj_;tYP|bHg2V*moVc+!yn_W?k+)-k;}y zLs;N1%ZLY(%2~pB!Z{52Yv2wZ_x}p-quo;|J`iwV{!4j%eAFefM@<@EOT9^5xUR}i zk$qK?`E%0IbHSh%E?6xl>pwb8?lZW5;RW-jWbVO5)m0P4_Eh_M@W<5+hP`^+R}}Fz zM}Sc>UlDyv>N_byWBLI|2rClfCxC^?rI)5}i9t$9n6%eu{WNon+}WYTv_x7$IykJ0 z(nvp+z)@tU2YVOKfi(5A#gYiuu(YnsOh47KvDcZ7a$N!xsoU#zLh6s?HA#%gEWm!k z2TSUq9P8_QpbszC2Q%gXS2gjNZsGexEAw)T4dd*k&2R~EY0+|h5_a+y5FCVJ!kdI+ z1bw~qN$LG6BHtWB2|;g#zQKP()3UxP{5l&m2Cy1WNz_@2%Xi zfTA^1l!ZH#aS>8VC8W@hWiykvZQ2};NX)?d!B4>C<9~Wp4b>P(G-B*#KfP zWrns%+hu-42G?Zp4gAZRQ!^e_Je_`FlEg z^ Path | None: - """Return the tasks directory. Checks both standard locations.""" - candidates = [ - project_root / ".automaton" / "tasks", - project_root / "tasks", - ] + from ..core.scope import detect_scope + _, scope = detect_scope() + # Framework mode: tasks live inside .automaton/ + # Project mode: tasks live at project root, .automaton/tasks/ may be a symlink + if scope == "framework": + candidates = [ + project_root / ".automaton" / "tasks", + project_root / "tasks", + ] + else: + candidates = [ + project_root / "tasks", + project_root / ".automaton" / "tasks", + ] for p in candidates: if p.exists() and p.is_dir(): return p diff --git a/prompts/orchestrate.md b/prompts/orchestrate.md index 2b4a653..657aca4 100644 --- a/prompts/orchestrate.md +++ b/prompts/orchestrate.md @@ -19,7 +19,7 @@ Specifically: 7. {project}/.automaton/extensions/contracts/*.md — Additive extensions loaded after global contracts 8. ~/.automaton/scripts/*.sh — Always from global framework 9. {project}/.automaton/extensions/scripts/*.sh — Additive extensions loaded before global scripts (pre-processing) -10. Any existing files under {project}/tasks/ +10. {project}/tasks/ — Project tasks (project mode) or ~/.automaton/tasks/ (framework mode) ## VRAM Detection @@ -201,7 +201,10 @@ If the user says "orchestrate" or "continue" with no new task description, the O #### New tasks from user input If {task-description} contains a description for a NEW task, the Orchestrator MUST: 1. Generate a kebab-case task name from the description (e.g., "add user auth" → `add-user-auth`) -2. Create the task folder: `{project}/tasks/{task-name}/` (empty — no artifact files) +2. Create the task folder. Task location depends on scope: + - **Framework mode** (inside ~/.automaton/): `~/.automaton/tasks/{task-name}/` + - **Project mode** (in a user project): `{project}/tasks/{task-name}/` + The dashboard reads from both locations automatically. 3. **Immediately drive it to completion** using the auto-execution loop Note: `IMPLEMENTATION.md` is the artifact produced by the implementation phase, not the Orchestrator. Do not pre-create it. **Do not create an empty `IMPLEMENTATION.md` for new tasks** — this is inconsistent with the Orchestrator's own rule and can confuse the Research phase. @@ -237,7 +240,9 @@ In manual mode, the Orchestrator only **reports** the current state and the next ## State Determination -Examine the tasks/ directory and determine the state of each task folder. Check from the most advanced state backward. **Important**: Always check that artifacts are non-empty before considering them as indicators of task state. +Examine the tasks/ directory and determine the state of each task folder. The tasks directory is: +- **Framework mode**: `~/.automaton/tasks/` +- **Project mode**: `{project}/tasks/` Check from the most advanced state backward. **Important**: Always check that artifacts are non-empty before considering them as indicators of task state. 1. Has `VERDICT.md` with `PASS` (non-empty) → **Complete** 2. Has `VERDICT.md` with `NEEDS_REVIEW` or `FAIL` (non-empty) → **Human Intervention** diff --git a/scripts/migrate-project.sh b/scripts/migrate-project.sh index 06d2292..7554bb7 100755 --- a/scripts/migrate-project.sh +++ b/scripts/migrate-project.sh @@ -107,6 +107,18 @@ while IFS= read -r -d '' project_file; do fi done < <(find "$PROJECT_AUTOMATON" -maxdepth 1 -type f -name "*.md" -o -name "*.sh" -print0 2>/dev/null || true) +# Task directory — old model stored tasks in .automaton/tasks/, new model uses tasks/ +OLD_TASKS="$PROJECT_AUTOMATON/tasks" +NEW_TASKS="$PROJECT_DIR/tasks" +if [ -d "$OLD_TASKS" ] && [ ! -e "$NEW_TASKS" ]; then + echo " MOVING .automaton/tasks/ → tasks/ (tasks should be at project root)" + mv "$OLD_TASKS" "$NEW_TASKS" + MOVED+=(".automaton/tasks/ -> tasks/") +elif [ -d "$OLD_TASKS" ] && [ -d "$NEW_TASKS" ]; then + echo " NOTICE Both .automaton/tasks/ and tasks/ exist — keeping both" + KEPT+=(".automaton/tasks/ and tasks/") +fi + # Report echo "" echo "=== Migration Summary ==="