@tea-agent/loop-agent 0.13.0-beta.0 → 0.14.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.
Files changed (127) hide show
  1. package/AGENTS.md +2 -0
  2. package/CHANGELOG.md +56 -305
  3. package/README.md +13 -19
  4. package/dist/commands/init.js +92 -23
  5. package/dist/executors/pi-event-serializer.js +33 -11
  6. package/dist/executors/shell-executor.js +200 -21
  7. package/dist/infrastructure/evaluation/candidate-store.js +5 -1
  8. package/dist/worker/observe/spec-evidence.js +19 -10
  9. package/dist/worker/observe/static/app.js +4 -3
  10. package/dist/worker/observe/static/constants.js +10 -2
  11. package/dist/worker/observe/static/dag-helpers.js +37 -8
  12. package/dist/worker/observe/static/dom.js +159 -0
  13. package/dist/worker/observe/static/format-pool.d.ts +71 -0
  14. package/dist/worker/observe/static/format-pool.js +67 -0
  15. package/dist/worker/observe/static/format.js +27 -2
  16. package/dist/worker/observe/static/index.html +76 -34
  17. package/dist/worker/observe/static/kpi.js +12 -6
  18. package/dist/worker/observe/static/markdown-render.js +124 -0
  19. package/dist/worker/observe/static/shell-chrome.js +8 -2
  20. package/dist/worker/observe/static/state.js +20 -0
  21. package/dist/worker/observe/static/styles.css +662 -60
  22. package/dist/worker/observe/static/views/dag-inspector.js +65 -142
  23. package/dist/worker/observe/static/views/dag.js +9 -0
  24. package/dist/worker/observe/static/views/dashboard.js +512 -269
  25. package/dist/worker/observe/static/views/pool.js +595 -237
  26. package/dist/worker/observe/static/views/session-timeline.js +577 -11
  27. package/dist/workflows/dag/backend-test-case-manifest.js +503 -0
  28. package/dist/workflows/dag/backend-test-execution-contract.js +353 -0
  29. package/dist/workflows/dag/backend-test-result-contract.js +568 -0
  30. package/dist/workflows/dag/decision-envelope.js +57 -2
  31. package/dist/workflows/dag/frontend-implementation-contract.js +240 -0
  32. package/dist/workflows/dag/frontend-project-capability.js +309 -0
  33. package/dist/workflows/dag/frontend-repair.js +341 -0
  34. package/dist/workflows/dag/frontend-risk.js +161 -0
  35. package/dist/workflows/dag/frontend-verification-trace.js +190 -0
  36. package/dist/workflows/dag/init-hybrid.js +1020 -125
  37. package/dist/workflows/dag/repair-artifact.js +43 -3
  38. package/dist/workflows/dag/skill-instructions.js +4 -2
  39. package/dist/workflows/dag/types.js +29 -8
  40. package/docs/README.md +2 -0
  41. package/docs/agent-dag-recovery-playbook.md +3 -3
  42. package/docs/agent-dag-runner.md +3 -3
  43. package/docs/architecture/README.md +3 -3
  44. package/docs/architecture/dag-execution.md +1 -1
  45. package/docs/architecture/evolution.md +13 -13
  46. package/docs/architecture/facts-and-state.md +1 -1
  47. package/docs/architecture/runtime-boundaries.md +7 -7
  48. package/docs/architecture/system-overview.md +3 -3
  49. package/docs/architecture/worker-and-feature.md +3 -3
  50. package/docs/design/README.md +7 -7
  51. package/docs/development-principles.md +4 -4
  52. package/docs/exec-plans/active/README.md +2 -4
  53. package/docs/exec-plans/completed/README.md +29 -6
  54. package/docs/feature-workflow.md +57 -32
  55. package/docs/init-surface.manifest.json +21 -3
  56. package/docs/loop-agent-harness.md +8 -8
  57. package/docs/production-readiness.md +1 -1
  58. package/docs/progress/README.md +20 -3
  59. package/docs/reports/README.md +53 -7
  60. package/docs/templates/agent-dag.supervised-implementation.json +127 -8
  61. package/docs/templates/backend-test-case-manifest.schema.json +190 -0
  62. package/docs/templates/backend-test-dag.classify.prompt.md +75 -0
  63. package/docs/templates/backend-test-dag.generate-pytest.prompt.md +6 -4
  64. package/docs/templates/backend-test-dag.json +269 -21
  65. package/docs/templates/backend-test-dag.retrospect.prompt.md +44 -30
  66. package/docs/templates/backend-test-dag.review-cases.prompt.md +6 -4
  67. package/docs/templates/backend-test-execution.schema.json +133 -0
  68. package/docs/templates/backend-test-result.schema.json +99 -0
  69. package/docs/templates/branch-merge-report.md +93 -0
  70. package/docs/templates/frontend-eval/fixtures/failures/01-type-build-error.md +17 -0
  71. package/docs/templates/frontend-eval/fixtures/failures/02-unit-component-test-fail.md +16 -0
  72. package/docs/templates/frontend-eval/fixtures/failures/03-fixture-schema-drift.md +16 -0
  73. package/docs/templates/frontend-eval/fixtures/failures/04-missing-loading-empty-error-state.md +16 -0
  74. package/docs/templates/frontend-eval/fixtures/failures/05-forbidden-write-writeset-expansion.md +16 -0
  75. package/docs/templates/frontend-eval/fixtures/failures/06-unapproved-dependency-add.md +16 -0
  76. package/docs/templates/frontend-eval/fixtures/failures/07-mock-production-on.md +21 -0
  77. package/docs/templates/frontend-eval/fixtures/functional/01-simple-component-style.md +29 -0
  78. package/docs/templates/frontend-eval/fixtures/functional/02-form-validation.md +28 -0
  79. package/docs/templates/frontend-eval/fixtures/functional/03-list-detail-page.md +28 -0
  80. package/docs/templates/frontend-eval/fixtures/functional/04-api-mock.md +29 -0
  81. package/docs/templates/frontend-eval/fixtures/functional/05-permission-auth-gated-ui.md +27 -0
  82. package/docs/templates/frontend-eval/fixtures/functional/06-ssr-server-client-boundary.md +28 -0
  83. package/docs/templates/frontend-eval/fixtures/functional/07-shared-public-component-api.md +28 -0
  84. package/docs/templates/frontend-eval/fixtures/functional/08-pure-local-no-remote.md +27 -0
  85. package/docs/templates/frontend-eval/metrics.md +138 -0
  86. package/docs/templates/frontend-eval/smoke-targets.md +53 -0
  87. package/docs/templates/frontend-implementation-contract.schema.json +27 -0
  88. package/docs/verification-matrix.md +1 -1
  89. package/examples/decision-gate-agent-dag.json +4 -4
  90. package/examples/hybrid-loop-agent-dag.json +1 -1
  91. package/package.json +2 -2
  92. package/skills/ai-engineering-context/SKILL.md +2 -2
  93. package/skills/browser-tools/SKILL.md +196 -0
  94. package/skills/browser-tools/browser-content.js +103 -0
  95. package/skills/browser-tools/browser-cookies.js +35 -0
  96. package/skills/browser-tools/browser-eval.js +53 -0
  97. package/skills/browser-tools/browser-hn-scraper.js +108 -0
  98. package/skills/browser-tools/browser-nav.js +44 -0
  99. package/skills/browser-tools/browser-pick.js +162 -0
  100. package/skills/browser-tools/browser-screenshot.js +34 -0
  101. package/skills/browser-tools/browser-start.js +86 -0
  102. package/skills/browser-tools/package-lock.json +2556 -0
  103. package/skills/browser-tools/package.json +19 -0
  104. package/skills/frontend-implementation/SKILL.md +3 -1
  105. package/skills/frontend-implementation/references/node-contracts.md +17 -66
  106. package/skills/frontend-verification/SKILL.md +1 -1
  107. package/skills/grill-with-docs/SKILL.md +5 -5
  108. package/skills/grill-with-docs/adr-format.md +3 -3
  109. package/skills/init-capability-evolution/SKILL.md +5 -5
  110. package/skills/loop-agent/SKILL.md +5 -5
  111. package/skills/loop-agent/references/README.md +3 -3
  112. package/skills/loop-agent/references/command-reference.md +39 -17
  113. package/skills/loop-agent/references/docs-converge.md +15 -15
  114. package/skills/loop-agent/references/harness-policy.md +2 -2
  115. package/skills/loop-agent/references/hybrid-dag.md +20 -15
  116. package/skills/loop-agent/references/multi-worktree.md +1 -1
  117. package/skills/loop-agent/references/orchestrator-and-interventions.md +8 -8
  118. package/skills/loop-agent/references/task-workflow.md +1 -1
  119. package/skills/loop-agent/references/verification-and-failure-handling.md +6 -4
  120. package/skills/requesting-code-review/SKILL.md +1 -1
  121. package/skills/systematic-debugging/CREATION-LOG.md +3 -3
  122. package/skills/systematic-debugging/SKILL.md +1 -1
  123. package/skills/systematic-debugging/test-academic.md +1 -1
  124. package/skills/systematic-debugging/test-pressure-1.md +1 -1
  125. package/skills/systematic-debugging/test-pressure-2.md +1 -1
  126. package/skills/systematic-debugging/test-pressure-3.md +1 -1
  127. package/skills/verification-before-completion/SKILL.md +1 -1
@@ -0,0 +1,124 @@
1
+ /** Shared safe Markdown → DOM rendering for Observe UI. */
2
+ import { el } from "./dom.js";
3
+ import { parseMarkdownBlocks, markdownLinkHref } from "./format.js";
4
+
5
+ export function appendInlineMarkdown(target, text) {
6
+ const tokenPattern = /(`[^`]*`|\*\*[^*]+\*\*|\*[^*]+\*|\[[^\]]+\]\([^)]+\))/g;
7
+ let cursor = 0;
8
+ for (const match of text.matchAll(tokenPattern)) {
9
+ const index = match.index ?? 0;
10
+ if (index > cursor)
11
+ target.appendChild(document.createTextNode(text.slice(cursor, index)));
12
+ const token = match[0];
13
+ if (token.startsWith("`")) {
14
+ target.appendChild(el("code", null, token.slice(1, -1)));
15
+ } else if (token.startsWith("**")) {
16
+ const strong = document.createElement("strong");
17
+ strong.textContent = token.slice(2, -2);
18
+ target.appendChild(strong);
19
+ } else if (token.startsWith("*")) {
20
+ const emphasis = document.createElement("em");
21
+ emphasis.textContent = token.slice(1, -1);
22
+ target.appendChild(emphasis);
23
+ } else {
24
+ const link = token.match(/^\[([^\]]+)\]\((.+)\)$/);
25
+ const href = markdownLinkHref(link?.[2]);
26
+ if (link && href) {
27
+ const anchor = document.createElement("a");
28
+ anchor.href = href;
29
+ anchor.target = "_blank";
30
+ anchor.rel = "noopener noreferrer";
31
+ anchor.textContent = link[1];
32
+ target.appendChild(anchor);
33
+ } else {
34
+ target.appendChild(document.createTextNode(token));
35
+ }
36
+ }
37
+ cursor = index + token.length;
38
+ }
39
+ if (cursor < text.length)
40
+ target.appendChild(document.createTextNode(text.slice(cursor)));
41
+ }
42
+
43
+ /** Render paragraph text, honoring \n hard breaks as <br>. */
44
+ export function appendParagraphMarkdown(target, text) {
45
+ const segments = String(text ?? "").split("\n");
46
+ for (let i = 0; i < segments.length; i += 1) {
47
+ if (i > 0) target.appendChild(document.createElement("br"));
48
+ appendInlineMarkdown(target, segments[i]);
49
+ }
50
+ }
51
+
52
+ export function renderMarkdown(content) {
53
+ const article = el("article", "markdown-output");
54
+ for (const block of parseMarkdownBlocks(content)) {
55
+ switch (block.type) {
56
+ case "heading": {
57
+ const heading = document.createElement(`h${block.level}`);
58
+ appendInlineMarkdown(heading, block.text);
59
+ article.appendChild(heading);
60
+ break;
61
+ }
62
+ case "paragraph": {
63
+ const paragraph = document.createElement("p");
64
+ appendParagraphMarkdown(paragraph, block.text);
65
+ article.appendChild(paragraph);
66
+ break;
67
+ }
68
+ case "quote": {
69
+ const quote = document.createElement("blockquote");
70
+ appendParagraphMarkdown(quote, block.text);
71
+ article.appendChild(quote);
72
+ break;
73
+ }
74
+ case "list": {
75
+ const list = document.createElement(block.ordered ? "ol" : "ul");
76
+ for (const item of block.items) {
77
+ const listItem = document.createElement("li");
78
+ appendInlineMarkdown(listItem, item);
79
+ list.appendChild(listItem);
80
+ }
81
+ article.appendChild(list);
82
+ break;
83
+ }
84
+ case "code": {
85
+ const pre = document.createElement("pre");
86
+ const code = document.createElement("code");
87
+ if (block.language) code.dataset.language = block.language;
88
+ code.textContent = block.text;
89
+ pre.appendChild(code);
90
+ article.appendChild(pre);
91
+ break;
92
+ }
93
+ case "table": {
94
+ const table = document.createElement("table");
95
+ const head = document.createElement("thead");
96
+ const headRow = document.createElement("tr");
97
+ for (const value of block.headers) {
98
+ const cell = document.createElement("th");
99
+ appendInlineMarkdown(cell, value);
100
+ headRow.appendChild(cell);
101
+ }
102
+ head.appendChild(headRow);
103
+ table.appendChild(head);
104
+ const body = document.createElement("tbody");
105
+ for (const row of block.rows) {
106
+ const tableRow = document.createElement("tr");
107
+ for (const value of row) {
108
+ const cell = document.createElement("td");
109
+ appendInlineMarkdown(cell, value);
110
+ tableRow.appendChild(cell);
111
+ }
112
+ body.appendChild(tableRow);
113
+ }
114
+ table.appendChild(body);
115
+ article.appendChild(table);
116
+ break;
117
+ }
118
+ case "rule":
119
+ article.appendChild(document.createElement("hr"));
120
+ break;
121
+ }
122
+ }
123
+ return article;
124
+ }
@@ -45,14 +45,20 @@ export function setBreadcrumb(parts) {
45
45
  });
46
46
  }
47
47
 
48
- export function updateHeaderRefresh(generatedAt) {
48
+ export function updateHeaderRefresh(generatedAt, options = {}) {
49
49
  const elRefresh = document.getElementById("header-refresh");
50
50
  if (!elRefresh) return;
51
51
  if (!generatedAt) {
52
52
  elRefresh.textContent = "";
53
53
  return;
54
54
  }
55
- elRefresh.textContent = `${formatAgo(generatedAt)} · ${UI_TEXT.nearRealtime}`;
55
+ const modeLabel =
56
+ options.mode === "manual"
57
+ ? UI_TEXT.manualRefresh
58
+ : options.mode === "auto"
59
+ ? UI_TEXT.autoRefresh
60
+ : UI_TEXT.nearRealtime;
61
+ elRefresh.textContent = `${formatAgo(generatedAt)} · ${modeLabel}`;
56
62
  }
57
63
 
58
64
  export function mountRelationBar(containerId, ids, snapshot) {
@@ -17,6 +17,8 @@ export const uiState = {
17
17
  runPollTimer: null,
18
18
  dagPollTimer: null,
19
19
  poolTimer: null,
20
+ /** Pool page: auto-refresh opt-in (default false). */
21
+ poolAutoRefresh: false,
20
22
  taskPollTimer: null,
21
23
  runEventOffset: 0,
22
24
  runEvents: [],
@@ -26,6 +28,16 @@ export const uiState = {
26
28
  selectedDagNodeId: null,
27
29
  sessionEventOffset: 0,
28
30
  sessionEvents: [],
31
+ // Identity token ("<dagRunId>:<nodeId>#<seq>") bumped on every node/DAG
32
+ // switch. In-flight session-event fetches capture this before await and
33
+ // reject themselves when it no longer matches, so a stale response for a
34
+ // previous node can never mutate the current node's event cache.
35
+ sessionEventIdentity: null,
36
+ sessionEventIdentitySeq: 0,
37
+ /** When true,「执行过程」展开 message_start/end 原始协议事件。 */
38
+ sessionTimelineShowProtocol: false,
39
+ /** Open <details> keys restored across timeline re-renders. */
40
+ sessionTimelineOpenDetails: null,
29
41
  lastSnapshot: null,
30
42
  dagInspectorOpen: false,
31
43
  dagInspectorTab: "output",
@@ -40,6 +52,12 @@ export const uiState = {
40
52
  /** Per-dagRunId graph viewport restore map (stable Map instance). */
41
53
  export const dagGraphViewportStates = new Map();
42
54
 
55
+ /** Build a fresh session-event identity token and bump the global sequence. */
56
+ export function makeSessionEventIdentity(dagRunId, nodeId) {
57
+ uiState.sessionEventIdentitySeq += 1;
58
+ return `${dagRunId}:${nodeId}#${uiState.sessionEventIdentitySeq}`;
59
+ }
60
+
43
61
  export function isPageVisible() {
44
62
  return (
45
63
  typeof document === "undefined" || document.visibilityState !== "hidden"
@@ -188,6 +206,8 @@ export function stopTimers() {
188
206
  uiState.selectedDagNodeId = null;
189
207
  uiState.sessionEventOffset = 0;
190
208
  uiState.sessionEvents = [];
209
+ uiState.sessionEventIdentity = null;
210
+ uiState.sessionEventIdentitySeq += 1;
191
211
  uiState.runEventOffset = 0;
192
212
  uiState.runEvents = [];
193
213
  }