From 57f92f919f5a38f83031e3810bd5573143b97789 Mon Sep 17 00:00:00 2001 From: agent-exec-transport Date: Sat, 17 Oct 2026 07:20:34 +0000 Subject: [PATCH] agent-exec transport 73a75d97d4a11ad672c195da4806208f/c172f14cd48b --- .gitea/workflows/governance.yml | 150 ++++++++++++++++++++++++++++++++ .gitmodules | 3 + .task/templates/task-card.md | 66 ++++++++++++++ AGENTS.md | 18 ++++ PROJECT.md | 2 + deps/development-guidelines | 2 +- deps/development-manager | 1 + policy/guidelines-adoption.md | 55 ++++++------ scripts/agent-exec | 4 + scripts/dm | 55 ++++++++++++ scripts/hooks/pre-commit | 16 ++++ scripts/task | 4 + 12 files changed, 348 insertions(+), 28 deletions(-) create mode 100644 .gitea/workflows/governance.yml create mode 100644 .task/templates/task-card.md create mode 160000 deps/development-manager create mode 100755 scripts/agent-exec create mode 100755 scripts/dm create mode 100755 scripts/hooks/pre-commit create mode 100755 scripts/task diff --git a/.gitea/workflows/governance.yml b/.gitea/workflows/governance.yml new file mode 100644 index 0000000..e96821b --- /dev/null +++ b/.gitea/workflows/governance.yml @@ -0,0 +1,150 @@ +name: governance +on: + pull_request: + push: + branches: [main] + +jobs: + governance: + runs-on: ubuntu-latest + env: + GOPROXY: https://goproxy.cn,direct + steps: + - name: Checkout + env: + TOKEN: ${{ secrets.GITHUB_TOKEN }} + SUBMODULE_TOKEN: ${{ secrets.SUBMODULE_TOKEN }} + run: | + set -euo pipefail + # 只物化两个治理 gitlink(Guidelines 与 deps/development-manager),非递归; + # 其它 gitlink 不物化、不取回。凭据只以 URL 限定的 extraheader 存在于本进程树内。 + python3 - <<'PY_CHECKOUT' + import os + from pathlib import Path + import re + import subprocess + import sys + from urllib.parse import urlsplit + + # 服务端基址取运行器注入的 GITHUB_SERVER_URL(平台控制、候选 PR 不可影响)。 + SERVER = os.environ.get("GITHUB_SERVER_URL", "").rstrip("/") + parsed_server = urlsplit(SERVER) + if parsed_server.scheme not in {"http", "https"} or not parsed_server.netloc: + sys.exit("Checkout server must be the platform-injected http(s) URL") + SSH = "ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/" + # 审查过的白名单,独立于候选 .gitmodules:仅列出两个治理 gitlink。 + REPOSITORIES = { + "deps/development-guidelines": "Development-Guidelines", + "deps/development-manager": "Development-Manager", + } + TARGET = "weichen/Agent-Intent" + root_token = os.environ.pop("TOKEN", "") + component_token = os.environ.pop("SUBMODULE_TOKEN", "") + if not root_token or not component_token: + sys.exit("Checkout requires TOKEN and SUBMODULE_TOKEN") + if os.environ.get("GITHUB_REPOSITORY") != TARGET: + sys.exit("Checkout repository is outside the reviewed allowlist") + sha = os.environ.get("GITHUB_SHA", "") + if not re.fullmatch(r"[0-9a-fA-F]{40}", sha): + sys.exit("Checkout requires a fixed commit SHA") + + # 丢弃继承的 Git 追踪/配置/SSH 钩子;凭据只存在于单个 Git 进程树的精确 URL 头中。 + clean_env = {k: v for k, v in os.environ.items() if not k.startswith("GIT_")} + clean_env.update(GIT_CONFIG_NOSYSTEM="1", GIT_CONFIG_SYSTEM="/dev/null", + GIT_CONFIG_GLOBAL="/dev/null", GIT_TERMINAL_PROMPT="0") + config = { + "core.hooksPath": "/dev/null", "core.fsmonitor": "false", + "init.templateDir": "", "credential.helper": "", + "fetch.recurseSubmodules": "false", "submodule.recurse": "false", + "http.followRedirects": "false", "protocol.allow": "never", + "protocol." + urlsplit(SERVER).scheme + ".allow": "always", + } + + + def git(repo, *args, extra=None): + values = config | (extra or {}) + env = clean_env | {"GIT_CONFIG_COUNT": str(len(values))} + for index, (key, value) in enumerate(values.items()): + env[f"GIT_CONFIG_KEY_{index}"] = key + env[f"GIT_CONFIG_VALUE_{index}"] = value + return subprocess.run(["git", "-C", str(repo), *args], env=env, + check=True, stdout=subprocess.PIPE).stdout + + + def materialize_governance(root): + # -r 列出任意深度的 gitlink,但不进入 submodule 内部;其它 gitlink 只记录、从不取回。 + links = {} + for entry in git(root, "ls-tree", "-rz", "HEAD").split(b"\0"): + if not entry: + continue + metadata, path = entry.split(b"\t", 1) + mode, kind, commit = metadata.decode().split() + if mode == "160000": + links[path.decode()] = commit + for name in REPOSITORIES: + if name not in links: + raise ValueError("Governance gitlink is missing from the fixed commit") + raw = git(root, "config", "--no-includes", "--blob", "HEAD:.gitmodules", "--null", "--list") + entries = {} + for item in raw.split(b"\0"): + if not item: + continue + key, value = item.decode().split("\n", 1) + match = re.fullmatch(r"submodule\.(.+)\.(path|url)", key) + if not match: + continue + name, field = match.groups() + if name not in REPOSITORIES: + continue + if field in entries.setdefault(name, {}): + raise ValueError("Duplicate candidate .gitmodules setting") + entries[name][field] = value + # 先整体校验两个治理条目,再进行任何带凭据的取回。 + for name, repository in REPOSITORIES.items(): + fields = entries.get(name, {}) + if fields.get("path") != name: + raise ValueError("Governance submodule path is outside the reviewed allowlist") + trusted_url = f"{SERVER}/weichen/{repository}.git" + if fields.get("url") not in {SSH + repository + ".git", trusted_url}: + raise ValueError("Governance submodule URL is outside the reviewed allowlist") + for name, repository in REPOSITORIES.items(): + url = f"{SERVER}/weichen/{repository}.git" + # 仅持久化审查过的公开 URL,使 Git 在进程级配置消失后仍识别该 submodule。 + git(root, "config", f"submodule.{name}.url", url) + git(root, "submodule", "update", "--init", "--checkout", "--", name, + extra={f"submodule.{name}.url": url, + f"submodule.{name}.update": "checkout", + f"http.{url}.extraheader": "AUTHORIZATION: token " + component_token}) + child = root / name + if git(child, "rev-parse", "HEAD").decode().strip() != links[name]: + raise ValueError("Materialized governance gitlink does not match the fixed SHA") + + + try: + root = Path.cwd() + # 必须是干净的临时工作区;不复用既有 Git 状态。 + if (root / ".git").exists(): + raise ValueError("Checkout requires a fresh workspace") + git(root, "init", "-q") + url = f"{SERVER}/{TARGET}.git" + git(root, "remote", "add", "origin", url) + git(root, "fetch", "--depth=1", "origin", sha, + extra={f"http.{url}.extraheader": "AUTHORIZATION: token " + root_token}) + git(root, "checkout", "-q", "--detach", "FETCH_HEAD") + materialize_governance(root) + except (ValueError, OSError, subprocess.CalledProcessError) as error: + sys.exit(f"Checkout refused: {error}") + print("Checkout complete; credentials were not persisted in Git configuration") + PY_CHECKOUT + unset TOKEN SUBMODULE_TOKEN + - name: Install Go 1.27.1 + run: | + set -euo pipefail + curl -fsSL -o "$RUNNER_TEMP/go.tgz" https://mirrors.aliyun.com/golang/go1.27.1.linux-amd64.tar.gz + tar -C /usr/local -xzf "$RUNNER_TEMP/go.tgz" + ln -sfn /usr/local/go/bin/go /usr/local/bin/go + ln -sfn /usr/local/go/bin/gofmt /usr/local/bin/gofmt + - name: Validate agent execution configuration + run: scripts/agent-exec validate --repo . + - name: Governance check + run: scripts/dm governance check --repo . diff --git a/.gitmodules b/.gitmodules index 032d44a..617fe9e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "deps/logging-system"] path = deps/logging-system url = ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Logging-System.git +[submodule "deps/development-manager"] + path = deps/development-manager + url = ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Development-Manager.git diff --git a/.task/templates/task-card.md b/.task/templates/task-card.md new file mode 100644 index 0000000..e3a0237 --- /dev/null +++ b/.task/templates/task-card.md @@ -0,0 +1,66 @@ +# <任务标题> 任务卡 + +任务主记录:。 +状态:<进行中 / 待审核 / 已合入 / 已放弃>;owner:<填写>。 + +## 基线与授权 + +- 权威仓:<仓 URL 或逻辑 ID>;root_target:main;immediate_target:
+- branch_kind:;initiative_id:<稳定 ID,普通任务为空> +- R0(initial_main_sha):<完整 SHA>;工作区:<路径>(worktree / clone);分支: +- 父任务信息(仅子任务填写):parent_branch=<父分支>;parent_head_sha=;parent_pr=<父 PR> +- accepting_requirements:(仅 initiative 可为 true;冻结后为 false) +- 需求分流:verdict=;selected_initiative=<分支或无>;候选=<分支@HEAD 列表或无>;理由=<不适配/适配依据>;triage 收据=<源码外路径与摘要> +- 授权与交付终点:<本次允许的动作与终点;未授权事项写明> +- 实施执行:agent-per-unit(配置:AGENT-EXECUTION.md;外部 Agent 一单元一新进程/会话/工作区) + +## 目标与非目标 + +<预期结果、受影响入口/模块/契约;明确不做什么。> + +## Agent 实施收据 + +按根目录 AGENT-EXECUTION.md 路由;外部 Agent 一单元一新进程/会话/隔离工作区。实施、修复与测试必须通过登记的候选执行;未配置或候选安全耗尽停在 unavailable/blocked,禁止 host 隐式代写。 + +| 单元 ID | 预期范围 | 角色 | 候选顺序 | attempt | CLI/模型 | 终态 | transport | fallback | 源码外收据路径 | +|---|---|---|---|---|---|---|---|---|---| +| 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | + +## 复用材料(task-start 自动检索结果摘录) + +- 相关近期提交: 命中;无则写无>。 +- 相关经验条目:<检索命中;无则写无>。 + +## 同步记录 + +| 节点 | sync_base_sha | tested_head_sha | checked_at | 结果 | +|---|---|---|---|---| +| 启动 | | | <日期时间> | <一致/已同步> | +| 验收前 | <填写> | <填写> | <填写> | <填写> | + +字段没有发生的写"无",不省略。本卡与 PR 描述同源:开 PR 时将"目标与非目标、结果与验证、影响与剩余项"复制进 PR 描述,不另写第二份。 + +## 交付调度(有多个就绪任务时) + +- 调度记录 / entry_id / 当前 attempt_id:<平台或调度服务链接及标识;未入队写无>。 +- 入队源 HEAD / owner / 依赖:<完整 SHA、身份、依赖或无>。 +- 固定候选引用:<调度尝试中的 base/head、组件与配置;未固定写无>。 +- 窗口、最终 CI、Review 与真实合入结果:<引用调度记录及原始证据,不复制全队列>。 + +定义见 [合入调度与 CI 分配](../standards/merge-queue.md)。本段在候选固定前整理;固定后先使用源码之外的记录保存运行结果,再按项目闭合流程回填。 + +## 结果与验证(完成后填写) + +- 结果:<交付了什么;未发生写无>。 +- 验证:<结论性摘要:PASS/FAIL/SKIP/NOT_RUN 逐项;逐条证据见下表,来源标注与写入规则见 [按影响选择验证与证据](../standards/verification.md)>。 +- 影响与剩余项:<影响面、遗留风险、后续任务>。 + +| 时间(UTC) | 命令 | 被测 HEAD | exit | 来源 | 摘要/位置 | +|---|---|---|---|---|---| +| <时间> | <命令;由项目 evidence 工具写入,无工具时附命令+对象 SHA+输出 digest 并标 SELF> | | | GATE/REPLAY/SELF | <摘要/位置> | + +## 回收(task-finish) + +- 合入核对:<分支已包含于目标分支的核对输出>。 +- 未跟踪/ignored 文件处置:<归档/可再生/存疑 逐项;无则写无>。 +- 回收动作:。 diff --git a/AGENTS.md b/AGENTS.md index c32f9bc..2684f21 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -34,3 +34,21 @@ - **SSH key**:`~/.ssh/home_gitea`(ED25519,公钥指纹 `SHA256:GYXaOXIMeloQ1fKSfdJ/ndgPQzs/Ix7Hk62ekfkfQ20`,Gitea 侧密钥名 GMKtec); `~/.ssh/config` 已有 `git-ssh.u1680832.nyat.app` 主机条目,克隆/推送直接可用。 + +## Agent 执行与新项目准入(强制) + +1. 缺 Guidelines 固定版本(`deps/development-guidelines` gitlink 未就绪或 HEAD 不符)时,Agent 只能只读分析,不得实施。 +2. 缺有效 `AGENT-EXECUTION.md`(`scripts/dm governance check` 未通过)时禁止 AI 实施。 +3. 缺共享执行器(`scripts/agent-exec` 或 `deps/development-manager` 不可用)时,状态为 `blocked/unavailable`,不得改由 host 替代。 +4. 不允许 host 代写实施单元;实施、修复与测试必须经 `AGENT-EXECUTION.md` 登记的候选执行。 +5. 人类直接开发按其自身授权与项目规则进行,不受本条款约束。 +6. 分支保护与规范 tag 由用户负责设置与维护,Agent 不得代为设置。 + +入口: + +- 需求分流:`scripts/task triage discover|decide|verify` +- 任务启动:`scripts/task start …` +- PR 检查:`scripts/task pr-check …` +- Agent 执行:`scripts/agent-exec run|apply|admit|validate` + +AI 实施单元仅通过 `scripts/agent-exec run` 运行(依据 AGENT-EXECUTION.md),并经 `scripts/agent-exec apply` 集成。 diff --git a/PROJECT.md b/PROJECT.md index 88f2120..620ad32 100644 --- a/PROJECT.md +++ b/PROJECT.md @@ -23,6 +23,7 @@ | development-guidelines | `deps/development-guidelines` | development-only,规范文本 | | error-code-system | `deps/error-code-system` | build-required,规范码目录(catalogcheck 对齐 + `intent.*` 常量值) | | logging-system | `deps/logging-system` | build-required,可选日志器 | +| development-manager | `deps/development-manager` | development-only,共享 Agent 执行器与治理脚手架(`scripts/dm`、`scripts/agent-exec` 的钉住来源) | 克隆: @@ -44,6 +45,7 @@ git clone --recurse-submodules ssh://git@git-ssh.u1680832.nyat.app:31411/weichen | 并发/快照隔离 | 仓库根:`GOWORK=off go test -count=1 -race ./...` | 覆盖 Reload 与识别并发 | | 依赖纪律 | 仓库根:`GOWORK=off go list -m all` 仅标准库 + 两个生态模块 | 不证明宿主接入正确性 | | 宿主行为验收 | 消费方仓内跑 `conformance.Run` | 本命令不覆盖真实宿主配置 | +| 治理与 Agent 执行配置 | 仓库根:`scripts/agent-exec validate --repo .` 与 `scripts/dm governance check --repo .` | 只校验 `AGENT-EXECUTION.md` 与治理 gitlink/文件,不证明执行器真实运行 | ## 环境与数据 diff --git a/deps/development-guidelines b/deps/development-guidelines index 26b562d..2688fd2 160000 --- a/deps/development-guidelines +++ b/deps/development-guidelines @@ -1 +1 @@ -Subproject commit 26b562d2e34fbc560711296a309c91c74ffc55b1 +Subproject commit 2688fd2be6a52c0bf110e7e6366b6f291ab5e4eb diff --git a/deps/development-manager b/deps/development-manager new file mode 160000 index 0000000..bd3a7de --- /dev/null +++ b/deps/development-manager @@ -0,0 +1 @@ +Subproject commit bd3a7de57a3a9e1a4495b94c5fa5c08d71e7be8c diff --git a/policy/guidelines-adoption.md b/policy/guidelines-adoption.md index eccdd9a..aa4cd43 100644 --- a/policy/guidelines-adoption.md +++ b/policy/guidelines-adoption.md @@ -1,44 +1,45 @@ # 通用规范采纳记录 -- 项目/负责人:Agent-Intent / 仓库所有者 weichen +- 项目/负责人:Agent-Intent / weichen - 状态:active - 规范位置:`deps/development-guidelines` -- 规范性文档目录:`policy/` -- 过程文档位置:`docs/records/`(项目内固定目录豁免。当前为个人维护的基础库,单独过程仓会让每份记录都变成跨仓 gitlink;任务主记录仍在 Gitea Issue/PR。豁免一经登记,过程记录不得再写入 `policy/` 或规范库。) -- 版本权威:父仓 gitlink;可读标签:无(内容版本 `0.1.0-draft.6`,提交 `26b562d2e34fbc560711296a309c91c74ffc55b1`) -- 批准/生效依据:本仓接入提交;草案审阅完成后随该提交生效 -- 替代范围和迁移说明:本仓为新建仓库,无既往规则需要迁移。 +- 规范性文档目录:`policy/`(项目规则与制度放此处) +- 过程文档位置:任务卡在 `.task/`(模板 `.task/templates/task-card.md`,本次任务卡 `.task/feature-governance-adoption.md`);任务主记录在 PR 描述与 Gitea Issue/PR。既有项目内豁免目录 `docs/records/` 保持不变(理由见 PROJECT.md「仓库与操作」节与下方「项目差异」)。 +- 版本权威:本仓 gitlink deps/development-guidelines @ 2688fd2be6a5(内容版本 `0.1.0-draft.12`;可读标签:无) +- 批准/生效依据:feature/governance-adoption PR(Agent-Intent) +- 替代范围和迁移说明:本次替代此前的 Guidelines gitlink `26b562d2e34f`(内容版本 `0.1.0-draft.6`),固定为 `2688fd2be6a5`。新增 `AGENT-EXECUTION.md` 执行路由、`deps/development-manager` 治理 gitlink(@ `bd3a7de57a3a`)、`scripts/dm`、`scripts/agent-exec`、`scripts/task`、`scripts/hooks/pre-commit`、`.gitea/workflows/governance.yml`。本仓无既往 Agent 执行路由需迁移。 | 规范/工作流 | 适用条件与范围 | 采纳或不适用理由 | 执行方式/证据 | |---|---|---|---| -| core/baseline.md | 日常工作 | 所有改动都要守硬边界 | manual | -| workflows/delivery.md、debugging.md、handoff.md | 交付、排障与交接 | 单人维护仍需要可交接的任务记录 | manual | -| standards/collaboration.md | 并行共同起点、节点同步与陈旧候选拒绝 | 本仓会被 Agent-Squad / Agent-Native 以 gitlink 消费 | manual | -| standards/verification.md | 验证与结论 | 仓库根 `go vet` / `go test`(含 `-race`) | manual;命令见 PROJECT.md | -| workflows/design-verification.md、standards/testability.md、standards/failure-containment.md | 识别漏斗、配置合并与快照切换 | 识别必须可脱离外部 I/O 独立验证;配置失败保留上一快照 | manual | -| standards/module-contracts.md | intent/conformance/catalogcheck/examples 边界 | 公开端口按层拆分;扩展点只留接口 | manual | -| standards/observability.md | 错误码、识别事件日志 | 与 Error-Code-System / Logging-System 对齐 | manual | -| standards/configuration.md | spec/overlay 双源合并、快照 revision、生效时机与诊断 | 本仓核心就是配置驱动模块;check/explain 由 `intentctl` 承担 | manual | -| standards/multi-repo.md | submodule 与固定组合 | 规范与基础库以 gitlink 锁定 | manual | -| standards/security.md | 凭证、配置信任边界 | 配置文件属宿主可信输入;本仓不含凭证 | manual | -| standards/documentation.md | 三层文档 | `policy/` 与 `docs/records/` 已分开 | manual | -| standards/data-reliability.md | 本仓自有数据库 | 无数据库;快照替换的原子性由并发测试覆盖 | 不适用 | -| standards/agent-execution.md | Agent 执行契约 | 本仓不做执行,只做 LLM 前的确定性识别 | 不适用 | -| standards/release-operations.md | 独立发布流水线 | 当前无制品仓库与部署入口 | 不适用 | -| workflows/automation.md | 定时与后台任务 | 本仓无 daemon | 不适用 | +| core/baseline.md | 日常工作 | 所有改动守硬边界;集成分支不直接提交,经 feature 分支与 PR 合入 | manual;`scripts/hooks/pre-commit` 本地拒绝直提 `main` 与非法分支名(需 `core.hooksPath` 启用,由人执行) | +| workflows/delivery.md、debugging.md、handoff.md | 交付、排障与交接 | 单人维护仍需要可交接的任务记录 | manual;任务卡 `.task/`,主记录在 PR | +| standards/collaboration.md | 并行共同起点、节点同步与陈旧候选拒绝 | 本仓被 Agent-Squad / Agent-Native 以 gitlink 消费,需固定共同基线 | manual;合入前在 `main` 上 `git fetch` 并确认 HEAD | +| standards/merge-queue.md | 多个就绪任务的最终同步、CI、Review 与合入调度 | 不适用:当前为单维护者,无多任务同时合入的调度需求;出现并行合入时复查 | 不适用 | +| standards/agent-execution.md | 工程 Agent CLI 执行路由、会话隔离与受控集成 | 凡 AI 协助实施均经执行路由:配置 `AGENT-EXECUTION.md`,执行器入口 `scripts/agent-exec`(validate / run / apply / admit / cleanup) | enforced:CI `scripts/agent-exec validate --repo .` 与 `scripts/dm governance check --repo .`;证据:governance check + 正负例(.task/feature-governance-adoption.md) | +| standards/verification.md | 验证与结论 | 仓库根 `go vet` / `go test`(含 `-race`)为正式验证 | 命令见 PROJECT.md「验证命令」;CI `.gitea/workflows/ci.yml` | +| workflows/design-verification.md、standards/testability.md、standards/failure-containment.md | 识别漏斗、配置合并与快照切换的设计/验证、模块测试与故障控制 | 识别必须可脱离外部 I/O 独立验证;配置失败保留上一快照 | manual;快照并发测试(`-race`) | +| standards/module-contracts.md | intent / conformance / catalogcheck / examples 的边界与公开契约 | 公开端口按层拆分;扩展点只留接口 | manual | +| standards/observability.md | 错误码、识别事件日志 | 与 Error-Code-System / Logging-System 对齐 | manual;`catalogcheck` 测试 | +| standards/configuration.md | spec/overlay 双源合并、快照 revision、生效时机与诊断 | 本仓核心即配置驱动模块;诊断由 `intentctl` 承担 | manual;`intentctl lint` / `explain` | +| standards/multi-repo.md | submodule 与固定组合 | 规范、执行器与基础库均以 gitlink 锁定;不执行 `submodule update --remote` | manual;`scripts/submodule-consistency.sh`;`scripts/dm governance check` | +| standards/security.md | 凭证、配置信任边界 | 配置文件属宿主可信输入;本仓不保存凭证 | manual | +| standards/documentation.md | 三层文档(入口、规范性文档、过程记录) | `policy/` 为规范性文档;过程记录按既有豁免放 `docs/records/` | manual;见下方「项目差异」 | +| standards/tool-adaptation.md | 新工具/执行器适配 | 不适用:本次不新增工具适配卡;执行器 profile 由 AGENT-EXECUTION.md 登记 | 不适用 | +| standards/data-reliability.md | 本仓自有数据库 | 不适用:无数据库;快照替换的原子性由并发测试覆盖 | 不适用 | +| standards/release-operations.md | 独立发布流水线 | 不适用:当前无制品仓库与部署入口;可构建性以 `main` 的 `go test` 为准 | 不适用 | +| workflows/automation.md | 定时与后台任务 | 不适用:本仓无 daemon | 不适用 | ## 项目差异 | 原规则/章节 | 项目采用方式 | 原因与风险 | 负责人/复查条件 | |---|---|---|---| -| documentation.md 过程仓默认独立仓库 | 过程记录放 `docs/records/` | 个人基础库;风险是记录与代码同 PR 时容易把证据写成第二权威。任务状态仍只认 Gitea Issue/PR | 出现第二名维护者或对外发布流程时复查 | +| documentation.md 过程仓默认独立仓库 | 过程记录放 `docs/records/`;任务卡放 `.task/` | 个人基础库;风险是记录与代码同 PR 时容易把证据写成第二权威。任务状态仍只认 Gitea Issue/PR | 出现第二名维护者或对外发布流程时复查 | 默认做法差异说明理由;硬边界冲突须有明确有效决策,不能用此表自授权。建议不采用无需登记。 ## 本次升级或首次接入验证 -- 入口:根 `AGENTS.md`、`PROJECT.md` 指向 `deps/development-guidelines`。 -- 子模块:`deps/development-guidelines` 固定 `26b562d2e34fbc560711296a309c91c74ffc55b1`;`deps/error-code-system` 固定 `28fa06eaa56a19906732681cc02474a87ac9d408`(含 `intent` 种子域);`deps/logging-system` 固定 `2c5716fdcffbc4696fc0371afc70f39c44174201`。三者与 Agent-Squad / Agent-Native 当前组合一致(error-code-system 为新增 intent 域后的新提交,属追加式变更)。 -- `.gitmodules` 使用批准的上游 SSH URL,不含本机路径或凭证。 -- 执行方式保持 manual:挂载 Markdown 不自动改变 CI。 -- 回退:恢复本提交之前的 gitlink,并删除根入口与 `policy/guidelines-adoption.md` 中对应条款;无已生效的 CI 或权限变更需要另恢复。 +- 入口:根 `AGENTS.md` 与 `PROJECT.md` 指向 `deps/development-guidelines`;`AGENTS.md` 新增「Agent 执行与新项目准入(强制)」段落,`AGENT-EXECUTION.md` 为执行路由唯一权威。 +- 子模块:`deps/development-guidelines` 固定 `2688fd2be6a52c0bf110e7e6366b6f291ab5e4eb`;`deps/development-manager` 固定 `bd3a7de57a3a9e1a4495b94c5fa5c08d71e7be8c`;`deps/error-code-system` 与 `deps/logging-system` 不变。 +- 门禁:`.gitea/workflows/governance.yml` 在 PR 与 `main` 推送时运行 `scripts/agent-exec validate --repo .` 与 `scripts/dm governance check --repo .`;实际正负例与 Review/CI 证据记录在 `.task/feature-governance-adoption.md`。 +- 回退:恢复 `deps/development-guidelines` gitlink 为 `26b562d2e34f`,删除 `AGENTS.md` 新增段落、`deps/development-manager` 条目、`scripts/dm`、`scripts/agent-exec`、`scripts/task`、`scripts/hooks/pre-commit`、`.gitea/workflows/governance.yml` 与 `.task/templates/task-card.md`,并将本文件状态改回 proposed。分支保护与规范 tag 由用户设置,回退时同步撤销。 diff --git a/scripts/agent-exec b/scripts/agent-exec new file mode 100755 index 0000000..7dc09b3 --- /dev/null +++ b/scripts/agent-exec @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# 共享 Agent 执行器薄入口:转调 scripts/dm 的 agent-exec 子命令(validate / run / apply / admit / cleanup)。 +set -euo pipefail +exec "$(dirname "$0")/dm" agent-exec "$@" diff --git a/scripts/dm b/scripts/dm new file mode 100755 index 0000000..a7cdae3 --- /dev/null +++ b/scripts/dm @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# 共享 dm-server 薄入口:读取 deps/development-manager 的 gitlink 钉住提交, +# 按该提交构建并缓存 dm-server,再 exec 其子命令(agent-exec、task、governance)。执行语义与退出码以该二进制为准。 +set -euo pipefail + +root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P) +dm="$root/deps/development-manager" + +die() { echo "dm: $*" >&2; exit 2; } + +# git 钩子会导出仓库本地变量(GIT_DIR、GIT_INDEX_FILE 等),它们会让 `git -C "$dm"` 解析到外层仓库。 +# 所有针对 DM 检出的 git 与 go 调用都在清除这些变量后执行;读取外层 gitlink 与最终 exec 仍保留继承环境。 +dm_local_env="GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE GIT_PREFIX GIT_OBJECT_DIRECTORY GIT_ALTERNATE_OBJECT_DIRECTORIES GIT_COMMON_DIR GIT_GRAFT_FILE GIT_NAMESPACE GIT_CONFIG GIT_CONFIG_PARAMETERS GIT_CONFIG_COUNT GIT_SHALLOW_FILE GIT_IMPLICIT_WORK_TREE $(git rev-parse --local-env-vars 2>/dev/null || true)" +dm_clean_env() { for v in $dm_local_env; do unset "$v"; done; } +dmgit() ( dm_clean_env; git -C "$dm" "$@" ) + +# 1. 钉住版本只来自索引中的 gitlink(mode 160000),不读取工作区文件。 +entry=$(git -C "$root" ls-files -s -- deps/development-manager 2>/dev/null || true) +[ -n "$entry" ] || die "索引中缺少 deps/development-manager 的 gitlink,无法确定钉住的 DM 版本" +read -r mode pin _stage _path <<<"$entry" +[ "$mode" = 160000 ] || die "deps/development-manager 不是 gitlink(mode=$mode)" +[[ "$pin" =~ ^[0-9a-f]{40}$ ]] || die "gitlink 提交格式无效:$pin" + +# 2. 检出必须存在且确为 DM 独立仓库(避免 git -C 误解析到外层仓库),HEAD 必须等于钉住提交。 +[ -e "$dm/.git" ] || die "deps/development-manager 未检出;请按钉住提交 $pin 检出该 gitlink" +top=$(dmgit rev-parse --show-toplevel 2>/dev/null || true) +[ -n "$top" ] && [ "$top" = "$(cd "$dm" && pwd -P)" ] \ + || die "deps/development-manager 不是独立检出;请按钉住提交 $pin 检出该 gitlink" +head=$(dmgit rev-parse HEAD 2>/dev/null || true) +[ "$head" = "$pin" ] \ + || die "deps/development-manager HEAD(${head:-未知})与钉住提交 $pin 不一致;请按钉住提交检出" + +# 3. 检出工作树必须干净(忽略嵌套 submodule 状态)。 +dirty=$(dmgit status --porcelain --ignore-submodules=all) \ + || die "无法读取 deps/development-manager 的工作树状态" +[ -z "$dirty" ] || die "deps/development-manager 存在未提交改动,拒绝运行(请先清理该检出)" + +# 4. 二进制按钉住提交缓存;缺失时在缓存目录内临时构建,完成后原子改名,避免留下半成品。 +cache="${DM_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/development-manager/dm-server}" +bin="$cache/dm-server-$pin" +if [ ! -x "$bin" ]; then + command -v go >/dev/null 2>&1 || die "缺少 go,无法构建 dm-server($pin)" + mkdir -p "$cache" + cache=$(cd "$cache" && pwd -P) + bin="$cache/dm-server-$pin" + work=$(mktemp -d "$cache/build-$pin.XXXXXX") + if ! (dm_clean_env; cd "$dm" && GOWORK=off go build -trimpath -o "$work/dm-server" ./cmd/dm-server); then + rm -rf "$work" + die "构建 dm-server 失败($pin)" + fi + mv -f "$work/dm-server" "$bin" + rm -rf "$work" +fi + +exec "$bin" "$@" diff --git a/scripts/hooks/pre-commit b/scripts/hooks/pre-commit new file mode 100755 index 0000000..47404f4 --- /dev/null +++ b/scripts/hooks/pre-commit @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# 本地检查(pre-commit):集成分支直提拒绝 + 分支命名 + 本地完整性核对。权威准入在 PR(baseline.md:26)。 +branch=$(git rev-parse --abbrev-ref HEAD) +case "$branch" in + main|master) + echo "pre-commit: 拒绝——集成分支 ${branch} 不得直接提交,走 feature 分支 + PR(collaboration.md)" >&2 + exit 1 ;; +esac +echo "$branch" | grep -qE '^(feature|fix|hotfix|release)/[A-Za-z0-9._-]+$' || { + echo "pre-commit: 拒绝——分支名须为 feature|fix|hotfix|release/,当前:${branch}" >&2 + exit 1 +} +root=$(git rev-parse --show-toplevel) +# admit 只是本地完整性/篡改证据(SELF):同一 OS 用户可读取本地 HMAC 密钥并绕过本钩子, +# 它不是 GATE,也不是可信身份。缺失或无效的本地记录仍拒绝;交付信任来自精确 HEAD 的 CI 或独立 REPLAY。 +"$root/scripts/agent-exec" admit --repo "$root" diff --git a/scripts/task b/scripts/task new file mode 100755 index 0000000..fe7d2ca --- /dev/null +++ b/scripts/task @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# 通用任务入口:转调 scripts/dm 的 task 子命令(triage / start / pr-check)。 +set -euo pipefail +exec "$(dirname "$0")/dm" task "$@"