Files
Agent-System-Dev/Makefile
T
weichen 98d08347bd Integrate current task recovery and accepted planning contracts
Why:
Preserve work merged by concurrent tasks while adopting versioned dependency workspaces.

Evidence:
SELF task receipts record conflict detection, all 96 task/recovery/cutover cases, all 33 evidence cases and 5 component identity cases. Documents links and requirements were replayed after preserving both planning entries.

Impact:
Keep upstream idempotent sync, local resume and source-external receipt rules; adapt fixed-guidelines readiness and ignored component identity validation. Remove only obsolete index links and retain their physical Git metadata.

Refs:
Authoritative main57bcb17ea212a531186b6e21617a7f3bea65a791; Documents4a26798000c39cc59ba0c2cc6328f5c8f10dcb32; dependency-workspace R15.
2026-10-13 17:38:24 +00:00

344 lines
16 KiB
Makefile
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Agent-System-Dev 顶层编排
# 部署约束:非容器化;默认产物为单二进制(modules/backend,内嵌前端与嵌入式存储)。
SHELL := /bin/bash
SOURCE_MODE := $(if $(wildcard components.json),workspace,legacy)
ifeq ($(SOURCE_MODE),workspace)
CORE := .workspace/Agent-System-Core
BACKEND := .workspace/Agent-System-Backend
FRONTEND := .workspace/Agent-System-Frontend
UI := .workspace/Agent-System-UI
NATIVE := .workspace/Agent-Native
INTENT := .workspace/Agent-Intent
SQUAD := .workspace/Agent-Squad
COMMAND := .workspace/Agent-Command
DOCUMENTS := .workspace/Agent-System-Documents
else
CORE := modules/core
BACKEND := modules/backend
FRONTEND := modules/frontend
UI := modules/ui
NATIVE := deps/agent-native
INTENT := deps/agent-intent
SQUAD := deps/agent-squad
COMMAND := deps/agent-command
DOCUMENTS := modules/documents
endif
BIN := bin/agent-system
EMBED_DIR := $(BACKEND)/web/dist
PLUGINS := plugins
# 版本溯源(release-operations:运行制品须可对上固定组合)。无 tag 时 --always 给短 SHA。
COMBO := core=$(shell git -C $(CORE) rev-parse --short HEAD 2>/dev/null)+backend=$(shell git -C $(BACKEND) rev-parse --short HEAD 2>/dev/null)+frontend=$(shell git -C $(FRONTEND) rev-parse --short HEAD 2>/dev/null)+ui=$(shell git -C $(UI) rev-parse --short HEAD 2>/dev/null)+agentcmd=$(shell git -C $(COMMAND) rev-parse --short HEAD 2>/dev/null)+documents=$(shell git -C $(DOCUMENTS) rev-parse --short HEAD 2>/dev/null)+native=$(shell git -C $(NATIVE) rev-parse --short HEAD 2>/dev/null)+squad=$(shell git -C $(SQUAD) rev-parse --short HEAD 2>/dev/null)+intent=$(shell git -C $(INTENT) rev-parse --short HEAD 2>/dev/null)
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null)+$(COMBO)
.PHONY: help sync status workspace-prepare component-edit component-unlink workspace-status workspace-transition build frontend svc svc-list svc-info svc-commits svc-history svc-update svc-recover svc-watchdog test-backend test-backend-pg test-multi-instance test-lifecycle test-frontend test-ui test-core test-agentcmd test-pins test-libs dev pin clean setup precheck task-start task-resume task-sync task-close task-finish facts-verify evidence version
version:
@echo "agent-system $(VERSION)"
TASK := scripts/task.sh
export PRECHECK_RECEIPT RECEIPT IMPORT_RECEIPT TASK_WRITERS_STOPPED
TASK_WORK_MODE ?= delivery
export TASK_WORK_MODE
TASK_PARENT_BRANCH ?= $(PARENT)
TASK_PARENT_PR ?= $(PARENT_PR)
export TASK_PARENT_BRANCH TASK_PARENT_PR
setup:
git config core.hooksPath scripts/hooks
chmod +x scripts/hooks/pre-commit scripts/hooks/post-merge scripts/task.sh scripts/evidence.sh scripts/facts-verify.sh
@echo "OK: pre-commit/post-merge 钩子已启用(core.hooksPath=scripts/hooks)"
precheck:
@bash $(TASK) precheck
task-start:
@if [ -z "$(NAME)" ]; then echo "usage: make task-start NAME=feature/<slug>"; exit 2; fi
@bash $(TASK) start "$(NAME)"
task-resume:
@bash $(TASK) resume
task-sync:
@bash $(TASK) sync
task-close:
@bash $(TASK) close $(FOLD)
task-finish:
@bash $(TASK) finish $(ABANDON)
# 证据写入:执行命令并把结果行追加进当前任务卡(AGENTS.md「证据与验证门禁」)。
# 本地执行只记 SELF;RECEIPT 捕获启动收据,IMPORT_RECEIPT 导入原始收据而不重跑。
# 用法:CMD="<单行命令>" make evidence [TAIL=15];退出码随被执行命令。
# CMD 经环境直传(不经 make 变量展开重引号,命令内可含引号/管道);SRC/TAIL 为简单词,走 make 变量。
evidence:
@SRC='$(SRC)' TAIL='$(TAIL)' bash scripts/evidence.sh
# workspace.py owns source identity, locks and development overlays.
workspace-prepare:
@python3 scripts/workspace.py --root . prepare $(if $(NAME),--name "$(NAME)") $(if $(filter 1,$(REFRESH_FIXED)),--refresh-fixed)
component-edit:
@test -n "$(NAME)" || { echo "usage: make component-edit NAME=<component> [BRANCH=feature/<slug>]"; exit 2; }
@python3 scripts/workspace.py --root . edit --name "$(NAME)" $(if $(BRANCH),--branch "$(BRANCH)")
component-unlink:
@test -n "$(NAME)" || { echo "usage: make component-unlink NAME=<component>"; exit 2; }
@python3 scripts/workspace.py --root . unlink --name "$(NAME)"
workspace-status:
@python3 scripts/workspace.py --root . status $(if $(NAME),--name "$(NAME)")
# Default report is read-only. Only explicit ARGS=--apply copies into new roots.
workspace-transition:
@python3 scripts/workspace.py --root . transition $(if $(NAME),--name "$(NAME)") $(ARGS)
# 外部事实登记表逐条重验(--update 刷新 PASS 项 last_verified)。
facts-verify:
@bash scripts/facts-verify.sh $(ARGS)
help:
@echo "make sync 准备固定应用/资料/规则源码(旧提交保留 submodule 模式)"
@echo "make build 固定版本隔离构建 bin/agent-system(前端资产→embed→单二进制)"
@echo "make test 固定组合测试(治理 + boundaries/architecture + 组件与前端测试)"
@echo "make test-governance 临时真实仓库中的任务、证据、写守卫与 CI 凭据回归"
@echo "make svc 服务级操作:make svc ENV=<name> [ACTION=deploy|start|stop|restart|status|logs] [ARGS='--from dev@<sha> --tag ...']"
@echo "make svc-list 服务总览:make svc-list [ARGS='--tag core'];数据库运维:scripts/svc.sh db create|dsn|backup|backups|restore|clone|copy|ls|set"
@echo "make svc-info 综合信息报告(只读):make svc-info [ARGS='pg1 --reveal']——运行服务/数据库实例与内部库/配置快照"
@echo "make svc-commits 列出可部署提交:make svc-commits SRC=dev|release [N=20]"
@echo "make svc-history 事件历史:make svc-history [ENV] [N=20](完整文档:docs/svc.md)"
@echo "make svc-update 自动更新过时服务:make svc-update [NAMES='dev pg1'] [ARGS='--check --all']"
@echo "make svc-recover 自恢复:拉回 autostart=1 但已死的服务:make svc-recover [ARGS='dev --quiet']"
@echo "make svc-watchdog 自恢复看护:make svc-watchdog ARGS='install|remove|status'(systemd 用户 timer)"
@echo "make dev 开发模式说明(前后端分离热更新)"
@echo "make workspace-prepare 准备固定源码;component-edit NAME=<id> 按需编辑"
@echo "make workspace-transition [NAME=<id>] 默认只报告;ARGS=--apply 显式准备新现场"
ifeq ($(SOURCE_MODE),workspace)
sync: workspace-prepare
status: workspace-status
else
sync:
git submodule update --init --recursive
status:
@git submodule status
endif
# 契约同步:Core 的 TS 类型镜像到前端与 UI 组件库(Core 为权威,单一来源)。
ifeq ($(SOURCE_MODE),workspace)
# Contracts are versioned npm package exports; frontend builds materialize them.
contracts: frontend
frontend:
python3 scripts/build-composition.py --root . --target frontend
build:
python3 scripts/build-composition.py --root . --target build
else
contracts: test-worktree
cp $(CORE)/ts/types.ts $(FRONTEND)/src/contracts.ts.tmp
{ echo "// 从 Agent-System-Core ts/types.ts 同步(make contracts 生成;Core 为权威)。"; cat $(FRONTEND)/src/contracts.ts.tmp; } > $(FRONTEND)/src/contracts.ts
rm $(FRONTEND)/src/contracts.ts.tmp
cp $(CORE)/ts/types.ts $(UI)/src/contracts.ts.tmp
{ echo "// 从 Agent-System-Core ts/types.ts 同步(make contracts 生成;Core 为权威)。"; cat $(UI)/src/contracts.ts.tmp; } > $(UI)/src/contracts.ts
rm $(UI)/src/contracts.ts.tmp
frontend: contracts
cd $(UI) && npm ci --no-fund --no-audit
cd $(FRONTEND) && npm ci --no-fund --no-audit && npm run build
rm -rf $(EMBED_DIR) && mkdir -p $(EMBED_DIR) && cp -r $(FRONTEND)/dist/* $(EMBED_DIR)/ && touch $(EMBED_DIR)/.gitkeep
build: frontend
cd $(BACKEND) && CGO_ENABLED=0 go build -trimpath -ldflags "-s -w -X main.version=$(VERSION)" -o ../../$(BIN) ./cmd/agent-system
cd $(BACKEND) && CGO_ENABLED=0 go build -trimpath -ldflags "-s -w" -o ../../bin/storage-migrate ./cmd/storage-migrate
@echo "OK: $(BIN)(版本 $(VERSION);随附插件目录 $(PLUGINS)/)+ bin/storage-migrate(协作存储 U4 迁移工具)"
endif
ifeq ($(SOURCE_MODE),workspace)
# Named checks exercise developer sources, prepare selected versions, and keep
# GOWORK=off unless LOCAL_OVERLAY=1 explicitly selects registered component links.
.PHONY: dev-backend dev-frontend
LOCAL_CHECK := python3 scripts/component-check.py --root .
test-lifecycle:
@test -n "$${AGENT_PG_TEST_DSN}" || { echo "test-lifecycle: AGENT_PG_TEST_DSN 未设置(真实 PostgreSQL 必需,不静默跳过)"; exit 1; }
@test -n "$${SVC_RDM_SRC_DIR}" || { echo "test-lifecycle: SVC_RDM_SRC_DIR 未设置(RDM 检出必需,不静默跳过)"; exit 1; }
bash scripts/fetch-rdm-pin.sh tests/integration/lifecycle/rdm.pin >/dev/null
python3 tests/integration/lifecycle/lifecycle_suite.py
test-core test-backend test-backend-pg test-multi-instance test-frontend test-ui test-agentcmd eval-deliverables dev-backend dev-frontend:
$(LOCAL_CHECK) --target $@ $(if $(filter 1,$(LOCAL_OVERLAY)),--overlay)
else
test-core:
cd $(CORE) && go test ./...
test-backend:
cd $(BACKEND) && go test ./...
# 真实 PG/Redis 门禁(协作存储方案 U2):缺环境直接失败而非静默跳过。
# CI 的必跑 job 提供原生服务;本地用 scripts/svc.sh db create <名> --port 8897
# 与 redis-server --port 6399 起隔离实例(见 docs/guides/team-storage.md)。
test-backend-pg:
@test -n "$${AGENT_PG_TEST_DSN}" || { echo "test-backend-pg: AGENT_PG_TEST_DSN 未设置(真实 PostgreSQL 必需,不静默跳过)"; exit 1; }
@test -n "$${AGENT_REDIS_TEST_ADDR}" || { echo "test-backend-pg: AGENT_REDIS_TEST_ADDR 未设置(真实 Redis 必需,不静默跳过)"; exit 1; }
cd $(BACKEND) && go test -count=1 ./...
# 真实 Dev/RDM + PostgreSQL 生命周期门禁。缺环境直接失败,不静默跳过。
# 登录单独标 NOT_RUN(依赖账户方案 U7/U5),不把其余真实组合场景记成失败。
test-lifecycle:
@test -n "$${AGENT_PG_TEST_DSN}" || { echo "test-lifecycle: AGENT_PG_TEST_DSN 未设置(真实 PostgreSQL 必需,不静默跳过)"; exit 1; }
@test -n "$${SVC_RDM_SRC_DIR}" || { echo "test-lifecycle: SVC_RDM_SRC_DIR 未设置(RDM 检出必需,不静默跳过)"; exit 1; }
bash scripts/fetch-rdm-pin.sh tests/integration/lifecycle/rdm.pin >/dev/null
python3 tests/integration/lifecycle/lifecycle_suite.py
# 双进程 HTTP 级验收(协作存储方案 U7):两个真实 serve 进程共享隔离 PG。
# 缺环境时明确失败而非静默跳过;见 tests/integration/multi-instance/README.md。
test-multi-instance:
@test -n "$${AGENT_PG_TEST_DSN}" || { echo "test-multi-instance: AGENT_PG_TEST_DSN 未设置(真实 PostgreSQL 必需,不静默跳过)"; exit 1; }
mkdir -p tests/integration/multi-instance/.build
cd $(BACKEND) && CGO_ENABLED=0 go build -o ../../tests/integration/multi-instance/.build/agent-system ./cmd/agent-system
cd tests/integration/multi-instance && AGENT_BIN=./.build/agent-system go test -count=1 -timeout 15m .
eval-deliverables:
cd $(BACKEND) && go test ./eval/ ./internal/quality/ -count=1
test-frontend: contracts
cd $(FRONTEND) && npm ci --no-fund --no-audit && npx vitest run && node scripts/check-knip.mjs
test-ui: contracts
cd $(UI) && npm ci --no-fund --no-audit && npx tsc --noEmit && npx vitest run && node scripts/check-knip.mjs
test-agentcmd:
cd $(COMMAND) && go vet ./... && go test -count=1 ./...
endif
test-boundaries:
bash scripts/lint-boundaries.sh
# 容器仓 deps/ gitlink 与 Dev 顶层指针一致。读索引中的 gitlink。
ifeq ($(SOURCE_MODE),workspace)
test-pins:
@if [ -n "$${COMPOSITION_SOURCE_MAP:-}" ]; then bash scripts/check-pins.sh; else python3 scripts/workspace.py --root . verify; fi
else
test-pins:
bash scripts/check-pins.sh
endif
# 三个库在各自模块内测试。不用 go.work:工作区 MVS 会抬高 golang.org/x 版本。
ifeq ($(SOURCE_MODE),workspace)
test-libs:
$(LOCAL_CHECK) --target $@ $(if $(filter 1,$(LOCAL_OVERLAY)),--overlay)
else
test-libs:
cd $(INTENT) && GOWORK=off go vet ./... && GOWORK=off go test -count=1 ./...
cd $(NATIVE) && GOWORK=off go vet ./... && GOWORK=off go test -count=1 ./...
cd $(SQUAD) && GOWORK=off go vet ./... && GOWORK=off go test -count=1 ./...
cd $(SQUAD)/adapters/intent && GOWORK=off go vet ./... && GOWORK=off go test -count=1 ./...
cd $(SQUAD)/adapters/native && GOWORK=off go vet ./... && GOWORK=off go test -count=1 ./...
cd $(SQUAD)/adapters/sqlite && GOWORK=off go vet ./... && GOWORK=off go test -count=1 ./...
cd $(SQUAD)/cmd/agent-squad && GOWORK=off go vet ./... && GOWORK=off go test -count=1 ./...
endif
plugin-new:
@test -n "$(NAME)" || (echo "用法:make plugin-new NAME=<id>"; exit 2)
bash scripts/plugin-new.sh "$(NAME)"
.PHONY: test test-governance test-worktree contracts
test-governance:
PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s tests -p 'test_*.py' -v
test-worktree:
python3 scripts/check-worktree.py verify
# 即使 make -j,也先确认实际被测子仓与固定组合一致。
ifeq ($(SOURCE_MODE),workspace)
test-libs test-core test-backend test-frontend test-ui test-agentcmd: | test-worktree
ifeq ($(COMPOSITION_SOURCE_MAP),)
test-boundaries test-pins: | test-worktree
endif
else
test-boundaries test-pins test-libs test-core test-backend test-frontend test-ui test-agentcmd: | test-worktree
endif
ifeq ($(SOURCE_MODE),workspace)
# Formal composition uses isolated sources and GOWORK=off. Developer overlays
# remain untouched; the composition executor runs the component gates.
test:
python3 scripts/build-composition.py --root . --target test
else
test: test-worktree test-governance test-boundaries test-pins test-libs test-core test-backend test-frontend test-ui test-agentcmd
endif
# 运行演示(mock 模式):单二进制 + 示例插件 + 嵌入式存储,浏览器 http://127.0.0.1:8787
# 环境服务管理(scripts/svc.sh):deploy = 停旧 → 构建 → 启动;dev/prod 相互隔离。
svc:
@test -n "$(ENV)" || (echo "用法:make svc ENV=<name> [ACTION=deploy|stop|start|restart|status|logs] [ARGS='--port 9000 --tag ...']"; exit 2)
scripts/svc.sh $(ENV) $(ACTION) $(ARGS)
svc-list:
scripts/svc.sh list $(ARGS)
svc-info:
scripts/svc.sh info $(ARGS)
svc-commits:
@test -n "$(SRC)" || (echo "用法:make svc-commits SRC=dev|release [N=20]"; exit 2)
scripts/svc.sh commits $(SRC) $(N)
svc-history:
scripts/svc.sh history $(ENV) $(N)
svc-recover:
scripts/svc.sh recover $(ARGS)
svc-watchdog:
scripts/svc.sh watchdog $(ARGS)
svc-update:
scripts/svc.sh update $(NAMES) $(ARGS)
demo: build
$(BIN) serve --addr 127.0.0.1:8787 --data ./data --plugins $(PLUGINS) --mock
ifeq ($(SOURCE_MODE),workspace)
dev:
$(LOCAL_CHECK) --target dev $(if $(filter 1,$(LOCAL_OVERLAY)),--overlay)
else
dev:
@echo "开发模式(原生,非容器):"
@echo " 1. make sync && make contracts"
@echo " 2. 终端 A:cd $(BACKEND) && go run ./cmd/agent-system serve --addr 127.0.0.1:8787 --data ./data --plugins ../$(PLUGINS)"
@echo " 3. 终端 B:cd $(FRONTEND) && npm ci && npm run dev # Vite 代理到 8787"
@echo " 4. mock 演示:设置→运行时→演示模式;或终端 A 加 --mock"
endif
# 推进指针(多仓纪律:先验证后固定)。
ifeq ($(SOURCE_MODE),workspace)
pin:
@echo "pin: update consumer go.mod/package-lock.json or components.lock.json explicitly, then verify the fixed composition" >&2
@exit 2
else
pin:
@for m in modules/core modules/backend modules/frontend modules/ui modules/documents deps/agent-native deps/agent-squad deps/agent-intent deps/error-code-system deps/logging-system deps/development-guidelines deps/agent-command; do \
(git -C $$m fetch -q origin && git -C $$m checkout -q origin/main) || echo "skip $$m"; \
done
@echo "submodule 指针已推进;请 make test 后 git add .gitmodules modules deps && git commit"
@scripts/check-pins.sh || echo "pin: check-pins 未通过,上面列出的容器需要重钉;pin 本身不失败"
endif
ifeq ($(SOURCE_MODE),workspace)
clean:
rm -f $(BIN) bin/storage-migrate
else
clean:
rm -rf $(BIN) $(FRONTEND)/dist $(FRONTEND)/node_modules $(UI)/node_modules data
endif