agent-bios 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/DEPENDENCIES.md +35 -12
  2. package/README.md +346 -31
  3. package/claude/CLAUDE.md +2 -2
  4. package/claude/agents/frontier.md +1 -1
  5. package/claude/agents/sweep.md +3 -3
  6. package/claude/agents/workhorse.md +2 -2
  7. package/claude/guides/claude-prompting.md +119 -34
  8. package/claude/guides/cli-multi-model-workflow.md +33 -15
  9. package/claude/guides/gpt-prompting.md +148 -28
  10. package/claude/guides/review-request.md +27 -0
  11. package/claude/guides/session-distill-workflow.md +54 -2
  12. package/claude/guides/slide-writing/RUNBOOK.md +137 -0
  13. package/claude/guides/slide-writing/scripts/pair.py +979 -0
  14. package/claude/guides/slide-writing/scripts/render.mjs +82 -0
  15. package/claude/guides/slide-writing.md +195 -0
  16. package/claude/guides/svg-visualization-guide.md +9 -0
  17. package/claude/guides/verification-discipline.md +5 -1
  18. package/claude/hooks/tooling-gotchas-hook.py +7 -5
  19. package/codex/AGENTS.md +2 -2
  20. package/codex/agents/frontier.toml +2 -1
  21. package/codex/agents/reviewer.toml +1 -1
  22. package/codex/agents/sweep.toml +3 -3
  23. package/codex/agents/workhorse.toml +1 -1
  24. package/codex/config-additions.toml +1 -1
  25. package/codex/guides/claude-prompting.md +119 -34
  26. package/codex/guides/cli-multi-model-workflow.md +33 -15
  27. package/codex/guides/gpt-prompting.md +148 -28
  28. package/codex/guides/review-request.md +27 -0
  29. package/codex/guides/session-distill-workflow.md +54 -2
  30. package/codex/guides/slide-writing/RUNBOOK.md +137 -0
  31. package/codex/guides/slide-writing/scripts/pair.py +979 -0
  32. package/codex/guides/slide-writing/scripts/render.mjs +82 -0
  33. package/codex/guides/slide-writing.md +195 -0
  34. package/codex/guides/svg-visualization-guide.md +9 -0
  35. package/codex/guides/verification-discipline.md +5 -1
  36. package/compose/assemble.py +290 -14
  37. package/compose/bootstrap/SKILL.md +119 -0
  38. package/compose/check-domains.py +102 -9
  39. package/compose/corpus-state.py +1174 -0
  40. package/compose/corpus.py +387 -0
  41. package/compose/corpus_catalog.py +882 -0
  42. package/compose/corpus_install.py +1617 -0
  43. package/compose/corpus_session.py +726 -0
  44. package/compose/corpus_store.py +1414 -0
  45. package/compose/corpus_transaction.py +236 -0
  46. package/compose/corpus_ui.py +644 -0
  47. package/compose/domains.json +101 -100
  48. package/compose/write-update-cache.py +53 -0
  49. package/install.sh +174 -24
  50. package/launch/agent-launch.py +1327 -184
  51. package/launch/agent-launch.toml +12 -16
  52. package/launch/i18n/en.toml +113 -7
  53. package/launch/i18n/ja.toml +113 -7
  54. package/launch/i18n/ko.toml +113 -7
  55. package/learn/collect-learning.py +46 -19
  56. package/learn/migrate-learnings.py +10 -1
  57. package/package.json +13 -3
  58. package/provenance.json +1 -1
  59. package/session-cost.py +22 -2
  60. package/wrappers/codex-helm.sh +3 -3
@@ -2,11 +2,20 @@
2
2
 
3
3
  "mode.title" = "모드"
4
4
  "mode.swe.label" = "Software Engineer"
5
- "mode.swe.description" = "프로젝트 자체의 AGENTS.md/CLAUDE.md를 따르는 레포 범위 작업: 순정 Vanilla 세션 또는 Custom으로 직접 구성합니다."
5
+ "mode.swe.description" = "기존 프로젝트에서 CLI의 기본 지침 로딩 방식으로 작업합니다. Vanilla 런처의 추가 설정 없이 시작하고, Custom에서는 모델과 리뷰 방식을 직접 고릅니다."
6
6
  "mode.builder.label" = "Builder"
7
- "mode.builder.description" = "고정 프리셋들에서 tier·리뷰 라우트·권한을 조정합니다. Custom 포함."
7
+ "mode.builder.description" = "설치된 코퍼스를 활용하는 일반 개발 모드입니다. Balanced·Deep review·Fast batch·Solo 또는 Custom에서 메인 모델, 위임, 리뷰, 실행 권한을 고릅니다."
8
8
  "mode.distill.label" = "Session distill"
9
- "mode.distill.description" = "전용 session-distill 허브로 이동: 상태, 패키지, 버전, 세션 시작."
9
+ "mode.distill.description" = "지난 AI 작업 대화를 살펴보고 공통 지침에 반영할 교훈을 제안합니다. 상태 확인과 실행 메뉴를 엽니다. 현재 이 작업에는 agent-bios 소스 저장소가 필요합니다."
10
+
11
+ "preset.balanced.description" = "일반적인 기능 개발과 버그 수정에 권하는 시작점입니다. 메인 에이전트가 작업을 나눠 맡기고 독립 리뷰를 요청할 수 있습니다. 특별한 요구가 없을 때 고르세요. 에이전트와 리뷰가 늘면 시간과 사용량도 늘 수 있습니다."
12
+ "preset.deep-review.description" = "결함을 놓쳤을 때 손실이 큰 변경에 적합합니다. 다른 AI 제공자의 모델로 더 깊은 추가 리뷰를 요청합니다. 대기 시간과 사용량이 늘어날 수 있으며, 이 컴퓨터에서 가능한 리뷰 경로는 위 설정에 표시됩니다."
13
+ "preset.fast-batch.description" = "여러 파일에 같은 변경을 적용하는 등 기준이 분명한 반복 작업에 적합합니다. 실행 담당 티어인 WORKHORSE를 메인으로 시작합니다. 판단이 어려운 부분은 별도로 맡기거나 Balanced를 선택하세요. 실제 사용량은 모델과 작업량에 따라 달라집니다."
14
+ "preset.solo.description" = "메인 에이전트 하나와 진행하고 싶은 작업에 적합합니다. 작업 위임을 끄고, 이 프리셋에서는 리뷰를 자동 요청하지 않습니다. 추가 에이전트 호출이 없으며, 별도 리뷰가 필요할 때 직접 요청합니다."
15
+ "preset.vanilla.description" = "평소 CLI의 기본 설정으로 시작합니다. 런처가 모델 배정·권한 변경·리뷰 계약을 추가하지 않습니다. 설치된 전역 지침과 프로젝트 자체 지침은 CLI의 기본 로딩 규칙에 따라 적용됩니다."
16
+ "preset.custom.description" = "메인 모델, 리뷰 방식, 실행 권한, 위임할 작업의 담당 모델을 직접 고릅니다. 마지막 ‘이 설정으로 시작’ 전까지 설정을 살펴보고 바꿀 수 있습니다. 이 선택들이 낯설면 Balanced에서 시작하세요."
17
+ "preset.title" = "작업 방식 선택"
18
+ "preset.custom.label" = "직접 설정 (Custom)"
10
19
 
11
20
  "language.label" = "언어"
12
21
  "language.description" = "TUI 언어를 선택합니다 (English / 한국어 / 日本語). AI가 소비하는 코퍼스는 영어 그대로이며, 런처 화면만 바뀝니다."
@@ -16,18 +25,73 @@
16
25
  "language.ja.description" = "ランチャーの画面を日本語で表示します。"
17
26
 
18
27
  "corpus.label" = "코퍼스 패키지"
19
- "corpus.description" = "설치할 코퍼스 도메인 패키지를 선택합니다. 적용하면 설치기의 onboard 루프(설치 + 활성화 카나리)가 실행됩니다."
28
+ "corpus.private.title" = "Corpus Studio"
29
+ "corpus.private.description" = "개인 corpus 항목을 조회·생성·편집·삭제·복원합니다. 변경은 다음 활성 세션에 반영되고, 실행 중인 세션은 고정한 내용을 유지합니다."
30
+ "corpus.private.relationship" = "Corpus는 별도 저장소에 보관됩니다. Builder는 선택한 사본을 활성화하고, 기본 CLI와 Vanilla에는 자동 추가하지 않습니다. 기존 전역 설치는 별도 이전이 필요합니다."
31
+ "corpus.private.vanilla" = "기본 CLI와 사용자가 설정한 개인·프로젝트 지시문을 사용합니다. Private agent-bios corpus, 스킬 설명, 실행 설정은 추가하지 않습니다."
32
+ "corpus.description" = "AI가 참고할 작업 지침을 고릅니다. 개발·여러 에이전트의 협업·스프레드시트 같은 작업별 묶음입니다. 패키지를 고른 뒤 ‘선택 적용’으로 설치합니다. 이 컴퓨터의 이후 CLI 실행에 쓰는 공통 지침을 바꾸므로 다른 프로젝트에도 영향을 줍니다."
20
33
  "corpus.title" = "코퍼스 패키지"
21
- "corpus.core.line" = "core + infra 항상 설치됩니다. 체크리스트는 선택 도메인 패키지만 다룹니다."
22
- "corpus.toggle.description" = "이 도메인 패키지를 토글합니다. Apply 전까지 아무것도 바뀌지 않습니다."
34
+ "corpus.core.line" = "목표 설정·의사결정·교훈 기록의 기본 규칙(core + infra)은 항상 포함됩니다. 아래에서 작업별 패키지를 고르세요."
35
+ "corpus.toggle.description" = "이 패키지를 선택하거나 해제합니다. ‘선택 적용’은 체크된 패키지 전체를 함께 설치하고 해제한 패키지는 설치 목록에서 뺍니다. 적용 전에 뒤로 돌아가거나 취소하면 설치 상태는 그대로입니다."
36
+ "corpus.size.legend" = "각 패키지 옆의 크기는 모든 세션이 읽는 전역에 더해지는 양입니다. 가이드도 함께 배포되지만 규칙이 가리킬 때만 읽힙니다."
37
+ "corpus.size.detail" = "모든 세션에 규칙 {rules}개({size})를 더하고, 규칙이 가리킬 때만 읽히는 가이드 {guides}개({guide_size})를 배포합니다."
38
+ "corpus.size.detail.noguides" = "모든 세션에 규칙 {rules}개({size})를 더하고, 배포하는 가이드는 없습니다."
23
39
  "corpus.apply.label" = "선택 적용{pending}"
24
- "corpus.apply.description" = "체크된 집합 그대로 agent-bios onboard를 실행합니다. 배포·카나리·결과 기록은 설치기가 수행합니다."
40
+ "corpus.apply.description" = "체크한 패키지를 설치하고 해제한 패키지를 컴퓨터의 공통 지침에서 뺍니다. 설치 후 AI가 지침을 읽을 수 있는지 확인하고 결과를 보여 줍니다. 다른 프로젝트에서도 사용하는 지침이며, 프로젝트 코드를 바꾸는 작업은 아닙니다."
25
41
  "corpus.apply.unchanged" = "체크된 집합이 적용된 집합과 같습니다 — 적용할 것이 없습니다"
26
42
  "corpus.unavailable.line1" = "corpus status projection이 없거나 도메인 보고 이전 버전입니다."
27
43
  "corpus.none.line" = "이 투영에는 선택 가능한 도메인 패키지가 없습니다 — core와 infra는 항상 설치되므로 여기서 고를 것이 없습니다."
28
44
  "corpus.unavailable.line2" = "실행: agent-bios install (이 화면이 읽는 projection을 다시 씁니다)"
29
45
  "corpus.back.hint" = "모드 메뉴로 돌아갑니다."
30
46
 
47
+ "corpus.launch.relationship" = "모드와 프리셋은 세션의 실행 방식을 정합니다. 설치된 코퍼스 선택은 그대로 유지되며, 변경은 ‘코퍼스 패키지’에서 합니다. Vanilla에서도 호스트의 기본 지침 로딩을 통해 설치된 전역 규칙을 읽습니다."
48
+ "corpus.launch.applied" = "현재 적용된 코퍼스:"
49
+ "corpus.launch.base" = "core + infra: 목표·제약 확인, 선택지 비교, 검증 결과 보고, 다음 세션에 재사용할 교훈 기록을 다룹니다."
50
+ "corpus.launch.unknown" = "이 설치본에서 패키지 내용을 확인할 수 없습니다."
51
+ "corpus.domain.builder-base.label" = "개발 기본 원칙"
52
+ "corpus.domain.llm-pipeline-dev.label" = "LLM 파이프라인 개발"
53
+ "corpus.domain.multi-agent-orchestration.label" = "여러 에이전트의 협업"
54
+ "corpus.domain.visualization-docs.label" = "도표와 구현 지도"
55
+ "corpus.domain.office-work.label" = "스프레드시트 작업"
56
+ "corpus.domain.builder-base" = """
57
+ 소프트웨어 구현·검증·유지보수에 공통으로 쓰는 개발 원칙입니다.
58
+ • Coding(개발 절차): 완료 기준을 정하고 작업을 계획한 뒤, 필요한 부분을 수정하고 결과를 리뷰합니다.
59
+ • Verification menus(검증 선택): 코드·설정·문서 등 작업 대상에 맞는 검사를 고르고 실제 변경 경로를 검증합니다.
60
+ • Concept economy(개념 관리): 기존 개념을 재사용하고 이름과 값의 관리 주체를 하나로 유지해 중복을 줄입니다.
61
+ • Documentation hygiene(문서 관리): 현재 문서를 실제 동작과 맞추고 결정·이력·인수인계 기록을 알맞은 곳에 둡니다.
62
+ • Tooling safety(도구 사용): 도구·환경을 명확히 지정하고 셸·Git 함정, 비밀값 취급, 생성한 프로세스 정리를 다룹니다.
63
+ • Mock boundaries(테스트 대역): 모의 객체를 의도적으로 사용하고 최종 기능이 실제 의존성을 통해 동작하는지 확인합니다.
64
+ • Review requests & defect criteria(리뷰 기준): 근거와 구체적인 실패 기준을 리뷰어에게 주고 중요한 지적을 해결합니다.
65
+ • Repository instructions(저장소 지침): repo-charter 스킬로 저장소 코드에 근거한 AGENTS.md 작업 규칙을 만듭니다.
66
+ """
67
+ "corpus.domain.llm-pipeline-dev" = """
68
+ 모델의 판단과 코드로 보장할 계약을 구분해 LLM 파이프라인을 만듭니다.
69
+ • Capability boundary(역할 경계): 의미 해석과 선택은 모델이 맡고, 정확한 계산과 변환은 도구가 수행합니다.
70
+ • Structured output(구조화 출력): 제출 형식을 제한하고 코드가 검증·직렬화·최종 산출물 생성을 맡습니다.
71
+ • Runtime authority(실행 권한): 실제 도구와 소비 경로에서 권한·실행 경로를 보장합니다. 프롬프트나 읽히지 않는 플래그만으로는 동작이 바뀌지 않습니다.
72
+ • Failure handling(실패 처리): 계약을 어긴 출력은 거부하고 불확실한 품질 판단은 사용자에게 알립니다. 모델 출력을 몰래 보정하지 않습니다.
73
+ """
74
+ "corpus.domain.multi-agent-orchestration" = """
75
+ 여러 모델과 CLI 에이전트의 역할·인수인계·독립 리뷰를 조율합니다.
76
+ • Delegation(위임): 독립 작업이나 반복 작업에 에이전트가 유용한지 판단하고 범위와 완료 기준을 정해 맡깁니다.
77
+ • Model allocation(모델 배분): 난도와 영향에 따라 티어를 배정하고 저렴한 모델의 구현에는 검증을 보강합니다.
78
+ • Prompting guides(프롬프트 지침): 대상 모델 계열에 맞게 지시 방식과 추론 강도를 조정합니다.
79
+ • Independent review(독립 리뷰): 제공자와 관점을 비교하고 요청한 모델·설정에서 리뷰가 실제로 실행됐는지 확인합니다.
80
+ • Continuation & batches(재개·일괄 작업): 재개 가능한 산출물을 보존하고 세션 상태를 재확인하며 사용량 제한의 반복 재시도를 멈춥니다.
81
+ """
82
+ "corpus.domain.visualization-docs" = """
83
+ 시스템과 의사결정을 도표로 설명하고 현재 구현 상태를 지도로 관리합니다.
84
+ • Visual explanations(시각 설명): 비교·흐름·상태 변화를 가장 잘 전달하는 텍스트·표·HTML 표현을 고릅니다.
85
+ • SVG diagrams(SVG 도표): 역할·경계·의존성·방향을 읽기 쉬운 배치와 일관된 표기로 나타냅니다.
86
+ • Implementation map(구현 지도): 구조·목표·위험·결정·검증 상태를 현재 시점의 대시보드로 유지합니다.
87
+ """
88
+ "corpus.domain.office-work" = """
89
+ 스프레드시트 작업을 설치된 spreadsheet-processing 스킬로 안내합니다.
90
+ • Spreadsheet processing(시트 작업): 스킬이 있으면 통합문서 편집·생성·대사·검증에 사용합니다.
91
+ • Formula verification(수식 검증): 수식에 의존하는 Excel 결과를 실제 Microsoft Excel 엔진으로 확인합니다.
92
+ • Availability(사용 조건): 이 패키지는 작업 안내 규칙을 추가합니다. 스프레드시트 스킬과 Excel은 별도로 사용할 수 있어야 합니다.
93
+ """
94
+
31
95
  "wizard.title" = "다른 리뷰어 등록"
32
96
  "wizard.id.label" = "Method id (kebab-case)"
33
97
  "wizard.label.label" = "라벨 (method 목록에 표시)"
@@ -74,6 +138,8 @@
74
138
  "custom.review.description" = "리뷰 게이트가 작동할 때 요청할 리뷰 경로를 선택합니다."
75
139
  "custom.policy.label" = "실행 정책: {policy}"
76
140
  "custom.policy.description" = "호스트별 권한 또는 샌드박스 동작을 선택합니다."
141
+ "custom.global-instructions.label" = "내 전역 지침 파일: {choice}"
142
+ "custom.global-instructions.description" = "이 agent-bios 활성 세션에서 개인 전역 지침 파일을 불러올지 선택합니다."
77
143
  "custom.tier.description" = "{tier} 티어의 모델과 추론 강도를 편집하고 여기로 돌아옵니다."
78
144
  "custom.save.label" = "이 설정을 전역으로 저장하고 시작"
79
145
  "custom.save.description" = "이 구성을 사용자 설정에 이름 있는 프리셋으로 저장해 다른 곳에서도 재사용한 뒤 실행합니다."
@@ -162,9 +228,16 @@
162
228
  "panel.version.label" = "적용 버전"
163
229
  "panel.mechanisms.label" = "메커니즘"
164
230
  "panel.ledger.label" = "원장"
231
+ "panel.rules.label" = "규칙"
232
+ "panel.rules.value" = "모든 세션이 읽는 전역에 {rules}개 · {size}"
233
+ "panel.guides.label" = "가이드"
234
+ "panel.guides.value" = "{guides}개 배포됨 · {size}, 규칙이 가리킬 때 읽힘"
235
+ "panel.ledger.author-only" = "작성자 측 전용 — 패키지 설치에는 학습 원장이 없습니다"
236
+ "panel.domains.unknown" = "⚠ 적용되어 있으나 이 패키지에 없음: {names}"
165
237
  "panel.domains.label" = "도메인"
166
238
  "panel.rolled-back" = "(롤백됨. 최신은 {latest})"
167
239
  "panel.layers.none" = "없음"
240
+ "panel.unavailable" = "패키지 설치에서는 확인 불가"
168
241
  "panel.ledger.value" = "배치 {placed} · 인큐베이팅 {incubating} · 버전 {versions}"
169
242
  "panel.domains.unset" = "(아직 선택 안 함)"
170
243
  "panel.last-apply" = "⚠ 마지막 적용 {outcome} @ {at} — 요청: {requested}"
@@ -174,6 +247,39 @@
174
247
  # while every line of content around them was translated, so the Korean and Japanese
175
248
  # screens answered in one language and asked in another.
176
249
  "prompt.select" = "선택 [{default}] ({actions}): "
250
+ "tui.setup.title" = "현재 설정"
251
+ "setup.none" = "선택된 설정 없음"
252
+ "setup.host" = "호스트 {host} | 프리셋 {preset}"
253
+ "setup.bare" = "평소 CLI 설정으로 실행합니다. 런처가 실행 계약이나 권한 옵션을 추가하지 않습니다.\n전역 지침과 프로젝트 지침은 CLI의 기본 로딩 규칙에 따라 적용됩니다."
254
+ "setup.main" = "메인 {tier} | 리뷰 {review}"
255
+ "setup.delegation" = "위임 {delegation} | 실행 {execution}"
256
+ "setup.global-instructions.label" = "전역 파일"
257
+ "global-instructions.title" = "내 전역 지침 파일"
258
+ "global-instructions.summary" = "사용자 전역 지침 문서·규칙: {choice}"
259
+ "global-instructions.include.label" = "포함"
260
+ "global-instructions.include.description" = "CLI의 기본 방식대로 사용자 전역 지침 문서와 규칙을 읽습니다. 어느 쪽이든 프로젝트 지침·메모리, 설정, 로그인, 도구와 실행 권한은 유지합니다."
261
+ "global-instructions.exclude.label" = "제외"
262
+ "global-instructions.exclude.description" = "사용자 전역 지침 문서를 읽지 않습니다. Claude에서는 전역 CLAUDE.md, 그 import, 사용자 rules/를 제외합니다. 프로젝트 지침·메모리, 설정, 로그인, 도구와 실행 권한은 유지합니다."
263
+ "global-instructions.exclude.codex-unavailable" = "현재 Codex에서는 전역 지침 파일만 안전하게 제외하는 경로를 지원하지 않습니다."
264
+ "global-instructions.exclude.private-unavailable" = "agent-bios 활성 세션이 필요합니다. Vanilla와 일반 CLI 실행은 네이티브 지침 로딩을 유지합니다."
265
+ "setup.inactive.label" = "비활성"
266
+ "setup.inactive.value" = "{tiers} — 비활성, 투영되지 않음 ({reason})"
267
+ "tui.corpus.title" = "코퍼스 상태"
268
+ "tui.detail.title" = "선택 중인 항목 설명"
269
+ "tui.detail.scroll" = "j/k: 설명 아래/위 · Shift+PgUp/PgDn"
270
+ "tui.options.header" = "항목 (1-{count} / {count})"
271
+ "tui.key.move" = "Up/Down 이동"
272
+ "tui.key.select" = "Enter 선택"
273
+ "tui.key.apply" = "Enter 적용"
274
+ "tui.key.toggle" = "Space 토글"
275
+ "tui.key.scroll" = "PgUp/PgDn 스크롤"
276
+ "tui.key.back" = "Left 뒤로"
277
+ "tui.key.cancel" = "Esc 취소"
278
+ "tui.input.current" = "현재 값: {value}"
279
+ "tui.input.new" = "새 값 (비워 두면 현재 값 유지):"
280
+ "tui.input.placeholder" = "비워 두면 현재 값을 유지합니다"
281
+ "tui.input.footer" = "Enter 확정 | Esc/Ctrl-C 취소 | q + Enter 취소"
282
+ "prompt.text" = "{label} [{default}] ({cancel}): "
177
283
  "prompt.back" = "b 뒤로"
178
284
  "prompt.cancel" = "q 취소"
179
285
  "prompt.unavailable" = "사용 불가"
@@ -9,15 +9,13 @@ optional criteria / classification / proposed_domain / context) plus its session
9
9
  * mints learning_id (a lowercase UUID) + created (ISO-8601) + schema_version;
10
10
  * validates the full record against learn/learning.schema.json — the single
11
11
  validation source, reused from learn/check-learning.py (no second schema);
12
- * logs the JSON record to <home>/personal/learnings.jsonl the durable,
13
- append-only upload source that the Phase 2 watermark drain re-sends from;
14
- * writes the lesson prose where THIS host loads it next session, and wires it:
15
- - claude: appends to <home>/personal/learnings.md and ensures the
16
- `@personal/learnings.md` import once in the entry CLAUDE.md;
17
- - codex: appends into a preserved `agent-bios:personal-learnings` region
18
- of <home>/AGENTS.md (Codex has no @import; AGENTS.md is always loaded).
19
- The region lives OUTSIDE the central markers so compose/assemble.py —
20
- which only rewrites the central region — preserves it across re-assembly.
12
+ * appends the exact record to the private corpus's host-qualified events.jsonl;
13
+ * supplies it to future activated snapshots through CorpusStore, without changing
14
+ native global instructions or the running session;
15
+ * drains explicitly configured ingestion from that immutable private event source.
16
+
17
+ The global prose/import writers below are reached only under the explicit
18
+ AGENT_BIOS_LEGACY_INSTALL=1 compatibility path and its migration tests.
21
19
 
22
20
  It REFUSES any script-owned field in the payload (deterministic values are never
23
21
  hand-authored) and, on a schema/membership violation, REJECTS and exits 1 — it
@@ -27,7 +25,7 @@ Input: the semantic payload as one JSON object on stdin.
27
25
  Host: --host claude|codex (default: the tool prefix of supporting_sessions[0]).
28
26
  Home: --config-dir, else $CLAUDE_CONFIG_DIR / $CODEX_HOME by host, else ~/.claude / ~/.codex.
29
27
  After the local writes it best-effort uploads not-yet-delivered records to
30
- {base}/api/ingest/learnings via a watermark over learnings.jsonl. The base and
28
+ {base}/api/ingest/learnings via a host-private watermark over events.jsonl. The base and
31
29
  token resolve from the agent-bios-owned slot ~/.config/agent-bios/{ingest-url,
32
30
  token} — the one transport contract, written by whoever adopts this install;
33
31
  skipped when it is unset, or with --no-upload.
@@ -39,6 +37,7 @@ import json
39
37
  import os
40
38
  import pathlib
41
39
  import shutil
40
+ import stat
42
41
  import sys
43
42
  import http.client
44
43
  import time
@@ -418,7 +417,11 @@ def transport_config(slot_root=None):
418
417
  if not present(f):
419
418
  return None, (f"transport slot {slot} is missing {what} "
420
419
  "(a claimed slot never falls back)")
421
- if not f.is_file():
420
+ try:
421
+ is_regular_file = stat.S_ISREG(f.stat().st_mode)
422
+ except OSError:
423
+ is_regular_file = False
424
+ if not is_regular_file:
422
425
  return None, (f"transport slot {slot} has {what} but it is not a "
423
426
  "readable file (a claimed slot never falls back)")
424
427
  # One read per try, so the reason can name the file that actually
@@ -474,8 +477,8 @@ def read_jsonl_records(jsonl):
474
477
  return out
475
478
 
476
479
 
477
- def load_state(home):
478
- path = home / "personal" / STATE_NAME
480
+ def load_state(home, state_path=None):
481
+ path = pathlib.Path(state_path) if state_path is not None else home / "personal" / STATE_NAME
479
482
  if not path.is_file():
480
483
  return {"uploaded": set(), "dead": set()}
481
484
  try:
@@ -486,10 +489,10 @@ def load_state(home):
486
489
  return {"uploaded": set(), "dead": set()}
487
490
 
488
491
 
489
- def save_state(home, state, present_ids):
492
+ def save_state(home, state, present_ids, state_path=None):
490
493
  # Prune settled ids no longer in the durable log (e.g. migrated out) so the
491
494
  # state stays bounded to the log size. Atomic replace.
492
- path = home / "personal" / STATE_NAME
495
+ path = pathlib.Path(state_path) if state_path is not None else home / "personal" / STATE_NAME
493
496
  path.parent.mkdir(parents=True, exist_ok=True)
494
497
  data = {"uploaded": sorted(state["uploaded"] & present_ids),
495
498
  "dead": sorted(state["dead"] & present_ids)}
@@ -565,7 +568,8 @@ def http_post(base, token, record, timeout=UPLOAD_TIMEOUT_S):
565
568
 
566
569
 
567
570
  def drain_uploads(home, post_fn=http_post, now=time.monotonic,
568
- limit=UPLOAD_LIMIT, budget_s=UPLOAD_BUDGET_S, slot_root=None):
571
+ limit=UPLOAD_LIMIT, budget_s=UPLOAD_BUDGET_S, slot_root=None,
572
+ jsonl_path=None, state_path=None):
569
573
  """Best-effort upload of not-yet-settled learnings. post_fn/now/slot_root are
570
574
  injectable for tests (no sockets, no $HOME mutation). Returns a summary dict.
571
575
 
@@ -580,9 +584,10 @@ def drain_uploads(home, post_fn=http_post, now=time.monotonic,
580
584
  "reason": reason, "uploaded": 0, "dead": 0, "pending": None}
581
585
  token, base = config
582
586
 
583
- records = read_jsonl_records(home / "personal" / "learnings.jsonl")
587
+ records = read_jsonl_records(pathlib.Path(jsonl_path) if jsonl_path is not None
588
+ else home / "personal" / "learnings.jsonl")
584
589
  present_ids = {lid for lid, _ in records}
585
- state = load_state(home)
590
+ state = load_state(home, state_path)
586
591
  settled = state["uploaded"] | state["dead"]
587
592
  candidates = [(lid, rec) for lid, rec in records if lid not in settled]
588
593
 
@@ -608,7 +613,7 @@ def drain_uploads(home, post_fn=http_post, now=time.monotonic,
608
613
  stopped = "transient"
609
614
  break
610
615
 
611
- save_state(home, state, present_ids)
616
+ save_state(home, state, present_ids, state_path)
612
617
  pending = sum(1 for lid, _ in records
613
618
  if lid not in (state["uploaded"] | state["dead"]))
614
619
  return {"status": "ok", "reason": stopped, "uploaded": uploaded,
@@ -1168,6 +1173,28 @@ def main():
1168
1173
  sys.exit(1)
1169
1174
 
1170
1175
  dry = args.dry_run
1176
+ if os.environ.get("AGENT_BIOS_LEGACY_INSTALL") != "1":
1177
+ # Capture is an immutable private source. Model-visible projections are
1178
+ # composed when an activated session is started, never written globally.
1179
+ sys.path.insert(0, str(REPO / "compose"))
1180
+ from corpus_store import CorpusStore
1181
+ store = CorpusStore(REPO)
1182
+ destination = store.user_root / "learnings" / host
1183
+ if dry:
1184
+ print(f"collect-learning: [dry] private capture host={host} -> {destination / 'events.jsonl'}")
1185
+ return
1186
+ result = store.capture_learning(host, record)
1187
+ print(f"collect-learning: OK host={host} learning_id={result['learning_id']} · private source; future activated sessions")
1188
+ if not args.no_upload:
1189
+ import fcntl
1190
+ lock = destination / 'upload.lock'
1191
+ fd = os.open(lock, os.O_CREAT | os.O_RDWR | os.O_NOFOLLOW, 0o600)
1192
+ with os.fdopen(fd, 'a') as handle:
1193
+ fcntl.flock(handle, fcntl.LOCK_EX)
1194
+ print_upload_summary(drain_uploads(
1195
+ home, jsonl_path=destination / 'events.jsonl',
1196
+ state_path=destination / 'upload-state.json'))
1197
+ return
1171
1198
  bullet = prose_bullet(record)
1172
1199
  jsonl = append_record(home, record, dry)
1173
1200
  prose_path, wiring = APPLY[host](home, bullet, dry)
@@ -1,5 +1,10 @@
1
1
  #!/usr/bin/env python3
2
- """Promote -> migrate: clear the personal copy of promoted learnings (Phase 4).
2
+ """Private captures are retained; promotion suppression is a snapshot projection.
3
+
4
+ The default entrypoint performs no source deletion. CorpusStore requires exact
5
+ source and replacement evidence before omitting a duplicate from one snapshot.
6
+ The functions below implement only the explicit AGENT_BIOS_LEGACY_INSTALL=1
7
+ compatibility path, whose removal contract is described here.
3
8
 
4
9
  After a push lands, a learning that was promoted into the shared corpus is now
5
10
  loaded from the corpus — its personal copy (written by `learn!`,
@@ -402,6 +407,10 @@ def main():
402
407
  _self_test()
403
408
  return
404
409
 
410
+ if os.environ.get("AGENT_BIOS_LEGACY_INSTALL") != "1":
411
+ print("migrate-learnings: private capture sources retained; promotion suppression is resolved per session snapshot")
412
+ return
413
+
405
414
  if not args.host:
406
415
  die("--host claude|codex is required")
407
416
  if args.selection_file is None and args.domains is None:
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "agent-bios",
3
- "version": "0.14.0",
4
- "releaseDate": "2026-08-31",
5
- "description": "A thin, low-level instruction layer for LLM CLI agents: one set of principles and behavior whichever model you run. Deploys into $HOME by copy via an explicit `agent-bios install`.",
3
+ "version": "0.16.0",
4
+ "releaseDate": "2026-09-10",
5
+ "description": "A thin, low-level instruction layer for LLM CLI agents: one set of principles and behavior whichever model you run. Stores a private, editable corpus for explicitly activated sessions.",
6
6
  "bin": {
7
7
  "agent-bios": "install.sh"
8
8
  },
@@ -29,7 +29,17 @@
29
29
  "compose/assemble.py",
30
30
  "compose/prune-backups.py",
31
31
  "compose/check-domains.py",
32
+ "compose/corpus-state.py",
33
+ "compose/write-update-cache.py",
32
34
  "compose/canary.sh",
35
+ "compose/corpus.py",
36
+ "compose/corpus_ui.py",
37
+ "compose/corpus_store.py",
38
+ "compose/corpus_catalog.py",
39
+ "compose/corpus_session.py",
40
+ "compose/corpus_install.py",
41
+ "compose/corpus_transaction.py",
42
+ "compose/bootstrap/",
33
43
  "launch/check-prompting-targets.sh",
34
44
  "learn/check-learning.py",
35
45
  "learn/collect-learning.py",
package/provenance.json CHANGED
@@ -1 +1 @@
1
- {"commit":"db5e745b6f832a02b43556889c14ce1396688177","committedAt":"2026-08-31T13:13:32+09:00","dirty":false}
1
+ {"commit":"79b4adb99a51410411cdb416a56b40fe243be4c8","committedAt":"2026-09-10T08:03:58+09:00","dirty":false}
package/session-cost.py CHANGED
@@ -18,12 +18,14 @@ the bill: measured over two real sessions here, cache read + cache write were
18
18
  92-94% of cost and output 6-8%, so context size is the cost, and the only lever
19
19
  on it is how long a session is allowed to grow before it is reset.
20
20
  """
21
- import json, sys, glob, os, itertools, tempfile
21
+ import json, sys, glob, os, itertools, tempfile, subprocess
22
22
  from datetime import datetime, timezone
23
23
 
24
24
  # $/MTok: input, output, cache_read, cache_write_5m, cache_write_1h
25
25
  PRICES = {
26
26
  "claude-fable-5": (10.0, 50.0, 1.00, 12.50, 20.0),
27
+ # Fable 5.1 model overview, verified 2026-09-08.
28
+ "claude-fable-5-1": (10.0, 50.0, 0.25, 12.50, 20.0),
27
29
  "claude-mythos-5": (10.0, 50.0, 1.00, 12.50, 20.0),
28
30
  "claude-opus-5": (5.0, 25.0, 0.50, 6.25, 10.0),
29
31
  "claude-opus-4-8": (5.0, 25.0, 0.50, 6.25, 10.0),
@@ -35,7 +37,8 @@ PRICES = {
35
37
  }
36
38
 
37
39
  def price_for(model):
38
- for k, v in PRICES.items():
40
+ # Version-specific rates take precedence over their family prefix.
41
+ for k, v in sorted(PRICES.items(), key=lambda item: len(item[0]), reverse=True):
39
42
  if model.startswith(k):
40
43
  return v
41
44
  return None
@@ -393,6 +396,23 @@ def _self_test():
393
396
  return p
394
397
 
395
398
  with tempfile.TemporaryDirectory() as td:
399
+ # A version-specific cache rate must reach the public report without
400
+ # changing the older model's rate. Run the real CLI/scan/cost path.
401
+ for model, expected in (("claude-fable-5-1", "$0.25"),
402
+ ("claude-fable-5", "$1.00")):
403
+ transcript = write(td, model + ".jsonl", [
404
+ {"type": "assistant", "message": {
405
+ "id": "cache-price", "model": model,
406
+ "usage": {"cache_read_input_tokens": 1_000_000}}},
407
+ ])
408
+ result = subprocess.run(
409
+ [sys.executable, os.path.abspath(__file__), transcript],
410
+ capture_output=True, text=True)
411
+ check(model + " cache price reaches the report",
412
+ (result.returncode,
413
+ "modeled total cost: " + expected in result.stdout),
414
+ (0, True))
415
+
396
416
  # Claude: two requests. The first is written twice as it streams, the
397
417
  # second is a sidechain that must not be counted.
398
418
  claude = write(td, "claude.jsonl", [
@@ -233,9 +233,9 @@ EOF
233
233
  if [ "$fanout" -eq 1 ]; then
234
234
  cat <<EOF
235
235
  - Fan-out is authorized when delegation gates fire; do de-minimis work directly. Native multi-agent is off unless the main is explicit Ultra.
236
- - Internal roles via codex-run --profile inherit and bounded stdin packet: WORKHORSE=gpt-5.6-terra/high/read-only-or-workspace-write; SWEEP=gpt-5.6-luna/low/read-only; REVIEWER=gpt-5.6-terra/high/read-only.
237
- - Native spawn cannot pin role/effort. Do not use native spawn_agent for FRONTIER. Use codex-run with gpt-5.6-sol/read-only and task-fit effort: max default, Ultra for divisible work, lower when cost/latency dominates.
238
- - Internal FRONTIER command base: $codex_run --profile inherit --model gpt-5.6-sol --effort <effort> --multi-agent auto --sandbox read-only --cd "\$PWD" -c agents.max_threads=$max_threads -c agents.max_depth=$max_depth. The adapter enables native multi-agent only for ultra. Send a self-contained packet on stdin; never full-history resume.
236
+ - Internal roles via codex-run --profile inherit and bounded stdin packet: WORKHORSE=gpt-5.6-terra/xhigh/read-only-or-workspace-write; SWEEP=gpt-5.6-luna/max/read-only; REVIEWER=gpt-5.6-terra/xhigh/read-only.
237
+ - Native spawn cannot pin role/effort. Do not use native spawn_agent for FRONTIER. Use codex-run with gpt-6-astra/read-only and task-fit effort: max default, Ultra for divisible work, lower when cost/latency dominates.
238
+ - Internal FRONTIER command base: $codex_run --profile inherit --model gpt-6-astra --effort <effort> --multi-agent auto --sandbox read-only --cd "\$PWD" -c agents.max_threads=$max_threads -c agents.max_depth=$max_depth. The adapter enables native multi-agent only for ultra. Send a self-contained packet on stdin; never full-history resume.
239
239
  - Run independent units in parallel; respect depth/thread limits; wait and synthesize bounded reports.
240
240
  EOF
241
241
  else