aes-cli 0.4.2__tar.gz → 0.5.0__tar.gz
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.
- {aes_cli-0.4.2 → aes_cli-0.5.0}/PKG-INFO +10 -1
- {aes_cli-0.4.2 → aes_cli-0.5.0}/README.md +9 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/__init__.py +1 -1
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/commands/init.py +4 -1
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/frameworks.py +6 -1
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/agent.yaml.jinja +10 -2
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/instructions.md.jinja +4 -4
- aes_cli-0.5.0/aes/scaffold/ja/memory_command.md.jinja +99 -0
- aes_cli-0.5.0/aes/scaffold/memory_command.md.jinja +99 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/permissions.yaml.jinja +2 -2
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/skill.yaml.jinja +2 -2
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/workflow.yaml.jinja +1 -1
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/targets/claude.py +9 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes_cli.egg-info/PKG-INFO +10 -1
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes_cli.egg-info/SOURCES.txt +2 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/pyproject.toml +1 -1
- {aes_cli-0.4.2 → aes_cli-0.5.0}/tests/test_init.py +15 -6
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/__main__.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/analyzer.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/commands/__init__.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/commands/inspect.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/commands/install.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/commands/publish.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/commands/search.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/commands/status.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/commands/sync.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/commands/validate.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/config.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/domains.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/global_config.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/i18n/__init__.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/i18n/_messages.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/i18n/domains_ja.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/i18n/ja.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/mcp_server.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/registry.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/agentignore.jinja +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/ja/instructions.md.jinja +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/ja/operations.md.jinja +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/ja/orchestrator.md.jinja +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/ja/setup.md.jinja +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/ja/skill.md.jinja +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/ja/workflow_command.md.jinja +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/local.example.yaml.jinja +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/local.yaml.jinja +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/operations.md.jinja +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/orchestrator.md.jinja +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/setup.md.jinja +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/skill.md.jinja +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/scaffold/workflow_command.md.jinja +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/schemas/agent.schema.json +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/schemas/permissions.schema.json +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/schemas/registry.schema.json +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/schemas/skill.schema.json +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/schemas/workflow.schema.json +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/targets/__init__.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/targets/_base.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/targets/_composer.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/targets/copilot.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/targets/cursor.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/targets/windsurf.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes/validator.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes_cli.egg-info/dependency_links.txt +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes_cli.egg-info/entry_points.txt +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes_cli.egg-info/requires.txt +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/aes_cli.egg-info/top_level.txt +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/setup.cfg +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/tests/test_analyzer.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/tests/test_frameworks.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/tests/test_inspect.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/tests/test_install.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/tests/test_mcp_server.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/tests/test_publish.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/tests/test_registry.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/tests/test_search.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/tests/test_status.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/tests/test_sync.py +0 -0
- {aes_cli-0.4.2 → aes_cli-0.5.0}/tests/test_validate.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aes-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: CLI tool for the Agentic Engineering Standard
|
|
5
5
|
Author: Hiro
|
|
6
6
|
License: Apache-2.0
|
|
@@ -46,6 +46,15 @@ pipx install aes-cli
|
|
|
46
46
|
pip install aes-cli
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
### Upgrading
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pipx upgrade aes-cli # if installed with pipx
|
|
53
|
+
pip install --upgrade aes-cli # if installed with pip
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
After upgrading, run `aes sync` in your project to regenerate tool-specific configs with the new version's sync logic. Your `.agent/` source files are not modified by the upgrade.
|
|
57
|
+
|
|
49
58
|
Requires Python 3.10+.
|
|
50
59
|
|
|
51
60
|
## Quick Start
|
|
@@ -13,6 +13,15 @@ pipx install aes-cli
|
|
|
13
13
|
pip install aes-cli
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
+
### Upgrading
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pipx upgrade aes-cli # if installed with pipx
|
|
20
|
+
pip install --upgrade aes-cli # if installed with pip
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
After upgrading, run `aes sync` in your project to regenerate tool-specific configs with the new version's sync logic. Your `.agent/` source files are not modified by the upgrade.
|
|
24
|
+
|
|
16
25
|
Requires Python 3.10+.
|
|
17
26
|
|
|
18
27
|
## Quick Start
|
|
@@ -427,6 +427,7 @@ def _print_post_init_summary(
|
|
|
427
427
|
|
|
428
428
|
cmd_branch = tree.add("commands/")
|
|
429
429
|
cmd_branch.add("setup.md")
|
|
430
|
+
cmd_branch.add("memory.md [dim]/memory[/]")
|
|
430
431
|
if isinstance(domain_config, DomainConfig) and domain_config.workflow_commands:
|
|
431
432
|
for cmd_def in domain_config.workflow_commands:
|
|
432
433
|
cmd_branch.add(f"{cmd_def.id}.md [dim]{cmd_def.trigger}[/]")
|
|
@@ -702,10 +703,12 @@ def init_cmd(
|
|
|
702
703
|
memory_content = f"# {name} — Agent Memory\n\n## Project Overview\n\n## Architecture\n\n## Status\n\n## Key Patterns\n"
|
|
703
704
|
(agent_dir / MEMORY_DIR / "project.md").write_text(memory_content)
|
|
704
705
|
|
|
705
|
-
# Commands directory + /setup
|
|
706
|
+
# Commands directory + /setup and /memory runbooks
|
|
706
707
|
(agent_dir / COMMANDS_DIR).mkdir(exist_ok=True)
|
|
707
708
|
content = _render_template(env, "setup.md.jinja", context)
|
|
708
709
|
(agent_dir / COMMANDS_DIR / "setup.md").write_text(content)
|
|
710
|
+
content = _render_template(env, "memory_command.md.jinja", context)
|
|
711
|
+
(agent_dir / COMMANDS_DIR / "memory.md").write_text(content)
|
|
709
712
|
|
|
710
713
|
# Workflow command runbooks
|
|
711
714
|
if domain_config and domain_config.workflow_commands:
|
|
@@ -18,7 +18,7 @@ from copy import deepcopy
|
|
|
18
18
|
from dataclasses import dataclass, field
|
|
19
19
|
from typing import Dict, List, Optional
|
|
20
20
|
|
|
21
|
-
from aes.domains import DomainConfig, SkillDef, WorkflowDef, WorkflowStateDef, WorkflowTransitionDef
|
|
21
|
+
from aes.domains import CommandDef, DomainConfig, SkillDef, WorkflowDef, WorkflowStateDef, WorkflowTransitionDef, _BUILD_COMMAND
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
# ---------------------------------------------------------------------------
|
|
@@ -125,6 +125,7 @@ _API_WORKFLOW = WorkflowDef(
|
|
|
125
125
|
)
|
|
126
126
|
|
|
127
127
|
API_CONFIG = DomainConfig(
|
|
128
|
+
workflow_commands=[_BUILD_COMMAND],
|
|
128
129
|
instructions_description="API service with endpoints, authentication, and database.",
|
|
129
130
|
instructions_quick_ref="", # filled by framework overlay
|
|
130
131
|
instructions_project_structure="", # generic, filled by overlay or /setup
|
|
@@ -177,6 +178,7 @@ _FRONTEND_WORKFLOW = WorkflowDef(
|
|
|
177
178
|
)
|
|
178
179
|
|
|
179
180
|
FRONTEND_CONFIG = DomainConfig(
|
|
181
|
+
workflow_commands=[_BUILD_COMMAND],
|
|
180
182
|
instructions_description="Frontend application with components, routing, and state management.",
|
|
181
183
|
instructions_rules=[
|
|
182
184
|
"**Component-first** -- build small, reusable components.",
|
|
@@ -202,6 +204,7 @@ FRONTEND_CONFIG = DomainConfig(
|
|
|
202
204
|
)
|
|
203
205
|
|
|
204
206
|
FULLSTACK_CONFIG = DomainConfig(
|
|
207
|
+
workflow_commands=[_BUILD_COMMAND],
|
|
205
208
|
instructions_description="Full-stack application with frontend, API, and database.",
|
|
206
209
|
instructions_rules=[
|
|
207
210
|
"**Type safety everywhere** -- shared types between frontend and API.",
|
|
@@ -227,6 +230,7 @@ FULLSTACK_CONFIG = DomainConfig(
|
|
|
227
230
|
)
|
|
228
231
|
|
|
229
232
|
CLI_CONFIG = DomainConfig(
|
|
233
|
+
workflow_commands=[_BUILD_COMMAND],
|
|
230
234
|
instructions_description="Command-line tool with subcommands, argument parsing, and user interaction.",
|
|
231
235
|
instructions_rules=[
|
|
232
236
|
"**Clear error messages** -- users see stderr, make it helpful.",
|
|
@@ -251,6 +255,7 @@ CLI_CONFIG = DomainConfig(
|
|
|
251
255
|
)
|
|
252
256
|
|
|
253
257
|
LIBRARY_CONFIG = DomainConfig(
|
|
258
|
+
workflow_commands=[_BUILD_COMMAND],
|
|
254
259
|
instructions_description="Reusable library or package for other projects to consume.",
|
|
255
260
|
instructions_rules=[
|
|
256
261
|
"**Public API is a contract** -- don't break it without a major version bump.",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{% if domain_config %}
|
|
2
2
|
# .agent/agent.yaml — AES Manifest
|
|
3
|
-
aes: "1.
|
|
3
|
+
aes: "1.1"
|
|
4
4
|
|
|
5
5
|
name: "{{ name }}"
|
|
6
6
|
version: "0.1.0"
|
|
@@ -41,6 +41,10 @@ commands:
|
|
|
41
41
|
path: "commands/setup.md"
|
|
42
42
|
trigger: "/setup"
|
|
43
43
|
description: "Review and customize .agent/ files for your project"
|
|
44
|
+
- id: "memory"
|
|
45
|
+
path: "commands/memory.md"
|
|
46
|
+
trigger: "/memory"
|
|
47
|
+
description: "Review conversation and save learnings to agent memory"
|
|
44
48
|
{% if domain_config.workflow_commands %}
|
|
45
49
|
{% for cmd in domain_config.workflow_commands %}
|
|
46
50
|
- id: "{{ cmd.id }}"
|
|
@@ -72,7 +76,7 @@ environment:
|
|
|
72
76
|
{% endif %}
|
|
73
77
|
{% else %}
|
|
74
78
|
# .agent/agent.yaml — AES Manifest
|
|
75
|
-
aes: "1.
|
|
79
|
+
aes: "1.1"
|
|
76
80
|
|
|
77
81
|
name: "{{ name }}"
|
|
78
82
|
version: "0.1.0"
|
|
@@ -116,6 +120,10 @@ commands:
|
|
|
116
120
|
path: "commands/setup.md"
|
|
117
121
|
trigger: "/setup"
|
|
118
122
|
description: "Populate .agent/ files by analyzing the codebase"
|
|
123
|
+
- id: "memory"
|
|
124
|
+
path: "commands/memory.md"
|
|
125
|
+
trigger: "/memory"
|
|
126
|
+
description: "Review conversation and save learnings to agent memory"
|
|
119
127
|
# - id: "run"
|
|
120
128
|
# path: "commands/run.md"
|
|
121
129
|
# trigger: "/run"
|
|
@@ -51,7 +51,7 @@ When creating or editing `.agent/` files, follow these formats exactly.
|
|
|
51
51
|
### Skill manifest (`.skill.yaml`)
|
|
52
52
|
|
|
53
53
|
```yaml
|
|
54
|
-
aes_skill: "1.
|
|
54
|
+
aes_skill: "1.1"
|
|
55
55
|
|
|
56
56
|
id: "my-skill"
|
|
57
57
|
name: "My Skill"
|
|
@@ -100,7 +100,7 @@ tags:
|
|
|
100
100
|
### Workflow (`.yaml`)
|
|
101
101
|
|
|
102
102
|
```yaml
|
|
103
|
-
aes_workflow: "1.
|
|
103
|
+
aes_workflow: "1.1"
|
|
104
104
|
|
|
105
105
|
id: "my-workflow"
|
|
106
106
|
entity: "item"
|
|
@@ -226,7 +226,7 @@ When creating or editing `.agent/` files, follow these formats exactly.
|
|
|
226
226
|
### Skill manifest (`.skill.yaml`)
|
|
227
227
|
|
|
228
228
|
```yaml
|
|
229
|
-
aes_skill: "1.
|
|
229
|
+
aes_skill: "1.1"
|
|
230
230
|
|
|
231
231
|
id: "my-skill"
|
|
232
232
|
name: "My Skill"
|
|
@@ -275,7 +275,7 @@ tags:
|
|
|
275
275
|
### Workflow (`.yaml`)
|
|
276
276
|
|
|
277
277
|
```yaml
|
|
278
|
-
aes_workflow: "1.
|
|
278
|
+
aes_workflow: "1.1"
|
|
279
279
|
|
|
280
280
|
id: "my-workflow"
|
|
281
281
|
entity: "item"
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# コマンド: /memory
|
|
2
|
+
|
|
3
|
+
現在の会話をレビューし、記憶に値するアイテムを `.agent/memory/` に保存します。
|
|
4
|
+
|
|
5
|
+
## 実行タイミング
|
|
6
|
+
|
|
7
|
+
- **手動**: `/memory` を実行して重要な学びを保存
|
|
8
|
+
- **自動トリガー**: 重要な作業セッションの終了時に実行 — コマンド完了後、アーキテクチャの意思決定後、困難なバグの解決後、大規模な実装作業の完了後
|
|
9
|
+
|
|
10
|
+
## フェーズ 1: コンテキストのレビュー
|
|
11
|
+
|
|
12
|
+
会話をスキャンし、保存する価値のあるアイテムを特定:
|
|
13
|
+
|
|
14
|
+
1. **アーキテクチャの決定** — 新しいパターン、技術選択、根拠を伴うデザインのトレードオフ
|
|
15
|
+
2. **苦労して得た解決策** — 診断に労力を要したバグ、非自明な修正、ワークアラウンド
|
|
16
|
+
3. **プロジェクトの規約** — 複数のインタラクションで確認されたパターン
|
|
17
|
+
4. **環境/インフラのメモ** — デプロイの詳細、ランタイムの癖、認証情報の設定
|
|
18
|
+
5. **ステータスの変更** — 構築されたもの、進行中に移行したもの、計画されたもの
|
|
19
|
+
|
|
20
|
+
**無視するもの:**
|
|
21
|
+
- 一時的な状態(現在のタスクの詳細、進行中の作業の詳細)
|
|
22
|
+
- セッション間で未確認の単一観察による結論
|
|
23
|
+
- `.agent/instructions.md` に既に記載されている情報
|
|
24
|
+
- セッション固有の詳細(一時ファイルパス、エフェメラルID)
|
|
25
|
+
|
|
26
|
+
## フェーズ 2: 既存メモリの確認
|
|
27
|
+
|
|
28
|
+
重複を避けるために、現在のメモリファイルを読む:
|
|
29
|
+
|
|
30
|
+
1. `.agent/memory/project.md` — 全セクションを確認
|
|
31
|
+
2. `.agent/memory/learnings.yaml` — 既存の学習IDを確認
|
|
32
|
+
|
|
33
|
+
各候補アイテムについて:
|
|
34
|
+
- 既存エントリを**更新**する場合 → 既存エントリをその場で修正
|
|
35
|
+
- 既存エントリと**矛盾**する場合 → 新しい理解で置き換え
|
|
36
|
+
- **真に新しい**場合 → 適切なセクションに追加
|
|
37
|
+
- 既存エントリと**重複**する場合 → スキップ
|
|
38
|
+
|
|
39
|
+
## フェーズ 3: プロジェクトメモリへの保存
|
|
40
|
+
|
|
41
|
+
`.agent/memory/project.md` を以下のセクションに該当するアイテムで更新:
|
|
42
|
+
|
|
43
|
+
| セクション | 記載内容 |
|
|
44
|
+
|-----------|---------|
|
|
45
|
+
| **プロジェクト概要** | システム目的の変更、スコープの変更 |
|
|
46
|
+
| **アーキテクチャ** | 根拠を伴う新しい技術的決定 |
|
|
47
|
+
| **ステータス** | 構築済み、進行中、計画中のもの |
|
|
48
|
+
| **主要パターン** | コードベースから確認されたパターン |
|
|
49
|
+
| **環境メモ** | デプロイ、ランタイム、インフラの詳細 |
|
|
50
|
+
|
|
51
|
+
`project.md` を200行以下に維持してください。制限に近づいた場合は、超過するのではなく、古いエントリを統合または削除してください。
|
|
52
|
+
|
|
53
|
+
## フェーズ 4: 構造化された学習の保存
|
|
54
|
+
|
|
55
|
+
明確な適用性を持つ苦労して得た教訓について、`.agent/memory/learnings.yaml` に追加:
|
|
56
|
+
|
|
57
|
+
```yaml
|
|
58
|
+
- id: "ケバブケースid"
|
|
59
|
+
date: "YYYY-MM-DD"
|
|
60
|
+
context: "何が起きていたか"
|
|
61
|
+
observation: "何が観察されたか"
|
|
62
|
+
lesson: "一般化された教訓"
|
|
63
|
+
applies_when:
|
|
64
|
+
- "条件 1"
|
|
65
|
+
- "条件 2"
|
|
66
|
+
action: "これが適用される場合に何をするか"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
構造化された学習は以下の場合にのみ作成:
|
|
70
|
+
- 複数の観察で確認された、または
|
|
71
|
+
- 発見に大きな労力を要した、または
|
|
72
|
+
- 忘れると実害が生じる
|
|
73
|
+
|
|
74
|
+
## フェーズ 5: セッションスナップショット
|
|
75
|
+
|
|
76
|
+
セッションが実質的な作業を含んでいた場合、`.agent/memory/sessions/YYYY-MM-DD.md` を作成:
|
|
77
|
+
|
|
78
|
+
```markdown
|
|
79
|
+
# セッション: YYYY-MM-DD
|
|
80
|
+
|
|
81
|
+
## 実施内容
|
|
82
|
+
- ...
|
|
83
|
+
|
|
84
|
+
## 行われた決定
|
|
85
|
+
- ...
|
|
86
|
+
|
|
87
|
+
## 未解決の質問
|
|
88
|
+
- ...
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
軽微なセッション(クイックフィックス、小さな設定変更)ではこのフェーズをスキップしてください。
|
|
92
|
+
|
|
93
|
+
## フェーズ 6: 報告
|
|
94
|
+
|
|
95
|
+
保存されたものを要約:
|
|
96
|
+
- `project.md` に追加または更新されたアイテム
|
|
97
|
+
- `learnings.yaml` に追加された学習(ある場合)
|
|
98
|
+
- 作成されたセッションファイル(ある場合)
|
|
99
|
+
- 重複としてスキップされたアイテム
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Command: /memory
|
|
2
|
+
|
|
3
|
+
Review the current conversation and save memory-worthy items to `.agent/memory/`.
|
|
4
|
+
|
|
5
|
+
## When to Run
|
|
6
|
+
|
|
7
|
+
- **Manually**: Run `/memory` at any point to persist important learnings
|
|
8
|
+
- **Auto-trigger**: Run this at the end of significant work sessions — after completing commands, making architectural decisions, solving difficult bugs, or finishing substantial implementation work
|
|
9
|
+
|
|
10
|
+
## Phase 1: Review Context
|
|
11
|
+
|
|
12
|
+
Scan the conversation and identify items worth persisting:
|
|
13
|
+
|
|
14
|
+
1. **Architectural decisions** — new patterns, technology choices, design trade-offs with rationale
|
|
15
|
+
2. **Hard-won solutions** — bugs that took effort to diagnose, non-obvious fixes, workarounds
|
|
16
|
+
3. **Project conventions** — patterns confirmed across multiple interactions
|
|
17
|
+
4. **Environment/infra notes** — deployment details, runtime quirks, credentials setup
|
|
18
|
+
5. **Status changes** — what was built, what shifted to in-progress or planned
|
|
19
|
+
|
|
20
|
+
**Ignore:**
|
|
21
|
+
- Temporary state (current task details, in-progress work details)
|
|
22
|
+
- Single-observation conclusions not yet confirmed across sessions
|
|
23
|
+
- Information already captured in `.agent/instructions.md`
|
|
24
|
+
- Session-specific details (temp file paths, ephemeral IDs)
|
|
25
|
+
|
|
26
|
+
## Phase 2: Check Existing Memory
|
|
27
|
+
|
|
28
|
+
Read the current memory files to avoid duplicates:
|
|
29
|
+
|
|
30
|
+
1. `.agent/memory/project.md` — check all sections
|
|
31
|
+
2. `.agent/memory/learnings.yaml` — check existing learning IDs
|
|
32
|
+
|
|
33
|
+
For each candidate item:
|
|
34
|
+
- **Updates** an existing entry → modify the existing entry in place
|
|
35
|
+
- **Contradicts** an existing entry → replace with the newer understanding
|
|
36
|
+
- **Genuinely new** → append to the appropriate section
|
|
37
|
+
- **Duplicates** an existing entry → skip
|
|
38
|
+
|
|
39
|
+
## Phase 3: Save to Project Memory
|
|
40
|
+
|
|
41
|
+
Update `.agent/memory/project.md` with items that belong in these sections:
|
|
42
|
+
|
|
43
|
+
| Section | What goes here |
|
|
44
|
+
|---------|---------------|
|
|
45
|
+
| **Project Overview** | System purpose changes, scope shifts |
|
|
46
|
+
| **Architecture** | New technical decisions with rationale |
|
|
47
|
+
| **Status** | What's built, in progress, planned |
|
|
48
|
+
| **Key Patterns** | Confirmed patterns from the codebase |
|
|
49
|
+
| **Environment Notes** | Deployment, runtime, infrastructure details |
|
|
50
|
+
|
|
51
|
+
Keep `project.md` under 200 lines. If approaching the limit, consolidate or remove outdated entries rather than exceeding it.
|
|
52
|
+
|
|
53
|
+
## Phase 4: Save Structured Learnings
|
|
54
|
+
|
|
55
|
+
For hard-won lessons with clear applicability, append to `.agent/memory/learnings.yaml`:
|
|
56
|
+
|
|
57
|
+
```yaml
|
|
58
|
+
- id: "kebab-case-id"
|
|
59
|
+
date: "YYYY-MM-DD"
|
|
60
|
+
context: "what was happening"
|
|
61
|
+
observation: "what was observed"
|
|
62
|
+
lesson: "generalized takeaway"
|
|
63
|
+
applies_when:
|
|
64
|
+
- "condition 1"
|
|
65
|
+
- "condition 2"
|
|
66
|
+
action: "what to do when this applies"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Only create structured learnings for insights that:
|
|
70
|
+
- Were confirmed across multiple observations, OR
|
|
71
|
+
- Required significant effort to discover, OR
|
|
72
|
+
- Would cause real damage if forgotten
|
|
73
|
+
|
|
74
|
+
## Phase 5: Session Snapshot
|
|
75
|
+
|
|
76
|
+
If the session involved substantial work, create `.agent/memory/sessions/YYYY-MM-DD.md`:
|
|
77
|
+
|
|
78
|
+
```markdown
|
|
79
|
+
# Session: YYYY-MM-DD
|
|
80
|
+
|
|
81
|
+
## What Was Done
|
|
82
|
+
- ...
|
|
83
|
+
|
|
84
|
+
## Decisions Made
|
|
85
|
+
- ...
|
|
86
|
+
|
|
87
|
+
## Open Questions
|
|
88
|
+
- ...
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Skip this phase for minor sessions (quick fixes, small config changes).
|
|
92
|
+
|
|
93
|
+
## Phase 6: Report
|
|
94
|
+
|
|
95
|
+
Summarize what was persisted:
|
|
96
|
+
- Items added or updated in `project.md`
|
|
97
|
+
- Learnings added to `learnings.yaml` (if any)
|
|
98
|
+
- Session file created (if any)
|
|
99
|
+
- Items skipped as duplicates
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{% if domain_config %}
|
|
2
2
|
# .agent/permissions.yaml — Agent Capability Boundaries
|
|
3
|
-
aes_permissions: "1.
|
|
3
|
+
aes_permissions: "1.1"
|
|
4
4
|
|
|
5
5
|
allow:
|
|
6
6
|
shell:
|
|
@@ -82,7 +82,7 @@ resource_limits:
|
|
|
82
82
|
{% endif %}
|
|
83
83
|
{% else %}
|
|
84
84
|
# .agent/permissions.yaml — Agent Capability Boundaries
|
|
85
|
-
aes_permissions: "1.
|
|
85
|
+
aes_permissions: "1.1"
|
|
86
86
|
|
|
87
87
|
allow:
|
|
88
88
|
shell:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{% if skill %}
|
|
2
2
|
# .agent/skills/{{ skill.id }}.skill.yaml
|
|
3
|
-
aes_skill: "1.
|
|
3
|
+
aes_skill: "1.1"
|
|
4
4
|
|
|
5
5
|
id: "{{ skill.id }}"
|
|
6
6
|
name: "{{ skill.name }}"
|
|
@@ -107,7 +107,7 @@ tags:
|
|
|
107
107
|
{% endfor %}
|
|
108
108
|
{% else %}
|
|
109
109
|
# .agent/skills/{{ skill_id }}.skill.yaml
|
|
110
|
-
aes_skill: "1.
|
|
110
|
+
aes_skill: "1.1"
|
|
111
111
|
|
|
112
112
|
id: "{{ skill_id }}"
|
|
113
113
|
name: "{{ skill_name }}"
|
|
@@ -51,6 +51,15 @@ class ClaudeTarget(SyncTarget):
|
|
|
51
51
|
if confirm_section:
|
|
52
52
|
content += "\n" + confirm_section
|
|
53
53
|
|
|
54
|
+
# Memory management instruction (auto-trigger /memory)
|
|
55
|
+
content += (
|
|
56
|
+
"\n## Memory Management\n\n"
|
|
57
|
+
"At the end of significant work sessions \u2014 especially after "
|
|
58
|
+
"completing commands, making architectural decisions, or solving "
|
|
59
|
+
"difficult bugs \u2014 run `/memory` to persist learnings to "
|
|
60
|
+
"`.agent/memory/`.\n"
|
|
61
|
+
)
|
|
62
|
+
|
|
54
63
|
action = self._check_conflict(ctx.project_root, "CLAUDE.md", force)
|
|
55
64
|
plan.files.append(GeneratedFile(
|
|
56
65
|
relative_path="CLAUDE.md",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aes-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: CLI tool for the Agentic Engineering Standard
|
|
5
5
|
Author: Hiro
|
|
6
6
|
License: Apache-2.0
|
|
@@ -46,6 +46,15 @@ pipx install aes-cli
|
|
|
46
46
|
pip install aes-cli
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
### Upgrading
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pipx upgrade aes-cli # if installed with pipx
|
|
53
|
+
pip install --upgrade aes-cli # if installed with pip
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
After upgrading, run `aes sync` in your project to regenerate tool-specific configs with the new version's sync logic. Your `.agent/` source files are not modified by the upgrade.
|
|
57
|
+
|
|
49
58
|
Requires Python 3.10+.
|
|
50
59
|
|
|
51
60
|
## Quick Start
|
|
@@ -28,6 +28,7 @@ aes/scaffold/agentignore.jinja
|
|
|
28
28
|
aes/scaffold/instructions.md.jinja
|
|
29
29
|
aes/scaffold/local.example.yaml.jinja
|
|
30
30
|
aes/scaffold/local.yaml.jinja
|
|
31
|
+
aes/scaffold/memory_command.md.jinja
|
|
31
32
|
aes/scaffold/operations.md.jinja
|
|
32
33
|
aes/scaffold/orchestrator.md.jinja
|
|
33
34
|
aes/scaffold/permissions.yaml.jinja
|
|
@@ -37,6 +38,7 @@ aes/scaffold/skill.yaml.jinja
|
|
|
37
38
|
aes/scaffold/workflow.yaml.jinja
|
|
38
39
|
aes/scaffold/workflow_command.md.jinja
|
|
39
40
|
aes/scaffold/ja/instructions.md.jinja
|
|
41
|
+
aes/scaffold/ja/memory_command.md.jinja
|
|
40
42
|
aes/scaffold/ja/operations.md.jinja
|
|
41
43
|
aes/scaffold/ja/orchestrator.md.jinja
|
|
42
44
|
aes/scaffold/ja/setup.md.jinja
|
|
@@ -61,7 +61,7 @@ class TestInit:
|
|
|
61
61
|
agent_yaml = tmp_path / ".agent" / "agent.yaml"
|
|
62
62
|
with open(agent_yaml) as f:
|
|
63
63
|
data = yaml.safe_load(f)
|
|
64
|
-
assert data["aes"] == "1.
|
|
64
|
+
assert data["aes"] == "1.1"
|
|
65
65
|
assert data["name"] == "test-project"
|
|
66
66
|
assert data["domain"] == "ml"
|
|
67
67
|
|
|
@@ -321,12 +321,21 @@ class TestWorkflowCommands:
|
|
|
321
321
|
with open(tmp_path / ".agent" / "agent.yaml") as f:
|
|
322
322
|
data = yaml.safe_load(f)
|
|
323
323
|
commands = data.get("commands", [])
|
|
324
|
-
# Filter to workflow commands (exclude setup)
|
|
325
|
-
wf_cmds = [c for c in commands if c.get("id")
|
|
324
|
+
# Filter to workflow commands (exclude setup and memory)
|
|
325
|
+
wf_cmds = [c for c in commands if c.get("id") not in ("setup", "memory")]
|
|
326
326
|
assert len(wf_cmds) >= 2
|
|
327
327
|
assert wf_cmds[0]["id"] == "build"
|
|
328
328
|
assert wf_cmds[0]["trigger"] == "/build"
|
|
329
329
|
|
|
330
|
+
def test_ml_memory_command(self, tmp_path):
|
|
331
|
+
"""All domains get the /memory command."""
|
|
332
|
+
_init(tmp_path, name="test-ml", domain="ml")
|
|
333
|
+
cmd_path = tmp_path / ".agent" / "commands" / "memory.md"
|
|
334
|
+
assert cmd_path.exists()
|
|
335
|
+
content = cmd_path.read_text()
|
|
336
|
+
assert "/memory" in content
|
|
337
|
+
assert "Review" in content
|
|
338
|
+
|
|
330
339
|
def test_web_build_command(self, tmp_path):
|
|
331
340
|
_init(tmp_path, name="test-web", domain="web", language="typescript")
|
|
332
341
|
cmd_path = tmp_path / ".agent" / "commands" / "build.md"
|
|
@@ -363,7 +372,7 @@ class TestWorkflowCommands:
|
|
|
363
372
|
with open(tmp_path / ".agent" / "agent.yaml") as f:
|
|
364
373
|
data = yaml.safe_load(f)
|
|
365
374
|
commands = data.get("commands", [])
|
|
366
|
-
wf_cmds = [c for c in commands if c.get("id")
|
|
375
|
+
wf_cmds = [c for c in commands if c.get("id") not in ("setup", "memory")]
|
|
367
376
|
assert len(wf_cmds) >= 2
|
|
368
377
|
assert wf_cmds[0]["id"] == "build"
|
|
369
378
|
assert wf_cmds[0]["trigger"] == "/build"
|
|
@@ -380,9 +389,9 @@ class TestWorkflowCommands:
|
|
|
380
389
|
def test_other_domain_gets_build_command(self, tmp_path):
|
|
381
390
|
_init(tmp_path, name="test-other", domain="other")
|
|
382
391
|
commands_dir = tmp_path / ".agent" / "commands"
|
|
383
|
-
# Should get setup.md + build.md from DEV_ASSIST_BASE_CONFIG
|
|
392
|
+
# Should get setup.md + memory.md + build.md from DEV_ASSIST_BASE_CONFIG
|
|
384
393
|
cmd_files = sorted(f.name for f in commands_dir.glob("*.md"))
|
|
385
|
-
assert cmd_files == ["build.md", "setup.md"]
|
|
394
|
+
assert cmd_files == ["build.md", "memory.md", "setup.md"]
|
|
386
395
|
|
|
387
396
|
def test_explicit_domain_other_gets_build(self, tmp_path):
|
|
388
397
|
"""--domain other (explicit CLI, non-interactive) gets /build."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|