aisef 0.1.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.
- aisef-0.1.0/PKG-INFO +282 -0
- aisef-0.1.0/README.md +274 -0
- aisef-0.1.0/aisdlc/__init__.py +0 -0
- aisef-0.1.0/aisdlc/cli/__init__.py +101 -0
- aisef-0.1.0/aisdlc/cli/__main__.py +9 -0
- aisef-0.1.0/aisdlc/cli/_common.py +72 -0
- aisef-0.1.0/aisdlc/cli/doctor.py +286 -0
- aisef-0.1.0/aisdlc/cli/harness.py +270 -0
- aisef-0.1.0/aisdlc/cli/implement.py +552 -0
- aisef-0.1.0/aisdlc/cli/parser.py +248 -0
- aisef-0.1.0/aisdlc/cli/plan.py +280 -0
- aisef-0.1.0/aisdlc/clients/__init__.py +0 -0
- aisef-0.1.0/aisdlc/clients/base.py +156 -0
- aisef-0.1.0/aisdlc/clients/claude_code.py +151 -0
- aisef-0.1.0/aisdlc/clients/compile.py +250 -0
- aisef-0.1.0/aisdlc/clients/opencode.py +162 -0
- aisef-0.1.0/aisdlc/clients/stream.py +340 -0
- aisef-0.1.0/aisdlc/config.py +363 -0
- aisef-0.1.0/aisdlc/control/__init__.py +0 -0
- aisef-0.1.0/aisdlc/control/acceptance.py +41 -0
- aisef-0.1.0/aisdlc/control/approvals.py +367 -0
- aisef-0.1.0/aisdlc/control/bmad_status.py +181 -0
- aisef-0.1.0/aisdlc/control/change.py +138 -0
- aisef-0.1.0/aisdlc/control/complexity.py +533 -0
- aisef-0.1.0/aisdlc/control/conformance.py +178 -0
- aisef-0.1.0/aisdlc/control/design_contract.py +218 -0
- aisef-0.1.0/aisdlc/control/experience.py +214 -0
- aisef-0.1.0/aisdlc/control/gate.py +800 -0
- aisef-0.1.0/aisdlc/control/impact.py +364 -0
- aisef-0.1.0/aisdlc/control/journal.py +356 -0
- aisef-0.1.0/aisdlc/control/ledger.py +686 -0
- aisef-0.1.0/aisdlc/control/machine_gate.py +318 -0
- aisef-0.1.0/aisdlc/control/normalize.py +696 -0
- aisef-0.1.0/aisdlc/control/outcome.py +116 -0
- aisef-0.1.0/aisdlc/control/preflight.py +741 -0
- aisef-0.1.0/aisdlc/control/replay.py +121 -0
- aisef-0.1.0/aisdlc/control/scheduler.py +199 -0
- aisef-0.1.0/aisdlc/control/security.py +133 -0
- aisef-0.1.0/aisdlc/control/state.py +332 -0
- aisef-0.1.0/aisdlc/control/tdd.py +84 -0
- aisef-0.1.0/aisdlc/control/worktree.py +392 -0
- aisef-0.1.0/aisdlc/harness/__init__.py +0 -0
- aisef-0.1.0/aisdlc/harness/aria.py +159 -0
- aisef-0.1.0/aisdlc/harness/assets/render.mjs +122 -0
- aisef-0.1.0/aisdlc/harness/browser.py +152 -0
- aisef-0.1.0/aisdlc/harness/context.py +306 -0
- aisef-0.1.0/aisdlc/harness/guardrails.py +821 -0
- aisef-0.1.0/aisdlc/harness/mockup_map.py +164 -0
- aisef-0.1.0/aisdlc/harness/mockup_verify.py +297 -0
- aisef-0.1.0/aisdlc/harness/observe.py +320 -0
- aisef-0.1.0/aisdlc/harness/prompts.py +116 -0
- aisef-0.1.0/aisdlc/harness/routing.py +146 -0
- aisef-0.1.0/aisdlc/harness/sandbox.py +489 -0
- aisef-0.1.0/aisdlc/harness/testlog.py +245 -0
- aisef-0.1.0/aisdlc/harness/tools.py +373 -0
- aisef-0.1.0/aisdlc/kit/__init__.py +0 -0
- aisef-0.1.0/aisdlc/kit/catalog.json +89 -0
- aisef-0.1.0/aisdlc/kit/catalog.py +122 -0
- aisef-0.1.0/aisdlc/kit/constitution.py +144 -0
- aisef-0.1.0/aisdlc/kit/detect_stack.py +160 -0
- aisef-0.1.0/aisdlc/kit/docs.py +102 -0
- aisef-0.1.0/aisdlc/kit/fetch.py +128 -0
- aisef-0.1.0/aisdlc/kit/install.py +218 -0
- aisef-0.1.0/aisdlc/kit/prompts/devsecops.md +50 -0
- aisef-0.1.0/aisdlc/kit/prompts/mockup-screen.md +27 -0
- aisef-0.1.0/aisdlc/kit/prompts/story-implement.md +112 -0
- aisef-0.1.0/aisdlc/kit/prompts/story-review.md +120 -0
- aisef-0.1.0/aisdlc/kit/prompts/story-security-review.md +127 -0
- aisef-0.1.0/aisdlc/kit/registry.py +434 -0
- aisef-0.1.0/aisdlc/kit/router.py +204 -0
- aisef-0.1.0/aisdlc/kit/rules/must_never.md +40 -0
- aisef-0.1.0/aisdlc/kit/rules/principles.md +64 -0
- aisef-0.1.0/aisdlc/kit/security_filter.py +264 -0
- aisef-0.1.0/aisdlc/kit/skill_scan.py +225 -0
- aisef-0.1.0/aisdlc/kit/skills/aisdlc-mockup-html/SKILL.md +125 -0
- aisef-0.1.0/aisdlc/kit/skills.py +132 -0
- aisef-0.1.0/aisdlc/phases/__init__.py +1 -0
- aisef-0.1.0/aisdlc/phases/deploy.py +486 -0
- aisef-0.1.0/aisdlc/phases/implement.py +2020 -0
- aisef-0.1.0/aisdlc/phases/improve.py +524 -0
- aisef-0.1.0/aisdlc/phases/mockup.py +302 -0
- aisef-0.1.0/aisdlc/phases/plan.py +437 -0
- aisef-0.1.0/aisdlc/phases/qa.py +455 -0
- aisef-0.1.0/aisdlc/phases/report.py +430 -0
- aisef-0.1.0/aisdlc/phases/run.py +525 -0
- aisef-0.1.0/aisdlc/phases/story_split.py +362 -0
- aisef-0.1.0/aisef.egg-info/PKG-INFO +282 -0
- aisef-0.1.0/aisef.egg-info/SOURCES.txt +160 -0
- aisef-0.1.0/aisef.egg-info/dependency_links.txt +1 -0
- aisef-0.1.0/aisef.egg-info/entry_points.txt +2 -0
- aisef-0.1.0/aisef.egg-info/top_level.txt +1 -0
- aisef-0.1.0/pyproject.toml +23 -0
- aisef-0.1.0/setup.cfg +4 -0
- aisef-0.1.0/tests/test_acceptance.py +37 -0
- aisef-0.1.0/tests/test_approvals.py +230 -0
- aisef-0.1.0/tests/test_aria.py +123 -0
- aisef-0.1.0/tests/test_bmad_status.py +125 -0
- aisef-0.1.0/tests/test_candidate.py +357 -0
- aisef-0.1.0/tests/test_catalog.py +133 -0
- aisef-0.1.0/tests/test_change.py +54 -0
- aisef-0.1.0/tests/test_cli.py +805 -0
- aisef-0.1.0/tests/test_clients.py +368 -0
- aisef-0.1.0/tests/test_compile.py +238 -0
- aisef-0.1.0/tests/test_config.py +209 -0
- aisef-0.1.0/tests/test_conformance.py +163 -0
- aisef-0.1.0/tests/test_constitution.py +102 -0
- aisef-0.1.0/tests/test_context.py +192 -0
- aisef-0.1.0/tests/test_deploy.py +614 -0
- aisef-0.1.0/tests/test_design_contract_states.py +67 -0
- aisef-0.1.0/tests/test_detect_stack.py +164 -0
- aisef-0.1.0/tests/test_docs.py +51 -0
- aisef-0.1.0/tests/test_experience.py +150 -0
- aisef-0.1.0/tests/test_fetch.py +181 -0
- aisef-0.1.0/tests/test_findings.py +235 -0
- aisef-0.1.0/tests/test_gate.py +699 -0
- aisef-0.1.0/tests/test_gate_qualification.py +679 -0
- aisef-0.1.0/tests/test_guardrails.py +973 -0
- aisef-0.1.0/tests/test_handoff.py +77 -0
- aisef-0.1.0/tests/test_impact.py +255 -0
- aisef-0.1.0/tests/test_implement.py +1167 -0
- aisef-0.1.0/tests/test_improve.py +472 -0
- aisef-0.1.0/tests/test_install.py +157 -0
- aisef-0.1.0/tests/test_journal.py +234 -0
- aisef-0.1.0/tests/test_ledger.py +573 -0
- aisef-0.1.0/tests/test_machine_gate.py +228 -0
- aisef-0.1.0/tests/test_meta.py +192 -0
- aisef-0.1.0/tests/test_mockup.py +245 -0
- aisef-0.1.0/tests/test_mockup_map.py +285 -0
- aisef-0.1.0/tests/test_mockup_map_seed.py +37 -0
- aisef-0.1.0/tests/test_normalize.py +196 -0
- aisef-0.1.0/tests/test_observe.py +145 -0
- aisef-0.1.0/tests/test_outcome.py +80 -0
- aisef-0.1.0/tests/test_plan.py +312 -0
- aisef-0.1.0/tests/test_prd_headings.py +47 -0
- aisef-0.1.0/tests/test_preflight.py +457 -0
- aisef-0.1.0/tests/test_preservation.py +288 -0
- aisef-0.1.0/tests/test_prompts.py +223 -0
- aisef-0.1.0/tests/test_qa.py +448 -0
- aisef-0.1.0/tests/test_registry.py +259 -0
- aisef-0.1.0/tests/test_release_gate.py +51 -0
- aisef-0.1.0/tests/test_replay.py +191 -0
- aisef-0.1.0/tests/test_report.py +293 -0
- aisef-0.1.0/tests/test_report_mockup_cell.py +32 -0
- aisef-0.1.0/tests/test_requirements_evidence.py +53 -0
- aisef-0.1.0/tests/test_router.py +178 -0
- aisef-0.1.0/tests/test_run.py +891 -0
- aisef-0.1.0/tests/test_sandbox.py +474 -0
- aisef-0.1.0/tests/test_scheduler.py +198 -0
- aisef-0.1.0/tests/test_security.py +174 -0
- aisef-0.1.0/tests/test_security_filter.py +143 -0
- aisef-0.1.0/tests/test_skill_scan.py +108 -0
- aisef-0.1.0/tests/test_skills_inline.py +66 -0
- aisef-0.1.0/tests/test_state.py +267 -0
- aisef-0.1.0/tests/test_story_size.py +402 -0
- aisef-0.1.0/tests/test_story_split.py +263 -0
- aisef-0.1.0/tests/test_stream.py +285 -0
- aisef-0.1.0/tests/test_tdd.py +101 -0
- aisef-0.1.0/tests/test_testlog.py +161 -0
- aisef-0.1.0/tests/test_tools.py +357 -0
- aisef-0.1.0/tests/test_verification_contract.py +175 -0
- aisef-0.1.0/tests/test_worktree.py +328 -0
- aisef-0.1.0/tests/test_write_scope_verify.py +68 -0
aisef-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aisef
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Khung SDLC cho agent: đầu vào là docs/requirements.md, đầu ra là code đã qua cổng kiểm
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
|
|
9
|
+
# AI-SDLC
|
|
10
|
+
|
|
11
|
+
Khung phát triển phần mềm bằng agent. Đầu vào của mỗi dự án là **một file**
|
|
12
|
+
`docs/requirements.md`; đầu ra là một ứng dụng chạy được, kèm bằng chứng
|
|
13
|
+
cho từng bước.
|
|
14
|
+
|
|
15
|
+
Nguyên tắc nền, xuyên suốt mọi quyết định trong kho này:
|
|
16
|
+
|
|
17
|
+
> **Cần phán đoán thì giao cho model. Cần đảm bảo thì viết code.**
|
|
18
|
+
|
|
19
|
+
Viết PRD, thiết kế kiến trúc, dựng mockup, viết code — đều cần phán đoán,
|
|
20
|
+
đều giao cho model. Còn "mọi yêu cầu phải có story phủ", "không được ghi
|
|
21
|
+
ra ngoài phạm vi", "test phải xanh sau lần sửa cuối" — đều có đáp án đúng,
|
|
22
|
+
nên đều là code. Hệ quả: **không bao giờ giao cho model việc giám sát
|
|
23
|
+
chính nó.**
|
|
24
|
+
|
|
25
|
+
## Cài
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install aisef
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Hoặc chạy từ bản sao kho nguồn:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
git clone <repo> ai-sdlc && cd ai-sdlc && pip install -e .
|
|
35
|
+
python3 -m unittest discover -s tests -q # vài phút, không mở container (tests/__init__.py)
|
|
36
|
+
AISDLC_TEST_DOCKER=1 python3 -m unittest tests.test_sandbox tests.test_tools -q # thêm test Docker thật
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Kho skill tham chiếu **không cần clone tay**: `aisdlc setup` tự lấy về
|
|
40
|
+
`~/.cache/ai-sdlc/references` đúng commit mà `aisdlc/kit/catalog.json`
|
|
41
|
+
ghim (khoảng 93 MB, một lần cho mọi dự án). Máy ngoại tuyến hoặc CI trỏ
|
|
42
|
+
sang chỗ khác bằng `AISDLC_REFERENCES=/duong/dan`, hoặc dùng
|
|
43
|
+
`aisdlc setup --no-fetch` để chỉ xài những gì đã có trên đĩa.
|
|
44
|
+
|
|
45
|
+
Không có phụ thuộc Python nào ngoài thư viện chuẩn. Tuỳ chọn:
|
|
46
|
+
`docker` (cách ly khi chạy test), `playwright` (trích hợp đồng thị giác
|
|
47
|
+
từ mockup) — thiếu thì framework **nói thẳng là thiếu** chứ không giả vờ
|
|
48
|
+
vẫn kiểm được.
|
|
49
|
+
|
|
50
|
+
## Sáu bước
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cd /duong/dan/du-an-cua-ban
|
|
54
|
+
|
|
55
|
+
aisdlc doctor # môi trường có đủ chưa
|
|
56
|
+
aisdlc setup # dò stack, nạp skill, sinh CLAUDE.md + AGENTS.md
|
|
57
|
+
aisdlc compile # nối guard vào client (hook / plugin)
|
|
58
|
+
|
|
59
|
+
aisdlc plan # PRD → kiến trúc → UX → epic → story
|
|
60
|
+
aisdlc gates # xem cổng nào đang chờ người
|
|
61
|
+
aisdlc review prd # đọc artifact
|
|
62
|
+
aisdlc approve prd # duyệt
|
|
63
|
+
|
|
64
|
+
aisdlc mockup # mỗi màn hình một HTML + hợp đồng thị giác
|
|
65
|
+
aisdlc approve mockups
|
|
66
|
+
aisdlc approve readiness
|
|
67
|
+
|
|
68
|
+
aisdlc run # hiện thực: epic tuần tự, story song song
|
|
69
|
+
aisdlc run --verify-only --story STORY-01-07 # kiểm lại ứng viên đã đóng băng, không mở phiên developer
|
|
70
|
+
aisdlc qa # bộ kiểm định
|
|
71
|
+
aisdlc devsecops # CI + Dockerfile + triển khai + runbook
|
|
72
|
+
aisdlc pre-deploy # cổng cuối
|
|
73
|
+
aisdlc report # báo cáo nghiệm thu + sổ hành vi + INDEX.md
|
|
74
|
+
aisdlc evidence STORY-01-04 # lịch sử một story hay một hành vi (AC-…, FR-…, qa:e2e)
|
|
75
|
+
aisdlc issues --format csv # bảng gap/hồi quy từ sổ hành vi → _bmad-output/ISSUES.csv
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Chạy nhanh không cần người duyệt: `aisdlc plan --auto-approve all`. Phê duyệt
|
|
79
|
+
tự động **luôn** được ghi dấu `auto` để về sau truy được tài liệu nào chưa
|
|
80
|
+
từng có người thật xem.
|
|
81
|
+
|
|
82
|
+
## Sau khi có code
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
aisdlc doc vitest --topic coverage --story STORY-01-02
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Tra tài liệu thật của thư viện (context7, có cache) thay vì đoán tên API; có
|
|
89
|
+
`--story` thì lần tra vào bằng chứng. Khi yêu cầu đổi sau phát hành:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
aisdlc change FR-3 "Slug phải giữ dấu gạch dưới"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Ghi vào `docs/requirements.md`, đánh dấu PRD (cổng `prd` và các cổng sau
|
|
96
|
+
thành stale), sinh story delta `STORY-CH-01` với `covers=[FR-3]` — story cũ
|
|
97
|
+
giữ nguyên `DONE`.
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
aisdlc improve --epic EPIC-01 --max-loops 3 # [--auto] không dừng ở cổng người
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Vòng cải tiến theo bằng chứng (ADR-004 R3): QA → sổ hành vi → **một** story
|
|
104
|
+
sửa cho một hành vi GAP/REOPENED (`STORY-RP-01` trong `EPIC-RP-01`, sinh bằng
|
|
105
|
+
code) → `run` như story thường → QA → mốc `loops[]` + `LOOP-REPORT-<n>.md`.
|
|
106
|
+
Dừng bằng code: hết gap, đủ `improve.max_loops`, cải thiện biên ≤ 0
|
|
107
|
+
`improve.flat_loops` vòng liền, vượt `improve.cost_cap_usd`, hay story sửa bế
|
|
108
|
+
tắc kế hoạch (trả người kèm lời reviewer). Trước mỗi vòng ≥ 2 cần
|
|
109
|
+
`aisdlc approve improve` trừ `--auto`.
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
aisdlc run --verify-only --story STORY-01-07
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Story trượt chỉ vì môi trường đo (e2e nhạy tải máy) thì không cần trả tiền
|
|
116
|
+
cho một phiên developer để dựng lại mã đã có (ADR-004 R13): lượt kiểm-lại
|
|
117
|
+
lấy ứng viên ở HEAD nhánh story, chạy lại đúng phép kiểm ✗/thiếu ở SHA ấy,
|
|
118
|
+
giữ rà soát và bảo mật đã có ở cùng SHA, chấm đủ cổng; đạt thì merge như lượt
|
|
119
|
+
thường, trượt thì `failed` và không ăn vào `run.max_retries`.
|
|
120
|
+
|
|
121
|
+
## Cổng
|
|
122
|
+
|
|
123
|
+
Tám cổng, mỗi cổng hai lớp. **Cổng máy** chạy trước — nó bắt được thứ máy
|
|
124
|
+
bắt tốt hơn người (chu trình phụ thuộc, yêu cầu không kiểm chứng được,
|
|
125
|
+
story không khai phạm vi ghi). **Cổng người** chạy sau, trên thứ đã sạch.
|
|
126
|
+
|
|
127
|
+
Phê duyệt là **trạng thái trên đĩa**, không phải câu hỏi trong phiên chat:
|
|
128
|
+
người duyệt có thể là người khác, lúc khác, trên máy khác. Bản ghi phê
|
|
129
|
+
duyệt gắn với **băm nội dung** artifact — sửa tài liệu sau khi duyệt thì
|
|
130
|
+
phê duyệt hết hiệu lực, và sửa tầng trên làm mọi tầng dưới thành `stale`.
|
|
131
|
+
|
|
132
|
+
## Guard
|
|
133
|
+
|
|
134
|
+
Tám guard, mỗi guard là một lệnh trả mã thoát, nối vào ba mốc vòng đời:
|
|
135
|
+
|
|
136
|
+
| Mốc | Guard |
|
|
137
|
+
|---|---|
|
|
138
|
+
| trước mỗi tool | `write-scope` · `destructive` · `secret` · `git-stage` · `injection` · `process-ref` (luật 6: không mã story/epic trong nguồn) |
|
|
139
|
+
| sau mỗi tool | `diff-scope` |
|
|
140
|
+
| khi agent định dừng | `completion` |
|
|
141
|
+
|
|
142
|
+
Guard nằm ở phía framework, không ở phía client — client không được tin.
|
|
143
|
+
Cả Claude Code và OpenCode đều đã **chứng minh bằng phép thử trên agent
|
|
144
|
+
thật** rằng guard chặn *trước* khi tool chạy, chứ không phải phát hiện
|
|
145
|
+
sau. Client nào không gắn được guard tiền kiểm thì `aisdlc verify` chạy
|
|
146
|
+
lại toàn bộ trên diff, và `aisdlc compile` ghi rõ mức bảo đảm thấp hơn
|
|
147
|
+
vào báo cáo thay vì im lặng — năng lực là thứ được **khai và kiểm**, mặc
|
|
148
|
+
định là "chưa chứng minh", không phải "chắc là được". Trong V1, OpenCode
|
|
149
|
+
là client **hạng hai** theo quyết định V1: guard chặn được (hợp quy 7/7), và từ 2026-09-05 `--format json` cho luồng máy đọc được (tool, token, cost theo nhà cung cấp) — chưa lên hạng nhất vì chưa đủ số lần hợp quy hook ổn định; chi phí trước đó không đo
|
|
150
|
+
được từ harness; nó không chặn phát hành.
|
|
151
|
+
|
|
152
|
+
## Lỗi thật đã gặp
|
|
153
|
+
|
|
154
|
+
Hai mươi lăm lỗi tìm bằng đo trên agent thật, xếp theo mười một lớp nguyên nhân kèm phép hồi quy: `docs/FAILURE-TAXONOMY.md`. Lỗi mới thì thêm một dòng vào đó cùng commit với test. Thay đổi theo phiên bản, kèm việc phải làm khi nâng cấp: `CHANGELOG.md`.
|
|
155
|
+
|
|
156
|
+
## Hợp quy client
|
|
157
|
+
|
|
158
|
+
Hook và plugin là tạo tác **biên dịch ra** — đúng cú pháp không có nghĩa là
|
|
159
|
+
client chạy chúng. Bốn lỗi thật (31, 39, 40, 41) đều thuộc lớp này, và unit
|
|
160
|
+
test không bắt được theo định nghĩa. Bộ hợp quy chạy bảy phép thử trên
|
|
161
|
+
client thật, worktree thật, guard thật, `.claude/` không commit:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
AISDLC_CONFORMANCE=1 python3 -m unittest tests.conformance -v
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Kết quả ghép vào `docs/CONFORMANCE.md` — mỗi ô là một phiên agent, đọc từ
|
|
168
|
+
đĩa (tệp còn/mất), từ luồng `tool_use` và bằng chứng guard tự ghi, không từ
|
|
169
|
+
lời agent. Dự án thử và log thô từng phép giữ ở `.conformance/<client>/`
|
|
170
|
+
(đổi bằng `AISDLC_CONFORMANCE_DIR`) để tra lại một ô ✗ mà không phải đoán.
|
|
171
|
+
Bộ chạy **không** thừa hưởng biến `CLAUDE_*` của phiên gọi nó — chạy hợp
|
|
172
|
+
quy từ bên trong một phiên Claude là chuyện có thật, và phiên con thừa hưởng
|
|
173
|
+
cờ của phiên cha thì đo sai. Cổng
|
|
174
|
+
phát hành của chính kho này đọc bảng đó bằng code
|
|
175
|
+
(`AISDLC_RELEASE=1 python3 -m unittest tests.test_release_gate`): cột
|
|
176
|
+
`claude` phải đủ năm ô ✅ và bảng không cũ hơn 14 ngày. OpenCode là hạng
|
|
177
|
+
hai trong V1 — có cột, không chặn. CI: `.github/workflows/conformance.yml`
|
|
178
|
+
chạy tuần.
|
|
179
|
+
|
|
180
|
+
## Phát hành
|
|
181
|
+
|
|
182
|
+
Gói phân phối tên **`aisef`** trên PyPI (module Python và lệnh vẫn là `aisdlc`), phát hành khi hoàn tất đợt 4 (quyết định 2026-09-05).
|
|
183
|
+
Điều kiện đọc bằng lệnh, không bằng cảm giác:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
python3 -m unittest discover -s tests -q && AISDLC_RELEASE=1 AISDLC_ACCEPTANCE=<dự án nghiệm thu> python3 -m unittest tests.test_release_gate -q
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
`AISDLC_ACCEPTANCE` trỏ vào dự án dogfood đã nghiệm thu (v0.1.0: `e9`, phạm vi
|
|
190
|
+
EPIC-01): cổng đọc `pre-deploy-report.json` (đạt, có phạm vi, miễn có lý do)
|
|
191
|
+
và phê duyệt `pre-deploy` trên đúng bản ấy. Không đặt thì bỏ qua có nêu tên —
|
|
192
|
+
không tính là đạt.
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
uv build && uvx twine check dist/*
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
`.github/workflows/release.yml` publish bằng *trusted publishing* khi đẩy tag
|
|
199
|
+
`v*` — không có token nào trong kho. Việc làm **một lần bằng tay**, bằng tài
|
|
200
|
+
khoản tổ chức: tạo project `aisef` trên PyPI và khai trusted publisher
|
|
201
|
+
(kho này · workflow `release.yml` · environment `pypi`). Sau đó:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
git tag v0.1.0 && git push --tags
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Kho hồi quy dogfood (`tests/dogfood/`, bật bằng `AISDLC_DOGFOOD=1`) dựng lại
|
|
208
|
+
dự án thử `par` từ đầu vào trong kho và so với mốc đã đo — chạy trước mỗi tag.
|
|
209
|
+
|
|
210
|
+
### Giới hạn đã biết của v0.1.0
|
|
211
|
+
|
|
212
|
+
Khai ở đây vì mọi claim phải có bằng chứng; thứ chưa chứng minh gọi là chưa
|
|
213
|
+
chứng minh (quyết định chủ đầu tư 2026-09-06, `docs/RELEASE-PLAN-v0.1.0.md` §0):
|
|
214
|
+
|
|
215
|
+
- **Phạm vi nghiệm thu dogfood là EPIC-01 của `e9`** (7 story, `aisdlc
|
|
216
|
+
pre-deploy --epic EPIC-01`). EPIC-02..05 (16 story) chưa chạy — báo cáo ghi
|
|
217
|
+
"ngoài phạm vi", không phải "xong". `e9` chưa phải sản phẩm được nghiệm thu
|
|
218
|
+
hoàn chỉnh; nó là corpus nghiệm thu của framework.
|
|
219
|
+
- **OpenCode là client hạng hai**: hợp quy 9/10 (C9 model từ chối, không kết
|
|
220
|
+
luận), không có đầu ra máy đọc ổn định; claim phát hành dựa trên Claude Code.
|
|
221
|
+
- **Agent trong container chưa có cách ly credential** (S1 blocked): V1 chạy
|
|
222
|
+
agent trên host, chỉ kiểm định trong container; `doctor`/`pre-deploy` nêu
|
|
223
|
+
tên bảo đảm thiếu, không im lặng.
|
|
224
|
+
- **`mutation` ở môi trường nghiệm thu là KHÔNG CHẠY ĐƯỢC** (công cụ chưa cài);
|
|
225
|
+
được miễn có lý do ở `verify.waiver_reason`, hiện ◇, không bao giờ thành ✅.
|
|
226
|
+
`image-scan` cùng loại (docker scout đòi đăng nhập, trivy/grype vắng).
|
|
227
|
+
- **`skills.offer`/`skills.inline` tắt** (A/B không thấy gain), **`repo_map`
|
|
228
|
+
tắt** (`context.max_repo_map_chars = 0`, A/B hoãn sau v0.1.0).
|
|
229
|
+
- **`coverage`**: harness đọc số từ runner (`--coverage`/`--cov`); dự án chưa
|
|
230
|
+
bật thì mục cổng là ○ chưa cấu hình, không phải đạt.
|
|
231
|
+
|
|
232
|
+
## Khi cổng chặn
|
|
233
|
+
|
|
234
|
+
Cổng chặn là framework đang làm việc, không phải framework hỏng. Ba ca hay
|
|
235
|
+
gặp và cách xử đúng:
|
|
236
|
+
|
|
237
|
+
| Cổng báo | Nghĩa là | Làm gì |
|
|
238
|
+
|---|---|---|
|
|
239
|
+
| `mockup còn N chỗ chưa chốt` | mockup gặp câu hỏi chưa ai trả lời và **đánh dấu** thay vì tự quyết | trả lời câu hỏi (thường nằm ở `open_questions` của PRD/UX), sửa tài liệu, dựng lại mockup |
|
|
240
|
+
| `story đụng vào yêu cầu đang bị câu hỏi mở chặn` | epic gán một FR mà PRD ghi là chưa quyết được | trả lời câu hỏi, hoặc bỏ FR đó khỏi story |
|
|
241
|
+
| `merge đụng …` | hai story cùng sửa một file | `write_scope` khai sai — sửa ở story, **không** gỡ conflict cho xong |
|
|
242
|
+
|
|
243
|
+
`--force` có ở `approve` và `run` cho trường hợp cố ý bỏ qua. Dùng nó là
|
|
244
|
+
một quyết định, và nó được ghi lại: bản ghi phê duyệt giữ ghi chú, báo cáo
|
|
245
|
+
nghiệm thu hiện đúng trạng thái từng cổng.
|
|
246
|
+
|
|
247
|
+
## Chạy song song
|
|
248
|
+
|
|
249
|
+
Epic chạy tuần tự. Trong một epic, hai story chỉ được cùng đợt khi **hết
|
|
250
|
+
phụ thuộc** *và* **phạm vi ghi rời nhau** — thiếu điều kiện thứ hai thì hai
|
|
251
|
+
story cùng sửa một file và người thua là người merge sau. Mỗi story chạy
|
|
252
|
+
trong worktree git riêng; merge tuần tự cuối đợt. Conflict lúc merge không
|
|
253
|
+
được tự gỡ: nó là **bằng chứng `write_scope` khai sai**.
|
|
254
|
+
|
|
255
|
+
## Cấu trúc
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
aisdlc/
|
|
259
|
+
cli/ bộ lệnh chia theo pha, mọi lệnh gọi-một-lần, không daemon
|
|
260
|
+
config.py ngưỡng và cấu hình, có kiểu, có kiểm
|
|
261
|
+
clients/ Claude Code · OpenCode; năng lực được **khai**, không giả định
|
|
262
|
+
control/ cổng, phê duyệt, xếp lịch, worktree, chuẩn hoá tài liệu BMAD
|
|
263
|
+
harness/ prompt · tool · sandbox · guard · quan sát · map mockup
|
|
264
|
+
kit/ catalog skill, lọc bảo mật hai tầng, hiến pháp, prompt, skill riêng
|
|
265
|
+
phases/ plan · mockup · implement · run · qa · deploy · report
|
|
266
|
+
docs/
|
|
267
|
+
SOLUTION.md giải pháp tổng thể và vì sao chọn như vậy
|
|
268
|
+
EXECUTION-PLAN.md kế hoạch thực thi, trạng thái từng hạng mục
|
|
269
|
+
REQUIREMENTS-EVIDENCE.md R1–R14 → test chạy được
|
|
270
|
+
SPIKE-REPORT.md kết quả 7 spike kiểm chứng khả thi
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Bằng chứng, không tự khai
|
|
274
|
+
|
|
275
|
+
Mọi cổng đọc `_bmad-output/evidence/{story}.jsonl` — lần chạy test, lần
|
|
276
|
+
sửa file, lần gọi model kèm chi phí và độ trễ, lần đối chiếu mockup. Câu
|
|
277
|
+
"đã hoàn thành" của agent không được tính là gì cả.
|
|
278
|
+
|
|
279
|
+
Cụ thể, một story chỉ xong khi: test xanh **và** xanh sau lần sửa cuối ·
|
|
280
|
+
lint sạch · thay đổi nằm trong phạm vi khai báo · màn hình thật dựng đủ
|
|
281
|
+
component mockup đã hứa · rà soát độc lập (phiên khác, cấm sửa code) không
|
|
282
|
+
còn mục chặn · không có test nào rỗng khẳng định.
|
aisef-0.1.0/README.md
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# AI-SDLC
|
|
2
|
+
|
|
3
|
+
Khung phát triển phần mềm bằng agent. Đầu vào của mỗi dự án là **một file**
|
|
4
|
+
`docs/requirements.md`; đầu ra là một ứng dụng chạy được, kèm bằng chứng
|
|
5
|
+
cho từng bước.
|
|
6
|
+
|
|
7
|
+
Nguyên tắc nền, xuyên suốt mọi quyết định trong kho này:
|
|
8
|
+
|
|
9
|
+
> **Cần phán đoán thì giao cho model. Cần đảm bảo thì viết code.**
|
|
10
|
+
|
|
11
|
+
Viết PRD, thiết kế kiến trúc, dựng mockup, viết code — đều cần phán đoán,
|
|
12
|
+
đều giao cho model. Còn "mọi yêu cầu phải có story phủ", "không được ghi
|
|
13
|
+
ra ngoài phạm vi", "test phải xanh sau lần sửa cuối" — đều có đáp án đúng,
|
|
14
|
+
nên đều là code. Hệ quả: **không bao giờ giao cho model việc giám sát
|
|
15
|
+
chính nó.**
|
|
16
|
+
|
|
17
|
+
## Cài
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install aisef
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Hoặc chạy từ bản sao kho nguồn:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
git clone <repo> ai-sdlc && cd ai-sdlc && pip install -e .
|
|
27
|
+
python3 -m unittest discover -s tests -q # vài phút, không mở container (tests/__init__.py)
|
|
28
|
+
AISDLC_TEST_DOCKER=1 python3 -m unittest tests.test_sandbox tests.test_tools -q # thêm test Docker thật
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Kho skill tham chiếu **không cần clone tay**: `aisdlc setup` tự lấy về
|
|
32
|
+
`~/.cache/ai-sdlc/references` đúng commit mà `aisdlc/kit/catalog.json`
|
|
33
|
+
ghim (khoảng 93 MB, một lần cho mọi dự án). Máy ngoại tuyến hoặc CI trỏ
|
|
34
|
+
sang chỗ khác bằng `AISDLC_REFERENCES=/duong/dan`, hoặc dùng
|
|
35
|
+
`aisdlc setup --no-fetch` để chỉ xài những gì đã có trên đĩa.
|
|
36
|
+
|
|
37
|
+
Không có phụ thuộc Python nào ngoài thư viện chuẩn. Tuỳ chọn:
|
|
38
|
+
`docker` (cách ly khi chạy test), `playwright` (trích hợp đồng thị giác
|
|
39
|
+
từ mockup) — thiếu thì framework **nói thẳng là thiếu** chứ không giả vờ
|
|
40
|
+
vẫn kiểm được.
|
|
41
|
+
|
|
42
|
+
## Sáu bước
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cd /duong/dan/du-an-cua-ban
|
|
46
|
+
|
|
47
|
+
aisdlc doctor # môi trường có đủ chưa
|
|
48
|
+
aisdlc setup # dò stack, nạp skill, sinh CLAUDE.md + AGENTS.md
|
|
49
|
+
aisdlc compile # nối guard vào client (hook / plugin)
|
|
50
|
+
|
|
51
|
+
aisdlc plan # PRD → kiến trúc → UX → epic → story
|
|
52
|
+
aisdlc gates # xem cổng nào đang chờ người
|
|
53
|
+
aisdlc review prd # đọc artifact
|
|
54
|
+
aisdlc approve prd # duyệt
|
|
55
|
+
|
|
56
|
+
aisdlc mockup # mỗi màn hình một HTML + hợp đồng thị giác
|
|
57
|
+
aisdlc approve mockups
|
|
58
|
+
aisdlc approve readiness
|
|
59
|
+
|
|
60
|
+
aisdlc run # hiện thực: epic tuần tự, story song song
|
|
61
|
+
aisdlc run --verify-only --story STORY-01-07 # kiểm lại ứng viên đã đóng băng, không mở phiên developer
|
|
62
|
+
aisdlc qa # bộ kiểm định
|
|
63
|
+
aisdlc devsecops # CI + Dockerfile + triển khai + runbook
|
|
64
|
+
aisdlc pre-deploy # cổng cuối
|
|
65
|
+
aisdlc report # báo cáo nghiệm thu + sổ hành vi + INDEX.md
|
|
66
|
+
aisdlc evidence STORY-01-04 # lịch sử một story hay một hành vi (AC-…, FR-…, qa:e2e)
|
|
67
|
+
aisdlc issues --format csv # bảng gap/hồi quy từ sổ hành vi → _bmad-output/ISSUES.csv
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Chạy nhanh không cần người duyệt: `aisdlc plan --auto-approve all`. Phê duyệt
|
|
71
|
+
tự động **luôn** được ghi dấu `auto` để về sau truy được tài liệu nào chưa
|
|
72
|
+
từng có người thật xem.
|
|
73
|
+
|
|
74
|
+
## Sau khi có code
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
aisdlc doc vitest --topic coverage --story STORY-01-02
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Tra tài liệu thật của thư viện (context7, có cache) thay vì đoán tên API; có
|
|
81
|
+
`--story` thì lần tra vào bằng chứng. Khi yêu cầu đổi sau phát hành:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
aisdlc change FR-3 "Slug phải giữ dấu gạch dưới"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Ghi vào `docs/requirements.md`, đánh dấu PRD (cổng `prd` và các cổng sau
|
|
88
|
+
thành stale), sinh story delta `STORY-CH-01` với `covers=[FR-3]` — story cũ
|
|
89
|
+
giữ nguyên `DONE`.
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
aisdlc improve --epic EPIC-01 --max-loops 3 # [--auto] không dừng ở cổng người
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Vòng cải tiến theo bằng chứng (ADR-004 R3): QA → sổ hành vi → **một** story
|
|
96
|
+
sửa cho một hành vi GAP/REOPENED (`STORY-RP-01` trong `EPIC-RP-01`, sinh bằng
|
|
97
|
+
code) → `run` như story thường → QA → mốc `loops[]` + `LOOP-REPORT-<n>.md`.
|
|
98
|
+
Dừng bằng code: hết gap, đủ `improve.max_loops`, cải thiện biên ≤ 0
|
|
99
|
+
`improve.flat_loops` vòng liền, vượt `improve.cost_cap_usd`, hay story sửa bế
|
|
100
|
+
tắc kế hoạch (trả người kèm lời reviewer). Trước mỗi vòng ≥ 2 cần
|
|
101
|
+
`aisdlc approve improve` trừ `--auto`.
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
aisdlc run --verify-only --story STORY-01-07
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Story trượt chỉ vì môi trường đo (e2e nhạy tải máy) thì không cần trả tiền
|
|
108
|
+
cho một phiên developer để dựng lại mã đã có (ADR-004 R13): lượt kiểm-lại
|
|
109
|
+
lấy ứng viên ở HEAD nhánh story, chạy lại đúng phép kiểm ✗/thiếu ở SHA ấy,
|
|
110
|
+
giữ rà soát và bảo mật đã có ở cùng SHA, chấm đủ cổng; đạt thì merge như lượt
|
|
111
|
+
thường, trượt thì `failed` và không ăn vào `run.max_retries`.
|
|
112
|
+
|
|
113
|
+
## Cổng
|
|
114
|
+
|
|
115
|
+
Tám cổng, mỗi cổng hai lớp. **Cổng máy** chạy trước — nó bắt được thứ máy
|
|
116
|
+
bắt tốt hơn người (chu trình phụ thuộc, yêu cầu không kiểm chứng được,
|
|
117
|
+
story không khai phạm vi ghi). **Cổng người** chạy sau, trên thứ đã sạch.
|
|
118
|
+
|
|
119
|
+
Phê duyệt là **trạng thái trên đĩa**, không phải câu hỏi trong phiên chat:
|
|
120
|
+
người duyệt có thể là người khác, lúc khác, trên máy khác. Bản ghi phê
|
|
121
|
+
duyệt gắn với **băm nội dung** artifact — sửa tài liệu sau khi duyệt thì
|
|
122
|
+
phê duyệt hết hiệu lực, và sửa tầng trên làm mọi tầng dưới thành `stale`.
|
|
123
|
+
|
|
124
|
+
## Guard
|
|
125
|
+
|
|
126
|
+
Tám guard, mỗi guard là một lệnh trả mã thoát, nối vào ba mốc vòng đời:
|
|
127
|
+
|
|
128
|
+
| Mốc | Guard |
|
|
129
|
+
|---|---|
|
|
130
|
+
| trước mỗi tool | `write-scope` · `destructive` · `secret` · `git-stage` · `injection` · `process-ref` (luật 6: không mã story/epic trong nguồn) |
|
|
131
|
+
| sau mỗi tool | `diff-scope` |
|
|
132
|
+
| khi agent định dừng | `completion` |
|
|
133
|
+
|
|
134
|
+
Guard nằm ở phía framework, không ở phía client — client không được tin.
|
|
135
|
+
Cả Claude Code và OpenCode đều đã **chứng minh bằng phép thử trên agent
|
|
136
|
+
thật** rằng guard chặn *trước* khi tool chạy, chứ không phải phát hiện
|
|
137
|
+
sau. Client nào không gắn được guard tiền kiểm thì `aisdlc verify` chạy
|
|
138
|
+
lại toàn bộ trên diff, và `aisdlc compile` ghi rõ mức bảo đảm thấp hơn
|
|
139
|
+
vào báo cáo thay vì im lặng — năng lực là thứ được **khai và kiểm**, mặc
|
|
140
|
+
định là "chưa chứng minh", không phải "chắc là được". Trong V1, OpenCode
|
|
141
|
+
là client **hạng hai** theo quyết định V1: guard chặn được (hợp quy 7/7), và từ 2026-09-05 `--format json` cho luồng máy đọc được (tool, token, cost theo nhà cung cấp) — chưa lên hạng nhất vì chưa đủ số lần hợp quy hook ổn định; chi phí trước đó không đo
|
|
142
|
+
được từ harness; nó không chặn phát hành.
|
|
143
|
+
|
|
144
|
+
## Lỗi thật đã gặp
|
|
145
|
+
|
|
146
|
+
Hai mươi lăm lỗi tìm bằng đo trên agent thật, xếp theo mười một lớp nguyên nhân kèm phép hồi quy: `docs/FAILURE-TAXONOMY.md`. Lỗi mới thì thêm một dòng vào đó cùng commit với test. Thay đổi theo phiên bản, kèm việc phải làm khi nâng cấp: `CHANGELOG.md`.
|
|
147
|
+
|
|
148
|
+
## Hợp quy client
|
|
149
|
+
|
|
150
|
+
Hook và plugin là tạo tác **biên dịch ra** — đúng cú pháp không có nghĩa là
|
|
151
|
+
client chạy chúng. Bốn lỗi thật (31, 39, 40, 41) đều thuộc lớp này, và unit
|
|
152
|
+
test không bắt được theo định nghĩa. Bộ hợp quy chạy bảy phép thử trên
|
|
153
|
+
client thật, worktree thật, guard thật, `.claude/` không commit:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
AISDLC_CONFORMANCE=1 python3 -m unittest tests.conformance -v
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Kết quả ghép vào `docs/CONFORMANCE.md` — mỗi ô là một phiên agent, đọc từ
|
|
160
|
+
đĩa (tệp còn/mất), từ luồng `tool_use` và bằng chứng guard tự ghi, không từ
|
|
161
|
+
lời agent. Dự án thử và log thô từng phép giữ ở `.conformance/<client>/`
|
|
162
|
+
(đổi bằng `AISDLC_CONFORMANCE_DIR`) để tra lại một ô ✗ mà không phải đoán.
|
|
163
|
+
Bộ chạy **không** thừa hưởng biến `CLAUDE_*` của phiên gọi nó — chạy hợp
|
|
164
|
+
quy từ bên trong một phiên Claude là chuyện có thật, và phiên con thừa hưởng
|
|
165
|
+
cờ của phiên cha thì đo sai. Cổng
|
|
166
|
+
phát hành của chính kho này đọc bảng đó bằng code
|
|
167
|
+
(`AISDLC_RELEASE=1 python3 -m unittest tests.test_release_gate`): cột
|
|
168
|
+
`claude` phải đủ năm ô ✅ và bảng không cũ hơn 14 ngày. OpenCode là hạng
|
|
169
|
+
hai trong V1 — có cột, không chặn. CI: `.github/workflows/conformance.yml`
|
|
170
|
+
chạy tuần.
|
|
171
|
+
|
|
172
|
+
## Phát hành
|
|
173
|
+
|
|
174
|
+
Gói phân phối tên **`aisef`** trên PyPI (module Python và lệnh vẫn là `aisdlc`), phát hành khi hoàn tất đợt 4 (quyết định 2026-09-05).
|
|
175
|
+
Điều kiện đọc bằng lệnh, không bằng cảm giác:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
python3 -m unittest discover -s tests -q && AISDLC_RELEASE=1 AISDLC_ACCEPTANCE=<dự án nghiệm thu> python3 -m unittest tests.test_release_gate -q
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
`AISDLC_ACCEPTANCE` trỏ vào dự án dogfood đã nghiệm thu (v0.1.0: `e9`, phạm vi
|
|
182
|
+
EPIC-01): cổng đọc `pre-deploy-report.json` (đạt, có phạm vi, miễn có lý do)
|
|
183
|
+
và phê duyệt `pre-deploy` trên đúng bản ấy. Không đặt thì bỏ qua có nêu tên —
|
|
184
|
+
không tính là đạt.
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
uv build && uvx twine check dist/*
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
`.github/workflows/release.yml` publish bằng *trusted publishing* khi đẩy tag
|
|
191
|
+
`v*` — không có token nào trong kho. Việc làm **một lần bằng tay**, bằng tài
|
|
192
|
+
khoản tổ chức: tạo project `aisef` trên PyPI và khai trusted publisher
|
|
193
|
+
(kho này · workflow `release.yml` · environment `pypi`). Sau đó:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
git tag v0.1.0 && git push --tags
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Kho hồi quy dogfood (`tests/dogfood/`, bật bằng `AISDLC_DOGFOOD=1`) dựng lại
|
|
200
|
+
dự án thử `par` từ đầu vào trong kho và so với mốc đã đo — chạy trước mỗi tag.
|
|
201
|
+
|
|
202
|
+
### Giới hạn đã biết của v0.1.0
|
|
203
|
+
|
|
204
|
+
Khai ở đây vì mọi claim phải có bằng chứng; thứ chưa chứng minh gọi là chưa
|
|
205
|
+
chứng minh (quyết định chủ đầu tư 2026-09-06, `docs/RELEASE-PLAN-v0.1.0.md` §0):
|
|
206
|
+
|
|
207
|
+
- **Phạm vi nghiệm thu dogfood là EPIC-01 của `e9`** (7 story, `aisdlc
|
|
208
|
+
pre-deploy --epic EPIC-01`). EPIC-02..05 (16 story) chưa chạy — báo cáo ghi
|
|
209
|
+
"ngoài phạm vi", không phải "xong". `e9` chưa phải sản phẩm được nghiệm thu
|
|
210
|
+
hoàn chỉnh; nó là corpus nghiệm thu của framework.
|
|
211
|
+
- **OpenCode là client hạng hai**: hợp quy 9/10 (C9 model từ chối, không kết
|
|
212
|
+
luận), không có đầu ra máy đọc ổn định; claim phát hành dựa trên Claude Code.
|
|
213
|
+
- **Agent trong container chưa có cách ly credential** (S1 blocked): V1 chạy
|
|
214
|
+
agent trên host, chỉ kiểm định trong container; `doctor`/`pre-deploy` nêu
|
|
215
|
+
tên bảo đảm thiếu, không im lặng.
|
|
216
|
+
- **`mutation` ở môi trường nghiệm thu là KHÔNG CHẠY ĐƯỢC** (công cụ chưa cài);
|
|
217
|
+
được miễn có lý do ở `verify.waiver_reason`, hiện ◇, không bao giờ thành ✅.
|
|
218
|
+
`image-scan` cùng loại (docker scout đòi đăng nhập, trivy/grype vắng).
|
|
219
|
+
- **`skills.offer`/`skills.inline` tắt** (A/B không thấy gain), **`repo_map`
|
|
220
|
+
tắt** (`context.max_repo_map_chars = 0`, A/B hoãn sau v0.1.0).
|
|
221
|
+
- **`coverage`**: harness đọc số từ runner (`--coverage`/`--cov`); dự án chưa
|
|
222
|
+
bật thì mục cổng là ○ chưa cấu hình, không phải đạt.
|
|
223
|
+
|
|
224
|
+
## Khi cổng chặn
|
|
225
|
+
|
|
226
|
+
Cổng chặn là framework đang làm việc, không phải framework hỏng. Ba ca hay
|
|
227
|
+
gặp và cách xử đúng:
|
|
228
|
+
|
|
229
|
+
| Cổng báo | Nghĩa là | Làm gì |
|
|
230
|
+
|---|---|---|
|
|
231
|
+
| `mockup còn N chỗ chưa chốt` | mockup gặp câu hỏi chưa ai trả lời và **đánh dấu** thay vì tự quyết | trả lời câu hỏi (thường nằm ở `open_questions` của PRD/UX), sửa tài liệu, dựng lại mockup |
|
|
232
|
+
| `story đụng vào yêu cầu đang bị câu hỏi mở chặn` | epic gán một FR mà PRD ghi là chưa quyết được | trả lời câu hỏi, hoặc bỏ FR đó khỏi story |
|
|
233
|
+
| `merge đụng …` | hai story cùng sửa một file | `write_scope` khai sai — sửa ở story, **không** gỡ conflict cho xong |
|
|
234
|
+
|
|
235
|
+
`--force` có ở `approve` và `run` cho trường hợp cố ý bỏ qua. Dùng nó là
|
|
236
|
+
một quyết định, và nó được ghi lại: bản ghi phê duyệt giữ ghi chú, báo cáo
|
|
237
|
+
nghiệm thu hiện đúng trạng thái từng cổng.
|
|
238
|
+
|
|
239
|
+
## Chạy song song
|
|
240
|
+
|
|
241
|
+
Epic chạy tuần tự. Trong một epic, hai story chỉ được cùng đợt khi **hết
|
|
242
|
+
phụ thuộc** *và* **phạm vi ghi rời nhau** — thiếu điều kiện thứ hai thì hai
|
|
243
|
+
story cùng sửa một file và người thua là người merge sau. Mỗi story chạy
|
|
244
|
+
trong worktree git riêng; merge tuần tự cuối đợt. Conflict lúc merge không
|
|
245
|
+
được tự gỡ: nó là **bằng chứng `write_scope` khai sai**.
|
|
246
|
+
|
|
247
|
+
## Cấu trúc
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
aisdlc/
|
|
251
|
+
cli/ bộ lệnh chia theo pha, mọi lệnh gọi-một-lần, không daemon
|
|
252
|
+
config.py ngưỡng và cấu hình, có kiểu, có kiểm
|
|
253
|
+
clients/ Claude Code · OpenCode; năng lực được **khai**, không giả định
|
|
254
|
+
control/ cổng, phê duyệt, xếp lịch, worktree, chuẩn hoá tài liệu BMAD
|
|
255
|
+
harness/ prompt · tool · sandbox · guard · quan sát · map mockup
|
|
256
|
+
kit/ catalog skill, lọc bảo mật hai tầng, hiến pháp, prompt, skill riêng
|
|
257
|
+
phases/ plan · mockup · implement · run · qa · deploy · report
|
|
258
|
+
docs/
|
|
259
|
+
SOLUTION.md giải pháp tổng thể và vì sao chọn như vậy
|
|
260
|
+
EXECUTION-PLAN.md kế hoạch thực thi, trạng thái từng hạng mục
|
|
261
|
+
REQUIREMENTS-EVIDENCE.md R1–R14 → test chạy được
|
|
262
|
+
SPIKE-REPORT.md kết quả 7 spike kiểm chứng khả thi
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Bằng chứng, không tự khai
|
|
266
|
+
|
|
267
|
+
Mọi cổng đọc `_bmad-output/evidence/{story}.jsonl` — lần chạy test, lần
|
|
268
|
+
sửa file, lần gọi model kèm chi phí và độ trễ, lần đối chiếu mockup. Câu
|
|
269
|
+
"đã hoàn thành" của agent không được tính là gì cả.
|
|
270
|
+
|
|
271
|
+
Cụ thể, một story chỉ xong khi: test xanh **và** xanh sau lần sửa cuối ·
|
|
272
|
+
lint sạch · thay đổi nằm trong phạm vi khai báo · màn hình thật dựng đủ
|
|
273
|
+
component mockup đã hứa · rà soát độc lập (phiên khác, cấm sửa code) không
|
|
274
|
+
còn mục chặn · không có test nào rỗng khẳng định.
|
|
File without changes
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Giao diện dòng lệnh.
|
|
2
|
+
|
|
3
|
+
Mọi lệnh đều **gọi-một-lần**: đọc trạng thái trên đĩa, làm việc, ghi lại,
|
|
4
|
+
rồi thoát. Không lệnh nào giả định mình là tiến trình chính, không lệnh
|
|
5
|
+
nào chạy nền. Đó là điều kiện để cùng bộ lệnh này dùng được ở hai chế độ
|
|
6
|
+
(quyết định Đ2):
|
|
7
|
+
|
|
8
|
+
* **driver-led** — script hoặc CI gọi ``aisdlc run``;
|
|
9
|
+
* **agent-led** — chính agent gọi ``aisdlc next`` / ``verify`` / ``complete``
|
|
10
|
+
qua Bash, ngay trong phiên chat của Claude Desktop hay OpenCode.
|
|
11
|
+
|
|
12
|
+
Quy ước mã thoát: ``0`` thành công · ``1`` lỗi dùng sai · ``2`` trạng thái
|
|
13
|
+
chưa đạt (cổng chưa duyệt, doctor không đạt) — để CI phân biệt được
|
|
14
|
+
"hỏng" với "chưa xong".
|
|
15
|
+
|
|
16
|
+
Bố cục gói (chia theo pha, không đổi hành vi):
|
|
17
|
+
|
|
18
|
+
* :mod:`._common` — mã thoát, gốc artifact, kho duyệt/trạng thái, adapter;
|
|
19
|
+
* :mod:`.doctor` — lệnh ``doctor``;
|
|
20
|
+
* :mod:`.plan` — cổng người + pha lập kế hoạch;
|
|
21
|
+
* :mod:`.implement` — pha hiện thực và nghiệm thu;
|
|
22
|
+
* :mod:`.harness` — dựng và vận hành harness;
|
|
23
|
+
* :mod:`.parser` — bộ phân tích tham số và ``main``.
|
|
24
|
+
|
|
25
|
+
Mọi tên module-level cũ được xuất lại ở đây, nên ``from aisdlc.cli import
|
|
26
|
+
main`` và bạn bè vẫn chạy y như khi còn là một file.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from __future__ import annotations
|
|
30
|
+
|
|
31
|
+
from ._common import (
|
|
32
|
+
ARTIFACT_ROOT,
|
|
33
|
+
_GATE_MARK,
|
|
34
|
+
EXIT_NOT_READY,
|
|
35
|
+
EXIT_OK,
|
|
36
|
+
EXIT_USAGE,
|
|
37
|
+
_approvals,
|
|
38
|
+
_artifact_root,
|
|
39
|
+
_client,
|
|
40
|
+
_gate_arg,
|
|
41
|
+
_state,
|
|
42
|
+
)
|
|
43
|
+
from .doctor import _hook_paths_elsewhere, cmd_doctor
|
|
44
|
+
from .harness import cmd_compile, cmd_doc, cmd_guard, cmd_init, cmd_setup, cmd_skill
|
|
45
|
+
from .implement import (
|
|
46
|
+
_project_has_ui,
|
|
47
|
+
cmd_devsecops,
|
|
48
|
+
cmd_evidence,
|
|
49
|
+
cmd_predeploy,
|
|
50
|
+
cmd_qa,
|
|
51
|
+
cmd_report,
|
|
52
|
+
cmd_run,
|
|
53
|
+
cmd_status,
|
|
54
|
+
cmd_tool,
|
|
55
|
+
cmd_verify,
|
|
56
|
+
)
|
|
57
|
+
from .parser import build_parser, main
|
|
58
|
+
from .plan import (
|
|
59
|
+
_preflight_lines,
|
|
60
|
+
cmd_approve,
|
|
61
|
+
cmd_auto_approve,
|
|
62
|
+
cmd_change,
|
|
63
|
+
cmd_gates,
|
|
64
|
+
cmd_mockup,
|
|
65
|
+
cmd_plan,
|
|
66
|
+
cmd_reject,
|
|
67
|
+
cmd_review,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
__all__ = [
|
|
71
|
+
"ARTIFACT_ROOT",
|
|
72
|
+
"EXIT_NOT_READY",
|
|
73
|
+
"EXIT_OK",
|
|
74
|
+
"EXIT_USAGE",
|
|
75
|
+
"build_parser",
|
|
76
|
+
"cmd_approve",
|
|
77
|
+
"cmd_auto_approve",
|
|
78
|
+
"cmd_change",
|
|
79
|
+
"cmd_compile",
|
|
80
|
+
"cmd_devsecops",
|
|
81
|
+
"cmd_doc",
|
|
82
|
+
"cmd_doctor",
|
|
83
|
+
"cmd_evidence",
|
|
84
|
+
"cmd_gates",
|
|
85
|
+
"cmd_guard",
|
|
86
|
+
"cmd_init",
|
|
87
|
+
"cmd_mockup",
|
|
88
|
+
"cmd_plan",
|
|
89
|
+
"cmd_predeploy",
|
|
90
|
+
"cmd_qa",
|
|
91
|
+
"cmd_reject",
|
|
92
|
+
"cmd_report",
|
|
93
|
+
"cmd_review",
|
|
94
|
+
"cmd_run",
|
|
95
|
+
"cmd_setup",
|
|
96
|
+
"cmd_skill",
|
|
97
|
+
"cmd_status",
|
|
98
|
+
"cmd_tool",
|
|
99
|
+
"cmd_verify",
|
|
100
|
+
"main",
|
|
101
|
+
]
|