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
@@ -10,113 +10,114 @@
10
10
  "office-work": "Office artifacts: spreadsheet processing"
11
11
  },
12
12
  "bullets": [
13
- {"anchor": "Prefer concise Korean responses", "tier": "env-personal", "domains": []},
14
- {"anchor": "Keep file changes within the requested scope", "tier": "core", "domains": []},
15
- {"anchor": "First identify the goal, scope, ambiguities", "tier": "core", "domains": []},
16
- {"anchor": "Resolve ambiguity from context when safe", "tier": "core", "domains": []},
17
- {"anchor": "For simple requests, choose the most direct", "tier": "core", "domains": []},
18
- {"anchor": "For non-trivial requests, compare 2-4 methods", "tier": "core", "domains": []},
19
- {"anchor": "Mark one default method", "tier": "core", "domains": []},
20
- {"anchor": "Execute the chosen method accurately", "tier": "core", "domains": []},
21
- {"anchor": "Return to understanding if a discovery breaks", "tier": "core", "domains": []},
22
- {"anchor": "Reconsider the method if the selected approach", "tier": "core", "domains": []},
23
- {"anchor": "Log non-blocking discoveries and continue", "tier": "core", "domains": []},
24
- {"anchor": "If the same loopback happens twice", "tier": "core", "domains": []},
25
- {"anchor": "Compare the result with the selected", "tier": "core", "domains": []},
26
- {"anchor": "Ask decision questions in outcome terms", "tier": "core", "domains": []},
27
- {"anchor": "When the user may not know the domain", "tier": "core", "domains": []},
28
- {"anchor": "Present 2-4 meaningful options", "tier": "core", "domains": []},
29
- {"anchor": "For each option, state what changes", "tier": "core", "domains": []},
30
- {"anchor": "Translate technical terms into plain consequences", "tier": "core", "domains": []},
31
- {"anchor": "Ask for the user's goal or constraint", "tier": "core", "domains": []},
32
- {"anchor": "Evaluate user suggestions for goal fit", "tier": "core", "domains": []},
33
- {"anchor": "Distinguish implementation feasibility from recommendation", "tier": "core", "domains": []},
34
- {"anchor": "Do not default to a restrictive lens", "tier": "core", "domains": []},
35
- {"anchor": "Treat user suggestions, inherited premises, prior diagnoses", "tier": "core", "domains": []},
36
- {"anchor": "For structured-output, runtime-authority, capability-surface", "tier": "domain", "domains": ["llm-pipeline-dev"]},
37
- {"anchor": "Use instructions to describe intended work", "tier": "domain", "domains": ["llm-pipeline-dev"]},
38
- {"anchor": "Use the LLM for semantic work", "tier": "domain", "domains": ["llm-pipeline-dev"]},
39
- {"anchor": "Use the capability surface for structural constraints", "tier": "domain", "domains": ["llm-pipeline-dev"]},
40
- {"anchor": "Enforce constraints through the capability surface", "tier": "domain", "domains": ["llm-pipeline-dev"]},
41
- {"anchor": "Use tools/code for deterministic work", "tier": "domain", "domains": ["llm-pipeline-dev"]},
42
- {"anchor": "When exactness, freshness, scale, repeatability", "tier": "domain", "domains": ["llm-pipeline-dev"]},
43
- {"anchor": "Let the LLM design merge, projection", "tier": "domain", "domains": ["llm-pipeline-dev"]},
44
- {"anchor": "For required structured or machine-consumed outputs", "tier": "domain", "domains": ["llm-pipeline-dev"]},
45
- {"anchor": "Let tools/code own ids, paths, serialization", "tier": "domain", "domains": ["llm-pipeline-dev"]},
46
- {"anchor": "Keep deterministic values out of LLM authority", "tier": "domain", "domains": ["llm-pipeline-dev"]},
47
- {"anchor": "For simple stable explanations or planning", "tier": "domain", "domains": ["llm-pipeline-dev"]},
48
- {"anchor": "Treat a produced field, flag, signal", "tier": "domain", "domains": ["llm-pipeline-dev"]},
49
- {"anchor": "Hard-block only deterministically decidable structural", "tier": "domain", "domains": ["llm-pipeline-dev"]},
50
- {"anchor": "Runtime/code may enforce the contract", "tier": "domain", "domains": ["llm-pipeline-dev"]},
51
- {"anchor": "When adding, changing, renaming, splitting, or exposing anything lasting or shared", "tier": "domain", "domains": ["builder-base"]},
52
- {"anchor": "Before fixing a review finding or test failure", "tier": "domain", "domains": ["builder-base"]},
53
- {"anchor": "For `.xlsx` editing, generation, reconciliation", "tier": "domain", "domains": ["office-work"]},
54
- {"anchor": "For development work, read and use", "tier": "domain", "domains": ["builder-base"]},
55
- {"anchor": "For mock, fixture, fake, stub, simulated-provider", "tier": "domain", "domains": ["builder-base"]},
56
- {"anchor": "Own the full lifecycle of what you create", "tier": "domain", "domains": ["builder-base"]},
57
- {"anchor": "Land risky or behavior-changing work behind", "tier": "domain", "domains": ["builder-base"]},
58
- {"anchor": "For composing a review request, packet", "tier": "domain", "domains": ["builder-base"]},
59
- {"anchor": "After every meaningful code, ontology, config", "tier": "domain", "domains": ["builder-base"]},
60
- {"anchor": "For choosing verification depth, the per-domain mix, the case space, what makes a completion criterion falsifiable", "tier": "domain", "domains": ["builder-base"]},
61
- {"anchor": "Report the checks run, results", "tier": "core", "domains": []},
62
- {"anchor": "Trust a green check only when it traversed", "tier": "domain", "domains": ["builder-base"]},
63
- {"anchor": "Before comparing two of anything", "tier": "domain", "domains": ["builder-base"]},
64
- {"anchor": "For concrete shell/CLI traps", "tier": "domain", "domains": ["builder-base"]},
65
- {"anchor": "Ambient state — the active shell", "tier": "domain", "domains": ["builder-base"]},
66
- {"anchor": "Before relying on any model id", "tier": "domain", "domains": ["builder-base"]},
67
- {"anchor": "Scope destructive actions (kill, rm, force-push", "tier": "domain", "domains": ["builder-base"]},
68
- {"anchor": "Never accept secrets through transcript- or history-logged channels", "tier": "core", "domains": []},
69
- {"anchor": "When a secret must be supplied", "tier": "domain", "domains": ["builder-base"]},
70
- {"anchor": "Treat a coarse runtime signal", "tier": "domain", "domains": ["builder-base"]},
71
- {"anchor": "Standing spawn policy: check the spawn gates", "tier": "domain", "domains": ["multi-agent-orchestration"]},
72
- {"anchor": "Down-spawns carry a machine-checkable done-when", "tier": "domain", "domains": ["multi-agent-orchestration"]},
73
- {"anchor": "For work spanning multiple models or CLI agents", "tier": "domain", "domains": ["multi-agent-orchestration"]},
74
- {"anchor": "For composing a prompt, packet, or tool description", "tier": "domain", "domains": ["multi-agent-orchestration"]},
75
- {"anchor": "Allocate models by difficulty", "tier": "domain", "domains": ["multi-agent-orchestration"]},
76
- {"anchor": "Judge a review by how much independence", "tier": "domain", "domains": ["multi-agent-orchestration"]},
77
- {"anchor": "dual-provider frontier design drafts", "tier": "domain", "domains": ["multi-agent-orchestration"]},
78
- {"anchor": "Never retry-storm a live rate limit", "tier": "domain", "domains": ["multi-agent-orchestration"]},
79
- {"anchor": "On any resumed, cleared, or relocated session", "tier": "domain", "domains": ["multi-agent-orchestration"]},
80
- {"anchor": "Keep runtime code, active docs, and execution-facing", "tier": "domain", "domains": ["builder-base"]},
81
- {"anchor": "For where a comment, a compatibility note, deprecated behavior, a rejected alternative", "tier": "domain", "domains": ["builder-base"]},
82
- {"anchor": "For SVG diagrams, service blueprints", "tier": "domain", "domains": ["visualization-docs"]},
83
- {"anchor": "When a concept is easier to understand visually", "tier": "domain", "domains": ["visualization-docs"]},
84
- {"anchor": "Use HTML for comparisons, flows, state changes", "tier": "domain", "domains": ["visualization-docs"]},
85
- {"anchor": "Keep HTML self-contained, accessible, and minimal", "tier": "domain", "domains": ["visualization-docs"]},
86
- {"anchor": "Use plain text when it is clearer", "tier": "domain", "domains": ["visualization-docs"]},
87
- {"anchor": "For the detailed `IMPLEMENTATION_MAP.html` construction rules", "tier": "domain", "domains": ["visualization-docs"]},
88
- {"anchor": "In repos with implementation code", "tier": "domain", "domains": ["visualization-docs"]},
89
- {"anchor": "`learn!` — session learning", "tier": "core", "domains": []}
13
+ {"anchor": "Prefer concise Korean responses", "tier": "env-personal", "domains": [], "item_id": "rule-001"},
14
+ {"anchor": "Keep file changes within the requested scope", "tier": "core", "domains": [], "item_id": "rule-002"},
15
+ {"anchor": "First identify the goal, scope, ambiguities", "tier": "core", "domains": [], "item_id": "rule-003"},
16
+ {"anchor": "Resolve ambiguity from context when safe", "tier": "core", "domains": [], "item_id": "rule-004"},
17
+ {"anchor": "For simple requests, choose the most direct", "tier": "core", "domains": [], "item_id": "rule-005"},
18
+ {"anchor": "For non-trivial requests, compare 2-4 methods", "tier": "core", "domains": [], "item_id": "rule-006"},
19
+ {"anchor": "Mark one default method", "tier": "core", "domains": [], "item_id": "rule-007"},
20
+ {"anchor": "Execute the chosen method accurately", "tier": "core", "domains": [], "item_id": "rule-008"},
21
+ {"anchor": "Return to understanding if a discovery breaks", "tier": "core", "domains": [], "item_id": "rule-009"},
22
+ {"anchor": "Reconsider the method if the selected approach", "tier": "core", "domains": [], "item_id": "rule-010"},
23
+ {"anchor": "Log non-blocking discoveries and continue", "tier": "core", "domains": [], "item_id": "rule-011"},
24
+ {"anchor": "If the same loopback happens twice", "tier": "core", "domains": [], "item_id": "rule-012"},
25
+ {"anchor": "Compare the result with the selected", "tier": "core", "domains": [], "item_id": "rule-013"},
26
+ {"anchor": "Ask decision questions in outcome terms", "tier": "core", "domains": [], "item_id": "rule-014"},
27
+ {"anchor": "When the user may not know the domain", "tier": "core", "domains": [], "item_id": "rule-015"},
28
+ {"anchor": "Present 2-4 meaningful options", "tier": "core", "domains": [], "item_id": "rule-016"},
29
+ {"anchor": "For each option, state what changes", "tier": "core", "domains": [], "item_id": "rule-017"},
30
+ {"anchor": "Translate technical terms into plain consequences", "tier": "core", "domains": [], "item_id": "rule-018"},
31
+ {"anchor": "Ask for the user's goal or constraint", "tier": "core", "domains": [], "item_id": "rule-019"},
32
+ {"anchor": "Evaluate user suggestions for goal fit", "tier": "core", "domains": [], "item_id": "rule-020"},
33
+ {"anchor": "Distinguish implementation feasibility from recommendation", "tier": "core", "domains": [], "item_id": "rule-021"},
34
+ {"anchor": "Do not default to a restrictive lens", "tier": "core", "domains": [], "item_id": "rule-022"},
35
+ {"anchor": "Treat user suggestions, inherited premises, prior diagnoses", "tier": "core", "domains": [], "item_id": "rule-023"},
36
+ {"anchor": "For structured-output, runtime-authority, capability-surface", "tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "rule-024"},
37
+ {"anchor": "Use instructions to describe intended work", "tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "rule-025"},
38
+ {"anchor": "Use the LLM for semantic work", "tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "rule-026"},
39
+ {"anchor": "Use the capability surface for structural constraints", "tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "rule-027"},
40
+ {"anchor": "Enforce constraints through the capability surface", "tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "rule-028"},
41
+ {"anchor": "Use tools/code for deterministic work", "tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "rule-029"},
42
+ {"anchor": "When exactness, freshness, scale, repeatability", "tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "rule-030"},
43
+ {"anchor": "Let the LLM design merge, projection", "tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "rule-031"},
44
+ {"anchor": "For required structured or machine-consumed outputs", "tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "rule-032"},
45
+ {"anchor": "Let tools/code own ids, paths, serialization", "tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "rule-033"},
46
+ {"anchor": "Keep deterministic values out of LLM authority", "tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "rule-034"},
47
+ {"anchor": "For simple stable explanations or planning", "tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "rule-035"},
48
+ {"anchor": "Treat a produced field, flag, signal", "tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "rule-036"},
49
+ {"anchor": "Hard-block only deterministically decidable structural", "tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "rule-037"},
50
+ {"anchor": "Runtime/code may enforce the contract", "tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "rule-038"},
51
+ {"anchor": "When adding, changing, renaming, splitting, or exposing anything lasting or shared", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-039"},
52
+ {"anchor": "Before fixing a review finding or test failure", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-040"},
53
+ {"anchor": "For `.xlsx` editing, generation, reconciliation", "tier": "domain", "domains": ["office-work"], "item_id": "rule-041"},
54
+ {"anchor": "For development work, read and use", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-042"},
55
+ {"anchor": "For mock, fixture, fake, stub, simulated-provider", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-043"},
56
+ {"anchor": "Own the full lifecycle of what you create", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-044"},
57
+ {"anchor": "Land risky or behavior-changing work behind", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-045"},
58
+ {"anchor": "For composing a review request, packet", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-046"},
59
+ {"anchor": "After every meaningful code, ontology, config", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-047"},
60
+ {"anchor": "For choosing verification depth, the per-domain mix, the case space, what makes a completion criterion falsifiable", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-048"},
61
+ {"anchor": "Report the checks run, results", "tier": "core", "domains": [], "item_id": "rule-049"},
62
+ {"anchor": "Trust a green check only when it traversed", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-050"},
63
+ {"anchor": "Before comparing two of anything", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-051"},
64
+ {"anchor": "For concrete shell/CLI traps", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-052"},
65
+ {"anchor": "Ambient state — the active shell", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-053"},
66
+ {"anchor": "Before relying on any model id", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-054"},
67
+ {"anchor": "Scope destructive actions (kill, rm, force-push", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-055"},
68
+ {"anchor": "Never accept secrets through transcript- or history-logged channels", "tier": "core", "domains": [], "item_id": "rule-056"},
69
+ {"anchor": "When a secret must be supplied", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-057"},
70
+ {"anchor": "Treat a coarse runtime signal", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-058"},
71
+ {"anchor": "Standing spawn policy: check the spawn gates", "tier": "domain", "domains": ["multi-agent-orchestration"], "item_id": "rule-059"},
72
+ {"anchor": "Down-spawns carry a machine-checkable done-when", "tier": "domain", "domains": ["multi-agent-orchestration"], "item_id": "rule-060"},
73
+ {"anchor": "For work spanning multiple models or CLI agents", "tier": "domain", "domains": ["multi-agent-orchestration"], "item_id": "rule-061"},
74
+ {"anchor": "For composing a prompt, packet, or tool description", "tier": "domain", "domains": ["multi-agent-orchestration"], "item_id": "rule-062"},
75
+ {"anchor": "Allocate models by difficulty", "tier": "domain", "domains": ["multi-agent-orchestration"], "item_id": "rule-063"},
76
+ {"anchor": "Judge a review by how much independence", "tier": "domain", "domains": ["multi-agent-orchestration"], "item_id": "rule-064"},
77
+ {"anchor": "dual-provider frontier design drafts", "tier": "domain", "domains": ["multi-agent-orchestration"], "item_id": "rule-065"},
78
+ {"anchor": "Never retry-storm a live rate limit", "tier": "domain", "domains": ["multi-agent-orchestration"], "item_id": "rule-066"},
79
+ {"anchor": "On any resumed, cleared, or relocated session", "tier": "domain", "domains": ["multi-agent-orchestration"], "item_id": "rule-067"},
80
+ {"anchor": "Keep runtime code, active docs, and execution-facing", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-068"},
81
+ {"anchor": "For where a comment, a compatibility note, deprecated behavior, a rejected alternative", "tier": "domain", "domains": ["builder-base"], "item_id": "rule-069"},
82
+ {"anchor": "For SVG diagrams, service blueprints", "tier": "domain", "domains": ["visualization-docs"], "item_id": "rule-070"},
83
+ {"anchor": "When a concept is easier to understand visually", "tier": "domain", "domains": ["visualization-docs"], "item_id": "rule-071"},
84
+ {"anchor": "Use HTML for comparisons, flows, state changes", "tier": "domain", "domains": ["visualization-docs"], "item_id": "rule-072"},
85
+ {"anchor": "Keep HTML self-contained, accessible, and minimal", "tier": "domain", "domains": ["visualization-docs"], "item_id": "rule-073"},
86
+ {"anchor": "Use plain text when it is clearer", "tier": "domain", "domains": ["visualization-docs"], "item_id": "rule-074"},
87
+ {"anchor": "For the detailed `IMPLEMENTATION_MAP.html` construction rules", "tier": "domain", "domains": ["visualization-docs"], "item_id": "rule-075"},
88
+ {"anchor": "In repos with implementation code", "tier": "domain", "domains": ["visualization-docs"], "item_id": "rule-076"},
89
+ {"anchor": "`learn!` — session learning", "tier": "core", "domains": [], "item_id": "rule-077"}
90
90
  ],
91
91
  "guides": {
92
- "claude-prompting.md": {"tier": "domain", "domains": ["multi-agent-orchestration"], "handles": ["per-family prompting guide", "계열별 prompting guide"]},
93
- "cli-multi-model-workflow.md": {"tier": "domain", "domains": ["multi-agent-orchestration"], "handles": ["multi-model guide", "multi-model 가이드"]},
94
- "coding-staged-workflow.md": {"tier": "domain", "domains": ["builder-base"]},
95
- "concept-economy.md": {"tier": "domain", "domains": ["builder-base"]},
96
- "documentation-hygiene.md": {"tier": "domain", "domains": ["builder-base"]},
97
- "gpt-prompting.md": {"tier": "domain", "domains": ["multi-agent-orchestration"], "handles": ["prompting guides for gpt-family"]},
98
- "implementation-map.md": {"tier": "domain", "domains": ["visualization-docs"]},
99
- "llm-capability-boundary-examples.md": {"tier": "domain", "domains": ["llm-pipeline-dev"]},
100
- "llm-capability-boundary-patterns.md": {"tier": "domain", "domains": ["llm-pipeline-dev"]},
101
- "llm-capability-boundary.md": {"tier": "domain", "domains": ["llm-pipeline-dev"]},
102
- "mock-realization-boundary.md": {"tier": "domain", "domains": ["builder-base"]},
103
- "review-defect-criteria.md": {"tier": "domain", "domains": ["builder-base"]},
104
- "review-request.md": {"tier": "domain", "domains": ["builder-base"]},
105
- "session-distill-workflow.md": {"tier": "infra", "domains": []},
106
- "learning-flow.md": {"tier": "infra", "domains": []},
107
- "svg-visualization-guide.md": {"tier": "domain", "domains": ["visualization-docs"]},
108
- "verification-discipline.md": {"tier": "domain", "domains": ["builder-base"]},
109
- "tooling-gotchas.md": {"tier": "domain", "domains": ["builder-base"]}
92
+ "claude-prompting.md": {"tier": "domain", "domains": ["multi-agent-orchestration"], "handles": ["per-family prompting guide", "계열별 prompting guide"], "item_id": "guide-claude-prompting"},
93
+ "cli-multi-model-workflow.md": {"tier": "domain", "domains": ["multi-agent-orchestration"], "handles": ["multi-model guide", "multi-model 가이드"], "item_id": "guide-cli-multi-model-workflow"},
94
+ "coding-staged-workflow.md": {"tier": "domain", "domains": ["builder-base"], "item_id": "guide-coding-staged-workflow"},
95
+ "concept-economy.md": {"tier": "domain", "domains": ["builder-base"], "item_id": "guide-concept-economy"},
96
+ "documentation-hygiene.md": {"tier": "domain", "domains": ["builder-base"], "item_id": "guide-documentation-hygiene"},
97
+ "gpt-prompting.md": {"tier": "domain", "domains": ["multi-agent-orchestration"], "handles": ["prompting guides for gpt-family"], "item_id": "guide-gpt-prompting"},
98
+ "implementation-map.md": {"tier": "domain", "domains": ["visualization-docs"], "item_id": "guide-implementation-map"},
99
+ "llm-capability-boundary-examples.md": {"tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "guide-llm-capability-boundary-examples"},
100
+ "llm-capability-boundary-patterns.md": {"tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "guide-llm-capability-boundary-patterns"},
101
+ "llm-capability-boundary.md": {"tier": "domain", "domains": ["llm-pipeline-dev"], "item_id": "guide-llm-capability-boundary"},
102
+ "mock-realization-boundary.md": {"tier": "domain", "domains": ["builder-base"], "item_id": "guide-mock-realization-boundary"},
103
+ "review-defect-criteria.md": {"tier": "domain", "domains": ["builder-base"], "item_id": "guide-review-defect-criteria"},
104
+ "review-request.md": {"tier": "domain", "domains": ["builder-base"], "item_id": "guide-review-request"},
105
+ "session-distill-workflow.md": {"tier": "infra", "domains": [], "item_id": "guide-session-distill-workflow"},
106
+ "learning-flow.md": {"tier": "infra", "domains": [], "item_id": "guide-learning-flow"},
107
+ "svg-visualization-guide.md": {"tier": "domain", "domains": ["visualization-docs"], "item_id": "guide-svg-visualization-guide"},
108
+ "slide-writing.md": {"tier": "domain", "domains": ["office-work", "visualization-docs"], "item_id": "skill-slide-writing"},
109
+ "verification-discipline.md": {"tier": "domain", "domains": ["builder-base"], "item_id": "guide-verification-discipline"},
110
+ "tooling-gotchas.md": {"tier": "domain", "domains": ["builder-base"], "item_id": "guide-tooling-gotchas"}
110
111
  },
111
112
  "hooks": {
112
- "tooling-gotchas-hook.py": {"tier": "domain", "domains": ["builder-base"], "source_guide": "tooling-gotchas.md"}
113
+ "tooling-gotchas-hook.py": {"tier": "domain", "domains": ["builder-base"], "source_guide": "tooling-gotchas.md", "item_id": "hook-tooling-gotchas-hook"}
113
114
  },
114
115
  "agents": {
115
- "frontier.md": {"tier": "domain", "domains": ["multi-agent-orchestration"]},
116
- "sweep.md": {"tier": "domain", "domains": ["multi-agent-orchestration"]},
117
- "workhorse.md": {"tier": "domain", "domains": ["multi-agent-orchestration"]}
116
+ "frontier.md": {"tier": "domain", "domains": ["multi-agent-orchestration"], "item_id": "agent-frontier"},
117
+ "sweep.md": {"tier": "domain", "domains": ["multi-agent-orchestration"], "item_id": "agent-sweep"},
118
+ "workhorse.md": {"tier": "domain", "domains": ["multi-agent-orchestration"], "item_id": "agent-workhorse"}
118
119
  },
119
120
  "skills": {
120
- "repo-charter": {"tier": "domain", "domains": ["builder-base"]}
121
+ "repo-charter": {"tier": "domain", "domains": ["builder-base"], "item_id": "skill-repo-charter"}
121
122
  }
122
123
  }
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env python3
2
+ """Write the update-check cache atomically.
3
+
4
+ The launcher READS this file on every start and never writes it, so a half-written
5
+ cache is a crash in the TUI rather than a stale badge — hence os.replace over a
6
+ temp file in the same directory, not a plain open-and-write.
7
+
8
+ `latest` is omitted when the lookup failed; `checked_at` is written regardless, so
9
+ an offline machine records its attempt and waits out the interval instead of
10
+ retrying on every launch. Absence of `latest` therefore means "asked, no answer",
11
+ which the launcher must not render as "up to date".
12
+ """
13
+ import json
14
+ import os
15
+ import sys
16
+ import tempfile
17
+
18
+
19
+ def main(argv: list[str]) -> int:
20
+ if len(argv) != 5:
21
+ print("usage: write-update-cache.py <out> <checked_at> <latest|''> <current>",
22
+ file=sys.stderr)
23
+ return 2
24
+ out, checked_at, latest, current = argv[1], argv[2], argv[3], argv[4]
25
+ try:
26
+ checked = int(checked_at)
27
+ except ValueError:
28
+ print(f"checked_at is not an integer: {checked_at!r}", file=sys.stderr)
29
+ return 2
30
+ payload: dict[str, object] = {"checked_at": checked}
31
+ if current:
32
+ payload["current"] = current
33
+ if latest:
34
+ payload["latest"] = latest
35
+ directory = os.path.dirname(out) or "."
36
+ os.makedirs(directory, exist_ok=True)
37
+ fd, tmp = tempfile.mkstemp(dir=directory, prefix=".update-check.")
38
+ try:
39
+ with os.fdopen(fd, "w", encoding="utf-8") as handle:
40
+ json.dump(payload, handle)
41
+ os.replace(tmp, out)
42
+ except BaseException:
43
+ # A temp file left in the state dir would be swept by nothing.
44
+ try:
45
+ os.unlink(tmp)
46
+ except OSError:
47
+ pass
48
+ raise
49
+ return 0
50
+
51
+
52
+ if __name__ == "__main__":
53
+ sys.exit(main(sys.argv))
package/install.sh CHANGED
@@ -13,6 +13,7 @@
13
13
  # agent-bios status show what is installed and where
14
14
  # agent-bios cost the session cost / context meter, from any directory
15
15
  # agent-bios update git pull + reinstall (clone), or print the npm update line
16
+ # agent-bios update --check cache the registry's latest version for the TUI badge
16
17
  # agent-bios uninstall remove deployed files and the zsh hook
17
18
  # agent-bios help
18
19
  #
@@ -95,6 +96,13 @@ CLEANUP_FAILED=0
95
96
  # treating it as a failure made cmd_install exit 1 and the EXIT trap restore the previous
96
97
  # manifest — leaving the new corpus on disk with the record saying the old one was deployed.
97
98
  ENTRY_NEEDS_ACTION=0
99
+ # Set when the required corpus-status projection could not be written. Deferred rather than
100
+ # returned on the spot: the projection runs AFTER the corpus is deployed, and returning
101
+ # there would fire the EXIT trap and restore the PREVIOUS manifest — leaving the new corpus
102
+ # on disk with the record naming the old one, which is the split state above. The manifest
103
+ # is completed first so it describes what is really there, and the command then exits
104
+ # non-zero. The files, the record, and the exit code then each say something true.
105
+ PROJECTION_FAILED=0
98
106
  # Deployed files uninstall could not back up, so did not delete. Global rather than local
99
107
  # because the closing summary must not claim a clean removal that did not happen.
100
108
  UNBACKED=0
@@ -381,7 +389,37 @@ assemble_corpus() {
381
389
  if [ -f "$CLAUDE_DIR/central/bundle.md" ]; then
382
390
  printf '%s\n' "$CLAUDE_DIR/central/bundle.md" >> "$MANIFEST"
383
391
  fi
384
- for sub in guides hooks agents; do
392
+ # A guide can carry a same-stem companion tree. The assembler owns that structure, so
393
+ # manifest it through its resolver rather than flattening `guides/*.md`: uninstall needs
394
+ # every deployed script/asset by its exact path, and must not claim a user-created sibling
395
+ # merely because it sits below one of our guide directories.
396
+ local source_guides="$REPO/claude/guides" codex_guides="$REPO/codex/guides"
397
+ manifest_guide_members() {
398
+ # Pin the installed resolver file independently of the selected content tree.
399
+ python3 - "$REPO/compose/assemble.py" "$1" "$2" <<'PY'
400
+ import pathlib
401
+ import sys
402
+
403
+ assembler, source, dest = map(pathlib.Path, sys.argv[1:])
404
+ sys.path.insert(0, str(assembler.parent))
405
+ from assemble import GuideMemberError, guide_member_map
406
+
407
+ try:
408
+ members = guide_member_map(source)
409
+ except GuideMemberError as exc:
410
+ raise SystemExit(f"invalid guide bundle source: {exc}")
411
+ for paths in members.values():
412
+ for rel in paths:
413
+ target = dest / rel
414
+ if target.is_file():
415
+ print(target)
416
+ PY
417
+ }
418
+ if ! manifest_guide_members "$source_guides" "$CLAUDE_DIR/central/guides" >> "$MANIFEST"; then
419
+ log "could not enumerate assembled Claude guide members for the manifest"
420
+ return 1
421
+ fi
422
+ for sub in hooks agents; do
385
423
  for s in "$REPO"/claude/"$sub"/*; do
386
424
  [ -f "$s" ] || continue
387
425
  dst="$CLAUDE_DIR/central/$sub/$(basename "$s")"
@@ -390,16 +428,10 @@ assemble_corpus() {
390
428
  if [ -f "$dst" ]; then printf '%s\n' "$dst" >> "$MANIFEST"; fi
391
429
  done
392
430
  done
393
- for g in "$REPO"/codex/guides/*.md; do
394
- [ -f "$g" ] || continue
395
- dst="$CODEX_DIR/guides/$(basename "$g")"
396
- # if-form, not `[ -f ] && printf`: when the alphabetically LAST guide is
397
- # not deployed (a partial domain selection on a fresh machine), the
398
- # compound's false status became the loop's, the loop's became the
399
- # function's, and the install died silently right after ASSEMBLED —
400
- # a latent first-user bug the I9 scenario exposed.
401
- if [ -f "$dst" ]; then printf '%s\n' "$dst" >> "$MANIFEST"; fi
402
- done
431
+ if ! manifest_guide_members "$codex_guides" "$CODEX_DIR/guides" >> "$MANIFEST"; then
432
+ log "could not enumerate assembled Codex guide members for the manifest"
433
+ return 1
434
+ fi
403
435
  fi
404
436
  return 0
405
437
  }
@@ -859,12 +891,36 @@ cmd_install() {
859
891
  # deployed, against this script's own `--dry-run print actions without changing
860
892
  # anything` and README's identical sentence. A dry run that edits state is worse than
861
893
  # no dry run: it is consulted precisely when the user is unwilling to touch anything.
894
+ #
895
+ # The projection is REQUIRED, not best-effort. It used to be neither: stderr and the
896
+ # exit status were both discarded and every failure printed one guess of a note —
897
+ # "versions.json/ledger missing?" — which was wrong for the failure that actually
898
+ # happened. `compose/corpus-state.py` was not in the npm package at all, so a real
899
+ # npm install rewrote the corpus, updated selection.json and version.json, passed
900
+ # verification, exited 0, and left corpus-status.json stale from a previous
901
+ # deployment. The launcher's corpus panel reads that file, so the machine reported a
902
+ # selection the successful run had not recorded. A command that deploys the launcher
903
+ # and advertises its panel cannot call that a success.
904
+ #
905
+ # The script now ships and degrades honestly in an npm layout (domains real,
906
+ # version/ledger reported unavailable), so the remaining failures are real ones:
907
+ # an unwritable destination, an invalid status, a missing interpreter. Those fail
908
+ # the install, and the reason reaches the operator instead of /dev/null.
862
909
  if [ "$DRY_RUN" = 1 ]; then
863
910
  info "[dry-run] project corpus-status"
864
- elif python3 "$REPO/compose/corpus-state.py" project --repo "$REPO" >/dev/null 2>&1; then
865
- info "corpus-status projected"
866
911
  else
867
- log "note: corpus-status projection unavailable (versions.json/ledger missing?)"
912
+ local projection_log
913
+ projection_log="$(mktemp -t corpus-projection)"
914
+ if python3 "$REPO/compose/corpus-state.py" project --repo "$REPO" >"$projection_log" 2>&1; then
915
+ info "corpus-status projected"
916
+ rm -f "$projection_log"
917
+ else
918
+ log "corpus-status projection FAILED — the launcher's corpus panel would report a"
919
+ log "selection this run did not record. Its own output:"
920
+ sed 's/^/ /' "$projection_log"
921
+ log " full output: $projection_log"
922
+ PROJECTION_FAILED=1
923
+ fi
868
924
  fi
869
925
  # Deploy/system version marker for the launcher's TUI version line, read from
870
926
  # package.json (version + releaseDate) — distinct from the corpus content
@@ -917,7 +973,13 @@ PY
917
973
  # restore armed above must not fire.
918
974
  INSTALL_COMPLETED=1
919
975
  log ""
920
- log "Done. Open a new shell (or: source \"$ZSHRC\") to activate the zero-arg launcher."
976
+ # Withheld when the projection failed: the run below reports INSTALL INCOMPLETE and
977
+ # exits non-zero, and printing "Done." first told the operator both things in the
978
+ # same breath. The manifest is already complete by here, which is the point — the
979
+ # files really are deployed; what failed is the record of WHICH selection they are.
980
+ if [ "$PROJECTION_FAILED" != 1 ]; then
981
+ log "Done. Open a new shell (or: source \"$ZSHRC\") to activate the zero-arg launcher."
982
+ fi
921
983
  if [ "${ENTRY_NEEDS_ACTION:-0}" = 1 ]; then
922
984
  log ""
923
985
  log "ONE STEP LEFT: add this line to $CLAUDE_DIR/CLAUDE.md (yours; we never rewrite it):"
@@ -928,6 +990,13 @@ PY
928
990
  # must not become a nonzero exit under set -e.
929
991
  { [ -n "$BACKUP_DIR" ] && [ -d "$BACKUP_DIR" ] && log "Replaced files were backed up under $BACKUP_DIR"; } || true
930
992
  prune_backups
993
+ if [ "$PROJECTION_FAILED" = 1 ]; then
994
+ log ""
995
+ log "INSTALL INCOMPLETE: the corpus is deployed and the manifest records it, but the"
996
+ log "corpus-status projection failed above — the launcher's panel would describe a"
997
+ log "state this run did not record. Fix the cause and re-run: agent-bios install"
998
+ exit 1
999
+ fi
931
1000
  else
932
1001
  log "VERIFY FAILED after install — see messages above"
933
1002
  exit 1
@@ -1417,8 +1486,22 @@ cmd_onboard() {
1417
1486
  log "ONBOARDING INCOMPLETE: the bundle is installed but not loading — fix the cause above and re-run: agent-bios verify"
1418
1487
  exit 1
1419
1488
  fi
1420
- python3 "$REPO/compose/corpus-state.py" record-apply \
1421
- --requested "$sel" --outcome applied >/dev/null 2>&1 || true
1489
+ # The SUCCESS record is strict; the two failure records above stay tolerant. The
1490
+ # asymmetry is the point: a swallowed failure-record rides a run that is already
1491
+ # exiting non-zero and reporting why, while a swallowed success-record is how
1492
+ # onboarding prints a completed summary over a status file that never learned the
1493
+ # selection was applied. That is the state this whole change exists to remove, so it
1494
+ # cannot be the one still guarded by `|| true`.
1495
+ record_log="$(mktemp -t corpus-record-apply)"
1496
+ if ! python3 "$REPO/compose/corpus-state.py" record-apply \
1497
+ --requested "$sel" --outcome applied >"$record_log" 2>&1; then
1498
+ log "ONBOARDING INCOMPLETE: the corpus applied, but recording that outcome failed —"
1499
+ log "the corpus panel would not show this selection as applied. Its own output:"
1500
+ sed 's/^/ /' "$record_log"
1501
+ log " full output: $record_log"
1502
+ exit 1
1503
+ fi
1504
+ rm -f "$record_log"
1422
1505
  # The prune is authorized by the canary's proof, and cmd_install ran before the canary existed
1423
1506
  # for this bundle rev — so it kept everything. Now that loading is proven, run it for real.
1424
1507
  migrate_learnings
@@ -1613,11 +1696,57 @@ shell_shadow_summary() {
1613
1696
  fi
1614
1697
  }
1615
1698
 
1699
+ # The update check is a READ of a public version number: it sends the package name
1700
+ # and nothing derived from this machine, which is the same class as provision-venv's
1701
+ # PyPI fetch and the onboard model probe — see ENDPOINTS.md "Zero egress by default",
1702
+ # whose claim is scoped to DATA egress. It delegates to `npm view` rather than naming
1703
+ # a registry, so a private registry, a proxy, and the user's auth all keep working and
1704
+ # no shipped file carries a URL (gates/check-endpoints.py forbids that outright).
1705
+ #
1706
+ # `checked_at` is written even when the lookup FAILS. An offline machine that recorded
1707
+ # nothing would retry on every launch, which is the opposite of once a day.
1708
+ refresh_update_cache() {
1709
+ if [ "${AGENT_BIOS_UPDATE_CHECK:-1}" = "0" ]; then
1710
+ log "update check disabled (AGENT_BIOS_UPDATE_CHECK=0)"
1711
+ return 0
1712
+ fi
1713
+ local name latest now out
1714
+ name="$(json_field "$REPO/package.json" name)" || return 1
1715
+ [ -n "$name" ] || return 1
1716
+ now="$(date +%s)"
1717
+ latest=""
1718
+ if command -v npm >/dev/null 2>&1; then
1719
+ # `|| latest=""` is not defensive noise: this file runs under `set -euo pipefail`,
1720
+ # so an npm that exits non-zero (offline, firewalled, private registry down) makes
1721
+ # the PIPELINE fail and `set -e` abort the function before it can record the
1722
+ # attempt — turning every offline launch into a retry and `update --check` into
1723
+ # exit 1. Caught by I16's failing-registry stub, not by review.
1724
+ latest="$(npm view "$name" version 2>/dev/null | tr -d '[:space:]')" || latest=""
1725
+ fi
1726
+ mkdir -p "$STATE_DIR" || return 1
1727
+ out="$STATE_DIR/update-check.json"
1728
+ # Atomic: a half-written cache read by the launcher is a crash in the TUI.
1729
+ python3 "$REPO/compose/write-update-cache.py" "$out" "$now" "$latest" "$(source_version)" || return 1
1730
+ if [ -n "$latest" ]; then
1731
+ log "update check: latest $latest (installed $(source_version))"
1732
+ else
1733
+ log "update check: could not reach the registry; recorded the attempt"
1734
+ fi
1735
+ }
1736
+
1616
1737
  cmd_update() {
1738
+ if [ "${UPDATE_CHECK_ONLY:-0}" = 1 ]; then
1739
+ refresh_update_cache
1740
+ return $?
1741
+ fi
1617
1742
  if [ -e "$REPO/.git" ]; then
1618
1743
  log "Updating from git..."
1619
1744
  run git -C "$REPO" pull --ff-only
1620
- cmd_install
1745
+ if [ "${AGENT_BIOS_LEGACY_INSTALL:-0}" = 1 ]; then
1746
+ cmd_install
1747
+ else
1748
+ python3 "$REPO/compose/corpus_install.py" --repo "$REPO" install
1749
+ fi
1621
1750
  else
1622
1751
  log "Installed as an npm package. Update with:"
1623
1752
  log " npm install -g agent-bios@latest && agent-bios install"
@@ -1629,11 +1758,14 @@ cmd_update() {
1629
1758
 
1630
1759
  usage() {
1631
1760
  cat <<'EOF'
1632
- agent-bios — deploy the Claude/Codex instruction SSOT into $HOME (by copy).
1633
-
1634
- agent-bios install deploy into this environment (backs up + verifies)
1635
- agent-bios onboard interactive domain selection + install + activation canary
1636
- agent-bios verify check the deployed state matches the source
1761
+ agent-bios — manage private corpus content for explicitly activated sessions.
1762
+
1763
+ agent-bios install store a private runtime and corpus baseline
1764
+ agent-bios onboard select domains for future activated sessions
1765
+ agent-bios corpus open Corpus Studio; list/show/plan/apply also work non-TTY
1766
+ agent-bios migrate preview legacy global cleanup; --apply --yes applies it
1767
+ agent-bios reset preview reset; --apply --yes --expected-revision REV applies it
1768
+ agent-bios verify verify the private runtime, baseline, and managed files
1637
1769
  agent-bios learn submit a session learning (reads the JSON record on
1638
1770
  stdin; this is what the learn! flow calls, and it
1639
1771
  works from any directory, unlike a repo-relative path)
@@ -1641,7 +1773,10 @@ agent-bios — deploy the Claude/Codex instruction SSOT into $HOME (by copy).
1641
1773
  agent-bios cost the session cost / context meter (session-cost.py), from any
1642
1774
  directory: agent-bios cost [--context [--budget N]] <transcript>
1643
1775
  agent-bios update git pull + reinstall (clone), or print the npm update line
1644
- agent-bios uninstall remove deployed files and the zsh hook
1776
+ agent-bios update --check ask the registry for the latest version and cache it
1777
+ for the launcher's badge; sends the package name and nothing
1778
+ else, runs at most daily, AGENT_BIOS_UPDATE_CHECK=0 disables it
1779
+ agent-bios uninstall remove the private runtime; preserve personal and session data
1645
1780
  agent-bios help
1646
1781
 
1647
1782
  Flags: --dry-run print actions without changing anything
@@ -1679,6 +1814,20 @@ EOF
1679
1814
  CMD="${1:-help}"
1680
1815
  if [ $# -gt 0 ]; then shift; fi
1681
1816
 
1817
+ # Private installation is the new user path. The explicit legacy flag exists only
1818
+ # while maintained install fixtures and pre-migration environments exercise the old
1819
+ # writer. No private operation falls through to a global writer.
1820
+ if [ "$CMD" = "corpus" ]; then
1821
+ exec python3 "$REPO/compose/corpus.py" --repo "$REPO" "$@" <&3
1822
+ fi
1823
+ if [ "${AGENT_BIOS_LEGACY_INSTALL:-0}" != 1 ]; then
1824
+ case "$CMD" in
1825
+ install|onboard|verify|status|uninstall|migrate|reset)
1826
+ exec python3 "$REPO/compose/corpus_install.py" --repo "$REPO" "$CMD" "$@" <&3
1827
+ ;;
1828
+ esac
1829
+ fi
1830
+
1682
1831
  # `learn` forwards its arguments and stdin straight to the collector, so it must
1683
1832
  # bypass the flag parser below (which rejects anything it does not know). This
1684
1833
  # subcommand is the only PATH-reachable entry to capture: the corpus guide used
@@ -1706,6 +1855,7 @@ DOMAINS_SET=0
1706
1855
  while [ $# -gt 0 ]; do
1707
1856
  case "$1" in
1708
1857
  --dry-run) DRY_RUN=1 ;;
1858
+ --check) UPDATE_CHECK_ONLY=1 ;;
1709
1859
  --with) shift; WITH="${1:-}"; [ -n "$WITH" ] || { log "--with needs a comma-separated capability list"; exit 2; } ;;
1710
1860
  --with=*) WITH="${1#--with=}"; [ -n "$WITH" ] || { log "--with needs a comma-separated capability list"; exit 2; } ;;
1711
1861
  --domains) shift; DOMAINS_ARG="${1:-}"; DOMAINS_SET=1; [ -n "$DOMAINS_ARG" ] || { log "--domains needs a comma-separated domain list (use onboard for core-only)"; exit 2; } ;;