Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
9239028
docs: define agentseek api runtime migration
kic635 Aug 10, 2026
bc596ad
docs: plan agentseek api runtime migration
kic635 Aug 10, 2026
72f32ae
fix: pass template env to dev child processes
kic635 Aug 10, 2026
c8fce3c
chore: remove internal migration notes
kic635 Aug 10, 2026
cb91039
fix: avoid dotenv dependency in lifecycle runtime
kic635 Aug 10, 2026
55d5bda
test: cover AgentSeek API lifecycle commands
kic635 Aug 10, 2026
0840315
fix: align lifecycle child environment semantics
kic635 Aug 11, 2026
8eee570
fix: harden lifecycle environment compatibility
kic635 Aug 12, 2026
85e7e38
refactor: add immutable lifecycle environment snapshot
webup Aug 16, 2026
75413b9
fix: reuse one environment snapshot for lifecycle dev
webup Aug 16, 2026
12f777f
test: prove lifecycle boundary against published api
webup Aug 16, 2026
51a638b
test: reap lifecycle contract timeout process
webup Aug 16, 2026
93ec3af
test: bound lifecycle timeout fallback
webup Aug 16, 2026
86f7fdc
test: gate lifecycle contract to posix
webup Aug 16, 2026
d213f58
docs: define lifecycle environment ownership contract
webup Aug 16, 2026
5707336
docs: clarify lifecycle environment boundaries
webup Aug 16, 2026
256f209
docs: qualify lifecycle snapshot summaries
webup Aug 16, 2026
4dad0be
fix: sort lifecycle public exports
webup Aug 16, 2026
1626c11
fix: reject invalid lifecycle dotenv environments
webup Aug 16, 2026
9ebeb02
fix: reap contract helper after graceful parent exit
webup Aug 16, 2026
183fc09
fix: make lifecycle test cleanup portable
webup Aug 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,28 @@ jobs:
- name: Run lint and type check
run: make lint typecheck

minimum-supported-cli:
name: Minimum supported CLI import
runs-on: ubuntu-latest
steps:
- name: Check out
uses: actions/checkout@v4

- name: Set up the environment
uses: ./.github/actions/setup-python-env
with:
python-version: "3.13"

- name: Run CLI with the declared dependency floor
run: |
set -euo pipefail
export UV_CACHE_DIR="$(mktemp -d)/uv-cache"
uv run --python 3.13 --isolated --no-project \
--with-editable . \
--with pydantic-settings==2.0.0 \
--with python-dotenv==1.0.0 \
agentseek --help

cross-platform-tests-and-type-check:
runs-on: ${{ matrix.os }}
strategy:
Expand Down Expand Up @@ -74,6 +96,31 @@ jobs:
- name: Check typing
run: make typecheck

agentseek-api-lifecycle-contract:
name: Published agentseek-api lifecycle contract
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out
uses: actions/checkout@v4

- name: Set up the environment
uses: ./.github/actions/setup-python-env
with:
python-version: "3.12"

- name: Verify the exact published API floor through agentseek dev
run: |
set -euo pipefail
api_version="$(uv run --frozen python -c 'from agentseek.cli.lifecycle.compatibility import MINIMUM_AGENTSEEK_API_VERSION; print(MINIMUM_AGENTSEEK_API_VERSION)')"
test "${api_version}" = "0.2.2"
export PYTHONPATH=
export UV_CACHE_DIR="${RUNNER_TEMP}/agentseek-api-contract-cache"
uv run --python 3.12 --isolated --no-project \
--with-editable . \
--with "agentseek-api==${api_version}" \
python scripts/check_agentseek_api_lifecycle_contract.py

legacy-template-compatibility:
if: ${{ github.event_name == 'push' || startsWith(github.head_ref, 'release/') }}
runs-on: ubuntu-latest
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ docs/hub.zh.md
/.superpowers/
/specs/plans/

# Local rendered templates and runtime artifacts
/my_*/
/.cookiecutter-replay/
/catalog-lock-sync-analysis.md

# mypy
.mypy_cache/
.dmypy.json
Expand Down
7 changes: 5 additions & 2 deletions docs/get-started/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,11 @@ agentseek task frontend
Set the model and provider credentials required by the selected template in
`.env` or the environment used to run AgentSeek.

`.env` is used by AgentSeek only for lifecycle environment checks declared by
the template. It is not automatically passed to child processes.
For non-dry-run `agentseek dev`, AgentSeek reads the project `env_file` once, overlays
non-empty launch variables once, and reuses that immutable snapshot for
readiness and every long-running process. Lifecycle defaults are checks only.
One-shot `agentseek task` commands keep their normal launch environment and do
not inherit `env_file`.

## Check and run

Expand Down
5 changes: 3 additions & 2 deletions docs/get-started/index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ agentseek task frontend

在 `.env` 或运行 AgentSeek 的环境里,设置所选模板需要的模型和 provider 凭证。

AgentSeek 只把 `.env` 用作模板声明的生命周期环境检查来源。
它不会把 `.env` 自动传给子进程。
对于非 dry-run 的 `agentseek dev`,AgentSeek 只读取一次项目 `env_file`,只覆盖一次非空启动变量,
并将同一个不可变快照(immutable snapshot)复用于就绪检查和每个长运行进程。生命周期
默认值仅用于检查。一次性的 `agentseek task` 命令保留其正常启动环境,不继承 `env_file`。

## 检查并运行

Expand Down
17 changes: 15 additions & 2 deletions docs/guides/create-template.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,12 @@ adapters. Add provider-specific keys only when the selected SDK requires them.
Document how runtime code maps aliases and which value wins.

Declare the same required names under `[env.*]` in the lifecycle file. AgentSeek
uses those declarations for readiness checks; it does not inject `.env` into
child processes.
uses those declarations for readiness checks. For non-dry-run `agentseek dev`,
it reads `env_file` once, overlays non-empty launch values once, and reuses one
immutable snapshot for readiness and all long-running child processes.
Lifecycle defaults remain checks only. A dotenv `KEY=` is present and empty,
while bare `KEY` assigns nothing. One-shot `agentseek task` commands keep their
normal launch environment and do not inherit `env_file`.

## 5. Define The Lifecycle

Expand Down Expand Up @@ -149,6 +153,15 @@ Use `sync` for Python or backend dependencies and `frontend` for a separate
frontend dependency tree. Put all long-running local processes under
`[processes.*]` so `agentseek dev` owns the documented development stack.

### Released API contract

Templates that run agentseek-api require `agentseek-api >= 0.2.2` and pin one
exact published version in the generated dependency file. Lifecycle process
commands use direct argv. Shell wrappers, duplicated dotenv loading, and
editable or local API checkouts do not satisfy the release contract. The exact
version pin and catalog digest are delivered in the later template/catalog
stage, not by AgentSeek core.

Servers bind to loopback by default. If remote development is supported, add
documented host overrides. A browser frontend must derive the backend host from
the browser location or accept an explicit public API URL.
Expand Down
16 changes: 14 additions & 2 deletions docs/guides/create-template.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ sources:

## 前置条件

- 本地已有独立 catalog checkout,并已完成 `uv sync`。
- 本地已有独立 catalog 检出副本,并已完成 `uv sync`。
- 已明确生成应用的目标,并找到一个运行时相近的现有模板。
- 已选择唯一的 `type/name` spec。除非同时扩展 CLI 的类型支持,否则复用 `bub`、`deepagents` 或 `langchain`。

Expand Down Expand Up @@ -88,7 +88,11 @@ AGENTSEEK_API_BASE=

应用在多个原生 provider adapter 之间切换时,增加 `AGENTSEEK_MODEL_PROVIDER`。只有所选 SDK 确实要求时,才增加 provider 专属密钥。文档必须说明运行时代码如何映射别名,以及冲突时谁优先。

在 lifecycle 文件的 `[env.*]` 中声明同一组必需名称。AgentSeek 用这些声明检查就绪状态,不会把 `.env` 注入子进程。
在 lifecycle 文件的 `[env.*]` 中声明同一组必需名称。AgentSeek 用这些声明检查
就绪状态。对于非 dry-run 的 `agentseek dev`,它只读取一次 `env_file`,只覆盖一次
非空启动值,并将同一个不可变快照(immutable snapshot)复用于就绪检查和所有长运行
子进程。生命周期默认值只用于检查;dotenv 中的 `KEY=` 表示存在但为空,裸 `KEY` 不产生
赋值。一次性的 `agentseek task` 命令保留正常启动环境,不继承 `env_file`。

## 5. 定义生命周期

Expand Down Expand Up @@ -136,6 +140,14 @@ command = ["uv", "sync"]

Python 或 backend 依赖统一使用 `sync`,独立 frontend 依赖树使用 `frontend`。所有长时间运行的本地进程都放在 `[processes.*]` 下,让 `agentseek dev` 管理文档中的完整开发环境。

### 已发布 API 契约

运行 agentseek-api 的模板需要 `agentseek-api >= 0.2.2`,并在生成的依赖文件中固定一个
已发布的精确版本(exact published version)。生命周期进程命令使用直接参数数组
(direct argv)。Shell 包装、重复 dotenv 加载,以及可编辑安装或本地 API 检出副本都不
满足发布契约。精确版本固定与模板目录摘要在后续模板目录阶段交付,不由 AgentSeek
core 提供。

Server 默认绑定 loopback。支持远程开发时,增加并说明 host override。浏览器 frontend 必须根据浏览器地址推导 backend host,或接受显式 public API URL。

## 6. 编写两层 README
Expand Down
50 changes: 40 additions & 10 deletions docs/reference/lifecycle-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ title: Lifecycle Spec
type: reference
audience: [A2]
runs: no
verified_on: 2026-07-28
verified_on: 2026-08-17
sources:
- src/agentseek/cli/lifecycle/spec.py
- src/agentseek/cli/lifecycle/environment.py
- src/agentseek/cli/lifecycle/dotenv_adapter.py
- src/agentseek/cli/lifecycle/compatibility.py
- src/agentseek/cli/lifecycle/core.py
- src/agentseek/cli/commands/dev.py
- src/agentseek/cli/commands/doctor.py
- src/agentseek/cli/commands/info.py
- src/agentseek/cli/lifecycle/authored.py
- src/agentseek/cli/lifecycle/normalize.py
- src/agentseek/cli/lifecycle/json_output.py
Expand Down Expand Up @@ -91,7 +97,7 @@ command = ["npm", "install", "--prefix", "frontend"]

| Section | Purpose |
| --- | --- |
| `env_file` | Optional project-local env file used only for declared environment checks. It is not injected into child processes. |
| `env_file` | Optional project-local dotenv file resolved once by non-dry-run `agentseek dev` for declared checks and long-running child processes. |
| `tools` | Required executables used by the project. |
| `paths` | Required local files or directories. |
| `env.<name>` | Environment variables AgentSeek should check. Defaults are lower priority than `env_file` and shell variables. |
Expand All @@ -105,24 +111,48 @@ than `0` and no greater than `300`; `attempts` is a positive integer.

## Environment Checks

AgentSeek checks environment requirements from lifecycle defaults, the optional
`env_file`, and the current process environment:
AgentSeek resolves one immutable snapshot per non-dry-run `agentseek dev`
invocation. It captures the launch environment once, then creates the snapshot
from the project `env_file` and non-empty captured launch environment values:

```text
lifecycle default < env_file < shell environment
lifecycle env_file < non-empty captured launch environment
```

Only keys declared under `[env.<name>]` and their aliases are read from
`env_file`. Templates do not need to declare every runtime variable a project
may use. AgentSeek does not pass the env file or lifecycle defaults to child
processes.
Bounded python-dotenv resolves physical bindings in order and falls back to the
captured launch environment. In a lifecycle dotenv, `KEY=` is a present empty
assignment, while bare `KEY` assigns nothing. An empty raw launch value is
omitted before the snapshot is created, so a dotenv value can fill it.

Readiness, the internal preflight, and every long-running child consume the
same snapshot. Lifecycle defaults may satisfy readiness but never enter the
snapshot. Only declared `[env.<name>]` keys and aliases participate in
readiness checks. AgentSeek guarantees only the initial child environment/snapshot,
which contains resolved values, not source paths, provenance, or instructions
to repeat resolution. Compatible child configuration completion may fill absent
keys but must not replace inherited present keys. Arbitrary child code can
mutate its own process environment; the prohibition against
duplicated override-loading is an authoring rule, not an AgentSeek enforcement
claim. `agentseek task` does not inherit lifecycle `env_file`; its behavior is
unchanged.

Lifecycle processes using the API completion contract require
`agentseek-api >= 0.2.2`. `agentseek dev --dry-run` prints the plan without
reading the lifecycle dotenv. The missing, undecodable, or malformed dotenv
guarantee applies only to non-dry-run `agentseek dev`: it creates no partial
snapshot, starts no child, and returns `exit 2` with a value-free diagnostic;
bare `KEY` remains valid syntax. Standalone `agentseek info` reports dotenv status without
creating a snapshot. Standalone `agentseek doctor --strict`
renders readiness failures, such as a missing dotenv, and returns `exit 1`.

## Lifecycle v1 first-phase scope

Version 1 supports required tools, required paths, project environment
requirements, HTTP live checks, long-running processes, and one-shot tasks.
It does not support optional tool/path checks, TCP checks, process env
overrides, multiple env files, or env interpolation.
overrides, or multiple env files. It adds no lifecycle-schema interpolation
mode: for a configured `env_file`, bounded python-dotenv resolves physical
bindings in order and falls back to the captured launch environment.

## Lifecycle v2 authored fields

Expand Down
42 changes: 34 additions & 8 deletions docs/reference/lifecycle-spec.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ title: 生命周期规范
type: reference
audience: [A2]
runs: no
verified_on: 2026-07-28
verified_on: 2026-08-17
sources:
- src/agentseek/cli/lifecycle/spec.py
- src/agentseek/cli/lifecycle/environment.py
- src/agentseek/cli/lifecycle/dotenv_adapter.py
- src/agentseek/cli/lifecycle/compatibility.py
- src/agentseek/cli/lifecycle/core.py
- src/agentseek/cli/commands/dev.py
- src/agentseek/cli/commands/doctor.py
- src/agentseek/cli/commands/info.py
- src/agentseek/cli/lifecycle/authored.py
- src/agentseek/cli/lifecycle/normalize.py
- src/agentseek/cli/lifecycle/json_output.py
Expand Down Expand Up @@ -91,7 +97,7 @@ command = ["npm", "install", "--prefix", "frontend"]

| 段落 | 作用 |
| --- | --- |
| `env_file` | 可选项目本地 env 文件,只用于声明的环境检查。它不会注入子进程。 |
| `env_file` | 可选的项目本地 dotenv 文件,仅由非 dry-run 的 `agentseek dev` 解析一次,用于声明的环境检查和长运行子进程。 |
| `tools` | 项目需要的可执行文件。 |
| `paths` | 必需的本地文件或目录。 |
| `env.<name>` | AgentSeek 应检查的环境变量。默认值优先级低于 `env_file` 和 shell 变量。 |
Expand All @@ -105,20 +111,40 @@ command = ["npm", "install", "--prefix", "frontend"]

## 环境检查

AgentSeek 从生命周期默认值、可选 `env_file` 和当前进程环境检查环境需求:
每次非 dry-run 的 `agentseek dev` 调用都会只创建一次不可变快照(immutable snapshot)。
它会先捕获启动环境,再用项目 `env_file` 与已捕获启动环境中的非空值创建该快照:

```text
lifecycle default < env_file < shell environment
lifecycle env_file < non-empty captured launch environment
```

只有 `[env.<name>]` 下声明的 key 及其 aliases 会从 `env_file` 读取。
模板不需要声明项目可能使用的每一个运行时变量。AgentSeek 不会把 env 文件或
生命周期默认值传给子进程。
受限的 python-dotenv 会按文件中物理绑定出现的顺序解析,
并在文件内没有值时回退到已捕获的启动环境。在生命周期 dotenv 中,`KEY=` 表示一个
存在但为空的赋值;裸 `KEY` 不产生赋值。原始启动值为空时,会在创建快照前省略,因此
dotenv 值可以补上它。

就绪检查、内部预检与每个长运行子进程都使用同一个快照。生命周期默认值可以满足
就绪检查,但绝不会进入快照。只有声明在 `[env.<name>]` 的 key 及其 aliases 会参与
就绪检查。AgentSeek 只保证初始子进程环境/快照:
其中只有已解析的值,不包含源路径、provenance 或要求再次解析的指令。兼容的子进程配置
补全可以填入缺失 key,但不得替换继承的已有 key。任意子进程代码
仍可自行修改其进程环境;禁止重复加载覆盖配置只是模板编写约束,不是 AgentSeek 的
强制保证。`agentseek task` 不继承生命周期 `env_file`,其行为保持不变。

使用 API completion contract 的生命周期进程需要
`agentseek-api >= 0.2.2`。`agentseek dev --dry-run` 只打印计划,不读取生命周期
dotenv。缺失、无法解码或 malformed dotenv 的严格保证只适用于非 dry-run 的
`agentseek dev`:它会在任何子进程启动前返回 `exit 2`,不创建部分快照,且诊断不得
包含值;裸 `KEY` 仍是有效语法。单独运行 `agentseek info` 仍会报告 dotenv 状态,
不会创建快照。单独严格运行 `agentseek doctor --strict` 会渲染
就绪失败(例如 dotenv 缺失),并返回 `exit 1`。

## 生命周期 v1 第一阶段范围

Version 1 支持必需工具、必需路径、项目环境需求、HTTP live 检查、长运行进程和一次性任务。
它不支持可选 tool/path 检查、TCP 检查、进程级环境覆盖、多个 env 文件或 env 插值。
它不支持可选 tool/path 检查、TCP 检查、进程级环境覆盖或多个 env 文件。生命周期 schema
不新增独立插值模式:配置的 `env_file` 使用受限的 python-dotenv,按文件中物理绑定出现的
顺序解析,并回退到已捕获的启动环境。

## 生命周期 v2 编写字段

Expand Down
21 changes: 17 additions & 4 deletions docs/reference/template-authoring-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,28 @@ core repository and exact dependency snapshot recorded by the catalog release;
normal template changes must not replace them with the catalog repository or a
mutable branch.

Environment resolution for lifecycle checks:
Readiness-only environment resolution:

```text
lifecycle default < env_file < shell environment
```

Lifecycle defaults and `.env` values validate readiness. AgentSeek does not
inject them into child processes. Process commands must load their runtime
environment themselves.
For non-dry-run `agentseek dev`, AgentSeek resolves `env_file` once, overlays non-empty
launch values once, and passes one immutable snapshot to readiness and every
long-running child. Lifecycle defaults validate readiness only and never enter
the child snapshot; `agentseek task` keeps its normal launch environment and
does not inherit lifecycle `env_file`. AgentSeek guarantees only the initial
child environment/snapshot; compatible child configuration completion may fill
absent keys but must not replace inherited present keys. Arbitrary child code can
mutate its own process environment.

Templates that run agentseek-api require `agentseek-api >= 0.2.2` and pin one
exact published version in the generated dependency file. Lifecycle process
commands use direct argv. Shell wrappers, duplicated dotenv or override
loading, and editable or local API checkouts do not satisfy the release
contract. The duplicated override-loading prohibition is an authoring rule,
not an AgentSeek enforcement claim. The exact version pin and catalog digest
are delivered in the later template/catalog stage, not by AgentSeek core.

## Task Names

Expand Down
Loading
Loading