@tea-agent/loop-agent 0.24.3 → 0.24.4-beta.0

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.
package/CHANGELOG.md CHANGED
@@ -2,15 +2,10 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
- ## [0.24.3] - 2026-07-28
6
-
7
- ### 重点更新
8
-
9
- - 发布工作流改为发布已通过完整门禁并经 SHA-256 校验的 npm tarball,避免 `npm publish` 再次触发全量测试、类型检查与构建。
10
-
11
5
  ### 改进
12
6
 
13
7
  - 发布工作流改为发布已通过完整门禁并经 SHA-256 校验的 npm tarball,避免 `npm publish` 再次触发全量测试、类型检查与构建。
8
+ - 默认 `standard` 实现任务在 React、Next.js 或 Vue 项目中直接选择 `frontend-implementation` DAG,不再依赖需求关键词;明确后端、文档/测试范围或前端否定仍保留对应通用流程。
14
9
 
15
10
  ## [0.24.2] - 2026-07-28
16
11
 
@@ -239,10 +239,8 @@ export async function generateTaskDagUseCase(input) {
239
239
  reasons: ["dag run-task validate did not report governanceProfile"],
240
240
  });
241
241
  const hasExplicitSpecializedTaskKind = candidateResult.templateSelection.source === "taskKind";
242
- const hasSafeAutomaticTaskSourceRoute = candidateResult.templateSelection.source === "task-source" &&
243
- profileRouting.selectedByProfile !== "supervised" &&
244
- profileRouting.selectedTemplate !== "supervised-implementation";
245
- if (hasExplicitSpecializedTaskKind || hasSafeAutomaticTaskSourceRoute) {
242
+ const hasAutomaticTaskSourceRoute = candidateResult.templateSelection.source === "task-source";
243
+ if (hasExplicitSpecializedTaskKind || hasAutomaticTaskSourceRoute) {
246
244
  profileRouting.selectedTemplate = candidateResult.template;
247
245
  profileRouting.source = hasExplicitSpecializedTaskKind
248
246
  ? "taskKind"
@@ -256,10 +254,9 @@ export async function generateTaskDagUseCase(input) {
256
254
  profileRouting.selectedByProfile = parsed.profile;
257
255
  }
258
256
  }
259
- // Persist only a safe automatic route. Explicit supervised/profile policy
260
- // must remain authoritative and must not be weakened by this convenience
261
- // marker. Keep taskId stable; frontend-implementation is the taskKind.
262
- if (hasSafeAutomaticTaskSourceRoute && candidateResult.template === "frontend-implementation") {
257
+ // Persist the automatic business workflow route while preserving the
258
+ // governance profile as a separate routing dimension.
259
+ if (hasAutomaticTaskSourceRoute && candidateResult.template === "frontend-implementation") {
263
260
  const taskConfig = await loadTaskConfig(repoRoot, parsed.taskId);
264
261
  if (!taskConfig.taskKind || taskConfig.taskKind === "standard") {
265
262
  await writeTaskConfig(repoRoot, parsed.taskId, {
@@ -2049,11 +2049,11 @@ function buildTargetFeatureWorkflow(input) {
2049
2049
  "",
2050
2050
  "## Specialized Task Kinds",
2051
2051
  "",
2052
- "- standard tasks are classified conservatively by combining the task title, `source/需求.md`, structured `allowedPaths`, strong React/Next/Vue project evidence, and user-visible interaction/state semantics.",
2053
- "- An implicit frontend demand selects the frontend DAG only when project or frontend-path evidence is paired with product-delivery semantics; framework evidence alone is insufficient. Backend, mixed, negated, documentation/test maintenance, and unknown demands keep the template selected by the normal governance profile.",
2052
+ "- standard tasks first use the structured task type in `source/需求.md`, then combine `allowedPaths` with strong React/Next/Vue project evidence for deterministic routing.",
2053
+ "- A frontend project defaults eligible implementation work to the frontend DAG without requirement keyword matching. Explicit backend, mixed, frontend-negated, and documentation/test-only scopes keep the template selected by the normal governance profile.",
2054
2054
  "- `frontend-mock-assess-pi` reads Mock/API/schema evidence and selects `native|browser-intercept|request-adapter|not-needed|blocked` before frontend planning; its deterministic gate rejects blocked or malformed output, while the existing frontend implementer remains the only writer.",
2055
2055
  "- Mock-backed verification never proves real API integration. When the backend was not exercised, closeout must retain the gap and name `<task-id>-real-api-integration-verify`; that follow-up is explicitly created/run after backend readiness, never automatic.",
2056
- "- Automatic frontend classification never replaces a supervised template selected by an explicit profile, workflowPolicy, or the supervised quality gate.",
2056
+ "- Automatic frontend classification selects the frontend implementation workflow and persists taskKind; explicit profiles, workflowPolicy, and supervised quality gates record governance strength without switching the business workflow back to a generic DAG.",
2057
2057
  "- A backend implementation does not select the backend test DAG. `backend-test` remains an explicit test-engineering workflow.",
2058
2058
  "- Explicit specialized `taskKind` values remain compatible and take precedence over task-source classification.",
2059
2059
  "",
@@ -298,6 +298,11 @@ export function classifyTaskDemand(input) {
298
298
  message: "allowedPaths include a backend-specific source path",
299
299
  });
300
300
  }
301
+ const allowedPathsOnlyCoverNonProductArtifacts = input.allowedPaths.length > 0 &&
302
+ input.allowedPaths.every((rawPath) => {
303
+ const allowedPath = normalizedAllowedPath(rawPath);
304
+ return matchesAny(allowedPath, NON_PRODUCT_ALLOWED_PATH_PATTERNS);
305
+ });
301
306
  const pathSupportedFrontendDelivery = frontendPath &&
302
307
  (titleSignals.pathSupportedFrontendDelivery ||
303
308
  requirementSignals.pathSupportedFrontendDelivery ||
@@ -328,20 +333,27 @@ export function classifyTaskDemand(input) {
328
333
  message: "task text contains user-visible interaction/state delivery and the project has strong frontend framework evidence",
329
334
  });
330
335
  }
336
+ const backendDelivery = titleSignals.backendDelivery || requirementSignals.backendDelivery;
337
+ const frontendProjectDefaultImplementation = hasStrongFrontendProjectEvidence &&
338
+ !backendDelivery &&
339
+ !frontendNegated &&
340
+ !allowedPathsOnlyCoverNonProductArtifacts;
341
+ if (frontendProjectDefaultImplementation) {
342
+ addSignal(signals, {
343
+ id: "frontend-project-default-implementation",
344
+ source: "project",
345
+ message: "frontend project evidence selects the frontend implementation workflow by default",
346
+ });
347
+ }
331
348
  const frontendDelivery = titleSignals.frontendDelivery ||
332
349
  requirementSignals.frontendDelivery ||
333
350
  pathSupportedFrontendDelivery ||
334
- projectSupportedFrontendDelivery;
335
- const allowedPathsOnlyCoverNonProductArtifacts = input.allowedPaths.length > 0 &&
336
- input.allowedPaths.every((rawPath) => {
337
- const allowedPath = normalizedAllowedPath(rawPath);
338
- return matchesAny(allowedPath, NON_PRODUCT_ALLOWED_PATH_PATTERNS);
339
- });
351
+ projectSupportedFrontendDelivery ||
352
+ frontendProjectDefaultImplementation;
340
353
  if (allowedPathsOnlyCoverNonProductArtifacts && frontendDelivery) {
341
354
  blockers.push("non-product-allowed-paths");
342
355
  }
343
356
  const eligibleFrontendDelivery = frontendDelivery && !allowedPathsOnlyCoverNonProductArtifacts;
344
- const backendDelivery = titleSignals.backendDelivery || requirementSignals.backendDelivery;
345
357
  const taskTypeConflict = (hasFrontendTaskType && (backendDelivery || frontendNegated)) ||
346
358
  (hasBackendTaskType && eligibleFrontendDelivery);
347
359
  if (taskTypeConflict)
@@ -402,13 +414,6 @@ export function resolveTaskDagTemplateSelection(input) {
402
414
  reasons: [],
403
415
  };
404
416
  }
405
- if (requestedTemplate !== "standard-dag") {
406
- return {
407
- template: requestedTemplate,
408
- source: "requested-template",
409
- reasons: [],
410
- };
411
- }
412
417
  const classification = classifyTaskDemand(input);
413
418
  if (classification.kind === "frontend") {
414
419
  const frontendSignals = classification.signals
@@ -423,6 +428,14 @@ export function resolveTaskDagTemplateSelection(input) {
423
428
  classification,
424
429
  };
425
430
  }
431
+ if (requestedTemplate !== "standard-dag") {
432
+ return {
433
+ template: requestedTemplate,
434
+ source: "requested-template",
435
+ reasons: [],
436
+ classification,
437
+ };
438
+ }
426
439
  return {
427
440
  template: requestedTemplate,
428
441
  source: "requested-template",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tea-agent/loop-agent",
3
- "version": "0.24.3",
3
+ "version": "0.24.4-beta.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "loop-agent": "bin/loop-agent.js",
@@ -336,8 +336,8 @@ loop-agent dag resume --run-id <run-id> # approve 后继续
336
336
  - 从 run facts dry-run envelope 解析用 `dag decision inspect|validate`;`validate` 在无效 envelope 时 exit 1;永不自动 resume/retry。
337
337
  - Decision Gate prompt 可用 `buildDagDecisionGateEvidence()`(`src/workflows/dag/decision-evidence.ts`)做与 `dag report --json`、`ai_workspace/loop-agent/templates/agent-dag-report.schema.json` 对齐的只读摘要;不 mutate run state,不执行 retry/resume。
338
338
  - 仅当有意在 `.harness/dag-runs/active/` 下要 active run snapshot 时用 `run-dag --dry-run`。
339
- - task source 应从 `harness.json.workflowPolicy.dag.profileRouting` 与确定性 candidate `governanceProfile` 选择通用候选模板时用 `dag run-task --profile auto`。无 `--profile` 仅用于旧 standard-compatible 输出;`--profile minimal|standard|reviewed|supervised` 选择治理路由,其中 supervised 模板不会被自动前端分类替换。
340
- - 默认 `standard` 任务会根据标题、`source/需求.md` 和结构化 `allowedPaths` 做保守、确定性的需求分类。只有高置信的前端实现需求自动选择 `frontend-implementation`;后端、前后端混合、明确排除前端或无法可靠判断的需求保留 governance profile 选出的模板,绝不自动进入 `backend-test`。显式 profile、`workflowPolicy` 或 supervised quality gate 已选中 supervised 时,自动分类不得降低治理等级。
339
+ - task source 应从 `harness.json.workflowPolicy.dag.profileRouting` 与确定性 candidate `governanceProfile` 选择治理强度时用 `dag run-task --profile auto`。无 `--profile` 仅用于旧 standard-compatible 输出;`--profile minimal|standard|reviewed|supervised` 记录治理强度,不替换已识别的专用业务 workflow。
340
+ - 默认 `standard` 任务先读取 `source/需求.md` 中的结构化任务类型,再结合 `allowedPaths` React/Next/Vue 项目能力做确定性分类。确认是前端项目且任务不是明确后端、混合、排除前端或仅文档/测试范围时,自动选择 `frontend-implementation`,不依赖需求关键词;普通后端实现绝不自动进入 `backend-test`。
341
341
  - 新生成 DAG 会冻结任务源路径、SHA-256 和显式 `REQ/BR/AC` 到 `sourceBinding`。前端计划漏号时 `frontend-requirement-coverage-shell` 在 writer 前阻断。中断恢复应修复 task source 后重新运行 `dag run-task`,不要生成只携带上游摘要的 impl-only DAG;strict governance 会拒绝无来源绑定且无只读 planner 上游的 v3 孤立 writer。
342
342
  - 显式专用 `taskKind` 保持兼容并优先于任务源分类,也不扩充 governance profile:`frontend-implementation` 可有意覆盖为带 Mock 规范评估、contract gate、design gate 和验证链的前端模板;可选 `frontendMock` 配置 auto/required/disabled、既有服务目录和专项验证命令,required 合同不完整时不会生成 writer。`backend-test` 显式选择需求分析 → 功能用例 → 评审 → pytest 生成/执行 → 复盘的后端测试工程模板。
343
343
 
@@ -14,7 +14,7 @@
14
14
 
15
15
  此 policy 驱动 `dag run-task --profile auto`:CLI 仍要求显式 `dag run-task`、`dag validate`、`run-dag`,但 `--profile auto` 在确定性 candidate `governanceProfile` 推断后应用 `workflowPolicy.dag.profileRouting`。生成器还会把 `outputLanguage` 写入 DagSpec,runner 在每个 Pi/Cursor 节点 prompt 中注入语言规则;代码、命令、路径、JSON 字段与 gate token 保持原样。`humanGatePolicy` 是默认人机边界声明;真实暂停仍由 DAG 节点的 `decisionGate.mode: "pause-on-human"` 与 decision envelope 触发。无 profile 的 `dag run-task <task-id>` 仍为 standard-compatible,供 legacy/review workflow。
16
16
 
17
- 对于默认 `standard` 任务,生成器组合标题、`source/需求.md`、结构化 `allowedPaths`、React/Next/Vue 强工程证据与用户可见交互/状态语义,做保守、确定性的需求分类。即使需求没有显式写出“前端/UI/页面”,工程证据与产品交付语义共同成立时也会自动选择 `frontend-implementation` DAG;框架证据单独不足以触发。后端、前后端混合、明确排除前端、文档/测试维护或证据不足的需求继续使用 governance profile 选出的模板。分类不会把普通后端实现路由到 `backend-test`,也不会替换由显式 profile、`workflowPolicy` 或 supervised quality gate 选中的 supervised 模板。
17
+ 对于默认 `standard` 任务,生成器先读取 `source/需求.md` 中的结构化任务类型,再结合 `allowedPaths` 与 React/Next/Vue 强工程证据做确定性分类。确认是前端项目且任务不是明确后端、前后端混合、排除前端或仅文档/测试范围时,默认选择 `frontend-implementation` DAG,不依赖需求关键词。分类不会把普通后端实现路由到 `backend-test`;显式 profile、`workflowPolicy` 或 supervised quality gate 只记录治理强度,不把已识别的前端业务 workflow 换回通用模板。
18
18
 
19
19
  前端专用链保留独立 contract/scout;plan 同时选择 Mock/API 策略并输出结构化 implementation contract。design initial pass 直接使用原计划,只有 request-revision 才运行 revision/final review;small-risk 只执行一次 design review。`frontend-prewrite-gate-shell` 合并生效 verdict、REQ/BR/AC 覆盖、Mock policy 和 contract 物化,是唯一写入授权。实现后 `frontend-verify-assess-shell` 合并 Mock/static/behavior/trace/assessment;只有 `eligible=true` 才运行同 writeSet 的 repair 和 `frontend-reverify-shell`。`frontend-review-context-shell` 绑定真实 diff 与有效验证证据后再 review/closeout。standard/high-risk 为 15 个顶层节点,small-risk 为 13;绿色路径执行 11 个节点、7 次 Pi。生成期 blocked Mock 只生成一个确定性阻塞节点且没有 writer。
20
20
 
@@ -67,7 +67,7 @@ loop-agent run-dag --dag <temp-dir>/hybrid-dag.json --init-only --canvas-path <t
67
67
  **运维 warning**:
68
68
 
69
69
  - **常规 validation**:`dag validate --dag <path>` 做 schema/topology/ranks。JSON 输出含 `governanceProfile`(确定性 `minimal|standard|reviewed|supervised` 推断,含 `process` / `delivery` / `codeChange` signal 与 `reasons`),及 model-matrix drift、governance lint(如 read-only artifact-boundary drift 或 DAG 内 `check-repo.sh` shell env drift)的 warnings。手写临时 DAG spec 执行前用 `dag validate --dag <path> --strict-models`;governance warning 应 fail fast 时加 `--strict-governance`。含 `executor: "cursor"` 的旧 DAG 会在 schema 校验失败;默认生成 DAG 使用 `pi` read-only / Pi write profile / shell。仅当有意在 `.harness/dag-runs/active/` 要 active run snapshot 时用 `run-dag --dry-run`。
70
- - **Governance profile 推断与 routing(code vs skill 分工)**:`./src/workflows/dag/governance-profile.ts` 从 DAG 结构与 write scope 做 **硬确定性推断**。JSON 输出 **报告** `process` / `delivery` / `codeChange` signal 与人类可读 `reasons`;`profile` tier(`minimal|standard|reviewed|supervised`)仅由该模块 code rule 选择(如多个 exclusive writer、repair node、review-gate topology、`loop-agent-runtime-paths`、`scripts-ci-harness-paths`、weak post-implementation shell verification、supervised topology)。baseline `forbiddenPaths`(`.harness/**`、`.harness/dag-runs/**`、`artifacts/**`)是默认 governance,**本身不是** process-risk signal。skill prompt 与本 reference **解释** tier 并摘要 profile 选择原因;不替代 code 推断。`dag run-task` 转发 embedded validate step 的同一 candidate `governanceProfile`。`dag run-task --profile auto` 先将 candidate profile 经 `harness.json.workflowPolicy.dag.profileRouting` 映射,再在 candidate delivery signal 含 `loop-agent-runtime-paths`、`scripts-ci-harness-paths` 或 `public-contract-paths` 时应用 M4 `supervised-quality-gate` promotion;`profileRouting.routingReasons` 记录确定性 reason。无 profile `dag run-task <task-id>` 仍为 standard-compatible;显式 `--profile minimal|standard|reviewed|supervised` 选择治理路由的通用候选模板,默认 `standard` 前端任务可在非 supervised 候选上选择前端专用模板,但自动分类不得替换 supervised 候选。高风险 task 应用 `--profile auto` 或显式 `--profile supervised`,而非显式 `--profile reviewed`。
70
+ - **Governance profile 推断与 routing(code vs skill 分工)**:`./src/workflows/dag/governance-profile.ts` 从 DAG 结构与 write scope 做 **硬确定性推断**。JSON 输出 **报告** `process` / `delivery` / `codeChange` signal 与人类可读 `reasons`;`profile` tier(`minimal|standard|reviewed|supervised`)仅由该模块 code rule 选择(如多个 exclusive writer、repair node、review-gate topology、`loop-agent-runtime-paths`、`scripts-ci-harness-paths`、weak post-implementation shell verification、supervised topology)。baseline `forbiddenPaths`(`.harness/**`、`.harness/dag-runs/**`、`artifacts/**`)是默认 governance,**本身不是** process-risk signal。skill prompt 与本 reference **解释** tier 并摘要 profile 选择原因;不替代 code 推断。`dag run-task` 转发 embedded validate step 的同一 candidate `governanceProfile`。`dag run-task --profile auto` 先将 candidate profile 经 `harness.json.workflowPolicy.dag.profileRouting` 映射,再在 candidate delivery signal 含 `loop-agent-runtime-paths`、`scripts-ci-harness-paths` 或 `public-contract-paths` 时应用 M4 `supervised-quality-gate` promotion;`profileRouting.routingReasons` 记录确定性 reason。无 profile `dag run-task <task-id>` 仍为 standard-compatible;显式 `--profile minimal|standard|reviewed|supervised` 与自动 promotion 记录治理强度,已识别的前端业务 workflow 仍使用前端专用模板。高风险 task 应用 `--profile auto` 或显式 `--profile supervised`,而非显式 `--profile reviewed`。
71
71
  - **Executor model routing**:DAG spec 选 `executor` 与 `complexity`,可通过 `executorModels.pi` 覆盖 model 名;不选 provider。默认 routing:Pi LOW=`gpt-5.3-codex-spark`、MED=`glm-5.2`、HIGH=`gpt-5.5`。`shell` 不用 model,忽略 `executorModels`。
72
72
  - **Active visibility**:真实 `run-dag` execution 在 run/node 转换时写 active `state.json`,归档前 core runner 暴露 isolated `DagRunObserver` hook 供 derived view。`.harness/dag-runs/completed/<run-id>/` / `paused/<run-id>/` 仍是 source of truth;observer 输出非 canonical。
73
73
  - **可选 Canvas**:传 `--canvas-path <abs-path>` 或 `--canvas <name>` 输出 derived `.canvas.tsx` live view。省略 flag 行为不变。`--init-only` + Canvas 无需 `CURSOR_API_KEY`。