agent-lifecycle 0.2.0__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. agent_lifecycle-0.2.2/.devague/frames/agent-lifecycle-v0-3-ships-the-two-pluggable-seam.json +181 -0
  2. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.gitignore +6 -0
  3. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/CHANGELOG.md +37 -0
  4. agent_lifecycle-0.2.2/CLAUDE.md +166 -0
  5. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/PKG-INFO +1 -1
  6. agent_lifecycle-0.2.2/docs/specs/2026-06-09-agent-lifecycle-v0-3-ships-the-two-pluggable-seam.md +50 -0
  7. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/pyproject.toml +1 -1
  8. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/uv.lock +31 -31
  9. agent_lifecycle-0.2.0/CLAUDE.md +0 -28
  10. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/agent-config/SKILL.md +0 -0
  11. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/agent-config/data/backend-fingerprints.yaml +0 -0
  12. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/agent-config/scripts/show.sh +0 -0
  13. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/ask-colleague/SKILL.md +0 -0
  14. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/ask-colleague/prompts/explore.md +0 -0
  15. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/ask-colleague/prompts/review.md +0 -0
  16. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/ask-colleague/prompts/write.md +0 -0
  17. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/ask-colleague/scripts/ask-colleague.sh +0 -0
  18. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/assign-to-workforce/SKILL.md +0 -0
  19. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +0 -0
  20. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/cicd/SKILL.md +0 -0
  21. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/cicd/scripts/_resolve-nick.sh +0 -0
  22. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/cicd/scripts/portability-lint.sh +0 -0
  23. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/cicd/scripts/pr-reply.sh +0 -0
  24. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/cicd/scripts/pr-status.sh +0 -0
  25. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/cicd/scripts/workflow.sh +0 -0
  26. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/communicate/SKILL.md +0 -0
  27. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
  28. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
  29. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
  30. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
  31. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/communicate/scripts/templates/skill-new-brief.md +0 -0
  32. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/communicate/scripts/templates/skill-update-brief.md +0 -0
  33. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
  34. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
  35. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/pypi-maintainer/SKILL.md +0 -0
  36. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/pypi-maintainer/scripts/switch-source.sh +0 -0
  37. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/run-tests/SKILL.md +0 -0
  38. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/run-tests/scripts/test.sh +0 -0
  39. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/sonarclaude/SKILL.md +0 -0
  40. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
  41. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/spec-to-plan/SKILL.md +0 -0
  42. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +0 -0
  43. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/think/SKILL.md +0 -0
  44. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/think/scripts/think.sh +0 -0
  45. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/version-bump/SKILL.md +0 -0
  46. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills/version-bump/scripts/bump.py +0 -0
  47. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.claude/skills.local.yaml.example +0 -0
  48. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.flake8 +0 -0
  49. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.github/workflows/publish.yml +0 -0
  50. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.github/workflows/tests.yml +0 -0
  51. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/.markdownlint-cli2.yaml +0 -0
  52. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/LICENSE +0 -0
  53. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/README.md +0 -0
  54. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/agent_lifecycle/__init__.py +0 -0
  55. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/agent_lifecycle/__main__.py +0 -0
  56. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/agent_lifecycle/cli/__init__.py +0 -0
  57. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/agent_lifecycle/cli/_commands/__init__.py +0 -0
  58. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/agent_lifecycle/cli/_commands/cli.py +0 -0
  59. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/agent_lifecycle/cli/_commands/doctor.py +0 -0
  60. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/agent_lifecycle/cli/_commands/explain.py +0 -0
  61. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/agent_lifecycle/cli/_commands/learn.py +0 -0
  62. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/agent_lifecycle/cli/_commands/overview.py +0 -0
  63. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/agent_lifecycle/cli/_commands/whoami.py +0 -0
  64. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/agent_lifecycle/cli/_errors.py +0 -0
  65. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/agent_lifecycle/cli/_output.py +0 -0
  66. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/agent_lifecycle/explain/__init__.py +0 -0
  67. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/agent_lifecycle/explain/catalog.py +0 -0
  68. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/culture.yaml +0 -0
  69. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/docs/skill-sources.md +0 -0
  70. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/sonar-project.properties +0 -0
  71. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/tests/__init__.py +0 -0
  72. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/tests/test_cli.py +0 -0
  73. {agent_lifecycle-0.2.0 → agent_lifecycle-0.2.2}/tests/test_cli_introspection.py +0 -0
@@ -0,0 +1,181 @@
1
+ {
2
+ "slug": "agent-lifecycle-v0-3-ships-the-two-pluggable-seam",
3
+ "title": "agent-lifecycle v0.3 ships the two pluggable seam interfaces \u2014 Transport (message-first, presence optional) and Harness \u2014 plus a minimal in-process supervisor core and a reference echo transport+harness that prove the seam end-to-end, depending on nothing culture/agentirc/Slack-specific.",
4
+ "schema_version": 1,
5
+ "status": "exported",
6
+ "created": "2026-06-09T23:02:18Z",
7
+ "updated": "2026-06-09T23:08:43Z",
8
+ "claims": [
9
+ {
10
+ "id": "c1",
11
+ "kind": "announcement",
12
+ "text": "agent-lifecycle v0.3 ships the two pluggable seam interfaces \u2014 Transport (message-first, presence optional) and Harness \u2014 plus a minimal in-process supervisor core and a reference echo transport+harness that prove the seam end-to-end, depending on nothing culture/agentirc/Slack-specific.",
13
+ "origin": "user",
14
+ "status": "confirmed",
15
+ "honesty_conditions": [
16
+ {
17
+ "id": "h1",
18
+ "text": "The reference harness+transport demo runs in CI with no network and no optional culture/agentirc/Slack packages installed.",
19
+ "status": "confirmed"
20
+ }
21
+ ],
22
+ "hard_questions": [],
23
+ "links": []
24
+ },
25
+ {
26
+ "id": "c2",
27
+ "kind": "audience",
28
+ "text": "The cultureagent and colleague maintainers (the two proving harnesses) plus the charter reviewers (guildmaster#61) who need concrete code \u2014 not prose \u2014 to ratify the Transport/Harness seam.",
29
+ "origin": "llm",
30
+ "status": "confirmed",
31
+ "honesty_conditions": [
32
+ {
33
+ "id": "h7",
34
+ "text": "The exported spec is directly consumable by the cultureagent + colleague maintainers as the ratification target: it names both proving harnesses and links guildmaster#61.",
35
+ "status": "confirmed"
36
+ }
37
+ ],
38
+ "hard_questions": [],
39
+ "links": []
40
+ },
41
+ {
42
+ "id": "c3",
43
+ "kind": "after_state",
44
+ "text": "The Transport and Harness contracts are importable from agent_lifecycle and demonstrated end-to-end: a reference harness wired to a reference transport through the supervisor round-trips a message in-process, with zero culture/agentirc/Slack imports.",
45
+ "origin": "llm",
46
+ "status": "confirmed",
47
+ "honesty_conditions": [
48
+ {
49
+ "id": "h2",
50
+ "text": "round-trip is observable: an inbound message handed to the Harness produces an outbound message delivered back through the Transport, asserted by a test \u2014 not just an interface that type-checks.",
51
+ "status": "confirmed"
52
+ }
53
+ ],
54
+ "hard_questions": [],
55
+ "links": []
56
+ },
57
+ {
58
+ "id": "c4",
59
+ "kind": "before_state",
60
+ "text": "The agent runtime is entangled inside cultureagent: the four backend daemons and the supervisor mechanics live together, and IRC is hardcoded as the transport (IRCTransport / agentirc VirtualClient lineage). No transport-free, harness-free core exists.",
61
+ "origin": "llm",
62
+ "status": "confirmed",
63
+ "honesty_conditions": [
64
+ {
65
+ "id": "h8",
66
+ "text": "The entanglement is citable in cultureagent today: the backend daemons and the supervisor mechanics live in the same package, and IRCTransport is the only transport.",
67
+ "status": "confirmed"
68
+ }
69
+ ],
70
+ "hard_questions": [],
71
+ "links": []
72
+ },
73
+ {
74
+ "id": "c5",
75
+ "kind": "why_it_matters",
76
+ "text": "A transport-free, harness-free core lets cultureagent slim to a harness pack and lets colleague/Slack build on the same runtime without inheriting IRC or the Claude-family backends \u2014 the coupling that blocks both cases today.",
77
+ "origin": "llm",
78
+ "status": "confirmed",
79
+ "honesty_conditions": [
80
+ {
81
+ "id": "h9",
82
+ "text": "With the core extracted, a colleague-on-Slack deployment can be composed with no agentirc/IRC/culture package anywhere in its dependency tree.",
83
+ "status": "confirmed"
84
+ }
85
+ ],
86
+ "hard_questions": [],
87
+ "links": []
88
+ },
89
+ {
90
+ "id": "c6",
91
+ "kind": "boundary",
92
+ "text": "First increment only: NOT extracting cultureagent's four backends, NOT shipping the IRC/Slack/agtag transport plugs, and NOT refitting cultureagent to consume the package yet. Those follow once the seam is ratified.",
93
+ "origin": "llm",
94
+ "status": "confirmed",
95
+ "honesty_conditions": [
96
+ {
97
+ "id": "h10",
98
+ "text": "This increment is shippable and reviewable with NO cultureagent source present in this repo \u2014 it adds only new in-repo modules + tests.",
99
+ "status": "confirmed"
100
+ }
101
+ ],
102
+ "hard_questions": [],
103
+ "links": []
104
+ },
105
+ {
106
+ "id": "c7",
107
+ "kind": "success_signal",
108
+ "text": "A pytest test composes the reference Harness + reference Transport through the supervisor and round-trips a message in-process; an import-guard test asserts agent_lifecycle has no culture/agentirc/Slack import in its dependency tree.",
109
+ "origin": "llm",
110
+ "status": "confirmed",
111
+ "honesty_conditions": [
112
+ {
113
+ "id": "h3",
114
+ "text": "the import-guard test fails loudly if a future commit adds a culture/agentirc/Slack import to the core (e.g. it walks the import graph, not just a grep).",
115
+ "status": "confirmed"
116
+ }
117
+ ],
118
+ "hard_questions": [],
119
+ "links": []
120
+ },
121
+ {
122
+ "id": "c8",
123
+ "kind": "decision",
124
+ "text": "Transport is message-first: a small message core (send, receive/subscribe, identity) with presence (join/part/who) as an OPTIONAL capability that async transports omit. Adopted from day one regardless of the colleague question, per the charter's stated safe bet.",
125
+ "origin": "llm",
126
+ "status": "confirmed",
127
+ "honesty_conditions": [
128
+ {
129
+ "id": "h4",
130
+ "text": "the message-first core supports an async/no-presence transport without changing the Transport signature \u2014 verifiable by sketching the agtag shape against it.",
131
+ "status": "confirmed"
132
+ }
133
+ ],
134
+ "hard_questions": [],
135
+ "links": []
136
+ },
137
+ {
138
+ "id": "c9",
139
+ "kind": "requirement",
140
+ "text": "agent_lifecycle's runtime dependency tree imports nothing culture-, agentirc-, or Slack-specific; the seam is defined as abstract interfaces (Protocol/ABC) so concrete transports/harnesses live in downstream packs/plugs.",
141
+ "origin": "llm",
142
+ "status": "confirmed",
143
+ "honesty_conditions": [
144
+ {
145
+ "id": "h5",
146
+ "text": "a downstream pack can implement Transport/Harness against only agent_lifecycle's public exports, with no import from a sibling pack.",
147
+ "status": "confirmed"
148
+ }
149
+ ],
150
+ "hard_questions": [],
151
+ "links": []
152
+ },
153
+ {
154
+ "id": "c10",
155
+ "kind": "non_goal",
156
+ "text": "Presence-first transport design, and any real network transport (IRC/Slack/agtag) \u2014 the only concrete implementations in this increment are in-process reference doubles used to prove the seam.",
157
+ "origin": "llm",
158
+ "status": "confirmed",
159
+ "honesty_conditions": [],
160
+ "hard_questions": [],
161
+ "links": []
162
+ },
163
+ {
164
+ "id": "c11",
165
+ "kind": "decision",
166
+ "text": "Resolved (was the charter open question): colleague's agents are live, process-backed, streaming harnesses like Claude Code and Codex \u2014 the same family as cultureagent's backends. So every proving harness is real-time/request-reply; async-durable-no-presence is purely a TRANSPORT capability (only agtag), never a Harness one. The Harness interface must therefore support a long-lived, streaming-capable brain; presence stays a transport-only optional mixin.",
167
+ "origin": "llm",
168
+ "status": "confirmed",
169
+ "honesty_conditions": [
170
+ {
171
+ "id": "h6",
172
+ "text": "The Harness interface can express a process-backed streaming brain (start/feed-message/stream-reply/stop) without assuming any transport, and no Harness method takes presence as a parameter.",
173
+ "status": "confirmed"
174
+ }
175
+ ],
176
+ "hard_questions": [],
177
+ "links": []
178
+ }
179
+ ],
180
+ "open_vagueness": []
181
+ }
@@ -228,3 +228,9 @@ __marimo__/
228
228
 
229
229
  # Per-machine skills config (copy from skills.local.yaml.example)
230
230
  skills.local.yaml
231
+
232
+ # devague working state (not committed by default)
233
+ .devague/reviews/
234
+ # Mutable "current frame" pointer — local working state, churns per branch.
235
+ # The durable artifacts are .devague/frames/<slug>.json + docs/specs/<slug>.md.
236
+ .devague/current
@@ -5,6 +5,43 @@ All notable changes to this project will be documented in this file.
5
5
  Format follows [Keep a Changelog](https://keepachangelog.com/). This project
6
6
  adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.2] - 2026-06-10
9
+
10
+ ### Added
11
+
12
+ - **Converged devague spec for the first build increment of issue #1 /
13
+ guildmaster#61** (`docs/specs/2026-06-09-agent-lifecycle-v0-3-ships-the-two-pluggable-seam.md`,
14
+ with the frame state under `.devague/frames/`). Scopes the extraction's *start*
15
+ to: define the `Transport` (message-first, presence optional) and `Harness`
16
+ interfaces, a minimal in-process supervisor, and reference echo doubles that
17
+ prove the seam end-to-end — with **no** cultureagent backend extraction and
18
+ **no** real IRC/Slack/agtag transport in this increment. Resolves the charter's
19
+ open question: colleague's agents are live, process-backed streaming harnesses
20
+ (like Claude Code / Codex), so async-no-presence is a transport-only concern.
21
+
22
+ ### Changed
23
+
24
+ ### Fixed
25
+
26
+ ## [0.2.1] - 2026-06-10
27
+
28
+ ### Added
29
+
30
+ ### Changed
31
+
32
+ - **Expanded `CLAUDE.md` from the bootstrap seed into a full runtime prompt**
33
+ (via `/init`). It now documents the build/test/lint/rubric commands, the CLI
34
+ dispatch architecture (the `--json` argv pre-peek, the `register()` pattern,
35
+ `CliError` traceback suppression), the two cross-cutting contracts (error
36
+ shape + stdout/stderr split), the four parallel registries a new verb must
37
+ update, the identity/`whoami` source-of-truth, and the version-bump /
38
+ cite-don't-import / rename / CI conventions. Flags that the stated
39
+ process-lifecycle-supervisor domain is **not built yet** — the package ships
40
+ only the template's introspection CLI today — so a future instance does not
41
+ mistake the scaffold for the runtime.
42
+
43
+ ### Fixed
44
+
8
45
  ## [0.2.0] - 2026-06-06
9
46
 
10
47
  ### Added
@@ -0,0 +1,166 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## What this repo is
6
+
7
+ `agent-lifecycle` is an AgentCulture mesh agent, scaffolded from
8
+ `culture-agent-template`. Its **stated domain** (see `README.md` / `pyproject.toml`)
9
+ is a *harness- and transport-agnostic agent runtime: supervise an agent's process
10
+ lifecycle independent of its harness (brain) and its transport (IRC/Slack/agtag).*
11
+
12
+ **That runtime is not built yet.** Today the package ships only the template's
13
+ **agent-first introspection CLI** — `whoami`, `learn`, `explain`, `overview`,
14
+ `doctor`, and the `cli` noun group. These verbs describe the agent to other
15
+ agents; none of them supervise processes. When you add the lifecycle-supervisor
16
+ domain, it goes in *new* noun groups alongside the existing introspection verbs,
17
+ not by rewriting them.
18
+
19
+ The repo is still self-describing as a "clonable template" in several user-facing
20
+ strings (`learn`, `explain` catalog, `overview`). That phrasing is scaffold
21
+ residue — as the real domain lands, update those strings to describe the runtime.
22
+
23
+ ## Commands
24
+
25
+ This is a `uv` project, Python 3.12+, runtime `dependencies = []` (the CLI is
26
+ cited from `teken`/`agentfront`, not imported).
27
+
28
+ ```bash
29
+ uv sync # install (incl. dev group)
30
+ uv run pytest -n auto # full test suite (parallel)
31
+ uv run pytest tests/test_cli.py::test_whoami_text -v # a single test
32
+ uv run agent-lifecycle whoami # run the CLI (or: python -m agent_lifecycle)
33
+
34
+ # Lint gate (exactly what CI runs — see .github/workflows/tests.yml `lint` job):
35
+ uv run black --check agent_lifecycle tests
36
+ uv run isort --check-only agent_lifecycle tests
37
+ uv run flake8 agent_lifecycle tests
38
+ uv run bandit -c pyproject.toml -r agent_lifecycle
39
+ markdownlint-cli2 "**/*.md" "#node_modules" "#.local" "#.claude/skills" "#.teken"
40
+
41
+ # The agent-first rubric gate (CI blocks on this):
42
+ uv run teken cli doctor . --strict
43
+ ```
44
+
45
+ Note: the `teken` binary was renamed to `agentfront`; `teken` still works as a
46
+ deprecated alias, which is what CI and these docs invoke.
47
+
48
+ The `run-tests` skill (`.claude/skills/run-tests/`) wraps pytest with
49
+ `--ci` / `--quick` / `--coverage` presets if you prefer; plain `uv run pytest`
50
+ is fine.
51
+
52
+ ## Architecture
53
+
54
+ ### CLI dispatch (`agent_lifecycle/cli/`)
55
+
56
+ `cli/__init__.py:main()` is the single entry point. The flow:
57
+
58
+ 1. **Peek argv for `--json` before parsing** — parse-time errors happen before
59
+ `args.json` exists, so `main()` sets `_CliArgumentParser._json_hint` (a
60
+ class-level flag) so even argparse errors honor JSON mode.
61
+ 2. **`_build_parser()`** registers every verb. Each command module exposes a
62
+ `register(sub)` function; `_build_parser` calls them in turn. **To add a verb,
63
+ write the module, import it in `_build_parser`, and call its `register`.** The
64
+ subparsers are built with `parser_class=_CliArgumentParser` so the error
65
+ contract propagates to nested nouns too (see the `cli` noun, which re-passes
66
+ `type(p)` to its own sub-subparsers).
67
+ 3. **`_dispatch()`** invokes `args.func(args)`. Handlers return `None`/`int`
68
+ (success) or raise `CliError`. Any *other* exception is caught and wrapped
69
+ into a `CliError` so **no Python traceback ever leaks to stderr**.
70
+
71
+ ### Two cross-cutting contracts (don't break these — tests and the rubric enforce them)
72
+
73
+ - **Error contract** (`cli/_errors.py`): every failure is a `CliError(code,
74
+ message, remediation)`. Exit codes: `0` success, `1` user-input error, `2`
75
+ environment/setup error, `3+` reserved. Text-mode errors render as
76
+ `error: <msg>` + `hint: <remediation>` on stderr — the `hint:` prefix is
77
+ required by the agent-first rubric.
78
+ - **Stream split** (`cli/_output.py`): **results to stdout, diagnostics/errors to
79
+ stderr, never mixed.** Every verb supports `--json`; JSON payloads go to the
80
+ same split streams. Use `emit_result` / `emit_error` / `emit_diagnostic` — do
81
+ not `print()`.
82
+
83
+ ### The parallel registries that must stay in sync
84
+
85
+ A new verb touches **four** places, and the introspection verbs read each other.
86
+ Forgetting one is the most common bug here:
87
+
88
+ 1. The command module + its `register()` call in `_build_parser`.
89
+ 2. `explain/catalog.py` — add an `ENTRIES[("yourverb",)]` markdown entry.
90
+ `test_every_catalog_path_resolves` walks `known_paths()`, and
91
+ `overview_cli_noun_exists` rubric check expects coverage.
92
+ 3. `cli/_commands/overview.py` — the `_VERBS` / `_ARTIFACTS` lists feed both the
93
+ global `overview` and `cli overview`.
94
+ 4. `cli/_commands/learn.py` — both `_TEXT` and `_as_json_payload()` list the
95
+ command map; the rubric requires `learn` ≥200 chars and mentions of purpose,
96
+ exit codes, `--json`, and `explain`.
97
+
98
+ **Rubric invariant for nouns:** any noun with action-verbs must also expose
99
+ `overview`. The `cli` noun exists today purely to satisfy that
100
+ (`overview_cli_noun_exists`) — it has no action-verbs but still ships
101
+ `cli overview`. Mirror that pattern for any new noun group.
102
+
103
+ ### Identity (`whoami.py` is the source of truth)
104
+
105
+ `whoami.find_culture_yaml()` walks **up from `__file__`** (not CWD) to find the
106
+ agent's *own* `culture.yaml`, and `read_agent_fields()` parses `suffix`/`backend`/
107
+ `model` from the first agent block **with a hand-rolled parser (no YAML dep)** to
108
+ keep runtime deps empty. `doctor.py`, `overview.py`, and `learn.py` all build on
109
+ `whoami.report()`. A wheel install ships no `culture.yaml`, so both `whoami` and
110
+ `doctor` fall back gracefully (literal defaults / a single info check, exit 0).
111
+
112
+ `doctor` mirrors the invariants `steward doctor` checks: **prompt-file-present**
113
+ (declared `backend` → its prompt file: `claude`→`CLAUDE.md`, `acp`→`AGENTS.md`,
114
+ `gemini`→`GEMINI.md`), **backend-consistency**, plus **skills-present**.
115
+
116
+ ## Conventions
117
+
118
+ ### Every PR bumps the version (CI-enforced)
119
+
120
+ The `version-check` job fails any PR where `pyproject.toml`'s version equals
121
+ `main` — **including docs/config/CI-only changes.** Use the `version-bump` skill
122
+ (`major|minor|patch`); it updates `pyproject.toml` and prepends a Keep-a-Changelog
123
+ entry to `CHANGELOG.md`. `__version__` is read from installed package metadata
124
+ (`importlib.metadata`), so it's not edited by hand.
125
+
126
+ ### Skills are vendored cite-don't-import
127
+
128
+ `.claude/skills/` holds 11 skills copied (not depended-on) from **guildmaster**
129
+ (the skills supplier; `steward` keeps only the alignment role). `docs/skill-sources.md`
130
+ is the authoritative provenance ledger and re-sync procedure — **read it before
131
+ touching anything under `.claude/skills/`.** Script bodies are kept verbatim; only
132
+ consumer-identifying *prose* in `SKILL.md` is adapted, and every `SKILL.md` must
133
+ carry `type: command` (load-bearing — `core.skill_loader` silently skips files
134
+ without it). Tracked local divergences (e.g. `agex`→`devex`, `outsource`→
135
+ `ask-colleague`) are documented there.
136
+
137
+ PR work uses the `cicd` skill (layered on `devex pr`; adds SonarCloud gating via
138
+ `status`/`await`). Cross-repo issues + mesh messages use the `communicate` skill
139
+ (`agtag`-backed). Both `devex` and `agtag` are expected on PATH; `colleague` is
140
+ optional (only `ask-colleague` needs it).
141
+
142
+ ### Renaming the package (when forking this as a new agent)
143
+
144
+ The name `agent-lifecycle` / `agent_lifecycle` is hard-coded in ~30 tracked
145
+ files (CLI strings, `_ISSUES_URL`, tests, `sonar-project.properties`, `README`,
146
+ catalog markdown). List every occurrence first:
147
+
148
+ ```bash
149
+ git grep -lI 'agent-lifecycle\|agent_lifecycle'
150
+ ```
151
+
152
+ Then rename the package dir, update `culture.yaml` (`suffix` + `backend`), rewrite
153
+ this `CLAUDE.md`, and re-vendor only the skills you need.
154
+
155
+ ## CI / deploy
156
+
157
+ - **`tests.yml`**: `test` (pytest + coverage → SonarCloud, gated on `SONAR_TOKEN`
158
+ so fork PRs / token-less repos stay green), `lint` (black/isort/flake8/bandit/
159
+ markdownlint + the rubric gate), `version-check` (PR-only).
160
+ - **`publish.yml`**: TestPyPI on PRs from the same repo, PyPI on push to `main` —
161
+ both via Trusted Publishing (OIDC, no stored token). Triggered only by changes
162
+ under `pyproject.toml` / `agent_lifecycle/**`.
163
+ - **SonarCloud** (`sonar-project.properties`, key `agentculture_agent-lifecycle`):
164
+ `sonar.qualitygate.wait=true` blocks CI on a red gate. `relative_files = true`
165
+ in `[tool.coverage.run]` is required — without it coverage maps to absolute
166
+ paths and Sonar silently reports 0%.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-lifecycle
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Harness- and transport-agnostic agent runtime: supervises an agent's process lifecycle independent of its harness (brain) and transport (IRC/Slack/agtag).
5
5
  Project-URL: Homepage, https://github.com/agentculture/agent-lifecycle
6
6
  Project-URL: Issues, https://github.com/agentculture/agent-lifecycle/issues
@@ -0,0 +1,50 @@
1
+ # agent-lifecycle v0.3 — the two pluggable seam interfaces (Transport + Harness)
2
+
3
+ > agent-lifecycle v0.3 ships the two pluggable seam interfaces — Transport (message-first, presence optional) and Harness — plus a minimal in-process supervisor core and a reference echo transport+harness that prove the seam end-to-end, depending on nothing culture/agentirc/Slack-specific.
4
+
5
+ ## Audience
6
+
7
+ - The cultureagent and colleague maintainers (the two proving harnesses) plus the charter reviewers (guildmaster#61) who need concrete code — not prose — to ratify the Transport/Harness seam.
8
+
9
+ ## Before → After
10
+
11
+ - Before: The agent runtime is entangled inside cultureagent: the four backend daemons and the supervisor mechanics live together, and IRC is hardcoded as the transport (IRCTransport / agentirc VirtualClient lineage). No transport-free, harness-free core exists.
12
+ - After: The Transport and Harness contracts are importable from agent_lifecycle and demonstrated end-to-end: a reference harness wired to a reference transport through the supervisor round-trips a message in-process, with zero culture/agentirc/Slack imports.
13
+
14
+ ## Why it matters
15
+
16
+ - A transport-free, harness-free core lets cultureagent slim to a harness pack and lets colleague/Slack build on the same runtime without inheriting IRC or the Claude-family backends — the coupling that blocks both cases today.
17
+
18
+ ## Requirements
19
+
20
+ - agent_lifecycle's runtime dependency tree imports nothing culture-, agentirc-, or Slack-specific; the seam is defined as abstract interfaces (Protocol/ABC) so concrete transports/harnesses live in downstream packs/plugs.
21
+ - honesty: a downstream pack can implement Transport/Harness against only agent_lifecycle's public exports, with no import from a sibling pack.
22
+
23
+ ## Honesty conditions
24
+
25
+ - The reference harness+transport demo runs in CI with no network and no optional culture/agentirc/Slack packages installed.
26
+ - The exported spec is directly consumable by the cultureagent + colleague maintainers as the ratification target: it names both proving harnesses and links guildmaster#61.
27
+ - round-trip is observable: an inbound message handed to the Harness produces an outbound message delivered back through the Transport, asserted by a test — not just an interface that type-checks.
28
+ - The entanglement is citable in cultureagent today: the backend daemons and the supervisor mechanics live in the same package, and IRCTransport is the only transport.
29
+ - With the core extracted, a colleague-on-Slack deployment can be composed with no agentirc/IRC/culture package anywhere in its dependency tree.
30
+ - This increment is shippable and reviewable with NO cultureagent source present in this repo — it adds only new in-repo modules + tests.
31
+ - the import-guard test fails loudly if a future commit adds a culture/agentirc/Slack import to the core (e.g. it walks the import graph, not just a grep).
32
+ - the message-first core supports an async/no-presence transport without changing the Transport signature — verifiable by sketching the agtag shape against it.
33
+ - The Harness interface can express a process-backed streaming brain (start/feed-message/stream-reply/stop) without assuming any transport, and no Harness method takes presence as a parameter.
34
+
35
+ ## Success signals
36
+
37
+ - A pytest test composes the reference Harness + reference Transport through the supervisor and round-trips a message in-process; an import-guard test asserts agent_lifecycle has no culture/agentirc/Slack import in its dependency tree.
38
+
39
+ ## Scope / boundaries
40
+
41
+ - First increment only: NOT extracting cultureagent's four backends, NOT shipping the IRC/Slack/agtag transport plugs, and NOT refitting cultureagent to consume the package yet. Those follow once the seam is ratified.
42
+
43
+ ## Non-goals
44
+
45
+ - Presence-first transport design, and any real network transport (IRC/Slack/agtag) — the only concrete implementations in this increment are in-process reference doubles used to prove the seam.
46
+
47
+ ## Decisions
48
+
49
+ - Transport is message-first: a small message core (send, receive/subscribe, identity) with presence (join/part/who) as an OPTIONAL capability that async transports omit. Adopted from day one regardless of the colleague question, per the charter's stated safe bet.
50
+ - Resolved (was the charter open question): colleague's agents are live, process-backed, streaming harnesses like Claude Code and Codex — the same family as cultureagent's backends. So every proving harness is real-time/request-reply; async-durable-no-presence is purely a TRANSPORT capability (only agtag), never a Harness one. The Harness interface must therefore support a long-lived, streaming-capable brain; presence stays a transport-only optional mixin.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agent-lifecycle"
3
- version = "0.2.0"
3
+ version = "0.2.2"
4
4
  description = "Harness- and transport-agnostic agent runtime: supervises an agent's process lifecycle independent of its harness (brain) and transport (IRC/Slack/agtag)."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -2,6 +2,37 @@ version = 1
2
2
  revision = 3
3
3
  requires-python = ">=3.12"
4
4
 
5
+ [[package]]
6
+ name = "agent-lifecycle"
7
+ version = "0.2.2"
8
+ source = { editable = "." }
9
+
10
+ [package.dev-dependencies]
11
+ dev = [
12
+ { name = "bandit" },
13
+ { name = "black" },
14
+ { name = "flake8" },
15
+ { name = "isort" },
16
+ { name = "pytest" },
17
+ { name = "pytest-cov" },
18
+ { name = "pytest-xdist" },
19
+ { name = "teken" },
20
+ ]
21
+
22
+ [package.metadata]
23
+
24
+ [package.metadata.requires-dev]
25
+ dev = [
26
+ { name = "bandit", specifier = ">=1.7.5" },
27
+ { name = "black", specifier = ">=23.7.0" },
28
+ { name = "flake8", specifier = ">=6.1" },
29
+ { name = "isort", specifier = ">=5.12.0" },
30
+ { name = "pytest", specifier = ">=8.0" },
31
+ { name = "pytest-cov", specifier = ">=4.1" },
32
+ { name = "pytest-xdist", specifier = ">=3.0" },
33
+ { name = "teken", specifier = ">=0.8" },
34
+ ]
35
+
5
36
  [[package]]
6
37
  name = "bandit"
7
38
  version = "1.9.4"
@@ -154,37 +185,6 @@ wheels = [
154
185
  { url = "https://files.pythonhosted.org/packages/61/e8/cb8e80d6f9f55b99588625062822bf946cf03ed06315df4bd8397f5632a1/coverage-7.14.0-py3-none-any.whl", hash = "sha256:8de5b61163aee3d05c8a2beab6f47913df7981dad1baf82c414d99158c286ab1", size = 211764, upload-time = "2026-05-10T18:02:29.538Z" },
155
186
  ]
156
187
 
157
- [[package]]
158
- name = "agent-lifecycle"
159
- version = "0.2.0"
160
- source = { editable = "." }
161
-
162
- [package.dev-dependencies]
163
- dev = [
164
- { name = "bandit" },
165
- { name = "black" },
166
- { name = "flake8" },
167
- { name = "isort" },
168
- { name = "pytest" },
169
- { name = "pytest-cov" },
170
- { name = "pytest-xdist" },
171
- { name = "teken" },
172
- ]
173
-
174
- [package.metadata]
175
-
176
- [package.metadata.requires-dev]
177
- dev = [
178
- { name = "bandit", specifier = ">=1.7.5" },
179
- { name = "black", specifier = ">=23.7.0" },
180
- { name = "flake8", specifier = ">=6.1" },
181
- { name = "isort", specifier = ">=5.12.0" },
182
- { name = "pytest", specifier = ">=8.0" },
183
- { name = "pytest-cov", specifier = ">=4.1" },
184
- { name = "pytest-xdist", specifier = ">=3.0" },
185
- { name = "teken", specifier = ">=0.8" },
186
- ]
187
-
188
188
  [[package]]
189
189
  name = "execnet"
190
190
  version = "2.1.2"
@@ -1,28 +0,0 @@
1
- # CLAUDE.md — seed / bootstrap placeholder
2
-
3
- > **This is a self-initializing seed, not a finished runtime prompt.**
4
- > Run `/init` (or describe the agent's domain to your AI assistant) to
5
- > re-initialize this file into a full runtime prompt, using the description
6
- > below and the scaffolded repo as context.
7
-
8
- ## Agent
9
-
10
- This repository hosts the **agent-lifecycle** agent.
11
-
12
- ## Description
13
-
14
- Harness- and transport-agnostic agent runtime: supervises an agent's process lifecycle independent of its harness (brain) and transport (IRC/Slack/agtag).
15
-
16
- ## Re-init instruction
17
-
18
- This file is a seed. To expand it into your full runtime prompt:
19
-
20
- 1. Open this repo in Claude Code (or your preferred AI assistant).
21
- 2. Run `/init` — the assistant will read the repo, incorporate the description
22
- above, and replace this seed with a complete `CLAUDE.md`.
23
- 3. Commit the result.
24
-
25
- Until you run `/init`, `agent-lifecycle` satisfies the `steward doctor`
26
- `prompt-file-present` and `backend-consistency` invariants (a `CLAUDE.md`
27
- exists and `culture.yaml` declares `backend: claude`) but the prompt is not
28
- yet tailored to this agent's domain.
File without changes
File without changes