agent-exec transport 1549f6ab3ddd401443620c52e6ebda24/6f19424ccb58
This commit is contained in:
@@ -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-System-Releases"
|
||||||
|
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 .
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
[submodule "deps/development-guidelines"]
|
||||||
|
path = deps/development-guidelines
|
||||||
|
url = ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Development-Guidelines.git
|
||||||
|
[submodule "deps/development-manager"]
|
||||||
|
path = deps/development-manager
|
||||||
|
url = ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Development-Manager.git
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# <任务标题> 任务卡
|
||||||
|
|
||||||
|
任务主记录:<Issue/PR 链接,或注明"本文件随 PR 描述维护">。
|
||||||
|
状态:<进行中 / 待审核 / 已合入 / 已放弃>;owner:<填写>。
|
||||||
|
|
||||||
|
## 基线与授权
|
||||||
|
|
||||||
|
- 权威仓:<仓 URL 或逻辑 ID>;root_target:main;immediate_target:<main 或 feature/initiative>
|
||||||
|
- branch_kind:<initiative | child | standalone>;initiative_id:<稳定 ID,普通任务为空>
|
||||||
|
- R0(initial_main_sha):<完整 SHA>;工作区:<路径>(worktree / clone);分支:<feature|fix|hotfix/...>
|
||||||
|
- 父任务信息(仅子任务填写):parent_branch=<父分支>;parent_head_sha=<SHA>;parent_pr=<父 PR>
|
||||||
|
- accepting_requirements:<true | false>(仅 initiative 可为 true;冻结后为 false)
|
||||||
|
- 需求分流:verdict=<JOIN | NEW>;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 自动检索结果摘录)
|
||||||
|
|
||||||
|
- 相关近期提交:<git log -- <paths> 命中;无则写无>。
|
||||||
|
- 相关经验条目:<检索命中;无则写无>。
|
||||||
|
|
||||||
|
## 同步记录
|
||||||
|
|
||||||
|
| 节点 | sync_base_sha | tested_head_sha | checked_at | 结果 |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| 启动 | <R0> | <HEAD> | <日期时间> | <一致/已同步> |
|
||||||
|
| 验收前 | <填写> | <填写> | <填写> | <填写> |
|
||||||
|
|
||||||
|
字段没有发生的写"无",不省略。本卡与 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> | <HEAD> | <exit> | GATE/REPLAY/SELF | <摘要/位置> |
|
||||||
|
|
||||||
|
## 回收(task-finish)
|
||||||
|
|
||||||
|
- 合入核对:<分支已包含于目标分支的核对输出>。
|
||||||
|
- 未跟踪/ignored 文件处置:<归档/可再生/存疑 逐项;无则写无>。
|
||||||
|
- 回收动作:<worktree remove、分支删除、prune;放弃路径注明原因>。
|
||||||
@@ -24,3 +24,21 @@
|
|||||||
- **SSH key**:`~/.ssh/home_gitea`(ED25519,公钥指纹
|
- **SSH key**:`~/.ssh/home_gitea`(ED25519,公钥指纹
|
||||||
`SHA256:GYXaOXIMeloQ1fKSfdJ/ndgPQzs/Ix7Hk62ekfkfQ20`,Gitea 侧密钥名 GMKtec);
|
`SHA256:GYXaOXIMeloQ1fKSfdJ/ndgPQzs/Ix7Hk62ekfkfQ20`,Gitea 侧密钥名 GMKtec);
|
||||||
`~/.ssh/config` 已有 `git-ssh.u1680832.nyat.app` 主机条目,克隆/推送直接可用。
|
`~/.ssh/config` 已有 `git-ssh.u1680832.nyat.app` 主机条目,克隆/推送直接可用。
|
||||||
|
|
||||||
|
## Agent 执行与新项目准入(强制)
|
||||||
|
|
||||||
|
AI 实施单元只通过 `scripts/agent-exec run` 运行(见 [AGENT-EXECUTION.md](AGENT-EXECUTION.md)),并由 `scripts/agent-exec apply` 集成。
|
||||||
|
|
||||||
|
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`
|
||||||
|
|||||||
@@ -4,3 +4,10 @@
|
|||||||
- 技术栈:Go(静态链接,CGO_ENABLED=0)
|
- 技术栈:Go(静态链接,CGO_ENABLED=0)
|
||||||
- 构建/验证:见仓内 Makefile 或 Dev 仓顶层 Makefile(待 P1 起补充并保持本节同步)。
|
- 构建/验证:见仓内 Makefile 或 Dev 仓顶层 Makefile(待 P1 起补充并保持本节同步)。
|
||||||
- 状态:P0 骨架;当前阶段见 Dev 仓任务记录。
|
- 状态:P0 骨架;当前阶段见 Dev 仓任务记录。
|
||||||
|
|
||||||
|
## 验证
|
||||||
|
|
||||||
|
- 治理采纳核验:`scripts/dm governance check --repo .`
|
||||||
|
- Agent 执行配置校验:`scripts/agent-exec validate --repo .`
|
||||||
|
- 脚本语法:`bash -n scripts/dm scripts/agent-exec scripts/task scripts/hooks/pre-commit`
|
||||||
|
- 业务构建与测试命令:见上文「构建/验证」,待 P1 补充。
|
||||||
|
|||||||
+1
Submodule deps/development-guidelines added at 2688fd2be6
+1
Submodule deps/development-manager added at bd3a7de57a
@@ -0,0 +1,33 @@
|
|||||||
|
# 通用规范采纳记录
|
||||||
|
|
||||||
|
- 项目/负责人:Agent-System-Releases / weichen
|
||||||
|
- 状态:active
|
||||||
|
- 规范位置:`deps/development-guidelines`
|
||||||
|
- 规范性文档目录:`policy/`(项目规则与制度放此处;现有说明见 `policy/README.md`)
|
||||||
|
- 过程文档位置:`.task/`(任务卡,如 `.task/feature-governance-adoption.md`);任务主记录在采纳 PR 描述中
|
||||||
|
- 版本权威:本仓 gitlink deps/development-guidelines @ 2688fd2be6a5;可读标签:无
|
||||||
|
- 批准/生效依据:feature/governance-adoption PR(Agent-System-Releases)
|
||||||
|
- 替代范围和迁移说明:无。首次采纳,不替代既有采纳记录。`AGENTS.md` 既有段落中的 Dev 仓路径 `development/guidelines` 按"保留既有内容"原则未改动;本仓规范实际检出位置以 `deps/development-guidelines` 为准。
|
||||||
|
|
||||||
|
| 规范/工作流 | 适用条件与范围 | 采纳或不适用理由 | 执行方式/证据 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| core/baseline.md | 日常工作 | 采纳:本仓所有编辑与交付遵循核心规则的强度与授权定义 | manual |
|
||||||
|
| workflows/delivery.md、debugging.md、handoff.md | 交付、排障与交接 | 采纳:本仓以 feature/* 分支加 PR 交付,任务状态写入 `.task/` 任务卡,不依赖本地会话 | manual;证据为任务卡与 PR 记录 |
|
||||||
|
| standards/collaboration.md | 并行共同起点、两级分支、节点同步与陈旧候选拒绝 | 采纳:本仓使用功能分支与 PR 合入 main,默认一个实际工作区一个写者 | manual;有真实平台负例再登记 enforced |
|
||||||
|
| standards/merge-queue.md | 多个就绪任务的最终同步、CI、Review 与合入调度 | 不适用:本仓单维护者、单任务串行合入,当前无多任务同时向 main 交付的调度;出现并行合入时再采纳并补充调度记录 | 不适用 |
|
||||||
|
| standards/agent-execution.md | 工程 Agent CLI 执行路由、会话隔离与受控集成 | 凡允许 AI 协助必须采纳;配置见 AGENT-EXECUTION.md | 执行方式:AGENT-EXECUTION.md + scripts/agent-exec(validate / admit);证据:governance check + 正负例(.task/feature-governance-adoption.md) |
|
||||||
|
| standards/verification.md | 验证与结论 | 采纳:验证入口与证据要求按 PROJECT.md「验证」节执行 | manual;命令:`scripts/agent-exec validate --repo .`、`scripts/dm governance check --repo .`;CI:`.gitea/workflows/governance.yml` |
|
||||||
|
| workflows/design-verification.md、standards/testability.md、standards/failure-containment.md | 功能增量的设计/验证、模块测试与故障控制 | 不适用:本仓只做打包与分发,不含服务或业务模块源码(见 README);功能增量的设计与验证在 Agent-System-Dev 侧执行;部署失败回退由 `deploy/install.sh rollback` 承担 | 不适用 |
|
||||||
|
|
||||||
|
## 项目差异
|
||||||
|
|
||||||
|
无。本仓采用通用规范的默认做法,无需登记差异。
|
||||||
|
|
||||||
|
## 本次升级或首次接入验证
|
||||||
|
|
||||||
|
- 入口:`AGENTS.md`「Agent 执行与新项目准入(强制)」、`AGENT-EXECUTION.md`、`scripts/dm governance check --repo .`、`scripts/agent-exec validate --repo .`、`.gitea/workflows/governance.yml`。
|
||||||
|
- 版本获取:`dm-server governance init` 固定 Guidelines `2688fd2be6a5` 与 Development-Manager `bd3a7de57a3a`;两个 gitlink 记录于 `.gitmodules`,路径为 `deps/development-guidelines`、`deps/development-manager`。
|
||||||
|
- 占位符:本记录与 `AGENTS.md` 新增段落不含 `<…>` 占位文本。
|
||||||
|
- 冲突检查:既有 `AGENTS.md`、`PROJECT.md`、`AGENT-EXECUTION.md` 保留原内容;仓内无其他采纳记录(如 `policy/adoption.md`),无需引用。
|
||||||
|
- 正负例、Review 与 CI 结果:记录于 `.task/feature-governance-adoption.md`,合入前补全。
|
||||||
|
- 回退:需同时撤销两个 gitlink 与 `.gitmodules`,删除 `scripts/dm`、`scripts/agent-exec`、`scripts/task`、`scripts/hooks/pre-commit` 与 `.gitea/workflows/governance.yml`,并将本记录状态改为 deprecated;`AGENTS.md`、`PROJECT.md`、`AGENT-EXECUTION.md` 既有内容保留。
|
||||||
Executable
+4
@@ -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 "$@"
|
||||||
Executable
+55
@@ -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" "$@"
|
||||||
Executable
+16
@@ -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/<slug>,当前:${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"
|
||||||
Executable
+4
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# 通用任务入口:转调 scripts/dm 的 task 子命令(triage / start / pr-check)。
|
||||||
|
set -euo pipefail
|
||||||
|
exec "$(dirname "$0")/dm" task "$@"
|
||||||
Reference in New Issue
Block a user