@chinhae/atw-cli 0.3.6 → 0.5.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/README.md +191 -17
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +25 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +154 -17
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mode.d.ts +21 -0
- package/dist/commands/mode.d.ts.map +1 -0
- package/dist/commands/mode.js +401 -0
- package/dist/commands/mode.js.map +1 -0
- package/dist/commands/update.d.ts +7 -0
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +20 -13
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/workflow.d.ts +17 -0
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +9 -3
- package/dist/commands/workflow.js.map +1 -1
- package/dist/configurators/claude.d.ts +3 -2
- package/dist/configurators/claude.d.ts.map +1 -1
- package/dist/configurators/claude.js +3 -3
- package/dist/configurators/claude.js.map +1 -1
- package/dist/configurators/codex.d.ts +4 -3
- package/dist/configurators/codex.d.ts.map +1 -1
- package/dist/configurators/codex.js +10 -10
- package/dist/configurators/codex.js.map +1 -1
- package/dist/configurators/index.d.ts +9 -3
- package/dist/configurators/index.d.ts.map +1 -1
- package/dist/configurators/index.js +95 -17
- package/dist/configurators/index.js.map +1 -1
- package/dist/configurators/shared.d.ts +13 -0
- package/dist/configurators/shared.d.ts.map +1 -1
- package/dist/configurators/shared.js +25 -0
- package/dist/configurators/shared.js.map +1 -1
- package/dist/configurators/workflow.d.ts +15 -1
- package/dist/configurators/workflow.d.ts.map +1 -1
- package/dist/configurators/workflow.js +23 -5
- package/dist/configurators/workflow.js.map +1 -1
- package/dist/configurators/zcode.d.ts +1 -1
- package/dist/configurators/zcode.d.ts.map +1 -1
- package/dist/configurators/zcode.js +2 -2
- package/dist/configurators/zcode.js.map +1 -1
- package/dist/constants/paths.d.ts +4 -0
- package/dist/constants/paths.d.ts.map +1 -1
- package/dist/constants/paths.js +4 -0
- package/dist/constants/paths.js.map +1 -1
- package/dist/migrations/manifests/0.4.0.json +9 -0
- package/dist/migrations/manifests/0.5.0.json +9 -0
- package/dist/templates/atw/config.yaml +7 -6
- package/dist/templates/atw/index.d.ts +10 -1
- package/dist/templates/atw/index.d.ts.map +1 -1
- package/dist/templates/atw/index.js +11 -1
- package/dist/templates/atw/index.js.map +1 -1
- package/dist/templates/atw/scripts/add_session.py +34 -13
- package/dist/templates/atw/scripts/common/active_task.py +2 -2
- package/dist/templates/atw/scripts/common/config.py +13 -0
- package/dist/templates/atw/scripts/common/developer.py +15 -4
- package/dist/templates/atw/scripts/common/noob_mode.py +35 -15
- package/dist/templates/atw/scripts/common/packages_context.py +16 -3
- package/dist/templates/atw/scripts/common/session_context.py +77 -19
- package/dist/templates/atw/scripts/common/task_store.py +78 -27
- package/dist/templates/atw/scripts/noob_mode.py +16 -4
- package/dist/templates/atw/scripts/task.py +99 -38
- package/dist/templates/atw/workflow-general.md +554 -0
- package/dist/templates/atw/workflow.md +49 -19
- package/dist/templates/codex/hooks/session-start.py +69 -18
- package/dist/templates/common/bundled-skills/atw-implement/SKILL.md +8 -0
- package/dist/templates/common/bundled-skills/atw-implement-all/SKILL.md +93 -0
- package/dist/templates/common/bundled-skills/atw-implement-all/agents/openai.yaml +5 -0
- package/dist/templates/common/bundled-skills/atw-init-repo/references/issue-tracker-atw-local.md +3 -1
- package/dist/templates/common/bundled-skills/atw-init-repo/references/issue-tracker-atw.md +3 -1
- package/dist/templates/common/bundled-skills/atw-noob-mode/SKILL.md +7 -5
- package/dist/templates/common/bundled-skills/atw-tickets/SKILL.md +2 -0
- package/dist/templates/common/commands/continue.md +1 -1
- package/dist/templates/common/commands/start.md +43 -0
- package/dist/templates/copilot/hooks/session-start.py +69 -18
- package/dist/templates/dsh/DSH.md +43 -0
- package/dist/templates/markdown/agents.md +11 -0
- package/dist/templates/markdown/index.d.ts +9 -0
- package/dist/templates/markdown/index.d.ts.map +1 -1
- package/dist/templates/markdown/index.js +14 -1
- package/dist/templates/markdown/index.js.map +1 -1
- package/dist/templates/markdown/spec/conventions.md.txt +13 -0
- package/dist/templates/opencode/lib/atw-context.js +19 -0
- package/dist/templates/opencode/lib/session-utils.js +79 -24
- package/dist/templates/opencode/plugins/inject-workflow-state.js +18 -8
- package/dist/templates/pi/extensions/atw/index.ts.txt +20 -9
- package/dist/templates/shared-hooks/inject-shell-session-context.py +3 -3
- package/dist/templates/shared-hooks/inject-workflow-state.py +23 -4
- package/dist/templates/shared-hooks/session-start.py +70 -22
- package/dist/templates/snow/SNOW.md +31 -1
- package/dist/templates/snow/hooks/write-atw-context.py +64 -0
- package/dist/utils/manifest-prune.d.ts +2 -1
- package/dist/utils/manifest-prune.d.ts.map +1 -1
- package/dist/utils/manifest-prune.js +10 -7
- package/dist/utils/manifest-prune.js.map +1 -1
- package/dist/utils/optional-skills.d.ts.map +1 -1
- package/dist/utils/optional-skills.js +2 -1
- package/dist/utils/optional-skills.js.map +1 -1
- package/dist/utils/project-mode.d.ts +30 -0
- package/dist/utils/project-mode.d.ts.map +1 -0
- package/dist/utils/project-mode.js +86 -0
- package/dist/utils/project-mode.js.map +1 -0
- package/dist/utils/workflow-resolver.d.ts +9 -5
- package/dist/utils/workflow-resolver.d.ts.map +1 -1
- package/dist/utils/workflow-resolver.js +25 -11
- package/dist/utils/workflow-resolver.js.map +1 -1
- package/package.json +3 -3
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
No researched platform exports a session id into its shell tool's child
|
|
5
5
|
process, but every hook-capable one puts that id on hook stdin. So the hook
|
|
6
6
|
that fires just before a shell command writes a short-lived runtime ticket
|
|
7
|
-
whenever the pending command calls `task.py start/current/finish`, and the
|
|
7
|
+
whenever the pending command calls `task.py start/resume/current/finish`, and the
|
|
8
8
|
task script consumes it when it has no native session environment.
|
|
9
9
|
|
|
10
10
|
Registered on whichever pre-shell event the host provides — Cursor's
|
|
@@ -35,7 +35,7 @@ if callable(_stdin_reconfigure):
|
|
|
35
35
|
DIR_WORKFLOW = ".atw"
|
|
36
36
|
DIR_RUNTIME = ".runtime"
|
|
37
37
|
DIR_SHELL_TICKETS = "shell-tickets"
|
|
38
|
-
SESSION_SUBCOMMANDS = {"start", "current", "finish"}
|
|
38
|
+
SESSION_SUBCOMMANDS = {"start", "resume", "current", "finish"}
|
|
39
39
|
TICKET_TTL_SECONDS = 30
|
|
40
40
|
CONTEXT_IDENTITY_KEYS = (
|
|
41
41
|
"session_id",
|
|
@@ -177,7 +177,7 @@ def _extract_task_subcommands(command: str) -> list[dict[str, str]]:
|
|
|
177
177
|
if name not in SESSION_SUBCOMMANDS:
|
|
178
178
|
continue
|
|
179
179
|
item = {"name": name}
|
|
180
|
-
if name
|
|
180
|
+
if name in ("start", "resume") and index + 2 < len(tokens):
|
|
181
181
|
item["task_ref"] = tokens[index + 2]
|
|
182
182
|
subcommands.append(item)
|
|
183
183
|
return subcommands
|
|
@@ -328,13 +328,13 @@ def _codex_mode_banner(config: dict) -> str:
|
|
|
328
328
|
"context injection is preferred and child-side loading is the fallback. "
|
|
329
329
|
"Implementation is never dispatched on the per-ticket path: code is written inside /atw-implement "
|
|
330
330
|
"in the main session, which also coordinates, clarifies, updates specs, commits, and finishes. "
|
|
331
|
-
"Only a /atw-implement-spec run, started by the user, dispatches implementer sub-agents."
|
|
331
|
+
"Only a /atw-implement-spec or /atw-implement-all run, started by the user, dispatches implementer sub-agents."
|
|
332
332
|
)
|
|
333
333
|
else:
|
|
334
334
|
meaning = (
|
|
335
335
|
"inline: the main session also reviews directly; "
|
|
336
336
|
"do not dispatch any ATW sub-agent. Implementation is in /atw-implement; "
|
|
337
|
-
"/atw-implement-spec
|
|
337
|
+
"/atw-implement-spec and /atw-implement-all need sub-agents and are unavailable in this mode."
|
|
338
338
|
)
|
|
339
339
|
return f"<codex-mode>{meaning}</codex-mode>"
|
|
340
340
|
|
|
@@ -383,8 +383,24 @@ def build_breadcrumb(
|
|
|
383
383
|
return f"<workflow-state>\n{header}\n{body}\n</workflow-state>"
|
|
384
384
|
|
|
385
385
|
|
|
386
|
+
def _is_general_project(root: Path) -> bool:
|
|
387
|
+
"""Whether this is a `general` project, as `common.config` reads the mode.
|
|
388
|
+
|
|
389
|
+
An install whose scripts predate project modes is a dev project.
|
|
390
|
+
"""
|
|
391
|
+
scripts_dir = root / ".atw" / "scripts"
|
|
392
|
+
if str(scripts_dir) not in sys.path:
|
|
393
|
+
sys.path.insert(0, str(scripts_dir))
|
|
394
|
+
try:
|
|
395
|
+
from common.config import get_project_mode # type: ignore[import-not-found]
|
|
396
|
+
|
|
397
|
+
return get_project_mode(root) == "general"
|
|
398
|
+
except Exception:
|
|
399
|
+
return False
|
|
400
|
+
|
|
401
|
+
|
|
386
402
|
def _noob_mode_reminder(root: Path) -> str:
|
|
387
|
-
"""The `<noob-mode>` block
|
|
403
|
+
"""The `<noob-mode>` block while noob mode is on for this developer, else "".
|
|
388
404
|
|
|
389
405
|
Riding on the per-turn breadcrumb is the point of the feature: a skill
|
|
390
406
|
loaded once fades over a long conversation, this is said again every turn.
|
|
@@ -476,7 +492,10 @@ def main() -> int:
|
|
|
476
492
|
parts: list[str] = []
|
|
477
493
|
if task is None:
|
|
478
494
|
parts.append(CODEX_NO_TASK_BOOTSTRAP_NOTICE)
|
|
479
|
-
|
|
495
|
+
# The banner is about dispatching review sub-agents and the dev
|
|
496
|
+
# implement commands; a general project installs neither.
|
|
497
|
+
if not _is_general_project(root):
|
|
498
|
+
parts.append(_codex_mode_banner(config))
|
|
480
499
|
parts.append(breadcrumb)
|
|
481
500
|
breadcrumb = "\n\n".join(parts)
|
|
482
501
|
|
|
@@ -83,7 +83,7 @@ FIRST_REPLY_NOTICE = f"{_FIRST_REPLY_NOTICE_HEAD}\n{_FIRST_REPLY_NOTICE_TAIL}"
|
|
|
83
83
|
|
|
84
84
|
|
|
85
85
|
def _noob_mode_reminder(project_dir: Path) -> str:
|
|
86
|
-
"""The `<noob-mode>` block
|
|
86
|
+
"""The `<noob-mode>` block while noob mode is on for this developer, else "".
|
|
87
87
|
|
|
88
88
|
Platforms with a per-turn hook hear this again every turn; here it covers
|
|
89
89
|
the ones that only have SessionStart (Cursor) and the first reply of a
|
|
@@ -101,6 +101,24 @@ def _noob_mode_reminder(project_dir: Path) -> str:
|
|
|
101
101
|
return ""
|
|
102
102
|
|
|
103
103
|
|
|
104
|
+
def _conventions_context(project_dir: Path) -> str:
|
|
105
|
+
"""The `<conventions>` block of a `general` project, else "".
|
|
106
|
+
|
|
107
|
+
A general project has one flat conventions file instead of per-package,
|
|
108
|
+
per-layer guideline indexes. An install whose scripts predate the helper is
|
|
109
|
+
treated as a dev project.
|
|
110
|
+
"""
|
|
111
|
+
scripts_dir = project_dir / ".atw" / "scripts"
|
|
112
|
+
if str(scripts_dir) not in sys.path:
|
|
113
|
+
sys.path.insert(0, str(scripts_dir))
|
|
114
|
+
try:
|
|
115
|
+
from common.session_context import conventions_context # type: ignore[import-not-found]
|
|
116
|
+
|
|
117
|
+
return conventions_context(project_dir)
|
|
118
|
+
except Exception:
|
|
119
|
+
return ""
|
|
120
|
+
|
|
121
|
+
|
|
104
122
|
def _build_first_reply_notice(update_hint: str | None) -> str:
|
|
105
123
|
"""First-reply notice, carrying the ATW update reminder when there is one.
|
|
106
124
|
|
|
@@ -201,6 +219,9 @@ def _run_git(repo_root: Path, args: list[str]) -> str:
|
|
|
201
219
|
|
|
202
220
|
|
|
203
221
|
def _format_git_state(repo_root: Path) -> str:
|
|
222
|
+
# 普通文件夹没有分支,也谈不上干净:照实说,不编一个状态出来。
|
|
223
|
+
if _run_git(repo_root, ["rev-parse", "--is-inside-work-tree"]) != "true":
|
|
224
|
+
return "Git: not a git repository."
|
|
204
225
|
branch = _run_git(repo_root, ["branch", "--show-current"]) or "(detached)"
|
|
205
226
|
dirty_lines = [
|
|
206
227
|
line for line in _run_git(repo_root, ["status", "--porcelain"]).splitlines()
|
|
@@ -416,11 +437,21 @@ def _resolve_task_dir(atw_dir: Path, task_ref: str) -> Path:
|
|
|
416
437
|
return atw_dir / "tasks" / path_obj
|
|
417
438
|
|
|
418
439
|
|
|
419
|
-
def _get_task_status(atw_dir: Path, input_data: dict) -> str:
|
|
420
|
-
"""Return compact active-task status, artifact presence, and next action.
|
|
440
|
+
def _get_task_status(atw_dir: Path, input_data: dict, general: bool = False) -> str:
|
|
441
|
+
"""Return compact active-task status, artifact presence, and next action.
|
|
442
|
+
|
|
443
|
+
In a `general` project the AI decides on its own whether a request gets a
|
|
444
|
+
task, so the no-task line defers to the workflow instead of telling it to
|
|
445
|
+
ask first.
|
|
446
|
+
"""
|
|
421
447
|
active = _resolve_active_task(atw_dir, input_data)
|
|
422
448
|
|
|
423
449
|
if not active.task_path:
|
|
450
|
+
if general:
|
|
451
|
+
return (
|
|
452
|
+
"Status: NO ACTIVE TASK\n"
|
|
453
|
+
"Next-Action: Do what <atw-workflow> above says for a session with no current task."
|
|
454
|
+
)
|
|
424
455
|
return (
|
|
425
456
|
"Status: NO ACTIVE TASK\n"
|
|
426
457
|
"Next-Action: Classify the current turn before creating any ATW task. "
|
|
@@ -454,6 +485,15 @@ def _get_task_status(atw_dir: Path, input_data: dict) -> str:
|
|
|
454
485
|
present_line = ", ".join(present) if present else "(none)"
|
|
455
486
|
|
|
456
487
|
if task_status == "completed":
|
|
488
|
+
if general:
|
|
489
|
+
# A general task records no branch; without the switch the archive
|
|
490
|
+
# is refused in a repository that has a remote.
|
|
491
|
+
return (
|
|
492
|
+
f"Status: COMPLETED\nTask: {task_title}\n"
|
|
493
|
+
f"Present: {present_line}\n"
|
|
494
|
+
"Next-Action: The archive was interrupted — re-run "
|
|
495
|
+
"`task.py archive <task> --skip-branch-validation` to finish it."
|
|
496
|
+
)
|
|
457
497
|
return (
|
|
458
498
|
f"Status: COMPLETED\nTask: {task_title}\n"
|
|
459
499
|
f"Present: {present_line}\n"
|
|
@@ -824,7 +864,12 @@ def main():
|
|
|
824
864
|
|
|
825
865
|
output = StringIO()
|
|
826
866
|
|
|
827
|
-
|
|
867
|
+
# A general project keeps no guideline indexes — whatever a switch from dev
|
|
868
|
+
# left under `.atw/spec/` is not offered there.
|
|
869
|
+
conventions = _conventions_context(project_dir)
|
|
870
|
+
spec_index_paths = (
|
|
871
|
+
[] if conventions else _collect_spec_index_paths(atw_dir, allowed_pkgs)
|
|
872
|
+
)
|
|
828
873
|
|
|
829
874
|
output.write("""<session-context>
|
|
830
875
|
ATW compact SessionStart context. Use it to orient the session; load details on demand.
|
|
@@ -851,27 +896,30 @@ ATW compact SessionStart context. Use it to orient the session; load details on
|
|
|
851
896
|
output.write(_build_workflow_overview(atw_dir / "workflow.md"))
|
|
852
897
|
output.write("\n</atw-workflow>\n\n")
|
|
853
898
|
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
899
|
+
if conventions:
|
|
900
|
+
output.write(f"{conventions}\n\n")
|
|
901
|
+
else:
|
|
902
|
+
output.write("<guidelines>\n")
|
|
903
|
+
# D32/C23: same as `_get_task_status` — the injected order is jsonl then
|
|
904
|
+
# `prd.md`; `design.md` / `implement.md` are no longer materialized.
|
|
905
|
+
output.write(
|
|
906
|
+
"Task context order for implementation/check: jsonl entries -> `prd.md`.\n\n"
|
|
907
|
+
)
|
|
860
908
|
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
909
|
+
if spec_index_paths:
|
|
910
|
+
output.write("## Available indexes (read on demand)\n")
|
|
911
|
+
for p in spec_index_paths:
|
|
912
|
+
output.write(f"- {p}\n")
|
|
913
|
+
output.write("\n")
|
|
914
|
+
|
|
915
|
+
output.write(
|
|
916
|
+
"Discover more via: "
|
|
917
|
+
"`python3 ./.atw/scripts/get_context.py --mode packages`\n"
|
|
918
|
+
)
|
|
919
|
+
output.write("</guidelines>\n\n")
|
|
872
920
|
|
|
873
921
|
# Check task status and inject structured tag
|
|
874
|
-
task_status = _get_task_status(atw_dir, hook_input)
|
|
922
|
+
task_status = _get_task_status(atw_dir, hook_input, general=bool(conventions))
|
|
875
923
|
output.write(f"<task-status>\n{task_status}\n</task-status>\n\n")
|
|
876
924
|
|
|
877
925
|
output.write("""<ready>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# ATW on Snow CLI
|
|
2
2
|
|
|
3
|
+
{{^MODE_GENERAL}}
|
|
3
4
|
Snow is a **class-1** ATW host: auto context inject + project agent discovery +
|
|
4
5
|
`beforeSubAgentStart` prompt enrichment.
|
|
5
6
|
|
|
@@ -22,7 +23,7 @@ snow
|
|
|
22
23
|
In Snow:
|
|
23
24
|
|
|
24
25
|
1. Open a session in the project root — `onSessionStart` injects ATW context automatically.
|
|
25
|
-
2. Dispatch review (`atw-review`, project agent under `.snow/agents/`); implementation runs in the main session via `/atw-implement` (a `/atw-implement-spec` run dispatches its own implementers). Prefer prompt first line:
|
|
26
|
+
2. Dispatch review (`atw-review`, project agent under `.snow/agents/`); implementation runs in the main session via `/atw-implement` (a `/atw-implement-spec` or `/atw-implement-all` run dispatches its own implementers). Prefer prompt first line:
|
|
26
27
|
|
|
27
28
|
```text
|
|
28
29
|
Active task: .atw/tasks/<id>
|
|
@@ -38,6 +39,35 @@ Primary path: project agent discovery — no manual merge required. Do not use l
|
|
|
38
39
|
|
|
39
40
|
Context loading is class-1 hook inject (`beforeSubAgentStart` / session / user). Agents are **not** shipped with class-2 pull-based prelude text. Hooks already inject context; agents still re-read task artifacts for correctness.
|
|
40
41
|
|
|
42
|
+
{{/MODE_GENERAL}}
|
|
43
|
+
{{#MODE_GENERAL}}
|
|
44
|
+
Snow is a **class-1** ATW host: hooks inject ATW context into every session
|
|
45
|
+
and every message.
|
|
46
|
+
|
|
47
|
+
This project is in ATW's `general` mode, for work that is not code: you say
|
|
48
|
+
what you want in your own words, and the workflow in `.atw/workflow.md` has
|
|
49
|
+
the AI do the rest. There are no prompt commands to run and no project agents.
|
|
50
|
+
|
|
51
|
+
| Capability | Status |
|
|
52
|
+
| ------------------------------------------ | ---------------------------------------------------------------------------- |
|
|
53
|
+
| Skills (`.snow/skills/atw-*/SKILL.md`) | Works — the six skills of `general` mode |
|
|
54
|
+
| Context hooks (`.snow/hooks/`) | Inject model context via stdout JSON + write `.snow/log/atw-context.txt` |
|
|
55
|
+
| Prompt commands, project agents | None in `general` mode |
|
|
56
|
+
|
|
57
|
+
## Quick start
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
atw init --snow --mode general -u your-name
|
|
61
|
+
snow
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
In Snow:
|
|
65
|
+
|
|
66
|
+
1. Open a session in the project root — `onSessionStart` injects ATW context automatically, including what `.atw/spec/conventions.md` says and, unless you turned it off, the plain-language reminder.
|
|
67
|
+
2. Say what you want done. The AI keeps the task record, shows you what it wrote down before it starts, checks the result with you, and files it when you accept.
|
|
68
|
+
3. Debug injects: set `SNOW_DEBUG_HOOKS=1` and inspect `.snow/log/hooks-inject.txt`.
|
|
69
|
+
|
|
70
|
+
{{/MODE_GENERAL}}
|
|
41
71
|
## Tool names (Snow-native)
|
|
42
72
|
|
|
43
73
|
- `filesystem-read` / `filesystem-create` / `filesystem-replaceedit` / `filesystem-edit`
|
|
@@ -434,6 +434,40 @@ def _workflow_phase_summary(
|
|
|
434
434
|
return lines
|
|
435
435
|
|
|
436
436
|
|
|
437
|
+
def _conventions_context(repo: Path) -> str:
|
|
438
|
+
"""The `<conventions>` block of a `general` project, else "".
|
|
439
|
+
|
|
440
|
+
Same entry the shared session-start hook uses. An install whose scripts
|
|
441
|
+
predate the helper is treated as a dev project.
|
|
442
|
+
"""
|
|
443
|
+
scripts_dir = repo / ".atw" / "scripts"
|
|
444
|
+
if str(scripts_dir) not in sys.path:
|
|
445
|
+
sys.path.insert(0, str(scripts_dir))
|
|
446
|
+
try:
|
|
447
|
+
from common.session_context import conventions_context # type: ignore[import-not-found]
|
|
448
|
+
|
|
449
|
+
return conventions_context(repo)
|
|
450
|
+
except Exception:
|
|
451
|
+
return ""
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
def _noob_mode_reminder(repo: Path) -> str:
|
|
455
|
+
"""The `<noob-mode>` block while noob mode is on for this developer, else "".
|
|
456
|
+
|
|
457
|
+
Same entry the shared hooks use. An install whose scripts predate the
|
|
458
|
+
helper simply has no noob mode.
|
|
459
|
+
"""
|
|
460
|
+
scripts_dir = repo / ".atw" / "scripts"
|
|
461
|
+
if str(scripts_dir) not in sys.path:
|
|
462
|
+
sys.path.insert(0, str(scripts_dir))
|
|
463
|
+
try:
|
|
464
|
+
from common.noob_mode import noob_mode_reminder # type: ignore[import-not-found]
|
|
465
|
+
|
|
466
|
+
return noob_mode_reminder(repo)
|
|
467
|
+
except Exception:
|
|
468
|
+
return ""
|
|
469
|
+
|
|
470
|
+
|
|
437
471
|
def build_context(
|
|
438
472
|
repo: Path,
|
|
439
473
|
*,
|
|
@@ -468,6 +502,20 @@ def build_context(
|
|
|
468
502
|
lines.append(f"Dispatch prompt (truncated): {p}")
|
|
469
503
|
lines.append("")
|
|
470
504
|
|
|
505
|
+
# A general project has no session-start entry on Snow (the hooks replace
|
|
506
|
+
# it), so its conventions and the plain-language reminder reach the main
|
|
507
|
+
# session here or not at all. A dev project's context stays as it was,
|
|
508
|
+
# which on Snow has never included the plain-language reminder.
|
|
509
|
+
conventions = _conventions_context(repo) if mode != "subagent" else ""
|
|
510
|
+
general = bool(conventions)
|
|
511
|
+
if general:
|
|
512
|
+
# Ahead of the task state and the excerpts, so the byte limit can never
|
|
513
|
+
# cut it off; said again on every user message, like the per-turn hook
|
|
514
|
+
# of other platforms.
|
|
515
|
+
noob_mode = _noob_mode_reminder(repo)
|
|
516
|
+
if noob_mode:
|
|
517
|
+
lines.extend(["", noob_mode, ""])
|
|
518
|
+
|
|
471
519
|
task_py = repo / ".atw" / "scripts" / "task.py"
|
|
472
520
|
current = ""
|
|
473
521
|
task_dir: Path | None = None
|
|
@@ -492,6 +540,11 @@ def build_context(
|
|
|
492
540
|
lines.append("(could not resolve active task directory from task.py output)")
|
|
493
541
|
lines.append("")
|
|
494
542
|
|
|
543
|
+
if general and not compact:
|
|
544
|
+
# Ahead of the excerpts below: when the file is long, they are what the
|
|
545
|
+
# byte limit drops, and the block's first line still says where to read.
|
|
546
|
+
lines.extend([conventions, ""])
|
|
547
|
+
|
|
495
548
|
if not compact:
|
|
496
549
|
lines.extend(_workflow_phase_summary(repo, stdin_ctx))
|
|
497
550
|
|
|
@@ -546,6 +599,17 @@ def build_context(
|
|
|
546
599
|
"",
|
|
547
600
|
]
|
|
548
601
|
)
|
|
602
|
+
elif general:
|
|
603
|
+
# No sub-agents and no start entry are installed in a general project.
|
|
604
|
+
lines.extend(
|
|
605
|
+
[
|
|
606
|
+
"## Main-session checklist",
|
|
607
|
+
"1. Session/user hooks auto-inject ATW context."
|
|
608
|
+
if not compact
|
|
609
|
+
else "1. Compact inject — full context also at `.snow/log/atw-context.txt`.",
|
|
610
|
+
"",
|
|
611
|
+
]
|
|
612
|
+
)
|
|
549
613
|
else:
|
|
550
614
|
lines.extend(
|
|
551
615
|
[
|
|
@@ -49,7 +49,8 @@ export interface PruneOptions {
|
|
|
49
49
|
/**
|
|
50
50
|
* Walk the manifest and split it into kept vs pruned entries.
|
|
51
51
|
*
|
|
52
|
-
* @param cwd Project root — used to
|
|
52
|
+
* @param cwd Project root — used to read the project's mode and to save the
|
|
53
|
+
* rewritten manifest.
|
|
53
54
|
* @param configuredPlatforms Output of `getConfiguredPlatforms(cwd)` — caller
|
|
54
55
|
* resolves this so we don't have to re-walk the filesystem.
|
|
55
56
|
* @param hashes Already-loaded manifest contents. Passing it in (vs reading
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest-prune.d.ts","sourceRoot":"","sources":["../../src/utils/manifest-prune.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;
|
|
1
|
+
{"version":3,"file":"manifest-prune.d.ts","sourceRoot":"","sources":["../../src/utils/manifest-prune.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAYH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC1B,0DAA0D;IAC1D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,6EAA6E;IAC7E,MAAM,EAAE,cAAc,CAAC;CACxB;AAsDD,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,EACX,mBAAmB,EAAE,SAAS,MAAM,EAAE,EACtC,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,YAAiB,GACzB,WAAW,CAmCb"}
|
|
@@ -36,19 +36,22 @@ import { collectPlatformTemplates } from "../configurators/index.js";
|
|
|
36
36
|
import { FILE_NAMES } from "../constants/paths.js";
|
|
37
37
|
import { getAllMigrations } from "../migrations/index.js";
|
|
38
38
|
import { saveHashes } from "./template-hash.js";
|
|
39
|
+
import { loadProjectMode } from "./project-mode.js";
|
|
39
40
|
import { toPosix } from "./posix.js";
|
|
40
41
|
import { ATW_BLOCK_END, ATW_BLOCK_START } from "./managed-paths.js";
|
|
41
42
|
/**
|
|
42
43
|
* Compute the union of "what atw writes" across:
|
|
43
|
-
* - every configured platform's collectTemplates() output
|
|
44
|
+
* - every configured platform's collectTemplates() output, under the
|
|
45
|
+
* project's mode
|
|
44
46
|
* - root-level AGENTS.md when it still carries ATW managed-block markers
|
|
45
47
|
* - every migration manifest's from/to path (preserve so legitimate
|
|
46
48
|
* pending migrations can find their source/target)
|
|
47
49
|
*/
|
|
48
|
-
function buildKnownKeys(configuredPlatforms) {
|
|
50
|
+
function buildKnownKeys(cwd, configuredPlatforms) {
|
|
49
51
|
const known = new Set();
|
|
52
|
+
const mode = loadProjectMode(cwd);
|
|
50
53
|
for (const id of configuredPlatforms) {
|
|
51
|
-
const templates = collectPlatformTemplates(id);
|
|
54
|
+
const templates = collectPlatformTemplates(id, mode);
|
|
52
55
|
if (!templates)
|
|
53
56
|
continue;
|
|
54
57
|
for (const key of templates.keys()) {
|
|
@@ -80,8 +83,7 @@ function shouldKeepAgentsMd(cwd) {
|
|
|
80
83
|
}
|
|
81
84
|
try {
|
|
82
85
|
const content = fs.readFileSync(fullPath, "utf-8");
|
|
83
|
-
return
|
|
84
|
-
content.includes(ATW_BLOCK_END));
|
|
86
|
+
return content.includes(ATW_BLOCK_START) && content.includes(ATW_BLOCK_END);
|
|
85
87
|
}
|
|
86
88
|
catch {
|
|
87
89
|
return true;
|
|
@@ -90,7 +92,8 @@ function shouldKeepAgentsMd(cwd) {
|
|
|
90
92
|
/**
|
|
91
93
|
* Walk the manifest and split it into kept vs pruned entries.
|
|
92
94
|
*
|
|
93
|
-
* @param cwd Project root — used to
|
|
95
|
+
* @param cwd Project root — used to read the project's mode and to save the
|
|
96
|
+
* rewritten manifest.
|
|
94
97
|
* @param configuredPlatforms Output of `getConfiguredPlatforms(cwd)` — caller
|
|
95
98
|
* resolves this so we don't have to re-walk the filesystem.
|
|
96
99
|
* @param hashes Already-loaded manifest contents. Passing it in (vs reading
|
|
@@ -100,7 +103,7 @@ function shouldKeepAgentsMd(cwd) {
|
|
|
100
103
|
*/
|
|
101
104
|
export function pruneOrphanManifestKeys(cwd, configuredPlatforms, hashes, options = {}) {
|
|
102
105
|
const persist = options.persist ?? true;
|
|
103
|
-
const known = buildKnownKeys(configuredPlatforms);
|
|
106
|
+
const known = buildKnownKeys(cwd, configuredPlatforms);
|
|
104
107
|
const pruned = [];
|
|
105
108
|
const kept = {};
|
|
106
109
|
for (const [rawKey, value] of Object.entries(hashes)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest-prune.js","sourceRoot":"","sources":["../../src/utils/manifest-prune.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAWpE
|
|
1
|
+
{"version":3,"file":"manifest-prune.js","sourceRoot":"","sources":["../../src/utils/manifest-prune.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optional-skills.d.ts","sourceRoot":"","sources":["../../src/utils/optional-skills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"optional-skills.d.ts","sourceRoot":"","sources":["../../src/utils/optional-skills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAcH,eAAO,MAAM,yBAAyB,wEACiC,CAAC;AAcxE,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,WAAW,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC;AAED,2EAA2E;AAC3E,MAAM,MAAM,mBAAmB,GAAG,MAAM,CACtC,MAAM,EACN;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CACrC,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,kFAAkF;IAClF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sEAAsE;IACtE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA0CD;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAgBpE;AAUD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,CAuBxE;AAYD;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAUnE;AAqBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAuB,qBAAqB,CAC1C,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,cAAc,CAAC,mBAAmB,CAAC,CAoFrC"}
|
|
@@ -22,6 +22,7 @@ import path from "node:path";
|
|
|
22
22
|
import { downloadTemplate } from "giget";
|
|
23
23
|
import { getSkillRoots, PLATFORM_IDS } from "../configurators/index.js";
|
|
24
24
|
import { DIR_NAMES } from "../constants/paths.js";
|
|
25
|
+
import { loadProjectMode } from "./project-mode.js";
|
|
25
26
|
import { TIMEOUTS, withTimeout } from "./template-fetcher.js";
|
|
26
27
|
const OPTIONAL_SKILLS_REPO = "gh:LFT-OXY/oxy-Tools";
|
|
27
28
|
export const OPTIONAL_SKILLS_INDEX_URL = "https://raw.githubusercontent.com/LFT-OXY/oxy-Tools/main/index.json";
|
|
@@ -114,7 +115,7 @@ export function loadOptionalSkillRecord(cwd) {
|
|
|
114
115
|
}
|
|
115
116
|
if (!isRecord(raw) || !isRecord(raw.skills))
|
|
116
117
|
return {};
|
|
117
|
-
const knownRoots = new Set(getSkillRoots(PLATFORM_IDS));
|
|
118
|
+
const knownRoots = new Set(getSkillRoots(PLATFORM_IDS, loadProjectMode(cwd)));
|
|
118
119
|
const record = {};
|
|
119
120
|
for (const [name, entry] of Object.entries(raw.skills)) {
|
|
120
121
|
if (!SKILL_NAME_RE.test(name) || !isRecord(entry))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optional-skills.js","sourceRoot":"","sources":["../../src/utils/optional-skills.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"optional-skills.js","sourceRoot":"","sources":["../../src/utils/optional-skills.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 项目模式:项目级、随仓库提交的设置,记在 `.atw/config.yaml` 的顶层 `mode:`。
|
|
3
|
+
*
|
|
4
|
+
* 读取它的逻辑只有这一份。
|
|
5
|
+
*/
|
|
6
|
+
export declare const PROJECT_MODES: readonly ["dev", "general"];
|
|
7
|
+
export type ProjectMode = (typeof PROJECT_MODES)[number];
|
|
8
|
+
/** 配置里没有模式项(或为空)时的取值——现有项目不需要迁移。 */
|
|
9
|
+
export declare const DEFAULT_PROJECT_MODE: ProjectMode;
|
|
10
|
+
export declare function isProjectMode(value: string): value is ProjectMode;
|
|
11
|
+
/**
|
|
12
|
+
* 从 `.atw/config.yaml` 读取项目模式。
|
|
13
|
+
*
|
|
14
|
+
* 文件不存在、没有 `mode:`、或值为空,都是 {@link DEFAULT_PROJECT_MODE}。
|
|
15
|
+
* 其他任何值直接抛错:模式决定 ATW 安装和删除哪些文件,替用户猜一个会按错误的
|
|
16
|
+
* 文件集合去管理项目。
|
|
17
|
+
*/
|
|
18
|
+
export declare function loadProjectMode(cwd: string): ProjectMode;
|
|
19
|
+
/**
|
|
20
|
+
* 把模式记进 `.atw/config.yaml`。
|
|
21
|
+
*
|
|
22
|
+
* 还没有 `mode:` 项时追加在文件末尾。追加出来的形状与 `atw update` 带过本地
|
|
23
|
+
* 顶层键时拼出的结果逐字节相同(模板、一个空行、注释加键),所以之后的升级不会
|
|
24
|
+
* 改动这个文件。
|
|
25
|
+
*
|
|
26
|
+
* 已有 `mode:` 项时:回到默认模式、而那一项正是当初追加在末尾的那一段,就把那
|
|
27
|
+
* 一段去掉,文件回到没记过模式的样子;其余情况只改那一行的值。
|
|
28
|
+
*/
|
|
29
|
+
export declare function recordProjectMode(cwd: string, mode: ProjectMode): void;
|
|
30
|
+
//# sourceMappingURL=project-mode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-mode.d.ts","sourceRoot":"","sources":["../../src/utils/project-mode.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,eAAO,MAAM,aAAa,6BAA8B,CAAC;AAEzD,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,oCAAoC;AACpC,eAAO,MAAM,oBAAoB,EAAE,WAAmB,CAAC;AAIvD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,WAAW,CAEjE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAyBxD;AAYD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CAItE"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 项目模式:项目级、随仓库提交的设置,记在 `.atw/config.yaml` 的顶层 `mode:`。
|
|
3
|
+
*
|
|
4
|
+
* 读取它的逻辑只有这一份。
|
|
5
|
+
*/
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { DIR_NAMES } from "../constants/paths.js";
|
|
9
|
+
import { writeFileAtomic } from "./atomic-write.js";
|
|
10
|
+
export const PROJECT_MODES = ["dev", "general"];
|
|
11
|
+
/** 配置里没有模式项(或为空)时的取值——现有项目不需要迁移。 */
|
|
12
|
+
export const DEFAULT_PROJECT_MODE = "dev";
|
|
13
|
+
const CONFIG_RELATIVE_PATH = `${DIR_NAMES.WORKFLOW}/config.yaml`;
|
|
14
|
+
export function isProjectMode(value) {
|
|
15
|
+
return PROJECT_MODES.includes(value);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 从 `.atw/config.yaml` 读取项目模式。
|
|
19
|
+
*
|
|
20
|
+
* 文件不存在、没有 `mode:`、或值为空,都是 {@link DEFAULT_PROJECT_MODE}。
|
|
21
|
+
* 其他任何值直接抛错:模式决定 ATW 安装和删除哪些文件,替用户猜一个会按错误的
|
|
22
|
+
* 文件集合去管理项目。
|
|
23
|
+
*/
|
|
24
|
+
export function loadProjectMode(cwd) {
|
|
25
|
+
let content;
|
|
26
|
+
try {
|
|
27
|
+
content = fs.readFileSync(path.join(cwd, CONFIG_RELATIVE_PATH), "utf-8");
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return DEFAULT_PROJECT_MODE;
|
|
31
|
+
}
|
|
32
|
+
for (const line of content.split("\n")) {
|
|
33
|
+
const match = /^mode:(.*)$/.exec(line.trimEnd());
|
|
34
|
+
if (!match)
|
|
35
|
+
continue;
|
|
36
|
+
// 行内注释以"行首或空白后的 #"起头,与脚本侧 atw_config.py 的约定一致。
|
|
37
|
+
const value = match[1]
|
|
38
|
+
.replace(/(^|\s)#.*$/, "")
|
|
39
|
+
.trim()
|
|
40
|
+
.replace(/^(['"])(.*)\1$/, "$2");
|
|
41
|
+
if (value === "")
|
|
42
|
+
return DEFAULT_PROJECT_MODE;
|
|
43
|
+
if (isProjectMode(value))
|
|
44
|
+
return value;
|
|
45
|
+
throw new Error(`Invalid mode "${value}" in ${CONFIG_RELATIVE_PATH}: expected ${PROJECT_MODES.map((mode) => `"${mode}"`).join(" or ")}.`);
|
|
46
|
+
}
|
|
47
|
+
return DEFAULT_PROJECT_MODE;
|
|
48
|
+
}
|
|
49
|
+
/** 记模式时追加在配置末尾的那一段:一个空行、两行注释、`mode:` 项。 */
|
|
50
|
+
function appendedModeBlock(mode) {
|
|
51
|
+
return ("\n\n" +
|
|
52
|
+
'# What this project is for: "dev" (writing code, the default) or\n' +
|
|
53
|
+
'# "general" (other work: writing, research, organizing material, planning).\n' +
|
|
54
|
+
`mode: ${mode}\n`);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 把模式记进 `.atw/config.yaml`。
|
|
58
|
+
*
|
|
59
|
+
* 还没有 `mode:` 项时追加在文件末尾。追加出来的形状与 `atw update` 带过本地
|
|
60
|
+
* 顶层键时拼出的结果逐字节相同(模板、一个空行、注释加键),所以之后的升级不会
|
|
61
|
+
* 改动这个文件。
|
|
62
|
+
*
|
|
63
|
+
* 已有 `mode:` 项时:回到默认模式、而那一项正是当初追加在末尾的那一段,就把那
|
|
64
|
+
* 一段去掉,文件回到没记过模式的样子;其余情况只改那一行的值。
|
|
65
|
+
*/
|
|
66
|
+
export function recordProjectMode(cwd, mode) {
|
|
67
|
+
const configPath = path.join(cwd, CONFIG_RELATIVE_PATH);
|
|
68
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
69
|
+
writeFileAtomic(configPath, withProjectMode(content, mode));
|
|
70
|
+
}
|
|
71
|
+
function withProjectMode(content, mode) {
|
|
72
|
+
if (!/^mode:/m.test(content)) {
|
|
73
|
+
return `${content.trimEnd()}${appendedModeBlock(mode)}`;
|
|
74
|
+
}
|
|
75
|
+
if (mode === DEFAULT_PROJECT_MODE) {
|
|
76
|
+
for (const recorded of PROJECT_MODES) {
|
|
77
|
+
const block = appendedModeBlock(recorded);
|
|
78
|
+
if (content.endsWith(block)) {
|
|
79
|
+
return `${content.slice(0, -block.length)}\n`;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// 行尾的注释(空白后的 #)留着。
|
|
84
|
+
return content.replace(/^mode:.*?(\s+#.*)?$/m, `mode: ${mode}$1`);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=project-mode.js.map
|