codex-harness-engineering 0.1.4 → 0.1.6

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.
Files changed (34) hide show
  1. package/AGENTS.md +18 -6
  2. package/LICENSE +21 -0
  3. package/README.md +69 -6
  4. package/docs/harness-engineering/implementation-playbook.md +232 -286
  5. package/docs/harness-engineering/index.md +7 -4
  6. package/docs/harness-engineering/research-note.md +294 -274
  7. package/docs/harness-engineering/sources.md +166 -72
  8. package/package.json +9 -4
  9. package/scripts/install-skills.mjs +73 -15
  10. package/scripts/publish.sh +2 -2
  11. package/scripts/verify-harness.mjs +61 -4
  12. package/skills/acceptance-contract/SKILL.md +39 -49
  13. package/skills/acceptance-contract/agents/openai.yaml +2 -2
  14. package/skills/cleanup-harness/SKILL.md +48 -59
  15. package/skills/cleanup-harness/agents/openai.yaml +2 -2
  16. package/skills/creator-harness/SKILL.md +79 -95
  17. package/skills/creator-harness/agents/openai.yaml +2 -2
  18. package/skills/creator-harness/references/harness-artifacts.md +63 -62
  19. package/skills/lessons-harness/SKILL.md +68 -0
  20. package/skills/lessons-harness/agents/openai.yaml +4 -0
  21. package/templates/harness/AGENTS.md +77 -0
  22. package/templates/harness/feature_list.json +16 -0
  23. package/templates/harness/init.sh +15 -0
  24. package/templates/harness/lessons.md +18 -0
  25. package/templates/harness/memory/README.md +22 -0
  26. package/templates/harness/progress.md +33 -0
  27. package/templates/harness/rotate-state.mjs +131 -0
  28. package/templates/harness/verify-state.mjs +117 -0
  29. package/templates/team/roles/evaluator.md +43 -0
  30. package/templates/team/roles/implementer.md +29 -0
  31. package/templates/team/roles/planner.md +28 -0
  32. package/templates/team/sprint-template.md +36 -0
  33. package/templates/team/verify-team.mjs +71 -0
  34. package/templates/team/workflow.md +62 -0
@@ -1,7 +1,7 @@
1
1
  # Nguồn
2
2
 
3
- File này chỉ theo dõi bốn nguồn được phép dùng trong bản nghiên cứu hiện tại.
4
- Không thêm claim vào tài liệu nếu claim đó không ánh xạ tới một trong bốn nguồn
3
+ File này theo dõi năm nguồn được phép dùng trong bản nghiên cứu hiện tại.
4
+ Không thêm claim vào tài liệu nếu claim đó không ánh xạ tới một trong năm nguồn
5
5
  này hoặc không được đánh dấu rõ là diễn giải.
6
6
 
7
7
  ## Danh mục nguồn
@@ -9,23 +9,75 @@ này hoặc không được đánh dấu rõ là diễn giải.
9
9
  ### [S1] OpenAI
10
10
 
11
11
  - Tiêu đề: "Harness engineering: leveraging Codex in an agent-first world"
12
- - Tác giả: Ryan Lopopolo
13
- - Ngày xuất bản: 11 tháng 2, 2026
12
+ - Tác giả: Ryan Lopopolo (Member of the Technical Staff)
13
+ - Ngày xuất bản: 11 tháng 2, 2026 (bản clipping nội bộ ghi published 2026-05-27;
14
+ giữ Feb 2026 theo trích dẫn gốc — xem ghi chú cuối mục)
14
15
  - URL: https://openai.com/index/harness-engineering/
16
+ - Bối cảnh: thí nghiệm 5 tháng (commit đầu cuối tháng 8/2025), team lái Codex để
17
+ ship một sản phẩm beta nội bộ ~1 triệu dòng code với **0 dòng code viết tay**;
18
+ ~1.500 PR đã merge; team từ 3 lên 7 kỹ sư, throughput ~3.5 PR/kỹ sư/ngày và
19
+ *tăng* khi team lớn lên; ước tính nhanh hơn ~10 lần so với viết tay.
15
20
  - Dùng cho:
16
- - framing "humans steer, agents execute";
21
+ - framing "humans steer, agents execute": con người prioritize, dịch feedback
22
+ thành acceptance criteria, validate kết quả; khi agent vướng, hỏi "thiếu
23
+ capability nào và làm sao để agent thấy được + cưỡng chế được", rồi để chính
24
+ Codex viết bản sửa — không bao giờ tự sửa code tay;
17
25
  - harness engineering như thiết kế environment, intent specification, và
18
- feedback loop quanh Codex;
19
- - repository knowledge base như system of record;
20
- - `AGENTS.md` như bản đồ, không phải cẩm nang khổng lồ;
21
- - ưu tiên dependency, abstraction, thông tin agent thể inspect,
22
- validate, modify trực tiếp trong repo;
23
- - application, browser, log, metric, trace như tín hiệu agent đọc được;
24
- - progressive disclosure cho tri thức trong repo kiểm tra cơ học về
25
- freshness/cross-link để giảm drift của tài liệu;
26
- - cưỡng chế architecturetaste bằng lint, structural test, và custom rule;
27
- - throughput, merge philosophy, autonomy, entropy, cleanup định kỳ;
28
- - cảnh báo rằng mức tự chủ phụ thuộc vào cấu trúc tooling cụ thể của repo.
26
+ feedback loop quanh Codex; làm depth-first: chẻ goal lớn thành building block
27
+ (design, code, review, test) để mở khóa task phức tạp hơn;
28
+ - vòng lặp PR kiểu "Ralph Wiggum": Codex tự review local, xin thêm agent review
29
+ local + cloud, phản hồi feedback, lặp tới khi mọi reviewer hài lòng; review
30
+ đẩy gần như hoàn toàn sang agent-to-agent, human review không bắt buộc;
31
+ - application legibility: app bootable theo từng git worktree; nối Chrome
32
+ DevTools Protocol vào agent runtime + skill cho DOM snapshot/screenshot/
33
+ navigation để Codex tái hiện bug và validate fix; observability stack ephemeral
34
+ theo worktree, query log bằng LogQL metric bằng PromQL, làm prompt kiểu
35
+ "service startup < 800ms" hay "không span nào > 2s" trở nên tractable;
36
+ - repository knowledge base cấu trúc (`docs/` với design-docs, exec-plans,
37
+ product-specs, references llms.txt, ARCHITECTURE/QUALITY_SCORE/RELIABILITY…)
38
+ là system of record; plan là artifact hạng nhất, exec-plan kèm progress +
39
+ decision log được check-in;
40
+ - `AGENTS.md` như bản đồ / mục lục ngắn (~100 dòng) inject vào context, trỏ tới
41
+ nguồn sự thật sâu hơn — không phải encyclopedia một-file (one-big-AGENTS.md
42
+ thất bại vì: chiếm context, "everything important = nothing important", rot
43
+ nhanh, khó verify cơ học);
44
+ - progressive disclosure: agent bắt đầu từ entry point nhỏ ổn định rồi được chỉ
45
+ nơi xem tiếp; linter + CI validate knowledge base up-to-date/cross-linked,
46
+ cùng agent "doc-gardening" định kỳ quét doc cũ và mở PR sửa;
47
+ - agent legibility là mục tiêu: "thứ agent không truy cập được in-context coi
48
+ như không tồn tại" — phải đẩy context (kể cả thảo luận Slack) vào repo dạng
49
+ versioned artifact;
50
+ - ưu tiên dependency và abstraction có thể nội-hóa và lập luận in-repo; công
51
+ nghệ "boring" dễ model hơn; đôi khi rẻ hơn khi để agent tự reimplement một
52
+ phần thay vì lệ thuộc hành vi opaque upstream (vd tự viết map-with-concurrency
53
+ thay cho `p-limit`, tích hợp OpenTelemetry, 100% test coverage);
54
+ - cưỡng chế architecture và taste bằng invariant, không micromanage cài đặt:
55
+ mỗi business domain chia layer cố định, dependency chỉ đi "tiến"
56
+ `Types → Config → Repo → Service → Runtime → UI`, cross-cutting concern (auth,
57
+ connector, telemetry, feature flag) vào qua một interface duy nhất Providers;
58
+ enforce bằng custom linter (do Codex sinh) + structural test, error message
59
+ chèn luôn hướng dẫn remediation vào context; enforce boundary tập trung, cho
60
+ tự do cục bộ;
61
+ - throughput đổi merge philosophy: merge gate tối thiểu, PR ngắn hạn, test flake
62
+ xử lý bằng re-run thay vì block — correction rẻ, chờ đợi mới đắt;
63
+ - autonomy: repo đã vượt ngưỡng để Codex end-to-end một feature (validate state,
64
+ reproduce bug, quay video lỗi, fix, validate bằng cách drive app, quay video
65
+ fix, mở PR, phản hồi feedback, sửa build fail, escalate khi cần judgment,
66
+ merge) — nhưng *phụ thuộc nặng vào structure/tooling của repo này, chưa nên
67
+ giả định generalize nếu không đầu tư tương tự*;
68
+ - entropy và "garbage collection": Codex nhân bản cả pattern dở → drift; thay vì
69
+ dọn "AI slop" thủ công mỗi thứ Sáu (20% tuần, không scale), encode "golden
70
+ principle" + background task định kỳ quét deviation, cập nhật quality grade,
71
+ mở PR refactor nhỏ (review < 1 phút, automerge); tech debt như khoản vay lãi
72
+ cao, trả dần liên tục;
73
+ - frontier kế tiếp: thiết kế environment, feedback loop, và control system để
74
+ agent xây + bảo trì phần mềm phức tạp, tin cậy ở quy mô lớn; chưa rõ
75
+ coherence kiến trúc tiến hóa thế nào qua nhiều năm trong hệ thuần agent.
76
+
77
+ Ghi chú ngày: bài mô tả commit đầu "late August 2025" + "five months later", và
78
+ được InfoQ đưa tin tháng 2/2026, nên dùng 11/2/2026. Bản clipping nội bộ ghi
79
+ `published: 2026-05-27` (nhiều khả năng là metadata clip sai); nếu cần con số
80
+ chính thức, xác minh lại trên trang OpenAI.
29
81
 
30
82
  ### [S2] Anthropic
31
83
 
@@ -34,13 +86,21 @@ này hoặc không được đánh dấu rõ là diễn giải.
34
86
  - Ngày xuất bản: 26 tháng 11, 2025
35
87
  - URL: https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents
36
88
  - Dùng cho:
37
- - failure mode của agent qua nhiều context window;
38
- - initializer agent coding agent;
39
- - feature list dạng JSON với trạng thái pass/fail;
40
- - tiến triển từng feature thay làm quá rộng;
41
- - progress file, git commit, `init.sh`;
42
- - kiểm thử đầu-cuối bằng browser automation;
43
- - vòng bắt đầu session: đọc progress, feature list, git log, setup, smoke test.
89
+ - failure mode của agent qua nhiều context window (như kỹ sư làm theo ca mà
90
+ không nhớ ca trước), cần externalize state;
91
+ - tách initializer agent (dựng `init.sh`, file progress, git commit đầu) khỏi
92
+ coding agent (làm tăng tiến từng phần, để lại code sạch mergeable);
93
+ - feature list dạng JSON (vài trăm feature) với category, tả kèm bước kiểm
94
+ chứng, trường boolean `passes`; không được xóa/sửa test;
95
+ - tiến triển từng feature một thay làm quá rộng để tránh cạn context giữa
96
+ chừng;
97
+ - progress file, git commit mô tả rõ (cho phép revert/khôi phục), và `init.sh`
98
+ để khỏi tốn thời gian setup;
99
+ - kiểm thử đầu-cuối bằng browser automation (Puppeteer MCP), kiểm như người
100
+ dùng thay vì chỉ unit test/API;
101
+ - vòng bắt đầu session: `pwd`, đọc git log + progress, đọc feature list và chọn
102
+ feature ưu tiên cao chưa xong, chạy `init.sh`, smoke test, rồi mới code;
103
+ - hướng mở rộng: multi-agent chuyên cho test, QA, và cleanup.
44
104
 
45
105
  ### [S3] Anthropic
46
106
 
@@ -49,13 +109,22 @@ này hoặc không được đánh dấu rõ là diễn giải.
49
109
  - Ngày xuất bản: 19 tháng 12, 2024
50
110
  - URL: https://www.anthropic.com/engineering/building-effective-agents
51
111
  - Dùng cho:
52
- - phân biệt workflow định tuyến sẵn và agent tự điều khiển process/tool;
53
- - nguyên tắc bắt đầu bằng giải pháp đơn giản nhất;
54
- - tradeoff giữa performance, latency, cost, complexity;
55
- - building block "augmented LLM" với retrieval, tool, memory;
56
- - workflow pattern như prompt chaining, routing, parallelization,
57
- orchestrator-workers, evaluator-optimizer;
58
- - thiết kế agent-computer interface tool definition dễ dùng.
112
+ - phân biệt workflow (LLM + tool đi theo predefined code path) và agent (LLM tự
113
+ điều khiển process tool usage);
114
+ - nguyên tắc bắt đầu bằng giải pháp đơn giản nhất, chỉ tăng complexity khi cần;
115
+ thường tối ưu single LLM call với retrieval + in-context example là đủ;
116
+ - tradeoff: agentic system đánh đổi latency và cost để có task performance tốt
117
+ hơn, phải cân nhắc khi nào đáng;
118
+ - building block "augmented LLM" với retrieval, tool, memory, kèm interface
119
+ dễ dùng và tài liệu tốt;
120
+ - workflow pattern: prompt chaining, routing, parallelization (sectioning +
121
+ voting), orchestrator-workers, evaluator-optimizer, kèm khi nào dùng;
122
+ - agent như LLM dùng tool dựa trên feedback môi trường trong vòng lặp, cần
123
+ sandbox + guardrail + human oversight tại checkpoint;
124
+ - thiết kế agent-computer interface (ACI) như đầu tư ngang HCI: đặt mình vào vị
125
+ trí model, đặt tên tham số rõ, test nhiều input, áp dụng poka-yoke; ví dụ
126
+ SWE-bench dùng absolute filepath để loại lỗi đường dẫn tương đối;
127
+ - ba nguyên tắc lõi: simplicity, transparency, và tool documentation kỹ.
59
128
 
60
129
  ### [S4] Anthropic
61
130
 
@@ -64,58 +133,83 @@ này hoặc không được đánh dấu rõ là diễn giải.
64
133
  - Ngày xuất bản: 24 tháng 3, 2026
65
134
  - URL: https://www.anthropic.com/engineering/harness-design-long-running-apps
66
135
  - Dùng cho:
67
- - vấn đề context anxiety và self-evaluation;
68
- - tách generator khỏi evaluator;
69
- - grading criteria để làm chất lượng chủ quan dễ chấm hơn;
70
- - planner-generator-evaluator cho phát triển ứng dụng dài hạn;
71
- - sprint contract giữa generator evaluator;
72
- - QA bằng Playwright qua UI, API, database state, hành vi runtime;
73
- - chi phí, độ trễ, token cost của harness phức tạp;
74
- - nguyên tắc xem lại harness khi model mới làm một số lớp orchestration không
75
- còn load-bearing.
76
-
77
- ### [S5] Google
78
-
79
- - Tiêu đề: "AutoHarness: Improving LLM Agents by Automatically Synthesizing a Code Harness" (Google DeepMind) và thực tiễn vận hành Agent/Evaluation Harness trên Google Cloud.
80
- - Tác giả: Google DeepMind & Google Cloud
81
- - Ngày xuất bản: 2024-2026
82
- - URL: https://arxiv.org/abs/2406.11252
136
+ - context anxiety (model "wrap up" sớm khi tưởng sắp hết context) và self-
137
+ evaluation bias (agent khen chính sản phẩm của mình dù chất lượng tầm
138
+ thường), nặng nhất với việc mang tính chủ quan;
139
+ - tách generator khỏi evaluator: tinh chỉnh một evaluator độc lập dễ hơn nhiều
140
+ so với bắt generator tự phê phán công việc của chính nó;
141
+ - grading criteria để làm chất lượng chủ quan dễ chấm hơn (ví dụ frontend:
142
+ design quality, originality, craft, functionality, nhấn mạnh design
143
+ originality nơi model thường yếu);
144
+ - kiến trúc planner-generator-evaluator cho phát triển ứng dụng dài hạn;
145
+ - sprint contract: thỏa thuận về phạm vi và định nghĩa "done" trước khi
146
+ implement;
147
+ - QA bằng Playwright MCP qua UI, API, database state, và hành vi runtime (ví dụ
148
+ bắt lỗi route-matching FastAPI, lỗi đồng bộ state);
149
+ - chi phí/độ trễ/token của harness phức tạp như tradeoff thực (so sánh
150
+ single-agent ~20 phút/$9 cho ra sản phẩm hỏng vs full harness ~6 giờ/$200 cho
151
+ ra sản phẩm hoàn chỉnh; V2 ~3h50/$124.70);
152
+ - nguyên tắc "every component in a harness encodes an assumption about what the
153
+ model can't do on its own": khi Opus 4.6 xử lý long-context và planning tốt
154
+ hơn, sprint decomposition trở thành overhead và bị bỏ, giữ lại planner +
155
+ evaluator — harness phải được xem lại khi model mới xuất hiện.
156
+
157
+ ### [S5] Google DeepMind
158
+
159
+ - Tiêu đề: "AutoHarness: improving LLM agents by automatically synthesizing a code harness"
160
+ - Tác giả: Xinghua Lou, Miguel Lázaro-Gredilla, Antoine Dedieu, Carter Wendelken,
161
+ Wolfgang Lehrach, Kevin P. Murphy
162
+ - Ngày xuất bản: 10 tháng 2, 2026
163
+ - URL: https://arxiv.org/abs/2603.03329
83
164
  - Dùng cho:
84
- - AutoHarness: Tự động tổng hợp lớp bọc thực thi (code harness/wrapper) bằng LLM để chặn hành động lỗi và cưỡng chế ràng buộc;
85
- - Harness-as-Policy: Biên dịch chính sách quyết định thành code tĩnh để giảm chi phí/độ trễ runtime về 0;
86
- - Trajectory Evaluation: Đánh giá vết chạy đầy đủ (gồm tool call, suy luận) thay vì chỉ chấm điểm kết quả tĩnh;
87
- - LLM-as-a-Judge tự động & Meta-Evaluation (VeRO) để liên tục tối ưu cấu trúc của agent.
165
+ - vấn đề agent thường thử hành động không hợp lệ trong môi trường (ví dụ 78% số
166
+ ván thua của Gemini-2.5-Flash trong Kaggle GameArena cờ vua do nước đi
167
+ không hợp lệ);
168
+ - AutoHarness: model tự tổng hợp lớp bọc thực thi (code harness/wrapper) bằng
169
+ một số ít vòng iterative code refinement dựa trên feedback từ môi trường, để
170
+ chặn hành động không hợp lệ trước khi chúng tác động tới môi trường;
171
+ - harness sinh tự động giúp model nhỏ hơn (Gemini-2.5-Flash) vượt model lớn hơn
172
+ (Gemini-2.5-Pro) — ngăn nước đi không hợp lệ qua 145 ván TextArena;
173
+ - code-as-policy: sinh toàn bộ policy thành code tĩnh để loại bỏ LLM call ở thời
174
+ điểm ra quyết định, giảm chi phí và độ trễ runtime; code-policy đạt average
175
+ reward cao hơn cả Gemini-2.5-Pro và GPT-5.2-High trên 16 game single-player.
88
176
 
89
177
  ## Bản đồ bằng chứng
90
178
 
91
179
  | Nhận định | Nguồn |
92
180
  | --- | --- |
93
181
  | Harness engineering chuyển trọng tâm kỹ sư từ viết code tay sang thiết kế môi trường, intent, và feedback loop. | [S1] |
94
- | Repository-local knowledge giúp agent truy cập quyết định, quy tắc,trạng thái không phụ thuộc chat history. | [S1] |
95
- | `AGENTS.md` nên bản đồ ngắn trỏ tới nguồn sự thật sâu hơn, không phải một manual khổng lồ. | [S1] |
96
- | Chọn dependency và abstraction nên tính đến việc agent thể inspect, validate, modify chúng trực tiếp; hành vi opaque upstream làm giảm leverage. | [S1] |
97
- | Agent cần application legibility: UI, log, metric, trace, môi trường dev thể quan sát được. | [S1] |
98
- | Repository knowledge nên theo progressive disclosure kiểm tra học cho freshness/cross-link; doc-gardening định kỳ giúp giảm drift của source of truth. | [S1] |
99
- | Documentation đơn thuần không đủ; architecture taste nên được cưỡng chế bằng lint, structural test, custom rule. | [S1] |
100
- | Throughput cao làm entropy tích lũy nhanh, nên cleanup định kỳ một phần của harness. | [S1] |
101
- | Agent dài hạn dễ mất context giữa các sessioncần externalized state. | [S2] |
102
- | Feature list, progress file, git history, `init.sh` giúp session mới phục hồi trạng thái. | [S2] |
103
- | Feature list dạng JSON giúp agent giữ trạng thái feature cấu trúc cập nhật pass/fail nhất quán qua nhiều session. | [S2] |
104
- | Git commit tả progress update không chỉ để audit; chúng còn tạo checkpoint để agent revert thay đổi xấu khôi phục working state sạch hơn. | [S2] |
105
- | Làm từng feature chỉ đánh dấu pass sau kiểm thử giúp giảm tuyên bố hoàn thành sớm. | [S2] |
106
- | Browser automation giúp agent phát hiện lỗi không thấy được từ code hoặc unit test đơn lẻ. | [S2] |
107
- | Agentic system nên bắt đầu bằng giải pháp đơn giản nhất chỉ tăng complexity khi cần. | [S3] |
182
+ | Khi agent gặp lỗi, phản xạ đúng hỏi "thiếu capability nào làm sao agent thấy + cưỡng chế được", không phải tự sửa tay. | [S1] |
183
+ | Repository-local knowledge có cấu trúc (`docs/`)system of record, giúp agent truy cập quyết định/quy tắc/trạng thái mà không phụ thuộc chat history tránh lệch doc–implementation. | [S1] |
184
+ | `AGENTS.md` nên bản đồ ngắn (~100 dòng) trỏ tới nguồn sự thật sâu hơn, không phải manual khổng lồ một-file. | [S1] |
185
+ | Kiến trúc phân lớp với dependency chỉ đi tiến (`Types → Config → Repo → Service → Runtime → UI`) ràng buộc cho phép tốc độ không bị architectural drift. | [S1] |
186
+ | Chọn dependency và abstraction nên tính đến việc agentthể inspect, validate, modify trực tiếp; hành vi opaque upstream làm giảm leverage. | [S1] |
187
+ | Agent cần application legibility: log, metric, span/trace để giám sát hiệu năng tái hiện bug qua môi trường dev cô lập. | [S1] |
188
+ | Repository knowledge nên theo progressive disclosure kiểm tra học cho freshness/cross-link (linter + CI) để giảm drift. | [S1] |
189
+ | Documentation đơn thuần không đủ; architecture taste nên được cưỡng chế bằng custom linter, structural test, mechanical rule. | [S1] |
190
+ | Review thể đẩy gần hết sang agent-to-agent qua vòng lặp tự-review + xin agent review tới khi reviewer hài lòng; human review không bắt buộc. | [S1] |
191
+ | Throughput cao đổi merge philosophy: merge gate tối thiểu, PR ngắn hạn, test flake re-run thay block correction rẻ, chờ đợi đắt. | [S1] |
192
+ | Throughput cao làm entropy tích lũy nhanh; encode "golden principle" + background task định kỳ mở PR refactor nhỏ (automerge) thay cho dọn slop thủ công một phần của harness. | [S1] |
193
+ | Mức autonomy end-to-end của agent phụ thuộc nặng vào structure/tooling cụ thể của repo, không nên giả định generalize nếu chưa đầu tư tương đương. | [S1] |
194
+ | Agent dài hạn dễ mất context giữa các session (như làm theo ca không nhớ ca trước) và cần externalized state. | [S2] |
195
+ | Tách initializer agent (dựng `init.sh`, progress, git) khỏi coding agent (làm tăng tiến, để lại code mergeable) giúp session mới phục hồi trạng thái. | [S2] |
196
+ | Feature list dạng JSON với category, bước kiểm chứng, và trường `passes` giữ trạng thái feature có cấu trúc và nhất quán qua nhiều session; không được xóa/sửa test. | [S2] |
197
+ | Git commit mô tả rõ và progress update tạo checkpoint để agent revert thay đổi xấu và khôi phục working state sạch. | [S2] |
198
+ | Làm từng feature và chỉ đánh dấu pass sau kiểm thử đầu-cuối giúp giảm tuyên bố hoàn thành sớm. | [S2] |
199
+ | Browser automation (Puppeteer MCP) giúp agent phát hiện lỗi không thấy được từ code hoặc unit test đơn lẻ. | [S2] |
200
+ | Agentic system nên bắt đầu bằng giải pháp đơn giản nhất và chỉ tăng complexity khi cần; thường single LLM call + retrieval/example là đủ. | [S3] |
108
201
  | Workflow phù hợp với task có đường đi định sẵn; agent phù hợp khi cần model tự quyết định tool/process. | [S3] |
109
- | Tool nên được thiết kế như agent-computer interface với tả, tham số, ranh giới, dụ rõ. | [S3] |
202
+ | Agentic system đánh đổi latency cost để lấy task performance, phải cân nhắc khi nào đáng. | [S3] |
203
+ | Tool nên được thiết kế như agent-computer interface với mô tả, tham số, ranh giới, ví dụ rõ, và áp dụng poka-yoke để chống lạm dụng. | [S3] |
110
204
  | Generator tự đánh giá thường quá tích cực; evaluator riêng dễ được chỉnh thành hoài nghi hơn. | [S4] |
111
- | Sprint contract giúp generator evaluator đồng thuận về phạm vi, tiêu chí done, phương thức QA. | [S4] |
112
- | Context reset thể một phần chủ đích của harness; nếu state handoff đủ tốt, reset giúp giữ model bám task thay vì trượt theo context anxiety. | [S4] |
205
+ | Grading criteria (vd design quality, originality, craft, functionality) làm chất lượng chủ quan dễ chấm hơn. | [S4] |
206
+ | Sprint contract giúp generator evaluator đồng thuận về phạm vi, tiêu chí done, phương thức QA trước khi implement. | [S4] |
207
+ | QA bằng Playwright qua UI, API, database state, và hành vi runtime bắt được lỗi mà self-eval bỏ sót. | [S4] |
113
208
  | Harness phức tạp có thể tốn nhiều giờ và token, nên phải được xem là tradeoff thay vì mặc định. | [S4] |
114
- | Khi model mới xuất hiện, nên xem lại và loại bỏ các phần harness không còn tạo giá trị. | [S4] |
115
- | Thay tự viết thủ công mọi ràng buộc, hình (như Gemini Flash) thể tự động tổng hợp lớp bọc thực thi (AutoHarness) bằng code để lọc các hành động lỗi. | [S5] |
116
- | Biên dịch chính sách quyết định thành code tĩnh (Harness-as-Policy) giúp loại bỏ việc gọi hình runtime, tối ưu hóa chi phí độ trễ. | [S5] |
117
- | Đánh giá agent dài hạn cần dựa trên vết chạy đầy đủ (Trajectory Evaluation) bao gồm cả chuỗi gọi toolsuy luận, thay chỉ so sánh kết quả đầu ra tĩnh. | [S5] |
118
- | LLM-as-a-Judge tự động giúp đo lường độ an toàn và hiệu năng của agent liên tục, và Meta-Evaluation (VeRO) tối ưu hóa cấu trúc của harness dựa trên phản hồi. | [S5] |
209
+ | Mỗi thành phần harness mã hóa một giả định về thứ model chưa tự làm được; khi model mới mạnh hơn, nên xem lại và loại bỏ phần không còn tạo giá trị (vd bỏ sprint khi Opus 4.6 tự planning tốt). | [S4] |
210
+ | Agent thường thử hành động không hợp lệ trong môi trường (vd 78% ván thua của Gemini-2.5-Flash do nước đi sai luật). | [S5] |
211
+ | Thay tự viết thủ công mọi ràng buộc, model có thể tự tổng hợp lớp bọc thực thi (AutoHarness) bằng iterative code refinement để lọc hành động không hợp lệ, giúp model nhỏ vượt model lớn. | [S5] |
212
+ | Sinh toàn bộ policy thành code tĩnh (code-as-policy) loại bỏ LLM call lúc ra quyết định, tối ưu chi phí/độ trễ thể vượt cả model lớn trên các môi trường single-player. | [S5] |
119
213
 
120
214
  ## Chính sách citation
121
215
 
package/package.json CHANGED
@@ -1,7 +1,11 @@
1
1
  {
2
2
  "name": "codex-harness-engineering",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Codex harness engineering docs and installable agent skills.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/bonnguyenitc/codex-harness-engineering.git"
8
+ },
5
9
  "keywords": [
6
10
  "codex",
7
11
  "harness-engineering",
@@ -19,14 +23,15 @@
19
23
  "README.md",
20
24
  "docs",
21
25
  "scripts",
22
- "skills"
26
+ "skills",
27
+ "templates"
23
28
  ],
24
29
  "scripts": {
25
30
  "test": "node --test tests/*.test.mjs",
26
31
  "verify": "node scripts/verify-harness.mjs && npm test",
27
32
  "pack:dry": "npm pack --dry-run",
28
33
  "release": "./scripts/publish.sh",
29
- "prepublishOnly": "npm test"
34
+ "prepublishOnly": "npm run verify"
30
35
  },
31
36
  "engines": {
32
37
  "node": ">=18.17"
@@ -34,5 +39,5 @@
34
39
  "publishConfig": {
35
40
  "access": "public"
36
41
  },
37
- "license": "UNLICENSED"
42
+ "license": "MIT"
38
43
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { realpathSync } from "node:fs";
4
- import { access, cp, mkdir, rm } from "node:fs/promises";
4
+ import { access, chmod, cp, mkdir, rm } from "node:fs/promises";
5
5
  import path from "node:path";
6
6
  import { fileURLToPath, pathToFileURL } from "node:url";
7
7
 
@@ -12,6 +12,18 @@ export const SKILL_NAMES = [
12
12
  "acceptance-contract",
13
13
  "cleanup-harness",
14
14
  "creator-harness",
15
+ "lessons-harness",
16
+ ];
17
+
18
+ export const HARNESS_FILES = [
19
+ "AGENTS.md",
20
+ "progress.md",
21
+ "feature_list.json",
22
+ "lessons.md",
23
+ "memory/README.md",
24
+ "init.sh",
25
+ "verify-state.mjs",
26
+ "rotate-state.mjs",
15
27
  ];
16
28
 
17
29
  async function exists(filePath) {
@@ -33,49 +45,91 @@ export async function installSkills({
33
45
  packageRoot = PACKAGE_ROOT,
34
46
  projectRoot = process.cwd(),
35
47
  force = false,
48
+ harness = false,
49
+ team = false,
36
50
  } = {}) {
37
51
  const sourceRoot = path.join(packageRoot, "skills");
38
52
  const targetRoot = path.join(projectRoot, ".agents", "skills");
39
53
  const docsSource = path.join(packageRoot, "docs", "harness-engineering");
40
54
  const docsTarget = path.join(projectRoot, "docs", "harness-engineering");
55
+ const harnessSource = path.join(packageRoot, "templates", "harness");
56
+ const teamSource = path.join(packageRoot, "templates", "team");
57
+ const teamTarget = path.join(projectRoot, "team");
58
+ const scaffoldHarness = harness || team;
41
59
  const installed = [];
42
-
43
- await mkdir(targetRoot, { recursive: true });
60
+ const scaffolded = [];
61
+ const copies = [];
44
62
 
45
63
  for (const skillName of SKILL_NAMES) {
46
64
  const source = path.join(sourceRoot, skillName);
47
65
  const target = path.join(targetRoot, skillName);
48
66
 
49
67
  if (path.resolve(source) !== path.resolve(target)) {
50
- await assertCanWrite(target, force);
51
- await rm(target, { recursive: true, force: true });
52
- await cp(source, target, { recursive: true, force: true });
68
+ copies.push({ source, target });
53
69
  }
54
70
  installed.push(skillName);
55
71
  }
56
72
 
57
73
  if (path.resolve(docsSource) !== path.resolve(docsTarget)) {
58
- await assertCanWrite(docsTarget, force);
59
- await rm(docsTarget, { recursive: true, force: true });
60
- await cp(docsSource, docsTarget, { recursive: true, force: true });
74
+ copies.push({ source: docsSource, target: docsTarget });
75
+ }
76
+
77
+ if (scaffoldHarness) {
78
+ for (const fileName of HARNESS_FILES) {
79
+ const source = path.join(harnessSource, fileName);
80
+ const target = path.join(projectRoot, fileName);
81
+
82
+ if (path.resolve(source) !== path.resolve(target)) {
83
+ copies.push({ source, target });
84
+ scaffolded.push(fileName);
85
+ }
86
+ }
87
+ }
88
+
89
+ if (team && path.resolve(teamSource) !== path.resolve(teamTarget)) {
90
+ copies.push({ source: teamSource, target: teamTarget });
91
+ scaffolded.push("team/");
61
92
  }
62
93
 
63
- return { targetRoot, docsTarget, installed };
94
+ // Check every target before copying anything so a conflict cannot leave a
95
+ // partial install behind.
96
+ for (const { target } of copies) {
97
+ await assertCanWrite(target, force);
98
+ }
99
+
100
+ await mkdir(targetRoot, { recursive: true });
101
+
102
+ for (const { source, target } of copies) {
103
+ await rm(target, { recursive: true, force: true });
104
+ await cp(source, target, { recursive: true, force: true });
105
+ }
106
+
107
+ if (scaffolded.includes("init.sh")) {
108
+ await chmod(path.join(projectRoot, "init.sh"), 0o755);
109
+ }
110
+
111
+ return { targetRoot, docsTarget, installed, scaffolded };
64
112
  }
65
113
 
66
114
  export function parseArgs(args) {
67
115
  const [command, ...flags] = args;
68
116
 
69
117
  if (command !== "init") {
70
- throw new Error("Usage: codex-harness-engineering init [--force]");
118
+ throw new Error("Usage: codex-harness-engineering init [--force] [--team]");
71
119
  }
72
120
 
73
- const unknownFlag = flags.find((flag) => flag !== "--force");
121
+ const knownFlags = ["--force", "--harness", "--starter-kit", "--team"];
122
+ const unknownFlag = flags.find((flag) => !knownFlags.includes(flag));
74
123
  if (unknownFlag) {
75
124
  throw new Error(`Unknown option: ${unknownFlag}`);
76
125
  }
77
126
 
78
- return { command, force: flags.includes("--force") };
127
+ return {
128
+ command,
129
+ force: flags.includes("--force"),
130
+ harness: true,
131
+ team: flags.includes("--team"),
132
+ };
79
133
  }
80
134
 
81
135
  function isDirectRun() {
@@ -89,14 +143,18 @@ function isDirectRun() {
89
143
 
90
144
  if (isDirectRun()) {
91
145
  try {
92
- const { force } = parseArgs(process.argv.slice(2));
93
- const { targetRoot, docsTarget, installed } = await installSkills({ force });
146
+ const { force, harness, team } = parseArgs(process.argv.slice(2));
147
+ const { targetRoot, docsTarget, installed, scaffolded } = await installSkills({ force, harness, team });
94
148
 
95
149
  console.log(`Installed ${installed.length} skills to ${targetRoot}`);
96
150
  for (const skillName of installed) {
97
151
  console.log(`- ${skillName}`);
98
152
  }
99
153
  console.log(`Copied docs to ${docsTarget}`);
154
+ if (scaffolded.length > 0) {
155
+ console.log(`Scaffolded harness files: ${scaffolded.join(", ")}`);
156
+ console.log("Next: edit init.sh and the Commands section of AGENTS.md.");
157
+ }
100
158
  } catch (error) {
101
159
  console.error(error instanceof Error ? error.message : error);
102
160
  process.exitCode = 1;
@@ -95,8 +95,8 @@ fi
95
95
  echo "New version: $NEW_VERSION"
96
96
  echo ""
97
97
 
98
- echo "Running tests..."
99
- npm test
98
+ echo "Running harness verification and tests..."
99
+ npm run verify
100
100
 
101
101
  echo ""
102
102
  echo "Checking package contents..."
@@ -11,6 +11,8 @@ const REQUIRED_FILES = [
11
11
  "README.md",
12
12
  "progress.md",
13
13
  "feature_list.json",
14
+ "lessons.md",
15
+ "memory/README.md",
14
16
  "init.sh",
15
17
  "docs/harness-engineering/index.md",
16
18
  "docs/harness-engineering/research-note.md",
@@ -19,13 +21,18 @@ const REQUIRED_FILES = [
19
21
  "skills/creator-harness/SKILL.md",
20
22
  "skills/acceptance-contract/SKILL.md",
21
23
  "skills/cleanup-harness/SKILL.md",
24
+ "skills/lessons-harness/SKILL.md",
22
25
  ];
23
26
  const README_MAPPED_FILES = REQUIRED_FILES.filter(
24
27
  (relativePath) => relativePath !== "AGENTS.md" && relativePath !== "README.md"
25
28
  );
26
29
  const STATE_FILES = ["feature_list.json", "progress.md"];
30
+ const LINE_BUDGETS = {
31
+ "progress.md": 400,
32
+ "lessons.md": 400,
33
+ };
27
34
  const BEHAVIOR_CHANGE_PATTERNS = [
28
- /^(scripts|tests|skills)\//,
35
+ /^(scripts|tests|skills|templates)\//,
29
36
  /^package(?:-lock)?\.json$/,
30
37
  /^init\.sh$/,
31
38
  /^AGENTS\.md$/,
@@ -40,7 +47,7 @@ async function exists(filePath) {
40
47
  }
41
48
  }
42
49
 
43
- async function markdownFiles(directory, relativeRoot) {
50
+ async function listFiles(directory, relativeRoot, matches) {
44
51
  if (!await exists(directory)) {
45
52
  return [];
46
53
  }
@@ -53,8 +60,8 @@ async function markdownFiles(directory, relativeRoot) {
53
60
  const relativePath = path.join(relativeRoot, entry.name);
54
61
 
55
62
  if (entry.isDirectory()) {
56
- found.push(...await markdownFiles(absolutePath, relativePath));
57
- } else if (entry.isFile() && entry.name.endsWith(".md")) {
63
+ found.push(...await listFiles(absolutePath, relativePath, matches));
64
+ } else if (entry.isFile() && entry.name !== ".DS_Store" && matches(entry.name)) {
58
65
  found.push(relativePath);
59
66
  }
60
67
  }
@@ -62,6 +69,43 @@ async function markdownFiles(directory, relativeRoot) {
62
69
  return found;
63
70
  }
64
71
 
72
+ function markdownFiles(directory, relativeRoot) {
73
+ return listFiles(directory, relativeRoot, (name) => name.endsWith(".md"));
74
+ }
75
+
76
+ async function skillsMirrorErrors(root) {
77
+ const mirrorRoot = path.join(root, ".agents", "skills");
78
+ if (!await exists(mirrorRoot)) {
79
+ return [];
80
+ }
81
+
82
+ const errors = [];
83
+ const sourceFiles = await listFiles(path.join(root, "skills"), "", () => true);
84
+ const mirrorFiles = await listFiles(mirrorRoot, "", () => true);
85
+
86
+ for (const relativePath of sourceFiles) {
87
+ const mirrorPath = path.join(mirrorRoot, relativePath);
88
+ if (!await exists(mirrorPath)) {
89
+ errors.push(`.agents/skills/${relativePath}: mirror copy of skills/${relativePath} is missing`);
90
+ continue;
91
+ }
92
+
93
+ const source = await readFile(path.join(root, "skills", relativePath), "utf8");
94
+ const mirror = await readFile(mirrorPath, "utf8");
95
+ if (source !== mirror) {
96
+ errors.push(`.agents/skills/${relativePath}: mirror copy is out of sync with skills/${relativePath}`);
97
+ }
98
+ }
99
+
100
+ for (const relativePath of mirrorFiles) {
101
+ if (!sourceFiles.includes(relativePath)) {
102
+ errors.push(`.agents/skills/${relativePath}: has no source file under skills/`);
103
+ }
104
+ }
105
+
106
+ return errors;
107
+ }
108
+
65
109
  function changesHarnessBehavior(relativePath) {
66
110
  return BEHAVIOR_CHANGE_PATTERNS.some((pattern) => pattern.test(relativePath));
67
111
  }
@@ -128,6 +172,19 @@ export async function verifyHarness(root = PACKAGE_ROOT, { changedFiles = [] } =
128
172
  }
129
173
  }
130
174
 
175
+ errors.push(...await skillsMirrorErrors(root));
176
+
177
+ for (const [relativePath, budget] of Object.entries(LINE_BUDGETS)) {
178
+ if (await exists(path.join(root, relativePath))) {
179
+ const lineCount = (await readFile(path.join(root, relativePath), "utf8")).split("\n").length;
180
+ if (lineCount > budget) {
181
+ errors.push(
182
+ `${relativePath}: ${lineCount} lines exceeds the ${budget}-line budget; archive older entries with node templates/harness/rotate-state.mjs .`
183
+ );
184
+ }
185
+ }
186
+ }
187
+
131
188
  const behaviorChanges = changedFiles.filter(changesHarnessBehavior);
132
189
  if (behaviorChanges.length > 0) {
133
190
  for (const stateFile of STATE_FILES) {