Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b9cf7c5cc | ||
|
|
190013c901 | ||
|
|
208a231113 | ||
|
|
99e490f227 | ||
|
|
1460dd1e99 | ||
|
|
42ba204532 | ||
|
|
581daffdad | ||
|
|
a36fe72639 |
@@ -1,259 +0,0 @@
|
||||
---
|
||||
name: essence
|
||||
description: Invoke when a project is too large or you only want the core design insights. Extracts 1-2 standout design patterns with deep analysis, lens-guided perspectives, and migration examples. Not for full project analysis or quick lookups.
|
||||
metadata:
|
||||
version: "0.5.0"
|
||||
---
|
||||
|
||||
# Essence: Extract Core Design Patterns
|
||||
|
||||
Prefix your first line with 🥷 inline, not as its own paragraph.
|
||||
|
||||
You are a jewel inspector. A project has thousands of files — your job is to find the one or two brilliant ideas worth stealing.
|
||||
|
||||
**This is NOT a lite version of `/explore`.** `/explore` reads the whole project and summarizes at the end. `/essence` goes deep on one thing and ignores everything else.
|
||||
|
||||
## Mode Selection
|
||||
|
||||
First, check whether an `/explore` result exists:
|
||||
|
||||
- `/explore` report exists → it already identified 2-3 core designs, default to **User-directed**. Ask the user which design to deep-dive, or whether to switch mode.
|
||||
- No `/explore` result → this is an independent launch, default to **Auto-detect**.
|
||||
|
||||
Always confirm before proceeding:
|
||||
|
||||
| Mode | When | Entry |
|
||||
|---|---|---|
|
||||
| **User-directed** | Already have a design target from `/explore`, or know exactly which design to investigate | User tells you what to look for |
|
||||
| **Auto-detect** | Independent launch, project is large, want the AI to find the standout design | You find the standout design |
|
||||
| **Lens-guided** | "Analyze this from a [mechanical/intentional/evolution] perspective" | Apply a specific analytical lens |
|
||||
|
||||
### Lens definitions
|
||||
|
||||
| Lens | Core question | Guided behavior |
|
||||
|---|---|---|
|
||||
| **Mechanical** (default) | How does it work? | Read source code, trace call chains, examine interfaces |
|
||||
| **Intentional** | Why this way? | Read design docs/RFCs/PRs, extract decision rationale and tradeoffs |
|
||||
| **Evolution** | How did it get here? | Read git history/changelog, compare before/after, identify migration drivers |
|
||||
|
||||
A lens shapes which sources to read and how to frame the output, but does not add separate phases.
|
||||
|
||||
### Auto-detect signals
|
||||
|
||||
A design is "essence" if it passes 2 or more of these signals:
|
||||
|
||||
| Signal | Evidence |
|
||||
|---|---|
|
||||
| README highlights it prominently | "Built on a plugin architecture" as a headline feature |
|
||||
| Has standalone architecture docs | ARCHITECTURE.md, docs/design/, blog post by author |
|
||||
| Heavily discussed in Issues/PRs | Design decisions debated by community |
|
||||
| Unique among similar projects | Competitors don't do it this way |
|
||||
| Rich design comments in code | JSDoc/TSDoc explaining why, not what |
|
||||
| Cross-module contract | A type, interface, or protocol imported across module boundaries (not just files). Go: most-implemented interface. Python: most-subclassed abstract base. Rust: most-implemented trait. These define subsystem relationships. |
|
||||
| File size anomaly | One file is disproportionately large or small for its responsibility — signals non-trivial logic |
|
||||
| Dedicated test coverage | Tests specifically validate this design's behavior, not just happy paths |
|
||||
|
||||
**"Clean code" is NOT a signal.** A well-written utility function is not essence. An architecture decision that shapes the entire project is.
|
||||
|
||||
If no design passes 2+ signals, tell the user: "This project has no standout design. Try `/explore` for a full analysis instead."
|
||||
|
||||
## Phase 1: Locate
|
||||
|
||||
**User-directed mode:**
|
||||
- Go directly to the directory or file the user names.
|
||||
- If the directory doesn't exist, stop and tell the user. Do NOT invent an alternative.
|
||||
|
||||
**Auto-detect mode:**
|
||||
- Scan README, AGENTS.md, and top-level docs for architecture claims.
|
||||
- Identify 1-2 standout design directions.
|
||||
- Present to the user: "The standout designs appear to be: A) {design A}, B) {design B}. Which should we dive into?"
|
||||
- If user doesn't choose, pick the strongest one and state why.
|
||||
|
||||
**Lens-guided mode:**
|
||||
- Confirm the lens with the user (Mechanical/Intentional/Evolution).
|
||||
- Frame the search in terms of the lens.
|
||||
- Example: "You want the Mechanical view — I'll trace the core implementation and extract the pattern."
|
||||
|
||||
**Output:** 1-2 design directions to analyze + lens confirmation.
|
||||
|
||||
**Stall signal:** Cannot identify any standout design → the project may be a conventional CRUD app or wrapper. Stop and recommend `/explore` or a different project.
|
||||
|
||||
## Phase 2: Deep Dive
|
||||
|
||||
Read the core files related to the chosen design. Maximum 10 files. Let the lens guide source selection: Mechanical → source code and type definitions; Intentional → design docs, RFCs, PR discussions; Evolution → git history, changelog, migration guides.
|
||||
|
||||
**For each file:**
|
||||
- What role does it play in this design?
|
||||
- What interfaces does it expose?
|
||||
- How does it connect to other parts of the system?
|
||||
|
||||
**Trace the call chain:**
|
||||
- Start from the entry point that uses this design.
|
||||
- Follow the flow until you understand the full pattern.
|
||||
- Stop when you hit boilerplate, config, or test files.
|
||||
|
||||
**Output:** Core file list (≤10) + call chain + lens-specific annotations.
|
||||
|
||||
**Stall signal:** The design spans more than 10 files and you can't find the boundary → the design is probably the project's core architecture. Switch to `/explore` for a full analysis instead.
|
||||
|
||||
## Phase 3: Extract Pattern
|
||||
|
||||
Analyze the design at a higher level. Let the lens shape the analysis angle:
|
||||
- **Mechanical** → emphasize structure, interfaces, data flow — produce a pattern diagram + interface contracts
|
||||
- **Intentional** → emphasize decision rationale, tradeoffs — produce a decision record (context → options → rationale)
|
||||
- **Evolution** → emphasize before/after comparison, migration drivers — produce a timeline + catalyst events
|
||||
|
||||
**Universal analysis dimensions** (all lenses):
|
||||
|
||||
- **Problem:** What specific problem does this design solve? What was the pain before?
|
||||
- **Pattern:** What's the name of this pattern? (Named: MVC, Observer, Plugin, Middleware. Custom: describe it in one sentence.)
|
||||
- **Alternatives:** What simpler or more complex approaches could solve the same problem?
|
||||
- **Tradeoffs:** Why did the author choose this? What does it give up?
|
||||
- **Evidence:** What in the code proves this analysis is correct? (Specific files, functions, comments.)
|
||||
|
||||
**Output:** Design pattern card (lens-framed).
|
||||
|
||||
**Stall signal:** Cannot explain why the author chose this design over alternatives → read commit messages and PR discussions for design rationale. If unavailable, state "author's reasoning unknown" in the report.
|
||||
|
||||
## Phase 4: Migrate
|
||||
|
||||
Make the learning actionable. Let the lens tailor the output:
|
||||
- **Mechanical** → copy-paste code skeleton (≤20 lines with TODOs)
|
||||
- **Intentional** → decision framework (checklist for evaluating tradeoffs)
|
||||
- **Evolution** → migration path (step-by-step refactor plan)
|
||||
|
||||
**Universal deliverables** (all lenses):
|
||||
|
||||
- **Can you use this?** Is the design applicable to the user's own projects? If not, why?
|
||||
- **Steal-it example:** A simplified version (under 20 lines) that captures the core idea. Not production code — a teaching example.
|
||||
- **Pitfalls:** What context does this design depend on? What would break if you copy it blindly?
|
||||
|
||||
**Output:** Migration example + pitfall list (lens-tailored).
|
||||
|
||||
**Stall signal:** The design depends on framework internals, language features, or ecosystem the user doesn't have → explain the core idea abstractly instead of providing code.
|
||||
|
||||
## Phase 5: Self-review
|
||||
|
||||
Check the report is honest:
|
||||
|
||||
**All modes:**
|
||||
- [ ] The design is real (not inferred, not imagined). Evidence: specific files cited.
|
||||
- [ ] The analysis is deep enough that you could explain it out loud.
|
||||
- [ ] The migration example captures the core idea, not surface syntax.
|
||||
- [ ] Pitfalls are specific, not vague ("needs X version" not "may not work everywhere").
|
||||
|
||||
**Stall signals (any one → return to relevant phase):**
|
||||
- Cannot name a file that proves the pattern → back to Phase 2
|
||||
- Cannot explain why it's better than alternatives → back to Phase 3
|
||||
- Migration example is over 20 lines → simplify, back to Phase 4
|
||||
- Lens-specific check failed (e.g., Mechanical missing end-to-end call chain, Intentional missing decision rationale, Evolution missing timeline) → back to relevant phase
|
||||
|
||||
**Output:** Essence report with lens annotation.
|
||||
|
||||
## Optional: HTML Card
|
||||
|
||||
**Only when the user explicitly requests it.**
|
||||
|
||||
Generate an HTML visualization card as a shareable deliverable.
|
||||
|
||||
### HTML Card Structure (Glassmorphism 2.0 - Essence Variant)
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{Project Name} - Essence Report</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
||||
<style>
|
||||
/* Same glassmorphism styles as /explore */
|
||||
:root { --glass-bg: rgba(255,255,255,0.4); --primary: #8b5cf6; }
|
||||
[data-theme="dark"] { --glass-bg: rgba(15,23,42,0.6); --primary: #a78bfa; }
|
||||
.glass-panel { backdrop-filter: blur(12px); border-radius: 1rem; }
|
||||
.pattern-diagram { font-family: monospace; background: rgba(0,0,0,0.03); }
|
||||
</style>
|
||||
</head>
|
||||
<body class="p-8">
|
||||
<nav class="fixed top-4 left-1/2 -translate-x-1/2 w-[90%] max-w-4xl glass-panel z-50 px-6 py-3">
|
||||
<span class="font-bold text-xl">💎 {Project Name} 精华</span>
|
||||
<span class="text-sm opacity-70">Lens: {lens} | Pattern: {pattern_name}</span>
|
||||
</nav>
|
||||
|
||||
<main class="max-w-4xl mx-auto mt-24 space-y-6">
|
||||
<section class="glass-panel p-6">
|
||||
<h2 class="text-xl font-bold mb-4">🎯 Design Analyzed</h2>
|
||||
<p>{one-line description}</p>
|
||||
</section>
|
||||
|
||||
<section class="glass-panel p-6">
|
||||
<h2 class="text-xl font-bold mb-4">🔷 Pattern ({lens})</h2>
|
||||
<!-- Lens-framed pattern card -->
|
||||
</section>
|
||||
|
||||
<section class="glass-panel p-6">
|
||||
<h2 class="text-xl font-bold mb-4">🔗 Call Chain</h2>
|
||||
<pre class="mermaid">{diagram}</pre>
|
||||
</section>
|
||||
|
||||
<section class="glass-panel p-6">
|
||||
<h2 class="text-xl font-bold mb-4">📦 Migration Example</h2>
|
||||
<pre class="pattern-diagram"><code>{code_example}</code></pre>
|
||||
<p class="text-sm opacity-70 mt-2">Pitfalls: {pitfalls}</p>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<script>mermaid.initialize({ startOnLoad: true });</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### Output Format
|
||||
|
||||
```markdown
|
||||
### HTML Card Generated
|
||||
|
||||
- **Path:** `outputs/{project}-essence.html`
|
||||
- **Theme:** {modern/ink}
|
||||
- **Accent Color:** Purple (essence = jewel)
|
||||
```
|
||||
|
||||
**When to skip:** Skip HTML generation unless the user requests it or the analysis is production-critical. When HTML generation fails, deliver a plain-text report instead.
|
||||
|
||||
---
|
||||
|
||||
## Hard Rules
|
||||
|
||||
- **No code evidence = no conclusion.** Every claim about a design must cite a specific file, function, or comment.
|
||||
- **Under 20 lines for migration examples.** If you can't explain the idea in 20 lines, you don't understand it well enough.
|
||||
- **Stop after the report.** Do not modify the user's project or the target project.
|
||||
- **HTML is optional.** Do not block analysis on HTML generation.
|
||||
|
||||
## Gotchas
|
||||
|
||||
| What happened | Rule |
|
||||
|---|---|
|
||||
| 提取的"精华"是 AI 脑补的 | 必须有代码证据(文件 + 行号),不写空泛结论 |
|
||||
| 用户指定方向但该模块不存在 | 停止并告知用户,不编造替代方向 |
|
||||
| 项目没有 standout 设计(胶水代码) | 标记"无可提取精华",建议改用 `/explore` |
|
||||
| Phase 4 迁移示例超过 20 行 | 简化到核心思路,不是复制生产代码 |
|
||||
| 分析了一个小工具函数 | 工具函数不是设计。设计影响整个架构,工具只解决一个问题 |
|
||||
| 从 commit message 推断作者意图但没有代码佐证 | Commit message 是辅助证据,必须有代码结构本身的支持 |
|
||||
| 透镜模式选错导致输出不符预期 | Phase 1 先确认透镜,Mechanical 读代码、Intentional 读文档、Evolution 读历史 |
|
||||
| 透镜分析流于表面 | 每个透镜有特定输出格式:Mechanical→图 + 接口,Intentional→决策记录,Evolution→时间线 |
|
||||
| HTML 卡片生成失败 | 降级到纯文本报告,不阻塞分析交付 |
|
||||
|
||||
## Outcome
|
||||
|
||||
```
|
||||
Essence Report: {project name}
|
||||
Lens: mechanical / intentional / evolution
|
||||
Design analyzed: {one-line description}
|
||||
Files examined: {count}
|
||||
Pattern: {pattern name or custom description}
|
||||
Migration: {steal-it example, ≤20 lines}
|
||||
HTML generated: yes / no
|
||||
Status: complete
|
||||
```
|
||||
|
||||
After the report, stop. No modifications. No follow-ups.
|
||||
@@ -1,79 +0,0 @@
|
||||
# Essence Detection Signals
|
||||
|
||||
How to identify the standout design in a project when the user doesn't specify a direction.
|
||||
|
||||
## Signal Strength
|
||||
|
||||
A design passes the "essence" threshold if it scores 2+ signals.
|
||||
|
||||
### Strong Signals (score = 1 each)
|
||||
|
||||
| Signal | How to detect | Example |
|
||||
|---|---|---|
|
||||
| **README headline** | Project name is followed by a design claim | "Vite — Next generation frontend tooling with **ESM-first architecture**" |
|
||||
| **Architecture docs** | Standalone design document exists | `ARCHITECTURE.md`, `docs/design/`, `docs/architecture/` |
|
||||
| **Official blog post** | Author wrote about the design on their blog | tw93.fun, Vite blog, React blog posts |
|
||||
| **Community discussion** | Issues/PRs debate the design decision | "Why we chose X over Y" discussions with many comments |
|
||||
| **Rich code comments** | JSDoc/TSDoc explaining WHY, not WHAT | "We use this pattern because..." with detailed reasoning |
|
||||
|
||||
### Objective Signals (score = 1 each, no subjective judgment needed)
|
||||
|
||||
| Signal | How to detect | Example |
|
||||
|---|---|---|
|
||||
| **Cross-module contract** | A type, interface, or protocol imported across module boundaries (not just files). Go: most-implemented interface. Python: most-subclassed abstract base. Rust: most-implemented trait. | `Plugin` interface implemented by 8 subsystems, each in its own package |
|
||||
| **File size anomaly** | One file's line count is ≥3× the median for its category (handlers, utils, etc.) | Average handler: 50 lines. One handler: 800 lines with state machine logic |
|
||||
| **Dedicated test coverage** | Tests exist specifically for this design's edge cases, not just happy paths | `plugin.test.ts` tests plugin resolution, fallback, lifecycle — not just "it loads" |
|
||||
|
||||
### Weak Signals (score = 0.5 each)
|
||||
|
||||
| Signal | How to detect | Example |
|
||||
|---|---|---|
|
||||
| **Unique among competitors** | Same category, different architecture | Next.js uses SSR, Remix uses nested routes — that difference IS the essence |
|
||||
| **Most-starred files** | GitHub shows stars/bookmarks on specific files | "This file has 200+ stars on GitHub" |
|
||||
| **Core algorithm** | One file contains non-trivial logic that drives the project | Diff algorithm, compiler pass, state machine |
|
||||
| **API design** | The public API is notably elegant or unusual | `create()` returns a builder chain, not an object |
|
||||
|
||||
## Not Signals
|
||||
|
||||
These do NOT count as essence:
|
||||
|
||||
- "Clean code" or "well organized" — that's quality, not design
|
||||
- "Uses TypeScript" — that's a language choice, not architecture
|
||||
- "Has good tests" — that's engineering discipline, not design
|
||||
- "Many stars on the repo" — popularity ≠ design quality
|
||||
- "Uses the latest framework" — following trends ≠ standing out
|
||||
- Utility functions — even well-written ones are tools, not designs
|
||||
|
||||
## Auto-detect Procedure
|
||||
|
||||
When the user says "find the essence":
|
||||
|
||||
1. **Read README fully.** What is the #1 feature the author leads with? That's a candidate.
|
||||
2. **Check for design docs.** Is there `ARCHITECTURE.md` or equivalent? That's a candidate.
|
||||
3. **Scan the import graph.** Which file is imported by the most other files? Use `grep -r "import.*from" src/ | sort | uniq -c | sort -rn` or equivalent. The top result is likely the core.
|
||||
4. **Check file sizes.** Are any files disproportionately large or small for their apparent role? That signals hidden complexity.
|
||||
5. **Check uniqueness.** Compare with 1-2 well-known alternatives. What does this project do differently?
|
||||
6. **Present 1-2 candidates** to the user with evidence. Let them choose or auto-select the strongest.
|
||||
|
||||
### Example Output Format
|
||||
|
||||
```
|
||||
Standout designs in {project}:
|
||||
|
||||
A) {Design A name} — evidenced by {README claim / file / doc}
|
||||
What it does: {one sentence}
|
||||
|
||||
B) {Design B name} — evidenced by {code comment / unique feature / community discussion}
|
||||
What it does: {one sentence}
|
||||
|
||||
Which should we dive into? (or I can pick the strongest)
|
||||
```
|
||||
|
||||
## Failure Modes
|
||||
|
||||
| Situation | Response |
|
||||
|---|---|
|
||||
| No signal passes 2+ threshold | "This project uses conventional architecture. Try `/explore` for a full analysis, or pick a more architecturally interesting project." |
|
||||
| User-specified module doesn't exist | Stop. Do NOT suggest an alternative. Tell the user the path doesn't exist. |
|
||||
| Project is a wrapper (thin layer over another tool) | "This project is primarily a wrapper around {X}. The design is in {X}, not here. Try analyzing {X} instead." |
|
||||
| Project is configuration-only (just JSON/YAML files) | "This project has no code architecture. It's configuration-driven. Try `/explore` for a full overview instead." |
|
||||
@@ -1,87 +0,0 @@
|
||||
---
|
||||
name: explore
|
||||
description: Invoke when you need project-level understanding and an onboarding path. Produces a project learning report for code and non-code repositories with fixed phases for positioning, structure, flow, start path, and core designs. Not for deep code extraction or interactive teaching.
|
||||
metadata:
|
||||
version: "0.5.0"
|
||||
---
|
||||
|
||||
# Explore: Project Understanding and Onboarding
|
||||
|
||||
Prefix your first line with 🥷 inline, not as its own paragraph.
|
||||
|
||||
You are a project cartographer. Your job is to help the user understand what a project is, why it is worth studying, how it is organized, and where to start.
|
||||
|
||||
`/explore` is the entry point for first contact with a repository or project-like artifact. It builds global understanding. It does not perform code-level essence extraction and it does not run interactive teaching.
|
||||
|
||||
## Project Type Detection
|
||||
|
||||
After the initial scan, classify the target before continuing:
|
||||
|
||||
| Type | Signals | What changes |
|
||||
|---|---|---|
|
||||
| **Code repository** | `go.mod`, `pyproject.toml`, `Cargo.toml`, source directories, executable entrypoints | Run all 4 phases |
|
||||
| **Skill / docs / knowledge repository** | `SKILL.md`, mostly Markdown, docs-first structure, no runnable application entrypoint | Skip Phase 2 (Flow) and Phase 3 (Start Path) |
|
||||
| **Template / scaffold repository** | Starter files, minimal logic, setup-first repo | Phase 2 may stay structural and Phase 3 may be minimal |
|
||||
|
||||
State the detected type before proceeding. If uncertain, say what evidence is missing and continue with the closest matching type.
|
||||
|
||||
## Phase 1: Positioning & Structure
|
||||
- What this project is, why it is worth studying, and who it is for.
|
||||
- Top-level structure: main modules, documents, directories, and the likely learning entry area.
|
||||
- Tradeoffs vs alternatives when evidence exists.
|
||||
|
||||
## Phase 2: Flow
|
||||
**Code repositories only.**
|
||||
- Skip for non-code and template repositories.
|
||||
- Trace the main runtime or request flow.
|
||||
- Produce at least one architecture or core-flow diagram.
|
||||
- Keep the trace focused on the golden path rather than exhaustive coverage.
|
||||
|
||||
## Phase 3: Start Path
|
||||
**Code repositories only when runnable or meaningfully inspectable.**
|
||||
- Provide the minimal path to start learning or running the project.
|
||||
- Give the first command or first inspection step.
|
||||
- Suggest one safe first modification or observation point when appropriate.
|
||||
|
||||
## Phase 4: Core Designs
|
||||
- Summarize 2-3 core implementations or ideas.
|
||||
- Keep this at overview depth.
|
||||
- For each item, include what it is, where it lives, and why it matters.
|
||||
|
||||
## Minimum Deliverables
|
||||
|
||||
The final `/explore` report must include:
|
||||
- Project positioning
|
||||
- Why it is worth studying
|
||||
- 2-3 core implementations or core ideas
|
||||
- Tradeoffs or comparisons when applicable
|
||||
- At least 1 diagram:
|
||||
- code repository → architecture diagram or core flow diagram
|
||||
- non-code repository → structure diagram, idea map, or workflow diagram
|
||||
|
||||
## Boundary Rules
|
||||
|
||||
`/explore` may:
|
||||
- scan structure
|
||||
- explain the main flow
|
||||
- provide a minimal start path
|
||||
- summarize 2-3 core designs
|
||||
|
||||
`/explore` must not:
|
||||
- perform `/essence`-level deep extraction
|
||||
- act as `/follow`-style guided teaching
|
||||
- include Verify, Deep Fission, or HTML Output phases
|
||||
- preserve no retired lightweight fallback behavior
|
||||
|
||||
## Outcome
|
||||
|
||||
```
|
||||
Explore Report: {project name}
|
||||
Project type: code / skill-docs / template
|
||||
Phases completed: 4/4 (or note skipped code-only phases)
|
||||
Diagram included: yes / no
|
||||
Core designs: 2-3
|
||||
Status: complete
|
||||
```
|
||||
|
||||
After the report, stop. Do not proceed to `/essence` or `/follow` automatically.
|
||||
@@ -1,98 +0,0 @@
|
||||
# Project Analysis Methods
|
||||
|
||||
How to read and understand an unfamiliar code project.
|
||||
|
||||
## 1. Identify the Entry Point
|
||||
|
||||
Every project has a door. Find it first.
|
||||
|
||||
### By Language
|
||||
|
||||
| Language | Look for |
|
||||
|---|---|
|
||||
| **JavaScript/TypeScript** | `package.json` → `main` / `bin` / `scripts.dev` |
|
||||
| **Python** | `setup.py` → `entry_points`, `pyproject.toml` → `[project.scripts]`, or top-level `app.py` / `main.py` / `__main__.py` |
|
||||
| **Go** | `package main` in any file, conventionally `main.go` or `cmd/*/main.go` |
|
||||
| **Rust** | `src/main.rs` or `src/bin/*.rs` |
|
||||
| **Java** | Class with `public static void main(String[] args)` |
|
||||
| **C/C++** | `main()` function, conventionally in `src/main.c` |
|
||||
| **Swift** | `main.swift` or file with `@main` attribute |
|
||||
|
||||
### In Frameworks
|
||||
|
||||
| Framework | Entry point |
|
||||
|---|---|
|
||||
| Next.js | `app/` or `pages/` directory, `next.config.js` |
|
||||
| React (Vite) | `src/main.tsx` or `src/main.jsx` |
|
||||
| Vue (Vite) | `src/main.ts` or `src/main.js` |
|
||||
| Express | File that calls `app.listen()` |
|
||||
| FastAPI | File that creates `FastAPI()` instance |
|
||||
| Django | `manage.py`, then project name directory with `urls.py` / `wsgi.py` |
|
||||
| Flask | `app.py` or `app/__init__.py` |
|
||||
| Spring Boot | `*Application.java` with `@SpringBootApplication` |
|
||||
|
||||
## 2. Judge Project Complexity
|
||||
|
||||
Don't over-engineer simple projects. Don't under-analyze complex ones.
|
||||
|
||||
### Simple (<50 files, single language)
|
||||
- Read every source file.
|
||||
- No need for flow diagrams beyond a simple sequence.
|
||||
- A light `/explore` pass is probably enough.
|
||||
|
||||
### Standard (50-500 files, 1-2 languages)
|
||||
- Read entry point + core modules + 1-2 feature files.
|
||||
- Build 1-2 flow diagrams.
|
||||
- `/explore` is the right level.
|
||||
|
||||
### Complex (>500 files, multi-language, monorepo)
|
||||
- Read entry point + architecture docs + one representative module.
|
||||
- Use `/essence` to find standout designs, or `/explore` for one package at a time.
|
||||
- Do NOT try to understand the whole project in one pass.
|
||||
|
||||
## 3. Separate Core Code from Scaffolding
|
||||
|
||||
Not all files are worth reading.
|
||||
|
||||
### Ignore (scaffolding)
|
||||
- `*.config.js`, `*.config.ts` — configuration, not logic
|
||||
- `dist/`, `build/`, `out/` — generated output
|
||||
- `node_modules/`, `vendor/`, `.venv/` — dependencies
|
||||
- `*.lock`, `yarn.lock`, `go.sum` — lock files
|
||||
- `LICENSE`, `CODEOWNERS`, `.editorconfig` — project meta
|
||||
- `test/fixtures/`, `test/data/` — test data
|
||||
|
||||
### Read (core)
|
||||
- Entry point file
|
||||
- Router/middleware/config handlers
|
||||
- Model/entity/schema definitions
|
||||
- Core algorithm or business logic files
|
||||
- Files referenced most in imports
|
||||
|
||||
### Hint: Follow imports
|
||||
|
||||
```
|
||||
entry file → import A → import B → core logic
|
||||
```
|
||||
|
||||
Each import is a dependency. Follow the chain until you hit a file that doesn't import anything else — that's usually the core.
|
||||
|
||||
## 4. Read Unfamiliar Framework Code
|
||||
|
||||
You don't know every framework. That's fine.
|
||||
|
||||
### Strategy
|
||||
|
||||
1. **Find the routing layer first.** Every framework has a way to map URLs or events to handlers. Find it. It tells you the project's capabilities.
|
||||
|
||||
2. **Follow ONE request end-to-end.** Don't try to understand all routes. Pick the simplest one (often "health check" or "get by ID") and trace it from entry to response.
|
||||
|
||||
3. **Identify the framework's conventions.** Most frameworks follow a pattern:
|
||||
- MVC: Controller → Model → View
|
||||
- Middleware: Request → Middleware chain → Handler → Response
|
||||
- Component: Parent renders children, props flow down, events flow up
|
||||
- Plugin: Core calls hooks, plugins register handlers
|
||||
|
||||
4. **Don't fight the framework's abstraction.** If the project uses ORM, don't look for raw SQL. If it uses dependency injection, don't look for `new()` calls. Understand what abstraction layer they chose.
|
||||
|
||||
5. **Use the framework's own docs.** If stuck on "how does this framework work?", check the official docs. Don't reverse-engineer what's documented.
|
||||
@@ -1,173 +0,0 @@
|
||||
# Flow Pattern Library
|
||||
|
||||
Common architecture patterns and how to identify them in code.
|
||||
|
||||
## MVC / MVVM / MVX
|
||||
|
||||
### What it is
|
||||
Separation of data (Model), UI/presentation (View), and coordination logic (Controller/ViewModel).
|
||||
|
||||
### File signatures
|
||||
| Pattern | Directories/Files |
|
||||
|---|---|
|
||||
| **MVC** | `controllers/`, `models/`, `views/` |
|
||||
| **MVVM** | `viewmodels/`, `views/`, `models/` |
|
||||
| **Layered** | `app/`, `domain/`, `infrastructure/` (Clean/Hexagonal) |
|
||||
|
||||
### Flow
|
||||
```
|
||||
Request → Controller → Model (data) → View (render) → Response
|
||||
```
|
||||
|
||||
### Key question
|
||||
"Does the file handle data, display, or coordination?" If yes → MVC-family.
|
||||
|
||||
---
|
||||
|
||||
## Middleware Chain
|
||||
|
||||
### What it is
|
||||
Each handler processes the request and passes it to the next. Like an assembly line.
|
||||
|
||||
### File signatures
|
||||
| Framework | Indicator |
|
||||
|---|---|---|
|
||||
| **Express/Koa** | `app.use(...)`, `app.get('/', handler)` |
|
||||
| **FastAPI** | `@app.middleware("http")`, `Depends()` |
|
||||
| **Next.js** | `middleware.ts` at root or in `app/` |
|
||||
| **Gin (Go)** | `router.Use(middleware1, middleware2)` |
|
||||
| **Koa** | `app.use(async (ctx, next) => { ... })` |
|
||||
|
||||
### Flow
|
||||
```
|
||||
Request → Middleware A → Middleware B → Handler → Response
|
||||
↓ ↓
|
||||
auth check log request
|
||||
```
|
||||
|
||||
### Key question
|
||||
"Does this function call `next()` or pass control to something else?" If yes → middleware.
|
||||
|
||||
### Common middleware order
|
||||
```
|
||||
1. CORS / Security headers
|
||||
2. Logging / Request ID
|
||||
3. Authentication / Authorization
|
||||
4. Body parsing / Validation
|
||||
5. Rate limiting
|
||||
6. Route handler
|
||||
7. Error handler (catches everything above)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Plugin / Extension System
|
||||
|
||||
### What it is
|
||||
Core provides hooks or interfaces. External code registers handlers. The core doesn't know about specific plugins.
|
||||
|
||||
### File signatures
|
||||
| Pattern | Indicator |
|
||||
|---|---|
|
||||
| **Hook-based** | `registerHook('eventName', handler)`, `hooks.on('event', fn)` |
|
||||
| **Interface-based** | Abstract class or interface that plugins implement |
|
||||
| **Discovery-based** | Directory scan (`plugins/`), import all, register by convention |
|
||||
| **VSCode-style** | `contributes` in `package.json`, activation events |
|
||||
|
||||
### Flow
|
||||
```
|
||||
Core starts
|
||||
↓
|
||||
Scans for plugins
|
||||
↓
|
||||
Each plugin registers itself
|
||||
↓
|
||||
Core fires hooks → plugins respond
|
||||
↓
|
||||
Core runs with extended capabilities
|
||||
```
|
||||
|
||||
### Key question
|
||||
"Can I add functionality without modifying core code?" If yes → plugin architecture.
|
||||
|
||||
---
|
||||
|
||||
## Event-Driven
|
||||
|
||||
### What it is
|
||||
Components communicate through events, not direct calls. Publishers emit, subscribers listen.
|
||||
|
||||
### File signatures
|
||||
| Pattern | Indicator |
|
||||
|---|---|
|
||||
| **Node EventEmitter** | `eventEmitter.on('event', handler)`, `eventEmitter.emit('event', data)` |
|
||||
| **Pub/Sub** | `pubsub.subscribe('channel', handler)`, `pubsub.publish('channel', data)` |
|
||||
| **Redux-style** | `dispatch(action)`, `reducer(state, action) → newState` |
|
||||
| **Observable** | `observable.subscribe(fn)`, `pipe(map, filter)` |
|
||||
| **Signals (Python)** | `@signal.connect`, `signal.send()` |
|
||||
|
||||
### Flow
|
||||
```
|
||||
Component A emits "user.created"
|
||||
↓
|
||||
Listener B hears it → sends welcome email
|
||||
Listener C hears it → creates default settings
|
||||
Listener D hears it → logs analytics
|
||||
```
|
||||
|
||||
### Key question
|
||||
"Does code communicate without importing or calling each other directly?" If yes → event-driven.
|
||||
|
||||
---
|
||||
|
||||
## State Management
|
||||
|
||||
### What it is
|
||||
Centralized storage for application state. Components read and update through defined interfaces.
|
||||
|
||||
### File signatures
|
||||
| Pattern | Indicator |
|
||||
|---|---|
|
||||
| **Redux** | `createStore()`, `dispatch()`, `useSelector()`, `@reduxjs/toolkit` |
|
||||
| **Zustand** | `create((set) => ({ ... }))` |
|
||||
| **Jotai** | `atom(value)`, `useAtom(atom)` |
|
||||
| **MobX** | `@observable`, `@action`, `@computed` |
|
||||
| **React Context** | `createContext()`, `useContext()`, `Provider` |
|
||||
| **Pinia (Vue)** | `defineStore()`, `state`, `actions` |
|
||||
|
||||
### Flow
|
||||
```
|
||||
Component dispatches action
|
||||
↓
|
||||
Reducer processes action + current state
|
||||
↓
|
||||
New state emitted
|
||||
↓
|
||||
Subscribed components re-render
|
||||
```
|
||||
|
||||
### Key question
|
||||
"Where does the app store data that multiple components need?" If it's a single store → state management pattern.
|
||||
|
||||
---
|
||||
|
||||
## Pipeline / Chain of Responsibility
|
||||
|
||||
### What it is
|
||||
Data flows through a series of processors. Each processor transforms the data and passes it on.
|
||||
|
||||
### File signatures
|
||||
| Pattern | Indicator |
|
||||
|---|---|
|
||||
| **Stream processing** | `.pipe(transform1).pipe(transform2)` |
|
||||
| **Compiler/lexer** | Source → Tokenize → Parse → Transform → Generate |
|
||||
| **Data pipeline** | `input → transform → validate → output` |
|
||||
| **Makefile** | Target depends on prerequisites, each is a step |
|
||||
|
||||
### Flow
|
||||
```
|
||||
Raw input → Tokenizer → Parser → Transformer → Generator → Output
|
||||
```
|
||||
|
||||
### Key question
|
||||
"Does data get progressively transformed through a fixed sequence of steps?" If yes → pipeline.
|
||||
@@ -1,101 +0,0 @@
|
||||
---
|
||||
name: follow
|
||||
description: Invoke when the user wants an interactive learning session based on an existing `/explore` or `/essence` report. Guides runnable or reader-style follow-along sessions. Not for fresh project analysis or pattern-only extraction.
|
||||
metadata:
|
||||
version: "0.5.0"
|
||||
---
|
||||
|
||||
# Follow: Guided Learning Session
|
||||
|
||||
Prefix your first line with 🥷 inline, not as its own paragraph.
|
||||
|
||||
You are a guide. The user wants to learn from a project step by step with help, context, and correction. You guide the learning process, but you do not replace it.
|
||||
|
||||
`/follow` is not a fresh project analyzer. It only works from an existing `/explore` or `/essence` result.
|
||||
|
||||
## Pre-check
|
||||
|
||||
`/follow` only works when there is already an `/explore` report or an `/essence` report.
|
||||
|
||||
- `/explore` report exists → use it as the main learning path
|
||||
- `/essence` report exists → use it for design-focused guided study
|
||||
- Neither exists → refuse clearly
|
||||
|
||||
Refusal behavior:
|
||||
"I need an existing `/explore` or `/essence` result before I can guide a follow-along session. Please run `/explore` for project understanding or `/essence` for a focused deep dive first."
|
||||
|
||||
Load the existing report before continuing.
|
||||
|
||||
## Mode Selection
|
||||
|
||||
After the pre-check, select one mode based on the prerequisite report:
|
||||
|
||||
- From `/explore` + code repository → default **Runnable**
|
||||
- From `/explore` + non-code repository → force **Reader**
|
||||
- From `/essence` → default **Reader** (user is in design-analysis state)
|
||||
|
||||
| Mode | When | Entry |
|
||||
|---|---|---|
|
||||
| **Runnable** | Report confirms the project is a runnable code repository and the user wants to learn by running and changing it | Start from environment and first execution |
|
||||
| **Reader** | Project has no runtime, or the user is studying design/architecture, or the prerequisite report is from `/essence` | Start from guided reading |
|
||||
|
||||
State the selected mode before proceeding. Do not re-scan the project — use the prerequisite report to decide.
|
||||
|
||||
## Teaching Interaction Rules
|
||||
|
||||
`/follow` must teach by guidance, not by dumping answers:
|
||||
- explain the purpose of the current step first
|
||||
- give the user an observation point or action point
|
||||
- ask the user to predict, try, or explain before revealing the answer
|
||||
- then reveal, correct, or deepen the explanation
|
||||
- never say "go read the code" as a standalone instruction. When referencing code, always start with: what design idea this code embodies, why it matters in the overall architecture, and what the user should pay attention to
|
||||
|
||||
## Runnable Check
|
||||
|
||||
Before Runnable mode, confirm from the **prerequisite report** (do not re-scan the project):
|
||||
- If the report identified the target as a code repository with a recognized runtime (`go.mod`, `pyproject.toml`, `Cargo.toml`, `Makefile`, `build.gradle`, `pom.xml`, `CMakeLists.txt`, etc.), proceed with Runnable.
|
||||
- If the report classified it as non-code, or no runtime entrypoint was found, switch to Reader and explain why.
|
||||
- If the prerequisite is `/essence`, confirm with the user: essence is design-focused, Reader is the natural fit. Allow Runnable only if the user explicitly insists.
|
||||
- Do not introduce a third mode.
|
||||
|
||||
## Runnable Mode Flow
|
||||
1. Confirm environment and prerequisites.
|
||||
2. Let the user run the project.
|
||||
3. Let the user make one safe change.
|
||||
4. Walk the main flow together.
|
||||
5. Give one small exercise.
|
||||
6. Review what they learned.
|
||||
|
||||
## Reader Mode Flow
|
||||
1. Frame the learning goal around a core design or architectural idea, not a single file.
|
||||
2. Walk through the design concept layer by layer: problem → approach → implementation → tradeoff.
|
||||
3. Ask the user questions that probe understanding ("Why did the author choose this approach over a simpler one?"), not just prediction ("What happens next?").
|
||||
4. Use diagrams or structured summaries to connect the dots between files and design ideas.
|
||||
5. Give one reasoning exercise that tests whether the user can apply the design pattern elsewhere.
|
||||
6. Review what they learned.
|
||||
|
||||
## Boundary Rules
|
||||
|
||||
`/follow` must:
|
||||
- depend on `/explore` or `/essence`
|
||||
- guide the user interactively
|
||||
- adapt between code and non-code repositories through Runnable or Reader emphasis
|
||||
|
||||
`/follow` must not:
|
||||
- rescan the whole project as a new analyzer
|
||||
- reference retired skills as prerequisites
|
||||
- add any third learning mode
|
||||
- execute commands or write code for the user
|
||||
|
||||
## Outcome
|
||||
|
||||
```
|
||||
Follow Session: {project name}
|
||||
Mode: runnable / reader
|
||||
Prerequisite report: /explore or /essence
|
||||
Exercise result: completed / partial / too hard
|
||||
Next direction: {suggested follow-up}
|
||||
Status: complete
|
||||
```
|
||||
|
||||
After the review, stop. Ask whether the user wants another exercise or wants to end the session.
|
||||
@@ -1,113 +0,0 @@
|
||||
# Environment Detection Rules
|
||||
|
||||
How to detect the runtime environment and guide the user through setup in `/follow`.
|
||||
|
||||
## Language Detection from Config
|
||||
|
||||
Check these files in order. The first match is the primary language.
|
||||
|
||||
| Config file | Language | Runtime check | Install command |
|
||||
|---|---|---|---|
|
||||
| `package.json` | JavaScript/TypeScript | `node --version` | nvm or official installer |
|
||||
| `pyproject.toml` | Python | `python --version` | pyenv or python.org |
|
||||
| `go.mod` | Go | `go version` | golang.org/dl |
|
||||
| `Cargo.toml` | Rust | `rustc --version` | rustup |
|
||||
| `pom.xml` | Java | `java -version` | SDKMAN or official |
|
||||
| `build.gradle` / `build.gradle.kts` | Java/Kotlin | `java -version` | SDKMAN |
|
||||
| `Gemfile` | Ruby | `ruby --version` | rvm or rbenv |
|
||||
| `*.csproj` | C#/.NET | `dotnet --version` | .NET SDK |
|
||||
| `CMakeLists.txt` | C/C++ | `gcc --version` or `clang --version` | System package manager |
|
||||
| `swift package.json` | Swift | `swift --version` | Xcode or swift.org |
|
||||
|
||||
## Dependency Installation
|
||||
|
||||
Once language is detected, guide the user:
|
||||
|
||||
### JavaScript/TypeScript
|
||||
```bash
|
||||
# Check which package manager is used
|
||||
if [ -f "yarn.lock" ]; then yarn install
|
||||
elif [ -f "pnpm-lock.yaml" ]; then pnpm install
|
||||
elif [ -f "bun.lockb" ] || [ -f "bun.lock" ]; then bun install
|
||||
else npm install
|
||||
fi
|
||||
```
|
||||
|
||||
### Python
|
||||
```bash
|
||||
# Modern Python projects
|
||||
pip install -e .
|
||||
# Or with requirements
|
||||
pip install -r requirements.txt
|
||||
# Or with poetry
|
||||
poetry install
|
||||
# Or with uv
|
||||
uv pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Go
|
||||
```bash
|
||||
go mod download
|
||||
```
|
||||
|
||||
### Rust
|
||||
```bash
|
||||
cargo build
|
||||
```
|
||||
|
||||
### Java (Maven)
|
||||
```bash
|
||||
mvn install
|
||||
```
|
||||
|
||||
### Java (Gradle)
|
||||
```bash
|
||||
./gradlew build
|
||||
# or
|
||||
gradle build
|
||||
```
|
||||
|
||||
## Run Command Detection
|
||||
|
||||
How to start the project:
|
||||
|
||||
| Source | Command |
|
||||
|---|---|
|
||||
| `package.json` → `scripts.dev` | `npm run dev` |
|
||||
| `package.json` → `scripts.start` | `npm start` |
|
||||
| `Makefile` → `dev` target | `make dev` |
|
||||
| `Makefile` → `run` target | `make run` |
|
||||
| `pyproject.toml` (Poetry) | `poetry run python main.py` |
|
||||
| `go.mod` → `package main` | `go run main.go` |
|
||||
| `Cargo.toml` → `[[bin]]` | `cargo run` |
|
||||
| `docker-compose.yml` exists | `docker-compose up` |
|
||||
| `Dockerfile` exists, no compose | `docker build -t app . && docker run app` |
|
||||
|
||||
## Common Environment Issues
|
||||
|
||||
| Error | Cause | Fix |
|
||||
|---|---|---|
|
||||
| `command not found: node` | Node.js not installed | Install Node.js (recommend LTS) |
|
||||
| `ModuleNotFoundError` | Python deps not installed | Run `pip install -r requirements.txt` |
|
||||
| `EACCES: permission denied` | Global install without sudo | Use nvm/fnm, or prefix with sudo |
|
||||
| `ENOENT: no such file` | Wrong working directory | `cd` to project root first |
|
||||
| `port already in use` | Another process on same port | Kill the process or use different port |
|
||||
| `go: cannot find main module` | Outside Go module | `cd` to directory with `go.mod` |
|
||||
| `error: could not find Cargo.toml` | Outside Rust project | `cd` to directory with `Cargo.toml` |
|
||||
| `java.lang.UnsupportedClassVersionError` | Wrong Java version | Match JDK version to project requirement |
|
||||
| `npm ERR! code ERESOLVE` | Dependency conflict | Try `npm install --legacy-peer-deps` |
|
||||
|
||||
## Detection Script for /follow
|
||||
|
||||
```bash
|
||||
# Quick environment check
|
||||
echo "=== Environment ==="
|
||||
node --version 2>/dev/null || echo "Node.js: not installed"
|
||||
python --version 2>/dev/null || echo "Python: not installed"
|
||||
go version 2>/dev/null || echo "Go: not installed"
|
||||
rustc --version 2>/dev/null || echo "Rust: not installed"
|
||||
java -version 2>/dev/null || echo "Java: not installed"
|
||||
echo "PWD: $(pwd)"
|
||||
```
|
||||
|
||||
Run this at the start of `/follow` Step 1 to understand what's available.
|
||||
@@ -1,57 +0,0 @@
|
||||
# Frontend Design — Complete Guidance
|
||||
|
||||
This document provides a comprehensive framework for creating visually distinctive, non-templated UI designs. Here's the full breakdown:
|
||||
|
||||
## Foundational Approach
|
||||
|
||||
Act as the design lead for a studio known for unique client identities — the client has already turned down template-like proposals. Every choice about palette, typography, and layout must be specific to the brief, including "one real aesthetic risk you can justify."
|
||||
|
||||
## Grounding in Subject Matter
|
||||
|
||||
If the brief is vague about the product or subject, pin it down yourself: name the subject, its audience, and the page's single job. Draw inspiration from "the subject's own world, its materials, instruments, artifacts, and vernacular." Use any known context about the human's preferences or past designs as hints.
|
||||
|
||||
## Design Principles
|
||||
|
||||
- **Hero as thesis**: Open with "the most characteristic thing in the subject's world" — avoid default choices like a big number with a small label and gradient accent unless truly optimal.
|
||||
- **Typography**: Pair display and body faces deliberately, not from your usual repertoire. Set a clear type scale with intentional weights, widths, and spacing. "Make the type treatment itself a memorable part of the design."
|
||||
- **Structure as information**: Numbering, eyebrows, dividers must encode something true about the content. Question whether numbered markers (01/02/03) actually make sense before using them — only appropriate for real sequences.
|
||||
- **Motion**: Consider where animation serves the subject. "An orchestrated moment usually lands harder than scattered effects." Sometimes less is better to avoid an AI-generated feel.
|
||||
- **Complexity**: Match execution to the vision — maximalist needs elaborate execution, minimal needs precision.
|
||||
- **Content**: Come up with copy if the brief lacks it. Poor copy makes a design feel as templated as poor layout.
|
||||
|
||||
## AI-Generated Design Traps
|
||||
|
||||
Three common AI-default looks to watch for: (1) warm cream background (~#F4F1EA) with serif display and terracotta accent; (2) near-black with bright acid-green or vermilion; (3) broadsheet layout with hairline rules, zero border-radius, and dense columns. "All three are legitimate for some briefs, but they are defaults rather than choices." Where the brief leaves an axis free, don't spend that freedom on a default.
|
||||
|
||||
## Two-Pass Process
|
||||
|
||||
**Pass 1 — Plan**: Create a compact token system:
|
||||
|
||||
1. **Color**: 4–6 named hex values
|
||||
2. **Type**: Characterful display face (used with restraint), complementary body face, utility face for captions/data
|
||||
3. **Layout**: One-sentence prose descriptions + ASCII wireframes
|
||||
4. **Signature**: The single unique element the page will be remembered by
|
||||
|
||||
Review the plan against the brief. If any part reads like what you'd produce for any similar page, revise it. Only then write code.
|
||||
|
||||
**Pass 2 — Build**: Follow the revised plan exactly. Watch for CSS selector specificity conflicts (e.g., `.section` and `.cta` fighting over padding/margins). Do most planning internally, only sharing ideas when confident.
|
||||
|
||||
## Restraint & Self-Critique
|
||||
|
||||
"Spend your boldness in one place" — let the signature element be the one memorable thing; keep everything else quiet. "Not taking a risk can be a risk itself!" Build responsively down to mobile, with visible keyboard focus and reduced motion respected. Critique as you build. Follow Chanel's advice: before finishing, remove one accessory. Jot notes about what you've tried to avoid repeating yourself.
|
||||
|
||||
## Writing in Design
|
||||
|
||||
Words exist to make the design understandable and usable — they're "design material, not decoration." Write from the end user's perspective, naming things by what people control and recognize, never by how the system is built.
|
||||
|
||||
- Use active voice as default
|
||||
- A control should say exactly what happens: "Save changes," not "Submit"
|
||||
- Maintain consistent vocabulary throughout flows (button says "Publish," toast says "Published")
|
||||
- Treat errors as guidance, not mood — explain what went wrong and how to fix it
|
||||
- Empty screens are invitations to act
|
||||
- Keep the register conversational: "plain verbs, sentence case, no filler"
|
||||
- Let each element do exactly one job — "a label labels, an example demonstrates"
|
||||
|
||||
## License
|
||||
|
||||
Apache License 2.0 — see LICENSE.txt
|
||||
@@ -1,83 +0,0 @@
|
||||
---
|
||||
name: gitnexus-cli
|
||||
description: "Use when the user needs to run GitNexus CLI commands like analyze/index a repo, check status, clean the index, generate a wiki, or list indexed repos. Examples: \"Index this repo\", \"Reanalyze the codebase\", \"Generate a wiki\""
|
||||
---
|
||||
|
||||
# GitNexus CLI Commands
|
||||
|
||||
All commands work via `npx` — no global install required.
|
||||
|
||||
## Commands
|
||||
|
||||
### analyze — Build or refresh the index
|
||||
|
||||
```bash
|
||||
npx gitnexus analyze
|
||||
```
|
||||
|
||||
Run from the project root. This parses all source files, builds the knowledge graph, writes it to `.gitnexus/`, and generates AGENTS.md / AGENTS.md context files.
|
||||
|
||||
| Flag | Effect |
|
||||
| -------------- | ---------------------------------------------------------------- |
|
||||
| `--force` | Force full re-index even if up to date |
|
||||
| `--embeddings` | Enable embedding generation for semantic search (off by default) |
|
||||
| `--drop-embeddings` | Drop existing embeddings on rebuild. By default, an `analyze` without `--embeddings` preserves them. |
|
||||
|
||||
**When to run:** First time in a project, after major code changes, or when `gitnexus://repo/{name}/context` reports the index is stale. In Codex, a PostToolUse hook detects staleness after `git commit` and `git merge` and notifies the agent to run `analyze` — the hook does not run analyze itself, to avoid blocking the agent for up to 120s and risking KuzuDB corruption on timeout.
|
||||
|
||||
### status — Check index freshness
|
||||
|
||||
```bash
|
||||
npx gitnexus status
|
||||
```
|
||||
|
||||
Shows whether the current repo has a GitNexus index, when it was last updated, and symbol/relationship counts. Use this to check if re-indexing is needed.
|
||||
|
||||
### clean — Delete the index
|
||||
|
||||
```bash
|
||||
npx gitnexus clean
|
||||
```
|
||||
|
||||
Deletes the `.gitnexus/` directory and unregisters the repo from the global registry. Use before re-indexing if the index is corrupt or after removing GitNexus from a project.
|
||||
|
||||
| Flag | Effect |
|
||||
| --------- | ------------------------------------------------- |
|
||||
| `--force` | Skip confirmation prompt |
|
||||
| `--all` | Clean all indexed repos, not just the current one |
|
||||
|
||||
### wiki — Generate documentation from the graph
|
||||
|
||||
```bash
|
||||
npx gitnexus wiki
|
||||
```
|
||||
|
||||
Generates repository documentation from the knowledge graph using an LLM. Requires an API key (saved to `~/.gitnexus/config.json` on first use).
|
||||
|
||||
| Flag | Effect |
|
||||
| ------------------- | ----------------------------------------- |
|
||||
| `--force` | Force full regeneration |
|
||||
| `--model <model>` | LLM model (default: minimax/minimax-m2.5) |
|
||||
| `--base-url <url>` | LLM API base URL |
|
||||
| `--api-key <key>` | LLM API key |
|
||||
| `--concurrency <n>` | Parallel LLM calls (default: 3) |
|
||||
| `--gist` | Publish wiki as a public GitHub Gist |
|
||||
|
||||
### list — Show all indexed repos
|
||||
|
||||
```bash
|
||||
npx gitnexus list
|
||||
```
|
||||
|
||||
Lists all repositories registered in `~/.gitnexus/registry.json`. The MCP `list_repos` tool provides the same information.
|
||||
|
||||
## After Indexing
|
||||
|
||||
1. **Read `gitnexus://repo/{name}/context`** to verify the index loaded
|
||||
2. Use the other GitNexus skills (`exploring`, `debugging`, `impact-analysis`, `refactoring`) for your task
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **"Not inside a git repository"**: Run from a directory inside a git repo
|
||||
- **Index is stale after re-analyzing**: Restart Codex to reload the MCP server
|
||||
- **Embeddings slow**: Omit `--embeddings` (it's off by default) or set `OPENAI_API_KEY` for faster API-based embedding
|
||||
@@ -1,89 +0,0 @@
|
||||
---
|
||||
name: gitnexus-debugging
|
||||
description: "Use when the user is debugging a bug, tracing an error, or asking why something fails. Examples: \"Why is X failing?\", \"Where does this error come from?\", \"Trace this bug\""
|
||||
---
|
||||
|
||||
# Debugging with GitNexus
|
||||
|
||||
## When to Use
|
||||
|
||||
- "Why is this function failing?"
|
||||
- "Trace where this error comes from"
|
||||
- "Who calls this method?"
|
||||
- "This endpoint returns 500"
|
||||
- Investigating bugs, errors, or unexpected behavior
|
||||
|
||||
## Workflow
|
||||
|
||||
```
|
||||
1. gitnexus_query({query: "<error or symptom>"}) → Find related execution flows
|
||||
2. gitnexus_context({name: "<suspect>"}) → See callers/callees/processes
|
||||
3. READ gitnexus://repo/{name}/process/{name} → Trace execution flow
|
||||
4. gitnexus_cypher({query: "MATCH path..."}) → Custom traces if needed
|
||||
```
|
||||
|
||||
> If "Index is stale" → run `npx gitnexus analyze` in terminal.
|
||||
|
||||
## Checklist
|
||||
|
||||
```
|
||||
- [ ] Understand the symptom (error message, unexpected behavior)
|
||||
- [ ] gitnexus_query for error text or related code
|
||||
- [ ] Identify the suspect function from returned processes
|
||||
- [ ] gitnexus_context to see callers and callees
|
||||
- [ ] Trace execution flow via process resource if applicable
|
||||
- [ ] gitnexus_cypher for custom call chain traces if needed
|
||||
- [ ] Read source files to confirm root cause
|
||||
```
|
||||
|
||||
## Debugging Patterns
|
||||
|
||||
| Symptom | GitNexus Approach |
|
||||
| -------------------- | ---------------------------------------------------------- |
|
||||
| Error message | `gitnexus_query` for error text → `context` on throw sites |
|
||||
| Wrong return value | `context` on the function → trace callees for data flow |
|
||||
| Intermittent failure | `context` → look for external calls, async deps |
|
||||
| Performance issue | `context` → find symbols with many callers (hot paths) |
|
||||
| Recent regression | `detect_changes` to see what your changes affect |
|
||||
|
||||
## Tools
|
||||
|
||||
**gitnexus_query** — find code related to error:
|
||||
|
||||
```
|
||||
gitnexus_query({query: "payment validation error"})
|
||||
→ Processes: CheckoutFlow, ErrorHandling
|
||||
→ Symbols: validatePayment, handlePaymentError, PaymentException
|
||||
```
|
||||
|
||||
**gitnexus_context** — full context for a suspect:
|
||||
|
||||
```
|
||||
gitnexus_context({name: "validatePayment"})
|
||||
→ Incoming calls: processCheckout, webhookHandler
|
||||
→ Outgoing calls: verifyCard, fetchRates (external API!)
|
||||
→ Processes: CheckoutFlow (step 3/7)
|
||||
```
|
||||
|
||||
**gitnexus_cypher** — custom call chain traces:
|
||||
|
||||
```cypher
|
||||
MATCH path = (a)-[:CodeRelation {type: 'CALLS'}*1..2]->(b:Function {name: "validatePayment"})
|
||||
RETURN [n IN nodes(path) | n.name] AS chain
|
||||
```
|
||||
|
||||
## Example: "Payment endpoint returns 500 intermittently"
|
||||
|
||||
```
|
||||
1. gitnexus_query({query: "payment error handling"})
|
||||
→ Processes: CheckoutFlow, ErrorHandling
|
||||
→ Symbols: validatePayment, handlePaymentError
|
||||
|
||||
2. gitnexus_context({name: "validatePayment"})
|
||||
→ Outgoing calls: verifyCard, fetchRates (external API!)
|
||||
|
||||
3. READ gitnexus://repo/my-app/process/CheckoutFlow
|
||||
→ Step 3: validatePayment → calls fetchRates (external)
|
||||
|
||||
4. Root cause: fetchRates calls external API without proper timeout
|
||||
```
|
||||
@@ -1,78 +0,0 @@
|
||||
---
|
||||
name: gitnexus-exploring
|
||||
description: "Use when the user asks how code works, wants to understand architecture, trace execution flows, or explore unfamiliar parts of the codebase. Examples: \"How does X work?\", \"What calls this function?\", \"Show me the auth flow\""
|
||||
---
|
||||
|
||||
# Exploring Codebases with GitNexus
|
||||
|
||||
## When to Use
|
||||
|
||||
- "How does authentication work?"
|
||||
- "What's the project structure?"
|
||||
- "Show me the main components"
|
||||
- "Where is the database logic?"
|
||||
- Understanding code you haven't seen before
|
||||
|
||||
## Workflow
|
||||
|
||||
```
|
||||
1. READ gitnexus://repos → Discover indexed repos
|
||||
2. READ gitnexus://repo/{name}/context → Codebase overview, check staleness
|
||||
3. gitnexus_query({query: "<what you want to understand>"}) → Find related execution flows
|
||||
4. gitnexus_context({name: "<symbol>"}) → Deep dive on specific symbol
|
||||
5. READ gitnexus://repo/{name}/process/{name} → Trace full execution flow
|
||||
```
|
||||
|
||||
> If step 2 says "Index is stale" → run `npx gitnexus analyze` in terminal.
|
||||
|
||||
## Checklist
|
||||
|
||||
```
|
||||
- [ ] READ gitnexus://repo/{name}/context
|
||||
- [ ] gitnexus_query for the concept you want to understand
|
||||
- [ ] Review returned processes (execution flows)
|
||||
- [ ] gitnexus_context on key symbols for callers/callees
|
||||
- [ ] READ process resource for full execution traces
|
||||
- [ ] Read source files for implementation details
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
| Resource | What you get |
|
||||
| --------------------------------------- | ------------------------------------------------------- |
|
||||
| `gitnexus://repo/{name}/context` | Stats, staleness warning (~150 tokens) |
|
||||
| `gitnexus://repo/{name}/clusters` | All functional areas with cohesion scores (~300 tokens) |
|
||||
| `gitnexus://repo/{name}/cluster/{name}` | Area members with file paths (~500 tokens) |
|
||||
| `gitnexus://repo/{name}/process/{name}` | Step-by-step execution trace (~200 tokens) |
|
||||
|
||||
## Tools
|
||||
|
||||
**gitnexus_query** — find execution flows related to a concept:
|
||||
|
||||
```
|
||||
gitnexus_query({query: "payment processing"})
|
||||
→ Processes: CheckoutFlow, RefundFlow, WebhookHandler
|
||||
→ Symbols grouped by flow with file locations
|
||||
```
|
||||
|
||||
**gitnexus_context** — 360-degree view of a symbol:
|
||||
|
||||
```
|
||||
gitnexus_context({name: "validateUser"})
|
||||
→ Incoming calls: loginHandler, apiMiddleware
|
||||
→ Outgoing calls: checkToken, getUserById
|
||||
→ Processes: LoginFlow (step 2/5), TokenRefresh (step 1/3)
|
||||
```
|
||||
|
||||
## Example: "How does payment processing work?"
|
||||
|
||||
```
|
||||
1. READ gitnexus://repo/my-app/context → 918 symbols, 45 processes
|
||||
2. gitnexus_query({query: "payment processing"})
|
||||
→ CheckoutFlow: processPayment → validateCard → chargeStripe
|
||||
→ RefundFlow: initiateRefund → calculateRefund → processRefund
|
||||
3. gitnexus_context({name: "processPayment"})
|
||||
→ Incoming: checkoutHandler, webhookHandler
|
||||
→ Outgoing: validateCard, chargeStripe, saveTransaction
|
||||
4. Read src/payments/processor.ts for implementation details
|
||||
```
|
||||
@@ -1,64 +0,0 @@
|
||||
---
|
||||
name: gitnexus-guide
|
||||
description: "Use when the user asks about GitNexus itself — available tools, how to query the knowledge graph, MCP resources, graph schema, or workflow reference. Examples: \"What GitNexus tools are available?\", \"How do I use GitNexus?\""
|
||||
---
|
||||
|
||||
# GitNexus Guide
|
||||
|
||||
Quick reference for all GitNexus MCP tools, resources, and the knowledge graph schema.
|
||||
|
||||
## Always Start Here
|
||||
|
||||
For any task involving code understanding, debugging, impact analysis, or refactoring:
|
||||
|
||||
1. **Read `gitnexus://repo/{name}/context`** — codebase overview + check index freshness
|
||||
2. **Match your task to a skill below** and **read that skill file**
|
||||
3. **Follow the skill's workflow and checklist**
|
||||
|
||||
> If step 1 warns the index is stale, run `npx gitnexus analyze` in the terminal first.
|
||||
|
||||
## Skills
|
||||
|
||||
| Task | Skill to read |
|
||||
| -------------------------------------------- | ------------------- |
|
||||
| Understand architecture / "How does X work?" | `gitnexus-exploring` |
|
||||
| Blast radius / "What breaks if I change X?" | `gitnexus-impact-analysis` |
|
||||
| Trace bugs / "Why is X failing?" | `gitnexus-debugging` |
|
||||
| Rename / extract / split / refactor | `gitnexus-refactoring` |
|
||||
| Tools, resources, schema reference | `gitnexus-guide` (this file) |
|
||||
| Index, status, clean, wiki CLI commands | `gitnexus-cli` |
|
||||
|
||||
## Tools Reference
|
||||
|
||||
| Tool | What it gives you |
|
||||
| ---------------- | ------------------------------------------------------------------------ |
|
||||
| `query` | Process-grouped code intelligence — execution flows related to a concept |
|
||||
| `context` | 360-degree symbol view — categorized refs, processes it participates in |
|
||||
| `impact` | Symbol blast radius — what breaks at depth 1/2/3 with confidence |
|
||||
| `detect_changes` | Git-diff impact — what do your current changes affect |
|
||||
| `rename` | Multi-file coordinated rename with confidence-tagged edits |
|
||||
| `cypher` | Raw graph queries (read `gitnexus://repo/{name}/schema` first) |
|
||||
| `list_repos` | Discover indexed repos |
|
||||
|
||||
## Resources Reference
|
||||
|
||||
Lightweight reads (~100-500 tokens) for navigation:
|
||||
|
||||
| Resource | Content |
|
||||
| ---------------------------------------------- | ----------------------------------------- |
|
||||
| `gitnexus://repo/{name}/context` | Stats, staleness check |
|
||||
| `gitnexus://repo/{name}/clusters` | All functional areas with cohesion scores |
|
||||
| `gitnexus://repo/{name}/cluster/{clusterName}` | Area members |
|
||||
| `gitnexus://repo/{name}/processes` | All execution flows |
|
||||
| `gitnexus://repo/{name}/process/{processName}` | Step-by-step trace |
|
||||
| `gitnexus://repo/{name}/schema` | Graph schema for Cypher |
|
||||
|
||||
## Graph Schema
|
||||
|
||||
**Nodes:** File, Function, Class, Interface, Method, Community, Process
|
||||
**Edges (via CodeRelation.type):** CALLS, IMPORTS, EXTENDS, IMPLEMENTS, DEFINES, MEMBER_OF, STEP_IN_PROCESS
|
||||
|
||||
```cypher
|
||||
MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "myFunc"})
|
||||
RETURN caller.name, caller.filePath
|
||||
```
|
||||
@@ -1,97 +0,0 @@
|
||||
---
|
||||
name: gitnexus-impact-analysis
|
||||
description: "Use when the user wants to know what will break if they change something, or needs safety analysis before editing code. Examples: \"Is it safe to change X?\", \"What depends on this?\", \"What will break?\""
|
||||
---
|
||||
|
||||
# Impact Analysis with GitNexus
|
||||
|
||||
## When to Use
|
||||
|
||||
- "Is it safe to change this function?"
|
||||
- "What will break if I modify X?"
|
||||
- "Show me the blast radius"
|
||||
- "Who uses this code?"
|
||||
- Before making non-trivial code changes
|
||||
- Before committing — to understand what your changes affect
|
||||
|
||||
## Workflow
|
||||
|
||||
```
|
||||
1. gitnexus_impact({target: "X", direction: "upstream"}) → What depends on this
|
||||
2. READ gitnexus://repo/{name}/processes → Check affected execution flows
|
||||
3. gitnexus_detect_changes() → Map current git changes to affected flows
|
||||
4. Assess risk and report to user
|
||||
```
|
||||
|
||||
> If "Index is stale" → run `npx gitnexus analyze` in terminal.
|
||||
|
||||
## Checklist
|
||||
|
||||
```
|
||||
- [ ] gitnexus_impact({target, direction: "upstream"}) to find dependents
|
||||
- [ ] Review d=1 items first (these WILL BREAK)
|
||||
- [ ] Check high-confidence (>0.8) dependencies
|
||||
- [ ] READ processes to check affected execution flows
|
||||
- [ ] gitnexus_detect_changes() for pre-commit check
|
||||
- [ ] Assess risk level and report to user
|
||||
```
|
||||
|
||||
## Understanding Output
|
||||
|
||||
| Depth | Risk Level | Meaning |
|
||||
| ----- | ---------------- | ------------------------ |
|
||||
| d=1 | **WILL BREAK** | Direct callers/importers |
|
||||
| d=2 | LIKELY AFFECTED | Indirect dependencies |
|
||||
| d=3 | MAY NEED TESTING | Transitive effects |
|
||||
|
||||
## Risk Assessment
|
||||
|
||||
| Affected | Risk |
|
||||
| ------------------------------ | -------- |
|
||||
| <5 symbols, few processes | LOW |
|
||||
| 5-15 symbols, 2-5 processes | MEDIUM |
|
||||
| >15 symbols or many processes | HIGH |
|
||||
| Critical path (auth, payments) | CRITICAL |
|
||||
|
||||
## Tools
|
||||
|
||||
**gitnexus_impact** — the primary tool for symbol blast radius:
|
||||
|
||||
```
|
||||
gitnexus_impact({
|
||||
target: "validateUser",
|
||||
direction: "upstream",
|
||||
minConfidence: 0.8,
|
||||
maxDepth: 3
|
||||
})
|
||||
|
||||
→ d=1 (WILL BREAK):
|
||||
- loginHandler (src/auth/login.ts:42) [CALLS, 100%]
|
||||
- apiMiddleware (src/api/middleware.ts:15) [CALLS, 100%]
|
||||
|
||||
→ d=2 (LIKELY AFFECTED):
|
||||
- authRouter (src/routes/auth.ts:22) [CALLS, 95%]
|
||||
```
|
||||
|
||||
**gitnexus_detect_changes** — git-diff based impact analysis:
|
||||
|
||||
```
|
||||
gitnexus_detect_changes({scope: "staged"})
|
||||
|
||||
→ Changed: 5 symbols in 3 files
|
||||
→ Affected: LoginFlow, TokenRefresh, APIMiddlewarePipeline
|
||||
→ Risk: MEDIUM
|
||||
```
|
||||
|
||||
## Example: "What breaks if I change validateUser?"
|
||||
|
||||
```
|
||||
1. gitnexus_impact({target: "validateUser", direction: "upstream"})
|
||||
→ d=1: loginHandler, apiMiddleware (WILL BREAK)
|
||||
→ d=2: authRouter, sessionManager (LIKELY AFFECTED)
|
||||
|
||||
2. READ gitnexus://repo/my-app/processes
|
||||
→ LoginFlow and TokenRefresh touch validateUser
|
||||
|
||||
3. Risk: 2 direct callers, 2 processes = MEDIUM
|
||||
```
|
||||
@@ -1,121 +0,0 @@
|
||||
---
|
||||
name: gitnexus-refactoring
|
||||
description: "Use when the user wants to rename, extract, split, move, or restructure code safely. Examples: \"Rename this function\", \"Extract this into a module\", \"Refactor this class\", \"Move this to a separate file\""
|
||||
---
|
||||
|
||||
# Refactoring with GitNexus
|
||||
|
||||
## When to Use
|
||||
|
||||
- "Rename this function safely"
|
||||
- "Extract this into a module"
|
||||
- "Split this service"
|
||||
- "Move this to a new file"
|
||||
- Any task involving renaming, extracting, splitting, or restructuring code
|
||||
|
||||
## Workflow
|
||||
|
||||
```
|
||||
1. gitnexus_impact({target: "X", direction: "upstream"}) → Map all dependents
|
||||
2. gitnexus_query({query: "X"}) → Find execution flows involving X
|
||||
3. gitnexus_context({name: "X"}) → See all incoming/outgoing refs
|
||||
4. Plan update order: interfaces → implementations → callers → tests
|
||||
```
|
||||
|
||||
> If "Index is stale" → run `npx gitnexus analyze` in terminal.
|
||||
|
||||
## Checklists
|
||||
|
||||
### Rename Symbol
|
||||
|
||||
```
|
||||
- [ ] gitnexus_rename({symbol_name: "oldName", new_name: "newName", dry_run: true}) — preview all edits
|
||||
- [ ] Review graph edits (high confidence) and ast_search edits (review carefully)
|
||||
- [ ] If satisfied: gitnexus_rename({..., dry_run: false}) — apply edits
|
||||
- [ ] gitnexus_detect_changes() — verify only expected files changed
|
||||
- [ ] Run tests for affected processes
|
||||
```
|
||||
|
||||
### Extract Module
|
||||
|
||||
```
|
||||
- [ ] gitnexus_context({name: target}) — see all incoming/outgoing refs
|
||||
- [ ] gitnexus_impact({target, direction: "upstream"}) — find all external callers
|
||||
- [ ] Define new module interface
|
||||
- [ ] Extract code, update imports
|
||||
- [ ] gitnexus_detect_changes() — verify affected scope
|
||||
- [ ] Run tests for affected processes
|
||||
```
|
||||
|
||||
### Split Function/Service
|
||||
|
||||
```
|
||||
- [ ] gitnexus_context({name: target}) — understand all callees
|
||||
- [ ] Group callees by responsibility
|
||||
- [ ] gitnexus_impact({target, direction: "upstream"}) — map callers to update
|
||||
- [ ] Create new functions/services
|
||||
- [ ] Update callers
|
||||
- [ ] gitnexus_detect_changes() — verify affected scope
|
||||
- [ ] Run tests for affected processes
|
||||
```
|
||||
|
||||
## Tools
|
||||
|
||||
**gitnexus_rename** — automated multi-file rename:
|
||||
|
||||
```
|
||||
gitnexus_rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: true})
|
||||
→ 12 edits across 8 files
|
||||
→ 10 graph edits (high confidence), 2 ast_search edits (review)
|
||||
→ Changes: [{file_path, edits: [{line, old_text, new_text, confidence}]}]
|
||||
```
|
||||
|
||||
**gitnexus_impact** — map all dependents first:
|
||||
|
||||
```
|
||||
gitnexus_impact({target: "validateUser", direction: "upstream"})
|
||||
→ d=1: loginHandler, apiMiddleware, testUtils
|
||||
→ Affected Processes: LoginFlow, TokenRefresh
|
||||
```
|
||||
|
||||
**gitnexus_detect_changes** — verify your changes after refactoring:
|
||||
|
||||
```
|
||||
gitnexus_detect_changes({scope: "all"})
|
||||
→ Changed: 8 files, 12 symbols
|
||||
→ Affected processes: LoginFlow, TokenRefresh
|
||||
→ Risk: MEDIUM
|
||||
```
|
||||
|
||||
**gitnexus_cypher** — custom reference queries:
|
||||
|
||||
```cypher
|
||||
MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "validateUser"})
|
||||
RETURN caller.name, caller.filePath ORDER BY caller.filePath
|
||||
```
|
||||
|
||||
## Risk Rules
|
||||
|
||||
| Risk Factor | Mitigation |
|
||||
| ------------------- | ----------------------------------------- |
|
||||
| Many callers (>5) | Use gitnexus_rename for automated updates |
|
||||
| Cross-area refs | Use detect_changes after to verify scope |
|
||||
| String/dynamic refs | gitnexus_query to find them |
|
||||
| External/public API | Version and deprecate properly |
|
||||
|
||||
## Example: Rename `validateUser` to `authenticateUser`
|
||||
|
||||
```
|
||||
1. gitnexus_rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: true})
|
||||
→ 12 edits: 10 graph (safe), 2 ast_search (review)
|
||||
→ Files: validator.ts, login.ts, middleware.ts, config.json...
|
||||
|
||||
2. Review ast_search edits (config.json: dynamic reference!)
|
||||
|
||||
3. gitnexus_rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: false})
|
||||
→ Applied 12 edits across 8 files
|
||||
|
||||
4. gitnexus_detect_changes({scope: "all"})
|
||||
→ Affected: LoginFlow, TokenRefresh
|
||||
→ Risk: MEDIUM — run tests for these flows
|
||||
```
|
||||
@@ -1,16 +0,0 @@
|
||||
---
|
||||
name: handoff
|
||||
description: Compact the current conversation into a handoff document for another agent to pick up.
|
||||
argument-hint: "What will the next session be used for?"
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
Write a handoff document summarising the current conversation so a fresh agent can continue the work. Save to the temporary directory of the user's OS - not the current workspace.
|
||||
|
||||
Include a "suggested skills" section in the document, which suggests skills that the agent should invoke.
|
||||
|
||||
Do not duplicate content already captured in other artifacts (PRDs, plans, ADRs, issues, commits, diffs). Reference them by path or URL instead.
|
||||
|
||||
Redact any sensitive information, such as API keys, passwords, or personally identifiable information.
|
||||
|
||||
If the user passed arguments, treat them as a description of what the next session will focus on and tailor the doc accordingly.
|
||||
@@ -1,156 +0,0 @@
|
||||
---
|
||||
name: openspec-apply-change
|
||||
description: Implement tasks from an OpenSpec change. Use when the user wants to start implementing, continue implementation, or work through tasks.
|
||||
license: MIT
|
||||
compatibility: Requires openspec CLI.
|
||||
metadata:
|
||||
author: openspec
|
||||
version: "1.0"
|
||||
generatedBy: "1.3.1"
|
||||
---
|
||||
|
||||
Implement tasks from an OpenSpec change.
|
||||
|
||||
**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
|
||||
|
||||
**Steps**
|
||||
|
||||
1. **Select the change**
|
||||
|
||||
If a name is provided, use it. Otherwise:
|
||||
- Infer from conversation context if the user mentioned a change
|
||||
- Auto-select if only one active change exists
|
||||
- If ambiguous, run `openspec list --json` to get available changes and use the **AskUserQuestion tool** to let the user select
|
||||
|
||||
Always announce: "Using change: <name>" and how to override (e.g., `/opsx:apply <other>`).
|
||||
|
||||
2. **Check status to understand the schema**
|
||||
```bash
|
||||
openspec status --change "<name>" --json
|
||||
```
|
||||
Parse the JSON to understand:
|
||||
- `schemaName`: The workflow being used (e.g., "spec-driven")
|
||||
- Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others)
|
||||
|
||||
3. **Get apply instructions**
|
||||
|
||||
```bash
|
||||
openspec instructions apply --change "<name>" --json
|
||||
```
|
||||
|
||||
This returns:
|
||||
- `contextFiles`: artifact ID -> array of concrete file paths (varies by schema - could be proposal/specs/design/tasks or spec/tests/implementation/docs)
|
||||
- Progress (total, complete, remaining)
|
||||
- Task list with status
|
||||
- Dynamic instruction based on current state
|
||||
|
||||
**Handle states:**
|
||||
- If `state: "blocked"` (missing artifacts): show message, suggest using openspec-continue-change
|
||||
- If `state: "all_done"`: congratulate, suggest archive
|
||||
- Otherwise: proceed to implementation
|
||||
|
||||
4. **Read context files**
|
||||
|
||||
Read every file path listed under `contextFiles` from the apply instructions output.
|
||||
The files depend on the schema being used:
|
||||
- **spec-driven**: proposal, specs, design, tasks
|
||||
- Other schemas: follow the contextFiles from CLI output
|
||||
|
||||
5. **Show current progress**
|
||||
|
||||
Display:
|
||||
- Schema being used
|
||||
- Progress: "N/M tasks complete"
|
||||
- Remaining tasks overview
|
||||
- Dynamic instruction from CLI
|
||||
|
||||
6. **Implement tasks (loop until done or blocked)**
|
||||
|
||||
For each pending task:
|
||||
- Show which task is being worked on
|
||||
- Make the code changes required
|
||||
- Keep changes minimal and focused
|
||||
- Mark task complete in the tasks file: `- [ ]` → `- [x]`
|
||||
- Continue to next task
|
||||
|
||||
**Pause if:**
|
||||
- Task is unclear → ask for clarification
|
||||
- Implementation reveals a design issue → suggest updating artifacts
|
||||
- Error or blocker encountered → report and wait for guidance
|
||||
- User interrupts
|
||||
|
||||
7. **On completion or pause, show status**
|
||||
|
||||
Display:
|
||||
- Tasks completed this session
|
||||
- Overall progress: "N/M tasks complete"
|
||||
- If all done: suggest archive
|
||||
- If paused: explain why and wait for guidance
|
||||
|
||||
**Output During Implementation**
|
||||
|
||||
```
|
||||
## Implementing: <change-name> (schema: <schema-name>)
|
||||
|
||||
Working on task 3/7: <task description>
|
||||
[...implementation happening...]
|
||||
✓ Task complete
|
||||
|
||||
Working on task 4/7: <task description>
|
||||
[...implementation happening...]
|
||||
✓ Task complete
|
||||
```
|
||||
|
||||
**Output On Completion**
|
||||
|
||||
```
|
||||
## Implementation Complete
|
||||
|
||||
**Change:** <change-name>
|
||||
**Schema:** <schema-name>
|
||||
**Progress:** 7/7 tasks complete ✓
|
||||
|
||||
### Completed This Session
|
||||
- [x] Task 1
|
||||
- [x] Task 2
|
||||
...
|
||||
|
||||
All tasks complete! Ready to archive this change.
|
||||
```
|
||||
|
||||
**Output On Pause (Issue Encountered)**
|
||||
|
||||
```
|
||||
## Implementation Paused
|
||||
|
||||
**Change:** <change-name>
|
||||
**Schema:** <schema-name>
|
||||
**Progress:** 4/7 tasks complete
|
||||
|
||||
### Issue Encountered
|
||||
<description of the issue>
|
||||
|
||||
**Options:**
|
||||
1. <option 1>
|
||||
2. <option 2>
|
||||
3. Other approach
|
||||
|
||||
What would you like to do?
|
||||
```
|
||||
|
||||
**Guardrails**
|
||||
- Keep going through tasks until done or blocked
|
||||
- Always read context files before starting (from the apply instructions output)
|
||||
- If task is ambiguous, pause and ask before implementing
|
||||
- If implementation reveals issues, pause and suggest artifact updates
|
||||
- Keep code changes minimal and scoped to each task
|
||||
- Update task checkbox immediately after completing each task
|
||||
- Pause on errors, blockers, or unclear requirements - don't guess
|
||||
- Use contextFiles from CLI output, don't assume specific file names
|
||||
|
||||
**Fluid Workflow Integration**
|
||||
|
||||
This skill supports the "actions on a change" model:
|
||||
|
||||
- **Can be invoked anytime**: Before all artifacts are done (if tasks exist), after partial implementation, interleaved with other actions
|
||||
- **Allows artifact updates**: If implementation reveals design issues, suggest updating artifacts - not phase-locked, work fluidly
|
||||
@@ -1,114 +0,0 @@
|
||||
---
|
||||
name: openspec-archive-change
|
||||
description: Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete.
|
||||
license: MIT
|
||||
compatibility: Requires openspec CLI.
|
||||
metadata:
|
||||
author: openspec
|
||||
version: "1.0"
|
||||
generatedBy: "1.3.1"
|
||||
---
|
||||
|
||||
Archive a completed change in the experimental workflow.
|
||||
|
||||
**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
|
||||
|
||||
**Steps**
|
||||
|
||||
1. **If no change name provided, prompt for selection**
|
||||
|
||||
Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.
|
||||
|
||||
Show only active changes (not already archived).
|
||||
Include the schema used for each change if available.
|
||||
|
||||
**IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.
|
||||
|
||||
2. **Check artifact completion status**
|
||||
|
||||
Run `openspec status --change "<name>" --json` to check artifact completion.
|
||||
|
||||
Parse the JSON to understand:
|
||||
- `schemaName`: The workflow being used
|
||||
- `artifacts`: List of artifacts with their status (`done` or other)
|
||||
|
||||
**If any artifacts are not `done`:**
|
||||
- Display warning listing incomplete artifacts
|
||||
- Use **AskUserQuestion tool** to confirm user wants to proceed
|
||||
- Proceed if user confirms
|
||||
|
||||
3. **Check task completion status**
|
||||
|
||||
Read the tasks file (typically `tasks.md`) to check for incomplete tasks.
|
||||
|
||||
Count tasks marked with `- [ ]` (incomplete) vs `- [x]` (complete).
|
||||
|
||||
**If incomplete tasks found:**
|
||||
- Display warning showing count of incomplete tasks
|
||||
- Use **AskUserQuestion tool** to confirm user wants to proceed
|
||||
- Proceed if user confirms
|
||||
|
||||
**If no tasks file exists:** Proceed without task-related warning.
|
||||
|
||||
4. **Assess delta spec sync state**
|
||||
|
||||
Check for delta specs at `openspec/changes/<name>/specs/`. If none exist, proceed without sync prompt.
|
||||
|
||||
**If delta specs exist:**
|
||||
- Compare each delta spec with its corresponding main spec at `openspec/specs/<capability>/spec.md`
|
||||
- Determine what changes would be applied (adds, modifications, removals, renames)
|
||||
- Show a combined summary before prompting
|
||||
|
||||
**Prompt options:**
|
||||
- If changes needed: "Sync now (recommended)", "Archive without syncing"
|
||||
- If already synced: "Archive now", "Sync anyway", "Cancel"
|
||||
|
||||
If user chooses sync, use Task tool (subagent_type: "general-purpose", prompt: "Use Skill tool to invoke openspec-sync-specs for change '<name>'. Delta spec analysis: <include the analyzed delta spec summary>"). Proceed to archive regardless of choice.
|
||||
|
||||
5. **Perform the archive**
|
||||
|
||||
Create the archive directory if it doesn't exist:
|
||||
```bash
|
||||
mkdir -p openspec/changes/archive
|
||||
```
|
||||
|
||||
Generate target name using current date: `YYYY-MM-DD-<change-name>`
|
||||
|
||||
**Check if target already exists:**
|
||||
- If yes: Fail with error, suggest renaming existing archive or using different date
|
||||
- If no: Move the change directory to archive
|
||||
|
||||
```bash
|
||||
mv openspec/changes/<name> openspec/changes/archive/YYYY-MM-DD-<name>
|
||||
```
|
||||
|
||||
6. **Display summary**
|
||||
|
||||
Show archive completion summary including:
|
||||
- Change name
|
||||
- Schema that was used
|
||||
- Archive location
|
||||
- Whether specs were synced (if applicable)
|
||||
- Note about any warnings (incomplete artifacts/tasks)
|
||||
|
||||
**Output On Success**
|
||||
|
||||
```
|
||||
## Archive Complete
|
||||
|
||||
**Change:** <change-name>
|
||||
**Schema:** <schema-name>
|
||||
**Archived to:** openspec/changes/archive/YYYY-MM-DD-<name>/
|
||||
**Specs:** ✓ Synced to main specs (or "No delta specs" or "Sync skipped")
|
||||
|
||||
All artifacts complete. All tasks complete.
|
||||
```
|
||||
|
||||
**Guardrails**
|
||||
- Always prompt for change selection if not provided
|
||||
- Use artifact graph (openspec status --json) for completion checking
|
||||
- Don't block archive on warnings - just inform and confirm
|
||||
- Preserve .openspec.yaml when moving to archive (it moves with the directory)
|
||||
- Show clear summary of what happened
|
||||
- If sync is requested, use openspec-sync-specs approach (agent-driven)
|
||||
- If delta specs exist, always run the sync assessment and show the combined summary before prompting
|
||||
@@ -1,288 +0,0 @@
|
||||
---
|
||||
name: openspec-explore
|
||||
description: Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use when the user wants to think through something before or during a change.
|
||||
license: MIT
|
||||
compatibility: Requires openspec CLI.
|
||||
metadata:
|
||||
author: openspec
|
||||
version: "1.0"
|
||||
generatedBy: "1.3.1"
|
||||
---
|
||||
|
||||
Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.
|
||||
|
||||
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, and investigate the codebase, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first and create a change proposal. You MAY create OpenSpec artifacts (proposals, designs, specs) if the user asks—that's capturing thinking, not implementing.
|
||||
|
||||
**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.
|
||||
|
||||
---
|
||||
|
||||
## The Stance
|
||||
|
||||
- **Curious, not prescriptive** - Ask questions that emerge naturally, don't follow a script
|
||||
- **Open threads, not interrogations** - Surface multiple interesting directions and let the user follow what resonates. Don't funnel them through a single path of questions.
|
||||
- **Visual** - Use ASCII diagrams liberally when they'd help clarify thinking
|
||||
- **Adaptive** - Follow interesting threads, pivot when new information emerges
|
||||
- **Patient** - Don't rush to conclusions, let the shape of the problem emerge
|
||||
- **Grounded** - Explore the actual codebase when relevant, don't just theorize
|
||||
|
||||
---
|
||||
|
||||
## What You Might Do
|
||||
|
||||
Depending on what the user brings, you might:
|
||||
|
||||
**Explore the problem space**
|
||||
- Ask clarifying questions that emerge from what they said
|
||||
- Challenge assumptions
|
||||
- Reframe the problem
|
||||
- Find analogies
|
||||
|
||||
**Investigate the codebase**
|
||||
- Map existing architecture relevant to the discussion
|
||||
- Find integration points
|
||||
- Identify patterns already in use
|
||||
- Surface hidden complexity
|
||||
|
||||
**Compare options**
|
||||
- Brainstorm multiple approaches
|
||||
- Build comparison tables
|
||||
- Sketch tradeoffs
|
||||
- Recommend a path (if asked)
|
||||
|
||||
**Visualize**
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Use ASCII diagrams liberally │
|
||||
├─────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌────────┐ ┌────────┐ │
|
||||
│ │ State │────────▶│ State │ │
|
||||
│ │ A │ │ B │ │
|
||||
│ └────────┘ └────────┘ │
|
||||
│ │
|
||||
│ System diagrams, state machines, │
|
||||
│ data flows, architecture sketches, │
|
||||
│ dependency graphs, comparison tables │
|
||||
│ │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Surface risks and unknowns**
|
||||
- Identify what could go wrong
|
||||
- Find gaps in understanding
|
||||
- Suggest spikes or investigations
|
||||
|
||||
---
|
||||
|
||||
## OpenSpec Awareness
|
||||
|
||||
You have full context of the OpenSpec system. Use it naturally, don't force it.
|
||||
|
||||
### Check for context
|
||||
|
||||
At the start, quickly check what exists:
|
||||
```bash
|
||||
openspec list --json
|
||||
```
|
||||
|
||||
This tells you:
|
||||
- If there are active changes
|
||||
- Their names, schemas, and status
|
||||
- What the user might be working on
|
||||
|
||||
### When no change exists
|
||||
|
||||
Think freely. When insights crystallize, you might offer:
|
||||
|
||||
- "This feels solid enough to start a change. Want me to create a proposal?"
|
||||
- Or keep exploring - no pressure to formalize
|
||||
|
||||
### When a change exists
|
||||
|
||||
If the user mentions a change or you detect one is relevant:
|
||||
|
||||
1. **Read existing artifacts for context**
|
||||
- `openspec/changes/<name>/proposal.md`
|
||||
- `openspec/changes/<name>/design.md`
|
||||
- `openspec/changes/<name>/tasks.md`
|
||||
- etc.
|
||||
|
||||
2. **Reference them naturally in conversation**
|
||||
- "Your design mentions using Redis, but we just realized SQLite fits better..."
|
||||
- "The proposal scopes this to premium users, but we're now thinking everyone..."
|
||||
|
||||
3. **Offer to capture when decisions are made**
|
||||
|
||||
| Insight Type | Where to Capture |
|
||||
|----------------------------|--------------------------------|
|
||||
| New requirement discovered | `specs/<capability>/spec.md` |
|
||||
| Requirement changed | `specs/<capability>/spec.md` |
|
||||
| Design decision made | `design.md` |
|
||||
| Scope changed | `proposal.md` |
|
||||
| New work identified | `tasks.md` |
|
||||
| Assumption invalidated | Relevant artifact |
|
||||
|
||||
Example offers:
|
||||
- "That's a design decision. Capture it in design.md?"
|
||||
- "This is a new requirement. Add it to specs?"
|
||||
- "This changes scope. Update the proposal?"
|
||||
|
||||
4. **The user decides** - Offer and move on. Don't pressure. Don't auto-capture.
|
||||
|
||||
---
|
||||
|
||||
## What You Don't Have To Do
|
||||
|
||||
- Follow a script
|
||||
- Ask the same questions every time
|
||||
- Produce a specific artifact
|
||||
- Reach a conclusion
|
||||
- Stay on topic if a tangent is valuable
|
||||
- Be brief (this is thinking time)
|
||||
|
||||
---
|
||||
|
||||
## Handling Different Entry Points
|
||||
|
||||
**User brings a vague idea:**
|
||||
```
|
||||
User: I'm thinking about adding real-time collaboration
|
||||
|
||||
You: Real-time collab is a big space. Let me think about this...
|
||||
|
||||
COLLABORATION SPECTRUM
|
||||
════════════════════════════════════════════
|
||||
|
||||
Awareness Coordination Sync
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Presence│ │Cursors │ │ CRDT │
|
||||
│ "3 │ │ Multi │ │Conflict│
|
||||
│online" │ │ select │ │ free │
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │ │
|
||||
trivial moderate complex
|
||||
|
||||
Where's your head at?
|
||||
```
|
||||
|
||||
**User brings a specific problem:**
|
||||
```
|
||||
User: The auth system is a mess
|
||||
|
||||
You: [reads codebase]
|
||||
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ CURRENT AUTH FLOW │
|
||||
└─────────────────────────────────────────────┘
|
||||
│
|
||||
┌─────────────┼─────────────┐
|
||||
▼ ▼ ▼
|
||||
┌─────────┐ ┌─────────┐ ┌─────────┐
|
||||
│ Google │ │ GitHub │ │ Email │
|
||||
│ OAuth │ │ OAuth │ │ Magic │
|
||||
└────┬────┘ └────┬────┘ └────┬────┘
|
||||
│ │ │
|
||||
└─────────────┼─────────────┘
|
||||
▼
|
||||
┌───────────┐
|
||||
│ Session │
|
||||
└─────┬─────┘
|
||||
│
|
||||
▼
|
||||
┌───────────┐
|
||||
│ Perms │
|
||||
└───────────┘
|
||||
|
||||
I see three tangles. Which one's burning?
|
||||
```
|
||||
|
||||
**User is stuck mid-implementation:**
|
||||
```
|
||||
User: /opsx:explore add-auth-system
|
||||
The OAuth integration is more complex than expected
|
||||
|
||||
You: [reads change artifacts]
|
||||
|
||||
You're on task 4: "Implement OAuth flow"
|
||||
|
||||
Let me trace what's involved...
|
||||
|
||||
[draws diagram, explores options, suggests paths]
|
||||
|
||||
Want to update the design to reflect this?
|
||||
Or add a spike task to investigate?
|
||||
```
|
||||
|
||||
**User wants to compare options:**
|
||||
```
|
||||
User: Should we use Postgres or SQLite?
|
||||
|
||||
You: Generic answer is boring. What's the context?
|
||||
|
||||
User: A CLI tool that tracks local dev environments
|
||||
|
||||
You: That changes everything.
|
||||
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ CLI TOOL DATA STORAGE │
|
||||
└─────────────────────────────────────────────────┘
|
||||
|
||||
Key constraints:
|
||||
• No daemon running
|
||||
• Must work offline
|
||||
• Single user
|
||||
|
||||
SQLite Postgres
|
||||
Deployment embedded ✓ needs server ✗
|
||||
Offline yes ✓ no ✗
|
||||
Single file yes ✓ no ✗
|
||||
|
||||
SQLite. Not even close.
|
||||
|
||||
Unless... is there a sync component?
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Ending Discovery
|
||||
|
||||
There's no required ending. Discovery might:
|
||||
|
||||
- **Flow into a proposal**: "Ready to start? I can create a change proposal."
|
||||
- **Result in artifact updates**: "Updated design.md with these decisions"
|
||||
- **Just provide clarity**: User has what they need, moves on
|
||||
- **Continue later**: "We can pick this up anytime"
|
||||
|
||||
When it feels like things are crystallizing, you might summarize:
|
||||
|
||||
```
|
||||
## What We Figured Out
|
||||
|
||||
**The problem**: [crystallized understanding]
|
||||
|
||||
**The approach**: [if one emerged]
|
||||
|
||||
**Open questions**: [if any remain]
|
||||
|
||||
**Next steps** (if ready):
|
||||
- Create a change proposal
|
||||
- Keep exploring: just keep talking
|
||||
```
|
||||
|
||||
But this summary is optional. Sometimes the thinking IS the value.
|
||||
|
||||
---
|
||||
|
||||
## Guardrails
|
||||
|
||||
- **Don't implement** - Never write code or implement features. Creating OpenSpec artifacts is fine, writing application code is not.
|
||||
- **Don't fake understanding** - If something is unclear, dig deeper
|
||||
- **Don't rush** - Discovery is thinking time, not task time
|
||||
- **Don't force structure** - Let patterns emerge naturally
|
||||
- **Don't auto-capture** - Offer to save insights, don't just do it
|
||||
- **Do visualize** - A good diagram is worth many paragraphs
|
||||
- **Do explore the codebase** - Ground discussions in reality
|
||||
- **Do question assumptions** - Including the user's and your own
|
||||
@@ -1,110 +0,0 @@
|
||||
---
|
||||
name: openspec-propose
|
||||
description: Propose a new change with all artifacts generated in one step. Use when the user wants to quickly describe what they want to build and get a complete proposal with design, specs, and tasks ready for implementation.
|
||||
license: MIT
|
||||
compatibility: Requires openspec CLI.
|
||||
metadata:
|
||||
author: openspec
|
||||
version: "1.0"
|
||||
generatedBy: "1.3.1"
|
||||
---
|
||||
|
||||
Propose a new change - create the change and generate all artifacts in one step.
|
||||
|
||||
I'll create a change with artifacts:
|
||||
- proposal.md (what & why)
|
||||
- design.md (how)
|
||||
- tasks.md (implementation steps)
|
||||
|
||||
When ready to implement, run /opsx:apply
|
||||
|
||||
---
|
||||
|
||||
**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build.
|
||||
|
||||
**Steps**
|
||||
|
||||
1. **If no clear input provided, ask what they want to build**
|
||||
|
||||
Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:
|
||||
> "What change do you want to work on? Describe what you want to build or fix."
|
||||
|
||||
From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`).
|
||||
|
||||
**IMPORTANT**: Do NOT proceed without understanding what the user wants to build.
|
||||
|
||||
2. **Create the change directory**
|
||||
```bash
|
||||
openspec new change "<name>"
|
||||
```
|
||||
This creates a scaffolded change at `openspec/changes/<name>/` with `.openspec.yaml`.
|
||||
|
||||
3. **Get the artifact build order**
|
||||
```bash
|
||||
openspec status --change "<name>" --json
|
||||
```
|
||||
Parse the JSON to get:
|
||||
- `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`)
|
||||
- `artifacts`: list of all artifacts with their status and dependencies
|
||||
|
||||
4. **Create artifacts in sequence until apply-ready**
|
||||
|
||||
Use the **TodoWrite tool** to track progress through the artifacts.
|
||||
|
||||
Loop through artifacts in dependency order (artifacts with no pending dependencies first):
|
||||
|
||||
a. **For each artifact that is `ready` (dependencies satisfied)**:
|
||||
- Get instructions:
|
||||
```bash
|
||||
openspec instructions <artifact-id> --change "<name>" --json
|
||||
```
|
||||
- The instructions JSON includes:
|
||||
- `context`: Project background (constraints for you - do NOT include in output)
|
||||
- `rules`: Artifact-specific rules (constraints for you - do NOT include in output)
|
||||
- `template`: The structure to use for your output file
|
||||
- `instruction`: Schema-specific guidance for this artifact type
|
||||
- `outputPath`: Where to write the artifact
|
||||
- `dependencies`: Completed artifacts to read for context
|
||||
- Read any completed dependency files for context
|
||||
- Create the artifact file using `template` as the structure
|
||||
- Apply `context` and `rules` as constraints - but do NOT copy them into the file
|
||||
- Show brief progress: "Created <artifact-id>"
|
||||
|
||||
b. **Continue until all `applyRequires` artifacts are complete**
|
||||
- After creating each artifact, re-run `openspec status --change "<name>" --json`
|
||||
- Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array
|
||||
- Stop when all `applyRequires` artifacts are done
|
||||
|
||||
c. **If an artifact requires user input** (unclear context):
|
||||
- Use **AskUserQuestion tool** to clarify
|
||||
- Then continue with creation
|
||||
|
||||
5. **Show final status**
|
||||
```bash
|
||||
openspec status --change "<name>"
|
||||
```
|
||||
|
||||
**Output**
|
||||
|
||||
After completing all artifacts, summarize:
|
||||
- Change name and location
|
||||
- List of artifacts created with brief descriptions
|
||||
- What's ready: "All artifacts created! Ready for implementation."
|
||||
- Prompt: "Run `/opsx:apply` or ask me to implement to start working on the tasks."
|
||||
|
||||
**Artifact Creation Guidelines**
|
||||
|
||||
- Follow the `instruction` field from `openspec instructions` for each artifact type
|
||||
- The schema defines what each artifact should contain - follow it
|
||||
- Read dependency artifacts for context before creating new ones
|
||||
- Use `template` as the structure for your output file - fill in its sections
|
||||
- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file
|
||||
- Do NOT copy `<context>`, `<rules>`, `<project_context>` blocks into the artifact
|
||||
- These guide what you write, but should never appear in the output
|
||||
|
||||
**Guardrails**
|
||||
- Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`)
|
||||
- Always read dependency artifacts before creating a new one
|
||||
- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum
|
||||
- If a change with that name already exists, ask if user wants to continue it or create a new one
|
||||
- Verify each artifact file exists after writing before proceeding to next
|
||||
@@ -148,7 +148,7 @@ openspec/changes/phase-1-infrastructure/
|
||||
|
||||
## 敏感信息(已编辑)
|
||||
|
||||
- MySQL 密码:已从仓库移除,使用环境变量注入
|
||||
- MySQL 密码:已配置在 application.yml(`!Fucker123..`)
|
||||
- Redis:无密码
|
||||
|
||||
---
|
||||
|
||||
@@ -97,7 +97,7 @@ spring:
|
||||
redis:
|
||||
host: 119.29.78.52
|
||||
port: 6379
|
||||
password: ${SUPERBIZ_REDIS_PASSWORD}
|
||||
password: '!Fucker123..'
|
||||
database: 0
|
||||
timeout: 3000
|
||||
```
|
||||
|
||||
@@ -140,7 +140,7 @@ Error Code: 1049
|
||||
datasource:
|
||||
url: jdbc:mysql://119.29.78.52:33306/superbiz_agent?...
|
||||
username: root
|
||||
password: ${SUPERBIZ_MYSQL_PASSWORD}
|
||||
password: '!Fucker123..'
|
||||
```
|
||||
|
||||
**Redis 配置**:
|
||||
@@ -149,7 +149,7 @@ data:
|
||||
redis:
|
||||
host: 119.29.78.52
|
||||
port: 6379
|
||||
password: ${SUPERBIZ_REDIS_PASSWORD}
|
||||
password: '!Fucker123..'
|
||||
```
|
||||
|
||||
**Flyway 配置**:
|
||||
|
||||
+1
-8
@@ -44,13 +44,6 @@ build/
|
||||
app.log
|
||||
logs/
|
||||
|
||||
### Local Secrets ###
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
application-local.yml
|
||||
application-*.local.yml
|
||||
|
||||
### Upload Files ###
|
||||
uploads/
|
||||
|
||||
@@ -65,8 +58,8 @@ uploads/
|
||||
|
||||
### Windows / Runtime Artifacts
|
||||
*.stackdump
|
||||
NUL
|
||||
|
||||
### MVP Demo Generated Outputs
|
||||
mvp/demo/output/*.json
|
||||
!mvp/demo/output/README.md
|
||||
.pi/extensions/emdash-hook.ts
|
||||
|
||||
@@ -105,46 +105,3 @@ Find reuse opportunities + Trace the call/dependency chain and impact radius:
|
||||
Unless directly relevant to the user's current question, you should avoid proactively mentioning, illustrating, or
|
||||
trailing off into the following information in 99% of cases:
|
||||
|
||||
<!-- gitnexus:start -->
|
||||
# GitNexus — Code Intelligence
|
||||
|
||||
This project is indexed by GitNexus as **SuperBizAgent-java** (13483 symbols, 22230 relationships, 300 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
|
||||
|
||||
> If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first.
|
||||
|
||||
## Always Do
|
||||
|
||||
- **MUST run impact analysis before editing any symbol.** Before modifying a function, class, or method, run `gitnexus_impact({target: "symbolName", direction: "upstream"})` and report the blast radius (direct callers, affected processes, risk level) to the user.
|
||||
- **MUST run `gitnexus_detect_changes()` before committing** to verify your changes only affect expected symbols and execution flows.
|
||||
- **MUST warn the user** if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
|
||||
- When exploring unfamiliar code, use `gitnexus_query({query: "concept"})` to find execution flows instead of grepping. It returns process-grouped results ranked by relevance.
|
||||
- When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use `gitnexus_context({name: "symbolName"})`.
|
||||
|
||||
## Never Do
|
||||
|
||||
- NEVER edit a function, class, or method without first running `gitnexus_impact` on it.
|
||||
- NEVER ignore HIGH or CRITICAL risk warnings from impact analysis.
|
||||
- NEVER rename symbols with find-and-replace — use `gitnexus_rename` which understands the call graph.
|
||||
- NEVER commit changes without running `gitnexus_detect_changes()` to check affected scope.
|
||||
|
||||
## Resources
|
||||
|
||||
| Resource | Use for |
|
||||
|----------|---------|
|
||||
| `gitnexus://repo/SuperBizAgent-java/context` | Codebase overview, check index freshness |
|
||||
| `gitnexus://repo/SuperBizAgent-java/clusters` | All functional areas |
|
||||
| `gitnexus://repo/SuperBizAgent-java/processes` | All execution flows |
|
||||
| `gitnexus://repo/SuperBizAgent-java/process/{name}` | Step-by-step execution trace |
|
||||
|
||||
## CLI
|
||||
|
||||
| Task | Read this skill file |
|
||||
|------|---------------------|
|
||||
| Understand architecture / "How does X work?" | `.claude/skills/gitnexus/gitnexus-exploring/SKILL.md` |
|
||||
| Blast radius / "What breaks if I change X?" | `.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md` |
|
||||
| Trace bugs / "Why is X failing?" | `.claude/skills/gitnexus/gitnexus-debugging/SKILL.md` |
|
||||
| Rename / extract / split / refactor | `.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md` |
|
||||
| Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` |
|
||||
| Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` |
|
||||
|
||||
<!-- gitnexus:end -->
|
||||
|
||||
@@ -111,46 +111,3 @@ trailing off into the following information in 99% of cases:
|
||||
- 文档目录结构:
|
||||
- 不要将文档放到用户目录(如 `C:\Users\EDY\.claude\`)中
|
||||
|
||||
<!-- gitnexus:start -->
|
||||
# GitNexus — Code Intelligence
|
||||
|
||||
This project is indexed by GitNexus as **SuperBizAgent-java** (13483 symbols, 22230 relationships, 300 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
|
||||
|
||||
> If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first.
|
||||
|
||||
## Always Do
|
||||
|
||||
- **MUST run impact analysis before editing any symbol.** Before modifying a function, class, or method, run `gitnexus_impact({target: "symbolName", direction: "upstream"})` and report the blast radius (direct callers, affected processes, risk level) to the user.
|
||||
- **MUST run `gitnexus_detect_changes()` before committing** to verify your changes only affect expected symbols and execution flows.
|
||||
- **MUST warn the user** if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
|
||||
- When exploring unfamiliar code, use `gitnexus_query({query: "concept"})` to find execution flows instead of grepping. It returns process-grouped results ranked by relevance.
|
||||
- When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use `gitnexus_context({name: "symbolName"})`.
|
||||
|
||||
## Never Do
|
||||
|
||||
- NEVER edit a function, class, or method without first running `gitnexus_impact` on it.
|
||||
- NEVER ignore HIGH or CRITICAL risk warnings from impact analysis.
|
||||
- NEVER rename symbols with find-and-replace — use `gitnexus_rename` which understands the call graph.
|
||||
- NEVER commit changes without running `gitnexus_detect_changes()` to check affected scope.
|
||||
|
||||
## Resources
|
||||
|
||||
| Resource | Use for |
|
||||
|----------|---------|
|
||||
| `gitnexus://repo/SuperBizAgent-java/context` | Codebase overview, check index freshness |
|
||||
| `gitnexus://repo/SuperBizAgent-java/clusters` | All functional areas |
|
||||
| `gitnexus://repo/SuperBizAgent-java/processes` | All execution flows |
|
||||
| `gitnexus://repo/SuperBizAgent-java/process/{name}` | Step-by-step execution trace |
|
||||
|
||||
## CLI
|
||||
|
||||
| Task | Read this skill file |
|
||||
|------|---------------------|
|
||||
| Understand architecture / "How does X work?" | `.claude/skills/gitnexus/gitnexus-exploring/SKILL.md` |
|
||||
| Blast radius / "What breaks if I change X?" | `.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md` |
|
||||
| Trace bugs / "Why is X failing?" | `.claude/skills/gitnexus/gitnexus-debugging/SKILL.md` |
|
||||
| Rename / extract / split / refactor | `.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md` |
|
||||
| Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` |
|
||||
| Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` |
|
||||
|
||||
<!-- gitnexus:end -->
|
||||
|
||||
@@ -103,6 +103,11 @@
|
||||
- 使用场景:Trace API、Trace UI、Verifier 审计、评测 fixture 和人工排查。
|
||||
- 边界:Diagnosis Trace 是聚合视图,不要求单独的 trace 主表;当前 trace 明细由 `agent_step` 和 `tool_invocation` 表承载。
|
||||
|
||||
### Diagnosis Orchestration Trace
|
||||
- 定义:一次 Diagnosis Run 的紧凑编排审计摘要,记录实际节点路径、条件边原因、技术重试、降级和终止原因。
|
||||
- 使用场景:解释诊断编排为何进入某个节点、为何重试或为何提前终止,并支撑路由验收和人工审计。
|
||||
- 边界:它是 Diagnosis Trace 的编排维度,不是完整事件日志、自评估结果或持久恢复检查点;不保存 Prompt、模型思考、工具原文和完整编排上下文快照。
|
||||
|
||||
### Flyway
|
||||
- 定义:数据库版本迁移工具,管理 SQL 脚本的版本化执行
|
||||
- 配置:spring.flyway.enabled=true, baseline-on-migrate=true
|
||||
@@ -155,103 +160,15 @@
|
||||
- 使用场景:Executor 按 skill workflow 调用 evidence tools 收集事实,`tool_invocation` 记录这些事实证据。
|
||||
- 边界:最终诊断结论必须被 evidence tools 支撑,不能仅由 skill 正文支撑。
|
||||
|
||||
### Diagnosis Harness
|
||||
- 定义:围绕 Diagnosis Agent 提供确定性运行控制的边界,负责 Run、预算、取消、重试装配、Tool 调用记录、证据验真和最终释放,不承担业务诊断推理。
|
||||
- 边界:Harness 不是工作流引擎,不实现 Planner/Executor/Composer 节点或自行编写 ReAct 循环。
|
||||
|
||||
### Diagnosis Agent
|
||||
- 定义:诊断链路中唯一拥有 ReAct 工具循环并生成 `DiagnosisDraft` 的 Agent,负责规划证据查询、判断证据充分性和撰写完整诊断草稿。
|
||||
- 边界:不负责意图路由、Run/Session 生命周期、证据物理验真、独立语义审查或最终发布;证据不足时必须明确停止并保留限制。
|
||||
|
||||
### EvidenceGuard
|
||||
- 定义:Harness 内部的确定性证据验真能力,校验 Draft 引用、当前 Run 所有权、Tool 调用状态和有界 Agent 投影。
|
||||
- 边界:EvidenceGuard 不调用 LLM,也不判断证据是否足以推出业务结论。
|
||||
|
||||
### SemanticGuard
|
||||
- 定义:使用隔离上下文对完整诊断 Draft 与已验真证据做报告级语义审查的单轮 Agent。
|
||||
- 边界:无工具、无记忆、无 ReAct 循环,不访问 Redis,不生成或改写用户报告。
|
||||
|
||||
### Invocation Status
|
||||
- 定义:Tool 调用及结果投影的生命周期状态,固定为 `PROJECTING`、`READY`、`ERROR`。
|
||||
- 边界:它只说明调用记录是否完成,不说明结果是否包含证据。
|
||||
|
||||
### Durable Audit
|
||||
- 定义:为 Diagnosis Trace 长期保存的 Run、Agent 模型步骤和 Tool 调用元数据,用于 exact sessionId/runId 回放、评测和运维核对。
|
||||
- 边界:只保存有界、脱敏、可长期保留的身份、状态、耗时、预算和结果摘要;不保存 Prompt、Thought、完整 Tool 参数、raw response 或 Redis canonical invocation。
|
||||
|
||||
### Evidence Status
|
||||
- 定义:证据 Tool 的结果语义,固定为 `EVIDENCE_FOUND`、`NO_EVIDENCE`、`ERROR`。
|
||||
- 边界:`EVIDENCE_FOUND` 只表示存在候选内容,不保证内容能够支持当前诊断;`NO_EVIDENCE` 只表示当前查询范围内没有匹配结果,不能解释为问题不存在、根因被排除或系统健康。
|
||||
|
||||
### Information Gain
|
||||
- 定义:一次 Tool 结果是否推进当前 Diagnosis Run 的语义评价,固定为 `GAINED` 或 `NO_GAIN`。
|
||||
- 边界:它评价的是结果对当前诊断的作用,不评价 Tool 产品质量;`NO_EVIDENCE` 和重复的规范化 `tool + scope` 可由 Harness 机械标记为 `NO_GAIN`,其他成功非空结果(包括 RAG `REFERENCE`)由模型评价。
|
||||
|
||||
### Collection State
|
||||
- 定义:Diagnosis Harness 对当前 Run 是否允许继续收集证据的控制状态,固定为 `COLLECTING` 或 `SATURATED`。
|
||||
- 边界:状态由 Harness 维护;`SATURATED` 可因连续 `NO_GAIN` 或连续进展协议错误达到各自配置阈值而进入,不包括硬预算耗尽。模型可以请求新的 Tool 调用,但不能绕过 `SATURATED`。
|
||||
|
||||
### Diagnosis Stop Reason
|
||||
- 定义:Harness 停止当前 Run 继续调用 Tool 的内部原因,首版区分 `INFORMATION_SATURATED`、`BUDGET_LIMIT_REACHED` 与 `PROGRESS_PROTOCOL_VIOLATED`。
|
||||
- 边界:它用于控制、Trace 和 Release 输入,不是用户可见生命周期状态,也不进入模型上下文;真正的不可恢复技术故障走失败通道。协议错误不累计为 `NO_GAIN`,使用独立阈值与 stop reason。
|
||||
|
||||
### Progress Protocol Violation
|
||||
- 定义:模型未遵守 Tool Call Envelope 进展协议时的安全错误分类,例如缺失/错序/意外 `previous_observation`、缺失 `input` 或非法 Envelope。
|
||||
- 边界:返回可修正 observation(`repair_required`、`violation_type`、期望上一轮 Tool Call ID、允许的 `information_gain`);连续错误达到阈值后交付一次 `STOP_REQUIRED/PROGRESS_PROTOCOL_VIOLATED`。不泄露业务参数、上一轮观察正文、raw response 或内部异常。
|
||||
|
||||
### Progress Snapshot
|
||||
- 定义:Tool Loop 结束时,从当前 Run 的 Canonical Tool Result 一次性投影出的有界发布视图,用于生成已检查范围和客观结果。
|
||||
- 边界:Canonical Tool Result 是真理源;Progress Snapshot 不逐轮维护、不保存原始 Tool Response、Prompt 或内部 thought,也不直接进入模型上下文。
|
||||
|
||||
### Safe Fallback Type
|
||||
- 定义:`SafeFallback.type` 对没有发布诊断结论的业务原因分类,例如 `INSUFFICIENT_EVIDENCE`、`MISSING_REQUIRED_CONTEXT`、`BUDGET_EXHAUSTED` 或安全校验失败。
|
||||
- 边界:它是 `ReleaseOutcome.FALLBACK` 的原因字段,不是与 `SUCCESS / FALLBACK / FAILED / CANCELLED` 平行的第二套生命周期状态。
|
||||
|
||||
### Diagnosis Release Use Case
|
||||
- 定义:诊断业务发布的唯一决策入口,接收 DiagnosisDraft 和/或 Harness `stop_reason + ProgressSnapshot`,生成安全的 `SUCCESS / FALLBACK` 结果。
|
||||
- 边界:`conclusion=null` 不触发 EvidenceRepair;只有存在结论时才执行完整 EvidenceGuard、EvidenceRepair 和 SemanticGuard 链路。不可形成安全业务内容的技术故障由 Chat Application Use Case 映射为 `FAILED / CANCELLED`。
|
||||
|
||||
### Diagnosis Draft Contract Failure
|
||||
- 定义:Diagnosis Agent 最终文本为空、不是严格 JSON,或不满足 `DiagnosisDraft` Schema 时产生的 Agent 输出合同失败。
|
||||
- 边界:非法文本始终丢弃,不做 Markdown/自然语言提取,也不调用模型修复;仅当当前 Run 的 `ProgressSnapshot` 含已验真 observed facts 时,Release 才能确定性发布 `INSUFFICIENT_EVIDENCE`,否则保持 `FAILED`。它不是 `Diagnosis Stop Reason`,不得伪装成信息饱和或预算终止。
|
||||
|
||||
### Model Observation
|
||||
- 定义:Tool 内部标准化结果经过白名单投影后,作为 Tool Response 进入 Diagnosis Agent 上下文的有界视图。
|
||||
- 边界:只包含模型完成语义判断和证据引用所需的信息;预算、阈值、重复指纹、原始相似度、原始 Tool Response 和完整 Harness 控制状态不得进入该视图。
|
||||
|
||||
### RunContext
|
||||
- 定义:一次 Diagnosis Run 的显式执行上下文,结构不可变地携带 `sessionId`、`runId`、deadline,以及该 Run 独占的取消、预算、重试策略和生命周期状态句柄。
|
||||
- 边界:RunContext 通过方法参数或框架受控 context 显式传播,不依赖 ThreadLocal;结构不可变不等于内部计数和取消状态不能变化,这些变化由线程安全句柄管理。
|
||||
|
||||
### Run Lifecycle
|
||||
- 定义:Diagnosis Harness 对单次 Run 执行状态的内存控制,采用 first-terminal-wins 规则保证成功、失败、取消、超时和预算耗尽只能产生一个最终终态。
|
||||
- 边界:Run Lifecycle 不直接等同于数据库实体写入;应用用例负责把最终状态映射到 `diagnosis_run` 持久化。
|
||||
|
||||
### Run Budget
|
||||
- 定义:单次 Run 的模型调用、Tool 调用、单 Tool 调用、输入/输出/总 Token 和 canonical invocation 字节容量的线程安全消耗计数与门禁。
|
||||
- 边界:预算上限由 Harness 配置显式提供;实际 Token 在模型响应后记录,超限后保留真实消耗并阻止后续执行。
|
||||
|
||||
### Harness Retry Policy
|
||||
- 定义:Harness 对同一技术操作 attempt 数和可重试失败类型的显式策略。
|
||||
- 边界:Router 与 SemanticGuard 的技术失败最多两次 attempt;Diagnosis Agent、Tool 和 Evidence repair 只有一次 attempt。Agent 正常 ReAct 轮次不是 retry,`NO_EVIDENCE`、业务拒绝、取消和预算耗尽不可重试。
|
||||
|
||||
### Chat Application Use Case
|
||||
- 定义:一次 Chat 请求的唯一业务入口,拥有 Session/Run、意图路由、固定执行器、PreviousTurn 和最终持久化。
|
||||
- 边界:不拥有 HTTP/SSE 连接,不把 ChatModel 或 Tool 选择权交给 Controller,也不在 Diagnosis Release Use Case 之外单独决定预算 Fallback 的业务内容。
|
||||
|
||||
### Chat SSE Contract
|
||||
- 定义:Chat 公开入口的五事件协议,顺序固定为 `metadata -> status* -> content|failure -> done`。
|
||||
- 边界:过程状态实时发送,最终安全内容最多释放一次;它不是 Token streaming,也不包含内部计划、Prompt、raw Tool 数据或异常。
|
||||
|
||||
### Verifier Skill Isolation
|
||||
- 定义:Chat Verifier 与 skill 系统隔离,只校验 Executor 答案和 `tool_trace_summary`。
|
||||
- 定义:Chat Verifier 与 skill 系统隔离,只校验 Gatekeeper 投影后的 `verified_executor_output` 和 `verified_evidence`。
|
||||
- 使用场景:防止 Verifier 把 playbook 指令当作事实证据;Verifier 只判断已有证据是否支持结论。
|
||||
- 边界:Verifier 不接收 `skill_catalog`,不暴露 `read_skill`,不读取 `SKILL.md`。
|
||||
- 边界:Verifier 不接收 `skill_catalog`,不暴露 `read_skill`,不读取 `SKILL.md`、完整 `tool_trace_summary` 或未经验真的 Executor 自由文本。
|
||||
|
||||
## Diagnosis Playbook Business Rules
|
||||
|
||||
- Planner 只看 skill metadata,输出 `selected_skill`、`selection_reason` 和 plan。
|
||||
- Executor 才能调用 `read_skill(selected_skill)`,并且读取 skill 后仍必须调用 evidence tools。
|
||||
- Skill 正文不得替代 `lookup_knowledge`、日志、指标或告警数据。
|
||||
- Verifier 只基于 `tool_trace_summary` 校验事实,不基于 skill 正文校验事实。
|
||||
- Verifier 只基于 Gatekeeper 通过的 `verified_executor_output` 和 `verified_evidence` 校验事实,不基于 skill 正文、完整工具 Trace 或未验真输出校验事实。
|
||||
- 当前阶段保留单 active skill 白名单:`diagnose-mysql-connection-pool`。
|
||||
|
||||
+7
-26
@@ -1,27 +1,15 @@
|
||||
# devflow 索引
|
||||
|
||||
## Issue 生命周期
|
||||
|
||||
| Issue | 状态 | 说明 |
|
||||
|---|---|---|
|
||||
| ISS-014 | archived | 阶段 0-7 的单体 Diagnosis Agent、Harness、ACI、SSE、清理和最终 E2E 已完成并归档;阶段实现对应的 11 个 devflow/OpenSpec 项目均已 archived。 |
|
||||
| ISS-015 | active | 阶段 1 硬停止已由 ISS-016 收口;剩余 Evidence Repair Schema、Reasoning 审计验证/治理与最终综合验收。 |
|
||||
| ISS-016 | archived | Diagnosis 信息增益停止契约、协议修复反馈与统一 Release 已完成并归档。 |
|
||||
# devflow 索引
|
||||
|
||||
## 项目
|
||||
|
||||
| 日期 | slug | 说明 | 领域 | 关键词 | 关联 OpenSpec | 状态 |
|
||||
|---|---|---|---|---|---|---|
|
||||
| 2026-07-28 | rag-eval-hybrid-baseline | 离线 RAG eval 对齐 hybrid:search.mode 生成器、fixture meta、baseline 重刷;hybrid 质量闸门可用 denseDistance。 | RAG/eval/baseline | search.mode, fixture meta, kb_scope rag-eval, L0 filter fallback, denseDistance | openspec/changes/archive/2026-07-28-rag-eval-hybrid-baseline | archived |
|
||||
| 2026-07-28 | rag-quality-score-unify | 统一 dense/hybrid scoreLabel 与 qualityScore;保检索序;去掉关键词 boost 改序与 hybrid L2 伪装。 | RAG/质量分/后处理 | qualityScore, scoreLabel dense/hybrid, originalRank, RetrievalScoreNormalizer, no boost rerank | openspec/changes/archive/2026-07-28-rag-quality-score-unify | archived |
|
||||
| 2026-07-26 | diagnosis-information-gain-stop-contract | Diagnosis 信息增益停止、协议修复反馈、ProgressSnapshot 与统一 Release。 | Harness/Diagnosis stop/Release | ISS-016, GAINED, NO_GAIN, STOP_REQUIRED, ProgressSnapshot, PROGRESS_PROTOCOL_VIOLATED, INSUFFICIENT_EVIDENCE | openspec/changes/archive/2026-07-27-diagnosis-information-gain-stop-contract | archived |
|
||||
| 2026-07-27 | rag-chunk-evidence-identity-dedup | chunk 级证据身份、去重、retrieve-k/return-n 与 SearchPort 地基,为 hybrid 铺路。 | RAG/证据身份/去重 | evidenceKey, maxChunksPerDocument, retrieve-k, return-n, KnowledgeSearchPort, document_id chunk-scoped | openspec/changes/archive/2026-07-27-rag-chunk-evidence-identity-dedup | archived |
|
||||
| 2026-07-27 | rag-bm25-hybrid-drop-sdk | 真 dense+BM25 hybrid(MilvusClientV2),废弃知识路径旧 SDK 检索/写入。 | RAG/BM25/hybrid | MilvusClientV2, BM25, hybridSearch, RRFRanker, biz_hybrid, drop SDK path | openspec/changes/archive/2026-07-27-rag-bm25-hybrid-drop-sdk | archived |
|
||||
| 2026-07-27 | rag-hybrid-search-rrf | Delivery 2:可配置 hybrid 检索与 RRF 多路融合(不绑旧 SDK)。 | RAG/hybrid/RRF | hybrid mode, RRF, KnowledgeSearchPort, filtered+unfiltered fusion, sparse-lite lexical | openspec/changes/archive/2026-07-27-rag-hybrid-search-rrf | archived |
|
||||
| 2026-07-21 | single-react-tool-invocation-store | 建立统一 ToolBoundary 与 Redis canonical invocation store,集中生命周期、证据状态、TTL、容量和 Run 所有权。 | Harness/Tool boundary/Canonical store | ISS-014, ToolBoundary, canonical invocation, PROJECTING, READY, ERROR, TTL, RESULT_TOO_LARGE | openspec/changes/archive/2026-07-21-single-react-tool-invocation-store | archived |
|
||||
| 2026-07-21 | single-react-harness-run-context | 建立显式 RunContext、Harness Core、预算、取消、类型化重试和 Tool Store 基础。 | Harness/Run lifecycle/Budget | ISS-014, RunContext, deadline, cancellation, budget, retry, ToolCallKey | openspec/changes/archive/2026-07-21-single-react-harness-run-context | archived |
|
||||
| 2026-07-21 | single-react-aci-tool-contracts | 冻结 RAG、日志和 MySQL evidence Tool 的 Agent-facing ACI Schema、状态、框架调用引用和描述边界。 | Harness/Agent Tool contract | ISS-014, ACI, tool_call_id, evidence_status, RAG, query_logs, query_mysql, MOCK | openspec/changes/archive/2026-07-21-single-react-aci-tool-contracts | archived |
|
||||
| 2026-07-21 | single-react-design-freeze | 冻结单体 Diagnosis Agent、Harness、Guard、工具证据与阶段门禁契约。 | Chat/Harness/Agent contract | ISS-014, single ReactAgent, Harness, EvidenceGuard, SemanticGuard, tool_call_id, evidence_status | openspec/changes/archive/2026-07-21-single-react-design-freeze | archived |
|
||||
| 2026-07-17 | chat-diagnosis-stategraph-cleanup-docs | 清理旧诊断编排闭包,对齐当前文档与 demo contract,并完成 ISS-011 最终 live、日志和数据库验收。 | Chat diagnosis orchestration/cleanup | legacy closure, current docs, orchestration trace, Maven E2E, MySQL ownership | openspec/changes/archive/2026-07-20-chat-diagnosis-stategraph-cleanup-docs | archived |
|
||||
| 2026-07-17 | chat-diagnosis-stategraph-test-suite | 建立 Workflow、Node Contract、Chat Integration 三层权威测试体系并退役旧 Hook implementation tests。 | Chat diagnosis orchestration/testing | workflow test, node contract, Chat integration, coverage matrix, Hook test retirement | openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-test-suite | archived |
|
||||
| 2026-07-17 | chat-diagnosis-stategraph-chatservice-cutover | 将复杂 Chat 单轨切换到 Diagnosis StateGraph,并增加 Run 级 orchestration trace 和 verified-only Verifier 输入。 | Chat diagnosis orchestration/production cutover | ChatService, CompiledGraph stream, runId metadata, orchestration trace, verified-only prompt, V012 | openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-chatservice-cutover | archived |
|
||||
| 2026-07-17 | chat-diagnosis-stategraph-real-nodes | 接入真实 Agent/Java Nodes、显式 Gatekeeper、可信输入投影、关键证据补查与安全 Fallback,暂不切换生产入口。 | Chat diagnosis orchestration/nodes | ReactAgent adapter, Gatekeeper node, verified input, evidence retry, safe fallback, CompiledGraph | openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-real-nodes | archived |
|
||||
| 2026-07-17 | chat-diagnosis-stategraph-routing-skeleton | 实现未接生产入口的 Diagnosis StateGraph 骨架、有限路由和 Fake Node 测试。 | Chat diagnosis orchestration/graph | StateGraph, fake node, conditional edge, retry counter, orchestration events, trace builder | openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-routing-skeleton | archived |
|
||||
| 2026-07-17 | chat-diagnosis-stategraph-design-freeze | 冻结 ISS-011 的 Graph State、条件边、有限重试、安全降级、审计和测试迁移边界。 | Chat diagnosis orchestration/design | StateGraph, runId, Gatekeeper, verified evidence, fallback, orchestration trace, test migration | openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-design-freeze | archived |
|
||||
| 2026-07-10 | session-run-trace-isolation | 拆分会话态和运行态,引入 runId 隔离 Trace、Feedback、AIOps 和 demo 链路。 | Trace/session/run isolation | chat_session, diagnosis_run, runId, trace exact run, feedback fallback, AIOps SSE metadata, baseline drift | openspec/changes/archive/2026-07-10-session-run-trace-isolation | archived |
|
||||
| 2026-07-09 | interview-demo-quality-audit | 增加面试演示前置质量审计,覆盖 prompt、Gatekeeper 和评测基线。 | Agent eval/demo/Prompt audit | interview demo preflight, prompt_audit, gatekeeper rules, diagnosis baseline, 12 fixtures | openspec/changes/archive/2026-07-09-interview-demo-quality-audit | archived |
|
||||
| 2026-07-08 | executor-composer-final-answer | 引入 Composer 生成最终回答,只使用 Verifier 允许的结论材料。 | Chat quality gate/evidence attribution | chat_composer, final answer, allowed_claims, allowed_hypotheses, safe fallback, composer_output | openspec/changes/archive/2026-07-08-executor-composer-final-answer | archived |
|
||||
@@ -51,10 +39,3 @@
|
||||
| 2026-06-24 | lookup-knowledge-integration | 接入知识库检索,支持 L0 精确匹配和 L1 语义检索。 | 知识库检索 | L0精确匹配, L1语义检索, frontmatter, 混合检索 | - | archived |
|
||||
| 2026-06-23 | phase1-infrastructure | 搭建第一阶段基础设施,包括 MySQL、Redis、Milvus、Flyway 和 JPA。 | 基础设施/文档管理 | MySQL, Redis, Milvus, Flyway, JPA, 向量检索, 类别过滤 | - | archived |
|
||||
| 2026-05-29 | chatmodel-abstraction | 抽象 ChatModel 和 EmbeddingModel,支持多模型路由。 | 解耦/多模型路由 | ChatModel, EmbeddingModel, DeepSeek, BGE-M3, SiliconFlow, Spring AI | - | archived |
|
||||
| 2026-07-21 | single-react-rag-log-projections | RAG/log projection adapters through ToolBoundary | Harness/Tool projection | ISS-014, RAG, query_logs, projection, scope, redaction, MOCK, NO_EVIDENCE | openspec/changes/archive/2026-07-21-single-react-rag-log-projections | archived |
|
||||
| 2026-07-21 | single-react-mysql-readonly-tool | Fail-closed read-only MySQL evidence Tool with AST allowlist, JDBC controls and bounded projection | Harness/MySQL security | ISS-014, MySQL, JSqlParser, allowlist, PreparedStatement, timeout, projection | openspec/changes/archive/2026-07-21-single-react-mysql-readonly-tool | archived |
|
||||
| 2026-07-21 | single-react-diagnosis-agent | Single internal Diagnosis ReactAgent with Harness-controlled model/tool loop, bounded context and typed Draft | Harness/Diagnosis Agent/ReAct | ISS-014, ReactAgent, DiagnosisDraft, PreviousTurn, ToolInterceptor, ModelInterceptor, budget | openspec/changes/archive/2026-07-21-single-react-diagnosis-agent | archived |
|
||||
| 2026-07-21 | single-react-evidence-semantic-guards | Deterministic evidence validation, isolated semantic review and fail-closed diagnosis release | Harness/EvidenceGuard/SemanticGuard/Release | ISS-014, EvidenceGuard, verified snapshot, SemanticGuard, repair, fallback, release policy | openspec/changes/archive/2026-07-21-single-react-evidence-semantic-guards | archived |
|
||||
| 2026-07-21 | single-react-chat-application-usecase | Internal Chat application use case with isolated routing, fixed executors and safe PreviousTurn | Harness/Chat application/Run persistence | ISS-014, Intent Router, PreviousTurn, PublishedResult, V012, observer, cancellation | openspec/changes/archive/2026-07-21-single-react-chat-application-usecase | archived |
|
||||
| 2026-07-21 | single-react-chat-sse-cutover | Unique named-event Chat SSE endpoint, bounded production Harness wiring and strict frontend consumer | Chat/SSE/Harness production wiring | ISS-014, /api/chat, SSE, metadata, status, content, failure, done, disconnect, bounded executor | openspec/changes/archive/2026-07-22-single-react-chat-sse-cutover | archived |
|
||||
| 2026-07-22 | single-react-cleanup-e2e | Remove legacy Agent paths, add bounded Harness audit, and complete exact-run live acceptance | Chat/Harness/cleanup/E2E | ISS-014, single ReAct Agent, durable audit, named SSE, exact run, Flyway V013 | openspec/changes/archive/2026-07-22-single-react-cleanup-e2e | archived |
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
- `devflow/index.md` was checked. Relevant history includes `session-storage`, `confidence-feedback`, `executor-action-memory-relevance`, and `chat-verifier-agent`.
|
||||
- `mvp/archive/2026-07-09-doc-cleanup/notes/agent-engineering-decisions.md` already recommends the next phase as "可复现 MVP Demo", including `mvp-demo` profile, fixed diagnosis case, one-click request, and `GET /api/diagnosis/{sessionId}/trace`.
|
||||
- `mvp/issues/archived/ISS-003-mvp-design-implementation-review.md` identifies test stability, session traceability, verifier evidence chain, upload path, and SupervisorAgent consistency as historical MVP concerns. Security cleanup was intentionally deferred by user decision at that time.
|
||||
- `mvp/issues/active/ISS-003-mvp-design-implementation-review.md` identifies test stability, session traceability, verifier evidence chain, upload path, and SupervisorAgent consistency as recent MVP concerns. Security cleanup is intentionally deferred by user decision.
|
||||
|
||||
## Question Pool
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Draft Acceptance
|
||||
|
||||
- [x] Issue exists: `mvp/issues/archived/executor-evidence-attribution-hallucination.md`.
|
||||
- [x] Issue exists: `mvp/issues/active/executor-evidence-attribution-hallucination.md`.
|
||||
- [x] OpenSpec change artifacts exist.
|
||||
- [x] devflow tracking files exist.
|
||||
- [x] OpenSpec validation passes.
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
# Chat Diagnosis StateGraph ChatService Cutover 验收
|
||||
|
||||
## 结果
|
||||
|
||||
已接受。OpenSpec tasks 26/26 完成,阶段 3 可归档。
|
||||
|
||||
## 验证
|
||||
|
||||
### 静态验证
|
||||
|
||||
- `git diff --check`:通过。
|
||||
- source/reference isolation:cutover 核心文件中的 `SequentialAgent`、`VerifierContextHolder`、`VerifierInputHook`、`tool_trace_summary` 命中 0;核心 TODO/FIXME/placeholder 命中 0。
|
||||
- schema whitelist:V012 为 1 个 ALTER TABLE、1 个 ADD COLUMN、0 CREATE、0 DROP,目标仅 `diagnosis_run.orchestration_trace JSON NULL`。
|
||||
- `openspec validate chat-diagnosis-stategraph-chatservice-cutover --strict`:通过。
|
||||
- `openspec validate --specs --strict`:14 passed,0 failed。
|
||||
|
||||
### 脚本验证
|
||||
|
||||
- focused Maven regression:Graph runtime/result mapper/real nodes、ChatService cutover、Trace、Controller、Repository、Gatekeeper、Composer、Eval,共 27 suites / 119 tests;0 failures、0 errors、0 skipped。
|
||||
- `mvn -q -DskipTests test-compile`:通过。
|
||||
- `ChatServiceGraphIntegrationTest` 覆盖 SUCCESS、handled Fallback、unhandled failure、blank answer/partial trace 和同 session 多 Run 隔离。
|
||||
|
||||
### 浏览器/人工验证
|
||||
|
||||
- 未运行。阶段 3 的公开协议由 Controller/service tests 覆盖,完整人工/live 验收按用户规则保留到阶段 5。
|
||||
|
||||
### 未验证
|
||||
|
||||
- 未使用 Maven 启动应用做 live E2E。
|
||||
- 未检查 `logs/` 运行日志。
|
||||
- 未执行 `scripts/query_mysql.py` 查询真实数据库。
|
||||
- 原因:用户明确要求只有阶段 5 全部完成后统一执行端到端、日志和数据库验收;阶段 3 只做风险相关自动化验证。
|
||||
- 剩余风险:真实模型/工具调用下的 Prompt 行为、Flyway 在真实 MySQL 的应用结果和最终 Trace 数据须由阶段 5 E2E 证明。
|
||||
|
||||
## 已完成范围
|
||||
|
||||
- 复杂 Chat 唯一生产编排切换到 Diagnosis StateGraph,公开 ChatResult 保持兼容。
|
||||
- Run 生命周期、metrics、Eval、finally cleanup 与 runId 隔离保持;handled Fallback=SUCCESS,未处理/空答案=FAILED。
|
||||
- 新增 Run 级 compact orchestration trace,并只在 Trace run 对象暴露解析结果。
|
||||
- Verifier Prompt/self-evaluation 使用 verified-only 数据,不伪造未发生 verdict/event。
|
||||
- 移除冲突的 Sequential 实现测试并以 Graph/public contract tests 替代。
|
||||
|
||||
## Bug 修复和诊断
|
||||
|
||||
- 替代测试错误引用 `com.superbiz.agent.tool.ToolInvocationRecorder`:通过定义/引用搜索确认类型位于同一 `service` 包,删除错误 import。
|
||||
- no-answer 新测试错误期待 inner cause:分类为测试断言偏差,改为公开 wrapper error,同时保留 FAILED 与真实 partial trace 核心断言。
|
||||
|
||||
## 交接
|
||||
|
||||
- OpenSpec archive:已同步 5 份 delta specs,并归档到 `openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-chatservice-cutover/`。
|
||||
- 下一步:审查精确 Git diff 并完成阶段 3 独立提交,之后才启动阶段 4。
|
||||
- OpenSpec 归档确认:用户已明确授权后续阶段直接实现/归档;归档已完成。
|
||||
@@ -0,0 +1,21 @@
|
||||
# Chat Diagnosis StateGraph ChatService Cutover Brief
|
||||
|
||||
## 背景
|
||||
|
||||
- 用户目标:将 ISS-011 阶段 3 作为独立 sm-flow,正式切换复杂 Chat 生产编排并增加 Run 级 orchestration trace。
|
||||
- 当前问题:真实 Diagnosis Graph Nodes 已存在,但生产入口仍依赖 SequentialAgent、外层重试和 ThreadLocal/Hook 隐式状态。
|
||||
- 关联 OpenSpec:`openspec/changes/chat-diagnosis-stategraph-chatservice-cutover/`
|
||||
- devflow 分档:complex。
|
||||
|
||||
## 范围
|
||||
|
||||
- 本次要做:复杂 Chat 单轨 Graph cutover;复用四类 Agent builder;Graph result/self-evaluation 映射;V012 Run JSON 字段;Trace run-only 投影;verified-only Verifier Prompt;必要回归测试。
|
||||
- 本次不做:不改 `/api/chat` 请求/响应,不做历史 trace 回填,不删除仍供历史代码/测试使用的 Hook/ThreadLocal 类型,不完成阶段 4 测试体系全面收敛,不运行 live E2E/log/DB 验收。
|
||||
- 影响区域:ChatService、Diagnosis Graph runtime/result mapper、DiagnosisRun/Flyway、Trace DTO/service、Verifier Prompt、Graph/Service/Trace tests。
|
||||
|
||||
## OpenSpec 对齐
|
||||
|
||||
- proposal 覆盖状态:已覆盖。
|
||||
- design 覆盖状态:已覆盖。
|
||||
- specs 覆盖状态:已覆盖,5 个 delta capabilities。
|
||||
- tasks 覆盖状态:26/26 已完成。
|
||||
+207
@@ -0,0 +1,207 @@
|
||||
# Chat Diagnosis StateGraph ChatService Cutover Decisions
|
||||
|
||||
## Entry Summary
|
||||
|
||||
- 问题:复杂 Chat 仍使用 SequentialAgent + ThreadLocal/Hook 隐式状态机,真实 Graph 尚未成为生产入口,也没有 Run 级 orchestration trace 持久化和 API 投影。
|
||||
- 期望:阶段 3 独立完成生产 cutover、Run/Trace 映射和必要测试,归档并提交后才进入阶段 4。
|
||||
- 分档:complex。
|
||||
- Change:`chat-diagnosis-stategraph-chatservice-cutover`。
|
||||
- 授权:用户已要求后续阶段直接实现,不再逐 checkpoint 等待;阶段门禁、独立 archive/commit 与阶段 5 才 E2E 约束不变。
|
||||
|
||||
## Context Sources
|
||||
|
||||
- `mvp/issues/active/ISS-011-chat-diagnosis-stategraph-orchestration.md` 阶段 3、协议影响、Run 状态和验收章节。
|
||||
- 阶段 0–2 OpenSpec archives、devflow acceptance/decisions 与当前四份 Graph 主 specs。
|
||||
- `devflow/glossary/CONTEXT.md` 中 Chat Session、Diagnosis Run、Diagnosis Trace、Diagnosis Orchestration Trace 的边界。
|
||||
- `ChatService` 生产调用链、四个 Agent builder、Run persistence/self-evaluation/metrics 逻辑。
|
||||
- `DiagnosisRun`、V011 migration、`DiagnosisTraceResponse`、`DiagnosisTraceService` 与相关 tests。
|
||||
- `DiagnosisGraphFactory`、真实 action factory、Node adapters、final trace builder 和本地 CompiledGraph API。
|
||||
|
||||
## Question Pool
|
||||
|
||||
| # | 维度 | 问题 | 模式 | 状态 |
|
||||
|---|---|---|---|---|
|
||||
| Q1 | 术语 | orchestration trace 是否属于 self-evaluation 或完整 Trace event log? | evidence-driven | 已解决 |
|
||||
| Q2 | 边界 | 阶段 3 是否改变 `/api/chat`,以及 Trace 字段出现在哪一层? | user-interview(既有冻结决策) | 已确认 |
|
||||
| Q3 | 生命周期 | LOW_CONFID/REJECT/Fallback 是否应使用 FAILED 或新增 DEGRADED? | user-interview(既有冻结决策) | 已确认 |
|
||||
| Q4 | 错误处理 | Graph 异常时如何 best-effort 保存已有编排事实而不伪造 event? | evidence-driven | 已解决 |
|
||||
| Q5 | 技术实现 | 是否复用现有 Agent factory/Hook/ToolCallback 与真实 Node assembly? | evidence-driven | 已解决 |
|
||||
| Q6 | 安全 | Graph Verifier Prompt/self-evaluation 是否可继续使用 raw Executor 和完整 tool trace? | evidence-driven | 已解决 |
|
||||
| Q7 | 验收 | 阶段 3 是否需要新增测试,是否现在运行 live E2E? | user-interview(用户最新规则) | 已确认 |
|
||||
|
||||
## Evidence-driven Findings
|
||||
|
||||
- Q1:glossary 与阶段 0 spec 已定义 orchestration trace 为 Run 级紧凑编排摘要,与 self-evaluation、AgentStep/ToolInvocation 和 checkpoint 分离;无需新增术语或 ADR。
|
||||
- Q4:所有已定义 Agent/Java 失败应由 Graph 路由到 handled Fallback 并返回 final state;只有真实可取得的 final/partial state 才可构造 trace。无法取得 state 的未处理异常标记 Run FAILED,不得生成虚假 transition。
|
||||
- Q5:`DiagnosisRealGraphActionsFactory` 已提供真实 Node assembly;ChatService 现有四个 builder、AgentLoggingHook、Skills hooks、method tools 和 ToolCallbacks 可直接构造 ReactAgent,再通过 `ReactAgentDiagnosisInvoker` 注入,不得复制 Prompt/Agent factory。
|
||||
- Q6:阶段 2 spec 已禁止 Graph Verifier 使用 raw Executor/full tool trace;当前 `chat-verifier-prompt.md` 仍描述旧 Hook payload,是阶段 3 必须同步的明确 gap。self-evaluation 可保存 Graph 的 verified output、Gatekeeper audit 和 Composer audit,但不能重新引入 raw 输入。
|
||||
|
||||
## User-interview Confirmations
|
||||
|
||||
| 问题 | 用户原话/既有确认 | 确认状态 | OpenSpec 回写 |
|
||||
|---|---|---|---|
|
||||
| Q2 外部协议与 Trace 层级 | ISS-011 已冻结 `/api/chat` 不变,Trace 只在 `run.orchestrationTrace` 增解析对象 | 已确认 | proposal |
|
||||
| Q3 Run 生命周期 | ISS-011 已冻结安全 Fallback 为 SUCCESS,不新增 DEGRADED;只有无法生成安全响应的未处理失败为 FAILED | 已确认 | proposal |
|
||||
| Q7 验收节奏 | “端到端只在最后阶段全部完成后才验证;每个阶段如果有必要添加单元测试验收的话,就加” | 已确认 | proposal |
|
||||
|
||||
## Interface Impact
|
||||
|
||||
- 等级:L4。
|
||||
- 原因:复杂 Chat 内部状态机正式切换;DiagnosisRun 增加数据库 JSON 契约;Trace run 对象新增字段;旧固定顺序消费者/测试不再成立。
|
||||
- 保持兼容:`/api/chat` request/response、sessionId/runId、Executor/Verifier/Composer 输出契约不变。
|
||||
- 加法变化:只新增 `diagnosis_run.orchestration_trace` 和 `run.orchestrationTrace`。
|
||||
- 回滚:revert 阶段 3 代码/Prompt/spec,数据库列可保留 nullable;不保留运行时双轨开关。
|
||||
|
||||
## Discover Status
|
||||
|
||||
- `devflow/index.md`:命中阶段 0–2 archives 和 Run/Trace 历史项目。
|
||||
- Glossary:相关术语已存在且无冲突,不需更新。
|
||||
- ADR:阶段 0 已记录难以逆转的状态机/Trace 决策,本阶段没有新的三条件 ADR。
|
||||
- 未解决问题:0。
|
||||
- Draft 产物:当前只创建 proposal + decisions;design/specs/tasks 留到 Commit checkpoint。
|
||||
|
||||
## Grill-with-docs Review
|
||||
|
||||
### Domain model stress test
|
||||
|
||||
- 同一 session 连续两个复杂 Chat run:每次编译/执行使用自己的 runId threadId 和 metadata;orchestration trace 只写各自 DiagnosisRun,session 投影不复制,符合 Session/Run/Trace 领域边界。
|
||||
- Gatekeeper REJECT 或 Planner/Executor 技术失败:Graph 进入确定性 Fallback,返回安全非空答案;Run 为 SUCCESS,trace `degraded=true`,不会把诊断质量塞进 Run status。
|
||||
- Composer 成功但 verdict=LOW_CONFID/REJECT:Run 仍为 SUCCESS;self-evaluation 保存 effective verdict,orchestration trace 保存实际路径,两者职责不混合。
|
||||
- Graph 未处理异常:使用流式 NodeOutput 捕获最后一个真实 state,只有其中已有 events 时才 best-effort 构造 partial trace;没有 event 时不伪造 transition,Run 标记 FAILED。
|
||||
- 历史/AI_OPS run:新增列 nullable,Trace DTO 对旧 run 可返回 null;不增加历史回填或跨 flow 假数据。
|
||||
|
||||
### Design tree conclusions
|
||||
|
||||
- 生产切换采用单轨,不增加 feature flag 或保留 Sequential/Graph 双运行;回滚依靠 Git revert,nullable 列可保留。
|
||||
- ChatService 负责 Run 生命周期和调用一个专用 Graph runtime/orchestrator;复杂 Agent 构造从旧 Sequential 私有流程中搬移或封装复用,不复制第二套 builder。
|
||||
- Graph 执行优先使用可观察的 `CompiledGraph.stream(..., config)` 收集最后真实 state,以支持异常时 best-effort trace;正常终止仍以 END state 的 `final_answer` 为唯一答案来源。
|
||||
- Graph result mapping 形成独立组件:final answer、Verifier evaluation、Composer audit、Gatekeeper audit、trace JSON 均从显式 final state读取,不再访问 VerifierContextHolder。
|
||||
- Verifier Prompt 必须更新为 `diagnosis_context`、`verified_executor_output`、`verified_evidence`、`gatekeeper_audit`、`verdict_ceiling` 和可选 retry context;删除 raw Executor/full tool trace/Hook Gatekeeper 说明。
|
||||
- 阶段 3 必须有 production cutover 与 Trace DTO/Service tests;阶段 4 再做测试体系全面改名、夹具收敛和旧测试删除。
|
||||
|
||||
### Documentation result
|
||||
|
||||
- 术语与 `devflow/glossary/CONTEXT.md` 完全一致,无需修改 glossary。
|
||||
- 状态机、Run status 和 orchestration trace 隔离均来自阶段 0 已归档 ADR/规格,不创建重复 ADR。
|
||||
- proposal 已反映单轨切换、L4 接口影响、流式 partial-state 处理、Prompt 安全边界和阶段 5 E2E 延期。
|
||||
- Grill question pool 全部关闭;无需要再次询问用户的产品取舍。
|
||||
|
||||
## Architecture Audit
|
||||
|
||||
### Module and caller map
|
||||
|
||||
`ChatController` 的 normal/SSE 两个入口都调用 `ChatService.executeChatWithStrategy`,复杂分支进入 `executeChatComplex`;对外仍只消费 `ChatResult(answer, sessionId, runId)`。阶段 3 将内部链路变为 `ChatService Run lifecycle -> complex Chat Graph runtime/Agent assembly -> real Diagnosis Nodes -> Graph result mapper -> DiagnosisRun persistence -> DiagnosisTraceService`。Trace UI/Eval 当前读取兼容 `session.selfEvaluation`,它仍由 Run self-evaluation 投影;新增 orchestration trace 只属于 `run`。AIOps、Feedback、CaseLibrary 和 Run list 继续使用 DiagnosisRun 既有字段,不消费新增 orchestration trace。
|
||||
|
||||
| 模块 | 所有权 | 允许的依赖/影响 |
|
||||
|---|---|---|
|
||||
| ChatController | `/api/chat` normal/SSE 协议 | 继续只依赖 ChatResult;无字段变化 |
|
||||
| ChatService | Chat Session/Diagnosis Run 生命周期、成功/失败保存、metrics、Eval、finally cleanup | 调用一个 Graph runtime/result mapper;不再拥有条件边/重试/Gatekeeper/Composer 路由 |
|
||||
| Complex Chat Graph runtime | 每请求 Agent assembly、initial state、RunnableConfig、CompiledGraph stream | 复用现有 Prompt/tool/skill/logging;不持久化跨 Run 状态 |
|
||||
| Diagnosis Graph | Node status、verified material、events、final answer | 保持阶段 1/2 路由和 counter 所有权 |
|
||||
| Graph result mapper | final/partial state 到安全 evaluation/trace DTO | 不读 ThreadLocal,不查询其他 run,不持久化 raw material |
|
||||
| DiagnosisRun/Flyway | 当前 Run 的 orchestration JSON | 仅一个 nullable JSON 列;历史/AIOps 可为 null |
|
||||
| DiagnosisTraceService/DTO | exact/latest Run 查询和 API 投影 | 只在 RunTrace 加 parsed map;session/top-level/run-list 不重复 |
|
||||
|
||||
### Lifecycle and coupling audit
|
||||
|
||||
ReactAgent 与 CompiledGraph 都按请求构造,因为 Planner/Executor system Prompt 含本次 history/knowledge map;Graph State 和 runtime last-state holder 也是 invocation-scoped,不进入 singleton 可变字段。SessionContextHolder 仍只包围当前请求并在 finally 清理;Graph Node config 以 runId threadId + metadata 绑定 AgentStep、ToolInvocation 和 Gatekeeper。success persistence 在 Eval 之前完成,EvaluationService 再按 runId 合并 rule channel;handled Fallback 与 Composer 使用同一 SUCCESS 路径。Trace JSON 与 self-evaluation 分栏,避免把路线、质量和完整 Agent/tool 明细耦合到一个容器。
|
||||
|
||||
### Consumer impact audit
|
||||
|
||||
- ChatController normal/SSE:ChatResult 协议不变,L4 内部切换不要求调用方迁移。
|
||||
- Trace UI/demo:继续读取兼容 `session.selfEvaluation`;新的 `run.orchestrationTrace` 是加法字段,最终脚本断言留到阶段 5。
|
||||
- DiagnosisTraceEvaluator:现有 fixtures 不变;工具覆盖仍可从 `toolInvocations` 读取,兼容 `executor_structured_output` 保存 verified projection。pre-verification Fallback 质量未来应以 trace degraded 而非伪 verdict 判断,属于阶段 4 测试体系/阶段 5文档收尾。
|
||||
- AIOps/Feedback/CaseLibrary/Run list:实体新增 nullable 字段不改变 builder call sites或查询语义。
|
||||
- 数据库:Hibernate validate 要求 V012 与 entity 同批;回滚代码可忽略保留列。
|
||||
|
||||
### Cross-artifact alignment
|
||||
|
||||
| 对齐链 | 结果 | 证据 |
|
||||
|---|---|---|
|
||||
| brief/proposal 目标、范围、非目标 → proposal | 已对齐 | 单轨 cutover、Run/Trace、Prompt、阶段边界与 E2E 延期均明确 |
|
||||
| proposal 承诺与约束 → design | 已对齐 | 10 项决策覆盖 runtime、state、config、partial state、result、persistence、DB/API/Prompt/tests |
|
||||
| design 架构/接口结论 → specs/tasks | 已对齐 | L4、单轨、Run status、verified-only、Trace 唯一投影和 schema whitelist 均有 requirement/task |
|
||||
| specs 可观察行为 → tasks 可执行切片 | 已对齐 | 6 组 26 个切片覆盖数据、runtime、Prompt、cutover、tests、handoff |
|
||||
|
||||
### Audit result
|
||||
|
||||
未发现与阶段 0–2、Run/Trace ADR 或 glossary 冲突。审计确认不能把 Agent factory 复制进 Node,也不能把 pre-verification Fallback 伪装为 Verifier verdict;两项已在 design/specs/tasks 固定。唯一跨阶段依赖是阶段 4 让测试/Eval 以 orchestration degraded 理解无 Verifier verdict 的安全 Fallback,已记录但不阻塞阶段 3 production correctness。架构风险可接受,cross-artifact gap=0,无未解决接口消费者。
|
||||
|
||||
## Commit Gate
|
||||
|
||||
- schema:spec-driven;proposal/design/specs/tasks 全部 done,applyRequires=`tasks` 已满足。
|
||||
- OpenSpec:当前 change strict validation 通过;14 个主 specs 全部 strict pass。
|
||||
- 规格结构:5 个 delta capabilities、23 条 requirements、72 个 scenarios;tasks 26 个可执行 checkbox。
|
||||
- Cross-artifact:4/4 已对齐,gap=0。
|
||||
- Interface impact:L4;design 已独立记录消费者、加法 DB/Trace 协议、单轨迁移和 Git revert 回滚。
|
||||
- Question pool:所有 evidence-driven 已查证;所有 user-interview 已由 ISS-011/用户原话确认;无未决项。
|
||||
- Preflight:`git diff --check` 通过;Commit checkpoint 尚未修改 Java、SQL、Prompt 或测试。
|
||||
- 结论:Draft OpenSpec 已达到可执行状态,创建 `.committed`,阶段 3 Apply 只能以这些产物为依据。
|
||||
|
||||
## Apply Authorization
|
||||
|
||||
- 用户原话:“直接实现吧,不用找我授权了”。
|
||||
- 本阶段在 Commit gate 后直接进入 Apply;不扩大到阶段 4 全面测试迁移或阶段 5 live E2E。
|
||||
|
||||
## Pre-apply Research
|
||||
|
||||
### Reference implementations read
|
||||
|
||||
- `ChatService.executeChatComplex`、四个 complex Agent builders、Run start/save、metrics、Prompt audit、self-evaluation merge:迁移源实现和外部兼容基线。
|
||||
- `DiagnosisGraphFactory`、`DiagnosisRealGraphActionsFactory`、四个 Agent adapters、Gatekeeper/VerifiedInput/Fallback、`DiagnosisOrchestrationTraceBuilder`:Graph 路由/计数/安全材料唯一真理源。
|
||||
- `DiagnosisRun`、V011 migration、`DiagnosisTraceResponse`、`DiagnosisTraceService`、`DiagnosisTraceServiceTest`:Run JSON 字段和 exact/latest Trace 映射标准。
|
||||
- `ChatController` normal/SSE、`DiagnosisTraceController`:公开协议调用者与响应包装边界。
|
||||
- `SelfEvaluationMergeService`、`EvaluationService`、`DiagnosisTraceEvaluator`:evaluation container、异步 rule merge 和兼容消费者。
|
||||
- 本地 graph-core 1.1.2.0 `javap`:CompiledGraph `stream/invoke/state`、NodeOutput `state()`、RunnableConfig `threadId/metadata` 的真实 API。
|
||||
- `chat-*-prompt.md`:现有 Prompt 组装与 Verifier 旧 Hook payload gap。
|
||||
|
||||
### Technology inventory
|
||||
|
||||
| 类别 | 项目标准 / 本阶段使用 |
|
||||
|---|---|
|
||||
| Graph execution | `CompiledGraph.stream(initial, config)` + NodeOutput.state,当前请求线程阻塞消费 |
|
||||
| Run context | SessionContextHolder + RunnableConfig threadId/metadata;runId 是唯一执行边界 |
|
||||
| Agent assembly | ReactAgent builder、AgentLoggingHook、PlannerSkillMetadataHook/SkillsAgentHook、现有 tools/callbacks |
|
||||
| JSON persistence | Jackson map serialization;实体 String + `@JdbcTypeCode(SqlTypes.JSON)`;Flyway JSON column |
|
||||
| Trace API | Lombok DTO builder + DiagnosisTraceService parsed Map;exact/latest Run 查询 |
|
||||
| Evaluation | SelfEvaluationMergeService container;EvaluationService 按 runId 异步合并 rule channel |
|
||||
| Tests | JUnit 5,通过 public service/runtime/Trace API;只 mock repository/model/tool 外部边界 |
|
||||
| MQ/Consumer | 不涉及 |
|
||||
|
||||
### New infrastructure and reuse
|
||||
|
||||
- 新增一个深接口的 complex Chat Graph runtime/result mapper;复用既有 Graph/Node/Agent builders,不增加新依赖或第二套路由。
|
||||
- 新增 V012、DiagnosisRun 字段和 RunTrace parsed map;不新增表、repository method 或历史 backfill。
|
||||
- TDD tracer bullet 从 Trace DTO/Service 的唯一 Run 投影开始,再进入 runtime final-state mapping,最后切换 ChatService。
|
||||
- 研究未发现 devflow/OpenSpec 冲突,技术清单足以开始实现。
|
||||
|
||||
## Apply Progress
|
||||
|
||||
- TDD Trace slice RED:DiagnosisTraceServiceTest 明确缺少 DiagnosisRun builder 字段和 RunTrace getter。
|
||||
- GREEN:V012、DiagnosisRun JSON 字段、RunTrace parsed map、DiagnosisTraceService mapping 完成;10 个 Trace service tests 通过。
|
||||
- 失败分类:首次 GREEN 运行仅测试夹具用裸 ObjectMapper 无法序列化 LocalDateTime,属于 test harness 偏差;改为项目可用的 `findAndRegisterModules()` 后原始 focused loop 通过,未改业务协议。
|
||||
- Trace API JSON 断言证明顶层/session 无重复字段、run 为解析对象、无 raw 字段;null/invalid JSON fail closed。
|
||||
|
||||
## Apply Completion
|
||||
|
||||
- 复杂 Chat 已单轨切换到 `ChatDiagnosisGraphRuntime`;生产 `ChatService` 不再创建 `SequentialAgent`,不再读取 `VerifierContextHolder`,Graph Verifier 只保留 `AgentLoggingHook`。
|
||||
- runtime 使用 query-only initial state、`threadId=runId` 和 sessionId/runId metadata,流式保留最后真实 state;异常只保存真实 partial state/trace。
|
||||
- `DiagnosisGraphResultMapper` 只从 verified projection 构造兼容 self-evaluation;Verifier 未完成时不伪造 verdict,不持久化 full tool trace/raw Executor。
|
||||
- Verifier Prompt 与 runtime payload 已统一为 verified-only,Prompt audit 更新为 `chat-prompts-v2` / `chat-verifier-v3`。
|
||||
- 旧 `ChatServiceSequentialAgentTest` 因绑定已删除的固定顺序/ThreadLocal/score retry 实现而移除,由 public service/runtime/route tests 替代。
|
||||
- V012 schema 白名单测试确认只新增 `diagnosis_run.orchestration_trace JSON NULL`,无其他 schema object。
|
||||
|
||||
## Verification Summary
|
||||
|
||||
- focused regression:27 suites / 119 tests,0 failures、0 errors、0 skipped。
|
||||
- Maven test compilation:通过。
|
||||
- OpenSpec:当前 change strict pass;主 specs 14/14 strict pass。
|
||||
- 静态门禁:`git diff --check` 通过;cutover 禁用引用 0;核心 TODO/placeholder 0;schema whitelist 为 1 ALTER / 1 ADD COLUMN / 0 CREATE / 0 DROP。
|
||||
- 实现期唯一失败分类:no-answer service test 曾错误期待 inner cause 文本,属于测试断言偏差;按公开 wrapper error + FAILED/partial trace 契约修正后通过,OpenSpec 与生产代码无需变更。
|
||||
- 按阶段门禁未运行 Maven live E2E、未检查 `logs/`、未执行 `scripts/query_mysql.py`;统一保留到阶段 5。
|
||||
|
||||
## Archive Result
|
||||
|
||||
- 5 份 delta specs 已同步:新增 9、修改 13、删除 1 条 requirements。
|
||||
- OpenSpec 已归档到 `openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-chatservice-cutover/`。
|
||||
- CLI 对 proposal 结构给出非阻塞建议(大 change/delta 拆分与 SHALL/scenario 启发式);tasks 26/26、delta specs 和 strict validation 均通过,未形成验收阻塞。
|
||||
@@ -0,0 +1,21 @@
|
||||
# Chat Diagnosis StateGraph ChatService Cutover Evidence
|
||||
|
||||
## 证据
|
||||
|
||||
| 来源 | 证据 | 结论 | 是否已汇报 |
|
||||
|---|---|---|---|
|
||||
| `ChatService` + source isolation search | 复杂路径只有一次 Graph runtime 调用,无 SequentialAgent、VerifierContextHolder、VerifierInputHook 或 score retry | 单轨 cutover 完成,简单 Chat 路径未改 | 是 |
|
||||
| `ChatDiagnosisGraphRuntimeTest` / `DiagnosisRealGraphIntegrationTest` | query-only state、runId thread/metadata、Composer/Fallback、empty stream、blank answer、partial trace、Gatekeeper once/twice | Graph identity、路由和真实 partial-state 边界可观察 | 是 |
|
||||
| `DiagnosisGraphResultMapperTest` / `ChatVerifierPromptContractTest` | verified projection、effective verdict 兼容、pre-verification 无伪 verdict、禁用 raw/full trace 字段 | self-evaluation 与 Prompt 安全边界一致 | 是 |
|
||||
| `ChatServiceGraphIntegrationTest` | ChatResult、agent_flow、SUCCESS/Fallback/FAILED、metrics/Eval、partial trace、多 Run 隔离 | 生产生命周期与兼容返回满足阶段 3 规格 | 是 |
|
||||
| `DiagnosisTraceServiceTest` | `run.orchestrationTrace` 解析对象、top/session 无重复、invalid/null fail closed | Trace 字段所有权保持 Run 隔离 | 是 |
|
||||
| `DiagnosisRunSchemaContractTest` | V012 executable SQL 与唯一允许语句精确相等 | schema 仅增加一个 nullable JSON 列 | 是 |
|
||||
| focused Maven suite | 27 suites / 119 tests,0 failures/errors/skipped | Graph、Controller、Repository、Gatekeeper、Composer、Eval 回归通过 | 是 |
|
||||
| OpenSpec/static gates | change strict、14/14 主 specs、test compile、diff check、禁用引用/占位/schema whitelist 全通过 | 规格、编译和源级隔离闭环 | 是 |
|
||||
|
||||
## Evidence-driven 结论
|
||||
|
||||
- orchestration trace 必须独立于 self-evaluation 和详细 Agent/tool Trace;V012 与 RunTrace 的实现保持这一边界。
|
||||
- handled Fallback 表示安全降级答案,Run 仍为 SUCCESS;未处理、空答案或 invariant 失败才是 FAILED。
|
||||
- Verifier/Gatekeeper 只以显式 Graph state 传递可信材料;继续使用 Hook/ThreadLocal 会形成双 Gatekeeper 和不安全输入,因此生产路径已彻底移除该依赖。
|
||||
- 旧 Sequential 测试验证的是已废止内部机制,替换为 public service + runtime + route contract tests 才能保持真实回归价值。
|
||||
@@ -0,0 +1,49 @@
|
||||
# Acceptance
|
||||
|
||||
## 静态验证
|
||||
|
||||
- 旧闭包路径不存在,executable legacy refs=0。
|
||||
- current-doc stale architecture refs=0;历史兼容引用有明确限定。
|
||||
- `git diff --check` 通过;无新增 migration/schema 变更;临时调试标记=0。
|
||||
- 当前 change strict 和 16 个 main specs strict 全部通过。
|
||||
|
||||
## 脚本验证
|
||||
|
||||
- `mvn -q -DskipTests test-compile`:通过。
|
||||
- 39-suite authoritative/focused Maven command:157 tests,0 failure/error/skipped。
|
||||
- 归档前 `mvn clean` + test compilation + 43-suite deterministic command:189 tests,0 failure/error/skipped。
|
||||
- `DiagnosisTraceEvaluatorTest` + `DiagnosisEvalBaselineDiffTest`:12/12 baseline,same diff=0。
|
||||
- PowerShell parser + `InterviewDemoScriptContractTest`:通过。
|
||||
- `run-interview-demo-check.ps1 -SessionId iss-011-stage5-20260720015557 -OutputDir target/iss-011-stage5-output-current`:exit 0。
|
||||
- `scripts/query_mysql.py` exact queries:V012、Run JSON、AgentStep/ToolInvocation ownership 全部通过。
|
||||
- `openspec validate --all --strict --no-interactive`:17/17 passed;`git diff --check`、current-doc、schema、debug source、port/temp scope checks 通过。
|
||||
|
||||
## Live E2E
|
||||
|
||||
| 项目 | 结果 |
|
||||
|---|---|
|
||||
| Maven profile | `mvp-demo` |
|
||||
| sessionId | `iss-011-stage5-20260720015557` |
|
||||
| runId | `run-808ac38f-3ad0-4462-a6d0-ed50d8686473` |
|
||||
| Run | `CHAT/SUCCESS` |
|
||||
| answer / metrics | 109 chars / 75964ms / 111802 tokens / 8 steps / 12 tools |
|
||||
| Graph | `stategraph-v1`, `fallback`, `fallback_completed`, degraded=true, 3 transitions, retry=0 |
|
||||
| evaluation / feedback | non-empty / useful |
|
||||
| new ERROR | 0 |
|
||||
| DB ownership | wrong owner=0,wrong-session rows=0 |
|
||||
| process cleanup | owned PIDs stopped,9900 released |
|
||||
|
||||
## 浏览器/人工验证
|
||||
|
||||
- 不适用。本阶段验收入口是 API/PowerShell executable contract,无 UI 改动。
|
||||
|
||||
## 未验证
|
||||
|
||||
- 无 OpenSpec 必需项未验证。
|
||||
|
||||
## 归档状态
|
||||
|
||||
- ISS-011 已归档至 `mvp/issues/archived/ISS-011-chat-diagnosis-stategraph-orchestration.md`。
|
||||
- OpenSpec 归档路径:`openspec/changes/archive/2026-07-20-chat-diagnosis-stategraph-cleanup-docs`。
|
||||
- OpenSpec CLI 已同步主 specs:新增 `chat-diagnosis-stategraph-cleanup-docs`,更新 `mvp-demo-trace-acceptance` 3 项 requirement。
|
||||
- 不 push。
|
||||
@@ -0,0 +1,32 @@
|
||||
# Chat Diagnosis StateGraph Cleanup And Final Acceptance
|
||||
|
||||
## 背景
|
||||
|
||||
ISS-011 阶段 0-4 已完成 StateGraph 设计冻结、路由骨架、真实 Nodes、ChatService 单轨切换和三层权威测试。阶段 5 负责删除旧 Hook/ThreadLocal/full-trace service 闭包、对齐当前文档与 demo executable contract,并以唯一 Run 完成最终 Maven、日志和数据库验收。
|
||||
|
||||
## 目标
|
||||
|
||||
- 只保留 bounded StateGraph 复杂 Chat 编排和 verified-only Verifier 输入。
|
||||
- 让 current architecture/eval/demo 文档与 Run-owned orchestration trace 一致。
|
||||
- 先通过确定性回归,再用 Maven `mvp-demo` 证明 exact Chat/Trace/feedback、日志和数据库 ownership。
|
||||
- 所有门禁通过后关闭 ISS-011,并归档阶段 5 OpenSpec。
|
||||
|
||||
## 范围
|
||||
|
||||
- 删除 `VerifierInputHook`、`VerifierContextHolder`、`ToolTraceSummaryService` 及其 focused test。
|
||||
- 更新 current architecture/eval/demo 文档和 interview demo check。
|
||||
- 修复 live 暴露的 Graph event classloader 边界与 nested ReactAgent resume config 问题。
|
||||
- 完成 Graph/Chat/Trace/Eval 回归、Maven live E2E、日志/MySQL 核验、进程清理和 Issue 生命周期收口。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不修改公开 Chat/feedback API、Executor/Verifier/Composer 业务协议或数据库 schema。
|
||||
- 不重写 archived issues、历史 design notes 和 legacy fixtures。
|
||||
- 不删除旧 Trace/fixture 对 `tool_trace_summary` 的只读兼容。
|
||||
- 不 push,不删除失败尝试的审计数据。
|
||||
|
||||
## 元数据
|
||||
|
||||
- 分档:complex
|
||||
- OpenSpec:`chat-diagnosis-stategraph-cleanup-docs`
|
||||
- 接口影响:L2 内部类型/状态表示修复;外部 API/DTO/schema 不变
|
||||
@@ -0,0 +1,159 @@
|
||||
# Chat Diagnosis StateGraph Cleanup, Final Acceptance And Documentation Decisions
|
||||
|
||||
## Entry Summary
|
||||
|
||||
- 问题:ISS-011 运行时已切换且测试体系已收敛,但旧 Hook/ThreadLocal/service死代码、当前架构文档和最终 live 证据尚未闭环。
|
||||
- 期望:阶段 5完成清理、文档、自动化回归、eval、Maven E2E、日志/DB 验收、Issue 归档和独立提交。
|
||||
- 分档:complex;接口影响 L2 内部删除 + 文档/demo 验收增强,外部 API/DB 协议不变。
|
||||
- Change:`chat-diagnosis-stategraph-cleanup-docs`。
|
||||
- 授权:用户已明确要求直接实现;本阶段按此前规则执行唯一最终 E2E。
|
||||
|
||||
## Context Sources
|
||||
|
||||
- ISS-011 阶段 5、测试策略、协议影响、验收标准和冻结决策。
|
||||
- 阶段 0–4 OpenSpec archives、devflow acceptance 与提交 `581daff`、`42ba204`、`1460dd1`、`99e490f`、`208a231`。
|
||||
- 全仓 `VerifierInputHook`/`VerifierContextHolder`/`ToolTraceSummaryService` 定义与引用搜索。
|
||||
- `mvp/architecture/README.md` 列出的 current docs、`mvp/eval/README.md`、`mvp/demo/` scripts/checklist。
|
||||
- `mvp-demo` profile、payment-timeout request、`scripts/query_mysql.py` 和 logs/ 现有布局。
|
||||
|
||||
## Question Pool
|
||||
|
||||
| # | 维度 | 问题 | 模式 | 状态 |
|
||||
|---|---|---|---|---|
|
||||
| Q1 | 清理 | 旧 Hook/ThreadLocal/trace summary service 是否还有生产消费者? | evidence-driven | 已解决 |
|
||||
| Q2 | 文档 | 哪些旧引用应更新,哪些历史材料应保留? | evidence-driven | 已解决 |
|
||||
| Q3 | E2E | 最终 live 场景如何绑定唯一 session/run 并证明 Graph 路径? | evidence-driven | 已解决 |
|
||||
| Q4 | 日志/DB | 如何避免用旧日志/latest DB 记录冒充当前证据? | evidence-driven | 已解决 |
|
||||
| Q5 | 验收 | 何时允许启动 Maven、是否需要日志和 DB 查询? | user-interview(用户最新规则) | 已确认 |
|
||||
| Q6 | 关闭 | 何时把 ISS-011 从 active 移到 archived? | evidence-driven | 已解决 |
|
||||
|
||||
## Evidence-driven Findings
|
||||
|
||||
- Q1:旧闭包只有 `VerifierInputHook -> VerifierContextHolder + ToolTraceSummaryService`,以及 `ToolTraceSummaryServiceTest`;ChatService/Graph/Trace/Eval 均无引用,可整体删除。
|
||||
- 实现前规格校正:`ChatVerifierPromptContractTest` 和 `DiagnosisGraphTestSuiteStructureTest` 必须保留旧类型名称的负向字符串断言;这不构成 executable reference。OpenSpec 已收紧为无定义/import/实例化/type-use,允许负向 guard literal。
|
||||
- Q2:current architecture index 仍列 `agent-orchestration.md` 等为当前真理源,因此必须更新;`mvp/issues/design-notes`、archived issues、历史 eval fixtures 保留时间点/兼容语义,不做大规模重写。
|
||||
- Q3:`run-interview-demo-check.ps1` 已用 Chat response runId 查询 exact Trace/feedback,最适合扩展 `run.orchestrationTrace` fail-fast 和 summary,不另建重复脚本。
|
||||
- Q4:E2E 使用唯一 timestamp sessionId;日志记录启动前 byte/time 边界并按 session/run 搜索;DB 所有核心查询带 exact sessionId/runId,另查询错误 ownership count。
|
||||
- Q6:只有实现、回归、eval、live E2E、日志、DB 和 OpenSpec门禁全部通过后,Issue checkbox 才可完成并移动到 archived。
|
||||
|
||||
## User-interview Confirmation
|
||||
|
||||
| 问题 | 用户原话 | 状态 | OpenSpec 回写 |
|
||||
|---|---|---|---|
|
||||
| Q5 最终验收节奏 | “端到端只在最后阶段全部完成后才验证……日志在log文件夹,项目库有查询数据库的py工具” | 已确认 | proposal |
|
||||
|
||||
## Grill-with-docs Result
|
||||
|
||||
- Session/Run/Trace 术语保持不变;新增强调 `orchestration_trace` 是 Run 路由摘要,不属于 self-evaluation 或日志。
|
||||
- StateGraph、Workflow/Node Contract/Chat Integration 属于实现/测试架构术语,不修改业务 glossary。
|
||||
- 当前文档必须使用 explicit Gatekeeper Node、verified-only Verifier 和 bounded evidence retry;历史设计笔记仍可描述当时 Hook 架构。
|
||||
- 删除旧闭包是阶段 0 已冻结单轨迁移的自然收尾,不形成新的难逆转权衡,无需 ADR。
|
||||
|
||||
## Discover Status
|
||||
|
||||
- `devflow/index.md`:命中阶段 0–4 archives。
|
||||
- 接口影响:L2 内部类型删除;外部 API/DTO/DB/Prompt/状态语义无变化。
|
||||
- E2E 入口/脚本/日志/DB 工具已定位;真实执行留到 Apply 最后。
|
||||
- 未解决问题:0。
|
||||
- Draft 产物:proposal + decisions;尚未生成 design/spec/tasks,尚未删除代码或启动应用。
|
||||
|
||||
## Architecture Audit
|
||||
|
||||
### Module and evidence map
|
||||
|
||||
`ChatController -> ChatService -> ChatDiagnosisGraphRuntime -> DiagnosisRealGraphActionsFactory -> explicit Nodes -> DiagnosisGraphResultMapper -> DiagnosisRun/Trace` 是唯一当前 Chat链。旧 `VerifierInputHook -> ToolTraceSummaryService/VerifierContextHolder` 已从主链断开,删除不改变输入/输出或持久化。阶段 5新增的 demo script assertion只消费 exact Trace `run.orchestrationTrace`,DB/log检查是验收消费者,不成为运行时业务依赖。
|
||||
|
||||
| 模块 | 所有权 | 阶段 5动作 |
|
||||
|---|---|---|
|
||||
| Graph/Chat runtime | 路由、Node、Run 生命周期 | 不改行为,仅回归 |
|
||||
| Legacy Hook closure | 旧 Sequential Verifier payload | 整体删除 |
|
||||
| Current architecture docs | 当前实现真理源 | 更新 StateGraph/verified-only/trace |
|
||||
| Historical docs/fixtures | 时间点/兼容记录 | 保留,不冒充当前实现 |
|
||||
| Demo check | live Chat/Trace/feedback executable contract | 增加 exact orchestration trace fail-fast |
|
||||
| logs/MySQL | live运行证据 | 只读本次 session/run |
|
||||
| ISS/OpenSpec/devflow | 生命周期与交接 | 所有门禁通过后归档 |
|
||||
|
||||
### Lifecycle and failure ownership
|
||||
|
||||
- 自动化门禁失败:不启动 live Maven,修复代码/测试/规格后重跑。
|
||||
- live startup失败:应用未 ready,不执行 demo/DB成功声明,先读启动输出和新日志诊断。
|
||||
- Chat/Trace/feedback失败:保留 exact response/run证据,ISS保持 active。
|
||||
- log ERROR:逐条分类;未解释 ERROR阻塞验收。
|
||||
- DB不一致:以 exact run为准,不能用 API成功掩盖 persistence偏差。
|
||||
- finally:无论成功失败都停止本轮进程并确认端口,不扩大到未知已有进程。
|
||||
|
||||
### Consumer and compatibility audit
|
||||
|
||||
- 外部 API/DTO/DB consumer无迁移;demo summary仅加字段。
|
||||
- Trace UI/eval 对历史 `tool_trace_summary` 的读取保留,旧 fixture不批量迁移。
|
||||
- current docs消费者将看到新 StateGraph架构;历史链接仍可追溯 old Hook设计。
|
||||
- Issue move只改变文档位置/index,代码/运行时不依赖该路径。
|
||||
|
||||
### Cross-artifact alignment
|
||||
|
||||
| 上游 → 下游 | 检查内容 | 状态 |
|
||||
|---|---|---|
|
||||
| brief/proposal → proposal | cleanup、current docs、demo、regression、live/log/DB、Issue closure | 已对齐 |
|
||||
| proposal → design | 删除闭包、current/history边界、顺序、identity、日志/DB、cleanup | 已对齐 |
|
||||
| design → specs/tasks | 负向 literal例外、E2E字段、exact evidence、进程清理、Issue gate | 已对齐 |
|
||||
| specs → tasks | 每条 requirement有可执行 cleanup/docs/test/live/log/DB/closure slice | 已对齐 |
|
||||
|
||||
### Audit result
|
||||
|
||||
审计确认阶段 5不需要新运行时抽象或 DB migration;主要风险来自外部 live状态和证据归属,已通过 unique session/run、log boundary、exact DB queries和process ownership缓解。规格误把负向名称 literal 当 executable reference 的 gap 已修正。接口影响 L2,cross-artifact gap=0,无新 ADR。
|
||||
|
||||
## Commit Gate
|
||||
|
||||
- schema:spec-driven;proposal/design/2 delta specs/tasks 全部 done,applyRequires=`tasks` 已满足。
|
||||
- OpenSpec:当前 change strict pass;16 个主 specs strict pass。
|
||||
- Cross-artifact:4/4 已对齐,gap=0;负向 guard literal例外已写入 proposal/design/spec/tasks。
|
||||
- Question pool:5 个 evidence-driven 已解决,1 个 user-interview 已由用户原话确认,无未决项。
|
||||
- Interface impact:L2 internal type removal + demo/docs enhancement;外部协议/DB无变化。
|
||||
- Preflight:`git diff --check` 通过;尚未删除代码、修改 current docs/script或启动应用。
|
||||
- 结论:Draft OpenSpec 达到可执行状态,创建 `.committed` 后进入 Apply。
|
||||
|
||||
## Apply Progress
|
||||
|
||||
### Legacy closure removal
|
||||
|
||||
- 已删除 `VerifierInputHook`、`VerifierContextHolder`、`ToolTraceSummaryService` 和 `ToolTraceSummaryServiceTest`,四个路径均不存在。
|
||||
- `rg` 对 `src/main`、`src/test` 的旧类型扫描仅命中 `ChatVerifierPromptContractTest` 和 `DiagnosisGraphTestSuiteStructureTest` 中的负向守卫字符串;无定义、import、实例化、继承或类型依赖。
|
||||
- 删除后 focused 回归覆盖 Executor parser、Gatekeeper service/node、VerifiedInput、Verifier、Composer、Fallback、Workflow、Node Contract、Chat integration、Trace、result mapper 和结构契约:14 suites / 82 tests,0 failure、0 error、0 skipped。
|
||||
- `mvn -q -DskipTests test-compile` 通过;Graph/shared protocol 真理源保留,Spring 当前链路所需类型可完整编译。
|
||||
|
||||
### Current docs and demo contract
|
||||
|
||||
- architecture index、编排、session/trace、current MVP、evidence pipeline、quality gates、feedback、retrieval 和 eval 文档已切换为 bounded StateGraph、显式 Gatekeeper/Verified Input、verified-only Verifier、有限重试/Fallback 和 Run-owned `orchestration_trace`。
|
||||
- current-doc scan 对 `SequentialAgent`、旧 Hook/ThreadLocal/service 及旧测试类名为 0 命中;`tool_trace_summary` 仅剩 4 处,均明确标注为旧 Run/fixture 只读兼容,不是当前 Verifier 输入。
|
||||
- interview demo check 绑定 Chat 返回的 exact runId,校验 Chat/Trace ownership、Run CHAT/SUCCESS、Agent/tool/self-evaluation、Graph trace 六个字段和 feedback success;summary 新增 orchestration version、final node、termination reason、degraded、transition count 和 evidence retry count。
|
||||
- PowerShell parser 语法检查通过;`InterviewDemoScriptContractTest` 2 tests 通过,覆盖 exact runId URL/response、orchestration fail-fast 和 summary 字段。
|
||||
|
||||
### Final deterministic gates
|
||||
|
||||
- authoritative/focused regression:39 suites / 157 tests,0 failure、0 error、0 skipped;覆盖三层 Graph、全部 Graph Node/router/trace builder、Chat/Trace/Gatekeeper/Composer、Controller、Repository、schema、feedback/tool recorder 和 demo contract。
|
||||
- fixed diagnosis eval:12/12 passed,verdict distribution 为 PASS=5、LOW_CONFID=6、REJECT=1;same-baseline diff 无 regression、0 items。
|
||||
- `mvn -q -DskipTests test-compile` 通过;当前 change strict 通过,16 个主 specs strict 全部通过。
|
||||
- `git diff --check`、legacy executable refs、current-doc stale refs 和 unexpected schema change 检查全部通过。
|
||||
- focused 回归日志中的 Graph ERROR/exception stack trace 来自 `ChatServiceGraphIntegrationTest` 对 FAILED/no-answer/unhandled failure 的显式契约用例,Maven exit 0,不是未解释的 live ERROR。
|
||||
|
||||
### Live failure diagnosis and correction
|
||||
|
||||
- 首次 live identity:sessionId=`iss-011-stage5-20260717140450`,runId=`run-6db680f8-f764-49d1-995f-0e55a4b05a06`。demo contract 在 exact Trace `run.orchestrationTrace=null` 处 fail-fast,未提交 feedback;Run 为 `CHAT/FAILED`,步骤/工具均为 0。
|
||||
- 新日志根因:`DiagnosisOrchestrationTraceBuilder` 收到类名相同但 classloader identity 不同的 `OrchestrationEvent`,`instanceof` 失败并抛出 `orchestration events contain unsupported value`。这是 Spring Boot DevTools live classloader 才暴露的 Graph state 表示缺陷,单元 JVM 未复现。
|
||||
- 冲突分类:代码偏离/运行时兼容 bug,OpenSpec 对 non-empty orchestration trace 和 live Maven startup 的要求正确,不修改验收口径。
|
||||
- RED:新增 portable event map builder 回归,修复前 1 test error;GREEN:Graph state 的 production/test actions 改存 classloader-neutral Map,builder兼容 local record/Map,Node/Workflow assertions 改读 Map。
|
||||
- 修复后先运行 5-suite Graph/Node/Runtime/Chat integration focused gate,再运行完整 39 suites / 157 tests,全部 0 failure/error/skipped;首次 Maven 进程链已按 ownership 停止,9900 已释放。
|
||||
|
||||
- 第二个 live blocker 为外层 Graph `RunnableConfig` 的 resume metadata 被原样传给内层 ReactAgent,触发 `Resume request without a configured checkpoint saver`。回归先证明 nested config 与 outer config 同一且含 `HUMAN_FEEDBACK`,再改为保留 sessionId/runId、剔除 resume/state-update/checkpoint 控制信息的独立配置;5 suites / 50 tests 和随后完整 39 suites / 157 tests 通过,临时 `[DEBUG-ISS011-NODE]` 探针已删除且源码扫描为 0。
|
||||
- 2026-07-17 的一次长请求在工具执行期间遭遇外部 MySQL 瞬时 `Connection is closed`,留下精确 `RUNNING` 失败尝试;仓库查询工具随后证明数据库恢复且 server `wait_timeout=28800`。该失败未被当作验收通过,失败 Run 保留为真实审计记录。
|
||||
|
||||
### Accepted live E2E
|
||||
|
||||
- 启动:`mvn spring-boot:run "-Dspring-boot.run.profiles=mvp-demo"`;启动前 9900 空闲,隐藏进程链为 cmd `25080` -> Maven Java `17860` -> app Java `10732`,readiness 后执行固定 payment-timeout demo。
|
||||
- identity:sessionId=`iss-011-stage5-20260720015557`,runId=`run-808ac38f-3ad0-4462-a6d0-ed50d8686473`;Chat/Trace exact identity 一致,answer 长度 109,feedback request success。
|
||||
- Trace:Run=`CHAT/SUCCESS`,8 AgentSteps、12 ToolInvocations,self-evaluation 非空;`stategraph-v1`,final node=`fallback`,termination=`fallback_completed`,degraded=`true`,3 transitions,evidence retry count=0。
|
||||
- Fallback 原因是 Gatekeeper LOW_CONFID 且本轮模型输出缺少 `source_invocation_id`;这是按冻结契约执行的安全降级,answer 非空且未绕过 Gatekeeper,日志/DB 均可审计。
|
||||
- 最终日志发生跨日 rollover:7 月 20 日 active `application.log`/`chat.log` 全部属于本轮;`application-error.log` 最后写入仍为 7 月 17 日。本轮 `rg " ERROR "` 对 application/chat 为 0,新增 error-file bytes 为 0;session/run、Graph 75964ms、evaluation、exact Trace 和 useful feedback 均有关联日志。
|
||||
- MySQL:V012 `orchestration_trace` 为 nullable JSON;exact Run answer=109、duration=75964、token=111802、steps=8、tools=12、evaluation len=8822、trace len=438、feedback=useful;JSON 路由与 Trace 完全一致。
|
||||
- ownership:AgentStep 8、ToolInvocation 12,各自 distinct session/run=1、wrong owner=0;唯一 session 下 wrong run/step/tool 均为 0。
|
||||
- cleanup:只停止 PID `10732/17860/25080`,最终 9900 已释放,无剩余 owned process。
|
||||
@@ -0,0 +1,38 @@
|
||||
# Evidence
|
||||
|
||||
## Source And Dependency Evidence
|
||||
|
||||
- 旧闭包四个文件已删除;`src/main`/`src/test` 旧类型扫描仅剩两个测试中的负向名称守卫,无 definition/import/instantiation/type dependency。
|
||||
- 当前真理源保留 `ExecutorEvidenceParser`、`ExecutorGatekeeperService`、`GatekeeperNode`、`VerifiedInputNode`、`VerifierNodeAdapter` 和 `DiagnosisGraphResultMapper`。
|
||||
- current docs 不再描述 SequentialAgent、Hook Gatekeeper 或 full-trace Verifier;4 处 `tool_trace_summary` 均明确为历史只读兼容。
|
||||
|
||||
## Deterministic Evidence
|
||||
|
||||
- 删除后 focused:14 suites / 82 tests,0 failure/error/skipped。
|
||||
- 最终 authoritative/focused:39 suites / 157 tests,0 failure/error/skipped。
|
||||
- 归档前 `mvn clean` 后重建验证:43 suites / 189 tests,0 failure/error/skipped;额外覆盖 4 个无需外部服务的现存测试类。
|
||||
- diagnosis eval:12/12 passed;PASS=5、LOW_CONFID=6、REJECT=1;same-baseline diff=0。
|
||||
- `mvn -q -DskipTests test-compile`、PowerShell parser、OpenSpec current strict、16 main specs strict、`git diff --check`、legacy/current-doc/schema scans 均通过。
|
||||
|
||||
## Diagnose Evidence
|
||||
|
||||
- DevTools live classloader 使 record `instanceof` 边界失效;portable event map regression 先 RED,Node state 改用 Map 且 builder 兼容 record/Map 后 GREEN。
|
||||
- outer Graph resume metadata 污染 nested ReactAgent;nested config isolation regression 先 RED,保留 session/run metadata并剔除 resume/state-update/checkpoint 控制信息后 GREEN。
|
||||
- 两次修复后均重跑 focused 和完整 deterministic gate;临时调试探针为 0。
|
||||
|
||||
## Accepted Live Evidence
|
||||
|
||||
- sessionId:`iss-011-stage5-20260720015557`
|
||||
- runId:`run-808ac38f-3ad0-4462-a6d0-ed50d8686473`
|
||||
- Maven profile:`mvp-demo`;Chat/Trace/feedback script exit 0。
|
||||
- Run:CHAT/SUCCESS;answer=109 chars;8 steps;12 tools;self-evaluation 非空;feedback=useful。
|
||||
- Graph:stategraph-v1;planner -> executor -> gatekeeper -> fallback;termination=fallback_completed;degraded=true;evidence retries=0。
|
||||
- Logs:本轮 active application/chat 中 ERROR=0,error appender 无新写入;session/run、evaluation、Trace、feedback 可关联。
|
||||
- DB:V012 JSON column 存在;Run fields/JSON 与 API 一致;step/tool wrong owner=0;unique-session wrong rows=0。
|
||||
- Cleanup:owned process chain 已停止,9900 已释放。
|
||||
- Archive preflight:临时 `target/iss-011-stage5*` 目录为 0,OpenSpec strict 17/17,current-doc stale=0,schema diff=0,`git diff --check` 通过。
|
||||
|
||||
## Known Limits
|
||||
|
||||
- 本次真实模型遗漏 `source_invocation_id`,Gatekeeper 按契约降为 LOW_CONFID 并进入安全 Fallback;这是成功且可审计的 degraded Run,不是完整 Composer 正常路径。
|
||||
- 2026-07-17 外部 MySQL 瞬时断连留下一个 RUNNING 失败尝试;它未计入验收且保留审计,不影响 2026-07-20 exact accepted Run。
|
||||
@@ -0,0 +1,70 @@
|
||||
# Chat Diagnosis StateGraph Design Freeze Acceptance
|
||||
|
||||
## 结果
|
||||
|
||||
已接受。阶段 0 完成设计冻结,没有修改运行时实现。
|
||||
|
||||
## 验证
|
||||
|
||||
### 静态验证
|
||||
|
||||
- 命令:`git diff --check`
|
||||
- 结果:passed
|
||||
- 备注:仅有现有 LF/CRLF 提示,无 whitespace error。
|
||||
|
||||
- 检查:Git changed/untracked 路径运行时拒绝列表。
|
||||
- 结果:passed,12 个路径,`src/`、Maven、运行配置、脚本、数据库迁移命中 0。
|
||||
- 备注:阶段 0 只包含 Issue、glossary、OpenSpec/devflow 和执行记录。
|
||||
|
||||
- 检查:proposal → design → specs → tasks 四向对齐。
|
||||
- 结果:passed,gap=0。
|
||||
- 备注:状态、路由、Fallback、审计、测试迁移和六阶段边界均闭环。
|
||||
|
||||
### 脚本验证
|
||||
|
||||
- 命令:`openspec validate chat-diagnosis-stategraph-design-freeze --type change --strict --json`
|
||||
- 结果:passed,1/1。
|
||||
- 备注:当前 change 无结构或场景格式问题。
|
||||
|
||||
- 命令:`openspec validate --specs --strict --json`
|
||||
- 结果:passed,11/11。
|
||||
- 备注:归档前主规格基线未回归。
|
||||
|
||||
### 浏览器/人工验证
|
||||
|
||||
- 结果:not run。
|
||||
- 原因:阶段 0 无 UI 或运行行为。
|
||||
|
||||
### 未验证
|
||||
|
||||
- 单元测试:not run。阶段 0 无代码行为,新增或运行单元测试没有新的验收价值。
|
||||
- Maven E2E:not run。用户明确要求仅阶段 5 在全部实现完成后统一执行。
|
||||
- `logs/`:not inspected for stage acceptance;保留到阶段 5。
|
||||
- 数据库:not queried for stage acceptance;保留到阶段 5。
|
||||
- 备注:此前改造前 live baseline 仅为 research,不计入本阶段验收。
|
||||
|
||||
## 已完成范围
|
||||
|
||||
- 冻结最小 Graph State、所有条件边、四类独立计数和终止路径。
|
||||
- 冻结 verified-input、两类 Fallback、Run 状态与 orchestration trace 边界。
|
||||
- 冻结 L4 消费者、兼容、迁移、回滚和测试替换策略。
|
||||
- 创建 ADR-001,并规定阶段 1–5 引用本阶段 archive。
|
||||
- OpenSpec apply tasks 7/7 完成。
|
||||
|
||||
## 已知限制
|
||||
|
||||
- 运行时仍为旧 Sequential 编排,这是阶段 0 的有意状态。
|
||||
- 新设计尚未经过 Graph 编译、Node 单测、Chat 集成或最终 E2E;后续阶段逐项证明。
|
||||
- 主运行时 specs 暂时仍描述旧行为,只新增设计基线 capability。
|
||||
|
||||
## Bug 修复和诊断
|
||||
|
||||
- 更正此前错误流程模型:删除未提交的总 change,改为六个独立 sm-flow/change。
|
||||
- 更正此前错误 E2E 门禁:阶段 0–4 不做 E2E,阶段 5 统一验证。
|
||||
|
||||
## 交接
|
||||
|
||||
- 下一步:阶段 0 Git commit;提交完成后才能创建阶段 1 change。
|
||||
- Delta sync:新增 `chat-diagnosis-stategraph-design-freeze` 主 spec,共 6 个 requirements,无现有 spec 修改/删除。
|
||||
- OpenSpec 归档确认:用户已在目标中明确要求每阶段 archive,并在后续澄清中再次确认,视为已授权。
|
||||
- OpenSpec 归档结果:已同步主 spec,并归档到 `openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-design-freeze/`。
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
# ADR-001: StateGraph owns run-scoped diagnosis control
|
||||
|
||||
**状态**:已接受
|
||||
**日期**:2026-07-17
|
||||
|
||||
复杂 Chat 使用 Spring AI Alibaba StateGraph 管理一次 Diagnosis Run 内的顺序、条件边、有限重试、终止和降级;ReactAgent 只执行 Planner、Executor、Verifier、Composer 的语义任务,Gatekeeper、verified-input builder、evidence retry prepare 和固定 Fallback 使用确定性 Java Node。这样可以精确恢复失败位置并形成可审计路径,同时继续复用现有 Agent、工具和证据协议。
|
||||
|
||||
Gatekeeper 从 `VerifierInputHook` 的隐式执行迁为显式且唯一的 Graph Node。Verifier 只能消费 Gatekeeper passed checked bindings 投影出的 `verified_executor_output` 和 `verified_evidence`;前置验证失败的 Fallback 不得输出 Executor claim。
|
||||
|
||||
编排审计只属于当前 `runId`:有界 `orchestration_events` 压缩后写入 `diagnosis_run.orchestration_trace`,Trace API 只在 `run.orchestrationTrace` 暴露解析对象。它不替代 self evaluation、AgentStep、ToolInvocation 或持久 Graph checkpoint,也不新增 trace 明细表。
|
||||
|
||||
## Considered Options
|
||||
|
||||
- 继续在 `ChatService` 外层叠加 `for/if`:拒绝,失败恢复位置、循环上限和路由原因仍然隐式。
|
||||
- 使用 SupervisorAgent:拒绝,当前是固定诊断 Pipeline,不需要动态选择专科 Agent。
|
||||
- 直接将父 Graph State 交给 `ReactAgent.asNode(...)`:首版拒绝,无法证明 messages、outputKey 和私有执行上下文隔离。
|
||||
- 长期保留 Sequential/StateGraph feature flag 双轨:拒绝,会形成两个编排真理源并增加安全规则漂移。
|
||||
|
||||
## Compatibility And Migration
|
||||
|
||||
`/api/chat`、`executor_evidence_v2`、Verifier 和 Composer 输出协议保持不变。Trace API 只增加 run-scoped 字段;数据库只增加 nullable JSON 列,历史 Run 不回填。
|
||||
|
||||
实施必须按六个独立 sm-flow/change 依次完成:设计冻结、路由骨架、真实节点、ChatService/Trace 切换、测试体系、清理与最终验收。阶段 1–5 必须读取阶段 0 archive,偏离本 ADR 时通过当阶段 OpenSpec 显式修正。
|
||||
|
||||
## Rollback
|
||||
|
||||
每阶段使用独立 Git commit,可整体 revert 当前阶段。生产切换后回滚代码时允许保留 nullable `orchestration_trace` 列;不得用配置重新形成长期双轨。
|
||||
@@ -0,0 +1,20 @@
|
||||
# Chat Diagnosis StateGraph Design Freeze Brief
|
||||
|
||||
## 背景
|
||||
|
||||
- 用户目标:将 ISS-011 阶段 0–5 分别作为独立 sm-flow,前一阶段 archive 并 Git commit 后才进入下一阶段。
|
||||
- 当前问题:复杂 Chat 的跨 Agent 状态机分散在 ChatService、SequentialAgent、VerifierInputHook 和 ThreadLocal 中;实现前需先冻结统一设计。
|
||||
- 关联 OpenSpec:`openspec/changes/chat-diagnosis-stategraph-design-freeze/`
|
||||
- devflow 分档:complex
|
||||
|
||||
## 范围
|
||||
|
||||
- 本次要做:冻结最小 Graph State、完整路由、有限重试、安全 Fallback、run-scoped 审计、L4 接口影响和测试替换边界。
|
||||
- 本次不做:任何 Java、SQL、Prompt、配置、运行时 spec 或运行行为修改;不运行 Maven E2E。
|
||||
- 影响区域:ISS-011、glossary、OpenSpec 设计基线、阶段 0 ADR 和后续五阶段交接契约。
|
||||
|
||||
## OpenSpec 对齐
|
||||
|
||||
- proposal 覆盖状态:已覆盖阶段 0 目标、范围、非目标、验收和风险。
|
||||
- specs 覆盖状态:新增设计基线 capability,不提前修改运行时 capabilities。
|
||||
- tasks 覆盖状态:7/7 完成,且仅包含文档、ADR 和静态验证。
|
||||
@@ -0,0 +1,120 @@
|
||||
# Chat Diagnosis StateGraph Design Freeze Decisions
|
||||
|
||||
## Question Pool
|
||||
|
||||
| # | 维度 | 问题 | 模式 | 状态 |
|
||||
|---|---|---|---|---|
|
||||
| Q1 | 术语 | Diagnosis Orchestration Trace 与 Diagnosis Trace、self evaluation、Graph checkpoint 的边界是什么? | evidence-driven | 已解决 |
|
||||
| Q2 | 边界 | ISS-011 是一个总 sm-flow,还是阶段 0–5 各自独立 sm-flow? | user-interview | 已解决 |
|
||||
| Q3 | 验收 | Maven E2E 在每阶段执行还是只在最终阶段执行? | user-interview | 已解决 |
|
||||
| Q4 | 验收 | 每阶段是否强制新增并运行单元测试? | user-interview | 已解决 |
|
||||
| Q5 | 技术 | 锁定的 StateGraph 版本是否提供条件边、config-aware Node/Edge、recursion limit 和 threadId? | evidence-driven | 已解决 |
|
||||
| Q6 | 架构 | Gatekeeper、Verifier 输入与 Composer 的可信材料边界应复用什么现有契约? | evidence-driven | 已解决 |
|
||||
| Q7 | 接口 | 阶段 0 本身和最终设计分别属于什么接口影响等级? | evidence-driven | 已解决 |
|
||||
| Q8 | 归档 | 每阶段是否应在进入下一阶段前独立 archive 和 Git commit? | user-interview | 已解决 |
|
||||
|
||||
## Evidence-driven
|
||||
|
||||
| 结论 | 证据来源 | 是否已汇报用户 |
|
||||
|---|---|---|
|
||||
| Orchestration Trace 是 run 级紧凑编排摘要,不是事件日志、自评估或 Graph checkpoint | `devflow/glossary/CONTEXT.md`、ISS-011 §7.5、session-run-trace-isolation decisions | 已汇报 |
|
||||
| Gatekeeper 从 Hook 迁为显式 Node 是有意替换旧内部架构,不允许双入口 | executor-gatekeeper-hook decisions、ISS-011 §2.3/§7.2/§14 | 已汇报 |
|
||||
| Verifier verified evidence 必须来自 Gatekeeper 通过的 checked bindings;Composer 不得读取 raw Executor/tool output | verifier-evidence-reference-fidelity、executor-composer-final-answer 历史档案、ISS-011 §7.4 | 已汇报 |
|
||||
| 本地 1.1.2.0 API 支持条件边、config-aware Node/Edge、recursion limit、RunnableConfig.threadId 和 ReactAgent.call(input, config) | Maven dependency tree 与本地 JAR `javap` 研究记录 | 已汇报 |
|
||||
| 阶段 0 是文档/规格交付,无运行时接口变化;其冻结的最终目标涉及状态机、DB 和 Trace API,属于 L4 | sm-flow operating-rules、ISS-011 §10/§14 | 已汇报 |
|
||||
| 主 OpenSpec 的外层 groundedness round、Hook Gatekeeper 和完整 tool_trace_summary 输入与冻结设计冲突 | `openspec/specs/chat-verifier-agent/spec.md` 等主规格 | 已汇报 |
|
||||
|
||||
## User-interview
|
||||
|
||||
| 问题原文 | 用户原话 | 确认状态 | OpenSpec 回写 |
|
||||
|---|---|---|---|
|
||||
| ISS-011 的阶段关系如何映射 sm-flow? | “iss-011里每个阶段,都是一个sm-flow,而不是将一整个iss-011打包进一个sm-flow中” | 已确认 | 已回写 proposal 范围与非目标 |
|
||||
| Maven E2E 何时执行? | “端到端只在最后阶段全部完成后才验证” | 已确认 | 已回写 acceptance 与 out of scope |
|
||||
| 阶段单元测试是否强制? | “每个阶段如果有必要添加单元测试验收的话,就加,没有必要的话就跳过单元测试” | 已确认 | 已回写 acceptance |
|
||||
| 每阶段如何进入下一阶段? | “每个阶段需要归档完并提交才能进入下一个阶段” | 已确认 | 已回写阶段门禁 |
|
||||
|
||||
## OpenSpec Input Context
|
||||
|
||||
### devflow index
|
||||
|
||||
已命中并读取:
|
||||
|
||||
- `session-run-trace-isolation`
|
||||
- `executor-gatekeeper-hook`
|
||||
- `verifier-evidence-reference-fidelity`
|
||||
- `executor-evidence-output-contract`
|
||||
- `executor-v2-output-contract`
|
||||
- `executor-verifier-claim-checks`
|
||||
- `executor-composer-final-answer`
|
||||
- `mvp-demo-trace-acceptance`
|
||||
|
||||
### Historical constraints entering OpenSpec
|
||||
|
||||
- `runId` 是运行态和 Trace 的所有权边界。
|
||||
- AgentStep、ToolInvocation 与 self evaluation 的既有 run 绑定必须保留。
|
||||
- checked binding 是 verified evidence 的复用来源。
|
||||
- Composer 的 allowed-material 安全边界不得削弱。
|
||||
- 旧 Gatekeeper-in-Hook 决策在本设计中被显式废止,不能保留并行入口。
|
||||
- 主 OpenSpec 的旧运行时要求只能在对应实现阶段修改,阶段 0 不提前宣称代码已切换。
|
||||
|
||||
## Key Decisions
|
||||
|
||||
### 六个独立交付单元
|
||||
|
||||
阶段 0–5 分别使用独立 slug、OpenSpec change、devflow 项目、Archive 和 Git commit。前一 change 归档并提交后才创建下一 change。
|
||||
|
||||
### 阶段 0 不承载后续实现
|
||||
|
||||
阶段 0 只冻结设计并归档长期上下文。阶段 1–5 的代码、数据库、测试和清理任务不进入本 change 的 tasks。
|
||||
|
||||
### 验收分层
|
||||
|
||||
阶段 0 没有运行时行为变化,不新增或运行单元测试,也不运行 Maven E2E。验收使用 OpenSpec strict validation、结构检查和文档一致性检查。Maven E2E、`logs/` 与数据库只在阶段 5 统一执行。
|
||||
|
||||
### 接口影响
|
||||
|
||||
- 当前 change:L1 文档/设计交付,不改变调用方可观察行为。
|
||||
- 冻结目标:L4,涉及内部状态机语义、Trace API 加字段、数据库契约、迁移和回滚。
|
||||
- 兼容:保持 `/api/chat` 和 Agent 输出协议;Trace API 为加法式 run 字段。
|
||||
- 回滚:后续运行时代码可按阶段 Git revert;nullable DB 列可保留,不引入双轨配置。
|
||||
- 消费者:ChatController/ChatService、Trace DTO/Service/UI/demo、数据库迁移、评测与运维审计。
|
||||
|
||||
## Risks Accepted
|
||||
|
||||
- 阶段 0 archive 后,冻结设计已完成但运行时仍为旧 Sequential;这是有意的阶段性状态。
|
||||
- 六个 changes 的一致性由后续每次 context/commit gate 读取并审计本档案保证。
|
||||
- 不为阶段 0 的纯设计变更新增无行为价值的单元测试。
|
||||
|
||||
## Cross-Artifact 对齐检查
|
||||
|
||||
| 上游 → 下游 | 检查内容 | 状态 |
|
||||
|---|---|---|
|
||||
| brief/prd → proposal | Issue 的阶段 0 目标、范围、非目标和验收已进入 proposal | 已对齐 |
|
||||
| proposal → 设计产物 | 状态、路由、重试、Fallback、审计、测试迁移和六阶段边界均进入 design | 已对齐 |
|
||||
| 设计产物 → specs/tasks | L4 影响、安全边界、终止规则和阶段 0 文档工作均进入 spec 或 tasks | 已对齐 |
|
||||
| specs → tasks | 设计基线、源文档、ADR、严格验证和无运行时变更检查均有可执行任务 | 已对齐 |
|
||||
|
||||
Gap:无。
|
||||
|
||||
## Architecture Audit
|
||||
|
||||
输入链为 `ChatController -> ChatService`,目标处理链为 Run 生命周期 → Graph orchestrator → 白名单 Agent/Java Nodes,输出仍为 `ChatResult + DiagnosisRun + exact RunTrace`。Graph State 只属于当前 run,verified evidence 只来自当前 run 的 passed checked bindings,编排摘要只写当前 Diagnosis Run。旧“Gatekeeper stays in VerifierInputHook”决策被 ISS-011 的显式 Node 有意替代,但旧 Gatekeeper 规则本身继续复用;旧“不新增 trace 主表”和 run ownership 决策保持成立。主要耦合风险是 Hook/Node 双执行、阶段性主 spec 漂移和 Trace 投影重复,design 已分别通过单入口迁移、按阶段修改运行时 specs、唯一 `run.orchestrationTrace` 投影缓解。架构风险已由用户确认的 ISS-011 冻结决策和六阶段交付口径接受,无需返回 grill。
|
||||
|
||||
## Commit Preflight
|
||||
|
||||
- proposal、design、specs、tasks 完整:通过。
|
||||
- 所有 user-interview 已确认:通过。
|
||||
- 未汇报 evidence-driven 结论:无。
|
||||
- L4 接口影响、消费者、兼容、迁移和回滚:已在 design 独立章节记录。
|
||||
- OpenSpec strict validation:change 1/1 通过,主 specs 11/11 通过。
|
||||
- Apply 授权:用户启动目标时要求分阶段完整执行、archive 和 Git commit,后续又确认六个独立 sm-flow;视为当前阶段连续执行授权。
|
||||
|
||||
## Apply Evidence
|
||||
|
||||
- Task 1.1:ISS-011 §3–14 与 committed design 的 State 字段、条件边、四类计数、Fallback、安全审计和测试迁移语义一致;未发现需回写 OpenSpec 的 drift,未修改运行时代码。
|
||||
- Task 1.2:将 glossary 中新 Orchestration Trace 的具体 StateGraph/Graph State 表述收敛为“诊断编排/编排上下文快照”;Verifier 的 verified-output/evidence 名称作为跨节点协议保留。
|
||||
- Task 2.1:创建 ADR-001,记录 StateGraph 控制边界、显式 Gatekeeper、run-scoped trace、替代方案、兼容、迁移和回滚。
|
||||
- Task 2.2:六个独立 change 的唯一边界已写入 design、design-baseline spec、ADR 和根计划;阶段 1–5 必须引用阶段 0 archive。
|
||||
- Task 3.1:最终 strict validation 为 change 1/1、主 specs 11/11;proposal/design/spec/tasks 对状态、Fallback、审计、运行时非目标和测试迁移均形成闭环,cross-artifact gap 为 0。
|
||||
- Task 3.2:Git 枚举 12 个 changed/untracked 路径,运行时拒绝列表命中 0;无 `src/`、Maven、运行配置、脚本或数据库迁移变更。
|
||||
- Task 3.3:单元测试未运行,因为阶段 0 无代码行为;Maven E2E、`logs/` 和数据库核验未运行,因为用户明确要求只在阶段 5 全部实现后统一执行。改造前 research baseline 不计入阶段验收。
|
||||
@@ -0,0 +1,30 @@
|
||||
# Chat Diagnosis StateGraph Design Freeze Evidence
|
||||
|
||||
## 证据
|
||||
|
||||
| 来源 | 证据 | 结论 | 是否已汇报 |
|
||||
|---|---|---|---|
|
||||
| ISS-011 §3–14 | 已定义目标流程、26 个 State 字段、有限回边、Fallback、Trace 和测试策略 | 可形成无开放分支的阶段 0 设计基线 | 是 |
|
||||
| `ChatService` / Controller 引用核查 | 生产链为 Controller → ChatService → SequentialAgent,细粒度状态散布在 ChatService | StateGraph 应只接管 Run 内控制,ChatService 保留生命周期 | 是 |
|
||||
| `VerifierInputHook` / `VerifierContextHolder` 引用核查 | Gatekeeper、工具摘要和解析结果通过 Hook/ThreadLocal 隐式传播 | Gatekeeper 与 verified-input 必须迁为显式 Node,不能保留双入口 | 是 |
|
||||
| executor-gatekeeper-hook 历史 decisions | 旧阶段曾决定 Gatekeeper 留在 Hook 且不重试 | 本设计有意替换入口,但继续复用确定性规则 | 是 |
|
||||
| session-run-trace-isolation 历史 decisions | runId 是执行/Trace 所有权边界,AgentStep/ToolInvocation 已承载明细 | orchestration trace 只附着当前 Run,不新增明细主表 | 是 |
|
||||
| Verifier/Composer 历史档案 | checked bindings 和 allowed material 是可信边界 | Builder 不重复验真,Fallback 不泄漏 raw claim | 是 |
|
||||
| 本地 Graph Core 1.1.2.0 JAR | 已验证条件边、config-aware Node/Edge、recursion limit、threadId 与 Agent call API | 阶段 1 可基于锁定签名实现,不采用网上漂移示例 | 是 |
|
||||
| 主 OpenSpec 核查 | 旧 spec 仍描述 Hook Gatekeeper、完整 tool trace 和外层 groundedness round | 阶段 0 不提前改运行时 spec,后续对应实现阶段再修改 | 是 |
|
||||
| 用户原话 | 六个独立 sm-flow;仅阶段 5 E2E;单测按必要性 | 阶段门禁与测试口径已固定 | 是 |
|
||||
|
||||
## Evidence-driven 结论
|
||||
|
||||
- 结论:阶段 0 运行时影响为 L1,但冻结目标为 L4。
|
||||
- 证据:本阶段 changed paths 无 `src/`/SQL/配置;最终目标改变状态机、Trace API 和 DB。
|
||||
- 风险:设计完成不等于运行时完成。
|
||||
- 用户确认:已确认分阶段交付。
|
||||
- 结论:旧 Gatekeeper-in-Hook 决策应被显式 Node 有意替代。
|
||||
- 证据:当前 Hook 引用与 ISS-011 条件边要求冲突。
|
||||
- 风险:迁移期双执行。
|
||||
- 用户确认:ISS-011 冻结决策已确认。
|
||||
- 结论:阶段 0 不需要单元测试或 E2E。
|
||||
- 证据:Git 运行时拒绝列表命中 0,OpenSpec strict 和文档一致性已覆盖本阶段可观察产物。
|
||||
- 风险:运行时正确性仍未证明,将由阶段 1–5 测试和最终 E2E 证明。
|
||||
- 用户确认:已确认。
|
||||
@@ -0,0 +1,42 @@
|
||||
# Chat Diagnosis StateGraph Real Nodes 验收
|
||||
|
||||
## 结果
|
||||
|
||||
已接受。OpenSpec tasks 27/27 完成;真实 Nodes 可构造和测试,旧生产 Sequential 路径保持可用,阶段 2 未切换生产入口。
|
||||
|
||||
## 静态验证
|
||||
|
||||
- `openspec validate chat-diagnosis-stategraph-real-nodes --strict`:通过。
|
||||
- `openspec validate --specs --strict`:13 passed,0 failed。
|
||||
- `git diff --check`:通过;只有 LF/CRLF 转换提示,无 whitespace error。
|
||||
- 源码/引用检查:`ChatService` Graph 引用 0;新增源码 forbidden refs 0;protocol 反向依赖 0;DB/Trace/Prompt diff 0。
|
||||
- 装配对齐:无核心 TODO/FIXME/placeholder;Graph factory 继续拥有所有 retry counter 与 Planner reset。
|
||||
|
||||
## 脚本验证
|
||||
|
||||
- 新 protocol/Node/CompiledGraph/Router/Trace focused suite:通过。
|
||||
- `mvn -q "-Dtest=ChatServiceSequentialAgentTest,VerifierInputHookTest,ExecutorGatekeeperServiceTest" test`:通过。
|
||||
- 两组测试合计:100 tests,0 failures,0 errors,0 skipped。
|
||||
- `mvn -q -DskipTests test-compile`:通过。
|
||||
|
||||
## 浏览器/人工验证
|
||||
|
||||
- 未运行。阶段 2 不改变用户入口或 UI,没有独立人工验收价值。
|
||||
|
||||
## 未验证
|
||||
|
||||
- Maven live E2E、`logs/` 日志和 `scripts/query_mysql.py` 数据库核验未运行。
|
||||
- 原因:用户明确要求只在阶段 5 全部实现后统一做最终 E2E;阶段 2 尚未切换生产入口。
|
||||
- 风险:当前验收只证明组件/Graph 契约与旧路径回归,不证明真实生产装配、模型、DB 和 Trace 全链路。
|
||||
|
||||
## 已完成范围
|
||||
|
||||
- 中立共享 protocol 与旧路径行为保持型委托。
|
||||
- 四个 Agent adapters、显式 Gatekeeper、可信投影、关键证据补查、Composer 与两类 Fallback。
|
||||
- 真实 CompiledGraph 装配、critical gap 路由修复和完整 focused test 证据。
|
||||
|
||||
## 交接
|
||||
|
||||
- 下一步:归档本 change、独立提交阶段 2,然后启动阶段 3 `chat-diagnosis-stategraph-chatservice-cutover`。
|
||||
- OpenSpec 归档:已同步主 specs,并归档到 `openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-real-nodes/`。
|
||||
- 归档授权:用户已明确“直接实现吧,不用找我授权了”,授权后续阶段在门禁通过后直接归档和提交。
|
||||
@@ -0,0 +1,21 @@
|
||||
# Chat Diagnosis StateGraph Real Nodes Brief
|
||||
|
||||
## 背景
|
||||
|
||||
- 用户目标:将 ISS-011 阶段 2 作为独立 sm-flow,接入真实 Agent/Java Nodes,并在归档、验收和独立 Git 提交后才进入阶段 3。
|
||||
- 当前问题:阶段 1 只有 Fake Node 路由骨架;Executor/Verifier/Composer 协议逻辑分散在 Hook 与 ChatService,真实 Graph 尚不能安全调用 Agent、Gatekeeper 或投影可信材料。
|
||||
- 关联 OpenSpec:`openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-real-nodes/`
|
||||
- devflow 分档:complex
|
||||
|
||||
## 范围
|
||||
|
||||
- 本次要做:共享无状态 protocol 组件;Planner/Executor/Verifier/Composer adapters;显式 Gatekeeper、Verified Input、Evidence Retry、Fallback Nodes;真实 CompiledGraph 装配和 focused tests。
|
||||
- 本次不做:不切换 ChatService 生产入口,不修改 DB、Trace API、Prompt 契约,不删除旧 Sequential/Hook,不运行 live E2E。
|
||||
- 影响区域:`diagnosis.protocol`、`graph.diagnosis`、`VerifierInputHook`、`ChatService` 共享逻辑委托及对应测试。
|
||||
|
||||
## OpenSpec 对齐
|
||||
|
||||
- proposal 覆盖状态:已覆盖。
|
||||
- design 覆盖状态:已覆盖;接口影响为 L2,生产切换明确延期到阶段 3。
|
||||
- specs 覆盖状态:已覆盖真实 Nodes 安全边界,并修正 critical evidence gap 路由条件。
|
||||
- tasks 覆盖状态:27/27 完成。
|
||||
@@ -0,0 +1,218 @@
|
||||
# Chat Diagnosis StateGraph Real Nodes Decisions
|
||||
|
||||
## Question Pool
|
||||
|
||||
| # | 维度 | 问题 | 模式 | 状态 |
|
||||
|---|---|---|---|---|
|
||||
| Q1 | 边界 | 阶段 2 是否切换 ChatService/DB/Trace? | user-interview(六阶段已确认) | 已解决 |
|
||||
| Q2 | 复用 | 新 Nodes 如何避免复制 Hook/ChatService 解析与安全渲染? | evidence-driven | 已解决 |
|
||||
| Q3 | Agent | Adapter 如何调用真实 ReactAgent 并保留 Hook/ToolCallback/run config? | evidence-driven | 已解决 |
|
||||
| Q4 | Gatekeeper | 显式 Node 如何保证当前 run、单次调用和 fail-closed 标准化? | evidence-driven | 已解决 |
|
||||
| Q5 | 安全 | passed checked bindings 如何投影为 verified output/evidence? | evidence-driven | 已解决 |
|
||||
| Q6 | 补证据 | 哪些 facts 可触发 evidence retry,completed queries 如何表达? | evidence-driven | 已解决 |
|
||||
| Q7 | Fallback | 前置验证失败与 Composer 后置失败可分别使用哪些材料? | evidence-driven | 已解决 |
|
||||
| Q8 | Prompt | 阶段 2 是否立即修改共享 Verifier Prompt? | evidence-driven | 已解决 |
|
||||
| Q9 | 验收 | 阶段 2 是否需要单元/集成测试与 E2E? | evidence-driven + user rule | 已解决 |
|
||||
|
||||
## Evidence-driven
|
||||
|
||||
| 结论 | 证据来源 | 是否已汇报用户 |
|
||||
|---|---|---|
|
||||
| ReactAgent.call(input, config) 返回 AssistantMessage,现有 AgentLoggingHook 从 config metadata 读取 sessionId/runId | 本地 1.1.2.0 javap、AgentLoggingHook | 已汇报 |
|
||||
| Executor parser 当前在 VerifierInputHook,Verifier/Composer parser 与 renderer 当前在 ChatService | 定向源码阅读和 references | 已汇报 |
|
||||
| checked_bindings 提供 claim_id/tool_name/source_invocation_id/raw_path/matched_text/status | ExecutorGatekeeperService | 已汇报 |
|
||||
| Gatekeeper.validateRun 使用 run-scoped ToolInvocation repository | ExecutorGatekeeperService tests/code | 已汇报 |
|
||||
| Graph path不能注册旧 VerifierInputHook,否则 Gatekeeper 会双执行且输入包含 full tool trace | 阶段 0 ADR、Hook 源码 | 已汇报 |
|
||||
| evidence retry 只允许 critical no_evidence/indirect_support | 阶段 0 design/ISS-011 | 已汇报 |
|
||||
| 阶段 1 router 未检查 is_critical,属于实现偏离 | Router 源码与阶段 0 baseline 对照 | 已汇报 |
|
||||
| 共享 Prompt 暂时仍服务旧 Sequential path,本阶段直接修改会提前破坏生产 payload | ChatService agent builder + VerifierInputHook + prompt | 已汇报 |
|
||||
| Node 输入/安全边界新增且旧解析会重构,单元和 focused regression 必要;E2E 不必要 | 阶段边界和用户规则 | 已汇报 |
|
||||
|
||||
## User-interview
|
||||
|
||||
| 问题原文 | 用户原话 | 确认状态 | OpenSpec 回写 |
|
||||
|---|---|---|---|
|
||||
| 阶段 2 是否独立 sm-flow? | “iss-011里每个阶段,都是一个sm-flow” | 已确认 | 独立 change |
|
||||
| 是否可提前切生产入口? | “每个阶段需要归档完并提交才能进入下一个阶段” | 已确认不可提前阶段 3 | Out of Scope |
|
||||
| 阶段 2 是否执行 E2E? | “端到端只在最后阶段全部完成后才验证” | 已确认不执行 | Acceptance |
|
||||
| 是否添加单元测试? | “如果有必要添加单元测试验收的话,就加” | 已确认规则;本阶段判定必要 | Acceptance |
|
||||
|
||||
## Context And Handoff
|
||||
|
||||
- 阶段 0 archive/commit:design baseline / `581daff`
|
||||
- 阶段 1 archive/commit:routing skeleton / `42ba204`
|
||||
- 当前 change:`chat-diagnosis-stategraph-real-nodes`
|
||||
- 后续 change:`chat-diagnosis-stategraph-chatservice-cutover`,只能在本阶段 archive + commit 后创建。
|
||||
|
||||
## Technical Decisions
|
||||
|
||||
### Shared protocol components
|
||||
|
||||
- 抽取 Executor、Verifier、Composer 解析器,旧 Hook/ChatService 委托新组件。
|
||||
- 抽取 Composer safe input builder / renderer,旧 ChatService 保持相同输出。
|
||||
- JSON sanitization 只存在一份共享实现,不在每个 Node copy。
|
||||
- 抽取过程是行为保持 refactor;现有 focused tests 是回归门禁。
|
||||
|
||||
### Agent adapter boundary
|
||||
|
||||
- `DiagnosisAgentInvoker` 是最小 port:`invoke(String, RunnableConfig) -> String`。
|
||||
- `ReactAgentDiagnosisInvoker` 只包装 `ReactAgent.call(...).getText()`。
|
||||
- Planner/Executor/Verifier/Composer adapters 各自拥有白名单 input projector、parser 和 status event。
|
||||
- tests 使用 fake invoker,另有 ReactAgent wrapper test。
|
||||
|
||||
### Legacy Hook coexistence
|
||||
|
||||
- 旧 Sequential path 在阶段 3 前仍通过 VerifierInputHook 执行 Gatekeeper。
|
||||
- Graph Verifier Agent 不注册该 Hook;显式 Gatekeeper Node 是 Graph 中唯一 validation 入口。
|
||||
- Parser/enricher 可共享,但 Hook 的 legacy payload/prompt 暂不改变。
|
||||
- 阶段 3 切换生产入口并同步 Verifier Prompt;阶段 5 删除旧隐式结构。
|
||||
|
||||
### Gatekeeper normalization
|
||||
|
||||
- raw pass → PASS。
|
||||
- raw fail + severity low_confid → LOW_CONFID。
|
||||
- raw fail + severity reject → REJECT。
|
||||
- 缺失、unknown、异常或不一致 → REJECT。
|
||||
- verified_binding_count 只统计 checked_bindings.status=pass。
|
||||
|
||||
### Verified projection
|
||||
|
||||
- 通过项按 claim_id + source_invocation_id + tool_name + raw_path 与原 binding 精确匹配。
|
||||
- verified_executor_output 只包含 answer_version 与至少一条 passed binding 的 filtered claims;合法零 claim 保持空列表。
|
||||
- verified_evidence 只含 claim_id/source_invocation_id/tool_name/raw_path/matched_text。
|
||||
- hypotheses、失败 binding、未引用 ToolInvocation、raw Executor output 不投影。
|
||||
|
||||
### Evidence retry
|
||||
|
||||
- extractor 要求 `is_critical=true` 且 verification 为 no_evidence/indirect_support。
|
||||
- gap 字段:claim_id(从 `claim-id: text` 提取或空)、fact、verification、reason。
|
||||
- completed queries 由 verified evidence 的 tool/invocation/path 去重生成。
|
||||
- prior verified output/evidence 原样只读进入 retry_context。
|
||||
- 约束固定:max_retry=1、do_not_repeat_successful_queries、only_execute_incremental_queries、preserve_prior_verified_claims。
|
||||
- Executor 输入声明“增量执行、完整输出”,Java 不合并 claims。
|
||||
|
||||
### Interface impact
|
||||
|
||||
- 等级:L2 internal interface;共享 parser 委托保持旧行为。
|
||||
- 新消费者:阶段 3 Graph orchestrator/Agent factory。
|
||||
- 当前外部 API/DB/生产路由:无变化。
|
||||
- 回滚:revert 本阶段提交;旧 Sequential path仍完整。
|
||||
- 有意修正:Router 只允许 critical gap,属于对冻结基线的代码修复。
|
||||
|
||||
## Risks Accepted
|
||||
|
||||
- 真实模型尚未执行;Node contract 通过 fake invoker/real service tests证明,阶段 5 才 E2E。
|
||||
- Prompt 输入说明与 Graph input 的最终同步推迟到阶段 3,避免当前旧生产 Hook 提前不兼容。
|
||||
- 旧 Hook 暂时仍存在,但不进入 Graph action graph;阶段 5 必须删除。
|
||||
|
||||
## Architecture Audit
|
||||
|
||||
### Module and ownership map
|
||||
|
||||
`Diagnosis Context + RunnableConfig` → Agent adapters / deterministic Nodes → owned Graph State fields → `DiagnosisGraphRouter` → next Node or END → `final_answer + orchestration_events`。阶段 2 只提供这条可构造链,阶段 3 才由 `ChatService` 创建 Run、构造 Agent 实例并调用 Graph。
|
||||
|
||||
| 模块 | 数据所有权 | 允许依赖 |
|
||||
|---|---|---|
|
||||
| `diagnosis.protocol` | JSON contract、纯解析结果、安全 input/rendering | Jackson 与纯 DTO;不依赖 Graph/Hook/ChatService/ThreadLocal |
|
||||
| `graph.diagnosis` Agent adapters | 白名单输入、Agent attempt status/event | protocol、注入的 invoker、Graph API |
|
||||
| Gatekeeper Node | raw Gatekeeper result、normalized status/count | ExecutorGatekeeperService、当前 run config |
|
||||
| Verified Input / Retry Prepare | verified projection、critical gaps、retry context | raw result 的只读投影与 protocol DTO |
|
||||
| Router / Factory | 条件边、有限计数、调用次序 | Graph State;不解析 Agent raw output |
|
||||
| legacy Hook / ChatService | 阶段 3 前的生产 Sequential 流程 | 只委托 protocol;不得消费真实 Graph action set |
|
||||
|
||||
### Lifecycle and coupling audit
|
||||
|
||||
Graph State 和 events 都是 invocation-scoped,runId 只从当前 RunnableConfig 获取,Nodes 不持有跨 Run 可变状态。旧路径与 Graph 路径阶段性共享的只有无状态 protocol 组件和 Gatekeeper service,不共享 ThreadLocal 或 Agent output。ReactAgent/invoker 必须构造注入,阶段 2 不复制 ChatService Prompt/Agent factory。唯一有意的阶段性耦合是 legacy consumers 改为委托 protocol,这由旧 focused tests 和完整 revert 保护。阶段 3 前生产入口、DB、Trace、Prompt 均保持隔离。
|
||||
|
||||
### Cross-artifact alignment
|
||||
|
||||
| 对齐链 | 结果 | 证据 |
|
||||
|---|---|---|
|
||||
| brief/proposal 目标、范围、非目标 → proposal | 已对齐 | 独立阶段边界、真实 Nodes、无生产切换均明确 |
|
||||
| proposal 承诺与约束 → design | 已对齐 | invoker、共享组件、Gatekeeper、投影、retry、Fallback、L2 均有决策 |
|
||||
| design 架构/接口结论 → specs/tasks | 已对齐 | 中立 protocol 包、构造注入、fail-closed 和生产隔离均有任务/行为 |
|
||||
| specs 可观察行为 → tasks 可执行切片 | 已对齐 | 每个 requirement 至少由一个实现任务和一个测试/验收任务覆盖 |
|
||||
|
||||
### Audit result
|
||||
|
||||
审计发现共享协议组件包所有权与 Agent 实例装配边界需要显式化,已回写 design/tasks。未发现状态字段、路由计数、run 生命周期或阶段边界的新冲突。接口影响维持 L2,消费者都在本 change 与下一阶段明确范围内。剩余风险是共享抽取的旧行为漂移和 binding 投影泄漏,均有 focused regression 与 mixed-binding tests。架构风险可接受,无未解决问题。
|
||||
|
||||
## Commit Gate
|
||||
|
||||
- proposal/design/specs/tasks:全部存在,OpenSpec status `isComplete=true`。
|
||||
- 当前 change strict validation:通过。
|
||||
- 主 specs strict validation:13 passed,0 failed。
|
||||
- 规格结构:9 requirements、22 scenarios;tasks:27 个 checkbox 切片。
|
||||
- Cross-artifact:4/4 已对齐,gap=0。
|
||||
- 接口影响:L2,已在 design 独立章节记录消费者、兼容和回滚。
|
||||
- Question pool:所有 evidence-driven 已汇报;所有 user-interview 已确认;无未决项。
|
||||
- Preflight scope:`git diff --check` 通过;Commit checkpoint 未修改业务代码。
|
||||
- 结论:Draft OpenSpec 达到可执行状态,创建 `.committed`。
|
||||
|
||||
## Apply Authorization
|
||||
|
||||
- 用户原话:“直接实现吧,不用找我授权了”。
|
||||
- 解释:阶段 2–5 后续 checkpoint 可在前置门禁通过后直接继续,不再因 Apply 或 Archive 授权暂停。
|
||||
- 不扩大范围:每阶段仍须独立 OpenSpec、验收归档、Git commit;阶段 0–4 不做 E2E,阶段 5 才统一执行。
|
||||
|
||||
## Pre-apply Research
|
||||
|
||||
### Reference implementations read
|
||||
|
||||
- `src/main/java/com/superbiz/agent/hook/VerifierInputHook.java`:Executor JSON sanitization、parse status、tool-name normalization、唯一 invocation 回填与 legacy Gatekeeper payload。
|
||||
- `src/main/java/com/superbiz/agent/service/ChatService.java`:Verifier claim/fact parser、Gatekeeper ceiling、Composer allowed-material builder、Composer parser/safe renderer、旧 retry context。
|
||||
- `src/main/java/com/superbiz/agent/service/ExecutorGatekeeperService.java`:`validateRun`、severity normalization source、checked binding 与 matched_text 结构。
|
||||
- `src/main/java/com/superbiz/agent/graph/diagnosis/DiagnosisGraphFactory.java`:config-aware action ports、technical retry/evidence retry counter 所有权和 recursion limit。
|
||||
- `src/main/java/com/superbiz/agent/graph/diagnosis/OrchestrationEvent.java` 与 `src/test/java/com/superbiz/agent/graph/diagnosis/ScriptedDiagnosisGraphActions.java`:每 attempt 单 event 形态。
|
||||
- `src/main/java/com/superbiz/agent/hook/AgentLoggingHook.java`:RunnableConfig metadata 中 sessionId/runId 的审计读取方式。
|
||||
- `src/test/java/com/superbiz/agent/hook/VerifierInputHookTest.java`、`ChatServiceSequentialAgentTest.java`、`DiagnosisGraphRoutingTest.java`:JUnit 5、Mockito 边界替身和 CompiledGraph observable behavior 测试风格。
|
||||
- 本地 `1.1.2.0` JAR `javap`:`ReactAgent.call(String,RunnableConfig)` 与 `RunnableConfig.threadId/metadata` 公共 API。
|
||||
|
||||
### Technology inventory
|
||||
|
||||
| 类别 | 项目标准 / 本阶段使用 |
|
||||
|---|---|
|
||||
| JSON contract | Jackson `ObjectMapper`、`LinkedHashMap` 保持稳定字段顺序;共享 sanitization 只存在一份 |
|
||||
| Graph Node | `AsyncNodeActionWithConfig` 返回 `CompletableFuture<Map<String,Object>>`;state 默认 Replace、events Append |
|
||||
| Agent boundary | 构造注入的 `DiagnosisAgentInvoker`;ReactAgent wrapper 透传同一个 RunnableConfig |
|
||||
| Run scope | `config.metadata("runId")` 为 Gatekeeper 唯一运行边界;缺失即 fail closed |
|
||||
| Error handling | 合法 contract/invalid output/temporary/permanent 分离;unknown exception 不推断为可重试 |
|
||||
| Tests | JUnit 5;只在 ReactAgent、repository 等系统边界使用 fake/mock;Node/CompiledGraph 走公开 action/graph 接口 |
|
||||
| Request/response | 本阶段不改 Controller/DTO/API,不适用 |
|
||||
| MQ/Consumer | 本阶段不涉及,不适用 |
|
||||
| DB/Trace/Prompt | 本阶段禁止修改,阶段 3 处理 |
|
||||
|
||||
### Reuse and new infrastructure
|
||||
|
||||
- 新建中立 `com.superbiz.agent.diagnosis.protocol`:`JsonPayloadSupport`、Executor/Verifier/Composer protocol、safe input/rendering、`EvidenceGapExtractor`;不得依赖 Graph/Hook/ChatService/ThreadLocal。
|
||||
- 新建 `graph.diagnosis` Node 层:invoker wrapper、failure classifier、四个 Agent adapters、Gatekeeper、Verified Input、Retry Prepare、Fallback 和 action assembly。
|
||||
- 不新建 Prompt/Agent factory;阶段 3 通过构造注入已有 ReactAgent 实例。
|
||||
- 不新增 Maven dependency、数据库迁移、配置项或生产 consumer。
|
||||
|
||||
### Pre-apply conclusion
|
||||
|
||||
参考实现、API 签名、异常和测试标准已足以指导实现;未发现 devflow/OpenSpec 冲突。进入 TDD tracer bullet,先锁定共享 Executor parser 的合法 no-evidence 与 malformed 行为。
|
||||
|
||||
## Apply Completion And Verification
|
||||
|
||||
### Assembly alignment
|
||||
|
||||
- 首个共享 protocol 模块与最终真实 Graph action assembly 均逐项对照 design/specs:invoker 显式透传 RunnableConfig,Gatekeeper 单次 fail-closed,Verified Input 精确投影,Verifier/Composer 固定输入重试,critical evidence retry 与两类 Fallback 边界全部落地。
|
||||
- `DiagnosisGraphFactory` 继续独占技术重试计数、evidence retry 计数和 Planner mode/reset;Node 不重复拥有编排计数。
|
||||
- 新增源码中无 `ThreadLocal`、`VerifierInputHook`、`tool_trace_summary`、`raw_executor`、TODO 或 FIXME;protocol 包无 Graph/Hook/ChatService 反向依赖。
|
||||
- `ChatService` 无 Diagnosis Graph/CompiledGraph 引用,生产切换保持在阶段 3;DB migration、Trace DTO/entity/repository 和 prompts 均无 diff。
|
||||
|
||||
### Automated verification
|
||||
|
||||
- 新 protocol/Node/真实 CompiledGraph/Router/Trace focused suite:通过。
|
||||
- 旧 `ChatServiceSequentialAgentTest`、`VerifierInputHookTest`、`ExecutorGatekeeperServiceTest` 回归:通过。
|
||||
- 合计 100 tests,0 failures,0 errors,0 skipped。
|
||||
- `mvn -q -DskipTests test-compile`:通过。
|
||||
- `openspec validate chat-diagnosis-stategraph-real-nodes --strict`:通过。
|
||||
- `openspec validate --specs --strict`:13 passed,0 failed。
|
||||
- `git diff --check`:通过;仅报告 Git 既有 LF/CRLF 转换提示,无 whitespace error。
|
||||
|
||||
### Deferred final verification
|
||||
|
||||
- 阶段 2 按用户确认不运行 Maven live E2E,不启动应用,不检查 `logs/`,不查询数据库。
|
||||
- 上述端到端、日志和 `scripts/query_mysql.py` 数据库核验统一保留到阶段 5 全部实现完成后执行。
|
||||
@@ -0,0 +1,25 @@
|
||||
# Chat Diagnosis StateGraph Real Nodes Evidence
|
||||
|
||||
## 证据
|
||||
|
||||
| 来源 | 证据 | 结论 | 是否已汇报 |
|
||||
|---|---|---|---|
|
||||
| `VerifierInputHook.java`、`ChatService.java` | Executor/Verifier/Composer 解析与安全渲染原实现 | 抽取到中立 protocol 并让旧路径委托,避免双真理源 | 是 |
|
||||
| `ExecutorGatekeeperService.java` | `validateRun` 与 checked binding/matched_text 契约 | Graph Gatekeeper 必须按当前 runId 单次调用并 fail closed | 是 |
|
||||
| 本地 Graph/ReactAgent 1.1.2.0 API | `ReactAgent.call(String,RunnableConfig)` 与 config-aware Graph action | 最小 invoker 可精确透传输入和当前 Run metadata | 是 |
|
||||
| 阶段 0/1 OpenSpec archives | 路由、计数、状态与安全边界冻结 | 阶段 2 不改变 Graph counter 所有权或生产入口 | 是 |
|
||||
| 新 protocol/Node/CompiledGraph tests | PASS、REJECT、LOW_CONFID、critical retry、固定输入重试和安全 fallback | 真实 Nodes 的可观察路径和材料边界已覆盖 | 是 |
|
||||
| 旧 Sequential/Hook/Gatekeeper tests | 共享抽取后的旧路径回归 | 阶段 2 未破坏当前生产控制流 | 是 |
|
||||
|
||||
## Evidence-driven 结论
|
||||
|
||||
- Graph Verifier 不得注册旧 `VerifierInputHook`,否则会双执行 Gatekeeper 并泄漏完整 tool trace。
|
||||
- Verified Input 必须用 claim/invocation/tool/path 精确关联 passed binding;不能复刻 Gatekeeper 判断或读取未引用工具结果。
|
||||
- Router 与 Retry Prepare 必须共用 critical-gap 提取规则:仅 `is_critical=true` 的 `no_evidence`/`indirect_support`。
|
||||
- 技术重试输入必须字节一致,且不得重跑前序 Node;计数仍由 Graph factory 统一拥有。
|
||||
- 当前 ChatService 无 Graph 引用,DB/Trace/Prompt 无 diff,满足阶段 2 的生产隔离要求。
|
||||
|
||||
## 风险与后续证据
|
||||
|
||||
- 本阶段使用 fake invoker 和 focused tests,不证明真实模型/外部基础设施联通;阶段 5 最终 E2E 统一补证。
|
||||
- Prompt 输入说明、生产装配、Run/Trace 持久化属于阶段 3,不能提前从阶段 2 证据推断已完成。
|
||||
@@ -0,0 +1,69 @@
|
||||
# Chat Diagnosis StateGraph Routing Skeleton Acceptance
|
||||
|
||||
## 结果
|
||||
|
||||
已接受。阶段 1 完成未接生产入口的 Graph 骨架和 Fake Node 路由体系。
|
||||
|
||||
## 验证
|
||||
|
||||
### 静态验证
|
||||
|
||||
- 命令:`git diff --check`
|
||||
- 结果:passed。
|
||||
- 检查:production refs、forbidden deps、23 changed paths 白名单。
|
||||
- 结果:passed,outside refs=0,forbidden refs=0,out-of-scope=0。
|
||||
|
||||
### 脚本验证
|
||||
|
||||
- 命令:`mvn -q "-Dtest=DiagnosisGraphRoutingTest,DiagnosisOrchestrationTraceBuilderTest" test`
|
||||
- 结果:passed,35 tests(29 routing + 6 trace),0 failure/error。
|
||||
- 覆盖:正常、三类技术 retry、Executor 不重试、Gatekeeper、evidence retry、Composer、unknown fail-closed、threadId、Append events 和 trace。
|
||||
|
||||
- 命令:`mvn -q "-DskipTests" test`
|
||||
- 结果:passed。
|
||||
- 覆盖:main/test compilation。
|
||||
|
||||
- 命令:`openspec validate chat-diagnosis-stategraph-routing-skeleton --type change --strict --json`
|
||||
- 结果:passed,1/1。
|
||||
|
||||
- 命令:`openspec validate --specs --strict --json`
|
||||
- 结果:passed,12/12(归档前)。
|
||||
|
||||
### 浏览器/人工验证
|
||||
|
||||
- 结果:not run。
|
||||
- 原因:无 UI 或生产入口变化。
|
||||
|
||||
### 未验证
|
||||
|
||||
- Maven E2E:not run,用户要求仅阶段 5 全部实现后统一执行。
|
||||
- `logs/`:not inspected,保留到阶段 5。
|
||||
- 数据库:not queried,保留到阶段 5。
|
||||
- 真实模型/Agent:not invoked,属于阶段 2。
|
||||
|
||||
## 已完成范围
|
||||
|
||||
- 显式 Graph Core direct dependency。
|
||||
- 26 state keys、typed status、topology/route/reason constants。
|
||||
- 八个 config-aware action ports 和真实 CompiledGraph factory。
|
||||
- Planner/Verifier/Composer 技术计数、一次 evidence retry、recursion limit 32。
|
||||
- fail-closed router、events Append 和 trace builder。
|
||||
- 35 个 Fake Node/trace tests。
|
||||
|
||||
## 已知限制
|
||||
|
||||
- Skeleton 没有生产消费者,阶段 3 才切换 ChatService。
|
||||
- Fake Node 只证明控制流,不证明真实 Agent JSON、Gatekeeper 或安全输入映射。
|
||||
- orchestration trace 尚未持久化或通过 API 暴露。
|
||||
|
||||
## Bug 修复和诊断
|
||||
|
||||
- 架构审计发现并修正 Graph Core 传递依赖所有权,改为 BOM 管理的直接依赖。
|
||||
- 自查补齐全部正常节点 threadId、Verifier REJECT 和缺失 effective verdict 场景。
|
||||
|
||||
## 交接
|
||||
|
||||
- 下一步:阶段 1 Git commit;完成后才能创建阶段 2 change。
|
||||
- Delta sync:新增 `chat-diagnosis-stategraph-routing-skeleton` 主 spec,共 6 requirements。
|
||||
- OpenSpec 归档确认:用户已要求每阶段 archive,授权已存在。
|
||||
- OpenSpec 归档结果:已同步主 spec,并归档到 `openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-routing-skeleton/`。
|
||||
@@ -0,0 +1,21 @@
|
||||
# Chat Diagnosis StateGraph Routing Skeleton Brief
|
||||
|
||||
## 背景
|
||||
|
||||
- 用户目标:ISS-011 阶段 1 独立完成 Graph 骨架和 Fake Node 路由测试,archive/commit 后才能进入真实 Node 阶段。
|
||||
- 当前问题:阶段 0 只有设计基线,仓库此前没有可编译 StateGraph 或条件边验证。
|
||||
- 关联 OpenSpec:`openspec/changes/chat-diagnosis-stategraph-routing-skeleton/`
|
||||
- devflow 分档:complex
|
||||
- 前置基线:`openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-design-freeze/`
|
||||
|
||||
## 范围
|
||||
|
||||
- 本次要做:Graph Core 直接依赖、状态/枚举、config-aware action ports、deterministic router、Graph factory、有限计数、events/trace builder、Fake Node tests。
|
||||
- 本次不做:真实 Agent/Gatekeeper、ChatService、Hook、DB、Trace API、旧实现清理、Maven E2E。
|
||||
- 影响区域:`pom.xml`、`com.superbiz.agent.graph.diagnosis`、对应 test 包。
|
||||
|
||||
## OpenSpec 对齐
|
||||
|
||||
- proposal 覆盖状态:已覆盖 skeleton-only 目标、L2 边界、测试与 E2E 非目标。
|
||||
- specs 覆盖状态:6 个 requirements 覆盖编译、Planner、Executor/Gatekeeper、Verifier、Composer、trace。
|
||||
- tasks 覆盖状态:12/12 完成。
|
||||
@@ -0,0 +1,112 @@
|
||||
# Chat Diagnosis StateGraph Routing Skeleton Decisions
|
||||
|
||||
## Question Pool
|
||||
|
||||
| # | 维度 | 问题 | 模式 | 状态 |
|
||||
|---|---|---|---|---|
|
||||
| Q1 | 术语 | 阶段 1 的 Graph State、event、trace 含义从哪里继承? | evidence-driven | 已解决 |
|
||||
| Q2 | 边界 | 阶段 1 是否接入 ChatService 或真实 Agent/Service? | evidence-driven | 已解决 |
|
||||
| Q3 | 技术 | 锁定 1.1.2.0 是否支持所需 Node/Edge、策略和 recursion limit? | evidence-driven | 已解决 |
|
||||
| Q4 | 技术 | Node action port 是否需要 RunnableConfig? | evidence-driven | 已解决 |
|
||||
| Q5 | 验收 | 阶段 1 是否有必要添加单元测试? | evidence-driven + user rule | 已解决 |
|
||||
| Q6 | 接口 | 新骨架的接口影响等级与消费者是什么? | evidence-driven | 已解决 |
|
||||
| Q7 | 循环 | recursion limit 应取多少,是否替代业务计数? | evidence-driven | 已解决 |
|
||||
| Q8 | 阶段 | 是否在本 change 实现真实 nodes、DB、Trace API 或旧代码清理? | user-interview(已由六阶段口径确认) | 已解决 |
|
||||
|
||||
## Evidence-driven
|
||||
|
||||
| 结论 | 证据来源 | 是否已汇报用户 |
|
||||
|---|---|---|
|
||||
| 阶段 1 必须完整继承阶段 0 baseline | archived design/spec/ADR | 已汇报 |
|
||||
| 本阶段只做 Fake Node 骨架,不接真实模型 | ISS-011 阶段 1/2 边界 | 已汇报 |
|
||||
| 1.1.2.0 支持 AsyncNodeActionWithConfig、AsyncEdgeActionWithConfig、conditional edges、Replace/Append、recursionLimit 和 threadId | 本地 JAR `javap` / `javap -c` | 已汇报 |
|
||||
| AppendStrategy 将 list/collection 追加为有序列表,可用于 node terminal events | 本地 AppendStrategy bytecode | 已汇报 |
|
||||
| 路由是新增行为且分支多,单元测试有必要 | 阶段 1 完成标准与用户“必要则加”规则 | 已汇报 |
|
||||
| 最坏合法路径少于 20 次 Node 执行,limit 32 有安全余量 | 冻结路由矩阵的路径计数 | 已汇报 |
|
||||
| 当前仓库没有 Graph 包或实现 | `rg` / package 目录核查 | 已汇报 |
|
||||
| 生产代码将直接 import Graph Core,必须从传递依赖提升为 BOM 管理的直接依赖 | pom 与 dependency tree / 架构审计 | 已汇报 |
|
||||
|
||||
## User-interview
|
||||
|
||||
| 问题原文 | 用户原话 | 确认状态 | OpenSpec 回写 |
|
||||
|---|---|---|---|
|
||||
| 阶段 1 是否应独立执行 sm-flow? | “iss-011里每个阶段,都是一个sm-flow” | 已确认 | 本 change 独立边界 |
|
||||
| 阶段 1 是否执行 E2E? | “端到端只在最后阶段全部完成后才验证” | 已确认 | Out of Scope / Acceptance |
|
||||
| 阶段 1 是否添加单元测试? | “如果有必要添加单元测试验收的话,就加” | 已确认规则;本阶段判定必要 | Acceptance |
|
||||
| 是否可提前实现阶段 2–5? | “每个阶段需要归档完并提交才能进入下一个阶段” | 已确认不可提前 | Out of Scope |
|
||||
|
||||
## Context And Handoff
|
||||
|
||||
- 前置 archive:`openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-design-freeze/`
|
||||
- 前置 commit:`581daff`
|
||||
- 当前 change:`chat-diagnosis-stategraph-routing-skeleton`
|
||||
- 后续 change:`chat-diagnosis-stategraph-real-nodes`,只能在本阶段 archive + commit 后创建。
|
||||
|
||||
## Technical Decisions
|
||||
|
||||
### Package and API
|
||||
|
||||
- 新包:`com.superbiz.agent.graph.diagnosis`。
|
||||
- `pom.xml` 显式声明 Graph Core,版本继续由现有 BOM 管理。
|
||||
- Graph 工厂接收 config-aware Node action ports,不依赖 Spring Bean 或真实 Agent。
|
||||
- Fake actions 只放 `src/test`。
|
||||
- 状态读取集中在 typed helper/router,避免各 edge 复制字符串解析。
|
||||
|
||||
### Retry ownership
|
||||
|
||||
- Planner/Verifier/Composer Node wrapper 根据进入节点前的上次技术失败状态增加各自 retry count。
|
||||
- 第一次失败时 count=0,允许 self-loop;重入后 count=1,第二次失败直接 Fallback。
|
||||
- Evidence Retry Node 将 run-level evidence count 增加一次并重置 planner retry count。
|
||||
- Edge 只选择 route,不隐式修改状态。
|
||||
|
||||
### Event and trace
|
||||
|
||||
- 每个 Fake/后续真实 Node 返回一个 event list,AppendStrategy 负责累积。
|
||||
- event 包含 node/outcome/reasonCode/attempt,不包含 payload。
|
||||
- trace builder 由相邻 events 生成 transition;final node/reason 来自最后 event。
|
||||
- events 为空时拒绝构造 trace,避免伪造路径。
|
||||
|
||||
### Interface impact
|
||||
|
||||
- 等级:L2 internal interface。
|
||||
- 新消费者:阶段 2 Node adapters、阶段 3 ChatService orchestrator、阶段 4 tests。
|
||||
- 外部 API/DB/运行路径:无变化。
|
||||
- 回滚:revert 本阶段提交即可;因为未接生产入口,没有数据迁移。
|
||||
- 兼容:后续 action adapters 必须实现已冻结 ports,不得传递父 State 全量数据。
|
||||
|
||||
## Risks Accepted
|
||||
- Stage 1 skeleton 会暂时存在但未被生产调用,这是阶段边界要求,不是死代码最终状态。
|
||||
- 真实 Agent 状态映射尚未验证,由阶段 2 独立 change 负责。
|
||||
- Maven E2E 不运行,生产路径完全未改变。
|
||||
|
||||
## Apply Evidence
|
||||
|
||||
- Task 1.1:显式声明 BOM 管理的 Graph Core;新增 26 个 state keys、状态枚举、拓扑/route/reason 常量、默认 Replace + events Append 策略和安全 typed reads。
|
||||
- Task 1.2:新增不可变 event/transition/trace records,构造期拒绝空 routing metadata 和非法计数,map 输出只有冻结字段。
|
||||
- Task 2.1:新增八个 non-null config-aware action ports,Fake/真实 Node 共用同一 Graph 接入面。
|
||||
- Task 2.2:新增纯 router;所有未知/缺失状态 fail closed,LOW_CONFID guard 只读 facts_checked,不构造 retry context。
|
||||
- Task 2.3:Graph Factory 注册八节点和全部条件边;wrapper 独占 retry/evidence control state,compile recursion limit=32。
|
||||
- 首模块 Maven compile:passed(31s),锁定 1.1.2.0 API 假设成立。
|
||||
- Task 3.1:trace builder 从 event 单向派生 transitions/final reason/degraded/evidence count,空或异类 events 显式失败。
|
||||
- Task 4.1:新增严格 FIFO Fake Node fixture,记录 sequence/calls/threadId,每 attempt 只追加一个 terminal event,意外调用立即失败。
|
||||
- Task 4.2:真实 CompiledGraph normal/Planner/Executor/Gatekeeper focused tests 首轮通过(Maven exit 0,约 67s)。
|
||||
- Task 4.3:Verifier/evidence/Composer 路由与独立计数测试通过(Maven exit 0,约 12s)。
|
||||
- Task 4.4:routing + trace focused suite 通过(Maven exit 0,约 28s),覆盖事件顺序、degraded、map 白名单、不可变性和非法输入。
|
||||
- Task 5.1:35 tests(29 routing + 6 trace)全通过;Maven test compilation、change strict 1/1、主 specs 12/12、diff check 均通过。
|
||||
- Task 5.2:现有 production refs=0,新 Graph 对真实 Service/DB/Trace refs=0,23 个 changed paths 全部命中阶段白名单;Maven E2E/log/DB 按用户口径保留到阶段 5。
|
||||
- Review:补齐所有正常节点 threadId 传播、Verifier REJECT→Composer 和 completed-without-verdict fail-closed 用例;增强后 focused suite exit 0。
|
||||
|
||||
## Cross-Artifact 对齐检查
|
||||
|
||||
| 上游 → 下游 | 检查内容 | 状态 |
|
||||
|---|---|---|
|
||||
| brief/prd → proposal | 阶段 1 目标、Fake Node 边界、测试口径和 E2E 非目标 | 已对齐 |
|
||||
| proposal → 设计产物 | direct dependency、状态、ports、router、counter、trace、测试架构 | 已对齐 |
|
||||
| 设计产物 → specs/tasks | 所有可观察路由、终止、安全默认和实现模块 | 已对齐 |
|
||||
| specs → tasks | 编译、全路由、trace、focused tests、生产隔离检查 | 已对齐 |
|
||||
|
||||
Gap:无。
|
||||
|
||||
## Architecture Audit
|
||||
|
||||
输入是 run-scoped 初始 state 与 `RunnableConfig`,处理链是 CompiledGraph → config-aware action ports → deterministic router/counters,输出是最终 state 与纯路由 trace;阶段 1 没有 Controller/Service/DB 消费者。Graph State 由单次 invoke 所有,events 只由 Node append,transitions 只由 builder 派生,避免双写。阶段 2 只实现 action ports,阶段 3 才将 orchestrator 交给 ChatService,因此当前未接生产入口是刻意生命周期边界。审计发现的唯一缺口是 Graph Core 直接依赖所有权,已回写 proposal/design/tasks。与阶段 0 archive 无冲突,L2 风险可由 Fake Node CompiledGraph tests 和 revert 单提交控制。
|
||||
@@ -0,0 +1,31 @@
|
||||
# Chat Diagnosis StateGraph Routing Skeleton Evidence
|
||||
|
||||
## 证据
|
||||
|
||||
| 来源 | 证据 | 结论 | 是否已汇报 |
|
||||
|---|---|---|---|
|
||||
| 阶段 0 archive/ADR | 冻结 26 个 state keys、完整路由、四类计数、run audit | 阶段 1 实现未偏离基线 | 是 |
|
||||
| 本地 Graph Core 1.1.2.0 `javap` | config-aware Node/Edge、conditional edge、recursion limit、threadId 存在 | 使用公共锁定 API 可编译 | 是 |
|
||||
| AppendStrategy bytecode | list/collection 按顺序追加 | 每 Node 返回单 event list 可形成实际路径 | 是 |
|
||||
| Maven compile | `mvn -q "-DskipTests" compile` exit 0 | direct dependency 和 Factory API 编译成立 | 是 |
|
||||
| Fake Node CompiledGraph tests | 29 routing tests,0 failure/error | 全条件边、retry、threadId、unknown fail-closed 成立 | 是 |
|
||||
| Trace tests | 6 tests,0 failure/error | transitions、degraded、map 白名单、不可变和非法输入成立 | 是 |
|
||||
| Test compilation | `mvn -q "-DskipTests" test` exit 0 | 全测试源可编译 | 是 |
|
||||
| OpenSpec validation | change 1/1、主 specs 12/12 strict | artifacts 与既有规格无回归 | 是 |
|
||||
| 生产隔离检查 | outside Graph refs=0,Graph 对真实 Service/DB/Trace refs=0 | 阶段 1 未接生产入口 | 是 |
|
||||
| Git 路径白名单 | 23 changed paths,out-of-scope=0 | 无跨阶段文件混入 | 是 |
|
||||
|
||||
## Evidence-driven 结论
|
||||
|
||||
- 结论:直接声明 Graph Core 是正确依赖所有权。
|
||||
- 证据:生产代码直接 import Graph Core;依赖原先仅由 Agent Framework 传递。
|
||||
- 风险:BOM 升级仍需重新跑真实 Graph tests。
|
||||
- 用户确认:不需要,属于构建稳健性。
|
||||
- 结论:recursion limit 32 足够且没有替代业务计数。
|
||||
- 证据:最坏合法路径低于 20;第二次技术失败和第二次 LOW_CONFID tests 均终止。
|
||||
- 风险:未来新增循环必须重算。
|
||||
- 用户确认:不需要,冻结业务上限未变。
|
||||
- 结论:单元测试必要,E2E 不必要。
|
||||
- 证据:阶段新增条件边行为但未接生产入口;35 tests 直接验证 Graph。
|
||||
- 风险:真实 Agent 映射仍留给阶段 2。
|
||||
- 用户确认:符合用户按必要性和最终阶段 E2E 规则。
|
||||
@@ -0,0 +1,50 @@
|
||||
# Chat Diagnosis StateGraph Test Suite 验收
|
||||
|
||||
## 结果
|
||||
|
||||
已接受。OpenSpec tasks 21/21 完成,阶段 4为 test-only,无生产行为变更。
|
||||
|
||||
## 验证
|
||||
|
||||
### 静态验证
|
||||
|
||||
- `git diff --check`:通过。
|
||||
- `git diff --name-only HEAD -- src/main`:0 个文件。
|
||||
- test inventory:三个权威类均存在;`ChatServiceSequentialAgentTest`/`VerifierInputHookTest` 均不存在;`ScriptedDiagnosisGraphActions` 定义 1 处。
|
||||
- `openspec validate chat-diagnosis-stategraph-test-suite --strict`:通过。
|
||||
- `openspec validate --specs --strict`:15 passed,0 failed。
|
||||
|
||||
### 脚本验证
|
||||
|
||||
- 三层权威 suite:4 suites / 43 tests,0 failures/errors/skipped。
|
||||
- 完整保留安全回归:31 suites / 126 tests,0 failures/errors/skipped。
|
||||
- `mvn -q -DskipTests test-compile`:通过。
|
||||
|
||||
### 浏览器/人工验证
|
||||
|
||||
- 未运行;阶段 4仅重构自动化测试,且用户要求最终人工/live 验收到阶段 5统一执行。
|
||||
|
||||
### 未验证
|
||||
|
||||
- 未使用 Maven 启动应用做 live E2E。
|
||||
- 未检查 `logs/`。
|
||||
- 未执行 `scripts/query_mysql.py`。
|
||||
- 剩余风险:真实模型、工具、Flyway/MySQL 和最终 Trace 内容仍需阶段 5 E2E/log/DB 证据。
|
||||
|
||||
## 已完成范围
|
||||
|
||||
- 建立 Workflow、Node Contract、Chat Integration 三层权威测试体系。
|
||||
- 补齐 ceiling/second LOW_CONFID、tool-failure legal snapshot、partial-pass REJECT 和 Verifier invalid status 边界。
|
||||
- 删除旧 Hook implementation test,并保留 parser/Gatekeeper/projection/Composer 等安全回归。
|
||||
- 用结构测试和 source gate 防止旧 Sequential/Hook 测试回归。
|
||||
|
||||
## 已知限制
|
||||
|
||||
- 生产 `VerifierInputHook`/`VerifierContextHolder` 类型仍存在但已无生产/权威测试消费者;阶段 5清理。
|
||||
- component tests 与权威层存在有意的分层 overlap,详见 `evidence.md`。
|
||||
|
||||
## 交接
|
||||
|
||||
- OpenSpec archive:已同步 2 份 delta specs,并归档到 `openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-test-suite/`。
|
||||
- 下一步:审查精确 Git diff并完成阶段 4独立提交,之后启动阶段 5。
|
||||
- OpenSpec 归档确认:用户已授权直接执行后续归档;归档已完成。
|
||||
@@ -0,0 +1,20 @@
|
||||
# Chat Diagnosis StateGraph Test Suite Brief
|
||||
|
||||
## 背景
|
||||
|
||||
- 用户目标:将 ISS-011 阶段 4作为独立 sm-flow,建立以 Graph 路径和外部行为为中心的新测试体系。
|
||||
- 当前问题:阶段 1–3 覆盖充分但组织分散,旧 Hook payload test 仍会约束已退出生产的隐式状态机。
|
||||
- 关联 OpenSpec:`openspec/changes/chat-diagnosis-stategraph-test-suite/`
|
||||
- devflow 分档:complex;接口影响 L1 test-only。
|
||||
|
||||
## 范围
|
||||
|
||||
- 本次要做:Workflow/Node Contract/Chat Integration 三层权威入口、Issue 路径矩阵补齐、旧 Hook test 退役、保留安全回归。
|
||||
- 本次不做:不改生产源码,不删除生产 Hook/ThreadLocal 类型,不运行 live E2E/log/DB 验收。
|
||||
- 影响区域:Diagnosis Graph tests、ChatService integration test、OpenSpec/devflow。
|
||||
|
||||
## OpenSpec 对齐
|
||||
|
||||
- proposal/design/specs:已覆盖,2 个 delta capabilities。
|
||||
- tasks:21/21 已完成。
|
||||
- 生产行为:无变化,`src/main` diff=0。
|
||||
@@ -0,0 +1,121 @@
|
||||
# Chat Diagnosis StateGraph Test Suite Decisions
|
||||
|
||||
## Entry Summary
|
||||
|
||||
- 问题:阶段 1–3 的安全覆盖已充足,但测试命名/组织仍是逐步实现产物,尚未形成 ISS-011 指定的 Workflow、Node Contract、Chat Integration 三层权威体系。
|
||||
- 期望:阶段 4只重构测试结构并补齐矩阵,不改变生产行为;归档并提交后才进入阶段 5。
|
||||
- 分档:complex(路径矩阵广、涉及旧安全测试退役,但接口影响为 L1 test-only)。
|
||||
- Change:`chat-diagnosis-stategraph-test-suite`。
|
||||
- 授权:用户已要求直接实现,阶段门禁与阶段 5 才 live E2E 的约束不变。
|
||||
|
||||
## Context Sources
|
||||
|
||||
- ISS-011 阶段 4、测试策略和验收标准。
|
||||
- `chat-diagnosis-stategraph-design-freeze` 的 test migration requirement。
|
||||
- 阶段 1–3 archive/acceptance 和当前 119-test focused baseline。
|
||||
- `DiagnosisGraphRoutingTest`、各 Node tests、`DiagnosisRealGraphIntegrationTest`、`ChatDiagnosisGraphRuntimeTest`、`ChatServiceGraphIntegrationTest`。
|
||||
- `VerifierInputHookTest`、protocol parser tests、`ExecutorGatekeeperServiceTest` 与 Trace/Controller/Repository/Eval tests。
|
||||
|
||||
## Question Pool
|
||||
|
||||
| # | 维度 | 问题 | 模式 | 状态 |
|
||||
|---|---|---|---|---|
|
||||
| Q1 | 术语 | Workflow、Node Contract、Chat Integration 的职责边界是什么? | evidence-driven | 已解决 |
|
||||
| Q2 | 边界 | 是否把所有现有 Graph unit tests 合并成三个巨型类? | evidence-driven | 已解决 |
|
||||
| Q3 | 旧测试 | `VerifierInputHookTest` 在显式 Graph Gatekeeper 后应保留、改写还是删除? | evidence-driven | 已解决 |
|
||||
| Q4 | 验收 | 如何证明阶段 4矩阵完整且没有恢复固定 Sequential 顺序? | evidence-driven | 已解决 |
|
||||
| Q5 | 阶段 | 是否允许为测试可测性改生产代码或执行 live E2E? | user-interview(既有冻结规则) | 已确认 |
|
||||
|
||||
## Evidence-driven Findings
|
||||
|
||||
- Q1:Issue 已明确三类测试;现有 `DiagnosisGraphRoutingTest` 对应 Workflow,分散 Node/Protocol tests 对应 Node Contract,`ChatServiceGraphIntegrationTest` 对应外部生命周期。
|
||||
- Q2:现有细粒度测试失败定位清晰,全部合并会制造大文件;应保留专用 unit tests,同时新增/重命名三层权威入口并共享夹具。
|
||||
- Q3:生产 Graph Verifier 已不注册 Hook,Hook test 仍验证 raw/full-trace/ThreadLocal payload,与 verified-only 生产协议冲突;parser/Gatekeeper/投影行为已有独立 tests,故阶段 4删除 Hook test,生产类型留到阶段 5。
|
||||
- Q4:以 Issue 必需路径清单建立 requirement-to-test matrix;source check 禁止 `SequentialAgent`/`VerifierInputHookTest` 成为新 suite 依赖,并运行保留安全回归。
|
||||
|
||||
## User-interview Confirmation
|
||||
|
||||
| 问题 | 用户原话/既有确认 | 状态 | OpenSpec 回写 |
|
||||
|---|---|---|---|
|
||||
| Q5 阶段边界 | “端到端只在最后阶段全部完成后才验证;每个阶段如果有必要添加单元测试验收的话,就加” | 已确认 | proposal |
|
||||
|
||||
## Grill-with-docs Result
|
||||
|
||||
- 术语不进入业务 glossary:Workflow/Node Contract/Integration 是测试架构术语,不改变 Session、Run、Trace、Gatekeeper 或 evidence gap 领域定义。
|
||||
- 具体场景压力测试:同 session 多 run 属于 Chat Integration;Gatekeeper REJECT/LOW_CONFID 与 retry exhaustion 属于 Workflow;failed binding 过滤与 verified-only payload 属于 Node Contract。
|
||||
- 旧 Hook test 的有效行为已分别迁移到 `ExecutorEvidenceParserTest`、`ExecutorGatekeeperServiceTest`、`GatekeeperNodeTest` 和 `VerifiedInputNodeTest`;删除不会丢失安全真理源。
|
||||
- 没有难以逆转的新架构取舍,不创建 ADR;测试组织可以在保持行为矩阵的前提下继续演进。
|
||||
|
||||
## Discover Status
|
||||
|
||||
- `devflow/index.md`:命中阶段 0–3 archive。
|
||||
- 生产调用链:阶段 3 已冻结且测试阶段默认不修改。
|
||||
- 接口影响:L1 test-only;无 API/DTO/DB/Prompt/运行时消费者变化。
|
||||
- 未解决问题:0。
|
||||
- Draft 产物:proposal + decisions;尚未生成 design/spec/tasks,尚未修改测试代码。
|
||||
|
||||
## Architecture Audit
|
||||
|
||||
### Test ownership map
|
||||
|
||||
`ISS-011 path matrix -> DiagnosisGraphWorkflowTest -> ScriptedDiagnosisGraphActions -> real DiagnosisGraphFactory` 负责控制流;`Node/protocol contracts -> DiagnosisGraphNodeContractTest + focused component tests -> real Node actions/parsers/Gatekeeper` 负责安全投影;`public lifecycle -> ChatServiceGraphIntegrationTest -> Run repositories/Eval/Trace mapping` 负责外部行为。Controller、Repository、Trace、Eval 和 protocol tests 是三层体系的下游安全消费者,不应被重写成 Graph 内部顺序断言。
|
||||
|
||||
### Data and lifecycle ownership
|
||||
|
||||
- Workflow fixtures 只拥有脚本状态、调用计数和 events,不创建 Session/Run。
|
||||
- Node Contract fixtures 只拥有 invoker input/output 和 mock Gatekeeper current-run result,不持久化生产实体。
|
||||
- Chat Integration fixtures 只观察 ChatService public result 和 current Run persistence,不推断内部 Node 次序。
|
||||
- `VerifierInputHookTest` 删除后不产生数据契约缺口:Executor parser、Gatekeeper、passed-binding projection 各自已有单一测试所有者。
|
||||
|
||||
### Coupling risks
|
||||
|
||||
- 最大风险是 Workflow 与 Node Contract 都断言完整路径而重复;设计将 Fake route matrix 与 real-node input/security matrix分开。
|
||||
- `ScriptedDiagnosisGraphActions` 是唯一 Fake topology fixture;不新增第二套 Graph builder。
|
||||
- 测试-only阶段禁止 `src/main` diff,避免为测试便利扩大 production API。
|
||||
- 类重命名使用 Git rename,旧名称仅允许出现在 OpenSpec/devflow迁移说明中。
|
||||
|
||||
### Cross-artifact alignment
|
||||
|
||||
| 上游 → 下游 | 检查内容 | 状态 |
|
||||
|---|---|---|
|
||||
| brief/proposal → proposal | 三层体系、旧 Hook test退役、保留安全回归、阶段 5 E2E 延期 | 已对齐 |
|
||||
| proposal → design | rename-not-copy、职责归属、production diff=0、rollback | 已对齐 |
|
||||
| design → specs/tasks | Workflow/Node/Integration矩阵、Hook test删除、source inventory和验证门禁 | 已对齐 |
|
||||
| specs → tasks | 每类 scenario 均有 rename、补缺、回归或静态验收任务 | 已对齐 |
|
||||
|
||||
### Audit result
|
||||
|
||||
架构审计未发现业务 glossary、阶段 0–3 specs 或生产行为冲突。新 capability 只描述测试验证系统,modified design-freeze requirement 完整保留并细化旧测试替换边界。接口影响保持 L1,cross-artifact gap=0,无需回写生产 spec 或创建 ADR。
|
||||
|
||||
## Commit Gate
|
||||
|
||||
- schema:spec-driven;proposal/design/2 delta specs/tasks 全部 done,applyRequires=`tasks` 已满足。
|
||||
- OpenSpec:当前 change strict pass;15 个主 specs strict pass。
|
||||
- Cross-artifact:4/4 已对齐,gap=0。
|
||||
- Question pool:4 个 evidence-driven 已查证,1 个 user-interview 由用户既有原话确认,无未决项。
|
||||
- Interface impact:L1 test-only;design 有独立影响/回滚章节,默认 `src/main` diff=0。
|
||||
- Preflight:`git diff --check` 通过,当前仅 Draft OpenSpec/devflow 与根目录计划文件,无测试/生产代码修改。
|
||||
- 结论:Draft OpenSpec 达到可执行状态,创建 `.committed` 后进入 Apply。
|
||||
|
||||
## Apply Completion
|
||||
|
||||
- `DiagnosisGraphRoutingTest` 已以 Git rename 演进为 `DiagnosisGraphWorkflowTest`;所有 scripted run 统一断言 events 与真实 sequence 完全一致。
|
||||
- `DiagnosisRealGraphIntegrationTest` 已演进为 `DiagnosisGraphNodeContractTest`;补齐合法工具失败限制、partial-pass REJECT 和 Verifier invalid 无伪 verdict。
|
||||
- Workflow 显式断言 Gatekeeper ceiling 将模型 PASS 限制为 LOW_CONFID 且不触发 evidence retry,以及第二次 LOW_CONFID 不再补证据。
|
||||
- `ChatServiceGraphIntegrationTest` 增加 SessionContextHolder finally cleanup 断言;public Run/Trace/Eval/multi-run 覆盖保持。
|
||||
- `VerifierInputHookTest` 已删除;生产 Hook/ThreadLocal 类型未修改,留待阶段 5清理。
|
||||
- 新增 `DiagnosisGraphTestSuiteStructureTest`,保证三个权威类存在、Sequential/Hook实现测试不存在且权威测试不引用旧实现。
|
||||
|
||||
## Verification Summary
|
||||
|
||||
- 新权威层:4 suites / 43 tests,0 failures/errors/skipped。
|
||||
- 完整保留安全回归:31 suites / 126 tests,0 failures/errors/skipped。
|
||||
- Maven test compilation:通过。
|
||||
- OpenSpec:当前 change strict pass;主 specs 15/15 strict pass。
|
||||
- 静态门禁:`git diff --check` 通过;required authoritative classes=3;legacy tests=0;scripted fixture definitions=1;`src/main` diff=0。
|
||||
- 按阶段门禁未运行 Maven live E2E、未检查 `logs/`、未执行 `scripts/query_mysql.py`;统一保留到阶段 5。
|
||||
|
||||
## Archive Result
|
||||
|
||||
- 2 份 delta specs 已同步:新增 test-suite capability 6 条 requirements,修改 design-freeze test migration requirement 1 条。
|
||||
- OpenSpec 已归档到 `openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-test-suite/`。
|
||||
@@ -0,0 +1,42 @@
|
||||
# Chat Diagnosis StateGraph Test Suite Evidence
|
||||
|
||||
## Requirement-to-test Matrix
|
||||
|
||||
| ISS-011 路径/边界 | 权威测试 | 辅助证据 |
|
||||
|---|---|---|
|
||||
| PASS 与精确 event/transition | `DiagnosisGraphWorkflowTest.normalPassPathUsesCompiledGraphAndPreservesEventOrder` | `DiagnosisGraphNodeContractTest.compiledRealNodeGraphCompletesPassPathInExactOrder` |
|
||||
| Planner 一次技术重试/耗尽/非重试失败 | `DiagnosisGraphWorkflowTest.planner*` | Planner adapter focused test |
|
||||
| Executor FAILED/TOOL_BLOCKED/INVALID/no-evidence | `DiagnosisGraphWorkflowTest.executor*` | `DiagnosisGraphNodeContractTest.legalSnapshotAfterToolFailureRemainsCompletedAndReachesGatekeeper` |
|
||||
| Gatekeeper PASS/LOW/REJECT/unknown | `DiagnosisGraphWorkflowTest.gatekeeper*` | Gatekeeper Node/service tests |
|
||||
| partial-pass REJECT 不泄漏 claim | Workflow unsafe route | `DiagnosisGraphNodeContractTest.gatekeeperRejectSkipsVerifierAndUsesPreVerificationFallback` |
|
||||
| verified-only passed-binding projection | Workflow VerifiedInput route | `VerifiedInputNodeTest` + Verifier adapter test |
|
||||
| Verifier 技术重试/耗尽/非重试失败 | `DiagnosisGraphWorkflowTest.verifier*` | `DiagnosisGraphNodeContractTest.verifierInvalidOutputSetsExecutionStatusWithoutFabricatedVerdict` |
|
||||
| critical evidence retry、无 gap、non-critical、ceiling、第二次 LOW | `DiagnosisGraphWorkflowTest.*LowConfidence*` / `secondLowConfidence*` | EvidenceRetryPrepareNodeTest + real full-snapshot integration |
|
||||
| 第二轮完整 snapshot 再验真 | Workflow evidence retry | `DiagnosisGraphNodeContractTest.criticalGapPerformsOneIncrementalRoundAndRevalidatesCompleteSnapshot` |
|
||||
| Verifier REJECT 安全表达 | `DiagnosisGraphWorkflowTest.verifierRejectStillRunsComposerWithSafeMaterial` | ComposerSafeInputBuilderTest |
|
||||
| Composer retry/耗尽/非重试/安全 Fallback | `DiagnosisGraphWorkflowTest.composer*` | ComposerNodeAdapterTest + FallbackNodeTest |
|
||||
| ChatResult/Run/Trace/evaluation/cleanup | `ChatServiceGraphIntegrationTest` | Controller/Trace/Repository/Eval tests |
|
||||
| 同 session 多 run 隔离 | `ChatServiceGraphIntegrationTest.sameSessionCreatesDistinctRunIdsAndKeepsTracePerRun` | Run repository/Trace exact-run tests |
|
||||
| 三层结构与旧实现测试退役 | `DiagnosisGraphTestSuiteStructureTest` | source inventory command |
|
||||
|
||||
## 旧 Hook test 安全映射
|
||||
|
||||
| 旧行为 | 新真理源 |
|
||||
|---|---|
|
||||
| fenced/prefixed/malformed Executor JSON | `ExecutorEvidenceParserTest` |
|
||||
| invocation/raw_path/evidence excerpt真实性 | `ExecutorGatekeeperServiceTest` |
|
||||
| Gatekeeper status/severity/audit | `GatekeeperNodeTest` |
|
||||
| passed binding 精确投影 | `VerifiedInputNodeTest` |
|
||||
| Verifier verified-only payload | `VerifierNodeAdapterTest` + `ChatVerifierPromptContractTest` |
|
||||
|
||||
## 验证证据
|
||||
|
||||
- 31 suites / 126 tests:0 failures、0 errors、0 skipped。
|
||||
- test compilation、当前 change strict、主 specs 15/15、diff check 全通过。
|
||||
- `src/main` diff=0;三个权威类存在;旧 Sequential/Hook tests不存在;Scripted fixture 定义唯一。
|
||||
|
||||
## Intentional overlap and limits
|
||||
|
||||
- Workflow 与 Node Contract 都覆盖 PASS/REJECT,但前者验证 route/event,后者验证真实输入/安全材料;这是分层证据,不是复制 fixture。
|
||||
- 细粒度 component tests 保留以定位失败,不要求全部搬进三个权威类。
|
||||
- 真实模型/工具、日志和数据库行为未在阶段 4验证,统一由阶段 5 live E2E承担。
|
||||
@@ -1,44 +0,0 @@
|
||||
# Acceptance: single-react-aci-tool-contracts
|
||||
|
||||
## 实现结果
|
||||
|
||||
- RAG Contract:最小 query Request、bounded document evidence Result。
|
||||
- Log Contract:逻辑 Topic/Lookback Request、Mock provenance、Scope/Pattern/Event Result。
|
||||
- MySQL Contract:逻辑 data source、参数化 SQL Request、bounded structured rows Result。
|
||||
- 共享 Contract:snake_case Tool 名称、ACI 描述、不可变集合 helper,复用阶段 0 两套状态枚举。
|
||||
- 旧 Tool、Chat/AIOps、Controller、持久化、数据源和公开协议未修改。
|
||||
|
||||
## 静态验证
|
||||
|
||||
- `openspec validate single-react-aci-tool-contracts --strict`:通过。
|
||||
- `openspec instructions apply --change single-react-aci-tool-contracts --json`:12/12 tasks complete。
|
||||
- `rg` 引用检查:新 contract 生产包未接入旧运行链路。
|
||||
- 受保护文件 diff scope:旧 Tool、Chat/AIOps、Controller、Repository、resources 均为空。
|
||||
|
||||
## 脚本验证
|
||||
|
||||
- `mvn -q -DskipTests compile`:通过。
|
||||
- `mvn -q '-Dtest=RagToolContractTest,QueryLogsToolContractTest,MysqlToolContractTest' test`:通过。
|
||||
- `mvn -q '-Dtest=HarnessContractTest,LookupKnowledgeToolTest,QueryLogsToolsTest' test`:通过。
|
||||
|
||||
## 浏览器/人工验证
|
||||
|
||||
- 不适用。本阶段无 UI、Controller、SSE 或公开运行行为变化。
|
||||
|
||||
## 未验证
|
||||
|
||||
- 未执行 live LLM/Redis/CLS/MySQL E2E;本阶段没有接入这些运行路径,最终 live E2E 按 ISS-014 门禁留到阶段 7。
|
||||
- 未验证 ToolInterceptor 的真实 ID 传播;阶段 2/3A 必须以 `ToolCallRequest.getToolCallId()` 添加集成测试。
|
||||
- 未验证真实日志 adapter 的 `SourceKind` 扩展;本 Issue 首版明确只使用 Mock。
|
||||
- Provider 侧旧凭据轮换仍需凭据所有者完成,仓库只能证明明文已移除。
|
||||
|
||||
## 剩余风险与后续门禁
|
||||
|
||||
- 新旧 Contract 短期并存,阶段 3B/3C 接入前不得声称旧 Tool 已符合新 ACI 输出。
|
||||
- 下一阶段只能在本 change OpenSpec Archive 和 Git commit 完成后开始。
|
||||
|
||||
## 状态
|
||||
|
||||
- Stage acceptance: accepted
|
||||
- OpenSpec archive: archived at `openspec/changes/archive/2026-07-21-single-react-aci-tool-contracts`
|
||||
- Main spec sync: `openspec/specs/aci-evidence-tool-contracts/spec.md`(7 added requirements)
|
||||
@@ -1,32 +0,0 @@
|
||||
# Brief: single-react-aci-tool-contracts
|
||||
|
||||
## 背景
|
||||
|
||||
旧 RAG 和日志 Tool 暴露检索/基础设施细节与不一致状态,MySQL Tool 尚无 Agent-facing 类型。Harness 实现前需要先冻结三类最小 ACI 契约。
|
||||
|
||||
## 目标
|
||||
|
||||
- 冻结 RAG、日志、MySQL 的 Request/Result JSON Schema。
|
||||
- 统一 `evidence_status`,并保持其与 invocation lifecycle 独立。
|
||||
- 统一使用框架 `tool_call_id`,禁止模型传入或 Harness 生成第二套 ID。
|
||||
- 冻结简短 Tool 名称/描述和 Mock 日志来源边界。
|
||||
- 用三个独立契约测试锁定行为。
|
||||
|
||||
## 范围
|
||||
|
||||
- 新增 `com.superbiz.agent.harness.tool.contract` 值对象、枚举和描述常量。
|
||||
- 复用阶段 0 的 `InvocationStatus` 与 `EvidenceStatus`。
|
||||
- 验证 JSON、不可变集合、描述泄漏和新旧边界。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不切换旧 RAG/日志运行方法或 Chat/AIOps 注册。
|
||||
- 不实现投影、Redis store、真实日志适配器或 MySQL 执行。
|
||||
- 不修改 Controller/SSE 或公开协议。
|
||||
|
||||
## 元数据
|
||||
|
||||
- 分档:standard
|
||||
- 接口影响:L2 前置内部契约;当前运行行为无变化
|
||||
- 关联 Issue:ISS-014 阶段 1
|
||||
- 关联 OpenSpec:`openspec/changes/single-react-aci-tool-contracts`
|
||||
@@ -1,116 +0,0 @@
|
||||
# Decisions: single-react-aci-tool-contracts
|
||||
|
||||
## 规模与入口
|
||||
|
||||
- 分档:standard。
|
||||
- 入口:ISS-014 阶段 1,前置 `single-react-design-freeze` 已 Archive 并由 Git commit `58c3910` 固化。
|
||||
- 目标:冻结三类 evidence Tool 的 Agent-facing ACI 契约,不接入新运行链路。
|
||||
|
||||
## Context
|
||||
|
||||
- `devflow/index.md` 命中 `single-react-design-freeze`、`modular-rag-pipeline` 和 `evidence-trace-hardening`。
|
||||
- `devflow/glossary/CONTEXT.md` 已定义 Diagnosis Harness、Invocation Status、Evidence Status 与 Evidence Tools。
|
||||
- 阶段 0 已确认 `tool_call_id` 使用框架 ID、两套状态语义分离、阶段串行门禁和阶段 6B 才公开切换。
|
||||
- 未发现根目录旧 `CONTEXT.md` 与 glossary 冲突。
|
||||
|
||||
## Question Pool
|
||||
|
||||
| 维度 | 问题 | 模式 | 证据与结论 | 状态 |
|
||||
|---|---|---|---|---|
|
||||
| 术语 | invocation lifecycle 与 evidence result 是否使用同一状态? | evidence-driven | ISS-014 5.2、阶段 0 contract 明确分离;分别复用 `InvocationStatus` 与 `EvidenceStatus`。 | 已解决并汇报 |
|
||||
| 术语 | `tool_call_id` 由谁生成、从哪里取得? | evidence-driven | Spring AI `AssistantMessage.ToolCall.id()` 与 Alibaba `ToolCallRequest.getToolCallId()` 提供框架 ID;普通 `ToolContext` 不自动加入该 ID。Harness 不生成第二套 ID。 | 已解决并汇报 |
|
||||
| 边界 | 阶段 1 是否直接改旧 RAG/日志执行签名与返回值? | evidence-driven | ISS-014 阶段 1 只冻结 Contract,投影在阶段 3B、公开切换在阶段 6B;本阶段只新增契约代码和测试。 | 已解决并汇报 |
|
||||
| 边界 | 日志阶段是否实现真实 CLS/MCP 或保留 Topic discovery? | evidence-driven | ISS-014 8.1 明确继续 Mock、删除 Agent 侧 discovery、真实适配器不在本 Issue 提前设计。 | 已解决并汇报 |
|
||||
| 验收 | 如何证明契约已冻结且有界? | evidence-driven | 对三类独立 DTO 做精确 JSON、不可变集合、状态和描述泄漏测试;不以旧 Tool 集成测试代替。 | 已解决并汇报 |
|
||||
| 技术 | 框架 ID 能否在后续 Harness 边界取得? | evidence-driven | 本地依赖 Spring AI Alibaba 1.1.2.0 暴露 `ToolInterceptor.interceptToolCall(ToolCallRequest, ToolCallHandler)`,request 含 `toolCallId`。 | 已解决并汇报 |
|
||||
|
||||
## Grill 结论
|
||||
|
||||
- 术语、边界、验收三类问题均已由代码、依赖 API、阶段 0 档案和 ISS-014 证明。
|
||||
- 没有需要新增用户偏好或风险取舍的 `user-interview` 问题;不代理确认任何新方向。
|
||||
- `grill-with-docs` 要求的代码可证问题已先查证;结论已向用户汇报。
|
||||
- Proposal 已回写框架 ID 接入点、旧运行链路不切换、Mock 边界和 L2 接口影响。
|
||||
|
||||
## 已确认决策
|
||||
|
||||
- DTO 放在 Harness 的 Tool Contract 边界,复用阶段 0 的共享状态枚举,不在旧 `dto` 包继续堆叠协议。
|
||||
- 三类结果只携带 `evidence_status`,canonical invocation 的 `status` 保持独立;阶段 1 通过测试冻结枚举,不提前定义存储实现。
|
||||
- Tool description 使用代码常量冻结,后续 Tool adapter 注册时复用;旧 `@Tool` 注解本阶段不改,避免提前改变运行行为。
|
||||
- RAG 输入仅保留 `query`;日志输入仅保留逻辑 `topic/query/lookback_minutes`;MySQL 输入仅保留逻辑 `data_source/sql/params`。
|
||||
- 日志 `source_kind` 首版固定支持 `MOCK` 契约值,但保留 enum 扩展位置给后续真实适配器 change 审查。
|
||||
|
||||
## 能力与工具限制
|
||||
|
||||
- Discover 能力来源:`sm-flow` + `grill-with-docs`。
|
||||
- 仓库要求的 `codebase-retrieval` 和 LSP 工具在当前工具集中不可用;已用 `rg` 引用搜索、源码阅读和本地依赖 `javap` 补足事实核对。该限制不改变契约方向,但后续 Apply 仍需通过编译和引用测试验证。
|
||||
|
||||
## Cross-artifact 对齐
|
||||
|
||||
| 链路 | 状态 | 结论 |
|
||||
|---|---|---|
|
||||
| brief 目标/范围/非目标 -> proposal | 已对齐 | 三类 DTO、状态、框架 ID、短描述和不切旧运行链路均有对应。 |
|
||||
| proposal 范围/约束/承诺 -> design | 已对齐 | 包边界、ID 来源、record/defensive copy、三类 Schema 和迁移顺序均已设计。 |
|
||||
| design 决策/接口影响/风险 -> specs/tasks | 已对齐 | L2 边界、字段、状态、描述、Mock provenance 和运行不切换均有可验证 requirement 与任务。 |
|
||||
| specs 可观察行为 -> tasks | 已对齐 | 每类 Contract 都有实现与独立测试,另有状态、回归和 diff scope 验证。 |
|
||||
|
||||
## Architecture Audit
|
||||
|
||||
- 能力来源:`zoom-out`,以项目 glossary 的 Diagnosis Harness、Evidence Tools、Invocation Status 和 Evidence Status 术语审计。
|
||||
- 当前输入到输出链路仍为 `ChatController/ChatService` 或 `AiOpsService -> ReactAgent -> LookupKnowledgeTool/QueryLogsTools -> 旧结果`,新契约没有运行消费者。
|
||||
- 未来链路为 `Diagnosis Agent -> Alibaba ToolInterceptor/Harness -> typed Request -> adapter/store/projector -> bounded Result -> Agent observation`,阶段 1 只占有 typed contract 边界。
|
||||
- 数据所有权保持明确:框架拥有 `tool_call_id`,canonical invocation 拥有生命周期,Tool-specific result 拥有证据语义与有界内容。
|
||||
- 主要耦合风险是新旧契约短期并存被误当成已迁移;通过独立包、无旧调用方修改和后续阶段门禁控制,无 ADR 冲突。
|
||||
|
||||
## Commit Gate Preflight
|
||||
|
||||
- proposal、design、specs、tasks 文件完整,OpenSpec CLI 状态为 complete。
|
||||
- strict validation:`openspec validate single-react-aci-tool-contracts --strict` 通过。
|
||||
- question pool 中没有未汇报的 evidence-driven 结论或未确认的 user-interview 问题。
|
||||
- 接口影响为 L2,当前运行消费者零变更;阶段 6B 的 L4 切换保持独立。
|
||||
- cross-artifact 四段对齐无 gap,架构审计未发现需要回写的新实现约束。
|
||||
- Apply 已由用户对 ISS-014 全阶段的持续授权覆盖;仍严格限制在本 Committed OpenSpec tasks 内。
|
||||
|
||||
## Pre-apply Research
|
||||
|
||||
### 参考实现
|
||||
|
||||
- `src/main/java/com/superbiz/agent/tool/LookupKnowledgeTool.java`:确认旧 RAG 暴露 `LookupResult`、ContextPack 和检索 Trace,本阶段不改。
|
||||
- `src/main/java/com/superbiz/agent/agent/tool/QueryLogsTools.java`:确认旧日志输入包含 region/logTopic/limit、存在 Topic discovery 和 mutable nested DTO,本阶段不改。
|
||||
- `src/test/java/com/superbiz/agent/tool/LookupKnowledgeToolTest.java`:现有 RAG 行为回归基线。
|
||||
- `src/test/java/com/superbiz/agent/agent/tool/QueryLogsToolsTest.java`:现有 Mock 日志行为回归基线。
|
||||
- `src/main/java/com/superbiz/agent/harness/contract/*.java`:Java 17 record、Jackson snake_case 和共享状态枚举风格。
|
||||
|
||||
### 技术栈清单
|
||||
|
||||
- 请求/响应标准:Java 17 record + Jackson `@JsonProperty`,集合构造时 defensive copy。
|
||||
- Tool 定义:当前使用 Spring AI `@Tool`,新名称/描述先以常量冻结,后续 adapter 注册复用。
|
||||
- 框架调用 ID:Spring AI Alibaba `ToolCallRequest.getToolCallId()`;普通 `ToolContext` 不作为 ID 来源。
|
||||
- 异常与校验:本阶段只冻结结构;Schema、ID、权限、范围和状态组合错误由后续 Pre-Tool/Projector 显式返回安全 `ERROR`。
|
||||
- MQ/Consumer/加密验签:本 change 不涉及。
|
||||
|
||||
### 新建类型
|
||||
|
||||
- `AgentToolContracts` 与 contract defensive-copy helper。
|
||||
- RAG Request/Result/Evidence。
|
||||
- Log Topic/SourceKind/Request/Result/Scope/Pattern/Event。
|
||||
- MySQL Request/Result。
|
||||
- 三个独立 contract test classes。
|
||||
|
||||
### 影响半径
|
||||
|
||||
- 新增包当前应无生产调用方;旧 Chat/AIOps、Tool、Controller、Repository 和配置文件均不修改。
|
||||
- 通过 focused compile/tests 和 `rg`/diff scope 证明边界。
|
||||
|
||||
## Apply 结果
|
||||
|
||||
- 冲突分类:未发现 OpenSpec 遗漏、代码偏离或方向不确定项。
|
||||
- 新增共享 ACI Tool 名称/描述、defensive-copy helper 和三类 typed Request/Result records。
|
||||
- 新增三个独立契约测试,覆盖精确 JSON、状态分离、框架 ID 原样保留、不可变集合、Mock provenance 和基础设施字段排除。
|
||||
- 首模块对齐:共享/RAG/日志/MySQL contract 与 design/tasks 全部完成;旧 runtime 接入保持 TODO,归属后续 3B/3C/6B changes。
|
||||
|
||||
## Apply 验证
|
||||
|
||||
- 编译:`mvn -q -DskipTests compile` 通过。
|
||||
- 新契约:`mvn -q '-Dtest=RagToolContractTest,QueryLogsToolContractTest,MysqlToolContractTest' test` 通过。
|
||||
- 旧行为回归:`mvn -q '-Dtest=HarnessContractTest,LookupKnowledgeToolTest,QueryLogsToolsTest' test` 通过。
|
||||
- 静态 scope:新 contract 生产类型当前无旧运行消费者;受保护的 Tool、Chat/AIOps、Controller、Repository 和配置文件 diff 为空。
|
||||
@@ -1,27 +0,0 @@
|
||||
# Evidence: single-react-aci-tool-contracts
|
||||
|
||||
## 文档证据
|
||||
|
||||
- ISS-014 5.2/5.3 冻结 `evidence_status` 与框架 `tool_call_id`;6-9 节冻结 RAG、日志和 MySQL Agent-facing Schema。
|
||||
- ISS-014 阶段 1 明确只冻结 ACI Contract,不实现 Agent 架构切换、真实 CLS/MCP 或 MySQL 执行。
|
||||
- 阶段 0 OpenSpec 与 devflow 已冻结 `InvocationStatus`、`EvidenceStatus`、框架 ID 真理源和阶段 6B 才公开切换。
|
||||
|
||||
## 代码证据
|
||||
|
||||
- `LookupKnowledgeTool` 仍返回包含 ContextPack/Trace 的旧 `LookupResult`,证明需要新的 bounded RAG Contract,也证明本阶段未提前切换。
|
||||
- `QueryLogsTools` 仍暴露 region/logTopic/limit、Topic discovery 和旧 mutable DTO,证明逻辑 Topic/Scope/Mock provenance 契约的必要性。
|
||||
- `ChatService` 与 `AiOpsService` 仍引用旧 `LookupKnowledgeTool`/`QueryLogsTools`,新 contract 生产包当前没有旧运行消费者。
|
||||
- 本地 Spring AI 1.1.7 `AssistantMessage.ToolCall` 提供 `id()`;Spring AI Alibaba 1.1.2.0 `ToolCallRequest` 提供 `getToolCallId()` 与 `ToolInterceptor` 边界。
|
||||
- Spring AI 1.1.7 普通 `ToolContext` 只传递调用方 context/history,不自动提供当前 Tool Call ID,因此后续必须从 Alibaba interceptor request 接入。
|
||||
|
||||
## Evidence-driven 结论
|
||||
|
||||
- lifecycle 与 evidence result 必须保持两套正交状态;已汇报并进入 OpenSpec/代码测试。
|
||||
- `tool_call_id` 可以从当前框架 API 取得,Harness 无需也不得生成第二套 ID;已汇报并进入 OpenSpec。
|
||||
- 阶段 1 不改旧运行签名/返回;已通过引用和 diff scope 验证。
|
||||
- 日志首版保留 Mock 数据源但必须显式 `source_kind=MOCK`,不实现真实适配器;已进入 Log Contract。
|
||||
- 三类 Contract 的可验证口径是精确 JSON、不可变结果、短描述和基础设施字段排除;三个独立测试均通过。
|
||||
|
||||
## 工具限制
|
||||
|
||||
- 当前会话未提供 `codebase-retrieval` 或 LSP;使用 `rg` 引用搜索、源码阅读、本地依赖 `javap`、Maven 编译和 focused tests 完成等价核对。
|
||||
@@ -1,42 +0,0 @@
|
||||
# Acceptance: single-react-chat-application-usecase
|
||||
|
||||
## Result
|
||||
|
||||
- Status: archived
|
||||
- OpenSpec tasks: 14/14 complete
|
||||
- Interface impact: L3 database/collaboration
|
||||
- Public protocol: unchanged
|
||||
|
||||
## Static Verification
|
||||
|
||||
- V012 migration、`DiagnosisRun` 和 `DiagnosisRunRepository` 对齐 `intent/release_outcome/published_result` 及安全 PreviousTurn filter。
|
||||
- 公开 Controller、前端和 endpoint diff 为空。
|
||||
- Router/System executor 未检出 Tool、ReactAgent、ThreadLocal 或手写循环。
|
||||
- `PublishedResult` 固定为 `user_query/published_conclusion/scope/limitations/source_documents`;序列化负向测试覆盖内部字段泄漏。
|
||||
|
||||
## Script Verification
|
||||
|
||||
- `mvn -q -DskipTests compile`:通过。
|
||||
- Stage 6A focused `ApplicationExecutorsTest,PublishedResultPersistenceTest,ChatApplicationUseCaseTest`:13 tests,通过。
|
||||
- Stage 2-5 与 6A regression selection:18 suites / 76 tests,0 failure/error/skipped。
|
||||
- `openspec validate single-react-chat-application-usecase --strict`:通过。
|
||||
|
||||
## Browser or Manual Verification
|
||||
|
||||
- Not applicable。阶段 6A 没有 UI 或公开入口变化。
|
||||
|
||||
## Not Verified
|
||||
|
||||
- 未运行真实 LLM、Redis、日志和 MySQL live E2E;按 ISS-014 串行门禁统一留到阶段 7。
|
||||
- V012 未在本阶段连接真实数据库执行;migration/entity/query 已由静态检查、focused persistence tests 和 compile 覆盖。
|
||||
|
||||
## Remaining Work
|
||||
|
||||
- 阶段 6B:唯一 `POST /api/chat` SSE 原子切换、旧 endpoint 删除和前端消费者迁移。
|
||||
- 阶段 7:旧链路清理、全局 spec 格式修复和最终 live E2E。
|
||||
|
||||
## Archive
|
||||
|
||||
- `.archive-ready`: created
|
||||
- OpenSpec archive: `openspec/changes/archive/2026-07-21-single-react-chat-application-usecase`
|
||||
- Main spec sync: `openspec/specs/single-react-chat-application-usecase/spec.md`
|
||||
@@ -1,31 +0,0 @@
|
||||
# Brief: single-react-chat-application-usecase
|
||||
|
||||
## Background
|
||||
|
||||
阶段 2-5 已具备 RunContext、单一 Diagnosis Agent 和安全释放门禁,但没有统一应用用例拥有 Session/Run、意图路由、PreviousTurn、固定执行器和最终持久化,阶段 6B 因而无法只做协议切换。
|
||||
|
||||
## Goal
|
||||
|
||||
在不改变公开 Chat/SSE 行为的前提下,建立内部 `ChatApplicationUseCase`,统一三类意图、同一 Run 生命周期、安全 PreviousTurn 和 typed public content。
|
||||
|
||||
## Scope
|
||||
|
||||
- 无 Tool、无记忆、无 ReAct 的三分类 Intent Router。
|
||||
- SYSTEM_CHAT、KNOWLEDGE_QUERY、DIAGNOSIS 固定执行器。
|
||||
- Knowledge exact invocation/document reference validation。
|
||||
- 同 Session 最近安全 Diagnosis SUCCESS 的有界 PreviousTurn。
|
||||
- `diagnosis_run` V012 字段、JPA store 和安全 `PublishedResult`。
|
||||
- Protocol-neutral observer、Run control、终态持久化和 focused tests。
|
||||
|
||||
## Non-goals
|
||||
|
||||
- 不修改 Controller、`/api/chat`、`/api/chat_stream`、SSE schema 或前端消费者。
|
||||
- 不删除旧 ChatService、多 Agent、ThreadLocal 或旧 session storage。
|
||||
- 不运行真实模型、Redis、日志和 MySQL live E2E;统一留到阶段 7。
|
||||
|
||||
## Metadata
|
||||
|
||||
- Scale: complex
|
||||
- Interface impact: L3 database/collaboration
|
||||
- OpenSpec: `single-react-chat-application-usecase`
|
||||
- Parent issue: `ISS-014`
|
||||
@@ -1,117 +0,0 @@
|
||||
# Decisions: single-react-chat-application-usecase
|
||||
|
||||
## Discover Status
|
||||
|
||||
- Checkpoint: Discover
|
||||
- Capability source: `sm-flow` + `grill-with-docs`;`codebase-retrieval`、LSP 和 GitNexus MCP 当前不可用,使用既有 GitNexus 结论、`rg` 引用核对和源码阅读降级。
|
||||
- Scale: complex。跨模型路由、三类执行器、Run/session 生命周期、数据库 migration、PreviousTurn 和阶段 6B consumer boundary。
|
||||
- `devflow/index.md` 命中阶段 0-5、session-run-trace-isolation、RAG contracts 和 release guards;无 ADR 冲突。
|
||||
|
||||
## Question Pool
|
||||
|
||||
| # | 维度 | 问题 | 模式 | 状态 |
|
||||
|---|---|---|---|---|
|
||||
| Q1 | 术语 | Chat Application Use Case 与 Controller、Harness、Agent 的职责边界是什么? | evidence-driven | 已解决 |
|
||||
| Q2 | 路由 | Router 输入、输出和可重试失败范围是什么? | evidence-driven | 已解决 |
|
||||
| Q3 | 路由 | Router 最终失败是否允许默认进入 Diagnosis? | evidence-driven | 已解决 |
|
||||
| Q4 | 执行器 | 三种 intent 分别允许哪些模型和 Tool 行为? | evidence-driven | 已解决 |
|
||||
| Q5 | Knowledge | 单次 RAG 调用如何验证模型引用且不公开 Tool Call ID? | evidence-driven | 已解决 |
|
||||
| Q6 | PreviousTurn | 上一回合的真理源、筛选条件和截断边界是什么? | evidence-driven | 已解决 |
|
||||
| Q7 | 生命周期 | 何时读取上一回合、创建当前 Run、记录 intent 和终态? | evidence-driven | 已解决 |
|
||||
| Q8 | 持久化 | diagnosis_run 需要新增哪些字段,哪些内部内容禁止进入 published_result? | evidence-driven | 已解决 |
|
||||
| Q9 | 6B 边界 | 如何让 Controller 切换时不重写应用用例? | evidence-driven | 已解决 |
|
||||
| Q10 | 接口 | 数据库/内部接口影响等级和回滚要求是什么? | evidence-driven | 已解决 |
|
||||
| Q11 | 验收 | 如何证明原始 Query、sessionId/runId 和失败终态一致传播? | evidence-driven | 已解决 |
|
||||
|
||||
## Evidence-driven
|
||||
|
||||
| 结论 | 证据来源 | 是否已汇报用户 |
|
||||
|---|---|---|
|
||||
| Controller 只负责协议;Application Use Case 拥有 session/run、routing、executor、persistence,Harness 拥有预算/取消/释放,Agent 拥有诊断语义。 | ISS-014 3、4.2、阶段 6A/6B | 已汇报 |
|
||||
| Router 输入只含 query/last_intent/last_user_query,输出只允许三枚举;无 Tool/记忆/ReAct。 | ISS-014 4.5 | 已汇报 |
|
||||
| timeout/transport/非法输出可重试一次;第二次失败返回安全入口错误,不进入 Diagnosis。 | ISS-014 重试策略、`HarnessRetryPolicies.intentRouter()` | 已汇报 |
|
||||
| SYSTEM_CHAT 无 Tool;KNOWLEDGE_QUERY 只调用一次 lookup;DIAGNOSIS 进入 Agent + Guards。 | ISS-014 4.5 | 已汇报 |
|
||||
| PreviousTurn 只来自同 Session 最近 `DIAGNOSIS + SUCCESS + published_result`,不使用 Redis 历史。 | ISS-014 4.6 | 已汇报 |
|
||||
| `PublishedResult`/`PreviousTurn` 已冻结为 query/conclusion/scope/limitations/source_documents,不含 Tool ID/raw/Draft/reason。 | 阶段 0 contracts、`PublishedResult`、`PreviousTurn` | 已汇报 |
|
||||
| 当前 `DiagnosisRun`/V011 尚无 intent/release_outcome/published_result,需要 V012 和 repository query。 | `DiagnosisRun.java`、`V011__add_session_run_isolation.sql` | 已汇报 |
|
||||
| 上一回合必须在保存当前 PENDING Run 前读取,否则 latest query 会命中当前请求。 | repository 当前 latest method + 生命周期顺序推导 | 已汇报 |
|
||||
| 6B 需要 metadata/status/cancel,6A 应提供 observer 和显式 RunContext,而不包含 SSE 类型。 | ISS-014 4.7、阶段 6B | 已汇报 |
|
||||
|
||||
## User-interview
|
||||
|
||||
- 无新增 user-interview。三类路由、数据库字段、PreviousTurn、失败语义、阶段边界和自动 Apply/Archive/commit 均由 ISS-014 与用户持续授权冻结。
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- 在创建当前 Run 前读取 latest safe routing context 和 PreviousTurn,随后 `startRun -> persist RUNNING -> observer metadata -> route`。
|
||||
- Application output 使用 typed content union,Diagnosis success 转为无 Tool ID 的 public report view;Fallback output 不携带完整 snapshot。
|
||||
- Knowledge path 生成一次 direct canonical Tool Call ID(该路径没有框架 Tool Call),只调用 `lookup_knowledge`,严格验证 `KnowledgeAnswerDraft` 的 exact call ID 和 document subset,再移除 ID 发布。
|
||||
- 所有普通单轮模型调用复用阶段 5 的受控 `GuardModelCall`,从而共享 Core 模型/Token/timeout/cancel 边界;不引入新模型路由。
|
||||
- `PublishedResult` 仅在 Diagnosis SUCCESS 且 conclusion 非空时写入;Fallback/Failed/Cancelled/System/Knowledge 不生成 PreviousTurn 真理源。
|
||||
- 数据库变更使用 V012 可前向迁移;回滚为先停止新应用用例,再删除新索引/列,不影响 V011 既有字段。
|
||||
- 不创建 ADR:这些是 ISS-014 已冻结设计的落地,不是新的跨项目不可逆决策。
|
||||
|
||||
## OpenSpec Backfill
|
||||
|
||||
- 需进入 proposal/design/spec/tasks:路由隔离/重试、三执行器、original query、PreviousTurn filter/bounds、observer/cancel、Run terminal persistence、V012/L3、公开隔离。
|
||||
- 非目标:Controller/SSE/前端切换、旧链路删除、live E2E。
|
||||
|
||||
## Cross-artifact Alignment
|
||||
|
||||
| 上游 -> 下游 | 检查内容 | 状态 |
|
||||
|---|---|---|
|
||||
| ISS-014/brief -> proposal | 三路由、previous turn、Run lifecycle、内部-only 和阶段 6B handoff | 已对齐 |
|
||||
| proposal -> design | typed executors、observer、JPA/V012、异常/终态、L3 migration/rollback | 已对齐 |
|
||||
| design -> specs/tasks | 每项所有权/安全边界均有可观察 requirement 和实现测试切片 | 已对齐 |
|
||||
| specs -> tasks | 9 组 requirements 覆盖 Router/executors、store/policy、application、verification | 已对齐 |
|
||||
|
||||
## Architecture Audit
|
||||
|
||||
- 能力来源:`zoom-out`,使用 Chat Session、Diagnosis Run、RunContext、Diagnosis Agent、EvidenceGuard、SemanticGuard 和 PublishedResult 术语。
|
||||
- 链路为 `request -> application use case -> run store/router -> fixed executor -> Harness/Agent/Tool -> typed public content -> run finish`;Controller 不拥有模型/工具/Run。
|
||||
- ChatRunStore 拥有 MySQL 映射,Core 拥有运行状态,Application 拥有 dispatch/终态,path executor 拥有单一路径行为;PreviousTurn policy 是唯一安全历史投影。
|
||||
- 最大风险是 prior/current Run 顺序和 DB/lifecycle 双终态,design/tasks 已固定 prior read before start、single finish path 和 focused failure/cancel tests。
|
||||
- V012 是 L3 additive schema;migration、entity、repository、rollback 独立章节完整,公开入口阶段 6A 零变化。
|
||||
|
||||
## Interface Impact
|
||||
|
||||
- 级别:L3 database/collaboration interface。
|
||||
- 新增 `diagnosis_run.intent/release_outcome/published_result` 和索引;修改 Entity/Repository,新增 internal application/store/output contract。
|
||||
- 消费者:阶段 6B Controller/SSE adapter、MySQL/Flyway;旧 ChatService 在本阶段不消费新字段。
|
||||
- 迁移/回滚:V012 nullable additive;回滚先切旧入口,再删除 index/columns。
|
||||
|
||||
## Commit Gate Preflight
|
||||
|
||||
- proposal、design、specs、tasks 完整,`openspec status` complete,change strict validation 通过。
|
||||
- Question pool 全部已解决并汇报,无 user-interview、未判级接口或未接受架构风险。
|
||||
- Cross-artifact 四段对齐无 gap;V012/L3、prior read ordering、terminal persistence 和 6B handoff 已进入 design/spec/tasks。
|
||||
- Apply/Archive/commit 使用用户持续授权;公开协议和前端必须保持零 diff。
|
||||
- `.committed` 已创建,可进入 Apply。
|
||||
|
||||
## Pre-apply Research
|
||||
|
||||
- `DiagnosisHarnessCore`/`RunContext`:Run ID、budget、cancel 和 first-terminal-wins。
|
||||
- `GuardModelCall`/`HarnessRetryExecutor`:单轮模型 timeout/usage 和 Router 两次 attempt。
|
||||
- `HarnessEvidenceTools`/`RagToolResult`:Knowledge 唯一 lookup 路径和有界 projection。
|
||||
- `DiagnosisAgentUseCase`/`DiagnosisReleaseUseCase`:Diagnosis Draft 与安全 release boundary。
|
||||
- `DiagnosisRun`/`DiagnosisRunRepository`/`V011`:现有 Run schema 和写入模式。
|
||||
- `ChatService.ensureChatSession/startDiagnosisRun`:只参考 session metadata/JPA 写法,不复用旧 routing、多 Agent 或 ThreadLocal。
|
||||
- 技术栈:Spring AI direct Prompt、Jackson strict JSON、JPA repository、Flyway additive migration、protocol-neutral observer;无 MQ/新依赖。
|
||||
|
||||
## Apply Progress
|
||||
|
||||
- Router/System/Knowledge contracts 与 executors 已完成,tasks 1.1-1.4 完成。
|
||||
- 5 个 `ApplicationExecutorsTest` 通过:同输入 retry、最终 routing failure、System direct call、Knowledge exact references/no ID、NO_EVIDENCE/model skip。
|
||||
- TODO:PublishedResult/JPA/V012、Diagnosis executor、总应用用例和综合验证。
|
||||
- REVIEW:修正 `JpaChatRunStore` 多构造器 Spring 注入歧义;prior/start/intent/finish 持久化异常统一为稳定 `RUN_PERSISTENCE_FAILED`,并在安全完成时更新 ChatSession 活跃时间/消息对数。均为代码偏离修复,无需变更 OpenSpec。
|
||||
- PublishedResult/JPA/V012、Diagnosis executor、protocol-neutral Run control 与总 ChatApplicationUseCase 已完成,tasks 2.1-3.4 完成。
|
||||
- 13 个 stage 6A focused tests 通过;TODO 仅剩综合回归、static scope 和 OpenSpec verification。
|
||||
- 综合回归曾在 `SemanticGuardTest.attemptTimeoutCancelsBothPermittedModelCalls` 出现负载相关失败。诊断确认生产代码对每次 timeout 均调用 `Future.cancel(true)`,但第二个 Future 可能在任务线程启动前已取消,此时不存在可接收 interrupt 的线程。分类为测试假设偏差,不是 OpenSpec 或生产代码偏离;回归断言改为两次 TIMEOUT attempt、两次模型预算预留,以及至少一个已运行调用收到 interrupt。
|
||||
|
||||
## Final Review
|
||||
|
||||
- Stage 6A focused tests 与阶段 2-5 regression 共 18 suites / 76 tests,0 failure/error/skipped;Maven compile 通过。
|
||||
- OpenSpec strict validation 通过;V012、Entity、Repository 的三个字段和 previous-turn filter 对齐。
|
||||
- 公开 Controller、前端和 endpoint 零 diff;Router/System executor 无 Tool、ReactAgent、ThreadLocal 或手写 loop。
|
||||
- `PublishedResult` 只包含 `user_query/published_conclusion/scope/limitations/source_documents`,负向序列化测试通过。
|
||||
- 本阶段不运行 live E2E,按 ISS-014 门禁留到阶段 7。
|
||||
@@ -1,31 +0,0 @@
|
||||
# Evidence: single-react-chat-application-usecase
|
||||
|
||||
## Code and Contract Evidence
|
||||
|
||||
- `DiagnosisHarnessCore`/`RunContext` 已提供 Run ID、预算、取消和 first-terminal-wins,应用用例无需创建第二套生命周期。
|
||||
- `GuardModelCall`/`HarnessRetryExecutor` 提供单轮模型 timeout、Token 记账和两次 Router attempt。
|
||||
- `HarnessEvidenceTools`/`RagToolResult` 提供 Knowledge 路径唯一 lookup 和有界 projection。
|
||||
- `DiagnosisAgentUseCase`/`DiagnosisReleaseUseCase` 已形成 Diagnosis Draft 与安全发布边界。
|
||||
- `DiagnosisRun`/`DiagnosisRunRepository`/V011 提供既有 Run 持久化,V012 以 nullable additive 字段扩展。
|
||||
|
||||
## Confirmed Boundaries
|
||||
|
||||
- Router 输入只含原始 Query、可选 last intent 和 last user query;最终失败不得默认进入 Diagnosis。
|
||||
- 三类 executor 不互相调用,所有路径接收未改写 Query。
|
||||
- PreviousTurn 只来自同 Session 最近 `DIAGNOSIS + SUCCESS + published_result`,且必须在保存当前 Run 前读取。
|
||||
- Knowledge 公开内容只保留 stable document metadata,不发布 direct Tool Call ID。
|
||||
- `PublishedResult` 不保存 Tool ID、raw evidence、完整 Draft 或 SemanticGuard reason;Fallback/Failed/Cancelled 不写安全历史。
|
||||
- Controller/SSE/前端切换属于阶段 6B,本阶段保持公开协议不变。
|
||||
|
||||
## Diagnosis Finding
|
||||
|
||||
- 综合回归暴露 `SemanticGuardTest` 的负载竞态:第二个 Future 可能在获得线程前被取消,因而不会产生第二次 interrupt。
|
||||
- 生产代码已对每次 timeout 调用 `Future.cancel(true)`;测试改为验证两次 TIMEOUT attempt、两次模型预算预留,以及至少一个运行中调用被中断。
|
||||
- 分类为测试假设偏差,不是生产代码或 OpenSpec 偏离。
|
||||
|
||||
## Verification Evidence
|
||||
|
||||
- Stage 6A focused tests:13 tests 通过。
|
||||
- Stage 2-5 与 6A 综合回归:18 suites / 76 tests,0 failure/error/skipped。
|
||||
- Maven compile 与 change strict validation 通过。
|
||||
- 公开 Controller/前端零 diff;Router/System executor 无 Tool、ReactAgent、ThreadLocal 或手写 loop。
|
||||
@@ -1,49 +0,0 @@
|
||||
# Acceptance: single-react-chat-sse-cutover
|
||||
|
||||
## Result
|
||||
|
||||
- Status: archived
|
||||
- OpenSpec tasks: 14/14 complete
|
||||
- Interface impact: L4 breaking HTTP/frontend contract
|
||||
- Public Chat protocol: unique named-event SSE `POST /api/chat`
|
||||
|
||||
## Static Verification
|
||||
|
||||
- 组合路由保持 `/api/chat`、`/api/ai_ops`、`/api/chat/clear`、`/api/chat/session/{sessionId}` 和 `/runs`;`/api/chat_stream` 已删除。
|
||||
- 生产 Controller/前端 legacy Chat token scan:0。
|
||||
- `ChatController` forbidden dependency scan:0;结构测试固定其三个 protocol/application dependencies。
|
||||
- SSE payload 只包含固定 metadata/status/content/failure/done fields,`CANCELLED` 不作为公开 done outcome。
|
||||
- mode selector DOM、state、consumer 和 CSS 已删除。
|
||||
|
||||
## Script Verification
|
||||
|
||||
- `mvn -q -DskipTests compile`:通过。
|
||||
- Stage 2-6B + AiOps regression selection:24 suites / 101 tests,0 failure/error/skipped。
|
||||
- `openspec validate single-react-chat-sse-cutover --strict`:通过。
|
||||
- `node --check src/main/resources/static/app.js`:通过。
|
||||
- `git diff --check`:通过,仅有仓库既存 LF/CRLF 提示。
|
||||
|
||||
## Browser or Manual Verification
|
||||
|
||||
- 本阶段未运行浏览器人工验证;前端协议由静态 contract test 和 JavaScript syntax check 覆盖。
|
||||
|
||||
## Not Verified
|
||||
|
||||
- 未运行 live 模型、Redis、日志和 MySQL E2E;按 ISS-014 阶段门禁统一留到阶段 7。
|
||||
- 未验证外部第三方 Chat API consumer;L4 变更不提供兼容分支,外部消费者必须同步迁移到 named-event SSE。
|
||||
|
||||
## Migration and Rollback
|
||||
|
||||
- 部署必须将后端 SSE endpoint 与 bundled frontend consumer 作为同一版本原子发布。
|
||||
- 回滚必须同时回滚 Controller 和 frontend 到阶段 6A commit;V012 additive nullable migration 可保留。
|
||||
- 不允许通过恢复 `/api/chat_stream`、同步 JSON consumer 或旧 message wrapper 形成双轨兼容。
|
||||
|
||||
## Remaining Work
|
||||
|
||||
- 阶段 7:物理删除旧 Agent/Graph/Hook/ThreadLocal/ChatService 路径和过时测试,更新文档并完成最终 live E2E、日志与数据库核验。
|
||||
|
||||
## Archive
|
||||
|
||||
- `.archive-ready`: created
|
||||
- OpenSpec archive: `openspec/changes/archive/2026-07-22-single-react-chat-sse-cutover`
|
||||
- Main spec sync: `openspec/specs/single-react-chat-sse-cutover/spec.md` (10 requirements added)
|
||||
@@ -1,32 +0,0 @@
|
||||
# Brief: single-react-chat-sse-cutover
|
||||
|
||||
## Background
|
||||
|
||||
阶段 6A 已建立 protocol-neutral `ChatApplicationUseCase`,但公开 Chat 仍有同步 `/api/chat` 和伪流式 `/api/chat_stream` 两条旧链路,Controller 直接拥有模型、Tools、Session 历史和无界线程池,前端也保留两套消费者。
|
||||
|
||||
## Goal
|
||||
|
||||
将公开 Chat 原子切换为唯一 `POST /api/chat` named-event SSE,并让 Controller 只承担校验、HTTP/SSE 和连接生命周期;所有公开内容必须来自阶段 6A 的安全释放结果。
|
||||
|
||||
## Scope
|
||||
|
||||
- 唯一 `/api/chat` SSE 与 `metadata -> status* -> content|failure -> done` 状态机。
|
||||
- exact Run disconnect/timeout/send-failure cancellation。
|
||||
- Spring-managed bounded Chat/model executors 和完整 Harness production Bean graph。
|
||||
- 前端唯一 named-event consumer、typed renderer 和 metadata identity 保存。
|
||||
- AiOps 模型/Tool acquisition 下沉到 service,并将 AiOps/Session endpoint 从 Chat Controller 职责中隔离。
|
||||
- L4 前后端迁移、成对回滚和 focused regression。
|
||||
|
||||
## Non-goals
|
||||
|
||||
- 不做 Token streaming、最终答案切片、断线续传、事件重放、轮询或 WebSocket。
|
||||
- 不修改 `/api/ai_ops` 的公开 URL、请求和 SSE message-wrapper 行为。
|
||||
- 不在本阶段物理删除旧多 Agent、ChatService、Hook 或 ThreadLocal;阶段 7 统一清理。
|
||||
- 不运行 live 模型、Redis、日志或 MySQL E2E;阶段 7 统一验收。
|
||||
|
||||
## Metadata
|
||||
|
||||
- Scale: complex
|
||||
- Interface impact: L4 breaking HTTP/frontend contract
|
||||
- OpenSpec: `single-react-chat-sse-cutover`
|
||||
- Parent issue: `ISS-014`
|
||||
@@ -1,110 +0,0 @@
|
||||
# Decisions: single-react-chat-sse-cutover
|
||||
|
||||
## Discover Status
|
||||
|
||||
- Checkpoint: Discover
|
||||
- Capability source: `sm-flow` + `grill-with-docs`;`codebase-retrieval`、LSP 和 GitNexus MCP 当前不可用,使用 `rg` 引用核对、源码阅读和 focused tests 降级。
|
||||
- Scale: complex。涉及 L4 HTTP/SSE 协议、前端消费者、异步连接生命周期、生产 Bean 装配和阶段 7 删除边界。
|
||||
- `devflow/index.md` 命中阶段 0-6A、ISS-013 和 session-run-trace-isolation;ISS-014 是更新且已冻结的最终协议源。
|
||||
|
||||
## Question Pool
|
||||
|
||||
| # | 维度 | 问题 | 模式 | 状态 |
|
||||
|---|---|---|---|---|
|
||||
| Q1 | 术语 | “真正 SSE”是 Token streaming,还是过程事件实时 + 最终内容一次释放? | evidence-driven | 已解决 |
|
||||
| Q2 | 协议 | 唯一 endpoint、事件名称、payload、顺序、互斥和终态是什么? | evidence-driven | 已解决 |
|
||||
| Q3 | 边界 | Controller、Application Use Case、Harness 和 SSE adapter 各自拥有何种职责? | evidence-driven | 已解决 |
|
||||
| Q4 | 生命周期 | disconnect/timeout/send failure 如何取消同一个 Run,正常 complete 如何避免误取消? | evidence-driven | 已解决 |
|
||||
| Q5 | 执行器 | 如何消除 Controller 自建无界线程池并处理饱和? | evidence-driven | 已解决 |
|
||||
| Q6 | 装配 | 阶段 2-6A plain Java components 如何形成可启动的生产 Bean graph? | evidence-driven | 已解决 |
|
||||
| Q7 | 前端 | 快速/流式双模式如何迁移到唯一 SSE consumer? | evidence-driven | 已解决 |
|
||||
| Q8 | 安全 | 哪些内部状态/内容禁止进入 SSE? | evidence-driven | 已解决 |
|
||||
| Q9 | 兼容 | 是否保留同步 `/api/chat` 或 `/api/chat_stream` 兼容? | evidence-driven | 已解决 |
|
||||
| Q10 | 范围 | `/api/ai_ops` 和旧多 Agent 何时处理? | evidence-driven | 已解决 |
|
||||
| Q11 | 验收 | 如何证明 event order、single terminal、same IDs、cancel 和 production wiring? | evidence-driven | 已解决 |
|
||||
|
||||
## Evidence-driven
|
||||
|
||||
| 结论 | 证据来源 | 是否已汇报用户 |
|
||||
|---|---|---|
|
||||
| 真正 SSE 固定为状态实时发送、最终 typed content 一次释放,不做 Token/字符切片。 | ISS-014 4.7 | 已汇报 |
|
||||
| 唯一入口是 `POST /api/chat`;顺序为 `metadata -> status* -> content|failure -> done`。 | ISS-014 4.7、阶段 6B | 已汇报 |
|
||||
| metadata/status/content/failure/done 使用 named SSE event;payload 不再包含旧 `type/data` 包装。 | ISS-014 最小事件结构 | 已汇报 |
|
||||
| 当前 Controller 同时拥有旧 ChatService、模型、Tools、SessionManager、同步/伪流式流程和 cached thread pool。 | `ChatController.java` | 已汇报 |
|
||||
| 当前前端 quick 调 `/chat` JSON,stream 调 `/chat_stream` 并保留大量旧格式 fallback。 | `static/app.js` | 已汇报 |
|
||||
| `ChatApplicationUseCase` 已提供 observer、同一 run control、typed content 和 stable failure code,但组件尚无完整生产 Bean graph。 | 阶段 6A code + Spring annotation scan | 已汇报 |
|
||||
| 客户端断开必须通过 observer 得到的 `ChatRunControl` 取消,同一引用需覆盖断开早于 onStarted 的竞态。 | 阶段 6A design + `SseEmitter` lifecycle | 已汇报 |
|
||||
| `/api/ai_ops` 是独立公开入口,不属于阶段 6B Chat 原子切换;旧实现阶段 7 清理/处置。 | ISS-014 阶段 6B/7 | 已汇报 |
|
||||
|
||||
## User-interview
|
||||
|
||||
- 无新增 user-interview。唯一 endpoint、破坏性迁移、事件 schema、非 Token 流、自动 Apply/Archive/commit 均由 ISS-014 与用户持续授权冻结。
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- Controller 使用构造注入的 `ChatApplicationUseCase` 与受控 `TaskExecutor`;不注入 ChatModel、Tools、ChatService 或 SessionManager 来处理 Chat。
|
||||
- SSE adapter 为每个请求维护单一 state machine 和 `AtomicReference<ChatRunControl>`;disconnect 标记先于 onStarted 时,onStarted 立即取消。
|
||||
- 正常 result 只产生一次 typed content 和 done;异常只产生 failure 和 done;IOException/timeout/disconnect 只取消,不尝试补发终态。
|
||||
- executor rejection 在没有 Run 时发送稳定 failure/done;worker 启动后所有 failure code 来自 `ChatApplicationException`,不暴露 cause。
|
||||
- 生产装配使用集中 `harness.chat` properties 和 Spring-managed bounded executors;所有模型调用复用同一 `ChatModel` 和 `GuardModelCall`。
|
||||
- 前端移除 mode selector 和 quick path,只保留一个严格 named-event parser;unknown event/schema fail closed。
|
||||
- 不创建 ADR:L4 方案已经在 ISS-014 设计冻结,本 change 负责原子落地和迁移说明。
|
||||
|
||||
## OpenSpec Backfill
|
||||
|
||||
- 需进入 proposal/design/spec/tasks:唯一 SSE、五事件 state machine、typed payload、安全 failure、same IDs、disconnect cancellation、bounded executors、production assembly、frontend migration、L4 rollback。
|
||||
- 非目标:AiOps 协议、旧类物理删除、live E2E。
|
||||
|
||||
## Cross-artifact Alignment
|
||||
|
||||
| 上游 -> 下游 | 检查内容 | 状态 |
|
||||
|---|---|---|
|
||||
| ISS-014/brief -> proposal | 唯一 SSE、五事件、断开取消、前端迁移、生产装配、阶段 7 边界 | 已对齐 |
|
||||
| proposal -> design | named events、state machine、bounded executors、Bean graph、AiOps 隔离、L4 rollback | 已对齐 |
|
||||
| design -> specs/tasks | 每项 ownership/lifecycle/safety/migration 均有可观察 requirement 和纵向切片 | 已对齐 |
|
||||
| specs -> tasks | 10 组 requirements 覆盖 wiring、SSE、cancel、frontend、AiOps regression 和 verification | 已对齐 |
|
||||
|
||||
## Architecture Audit
|
||||
|
||||
- Capability source: `zoom-out`,使用 Chat Application Use Case、RunContext、Run Lifecycle、Diagnosis Harness 和 Chat SSE Contract 术语。
|
||||
- 链路为 `browser -> Controller -> SSE session -> bounded worker -> Application Use Case -> Harness -> typed release -> SSE session`;业务真理源不进入 Controller。
|
||||
- SSE session 独占协议状态,Application 独占 Run/dispatch/persistence,Core 独占 cancel/budget,configuration 独占 infrastructure graph。
|
||||
- 最大风险是 disconnect/onStarted 与 terminal callback 竞态,design/tasks 已固定 pending-disconnect、atomic terminal 和 no-send-after-close tests。
|
||||
- L4 部署必须 Controller/frontend 同版本;回滚成对返回阶段 6A commit,V012 可保留。
|
||||
|
||||
## Interface Impact
|
||||
|
||||
- Level: L4 breaking HTTP/frontend contract。
|
||||
- 删除同步 JSON `POST /api/chat`、`POST /api/chat_stream` 和旧 Chat SSE wrapper;新增 named-event SSE `POST /api/chat`。
|
||||
- 消费者:bundled `static/app.js`、外部 Chat callers、Controller/MockMvc tests;Trace/feedback 继续使用 metadata IDs。
|
||||
- 迁移/回滚:前后端同 commit 原子部署/回滚;不提供兼容开关、双 endpoint 或旧 parser。
|
||||
|
||||
## Commit Gate Preflight
|
||||
|
||||
- proposal、design、specs、tasks 完整,change strict validation 通过。
|
||||
- Question pool 全部 evidence-driven 解决并已汇报,无 user-interview、未判级接口或未接受架构风险。
|
||||
- Cross-artifact 四段对齐无 gap;L4 migration/rollback、production wiring、disconnect race 和阶段 7 边界均进入 design/spec/tasks。
|
||||
- `openspec-propose` 补全产物,`zoom-out` 完成架构审计;可提交为 Committed OpenSpec。
|
||||
|
||||
## Apply Progress
|
||||
|
||||
- 1.1-1.4 完成:新增 `ChatHarnessProperties`、bounded worker/model executors 和显式 `HarnessChatConfiguration` graph;空 MySQL datasource 只允许 fail-closed unknown logical ID。
|
||||
- 2.1-2.4 完成:新增 named-event `ChatSseEvent`/`ChatSseSession`,Chat 唯一 SSE Controller,移除 `/chat_stream` 和同步 Chat;AiOps 模型/Tool 依赖下沉到 service。
|
||||
- 3.1-3.3 完成:前端移除 quick/stream 双轨,统一 named-event parser、typed renderer 和静态 contract test。
|
||||
- `JpaChatRunStore` 生产构造器改为注入集中 `PublishedResultPolicy`,避免读写边界漂移;这是实现偏差修复,无需改需求方向。
|
||||
|
||||
## Apply Review
|
||||
|
||||
- Review 发现 `ChatController` 虽然 Chat path 已经只调用应用用例,但类本身仍承载 AiOps 和 Session 管理依赖,不完全满足“Chat Controller 只负责 Chat 协议”的 ownership 要求。
|
||||
- 用户确认将职责拆分为 `ChatController`(仅 `/api/chat`)、`AiOpsController`(保持 `/api/ai_ops`)和 `ChatSessionController`(保持 clear/session/runs URL)。
|
||||
- 该修正保持所有公开 URL、AiOps message-wrapper payload 和 Session observable behavior,不修改 Committed OpenSpec 的范围或方向。
|
||||
- `styles.css` 中 mode selector/dropdown 死样式随前端双轨删除一并移除。
|
||||
- AGENTS.md 指定的 `codebase-retrieval` 和 LSP 工具在当前环境不可用;使用 OpenSpec 全量上下文、`rg` 引用检查、Java 编译、结构测试和综合回归完成等价影响面确认。
|
||||
|
||||
## Verification and Migration
|
||||
|
||||
- Stage 2-6B + AiOps regression:24 suites / 101 tests,0 failure/error/skipped;包含 `HarnessChatConfigurationTest` Spring wiring。
|
||||
- `mvn -q -DskipTests compile`、`openspec validate single-react-chat-sse-cutover --strict`、`node --check src/main/resources/static/app.js` 均通过。
|
||||
- 生产 Controller/前端遗留 token 静态扫描为 0;`ChatController` 中模型、Tool、ChatService、AiOps、Session 和 Trace service 禁止依赖扫描为 0。
|
||||
- L4 部署必须将后端 `/api/chat` SSE 与 bundled frontend consumer 同版本原子部署;回滚必须成对回滚到阶段 6A commit,不提供兼容 endpoint、旧 parser 或双轨开关。
|
||||
- live 模型、Redis、日志和 MySQL E2E 按 ISS-014 门禁明确延后到阶段 7,本阶段没有把 focused/Mock 验证表述为 live 验收。
|
||||
@@ -1,32 +0,0 @@
|
||||
# Evidence: single-react-chat-sse-cutover
|
||||
|
||||
## Code and Contract Evidence
|
||||
|
||||
- `ChatApplicationUseCase` 已提供 typed result、observer 和 exact `ChatRunControl`,Controller 无需拥有模型、Tool 或业务路由。
|
||||
- `ChatSseSession` 使用 first-terminal-wins 状态和 pending disconnect,覆盖断开早于 `onStarted`、send failure、late terminal 与正常 completion 竞态。
|
||||
- `ChatSseEvent` 固定 metadata/status/content/failure/done payload;content 引用阶段 6A typed public content,failure 只公开 stable code/message。
|
||||
- `HarnessChatConfiguration` 组装同一个 Core、model boundary、canonical store、ToolBoundary、Diagnosis Agent、Guards、Router、executors 和 application use case。
|
||||
- `ChatHarnessProperties` 集中 worker/model queue、Run、SSE、canonical store、Agent、Router、Guard 和 single-turn limits;executors 使用有限队列与 `AbortPolicy`。
|
||||
- bundled frontend 只向 `/api/chat` 发起 streaming POST,按完整 named SSE frame 严格解析并 fail closed。
|
||||
|
||||
## Ownership Review
|
||||
|
||||
- Apply review 将原 Controller 拆为 `ChatController`、`AiOpsController` 和 `ChatSessionController`。
|
||||
- `ChatController` 只注入 `ChatApplicationUseCase`、bounded worker 和 Chat properties;禁止依赖扫描为 0。
|
||||
- `/api/ai_ops`、`/api/chat/clear`、session info 和 run list 的 URL 与 payload 字段保持不变。
|
||||
- mode selector/dropdown DOM、JS state 和 CSS 已全部移除,不保留双轨开关。
|
||||
|
||||
## Safety and Lifecycle Evidence
|
||||
|
||||
- success 测试验证 `metadata,status,content,done` 严格顺序和 typed content。
|
||||
- failure 测试验证内部 provider detail 不进入 failure payload,且 content/failure 互斥。
|
||||
- disconnect-before-start 与 send-failure 测试验证 exact Run 取消和 late terminal 阻断。
|
||||
- frontend contract test 验证唯一 request target、五类 event branch 与旧 consumer token 删除。
|
||||
- static scan:生产 Controller/前端 legacy Chat token 0;Chat Controller forbidden dependency 0。
|
||||
|
||||
## Verification Evidence
|
||||
|
||||
- Stage 2-6B + AiOps regression:24 suites / 101 tests,0 failure/error/skipped。
|
||||
- `HarnessChatConfigurationTest` 覆盖 bounded queues、共享依赖、空 MySQL fail-closed 和 Spring context wiring。
|
||||
- Maven compile、strict OpenSpec validation 和 JavaScript syntax check 通过。
|
||||
- 真实模型、Redis、日志和 MySQL live E2E 按 ISS-014 串行门禁留到阶段 7。
|
||||
@@ -1,36 +0,0 @@
|
||||
# Acceptance: single-react-design-freeze
|
||||
|
||||
## 实现结果
|
||||
|
||||
- 新增类型化 Harness contracts 和序列化契约测试。
|
||||
- ISS-014 已调整为 11 个串行 changes,并补齐 Tool ID、双状态、previous turn 和安全切换决策。
|
||||
- Python 查询脚本和 Spring 主配置改为环境变量 Secret。
|
||||
- 集成测试和历史 handoff 中的旧 Secret 副本已删除或脱敏。
|
||||
- devflow glossary 新增 Harness、EvidenceGuard、SemanticGuard、Invocation Status 和 Evidence Status。
|
||||
|
||||
## 静态验证
|
||||
|
||||
- OpenSpec strict validation:通过。
|
||||
- Secret 扫描:通过,已知真实 Secret 模式零匹配。
|
||||
- Diff whitespace 检查:通过。
|
||||
|
||||
## 脚本验证
|
||||
|
||||
- 4 个 contract tests:通过。
|
||||
- ToolInvocationRecorder、ExecutorGatekeeperService、ChatController focused baseline:通过。
|
||||
- 查询脚本缺失密码环境变量时 fail fast:通过。
|
||||
|
||||
## 浏览器/人工验证
|
||||
|
||||
- 不适用;阶段 0 未切换任何公开 UI/API。
|
||||
|
||||
## 未验证与后续门禁
|
||||
|
||||
- Provider 侧旧凭据轮换待凭据所有者完成。
|
||||
- Live E2E 留到阶段 7。
|
||||
- 阶段 1 只有在本 change Archive 和 Git commit 后才能开始。
|
||||
|
||||
## 状态
|
||||
|
||||
- Stage acceptance: accepted
|
||||
- OpenSpec archive: authorized by standing user instruction
|
||||
@@ -1,31 +0,0 @@
|
||||
# Brief: single-react-design-freeze
|
||||
|
||||
## 背景
|
||||
|
||||
ISS-014 将 Chat 诊断从多 Agent、Hook、ThreadLocal 和外层重试编排收敛为单体 Diagnosis ReAct Agent、确定性 Harness 和隔离 SemanticGuard。阶段 0 先冻结后续实施共同依赖的契约和安全边界。
|
||||
|
||||
## 目标
|
||||
|
||||
- 提供可复用的 Diagnosis Draft、Knowledge Answer、Fallback、published result 和 previous turn 类型。
|
||||
- 固定 framework Tool Call ID、调用生命周期和证据结果双状态。
|
||||
- 固定取消、重试、no-evidence、阶段门禁和安全凭据策略。
|
||||
- 保持当前公开 Chat 运行行为不变。
|
||||
|
||||
## 范围
|
||||
|
||||
- `com.superbiz.agent.harness.contract` 类型层和 focused tests。
|
||||
- ISS-014 的 11 个串行 OpenSpec changes 台账。
|
||||
- 主配置、查询脚本和集成测试中的明文 Secret 清理。
|
||||
- OpenSpec、devflow glossary 和阶段验收基线。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不接入新 Harness、Agent 或 Guards。
|
||||
- 不切换 `/api/chat`,不删除旧运行链。
|
||||
- 不执行 live E2E。
|
||||
|
||||
## 元数据
|
||||
|
||||
- Scale: complex
|
||||
- Parent issue: `ISS-014`
|
||||
- OpenSpec: `openspec/changes/single-react-design-freeze`
|
||||
@@ -1,20 +0,0 @@
|
||||
# Decisions: single-react-design-freeze
|
||||
|
||||
## 已确认决策
|
||||
|
||||
- ISS-014 保留为总 Issue,实施拆成 11 个独立、串行 sm-flow changes。
|
||||
- 每个 change 必须完成 Apply、阶段验收、OpenSpec Archive 和 Git commit 后才能进入下一项。
|
||||
- Apply、Archive 和阶段 Git commit 已获得用户对整个目标的持续授权;仅方向性决策需要暂停。
|
||||
- `tool_call_id` 使用框架协议 ID,Harness 不生成第二套 ID。
|
||||
- `status=PROJECTING/READY/ERROR` 表示 invocation lifecycle;`evidence_status=EVIDENCE_FOUND/NO_EVIDENCE/ERROR` 表示结果语义。
|
||||
- `NO_EVIDENCE` 只能支持限定范围的 `NEGATIVE_OBSERVATION`。
|
||||
- KNOWLEDGE_QUERY 使用 answer items 绑定 `tool_call_id + document_id`,首版不进入 SemanticGuard。
|
||||
- `diagnosis_run` 是 previous turn 的持久化真理源;只有最近的 `DIAGNOSIS + SUCCESS` 安全发布结果可用。
|
||||
- 取消采用分层、可观测语义;同步模型调用不承诺无法证明的立即硬取消。
|
||||
- 底层重试压为一次 attempt,Router/SemanticGuard 的允许重试只由 Harness 执行。
|
||||
- 阶段 4 和 6A 不接管公开入口,阶段 6B 才执行原子 SSE 切换。
|
||||
|
||||
## 权衡
|
||||
|
||||
- contract types 提前落地会增加少量文件,但后续 output type、validator、持久化和 SSE 可以复用,避免多阶段字符串协议漂移。
|
||||
- Provider 侧凭据轮换是外部前置,阶段 0 只证明工作树已清理,不伪造外部完成状态。
|
||||
@@ -1,25 +0,0 @@
|
||||
# Evidence: single-react-design-freeze
|
||||
|
||||
## 代码与框架证据
|
||||
|
||||
- `ChatController` 当前直接管理会话、模型、工具、执行和伪流式 SSE,证明公开切换必须延后到阶段 6B。
|
||||
- `ChatService` 当前构建 Planner/Executor/Verifier/Composer 并依赖 ThreadLocal,证明阶段 0 只能创建无运行依赖的 contract types。
|
||||
- Spring AI Alibaba `Builder` 提供 ToolInterceptor、output type、tool timeout 和调用限制扩展点;`ReactAgent` 提供 interrupt。
|
||||
- Spring AI 1.1.7 `SpringAiRetryProperties` 构造器默认 `maxAttempts=10`,与 Harness 单一重试所有权冲突,阶段 2 必须压为一次底层 attempt。
|
||||
- `DiagnosisRun` 当前只有通用 status 和文本 answer,不足以确定性恢复安全 previous turn,因此确认后续保存 `intent/release_outcome/published_result`。
|
||||
- 历史 ISS-009 和 verifier evidence 归档证明 `NO_EVIDENCE` 只能表达限定范围内无匹配结果。
|
||||
|
||||
## 验证证据
|
||||
|
||||
- `mvn -q '-Dtest=HarnessContractTest' test`:通过。
|
||||
- `mvn -q '-Dtest=ToolInvocationRecorderTest,ExecutorGatekeeperServiceTest,ChatControllerTest' test`:通过。
|
||||
- `mvn -q '-Dtest=HarnessContractTest,ToolInvocationRecorderTest,ExecutorGatekeeperServiceTest,ChatControllerTest' test`:通过。
|
||||
- `openspec validate single-react-design-freeze --strict`:通过。
|
||||
- `git diff --check`:通过,仅有 Windows line-ending warning。
|
||||
- 已知旧 Secret 模式扫描:零匹配。
|
||||
- 缺少 `SUPERBIZ_MYSQL_PASSWORD` 时运行查询脚本:在连接前 fail fast,符合预期。
|
||||
|
||||
## 未验证
|
||||
|
||||
- 未运行模型、Redis、MySQL 或 Milvus live E2E;按阶段门禁留到阶段 7。
|
||||
- Provider 侧旧凭据是否已经轮换无法由仓库证明,必须由凭据所有者完成,并在阶段 3C/7 前核验。
|
||||
@@ -1,65 +0,0 @@
|
||||
# Single React Diagnosis Agent Acceptance
|
||||
|
||||
## 结果
|
||||
|
||||
已接受。阶段 4 Committed OpenSpec 的 11 项任务全部完成,新链路仅通过内部 Java/test 入口运行,公开 Chat 未切换。
|
||||
|
||||
## 验证
|
||||
|
||||
### 静态验证
|
||||
|
||||
- 检查:新 `harness.agent` 包与 Prompt 搜索 `ThreadLocal|SessionContextHolder|while|SequentialAgent|SupervisorAgent|StateGraph|Planner|Composer|Verifier|raw_response`。
|
||||
- 结果:通过,无匹配。
|
||||
- 检查:`git diff --name-only` 限定 Controller、ChatService、AiOpsService。
|
||||
- 结果:通过,无 diff。
|
||||
- 检查:OpenSpec artifact status、cross-artifact、L2 interface impact、`.committed`、`.archive-ready`。
|
||||
- 结果:通过。
|
||||
|
||||
### 脚本验证
|
||||
|
||||
- 命令:`mvn -q -DskipTests compile`
|
||||
- 结果:通过。
|
||||
- 命令:`mvn -q '-Dtest=HarnessToolInterceptorTest,DiagnosisAgentUseCaseTest' test`
|
||||
- 结果:通过,14 tests。
|
||||
- 命令:`mvn -q '-Dtest=DiagnosisAgentUseCaseTest,HarnessToolInterceptorTest,DiagnosisHarnessCoreTest,ToolBoundaryTest,ToolAdapterTest,MysqlToolAdapterTest,CanonicalInvocationStoreTest,HarnessContractTest,RagToolContractTest,QueryLogsToolContractTest,MysqlToolContractTest' test`
|
||||
- 结果:通过。
|
||||
- 命令:`openspec validate single-react-diagnosis-agent --strict`
|
||||
- 结果:通过。
|
||||
- 命令:归档后 `openspec validate single-react-diagnosis-agent --type spec --strict`
|
||||
- 结果:通过;仓库级 `openspec validate --specs --strict` 另发现前序 `mysql-readonly-tool`、`rag-log-projections` 主规格仍使用旧 scenario 格式,本阶段不跨归档边界修改。
|
||||
|
||||
### 浏览器/人工验证
|
||||
|
||||
- 不适用。本阶段无 UI、HTTP 或 SSE 行为变化。
|
||||
|
||||
### 未验证
|
||||
|
||||
- 未启动 Maven 应用、外部模型、MySQL、Redis、Milvus 或日志服务;按 ISS-014 门禁统一留到阶段 7 live E2E。
|
||||
- 未验证 provider 生产响应始终携带 Token Usage;缺失 Usage 时模型调用次数仍强制,实际 Token 只能在 provider 返回时记录。
|
||||
|
||||
## 已完成范围
|
||||
|
||||
- 单一 Diagnosis ReactAgent、单 Prompt 和固定 Query/PreviousTurn 输入。
|
||||
- 框架原生 tool loop、exact Tool Call ID 和三类 Harness adapter bridge。
|
||||
- 模型/Token/Tool/上下文/Draft 预算与无自动 retry。
|
||||
- 严格 DiagnosisDraft 输出和无证据停止规则。
|
||||
- 显式 sessionId/runId audit metadata、可注入 AgentStep Hook、canonical Tool invocation。
|
||||
- 公开 Chat/AiOps 与旧多 Agent 路径保持不变。
|
||||
|
||||
## 已知限制
|
||||
|
||||
- Draft 尚未经过 EvidenceGuard/SemanticGuard,不能公开发布;阶段 5 负责释放门禁。
|
||||
- previous turn 由调用方传入,阶段 6A 才实现同 Session 安全 Run 选择和确定性组装。
|
||||
- 真实业务 adapter/Spring Bean 装配和公开入口切换分别留给阶段 6A/6B。
|
||||
- 仓库级全规格 strict validation 仍受阶段 3B/3C 主规格 scenario 标题格式阻塞,建议阶段 7 文档清理时统一修正并复验。
|
||||
|
||||
## Bug 修复和诊断
|
||||
|
||||
- 编译发现框架 `Interceptor.getName()` 必须实现,已补充稳定名称并回归。
|
||||
- 首次测试修正了两个测试假设:callback 异常包装类型,以及 ToolResponseMessage 在 Prompt instructions 中的实际位置;生产规格与实现方向未变。
|
||||
- 提交前自审发现默认 BeanOutputConverter schema 不允许 `conclusion=null`,与冻结的无证据契约冲突;已增加 schema post-process 和 focused regression,未放宽其他 Draft 字段。
|
||||
|
||||
## 交接
|
||||
|
||||
- 下一步:提交独立阶段 4 commit,再进入阶段 5。
|
||||
- OpenSpec 归档确认:用户已对 ISS-014 每阶段 Apply、Archive 和 Git commit 提供持续授权;已归档至 `openspec/changes/archive/2026-07-21-single-react-diagnosis-agent`,主规格已同步至 `openspec/specs/single-react-diagnosis-agent/spec.md`。
|
||||
@@ -1,21 +0,0 @@
|
||||
# Single React Diagnosis Agent Brief
|
||||
|
||||
## 背景
|
||||
|
||||
- 用户目标:按 ISS-014 阶段 4 建立唯一的 Diagnosis ReAct Agent,并完成独立 sm-flow 归档与提交。
|
||||
- 当前问题:Harness Core 和三类 evidence Tool 已就绪,但没有一个内部诊断执行链消费它们;公开 Chat 仍依赖旧的简单/多 Agent 路径。
|
||||
- 关联 OpenSpec:`openspec/changes/archive/2026-07-21-single-react-diagnosis-agent/`
|
||||
- devflow 分档:complex
|
||||
- 需求真理源:`mvp/issues/archived/ISS-014-single-react-agent-harness-aci-ptk-refactor.md`,不重复创建独立 PRD。
|
||||
|
||||
## 范围
|
||||
|
||||
- 本次要做:单 Prompt、单 Diagnosis ReactAgent、固定 Query/PreviousTurn 输入、Harness Model/Tool interceptors、三类 Tool 注册、严格 DiagnosisDraft 解析、上下文/模型/Tool/Token 预算和内部审计注入。
|
||||
- 本次不做:公开 Chat 切换、旧链路删除、EvidenceGuard、SemanticGuard、previous turn 选择、DiagnosisRun 持久化和 live E2E。
|
||||
- 影响区域:`com.superbiz.agent.harness.agent`、`src/main/resources/prompts`、focused tests、OpenSpec/devflow/ISS-014 状态。
|
||||
|
||||
## OpenSpec 对齐
|
||||
|
||||
- proposal 覆盖状态:已覆盖
|
||||
- specs 覆盖状态:已覆盖
|
||||
- tasks 覆盖状态:已覆盖
|
||||
@@ -1,156 +0,0 @@
|
||||
# Decisions: single-react-diagnosis-agent
|
||||
|
||||
## Discover status
|
||||
|
||||
- Checkpoint: Discover
|
||||
- Capability source: `sm-flow`,使用 `grill-with-docs` 进行代码可证问题澄清,并使用 GitNexus、源码、依赖 sources jar 与 `javap` 核对调用链和框架 API。
|
||||
- Scale: complex。变更新增内部 Agent/use case,跨越模型、Tool、预算、结构化输出和审计边界,但不切换公开协议。
|
||||
- `devflow/index.md` 命中 design freeze、RunContext、ACI contracts、canonical store、RAG/log projection 和 MySQL Tool;没有与 OpenSpec 冲突的 ADR。
|
||||
|
||||
## Question Pool
|
||||
|
||||
| # | 维度 | 问题 | 模式 | 状态 |
|
||||
|---|---|---|---|---|
|
||||
| Q1 | 术语 | 单体 Diagnosis Agent 是否包含外层 Graph 或多个报告作者? | evidence-driven | 已解决 |
|
||||
| Q2 | 边界 | 阶段 4 是否切换公开 Chat 或删除旧多 Agent 链路? | evidence-driven | 已解决 |
|
||||
| Q3 | 验收 | 如何证明 ReAct 正常轮次不是 Harness retry? | evidence-driven | 已解决 |
|
||||
| Q4 | 技术 | 如何取得并保留框架原始 tool_call_id? | evidence-driven | 已解决 |
|
||||
| Q5 | 技术 | 如何在每个模型和 Tool 边界强制 Run 预算? | evidence-driven | 已解决 |
|
||||
| Q6 | 输出 | 框架生成的 DiagnosisDraft schema 是否与可空 conclusion 契约一致,并会直接返回 DiagnosisDraft? | evidence-driven | 已解决 |
|
||||
| Q7 | 上下文 | previous_turn 如何进入模型且保持固定 Schema 和有界? | evidence-driven | 已解决 |
|
||||
| Q8 | 审计 | 如何保留 Run/AgentStep/ToolInvocation 而不引入 ThreadLocal? | evidence-driven | 已解决 |
|
||||
| Q9 | 验收 | 无证据结果如何停止而不补造根因? | evidence-driven | 已解决 |
|
||||
|
||||
## Evidence-driven
|
||||
|
||||
| 结论 | 证据来源 | 是否已汇报用户 |
|
||||
|---|---|---|
|
||||
| 只新增一个拥有 tool loop 的 `ReactAgent`,无 SequentialAgent、SupervisorAgent 或业务 StateGraph。 | ISS-014 阶段 4;`ChatService` 旧链路反例;Spring AI Alibaba `ReactAgent` API | 已汇报 |
|
||||
| 阶段 4 只提供内部用例,公开入口保持旧实现,接口影响 L2。 | ISS-014 1174-1197、阶段 0 design freeze、GitNexus `createReactAgent` 引用 | 已汇报 |
|
||||
| `ToolCallRequest.getToolCallId()` 精确暴露 `AssistantMessage.ToolCall.id()`;ToolInterceptor 可在回调执行前取得该 ID。 | framework sources `ToolCallRequest`、`AgentToolNode` | 已汇报 |
|
||||
| `ModelInterceptor` 包围每次真实模型调用,适合调用 `beforeModelCall` 并记录响应 Usage;ToolBoundary 已负责 Tool 预算,不能重复计数。 | framework `AgentLlmNode`/`InterceptorChain`;`ToolBoundary` | 已汇报 |
|
||||
| BeanOutputConverter 可从 DiagnosisDraft 生成格式说明,但默认 schema 不允许冻结契约的 `conclusion=null`;必须 post-process nullable conclusion,且 `ReactAgent.call` 仍返回 AssistantMessage,需要 Harness 严格解析 JSON。 | framework `DefaultBuilder`、`ReactAgent`、本地生成 schema | 已汇报 |
|
||||
| RunContext 可放入 `RunnableConfig` metadata,由框架控制地传播到 ToolInterceptor;不需要 ThreadLocal。 | `RunnableConfig.addMetadata(String,Object)`、`AgentToolNode` | 已汇报 |
|
||||
| 现有 `AgentLoggingHook` 优先读取 config metadata 的 sessionId/runId,可作为可选审计 Hook 复用;ToolBoundary 保持 canonical Tool invocation。 | `AgentLoggingHook`、`ToolBoundary` | 已汇报 |
|
||||
| 原始 Query 不截断;超限 fail closed。PreviousTurn 先按固定 record 序列化并受独立/总上下文字节限制。 | ISS-014 极简上下文与预算规则 | 已汇报 |
|
||||
| `NO_EVIDENCE` 不是错误,只能形成限定范围的 NEGATIVE_OBSERVATION;Prompt 必须要求 conclusion=null、记录 missing_info 并停止。 | glossary、ACI spec、DiagnosisDraft contract | 已汇报 |
|
||||
|
||||
## User-interview
|
||||
|
||||
- 本阶段没有新增 user-interview 问题。方向、范围、阶段串行规则、框架 ID、状态语义以及 routine Apply/Archive/Commit 持续授权均已由用户在 ISS-014 评审与前序阶段确认。
|
||||
|
||||
## 关键取舍
|
||||
|
||||
- 决策:使用框架 `ToolInterceptor` 直接桥接已注册的 Tool 定义与 Harness adapter。
|
||||
- 原因:Spring AI `ToolCallback` 的调用参数不包含 Tool Call ID,而 Alibaba interceptor 明确提供原始 ID 和运行 metadata。
|
||||
- 影响:ToolCallback 负责模型可见定义,interceptor 负责受控执行;未知 Tool 仍交给框架 handler 并最终失败,不伪造结果。
|
||||
- 决策:模型预算由 `ModelInterceptor` 执行,Tool 预算继续由 `ToolBoundary` 执行。
|
||||
- 原因:避免在 Agent 层和 Tool boundary 双重 reserve。
|
||||
- 决策:阶段 4 只严格反序列化 `DiagnosisDraft`,不提前实现 EvidenceGuard。
|
||||
- 原因:字段引用真实性、唯一性和语义支持属于阶段 5;本阶段只验证 Agent 能生成冻结结构并携带框架 IDs。
|
||||
- 决策:复用现有 Agent Hook 注入点,不复制 AgentStep 持久化实现。
|
||||
- 原因:阶段 4 不接公开运行态,阶段 6A 再装配真实 Repository 和 Run 持久化。
|
||||
|
||||
## OpenSpec 回写
|
||||
|
||||
- 需进入 proposal/design/spec/tasks:单 Agent、内部入口、ToolInterceptor 原始 ID、ModelInterceptor 模型预算、ToolBoundary 单点 Tool 预算、严格 JSON 解析、上下文字节限制、审计 Hook 注入、无证据停止、不切换公开入口。
|
||||
- 不创建 ADR:这些是 ISS-014 已冻结方向和当前阶段可逆的内部装配,不满足新的难逆转架构决策条件。
|
||||
|
||||
## Cross-artifact 对齐
|
||||
|
||||
| 上游 -> 下游 | 检查内容 | 状态 |
|
||||
|---|---|---|
|
||||
| brief/ISS-014 -> proposal | 单 Agent、内部入口、极简上下文、预算、审计、非目标和验收预期 | 已对齐 |
|
||||
| proposal -> design | Tool/Model interceptor、严格 Draft、无重试、审计注入和公开隔离 | 已对齐 |
|
||||
| design -> specs/tasks | ID 传播、预算单点、输入输出限制、生命周期所有权和风险缓解 | 已对齐 |
|
||||
| specs -> tasks | 7 组可观察要求均有输入/Prompt、Tool bridge、Agent use case 和 focused test 切片 | 已对齐 |
|
||||
|
||||
## Architecture Audit
|
||||
|
||||
- 能力来源:`zoom-out`,使用 glossary 的 Diagnosis Agent、Diagnosis Harness、RunContext、Evidence Status 和 Invocation Status 术语。
|
||||
- 链路为 `DiagnosisAgentInput + RunContext -> internal use case -> one ReactAgent -> model/tool interceptors -> ChatModel/ToolBoundary -> strict DiagnosisDraft`,没有外层业务 Graph。
|
||||
- RunContext 拥有预算/取消/生命周期,ToolBoundary/store 拥有 canonical invocation,use case 拥有输入和 Draft 解析,Agent 只拥有诊断语义;数据所有权不重叠。
|
||||
- 最大耦合风险是 Spring AI Alibaba interceptor/output schema API;设计通过本地 1.1.2.0 sources jar 和实际 schema 生成结果证实,并以 focused framework-loop/schema tests 固定。
|
||||
- 最大阶段风险是 Draft 在 Guards 前被误用;类名、文档和零 Controller 消费者共同保持 internal/draft 边界,阶段 5 前不得发布。
|
||||
|
||||
## 接口影响
|
||||
|
||||
- 级别:L2 内部接口。
|
||||
- 变更对象:新增内部 Java use case/factory/input/limits/interceptors/registry,不修改既有方法签名。
|
||||
- 消费者:本阶段只有 focused tests;阶段 6A 将成为首个生产消费者。
|
||||
- 兼容性:公开 HTTP/SSE、Controller DTO、数据库和旧 Chat/AiOps 路径不变,无迁移或回滚要求。
|
||||
|
||||
## Pre-apply Research
|
||||
|
||||
### 参考实现与框架源码
|
||||
|
||||
- `src/main/java/com/superbiz/agent/service/ChatService.java`:`createReactAgent`、`buildChatExecutorAgent` 和旧多 Agent 反例;只复用 Builder 形态,不复用运行职责。
|
||||
- `src/test/java/com/superbiz/agent/service/ChatServiceSequentialAgentTest.java`:scripted `ChatModel` 测试模式。
|
||||
- `src/main/java/com/superbiz/agent/harness/core/DiagnosisHarnessCore.java`:模型/Tool/Token/容量边界。
|
||||
- `src/main/java/com/superbiz/agent/harness/tool/boundary/ToolBoundary.java`:Tool budget 和 canonical record 单点。
|
||||
- `src/main/java/com/superbiz/agent/harness/tool/adapter/RagToolAdapter.java`、`QueryLogsToolAdapter.java`、`MysqlToolAdapter.java`:阶段 4 唯一允许的 evidence Tool 执行入口。
|
||||
- `src/main/java/com/superbiz/agent/hook/AgentLoggingHook.java`:可注入 AgentStep audit,优先读取 RunnableConfig metadata。
|
||||
- Spring AI Alibaba 1.1.2.0 sources:`ReactAgent`、`DefaultBuilder`、`AgentLlmNode`、`AgentToolNode`、`ToolCallRequest`、`InterceptorChain`。
|
||||
|
||||
### 技术栈清单
|
||||
|
||||
- `ReactAgent.builder()` + 从 `DiagnosisDraft` 生成并修正 nullable conclusion 的 `.outputSchema(...)`,不新建 Graph/SequentialAgent。
|
||||
- `RunnableConfig.addMetadata(String,Object)` 显式携带 sessionId/runId/RunContext,并设置 `_stream_=false`。
|
||||
- `ModelInterceptor` 对每次模型调用执行 Core budget;读取 `ChatResponseMetadata.Usage`。
|
||||
- `ToolInterceptor` 读取 exact framework ID,调用 adapter bridge;`ToolBoundary` 保留唯一 Tool reserve/store 边界。
|
||||
- Spring `FunctionToolCallback` 仅定义模型可见 Tool Schema/description;直接 callback 执行 fail closed。
|
||||
- Jackson `ObjectMapper` 负责固定输入 JSON 和严格 DiagnosisDraft 反序列化;UTF-8 字节按 `StandardCharsets.UTF_8` 计算。
|
||||
- 框架 Hook 列表作为 AgentStep audit 扩展点;阶段 4 不新增 JPA/Redis/Flyway。
|
||||
|
||||
### 新建基础设施
|
||||
|
||||
- `harness.agent`:Input、Limits、Tool registry/interceptor、Model interceptor、Factory、UseCase 和异常类型。
|
||||
- `prompts/diagnosis-agent-prompt.md`:唯一 Diagnosis Agent Prompt。
|
||||
- focused scripted model/tool-loop tests;无需新 Maven 依赖。
|
||||
|
||||
### ISS-014 PRD 复用
|
||||
|
||||
- 阶段 4 不新建独立 `prd.md`:ISS-014 已完整覆盖问题、用户价值、数据流、Draft Schema、预算、重试、阶段边界和验收;`brief.md` 只索引本切片,不复制总 Issue。
|
||||
|
||||
## Commit Gate Preflight
|
||||
|
||||
- proposal、design、specs、tasks 完整,`openspec status` 为 complete,`openspec validate single-react-diagnosis-agent --strict` 通过。
|
||||
- question pool 全部为已汇报的 evidence-driven 结论;无未确认 user-interview、接口等级或风险接受问题。
|
||||
- Cross-artifact 四段对齐无 gap;架构审计的数据所有权、阶段边界和框架耦合缓解已进入 design/spec/tasks。
|
||||
- 接口影响为 L2,仅新增内部 Java API;公开 Controller/SSE/JPA/旧 ChatService 保持不变。
|
||||
- Apply、Archive 和阶段 Git commit 使用用户对 ISS-014 各阶段的持续授权;实现必须严格限制为 Committed OpenSpec。
|
||||
- `.committed` 已创建,Committed OpenSpec 可进入 Apply。
|
||||
|
||||
## Apply Progress
|
||||
|
||||
- 首模块对齐:Input/Limits/Prompt/Tool registry/Tool interceptor 已落地,任务 1.2、2.1、2.2 完成;1.1 等待 focused test 后完成。
|
||||
- 编译首次发现 `ToolInterceptor` 必须实现 `Interceptor.getName()`;分类为代码偏离,已补充稳定名称并复编译通过,无需修改 OpenSpec。
|
||||
- 单 Agent use case、Model interceptor、strict Draft parser 和 audit Hook 注入已完成;scripted ChatModel 真实执行框架 `model -> Tool -> model` loop。
|
||||
- 首次测试的两处失败均为测试假设偏差:Spring 会将 callback 异常包装为 `ToolExecutionException`,Tool observation 位于 `Prompt.instructions` 的 `ToolResponseMessage` 而非 `Prompt.getContents()`;已按框架真实 API 修正测试,生产设计未变。
|
||||
- 阶段 4 focused tests 共 14 个通过,任务 1.1-4.2 完成;剩余任务 4.3 为综合回归、静态范围和 OpenSpec 验证。
|
||||
|
||||
## Apply Result
|
||||
|
||||
- 新增一个且仅一个 `diagnosis_agent` Factory 和内部 `DiagnosisAgentUseCase`;没有外层业务 Graph、SequentialAgent、SupervisorAgent 或手写 ReAct loop。
|
||||
- 新增单一 Prompt、固定 `DiagnosisAgentInput(query, previous_turn)`、可配置 UTF-8 限制和严格 `DiagnosisDraft` 解析;不接受完整历史,不执行结构修复或 Agent retry。
|
||||
- 新增 `HarnessModelInterceptor`,对每个非流式模型轮次执行 Core model/Token budget,并在 late result 返回后复查 Run active 状态。
|
||||
- 新增 `HarnessEvidenceTools` 和 `HarnessToolInterceptor`,注册三类冻结 Tool,精确传播框架 Tool Call ID,并通过阶段 3B/3C adapter/ToolBoundary 返回有界结果。
|
||||
- AgentStep 使用可注入框架 Hook 保留,RunnableConfig 显式传播 sessionId/runId;Run 和 Tool canonical invocation 继续由既有 Harness 边界拥有。
|
||||
- 公开 Controller、ChatService、AiOpsService 无 diff;旧多 Agent 主链路继续保留。
|
||||
|
||||
## Apply Verification
|
||||
|
||||
- 编译:`mvn -q -DskipTests compile` 通过。
|
||||
- 阶段 4 focused:`mvn -q '-Dtest=HarnessToolInterceptorTest,DiagnosisAgentUseCaseTest' test`,14 tests 通过。
|
||||
- 综合回归:`mvn -q '-Dtest=DiagnosisAgentUseCaseTest,HarnessToolInterceptorTest,DiagnosisHarnessCoreTest,ToolBoundaryTest,ToolAdapterTest,MysqlToolAdapterTest,CanonicalInvocationStoreTest,HarnessContractTest,RagToolContractTest,QueryLogsToolContractTest,MysqlToolContractTest' test` 通过。
|
||||
- OpenSpec:`openspec validate single-react-diagnosis-agent --strict` 通过。
|
||||
- 静态范围:新 Agent 包无 ThreadLocal、手写 while、外层 Graph、多 Agent 类型或 raw response;Controller/ChatService/AiOpsService diff 为空。
|
||||
- 未执行 live E2E:按 ISS-014 阶段门禁统一留到阶段 7。
|
||||
|
||||
## Archive Result
|
||||
|
||||
- 11/11 OpenSpec tasks 完成,`.archive-ready` 已创建。
|
||||
- 主规格已同步至 `openspec/specs/single-react-diagnosis-agent/spec.md`。
|
||||
- Change 已归档至 `openspec/changes/archive/2026-07-21-single-react-diagnosis-agent`。
|
||||
- `devflow/index.md` 和 ISS-014 阶段表已更新为阶段 0-4 archived,下一阶段为 5。
|
||||
- 提交前 schema 自审发现框架默认 BeanOutputConverter 将 `conclusion` 限为 object,与冻结的无证据 `null` 语义冲突;分类为实现设计遗漏,已回写 archived design,新增 nullable schema post-process 与回归测试,规格行为未改变。
|
||||
@@ -1,29 +0,0 @@
|
||||
# Single React Diagnosis Agent Evidence
|
||||
|
||||
## 代码与文档证据
|
||||
|
||||
| 来源 | 证据 | 结论 | 是否已汇报 |
|
||||
|---|---|---|---|
|
||||
| `mvp/issues/archived/ISS-014-single-react-agent-harness-aci-ptk-refactor.md` | 阶段 4 明确单 Agent、内部入口、极简上下文、结构化 Draft、无重试和预算验收 | 本 change 不得切换公开入口或删除旧链路 | 是 |
|
||||
| `ChatService.java` + GitNexus references | `createReactAgent` 被旧策略入口调用;复杂路径仍创建 Planner/Executor/Verifier/Composer | 新实现必须是独立内部 use case,不能复用旧 Service 运行职责 | 是 |
|
||||
| Spring AI Alibaba 1.1.2.0 `ReactAgent`/`AgentLlmNode` sources | 框架自带 ReAct loop;非流式 `ModelResponse` 保留 `ChatResponse` Usage | 不手写循环,使用 ModelInterceptor 强制模型/Token 预算 | 是 |
|
||||
| Spring AI Alibaba `ToolCallRequest`/`AgentToolNode` sources | `ToolCallRequest.getToolCallId()` 来自 `AssistantMessage.ToolCall.id()`,Tool interceptor 在 callback 前执行 | 可以精确传播框架 ID,不生成第二套 ID | 是 |
|
||||
| Spring AI Alibaba `DefaultBuilder` + 本地 BeanOutputConverter 输出 | 默认 schema 只允许 object conclusion,但冻结契约允许无证据时 conclusion=null | 生成 schema 必须 post-process nullable conclusion,UseCase 仍严格反序列化 DiagnosisDraft | 是 |
|
||||
| `DiagnosisHarnessCore.java` / `ToolBoundary.java` | Core 提供 model/Token/capacity;ToolBoundary 已负责 Tool reserve/store | Agent 层只 reserve model/context,禁止双扣 Tool budget | 是 |
|
||||
| 阶段 3B/3C adapters | RAG/log/MySQL 都以 `RunContext + ToolCallRequestEnvelope` 进入 ToolBoundary | Tool registry 可直接桥接既有 adapter,不复制投影或安全策略 | 是 |
|
||||
| `AgentLoggingHook.java` | 优先从 RunnableConfig metadata 读取 sessionId/runId | Factory 可复用现有 Hook 注入点,不依赖 ThreadLocal | 是 |
|
||||
|
||||
## Evidence-driven 结论
|
||||
|
||||
- 单 Agent 的可验证边界是一个 `ReactAgent.call`,内部允许正常模型/Tool轮次,但外部没有 Agent retry 或第二个报告作者。
|
||||
- ToolCallback 不直接提供 Tool Call ID,必须使用 Alibaba `ToolInterceptor`;已由真实 scripted framework loop 证明 ID 进入 ToolResponseMessage。
|
||||
- `PreviousTurn` 只作为固定上下文,当前 Draft 只允许引用当前 Run Tool result 中的 ID。
|
||||
- `NO_EVIDENCE` 必须以 `conclusion=null`、限定范围的负向观察和 missing info 结束,不能推导健康或排除根因。
|
||||
- 阶段 4 的 L2 内部 API 不影响公开消费者;阶段 5/6A/6B 前 Draft 不可发布。
|
||||
|
||||
## 实现证据
|
||||
|
||||
- 新包 `com.superbiz.agent.harness.agent` 包含 Input/Limits、Prompt loader、Tool registry/interceptor、Model interceptor、Factory 和 UseCase。
|
||||
- `diagnosis-agent-prompt.md` 是唯一新 Diagnosis Agent Prompt,包含 Tool、证据绑定、停止和精确 JSON 规则。
|
||||
- 14 个阶段 4 tests 覆盖框架 model -> Tool -> model、ID、错误、未知 Tool、PreviousTurn、审计 metadata、nullable conclusion schema、no-evidence、解析和预算。
|
||||
- 综合回归同时覆盖 Harness Core、ToolBoundary、3B/3C adapter、canonical store 和冻结 contracts。
|
||||
@@ -1,44 +0,0 @@
|
||||
# Acceptance: single-react-evidence-semantic-guards
|
||||
|
||||
## Result
|
||||
|
||||
- Status: archived
|
||||
- OpenSpec tasks: 14/14 complete
|
||||
- Interface impact: L2 internal
|
||||
- Public protocol: unchanged
|
||||
|
||||
## Static Verification
|
||||
|
||||
- `git diff --check`:阶段文件无 whitespace error;工作区用户已有 `AGENTS.md`/`CLAUDE.md` 仅报告 line-ending warning,未纳入阶段范围。
|
||||
- 公开 `controller`、`ChatService.java`、`AiOpsService.java` diff 为空。
|
||||
- SemanticGuard 包和 prompt 不含 Tool Call ID、raw response、ReactAgent、StateGraph、ThreadLocal 或手写 while。
|
||||
- 新 guard/release 包不包含业务 Agent loop。
|
||||
|
||||
## Script Verification
|
||||
|
||||
- `mvn -q -DskipTests compile`:通过。
|
||||
- Stage-focused `EvidenceGuardTest,SemanticGuardTest,DiagnosisReleaseUseCaseTest`:19 tests,0 failure/error。
|
||||
- Harness/Tool/Agent regression selection:18 suites / 70 tests,0 failure/error/skipped。
|
||||
- `openspec validate single-react-evidence-semantic-guards --strict`:通过。
|
||||
- `openspec validate --specs --strict`:16 passed / 2 failed;失败是前序 `mysql-readonly-tool`、`rag-log-projections` scenario 标题格式,不阻塞本 change,计划阶段 7 统一修复。
|
||||
|
||||
## Browser or Manual Verification
|
||||
|
||||
- Not applicable。阶段 5 没有 UI 或公开入口变化。
|
||||
|
||||
## Not Verified
|
||||
|
||||
- 未运行真实 LLM、Redis、日志和 MySQL live E2E;按 ISS-014 串行门禁统一留到阶段 7。
|
||||
- Provider 是否立即响应 Java thread interrupt 取决于 SDK;Harness 已保证 Future cancel、迟到 Token 记账和迟到结果不释放,阶段 7 需用真实模型观察取消延迟。
|
||||
|
||||
## Remaining Work
|
||||
|
||||
- 阶段 6A:Chat Application Use Case、Intent Router、PreviousTurn 和 Run persistence。
|
||||
- 阶段 6B:公开 SSE 原子切换。
|
||||
- 阶段 7:旧链路清理、全局 spec 格式修复和最终 live E2E。
|
||||
|
||||
## Archive
|
||||
|
||||
- `.archive-ready`: created
|
||||
- OpenSpec archive: `openspec/changes/archive/2026-07-21-single-react-evidence-semantic-guards`
|
||||
- Main spec: `openspec/specs/single-react-evidence-semantic-guards/spec.md`
|
||||
@@ -1,32 +0,0 @@
|
||||
# Brief: single-react-evidence-semantic-guards
|
||||
|
||||
## Background
|
||||
|
||||
阶段 4 已能生成带框架 Tool Call ID 的 `DiagnosisDraft`,但草稿在发布前还缺少当前 Run 证据验真、独立语义审查和 fail-closed 释放边界。
|
||||
|
||||
## Goal
|
||||
|
||||
在不恢复业务 Graph、不切换公开入口的前提下,实现确定性 EvidenceGuard、一次语义不变的结构修复、无 Tool/无记忆的单轮 SemanticGuard,以及只发布原 Draft 或固定 SafeFallback 的内部 release use case。
|
||||
|
||||
## Scope
|
||||
|
||||
- Draft 结构、Analysis/报告引用和 canonical Tool invocation 验真。
|
||||
- RAG/log/MySQL verified evidence snapshot。
|
||||
- Evidence repair 单次调用与语义不变约束。
|
||||
- SemanticGuard 模型/Token/字节预算、超时、取消、技术重试和严格二元输出。
|
||||
- SUPPORTED/UNSUPPORTED/unavailable/evidence-failed release policy。
|
||||
- focused tests、Harness/Tool/Agent 回归和静态范围验证。
|
||||
|
||||
## Non-goals
|
||||
|
||||
- 不切换 Chat/AiOps/SSE 公开协议。
|
||||
- 不实现 Intent Router、PreviousTurn、Run persistence 或最终报告渲染。
|
||||
- 不删除旧 Gatekeeper/Verifier/Composer/多 Agent 链路。
|
||||
- 不运行 live model/Redis/MySQL E2E;统一留到阶段 7。
|
||||
|
||||
## Metadata
|
||||
|
||||
- Scale: complex
|
||||
- Interface impact: L2 internal
|
||||
- OpenSpec: `single-react-evidence-semantic-guards`
|
||||
- Parent issue: `ISS-014`
|
||||
@@ -1,144 +0,0 @@
|
||||
# Decisions: single-react-evidence-semantic-guards
|
||||
|
||||
## Discover Status
|
||||
|
||||
- Checkpoint: Discover
|
||||
- Capability source: `sm-flow`,使用 `grill-with-docs` 做 evidence-driven 澄清;`codebase-retrieval`、LSP 和 GitNexus MCP 在当前会话不可用,降级为既有 GitNexus 研究结论、`rg` 调用点核对和逐文件源码阅读。
|
||||
- Scale: complex。变更跨 canonical store、三类 Tool projection、模型预算、超时/取消、结构修复、语义审查和释放边界,但不切换公开协议。
|
||||
- `devflow/index.md` 命中阶段 0-4 的设计冻结、RunContext、canonical store、Tool projection 和 Diagnosis Agent;没有与当前 OpenSpec 冲突的 ADR。
|
||||
|
||||
## Question Pool
|
||||
|
||||
| # | 维度 | 问题 | 模式 | 状态 |
|
||||
|---|---|---|---|---|
|
||||
| Q1 | 术语 | EvidenceGuard 是否判断证据足以推出结论? | evidence-driven | 已解决 |
|
||||
| Q2 | 边界 | verified snapshot 能读取哪些 canonical 字段,并向 SemanticGuard 暴露哪些内容? | evidence-driven | 已解决 |
|
||||
| Q3 | 边界 | `NO_EVIDENCE` 能支持哪类 Analysis? | evidence-driven | 已解决 |
|
||||
| Q4 | 修复 | 首次 EvidenceGuard 失败允许如何修复,是否可重跑 Agent 或 Tool? | evidence-driven | 已解决 |
|
||||
| Q5 | 语义 | SemanticGuard 是否拥有 Tool、记忆、ReAct loop 或报告写作能力? | evidence-driven | 已解决 |
|
||||
| Q6 | 重试 | 哪些 SemanticGuard 结果允许第二次 attempt? | evidence-driven | 已解决 |
|
||||
| Q7 | 超时 | 单轮模型超时和 Run 取消如何终止后台调用? | evidence-driven | 已解决 |
|
||||
| Q8 | 释放 | 三种 Fallback 能否包含 Draft、reason 或未验真来源? | evidence-driven | 已解决 |
|
||||
| Q9 | 接口 | 阶段 5 是否切换公开入口或修改 SSE/持久化协议? | evidence-driven | 已解决 |
|
||||
| Q10 | 验收 | 如何证明不存在隐式 Agent/repair/retry loop? | evidence-driven | 已解决 |
|
||||
|
||||
## Evidence-driven
|
||||
|
||||
| 结论 | 证据来源 | 是否已汇报用户 |
|
||||
|---|---|---|
|
||||
| EvidenceGuard 只验证结构、引用和 canonical invocation 真实性,不判断 Analysis/Conclusion 的语义充分性。 | ISS-014 4.3、阶段 5;glossary `EvidenceGuard` | 已汇报 |
|
||||
| Store 只能按 `ToolCallKeyFactory.create(runId, toolCallId)` 查找;可引用记录必须是当前 Run、`READY`、含 `agent_result` 且状态为 `EVIDENCE_FOUND|NO_EVIDENCE`。 | `CanonicalInvocationStore`、`CanonicalToolInvocation.isReferencableBy` | 已汇报 |
|
||||
| Snapshot 解析 `agent_result` 和必要的有界 request 字段,不读取 `raw_response`;输出按 `analysis_id` 分组且不包含 Tool Call ID。 | ISS-014 4.4、10.2、已冻结 Tool contracts | 已汇报 |
|
||||
| `NORMAL` 只绑定 `EVIDENCE_FOUND`;`NEGATIVE_OBSERVATION` 只绑定 `NO_EVIDENCE`,且零结果范围来自投影/请求。 | ISS-014 4.3、10.2;`EvidenceStatus` glossary | 已汇报 |
|
||||
| Evidence repair 只在首次物理验真失败后执行一次无 Tool单轮模型调用,不重跑 Diagnosis Agent 或 Tool loop。 | ISS-014 10.3、阶段 5、重试边界决策 | 已汇报 |
|
||||
| SemanticGuard 复用同一 `ChatModel`,使用全新 `Prompt` 单轮调用,无 Tool/记忆/ReAct;只返回二元 verdict 和审计 reason。 | ISS-014 4.4、阶段 5;Spring AI `ChatModel.call(Prompt)` | 已汇报 |
|
||||
| 仅超时、传输、解析或 Schema 技术失败可重试一次;`UNSUPPORTED` 是有效业务结果,不重试。 | `HarnessRetryPolicies.strict().semanticGuard()`、ISS-014 重试策略 | 已汇报 |
|
||||
| `ChatResponseMetadata.Usage` 可复用 Core 的 model/Token 预算;受控 `Future.get(timeout)` 可在超时或 Run 取消时取消任务。 | `HarnessModelInterceptor`、`DiagnosisHarnessCore`、`RunCancellation` | 已汇报 |
|
||||
| `EVIDENCE_VALIDATION_FAILED` 的来源必须为空;其余 Fallback 只能包含已验真来源,不包含 Draft 或 SemanticGuard reason。 | ISS-014 10.3、阶段 5;`SafeFallback`/`FallbackType` | 已汇报 |
|
||||
| 阶段 5 只新增内部用例,公开入口切换留到阶段 6B。 | ISS-014 阶段顺序和 6B 门禁 | 已汇报 |
|
||||
|
||||
## User-interview
|
||||
|
||||
- 本阶段没有新增 user-interview 问题。上述方向、范围、修复次数、模型复用、超时/重试、Fallback 和阶段串行规则均已在 ISS-014 评审及前序对话中由用户确认。
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- Snapshot 使用 Tool-specific adapter 严格解析冻结 projection;未知 Tool、ID 不一致、projection 反序列化失败或 projection 的 EvidenceStatus 与 canonical record 不一致均 fail closed。
|
||||
- MySQL 的逻辑数据源和查询范围来自 canonical `request`,行/列和值来自 `agent_result`;RAG/log 以 `agent_result` 自带的稳定来源和范围为准。
|
||||
- SemanticGuard 使用直接 `ChatModel.call(Prompt)`,不创建第二个 `ReactAgent`;模型调用由受控 Executor 执行,超时/取消时调用 `Future.cancel(true)`。
|
||||
- Evidence repair 与 SemanticGuard 共用同一模型抽象,但各自拥有独立 prompt、严格输出类型和预算;repair 策略固定一次 attempt,不能嵌套 retry executor。
|
||||
- Release use case 只在 EvidenceGuard 成功后调用 SemanticGuard;SUPPORTED 返回原 Draft 对象,所有其他路径只返回固定 `SafeFallback`。
|
||||
- 不创建 ADR:这些是 ISS-014 已冻结架构的阶段实现,不产生新的难逆转跨项目决策。
|
||||
|
||||
## OpenSpec Backfill
|
||||
|
||||
- 需进入 proposal/design/spec/tasks:EvidenceGuard 规则、Tool-specific snapshot、无 raw/ID 泄漏、repair 单次边界、SemanticGuard 隔离/预算/超时/重试、原样发布与三类 Fallback、L2/公开隔离。
|
||||
- 不进入本阶段:公开 Chat/SSE 装配、Run 持久化、旧多 Agent 删除和 live E2E。
|
||||
|
||||
## Cross-artifact Alignment
|
||||
|
||||
| 上游 -> 下游 | 检查内容 | 状态 |
|
||||
|---|---|---|
|
||||
| ISS-014/brief -> proposal | 物理验真、结构修复、隔离语义审查、固定 Fallback、阶段边界 | 已对齐 |
|
||||
| proposal -> design | Store ownership、Tool-specific snapshot、timeout/cancel/retry、唯一报告作者和 L2 影响 | 已对齐 |
|
||||
| design -> specs/tasks | 每个关键决策均有可观察 requirement 和对应实现/测试切片 | 已对齐 |
|
||||
| specs -> tasks | 9 组 requirements 覆盖为 Evidence、model boundary、repair/release 和回归验证任务 | 已对齐 |
|
||||
|
||||
## Architecture Audit
|
||||
|
||||
- 能力来源:`zoom-out`,使用 glossary 的 Diagnosis Harness、EvidenceGuard、SemanticGuard、RunContext、Invocation Status 和 Evidence Status 术语。
|
||||
- 链路为 `query + Draft + RunContext -> EvidenceGuard/store -> optional repair/shared model boundary -> SemanticGuard/shared model boundary -> original Draft or fixed Fallback`,没有外层 Graph 或第二个 Tool loop。
|
||||
- Store 拥有物理调用记录,EvidenceGuard 只读并生成 snapshot;Diagnosis Agent 拥有报告语义,repair 只修 ID,SemanticGuard 只审查,release 只做二选一,数据所有权没有重叠。
|
||||
- 最大运行风险是 provider 忽略 interrupt;design 要求 Future cancel、迟到 Token 记录和 `core.checkActive` 丢弃迟到结果,阶段 6A 再负责 Run 终态。
|
||||
- 架构审计未发现与阶段 0-4 或 ADR 冲突;所有风险缓解已回写 design/spec/tasks。
|
||||
|
||||
## Interface Impact
|
||||
|
||||
- 级别:L2 内部接口。
|
||||
- 变更对象:新增 guard/release records、interfaces、use cases、prompts 和 tests;现有方法签名不变。
|
||||
- 消费者:本阶段只有 focused tests,阶段 6A 才接入 production application use case。
|
||||
- 兼容性:公开 HTTP/SSE、Controller DTO、数据库、Redis key schema 和旧 Chat/AiOps 路径不变。
|
||||
|
||||
## Commit Gate Preflight
|
||||
|
||||
- proposal、design、specs、tasks 完整,`openspec status` 为 complete,`openspec validate single-react-evidence-semantic-guards --strict` 通过。
|
||||
- Question pool 全部为已汇报的 evidence-driven 结论;无未确认 user-interview、接口等级或风险接受问题。
|
||||
- Cross-artifact 四段对齐无 gap;架构审计的数据所有权、模型取消和唯一报告作者约束已进入 design/spec/tasks。
|
||||
- 接口影响为 L2,仅新增内部 Java API;公开 Controller/SSE/JPA/Redis schema/旧 ChatService 保持不变。
|
||||
- Apply、Archive 和阶段 Git commit 使用用户对 ISS-014 各阶段的持续授权;实现必须严格限制为 Committed OpenSpec。
|
||||
- `.committed` 已创建,Committed OpenSpec 可进入 Apply。
|
||||
|
||||
## Pre-apply Research
|
||||
|
||||
### Reference Implementations
|
||||
|
||||
- `harness/tool/store/CanonicalInvocationStore.java`、`CanonicalToolInvocation.java`、`ToolCallKeyFactory.java`:当前 Run 物理验真和 lifecycle 真理源。
|
||||
- `harness/tool/projection/RagResultProjector.java`、`QueryLogsResultProjector.java`、`harness/tool/mysql/MysqlResultProjector.java`:三类 `agent_result` 的唯一生产者和有界字段来源。
|
||||
- `harness/agent/HarnessModelInterceptor.java`:模型调用前预算、响应 Usage 记账和 late-result active check 模式。
|
||||
- `harness/retry/HarnessRetryExecutor.java`、`HarnessRetryPolicies.java`:SemanticGuard 两次技术 attempt 与 repair 一次 attempt 的装配边界。
|
||||
- `harness/core/RunCancellation.java`:取消 callback 注册和 first-cancel 语义。
|
||||
- `service/ExecutorGatekeeperService.java`:仅参考报告内部引用检查思想,不复用旧 Map/JPA/session DTO 或规则目录。
|
||||
|
||||
### Technology Stack
|
||||
|
||||
- Jackson strict `ObjectReader` 解析 frozen Draft/Tool projections;Tool-specific adapter 生成 typed snapshot,不透传 JsonNode/raw response。
|
||||
- Spring AI `ChatModel.call(Prompt)` 执行无 Tool 单轮 guard;`ChatResponseMetadata.Usage` 接入现有 Core Token 预算。
|
||||
- Java 17 `ExecutorService/Future.get(timeout)` 提供 per-attempt timeout,`Future.cancel(true)` 接入 Run cancellation;Semantic 总时限由 monotonic elapsed time 控制。
|
||||
- JUnit 5 scripted `ChatModel` 和 in-memory canonical store 作为外部边界 fake;测试只通过 EvidenceGuard/SemanticGuard/Release use case 公共接口断言行为。
|
||||
- 无 Controller、MQ、JPA、Flyway 或新 Maven dependency;不需要新共享基础设施。
|
||||
|
||||
## Apply Progress
|
||||
|
||||
- 首模块对齐:EvidenceGuard typed contracts、Draft/reference checks、current-Run canonical validation 和 RAG/log/MySQL snapshot adapters 已完成,tasks 1.1-1.4 完成。
|
||||
- 8 个 `EvidenceGuardTest` 行为测试通过;快照序列化不含 Tool Call ID 或 `raw_response`,`NO_EVIDENCE` 仅在 `NEGATIVE_OBSERVATION` 下进入带 scope/zero-match 的快照。
|
||||
- TODO:tasks 2.1-4.2,尚未实现模型边界、SemanticGuard、repair/release 和综合回归。
|
||||
- REVIEW 发现 corrupted Store key 下 record ID 可能与 Draft reference 不同;分类为代码偏离,已增加 exact canonical ID 校验和回归测试,无需改变规格方向。
|
||||
- REVIEW 发现 fallback `DiagnosisReleaseResult` 携带完整 snapshot 会通过 `analysis_text` 间接泄漏 Draft;分类为规格安全边界细化,已回写 design/spec,并让 fallback result 强制使用空 snapshot,安全来源只保留在 `SafeFallback.verified_sources`。
|
||||
|
||||
## Apply Result
|
||||
|
||||
- 新增确定性 EvidenceGuard:校验 typed Draft、唯一 Analysis ID、报告引用、exact current-Run Tool ID、READY lifecycle、agent result、Evidence Status 与 Analysis Kind,并严格展开 RAG/log/MySQL projection。
|
||||
- verified snapshot 按 Analysis ID 分组,只含稳定 source/scope/timestamp/excerpt/values;SemanticGuard 输入不含 Tool Call ID、Redis key 或 raw response。
|
||||
- 新增共享 `GuardModelCall`:复用系统 ChatModel,执行 Core model/Token/Run byte budget、per-attempt timeout、total timeout、Future cancellation 和 late-result active check。
|
||||
- 新增无 Tool/无记忆/无 ReAct 的单轮 SemanticGuard,严格解析 `SUPPORTED|UNSUPPORTED + reason`;仅技术失败使用既有两次 attempt,业务 UNSUPPORTED 不重试。
|
||||
- 新增一次 EvidenceRepair,只允许 ID/reference 修复;任何可见文本、kind、顺序、human-confirmation 或 limitations 变化都直接 Evidence fallback。
|
||||
- 新增 DiagnosisReleaseUseCase 和固定 SafeFallbackFactory:SUPPORTED 原样返回 Draft;evidence failed、semantic unsupported/unavailable 均不返回 Draft、完整 snapshot 或审计 reason。
|
||||
- 公开 Controller、ChatService、AiOpsService、SSE、JPA/Flyway 和旧多 Agent 链路无修改。
|
||||
|
||||
## Apply Verification
|
||||
|
||||
- 编译:`mvn -q -DskipTests compile` 通过。
|
||||
- 阶段 5 focused:`EvidenceGuardTest` 9、`SemanticGuardTest` 4、`DiagnosisReleaseUseCaseTest` 6,共 19 tests,0 failure/error。
|
||||
- 综合回归:阶段 5 + Harness Core/Retry/Tool boundary/store/projections/contracts + Diagnosis Agent,共 18 suites / 70 tests,0 failure/error/skipped。
|
||||
- OpenSpec:`openspec validate single-react-evidence-semantic-guards --strict` 通过。
|
||||
- 静态范围:公开 Controller/ChatService/AiOpsService diff 为空;SemanticGuard 无 Tool ID/raw response/ReactAgent/StateGraph/ThreadLocal/手写 while;新 guard/release 包无业务 Agent loop。
|
||||
- 仓库级 `openspec validate --specs --strict` 为 16 passed / 2 failed;失败仍是前序 `mysql-readonly-tool`、`rag-log-projections` 的 scenario 标题格式,按计划阶段 7 统一修复。
|
||||
- 未执行 live E2E:按 ISS-014 阶段门禁统一留到阶段 7。
|
||||
|
||||
## Archive Result
|
||||
|
||||
- 14/14 OpenSpec tasks 完成,`.archive-ready` 已创建。
|
||||
- 主规格已同步至 `openspec/specs/single-react-evidence-semantic-guards/spec.md`,新增 9 个 requirements。
|
||||
- Change 已归档至 `openspec/changes/archive/2026-07-21-single-react-evidence-semantic-guards`。
|
||||
- `devflow/index.md` 和 ISS-014 阶段表已更新为阶段 0-5 archived,下一阶段为 6A。
|
||||
- 未创建 ADR/compound knowledge:本阶段落实 ISS-014 已冻结边界,没有新的跨项目难逆转决策。
|
||||
@@ -1,29 +0,0 @@
|
||||
# Evidence: single-react-evidence-semantic-guards
|
||||
|
||||
## Code and Contract Evidence
|
||||
|
||||
- `CanonicalInvocationStore` 只提供 key lookup;`ToolCallKeyFactory` 冻结 `runId + toolCallId` 隔离,`CanonicalToolInvocation` 冻结 READY/agent_result/evidence status 可引用条件。
|
||||
- `RagToolResult`、`QueryLogsToolResult`、`MysqlToolResult` 是 Agent-facing 有界 projection,足以构造 snapshot;只有 MySQL 的逻辑数据源/SQL/params 需要从 canonical request 补足。
|
||||
- `AnalysisKind.accepts` 已冻结 `NORMAL -> EVIDENCE_FOUND`、`NEGATIVE_OBSERVATION -> NO_EVIDENCE`。
|
||||
- `HarnessRetryPolicies.strict()` 已冻结 SemanticGuard 两次技术 attempt 和 Evidence repair 一次 attempt。
|
||||
- `ChatModel.call(Prompt)`、`ChatResponseMetadata.Usage` 和 `RunCancellation.onCancel` 支持直接单轮模型调用、Token 记账与 Future cancellation,无需 ReactAgent。
|
||||
|
||||
## Confirmed Boundaries
|
||||
|
||||
- EvidenceGuard 不判断证据是否支持结论,只验证结构、引用和物理真实性。
|
||||
- SemanticGuard 只接收原始 Query、移除 Tool ID 的完整 Draft view 和 verified snapshot,不访问 Redis/raw response。
|
||||
- Evidence repair 只修改 ID/reference;用户可见语义发生任何变化即失败。
|
||||
- `UNSUPPORTED` 是有效业务结果,不重试;只有 timeout/transport/parse/schema 技术失败可进行第二次 attempt。
|
||||
- Fallback 不含 Draft、完整 snapshot 或 SemanticGuard reason;Evidence failure 的 verified sources 为空。
|
||||
|
||||
## Review Findings
|
||||
|
||||
- 增加 canonical record ID 与 Draft reference 的 exact match,防止 corrupted key 映射被误信任。
|
||||
- Fallback release result 强制使用空 snapshot,防止 `analysis_text` 通过误序列化泄漏 Draft;安全来源只保留在 `SafeFallback.verified_sources`。
|
||||
|
||||
## Verification Evidence
|
||||
|
||||
- Stage-focused: 19 tests,覆盖 EvidenceGuard 9、SemanticGuard 4、DiagnosisReleaseUseCase 6。
|
||||
- Regression: 18 suites / 70 tests,0 failure/error/skipped。
|
||||
- Maven compile 和 change strict validation 通过。
|
||||
- 公开 Controller/ChatService/AiOpsService 零 diff;SemanticGuard 无 Tool ID/raw/ReactAgent/Graph/ThreadLocal/手写 loop。
|
||||
@@ -1,45 +0,0 @@
|
||||
# Acceptance: single-react-harness-run-context
|
||||
|
||||
## 实现结果
|
||||
|
||||
- 新增显式 `RunContext`、取消信号、deadline 检查、Run Lifecycle 和 first-terminal-wins。
|
||||
- 新增 caller-supplied limits、线程安全 Model/Tool/Token/Run bytes 预算和容量 CAS。
|
||||
- 新增 strict typed retry policies/executor,记录每个实际 attempt 并阻止取消/预算异常误重试。
|
||||
- 新增无 Redis 依赖的 ToolCallKeyFactory,精确保留框架 Tool Call ID。
|
||||
- Spring AI `spring.ai.retry.max-attempts` 设置为 1;未修改 provider/model routing。
|
||||
- 未接入旧 Chat/AIOps/Controller、ThreadLocal、JPA、Redis、Agent 或公开协议。
|
||||
|
||||
## 静态验证
|
||||
|
||||
- `openspec validate single-react-harness-run-context --strict`:通过。
|
||||
- 新 Harness 包 `rg`:无 ThreadLocal/current-holder/Redis 引用。
|
||||
- 旧 Chat/AIOps/Controller/JPA 调用链 diff:为空。
|
||||
- 受保护配置检查:仅新增 `spring.ai.retry.max-attempts: 1`,model routing/provider 保持不变。
|
||||
|
||||
## 脚本验证
|
||||
|
||||
- `mvn -q -DskipTests compile`:通过。
|
||||
- Core focused suite:通过。
|
||||
- 综合回归 suite(阶段 0/1 契约 + 阶段 2 Core + ChatController):通过。
|
||||
|
||||
## 浏览器/人工验证
|
||||
|
||||
- 不适用。本阶段没有 UI、Controller、SSE 或公开协议变化。
|
||||
|
||||
## 未验证
|
||||
|
||||
- 未执行真实模型调用、Redis、CLS、MySQL 或客户端断开 live E2E;这些属于后续 Tool store/adapter/最终 E2E 门禁。
|
||||
- 未将 RunContext 接入旧 ChatService;这是本阶段明确非目标,阶段 6A 才接入。
|
||||
- `RunContext` 取消对已进入的同步第三方调用仍是协作式;实际 HTTP/JDBC future 取消留给后续 adapter。
|
||||
- Provider 侧凭据轮换状态不由仓库证明。
|
||||
|
||||
## 剩余风险与后续门禁
|
||||
|
||||
- 关闭 SDK 隐式 retry 会使旧路径瞬时错误不再自动重试,直到后续 Router/SemanticGuard 接入 Harness;该变化已记录并可通过恢复配置回滚。
|
||||
- 下一阶段 3A 必须在 ToolInterceptor 接收 RunContext 和框架 Tool Call ID,直接复用 Key/Capacity/Cancellation 门禁。
|
||||
|
||||
## 状态
|
||||
|
||||
- Stage acceptance: accepted
|
||||
- OpenSpec archive: archived at `openspec/changes/archive/2026-07-21-single-react-harness-run-context`
|
||||
- Main spec sync: `openspec/specs/diagnosis-harness-run-context/spec.md`(8 added requirements)
|
||||
@@ -1,32 +0,0 @@
|
||||
# Brief: single-react-harness-run-context
|
||||
|
||||
## 背景
|
||||
|
||||
旧 Chat/AIOps 通过多个 ThreadLocal 和业务方法内状态机传播 session/run/token/retry,无法成为后续 Tool、Agent、Guard 和新入口的稳定共同边界。Spring AI 默认 10 attempts 还会制造未被 Harness 记录的隐藏重试。
|
||||
|
||||
## 目标
|
||||
|
||||
- 建立显式、结构不可变、可异步传播的 RunContext。
|
||||
- 集中实现 deadline、协作式取消、线程安全预算和唯一 Run 终态。
|
||||
- 实现类型化、最多两次 attempt、逐 attempt 记录的 Harness retry。
|
||||
- 提供阶段 3A 可直接使用的 Tool Call Key Factory 和单 Run 容量计数器。
|
||||
- 将 Spring AI 底层 retry 压为一次。
|
||||
|
||||
## 范围
|
||||
|
||||
- 新增 Harness Core/Retry/Tool Store foundation 类型和 focused Fake tests。
|
||||
- 更新 `application.yml` 的 Spring AI retry 配置。
|
||||
- 更新 glossary 和 OpenSpec/devflow 档案。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不接入旧 ChatService/AiOpsService/Controller/SSE。
|
||||
- 不读写现有 ThreadLocal,不删除旧实现。
|
||||
- 不写 `diagnosis_run` 或 Redis,不实现 Tool projection。
|
||||
|
||||
## 元数据
|
||||
|
||||
- 分档:complex
|
||||
- 接口影响:L2;另有关闭旧 SDK 隐式 retry 的有意内部行为变化
|
||||
- 关联 Issue:ISS-014 阶段 2
|
||||
- 关联 OpenSpec:`openspec/changes/single-react-harness-run-context`
|
||||
@@ -1,110 +0,0 @@
|
||||
# Decisions: single-react-harness-run-context
|
||||
|
||||
## 规模与入口
|
||||
|
||||
- 分档:complex。
|
||||
- 入口:ISS-014 阶段 2;阶段 0/1 已分别由 Git commit `58c3910`、`4274f33` 固化并 Archive。
|
||||
- 目标:建立后续 Tool、Agent、Guard 和入口共同依赖的显式 Harness 运行边界,不接旧 ChatService。
|
||||
|
||||
## Context
|
||||
|
||||
- `devflow/index.md` 命中 design freeze、ACI contracts 和 session/run trace isolation。
|
||||
- 当前 `SessionContextHolder`、`VerifierContextHolder`、`TokenUsageHolder` 使用 ThreadLocal;新 Harness 禁止复用。
|
||||
- 当前 ChatService 自行生成 runId、写 `diagnosis_run`、执行两轮 retry loop 并在 finally 清理 ThreadLocal,职责与新 Harness 边界冲突。
|
||||
- `DiagnosisRun.status` 当前是字符串 `PENDING/RUNNING/SUCCESS/FAILED`;本阶段不修改实体或迁移,由后续应用用例映射。
|
||||
- Spring AI 1.1.7 `SpringAiRetryProperties` 的配置前缀是 `spring.ai.retry`,默认 `maxAttempts=10`。
|
||||
|
||||
## Question Pool
|
||||
|
||||
| 维度 | 问题 | 模式 | 证据与结论 | 状态 |
|
||||
|---|---|---|---|---|
|
||||
| 术语 | “不可变 RunContext”是否意味着预算/取消也不能变化? | evidence-driven | ISS 要求上下文不可变同时要求计数/取消/终态;采用结构不可变 record + 线程安全单 Run 状态句柄。 | 已解决并汇报 |
|
||||
| 术语 | Run 与 DiagnosisRun 是否在阶段 2 直接持久化绑定? | evidence-driven | 阶段 2 只建 Core,阶段 6A 才接应用用例;本阶段生命周期为内存执行真理,不改 JPA。 | 已解决并汇报 |
|
||||
| 边界 | 是否迁移旧 ThreadLocal/ChatService 调用? | evidence-driven | ISS 1109-1111 明确禁止 ThreadLocal 和旧 ChatService 临时适配;只新增零消费者 Core。 | 已解决并汇报 |
|
||||
| 边界 | 取消是否承诺立即中断同步模型调用? | evidence-driven | 阶段 0 已确认分层取消;阻止后续边界并执行资源回调,不承诺不可证明的硬中断。 | 已解决并汇报 |
|
||||
| 验收 | 唯一终态如何证明? | evidence-driven | atomic first-terminal-wins lifecycle,并用取消/预算/异常/成功竞态测试证明后续终态不能覆盖。 | 已解决并汇报 |
|
||||
| 验收 | 异步传播如何证明不依赖 ThreadLocal? | evidence-driven | Fake Tool 在 `CompletableFuture` 线程只接收显式 RunContext,并验证相同 session/run/state handles。 | 已解决并汇报 |
|
||||
| 技术 | 隐藏重试如何关闭? | evidence-driven | 本地依赖 `SpringAiRetryProperties` 证实 `spring.ai.retry.max-attempts` 默认 10;配置改为 1 并加配置测试。 | 已解决并汇报 |
|
||||
| 技术 | 尚未校准的预算默认值如何处理? | evidence-driven | ISS 要求集中配置且不伪造数值;Core 接受显式 limits,不内置默认预算,后续 Spring wiring 决定配置值。 | 已解决并汇报 |
|
||||
| 技术 | Tool Call Key 是否生成 Tool ID? | evidence-driven | 阶段 0/1 冻结框架 ID;Factory 仅验证安全 segment 并拼接,不生成或改写。 | 已解决并汇报 |
|
||||
|
||||
## Grill 结论
|
||||
|
||||
- 术语、边界、验收和技术问题均可由已确认 ISS、现有代码和本地依赖 API 证明。
|
||||
- 没有新的产品偏好、公开协议或风险接受度问题需要 `user-interview`;短期关闭旧 SDK retry 的影响已在 proposal 明示。
|
||||
- `grill-with-docs` 的代码可证问题已先查证并向用户汇报;所有结论均已回写 proposal。
|
||||
|
||||
## 能力与工具限制
|
||||
|
||||
- Discover 能力来源:`sm-flow` + `grill-with-docs`。
|
||||
- 当前工具集没有 `codebase-retrieval` 和 LSP;使用 `rg`、源码阅读、本地依赖 `jar/javap`、编译和 focused tests 补足调用链与 API 核对。
|
||||
|
||||
## Cross-artifact 对齐
|
||||
|
||||
| 链路 | 状态 | 结论 |
|
||||
|---|---|---|
|
||||
| brief 目标/范围/非目标 -> proposal | 已对齐 | 显式 context、Core、预算/取消/终态、retry、key/capacity、隐藏 retry 和不接旧 runtime 全部覆盖。 |
|
||||
| proposal 范围/约束/承诺 -> design | 已对齐 | 类职责、并发语义、first-wins、配置变化、迁移和回滚均有明确设计。 |
|
||||
| design 决策/接口影响/风险 -> specs/tasks | 已对齐 | 每个状态边界都有 scenario,配置行为变化和 zero-consumer 边界有独立任务与验证。 |
|
||||
| specs 可观察行为 -> tasks | 已对齐 | 8 条 requirements 分解为 primitives、budget、Core、retry、key、配置和三层验证。 |
|
||||
|
||||
## Architecture Audit
|
||||
|
||||
- 能力来源:`zoom-out`,使用 glossary 的 RunContext、Run Lifecycle、Run Budget、Harness Retry Policy 和 Diagnosis Run 术语。
|
||||
- 输入链路为未来 application use case 创建 RunContext,处理链路由 Core/Retry/Key/Capacity 通过显式参数消费,输出为唯一 RunTermination;当前 runtime 不接入。
|
||||
- RunContext 拥有单 Run 内存状态,应用用例拥有数据库映射,Tool store 拥有 Redis invocation;数据所有权没有重叠。
|
||||
- Core 不保存全局 Run map、不调用 Agent/数据库/Redis、不实现循环编排,因此不会演变为工作流引擎。
|
||||
- 最大风险是关闭 SDK retry 对旧路径的短期行为影响;已作为显式配置变更进入 proposal/spec/test 和回滚说明,无 ADR 冲突。
|
||||
|
||||
## Commit Gate Preflight
|
||||
|
||||
- proposal、design、specs、tasks 完整,OpenSpec status complete,strict validation 通过。
|
||||
- question pool 无未汇报 evidence-driven 结论、无未确认 user-interview 问题。
|
||||
- 接口影响 L2;`spring.ai.retry.max-attempts=1` 的有意内部行为变化已明确影响和回滚边界。
|
||||
- cross-artifact 四段对齐无 gap,架构审计约束已进入 design/spec/tasks。
|
||||
- Apply 持续授权已存在;执行范围严格限制为新 Harness foundation、配置 override 和 focused tests。
|
||||
|
||||
## Pre-apply Research
|
||||
|
||||
### 参考实现与反例
|
||||
|
||||
- `SessionContextHolder`:ThreadLocal session/run fallback,新 Harness 明确禁止复用。
|
||||
- `TokenUsageHolder` / `TokenTrackingChatModel`:当前只记录 total token 且依赖 ThreadLocal,后续 model boundary 应改为显式 RunBudget;本阶段不改旧类。
|
||||
- `ChatService.executeChatComplex`:当前业务方法内创建 Run、两轮 retry、写终态和清理 ThreadLocal,是后续替换对象,不是 Core 参考实现。
|
||||
- `DiagnosisRun`:现有持久化字段和字符串状态;本阶段只确认映射边界,不修改实体或 Repository。
|
||||
- Spring AI 1.1.7 `SpringAiRetryProperties`:`spring.ai.retry` 前缀、默认 `maxAttempts=10`,支持精确配置 override。
|
||||
|
||||
### 技术栈清单
|
||||
|
||||
- Java 17 record 表达结构不可变 context/limits/snapshot/policy/attempt。
|
||||
- `AtomicReference` 实现 first-reason/first-terminal-wins;`AtomicLong` 实现 capacity CAS;同步临界区维护复合预算一致性。
|
||||
- `Clock` 和 `Supplier<String>` 注入保证 deadline/ID 可测试,不引入 scheduler 或全局 registry。
|
||||
- SLF4J 只记录取消 callback 异常,不记录用户输入、Tool payload 或凭据。
|
||||
- SnakeYAML 直接解析 classpath `application.yml` 验证 retry override,不启动外部 MySQL/Redis/Milvus/模型。
|
||||
|
||||
### 新建基础设施
|
||||
|
||||
- `harness.core`:RunContext、Cancellation、Lifecycle、Budget、Capacity、Core 和类型化异常/状态。
|
||||
- `harness.retry`:RetryFailure/Policy/Policies/Attempt/Executor/Exception 与函数接口。
|
||||
- `harness.tool.store.ToolCallKeyFactory`:纯 Key 构造,不访问 Redis。
|
||||
- focused unit tests 与 Fake Model/Tool;无需新 Maven 依赖。
|
||||
|
||||
### 影响半径
|
||||
|
||||
- 新生产包在本阶段保持零消费者。
|
||||
- 唯一现有运行配置变化为 `spring.ai.retry.max-attempts=1`;Model 路由、provider、Controller、JPA 和 Redis 配置保持不变。
|
||||
|
||||
## Apply 结果
|
||||
|
||||
- 冲突分类:未发现 OpenSpec 遗漏、代码偏离或方向不确定项;一次自审发现 RetryExecutor 需要无条件拦截预算/取消异常,已回写代码并通过回归测试。
|
||||
- 新增 `RunContext`、Cancellation、Lifecycle、Budget、Capacity、DiagnosisHarnessCore、typed Retry 和 ToolCallKeyFactory;未接旧 Chat/AIOps/Controller/Redis/JPA。
|
||||
- Spring AI 全局 retry 已由默认 10 压为 1;Harness strict policies 只允许 Router/SemanticGuard 技术失败一次显式重试。
|
||||
- 首模块对齐:Run state/budget/Core/retry/key/config 与 design/tasks 全部完成;Tool interceptor/store/Agent/应用用例仍留给后续阶段。
|
||||
|
||||
## Apply 验证
|
||||
|
||||
- 编译:`mvn -q -DskipTests compile`:通过。
|
||||
- Core focused:`mvn -q '-Dtest=RunContextTest,RunBudgetTest,DiagnosisHarnessCoreTest,HarnessRetryExecutorTest,ToolCallKeyFactoryTest,SpringAiRetryConfigurationTest' test`:通过(加固后复跑通过)。
|
||||
- 综合回归:`mvn -q '-Dtest=HarnessContractTest,RagToolContractTest,QueryLogsToolContractTest,MysqlToolContractTest,RunContextTest,RunBudgetTest,DiagnosisHarnessCoreTest,HarnessRetryExecutorTest,ToolCallKeyFactoryTest,SpringAiRetryConfigurationTest,ChatControllerTest' test`:通过。
|
||||
- 静态 scope:新 Harness 包无 ThreadLocal/current-holder/Redis 引用;旧 Chat/AIOps/Controller/JPA 调用链 diff 为空;模型路由/provider 未改。
|
||||
- OpenSpec:`openspec validate single-react-harness-run-context --strict`:通过。
|
||||
@@ -1,25 +0,0 @@
|
||||
# Evidence: single-react-harness-run-context
|
||||
|
||||
## 文档与依赖证据
|
||||
|
||||
- ISS-014 4.2/阶段 2 要求显式 `RunContext`、deadline、取消、预算、retry、Key Factory 和 no-ThreadLocal 边界。
|
||||
- 阶段 0/1 OpenSpec 已冻结框架 `tool_call_id`、两套状态语义和后续阶段串行门禁。
|
||||
- 本地 Spring AI 1.1.7 `SpringAiRetryProperties` 的 `@ConfigurationProperties("spring.ai.retry")` 默认 `maxAttempts=10`;配置已覆盖为 1。
|
||||
|
||||
## 代码证据
|
||||
|
||||
- `SessionContextHolder`、`TokenUsageHolder`、`VerifierContextHolder` 当前是旧链路 ThreadLocal;新 `com.superbiz.agent.harness` 包无任何 holder/ThreadLocal/Redis 引用。
|
||||
- `ChatService.executeChatComplex` 当前自行创建 run、执行两轮 retry、写 `diagnosis_run` 和清理 ThreadLocal;新 Core 不接入该方法,后续应用用例负责迁移。
|
||||
- `DiagnosisRun` 仍保留现有字符串状态和 JPA Schema;阶段 2 未修改实体、Repository 或数据库。
|
||||
- `DiagnosisHarnessCore` 不保存全局 Run map;RunContext 结构不可变,Cancellation/Budget/Lifecycle 为同一 Run 的线程安全句柄。
|
||||
|
||||
## Evidence-driven 结论
|
||||
|
||||
- first-reason-wins cancellation + first-terminal-wins lifecycle 可以用 AtomicReference 实现并跨异步边界共享。
|
||||
- 复合 Tool/Token 预算需要同步一致性;Run bytes 用 CAS 预留避免并发超限或部分增长。
|
||||
- SDK 隐藏 retry 压为一次后,Harness 才能记录 Router/SemanticGuard 的显式 attempt;Tool/Diagnosis/Evidence repair 固定一次。
|
||||
- Key Factory 可直接复用阶段 3A,但不生成或改写框架 Tool Call ID,也不访问 Redis。
|
||||
|
||||
## 工具限制
|
||||
|
||||
- `codebase-retrieval` 和 LSP 不在当前工具集中;使用 `rg`、源码阅读、`jar/javap`、Maven 编译、YAML 解析和 focused tests 补足核对。
|
||||
@@ -1,26 +0,0 @@
|
||||
# Acceptance: single-react-mysql-readonly-tool
|
||||
|
||||
## Commit preflight
|
||||
|
||||
- OpenSpec strict validation: passed.
|
||||
- Scope: fail-closed SQL validator, exact allowlist, JDBC read-only executor, bounded MySQL projection, ToolBoundary adapter and query-script safety cleanup.
|
||||
- Non-goals: public Agent/Chat cutover, metadata discovery, Agent persistence database access, dynamic/tenant authorization and live production datasource provisioning.
|
||||
- Security prerequisite: script write branch/default external connection values are explicitly included in this change.
|
||||
|
||||
## Apply acceptance
|
||||
|
||||
- Implemented and verified.
|
||||
- Static, Maven and script evidence is recorded in `evidence.md`.
|
||||
- No browser/manual verification applies; this stage adds no UI or public protocol change.
|
||||
- Residual risk is limited to later live datasource provisioning/driver behavior and stage 4 integration.
|
||||
|
||||
## Archive acceptance
|
||||
|
||||
- All OpenSpec tasks are complete.
|
||||
- `.archive-ready` marker is created after focused verification.
|
||||
- OpenSpec is ready to move to the dated archive directory.
|
||||
- Archive completed at `openspec/changes/archive/2026-07-21-single-react-mysql-readonly-tool`.
|
||||
|
||||
## Remaining work
|
||||
|
||||
- Stage 4 Diagnosis Agent integration and later live datasource/driver E2E remain outside this archive.
|
||||
@@ -1,26 +0,0 @@
|
||||
# Brief: single-react-mysql-readonly-tool
|
||||
|
||||
## Background
|
||||
|
||||
阶段 3A 提供了统一 ToolBoundary 和 canonical invocation store,阶段 3B 提供了 RAG/日志投影。3C 需要独立实现安全敏感的只读 MySQL Tool,避免 Agent 生成的 SQL 直接进入数据库。
|
||||
|
||||
## Goals
|
||||
|
||||
- 使用 JSqlParser 对保守 SELECT 子集进行 fail-closed AST 校验。
|
||||
- 使用逻辑数据源和 schema/table/column 精确 allowlist 授权。
|
||||
- 使用参数绑定、只读 JDBC、超时、取消和结果预算。
|
||||
- 通过阶段 3A boundary 投影为冻结的 `MysqlToolResult`。
|
||||
- 清理查询脚本的写入分支和默认连接风险。
|
||||
|
||||
## Non-goals
|
||||
|
||||
- 不接入公开 Agent/Chat 入口。
|
||||
- 不提供元数据发现、动态授权、租户/行级权限或生产 datasource provisioning。
|
||||
- 不查询 Agent 自身持久化数据库。
|
||||
|
||||
## Classification
|
||||
|
||||
- Scale: complex
|
||||
- Interface impact: L2 internal Harness tool/adapter, plus build dependency and script safety behavior
|
||||
- Issue: ISS-014 stage 3C
|
||||
- Change slug: `single-react-mysql-readonly-tool`
|
||||
@@ -1,108 +0,0 @@
|
||||
# Decisions: single-react-mysql-readonly-tool
|
||||
|
||||
## Discover status
|
||||
|
||||
- Checkpoint: Discover
|
||||
- Capability source: `sm-flow` with local ISS-014, OpenSpec contracts, existing JDBC dependency/configuration and JSqlParser 4.6 already present in the local Maven cache.
|
||||
- Scale: complex, because this stage combines AST policy, authorization, JDBC resource limits, projection, and security cleanup.
|
||||
|
||||
## Evidence-driven findings
|
||||
|
||||
1. `MysqlToolRequest` and `MysqlToolResult` are already frozen under `harness.tool.contract`; no public DTO change is needed.
|
||||
2. The project already has MySQL JDBC/JPA dependencies, but no Agent-facing external read-only executor or SQL policy.
|
||||
3. JSqlParser 4.6 is available in the local Maven cache and exposes `CCJSqlParserUtil`, `Select`, `PlainSelect`, `Table`, `Column`, `Function`, `JdbcParameter` and visitor adapters compatible with Java 17.
|
||||
4. The current application datasource points to the Agent persistence database; the new Tool must use an independently configured logical datasource map and must not reuse that datasource implicitly.
|
||||
5. `scripts/query_mysql.py` currently defaults host/port/user values and contains a non-SELECT commit branch. This violates the ISS-014 security prerequisite and will be changed to read-only, environment-only behavior.
|
||||
|
||||
## Question pool
|
||||
|
||||
| Dimension | Question | Mode | Conclusion | Status |
|
||||
|---|---|---|---|---|
|
||||
| SQL language | Which SQL subset is executable? | evidence-driven | One SELECT, explicit columns, INNER/LEFT JOIN, predicates/group/order, parameter placeholders and allowlisted aggregates. | resolved |
|
||||
| Security | How is authorization decided? | evidence-driven | Independent exact schema/table/column allowlist; parser acceptance alone is insufficient. | resolved |
|
||||
| Data source | Can the Agent pass JDBC coordinates? | evidence-driven | No. Only logical data_source IDs are accepted; connection properties remain configuration/Secret data. | resolved |
|
||||
| Execution | Which JDBC controls are mandatory? | evidence-driven | PreparedStatement, readOnly connection, setMaxRows, query timeout and Run cancellation. | resolved |
|
||||
| Metadata | Can the Tool discover tables/columns? | evidence-driven | No. SHOW/DESCRIBE/information_schema are rejected. | resolved |
|
||||
| Compatibility | Does this cut over public runtime now? | evidence-driven | No. Add internal adapter/executor; Diagnosis Agent integration is stage 4. | resolved |
|
||||
|
||||
## User-confirmed direction
|
||||
|
||||
- Use the frozen `MysqlToolRequest`/`MysqlToolResult` contract.
|
||||
- Reuse the existing ToolBoundary and canonical invocation store.
|
||||
- Keep stage boundaries serial: archive and commit 3C before stage 4.
|
||||
- Do not pause for routine apply/archive/commit confirmation.
|
||||
|
||||
## Pre-apply research
|
||||
|
||||
### Existing implementations and dependencies
|
||||
|
||||
- `src/main/java/com/superbiz/agent/harness/tool/contract/MysqlToolRequest.java`
|
||||
- `src/main/java/com/superbiz/agent/harness/tool/contract/MysqlToolResult.java`
|
||||
- `src/main/java/com/superbiz/agent/harness/tool/boundary/ToolBoundary.java`
|
||||
- `src/main/java/com/superbiz/agent/harness/tool/adapter/QueryLogsToolAdapter.java`
|
||||
- `src/main/resources/application.yml`
|
||||
- `pom.xml` (`mysql-connector-j` already present; add JSqlParser 4.6)
|
||||
- `scripts/query_mysql.py`
|
||||
|
||||
### New classes
|
||||
|
||||
- `MysqlToolLimits`
|
||||
- `MysqlDataSourceDefinition` / allowlist value objects
|
||||
- `MysqlQueryPlan`
|
||||
- `MysqlSqlValidator`
|
||||
- `MysqlReadOnlyExecutor` and JDBC implementation
|
||||
- `MysqlResultProjector`
|
||||
- `MysqlToolAdapter`
|
||||
|
||||
### Risk controls
|
||||
|
||||
- Do not create a generic plugin/DSL layer.
|
||||
- Do not use regex or `startsWith` as SQL authorization.
|
||||
- Fail closed on parser/visitor uncertainty.
|
||||
- Keep raw result canonical-only and expose only bounded projection.
|
||||
|
||||
## Commit checkpoint preparation
|
||||
|
||||
- Proposal scope, design choices, frozen SQL subset, security script cleanup and acceptance scenarios are ready for Commit artifact generation.
|
||||
|
||||
## Commit audit
|
||||
|
||||
- Capability source: `sm-flow` and local OpenSpec CLI.
|
||||
- OpenSpec strict validation: passed for `single-react-mysql-readonly-tool`.
|
||||
- Cross-artifact alignment:
|
||||
- brief goals/non-goals -> proposal scope: aligned.
|
||||
- proposal SQL/security boundaries -> design architecture: aligned.
|
||||
- design validator/executor/projector decisions -> spec requirements: aligned.
|
||||
- spec scenarios -> tasks for dependency, policy, JDBC, projection, adapter and verification: aligned.
|
||||
- Interface impact: L2 internal Harness tool/adapter plus JSqlParser dependency and query-script behavior; no public protocol changes.
|
||||
- Preflight risk accepted: parser ambiguity, datasource isolation, driver cancellation behavior and sensitive result values all fail closed or remain Harness-only.
|
||||
|
||||
## Commit gate
|
||||
|
||||
- [x] proposal, design, specs and tasks exist.
|
||||
- [x] strict OpenSpec validation passes.
|
||||
- [x] all evidence-driven questions are resolved.
|
||||
- [x] no unresolved interface decision remains.
|
||||
- [x] `.committed` marker created for Apply.
|
||||
|
||||
## Apply result
|
||||
|
||||
- Added JSqlParser 4.6 and fail-closed `MysqlSqlValidator`.
|
||||
- Added immutable logical datasource/allowlist/limit/query-plan/raw-result models and independent `MysqlToolProperties` binding.
|
||||
- Added `JdbcMysqlReadOnlyExecutor` with read-only connection, PreparedStatement binding, query timeout, max rows, cell/result limits and Run cancellation callback.
|
||||
- Added `MysqlResultProjector` with sensitive-column redaction, row/cell/total UTF-8 bounds and `NO_EVIDENCE`.
|
||||
- Added `MysqlToolAdapter` through the existing ToolBoundary; invalid SQL is rejected before database execution.
|
||||
- Replaced `scripts/query_mysql.py` with environment-only, read-only transaction behavior and pre-connect write/metadata rejection.
|
||||
|
||||
## Apply conflicts and corrections
|
||||
|
||||
- `COUNT(*)` is represented by JSqlParser as an `AllColumns` parameter in this version; the visitor was corrected to permit only the explicit `COUNT(*)` exception.
|
||||
- JDBC metadata access cannot be used as a checked-exception stream method reference; the implementation uses an explicit column loop.
|
||||
- No OpenSpec/design conflict was found; both corrections were implementation details.
|
||||
|
||||
## Archive result
|
||||
|
||||
- Apply tasks complete and `.archive-ready` created.
|
||||
- OpenSpec archived at `openspec/changes/archive/2026-07-21-single-react-mysql-readonly-tool`.
|
||||
- Main capability specification added at `openspec/specs/mysql-readonly-tool/spec.md`.
|
||||
- Stage 4 may consume the internal adapter only after this stage is committed.
|
||||
@@ -1,29 +0,0 @@
|
||||
# Evidence: single-react-mysql-readonly-tool
|
||||
|
||||
## Static verification
|
||||
|
||||
- `git diff --check`: passed before archive.
|
||||
- Security scan confirms the query helper has no default external host/port/root user and no `commit()` write path.
|
||||
- New MySQL Harness code receives only injected logical DataSources and does not reference `spring.datasource` or the application persistence datasource.
|
||||
- OpenSpec strict validation passed for `single-react-mysql-readonly-tool`.
|
||||
|
||||
## Script/build verification
|
||||
|
||||
- `mvn -q -DskipTests compile`: passed.
|
||||
- Focused suite passed: `MysqlSqlValidatorTest`, `MysqlResultProjectorTest`, `JdbcMysqlReadOnlyExecutorTest`, `MysqlToolAdapterTest`, `MysqlToolContractTest`, `ToolBoundaryTest`, `CanonicalInvocationStoreTest`.
|
||||
- Python syntax compilation passed for `scripts/query_mysql.py`.
|
||||
- Missing connection environment variables exit before connection with code 2.
|
||||
- A write SQL invocation is rejected before connection with code 3.
|
||||
|
||||
## Security coverage
|
||||
|
||||
- Allowed: explicit allowlisted SELECT, parameter placeholders, qualified INNER JOIN and `COUNT(*)`.
|
||||
- Rejected: write, WITH, subquery, UNION, wildcard projection, unknown table/column, ambiguous column, dangerous function, inline literal, CASE, FOR UPDATE, multi-statement and placeholder mismatch.
|
||||
- JDBC controls verified: `setReadOnly(true)`, `PreparedStatement`, `setQueryTimeout`, `setMaxRows`, ordered parameter binding and cancellation-before-execution.
|
||||
- Projection controls verified: max rows, max cell chars, total UTF-8 bytes, sensitive-column redaction, valid bounded JSON and `NO_EVIDENCE`.
|
||||
|
||||
## Not verified in this stage
|
||||
|
||||
- No live production business datasource was provisioned or queried; ISS-014 explicitly assigns live E2E to a later issue/stage.
|
||||
- No public Diagnosis Agent/Chat integration was performed; stage 4 will consume the adapter internally.
|
||||
- JDBC driver timeout/cancel behavior against a real remote MySQL server remains an operational integration risk.
|
||||
@@ -1,25 +0,0 @@
|
||||
# Acceptance: single-react-rag-log-projections
|
||||
|
||||
## Commit preflight
|
||||
|
||||
- OpenSpec strict validation: passed.
|
||||
- Scope: RAG and Mock query-log projectors/adapters through the existing ToolBoundary.
|
||||
- Explicit non-goals: real CLS/MCP, MySQL, Diagnosis Agent cutover, public Chat/AIOps/SSE changes, legacy recorder cleanup.
|
||||
- Main residual risk: legacy log payloads contain sensitive values; projector tests must prove redaction before Agent serialization.
|
||||
|
||||
## Apply acceptance
|
||||
|
||||
- Implemented and verified.
|
||||
- Static verification and focused/regression Maven tests are recorded in `evidence.md`.
|
||||
- No browser/manual verification applies; this stage adds no UI or public protocol change.
|
||||
- Residual risks: live Redis/CLS integration and Agent cutover remain later stages.
|
||||
|
||||
## Archive acceptance
|
||||
|
||||
- `.archive-ready` marker is created after all tasks and checks pass.
|
||||
- OpenSpec is ready to move to the dated archive directory.
|
||||
- Archive completed at `openspec/changes/archive/2026-07-21-single-react-rag-log-projections`.
|
||||
|
||||
## Remaining work
|
||||
|
||||
- Real Redis/CLS integration, MySQL projection, Diagnosis Agent cutover and final E2E remain later stages.
|
||||
@@ -1,24 +0,0 @@
|
||||
# Brief: single-react-rag-log-projections
|
||||
|
||||
## Background
|
||||
|
||||
阶段 3A 已经统一 ToolBoundary 和 canonical invocation store。下一阶段需要把现有 RAG 与 Mock 日志工具接入该边界,并把旧工具输出投影为冻结的 Agent-facing ACI 结果。
|
||||
|
||||
## Goal
|
||||
|
||||
- 提供 bounded RAG evidence projection。
|
||||
- 提供带完整 logical scope 和 Mock provenance 的 query-log projection。
|
||||
- 复用阶段 3A 生命周期、Run ownership、tool_call_id、预算、错误和 canonical record。
|
||||
|
||||
## Non-goals
|
||||
|
||||
- 不接入真实 CLS/MCP。
|
||||
- 不实现 MySQL projection。
|
||||
- 不切换 Diagnosis Agent、Chat/AIOps、SSE 或旧 recorder。
|
||||
|
||||
## Classification
|
||||
|
||||
- Scale: complex
|
||||
- Interface impact: L2 internal Harness adapter/projector
|
||||
- Issue: ISS-014 stage 3B
|
||||
- Change slug: `single-react-rag-log-projections`
|
||||
@@ -1,72 +0,0 @@
|
||||
# Decisions: single-react-rag-log-projections
|
||||
|
||||
## Discover status
|
||||
|
||||
- Checkpoint: Discover
|
||||
- Capability source: `sm-flow` with `grill-with-docs` codebase evidence; no external service integration required.
|
||||
- Scale: complex, because two tool adapters share a lifecycle boundary and define bounded Agent-facing output semantics.
|
||||
|
||||
## Evidence-driven findings
|
||||
|
||||
1. `ToolBoundary` currently accepts `project(String rawResponse)` and already owns Run/ID/authorization/read-only/JSON/budget/lifecycle enforcement.
|
||||
2. `LookupKnowledgeTool` emits `evidenceBlocks`, `contextPack`, `retrievalTrace`, `rerankTrace`, session domains, and message; these are internal retrieval/audit fields and must not be projected.
|
||||
3. `QueryLogsTools` emits region, physical log topic, result limit, instance and metrics; the frozen contract requires logical topic/query/lookback scope and `source_kind=MOCK` instead.
|
||||
4. Existing ACI records already define the required snake_case fields and immutable collections.
|
||||
5. The request scope must be passed to the log projector through a typed adapter method rather than inferred from raw output.
|
||||
|
||||
## User-confirmed direction
|
||||
|
||||
- Use the framework-provided `tool_call_id` only.
|
||||
- Keep lifecycle status and evidence status separate.
|
||||
- Implement the stage in phases and complete sm-flow archive plus Git commit before the next stage.
|
||||
- Adopt the request-aware projector adapter for log scope preservation.
|
||||
|
||||
## Question pool
|
||||
|
||||
| Dimension | Question | Mode | Conclusion | Status |
|
||||
|---|---|---|---|---|
|
||||
| Terminology | Are RAG traces and context packs Agent evidence? | evidence-driven | No. They are internal retrieval/audit details and are excluded from projection. | resolved |
|
||||
| Boundary | How is log scope preserved when the generic projector has no request? | evidence-driven | Typed adapter carries `QueryLogsRequest` into a request-aware projector method. | resolved |
|
||||
| Provenance | Which log source is implemented now? | evidence-driven | Existing Mock source only; result always records `source_kind=MOCK`. | resolved |
|
||||
| Negative result | What does an empty query mean? | evidence-driven | `NO_EVIDENCE` for the recorded scope, with no health/problem inference. | resolved |
|
||||
| Compatibility | Should legacy tools and public paths be changed now? | evidence-driven | No. Add adapters/projectors only; cutover is later. | resolved |
|
||||
|
||||
## Risks
|
||||
|
||||
- Existing mock messages contain hostnames, pod IDs, SQL literals, and stack-like text; sanitization must happen before projection.
|
||||
- Collection limits and excerpt limits can make the Agent result incomplete; `truncated` must be explicit.
|
||||
- The generic boundary API should remain reusable for stage 3C, so request-aware behavior belongs in an adapter or specialized projector interface.
|
||||
|
||||
## Discover checkpoint
|
||||
|
||||
- Proposal created: `openspec/changes/single-react-rag-log-projections/proposal.md`
|
||||
- Context and issue evidence recorded.
|
||||
- No unresolved user-interview question remains for this bounded stage; implementation direction was explicitly accepted in the conversation.
|
||||
|
||||
## Commit audit
|
||||
|
||||
- Capability source: `sm-flow` and local OpenSpec CLI.
|
||||
- OpenSpec strict validation: passed for `single-react-rag-log-projections`.
|
||||
- Cross-artifact alignment:
|
||||
- brief goals/non-goals -> proposal scope: aligned.
|
||||
- proposal boundaries and request-aware projector decision -> design: aligned.
|
||||
- design projection bounds, redaction, scope and adapter ownership -> spec requirements: aligned.
|
||||
- spec scenarios -> tasks for limits, RAG, logs, boundary integration and verification: aligned.
|
||||
- Interface impact: L2 internal Harness adapter/projector only; no public protocol or legacy runtime cutover.
|
||||
- Preflight risks accepted: legacy payload drift fails closed; sensitive log fields are redacted; total projection budget is explicit.
|
||||
|
||||
## Commit gate
|
||||
|
||||
- [x] proposal, design, specs and tasks exist.
|
||||
- [x] strict OpenSpec validation passes.
|
||||
- [x] all evidence-driven questions are resolved.
|
||||
- [x] no unresolved interface decision remains.
|
||||
- [x] `.committed` marker created for Apply.
|
||||
|
||||
## Archive result
|
||||
|
||||
- Apply tasks complete.
|
||||
- `.archive-ready` marker created.
|
||||
- OpenSpec archived at `openspec/changes/archive/2026-07-21-single-react-rag-log-projections`.
|
||||
- Main capability specification added at `openspec/specs/rag-log-projections/spec.md`.
|
||||
- Next stage remains 3C MySQL projection; no Agent cutover is implied by this archive.
|
||||
@@ -1,25 +0,0 @@
|
||||
# Evidence: single-react-rag-log-projections
|
||||
|
||||
## Static verification
|
||||
|
||||
- `git diff --check`: passed.
|
||||
- Existing legacy files were checked and have no diff: `LookupKnowledgeTool`, `QueryLogsTools`, `ChatService`, `AiOpsService`, and `ToolInvocationRecorder`.
|
||||
- OpenSpec strict validation: passed for `single-react-rag-log-projections`.
|
||||
|
||||
## Script/build verification
|
||||
|
||||
- `mvn -q -DskipTests compile`: passed.
|
||||
- Focused projection tests: passed (`RagResultProjectorTest`, `QueryLogsResultProjectorTest`).
|
||||
- Adapter tests: passed (`ToolAdapterTest`).
|
||||
- Stage regression suite: passed (`CanonicalInvocationStoreTest`, `ToolBoundaryTest`, ACI/Core/retry/key/config/ChatController tests plus the new projection tests).
|
||||
|
||||
## Coverage
|
||||
|
||||
- RAG: bounded exact excerpts, duplicate document IDs, internal field exclusion, `NO_EVIDENCE`, truncation and framework ID.
|
||||
- Logs: logical scope, Mock provenance, pattern aggregation, timeline sampling, sensitive value redaction, empty result and bounded output.
|
||||
- Boundary: adapters use the existing canonical lifecycle and do not return raw payloads.
|
||||
|
||||
## Not verified in this stage
|
||||
|
||||
- Real Redis connectivity and live CLS/MCP integration.
|
||||
- Diagnosis Agent/application cutover and end-to-end Maven runtime flow.
|
||||
@@ -1,43 +0,0 @@
|
||||
# Acceptance: single-react-tool-invocation-store
|
||||
|
||||
## 实现结果
|
||||
|
||||
- 新增 canonical record/limits/exceptions/store interface/Redis JSON adapter。
|
||||
- 新增 ToolBoundary envelope/result、executor/projector interfaces 和稳定错误码。
|
||||
- 实现 preflight、Run/Tool budget、Run capacity、PROJECTING、READY/ERROR、evidence semantics、TTL 和 UTF-8 limits。
|
||||
- 旧 ToolInvocationRecorder、JPA、Chat/AIOps、Controller、Repository 和公开协议未修改。
|
||||
|
||||
## 静态验证
|
||||
|
||||
- `openspec validate single-react-tool-invocation-store --strict`:通过。
|
||||
- 新 Harness 包 Redis 引用仅为 `RedisCanonicalInvocationStore`。
|
||||
- legacy recorder/JPA/Chat/AIOps/Controller/repository/resources diff:为空。
|
||||
- staged diff check 与 Secret scan:提交前执行并通过。
|
||||
|
||||
## 脚本验证
|
||||
|
||||
- `mvn -q -DskipTests compile`:通过。
|
||||
- `mvn -q '-Dtest=CanonicalInvocationStoreTest,ToolBoundaryTest' test`:通过。
|
||||
- 综合阶段 0/1/2/3A suite(含 Harness/ACI/Core/retry/key/config/ChatController):通过。
|
||||
|
||||
## 浏览器/人工验证
|
||||
|
||||
- 不适用。本阶段没有 UI、Controller、SSE 或公开协议变化。
|
||||
|
||||
## 未验证
|
||||
|
||||
- 未连接真实 Redis,未做 ACL/network/TTL live 验证;最终 E2E 阶段执行。
|
||||
- 未接入 Alibaba ToolInterceptor,真实框架 ID 传播留给后续 Agent/application stage。
|
||||
- 未实现 RAG/log/MySQL projector,留给 3B/3C。
|
||||
- canonical update 的 read-TTL-write 并发窗口已记录为风险,尚未 Lua/CAS 化。
|
||||
|
||||
## 剩余风险与后续门禁
|
||||
|
||||
- 新旧 JPA audit 与 canonical store 短期并存,后续 projector 必须只以新 boundary 的 READY record 作为引用来源。
|
||||
- 下一阶段 3B/3C 必须复用本 ToolBoundary,不复制 Redis 状态机。
|
||||
|
||||
## 状态
|
||||
|
||||
- Stage acceptance: accepted
|
||||
- OpenSpec archive: archived at `openspec/changes/archive/2026-07-21-single-react-tool-invocation-store`
|
||||
- Main spec sync: `openspec/specs/canonical-tool-invocation-store/spec.md`(7 added requirements)
|
||||
@@ -1,29 +0,0 @@
|
||||
# Brief: single-react-tool-invocation-store
|
||||
|
||||
## 背景
|
||||
|
||||
旧 `ToolInvocationRecorder` 依赖 ThreadLocal 和 JPA preview,不能证明完整 Tool 结果、生命周期和当前 Run 所有权。阶段 2 已提供 RunContext/Key/Capacity,需要统一 canonical ToolBoundary 和 Redis store 供后续 projector 复用。
|
||||
|
||||
## 目标
|
||||
|
||||
- 统一 Pre-Tool 门禁、PROJECTING/READY/ERROR 状态和 evidence semantics。
|
||||
- 在同一 Redis record 保存 request/raw_response/agent_result、框架 ID、Run、时间和错误。
|
||||
- 固定 TTL 不续期、容量/结果大小 fail-closed、raw 不静默截断。
|
||||
- 用 Fake Tool/Projector/Store 覆盖 duplicate、cross-run、no-evidence、error、TTL 和 oversize。
|
||||
|
||||
## 范围
|
||||
|
||||
- Canonical invocation model/store、Redis JSON adapter、ToolBoundary 和 focused tests。
|
||||
- 复用阶段 2 Core、budget、capacity、ToolCallKeyFactory。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不实现 RAG/log/MySQL projector。
|
||||
- 不修改旧 recorder/JPA、Chat/AIOps、Controller/SSE 或公开协议。
|
||||
|
||||
## 元数据
|
||||
|
||||
- 分档:complex
|
||||
- 接口影响:L2 内部 Harness boundary/store
|
||||
- 关联 Issue:ISS-014 阶段 3A
|
||||
- 关联 OpenSpec:`openspec/changes/single-react-tool-invocation-store`
|
||||
@@ -1,106 +0,0 @@
|
||||
# Decisions: single-react-tool-invocation-store
|
||||
|
||||
## 规模与入口
|
||||
|
||||
- 分档:complex。
|
||||
- 入口:ISS-014 阶段 3A;阶段 0/1/2 已 Archive 并由 `58c3910`、`4274f33`、`6b74990` 提交。
|
||||
- 目标:统一 ToolBoundary 和 Redis canonical invocation store,不实现 Tool-specific projection。
|
||||
|
||||
## Context
|
||||
|
||||
- 阶段 1 主规格已冻结 RAG/log/MySQL Agent-facing Request/Result 和 `EvidenceStatus`。
|
||||
- 阶段 2 主规格已冻结 `RunContext`、预算、取消、Key Factory 和 strict retry。
|
||||
- 旧 `ToolInvocationRecorder` 依赖 `SessionContextHolder`、JPA `ToolInvocation` 和 500 字符 preview,属于 durable audit 兼容路径,不是 canonical store。
|
||||
- 既有 `SessionConfiguration` 提供 `RedisTemplate<String,Object>` + JSON serializer;新 store 复用 bean,不新增连接配置。
|
||||
|
||||
## Question Pool
|
||||
|
||||
| 维度 | 问题 | 模式 | 证据与结论 | 状态 |
|
||||
|---|---|---|---|---|
|
||||
| 术语 | canonical invocation 与旧 JPA ToolInvocation 是否同一记录? | evidence-driven | ISS-014 数据分层明确 Redis canonical 保存完整 request/raw/agent,JPA 只做 durable audit;两者分离。 | 已解决并汇报 |
|
||||
| 术语 | `PROJECTING/READY/ERROR` 与 evidence status 如何组合? | evidence-driven | 阶段 0/1 规格:只有 READY 可为 FOUND/NO_EVIDENCE,ERROR 不可引用;PROJECTING 是内部暂态。 | 已解决并汇报 |
|
||||
| 边界 | 阶段 3A 是否实现 RAG/log projector? | evidence-driven | ISS-014 3A 明确不实现 Tool-specific projection,3B/3C 单独接入。 | 已解决并汇报 |
|
||||
| 边界 | Redis 读取是否刷新 TTL? | evidence-driven | ISS-014 固定“创建设置、读取/更新不续期”;更新采用当前剩余 TTL,不恢复初始 TTL。 | 已解决并汇报 |
|
||||
| 验收 | raw 超限是否静默截断? | evidence-driven | ISS-014 明确 `RESULT_TOO_LARGE` ERROR,raw 不静默截断;agent projection 才可按 projector 预算截断并标记。 | 已解决并汇报 |
|
||||
| 验收 | 缺失/重复/cross-run ID 如何处理? | evidence-driven | 阶段 3A 任务明确覆盖;Key Factory 保留框架 ID,ToolBoundary 在 store 创建前校验 Run/ID 和 duplicate。 | 已解决并汇报 |
|
||||
| 技术 | Redis 如何避免 update 重置 TTL? | evidence-driven | 既有 RedisTemplate;begin 使用 setIfAbsent + TTL,update 先读取剩余 TTL 再写回相同/更短 TTL,get 不调用 expire。 | 已解决并汇报 |
|
||||
| 技术 | 是否修改旧 recorder 以复用新 store? | evidence-driven | 旧链路大量测试依赖 JPA preview/evidence_refs;本阶段零消费者,保持旧 recorder 不变,避免行为回归。 | 已解决并汇报 |
|
||||
|
||||
## Grill 结论
|
||||
|
||||
- 所有术语、边界、验收和技术问题均由 ISS、阶段规格、旧代码和 Redis 配置事实证明。
|
||||
- 没有新增产品偏好或兼容性取舍需要 user-interview;并发更新窗口作为已接受风险记录。
|
||||
- `grill-with-docs` 的代码可证结论已回写 proposal;没有未确认问题。
|
||||
|
||||
## 能力与工具限制
|
||||
|
||||
- Discover 能力来源:`sm-flow` + `grill-with-docs`。
|
||||
- 当前无 `codebase-retrieval`/LSP;使用 `rg`、源码、既有测试、本地 Redis 配置和 focused fake tests 进行等价核对。
|
||||
|
||||
## Cross-artifact 对齐
|
||||
|
||||
| 链路 | 状态 | 结论 |
|
||||
|---|---|---|
|
||||
| brief 目标/范围/非目标 -> proposal | 已对齐 | Boundary、canonical record、TTL/size、Fake tests 和 legacy isolation 全部覆盖。 |
|
||||
| proposal 范围/约束/承诺 -> design | 已对齐 | Redis value、状态机、preflight 顺序、raw/projection 和失败处理均已设计。 |
|
||||
| design 决策/接口影响/风险 -> specs/tasks | 已对齐 | L2 boundary、TTL 更新窗口、oversize/error、ID/Run 所有权有对应要求和任务。 |
|
||||
| specs 可观察行为 -> tasks | 已对齐 | 7 条 requirements 分解为 store、boundary、limits/failure 和隔离验证纵向切片。 |
|
||||
|
||||
## Architecture Audit
|
||||
|
||||
- 能力来源:`zoom-out`,按 RunContext、Invocation Status、Evidence Status、canonical invocation 和 durable audit 术语审计。
|
||||
- ToolBoundary 只编排一次调用;CanonicalInvocationStore 独占 Redis 状态转换;DiagnosisHarnessCore 独占 Run budget/cancellation;旧 recorder 只写 JPA audit。
|
||||
- request/raw/agent result 归同一 canonical record,Agent 只获得 ToolBoundaryResult,不存在 raw 旁路。
|
||||
- Redis adapter 是唯一 Redis 访问点,接口/Fake 不依赖 Redis;后续 3B/3C 可直接复用而不复制状态机。
|
||||
- 风险集中在 read-TTL-write 并发窗口和 canonical raw 敏感性,已进入 design/spec/limits,无架构或 ADR 冲突。
|
||||
|
||||
## Commit Gate Preflight
|
||||
|
||||
- proposal、design、specs、tasks 完整,OpenSpec status complete,strict validation 通过。
|
||||
- question pool 无未汇报 evidence-driven 或未确认 user-interview 项。
|
||||
- L2 内部接口影响已记录;旧 JPA/Chat/Controller/协议不改。
|
||||
- cross-artifact 无 gap,所有错误、TTL、size、ID/Run 所有权和隔离要求可由 Fake tests 验证。
|
||||
- Apply 已获持续授权,范围只包括新 store/boundary 与 focused tests。
|
||||
|
||||
## Pre-apply Research
|
||||
|
||||
### 参考实现与复用
|
||||
|
||||
- 复用 `DiagnosisHarnessCore` 的 active/deadline/Tool budget/Run bytes 门禁。
|
||||
- 复用 `ToolCallKeyFactory` 精确保留框架 Tool Call ID 并隔离 Run key。
|
||||
- 复用阶段 0 `InvocationStatus` / `EvidenceStatus`,不创建字符串状态副本。
|
||||
- 复用 `SessionConfiguration` 提供的 `RedisTemplate<String,Object>` 和 Spring Boot ObjectMapper。
|
||||
- 旧 `ToolInvocationRecorder`/JPA preview 仅作为 durable audit 反例,本阶段不修改或调用。
|
||||
|
||||
### 技术栈清单
|
||||
|
||||
- canonical record:Java 17 record + Jackson JSON String,所有状态组合在 record transition 方法中校验。
|
||||
- Redis create:`ValueOperations.setIfAbsent` + TTL;update:读取当前 remaining TTL 后写回;get 不调用 expire。
|
||||
- 大小:UTF-8 bytes;record/agent result/store limits 与 RunContext 累计 capacity 双重门禁。
|
||||
- 测试:Mockito RedisTemplate/ValueOperations 验证 TTL API;In-memory fake store + Fake Tool/Projector 验证 boundary,不连接外部 Redis。
|
||||
|
||||
### 新建类型
|
||||
|
||||
- canonical model/limits/store/exceptions/Redis adapter。
|
||||
- ToolCallRequestEnvelope、ToolBoundaryResult、ProjectedToolResult、ToolExecutor、ToolResultProjector、ToolBoundary 和稳定 error codes。
|
||||
- Redis adapter tests 与 boundary fake tests。
|
||||
|
||||
### 影响半径
|
||||
|
||||
- 新 package 在阶段 3A 保持零现有消费者。
|
||||
- Redis 访问只允许出现在 `RedisCanonicalInvocationStore`;旧 Chat/AIOps/Controller/JPA/Recorder 不修改。
|
||||
|
||||
## Apply 结果
|
||||
|
||||
- 冲突分类:一次 focused test 断言错误(duplicate 场景应调用 `setIfAbsent` 两次)已修正并复跑通过;无规格偏离。
|
||||
- 新增 canonical record/limits/store exceptions、Redis JSON adapter、ToolBoundary envelope/result/interfaces 和 stable error codes。
|
||||
- ToolBoundary 已实现 preflight、Core budget/capacity、PROJECTING、raw/projection size、READY/ERROR 和安全返回边界;未接具体 projector。
|
||||
- 首模块对齐:store/boundary/limits/failure 与 design/tasks 全部完成;RAG/log/MySQL adapters 仍留给后续阶段。
|
||||
|
||||
## Apply 验证
|
||||
|
||||
- 编译:`mvn -q -DskipTests compile`:通过。
|
||||
- Store/Boundary focused:`mvn -q '-Dtest=CanonicalInvocationStoreTest,ToolBoundaryTest' test`:通过。
|
||||
- 综合回归:`mvn -q '-Dtest=CanonicalInvocationStoreTest,ToolBoundaryTest,HarnessContractTest,RagToolContractTest,QueryLogsToolContractTest,MysqlToolContractTest,RunContextTest,RunBudgetTest,DiagnosisHarnessCoreTest,HarnessRetryExecutorTest,ToolCallKeyFactoryTest,SpringAiRetryConfigurationTest,ChatControllerTest' test`:通过。
|
||||
- 静态隔离:新 Harness 包仅 `RedisCanonicalInvocationStore` 引用 Redis;legacy recorder/JPA/Chat/AIOps/Controller/repository/resources diff 为空。
|
||||
- OpenSpec:`openspec validate single-react-tool-invocation-store --strict`:通过。
|
||||
@@ -1,20 +0,0 @@
|
||||
# Evidence: single-react-tool-invocation-store
|
||||
|
||||
## 文档与代码证据
|
||||
|
||||
- ISS-014 阶段 3A 明确要求统一 ToolBoundary、canonical invocation、PROJECTING/READY/ERROR、TTL/容量、ID/Run 所有权,且不实现 3B/3C projector。
|
||||
- 阶段 2 已提供 `RunContext`、Run bytes capacity 和 `ToolCallKeyFactory`,本阶段直接复用。
|
||||
- 旧 `ToolInvocationRecorder` 使用 JPA preview 和 ThreadLocal fallback;新 canonical record 独立保存完整 request/raw/agent,不修改旧 recorder/JPA。
|
||||
- 既有 `SessionConfiguration` 提供 `RedisTemplate<String,Object>` JSON bean;`RedisCanonicalInvocationStore` 是新 Harness 包唯一 Redis 引用。
|
||||
|
||||
## Evidence-driven 结论
|
||||
|
||||
- `setIfAbsent` 确保同一 `runId+toolCallId` 不覆盖;读取不调用 expire;更新使用剩余 TTL。
|
||||
- canonical record transition 只允许 PROJECTING -> READY/ERROR;READY 只接受 FOUND/NO_EVIDENCE,ERROR 不可引用。
|
||||
- ToolBoundary 在执行前校验 Run、ID、JSON、授权、只读和预算;raw 只在可信 store 保存,不返回 Agent。
|
||||
- UTF-8 record/Agent limits 与 Run capacity 双门禁;raw oversize 跳过 projector,Agent oversize 不返回,均产生 RESULT_TOO_LARGE。
|
||||
- Fake store/Redis mock tests 已覆盖 duplicate、cross-run、unauthorized、writable、execution/projection error、NO_EVIDENCE、TTL、raw/agent oversize。
|
||||
|
||||
## 工具限制
|
||||
|
||||
- 当前无 `codebase-retrieval`/LSP;使用 `rg`、源码、Maven 编译、Mockito Redis API 和 in-memory fake 完成等价验证。
|
||||
@@ -1,57 +0,0 @@
|
||||
# Acceptance: single-react-cleanup-e2e
|
||||
|
||||
## Result
|
||||
|
||||
Accepted. 阶段 7 的清理、Harness-native audit、文档收口和 live E2E 已完成;最终发布为安全 `FALLBACK`,没有释放未验证 Draft。
|
||||
|
||||
## Static Verification
|
||||
|
||||
- `openspec validate --all --strict`: 22/22 passed。
|
||||
- `node --check src/main/resources/static/app.js`: passed。
|
||||
- `git diff --check`: passed。
|
||||
- production legacy path、旧 Agent-facing Tool contract 和持久化敏感 payload 扫描:0 matches。
|
||||
- 最终 Tool 时间窗日志扫描:原始 query、request/response、Tool Call ID、Prompt、stack、debug instrumentation 均为 0;只保留有界 metadata。
|
||||
|
||||
## Script Verification
|
||||
|
||||
- Deterministic Maven regression: 60 suites / 221 tests,0 failures,0 errors,3 skipped。
|
||||
- `mvn -q -DskipTests compile`: passed。
|
||||
- `mvn -q -DskipTests package`: passed。
|
||||
- `mvn -q -Dtest=QueryLogsToolsTest,QueryLogsResultProjectorTest,CanonicalInvocationStoreTest test`: passed。
|
||||
- Flyway 9.22.3 repair + migrate: V012 checksum repaired,V013 applied,schema current version 013。
|
||||
- Maven `spring-boot:run` with `mvp-demo`: Flyway 13 migrations validated,JPA schema validation passed,Tomcat 9900 started,Harness/Audit wiring active。
|
||||
- `run-payment-timeout-demo.ps1`: strict named SSE validation passed for exact final session/run。
|
||||
- `scripts/query_mysql.py`: exact diagnosis_run、agent_step、tool_invocation queries passed。
|
||||
|
||||
## Final Live Evidence
|
||||
|
||||
- sessionId: `mvp-demo-payment-timeout-stage7-20260722-1741`
|
||||
- runId: `363f481c-33b8-42e7-8699-428a6ec61806`
|
||||
- SSE: `metadata -> status -> status -> status -> content -> done`
|
||||
- diagnosis_run: `status=SUCCESS`、`intent=DIAGNOSIS`、`release_outcome=FALLBACK`、`tool_call_count=2`、`total_token_count=11764`。
|
||||
- AgentStep: 2 exact-run rows,唯一 agent `diagnosis_agent`,`thought IS NULL`,只含角色/数量/Tool name metadata。
|
||||
- ToolInvocation: `lookup_knowledge` 和 Mock `query_logs` 各 1 行,均 `READY/EVIDENCE_FOUND/success=1`;input/details 只有 framework Tool Call ID、状态和字节数。
|
||||
|
||||
## Browser / Manual Verification
|
||||
|
||||
- 未执行浏览器点击验收;本阶段公开协议由真实 HTTP SSE 脚本和前端 JavaScript syntax/contract tests 覆盖。
|
||||
|
||||
## Remaining Risks
|
||||
|
||||
- live 结果为 EvidenceGuard/SemanticGuard 约束下的安全 `FALLBACK`,不是业务根因成功发布;这是允许的最终释放状态。
|
||||
- `diagnosis_run.step_count` 仍为空,但 exact AgentStep 查询返回 2 行;该历史汇总字段不作为本阶段 release gate。
|
||||
- `query_logs` 使用 Mock;真实 CLS 与生产业务 `query_mysql` datasource 仍属于后续接入范围。
|
||||
- `application-local.yml` 含本地内部配置且被 Git 忽略;未 stage、未提交、未输出凭据。
|
||||
|
||||
## Migration And Rollback
|
||||
|
||||
- L4 endpoint/frontend cleanup 必须整体回滚阶段 7 commit,不恢复双轨 endpoint 或旧 Tool annotations。
|
||||
- V013 仅幂等增加缺失列/索引;应用回滚时保留新增 nullable 列,避免破坏已写数据,不执行 destructive down migration。
|
||||
- Flyway repair 已将远端 V012 checksum 对齐当前迁移;V013 保证旧库与 fresh database 最终 schema 一致。
|
||||
|
||||
## Archive
|
||||
|
||||
- OpenSpec archive: completed at `openspec/changes/archive/2026-07-22-single-react-cleanup-e2e`。
|
||||
- Delta specs synced: created main `single-react-cleanup-e2e` spec and removed the temporary AiOps-preservation requirement from `single-react-chat-sse-cutover`。
|
||||
- Parent Issue `ISS-014` was closed and moved to `mvp/issues/archived/` after the stage 7 E2E evidence was accepted.
|
||||
- Post-E2E runtime-quality findings are tracked by active `ISS-015`; they do not reopen this completed cleanup change.
|
||||
@@ -1,30 +0,0 @@
|
||||
# Brief: single-react-cleanup-e2e
|
||||
|
||||
## Background
|
||||
|
||||
ISS-014 阶段 0-6B 已建立单一 Diagnosis ReAct Agent、Harness、ACI Tool、Guard 和 named SSE,但仓库仍存在 legacy AiOps/Sequential/Redis Session 链、旧 Tool contract、副作用式审计和过时文档。阶段 7 负责物理清理、durable metadata audit 和最终 live E2E。
|
||||
|
||||
## Goals
|
||||
|
||||
- 公开诊断只保留 `POST /api/chat`,业务代码只保留一个拥有 Tool loop 的 `diagnosis_agent`。
|
||||
- RAG/log 仅作为 Harness backend;Agent-facing Tool 只来自 `HarnessEvidenceTools`。
|
||||
- AgentStep 与 ToolInvocation 使用 exact sessionId/runId,长期持久化仅包含有界 metadata。
|
||||
- 通过 Maven 启动、named SSE、日志与 MySQL exact-run 查询完成最终验收。
|
||||
|
||||
## Scope
|
||||
|
||||
- 删除 legacy Controller、Service、Hook、ThreadLocal、prompt、前端入口、测试和死文档。
|
||||
- 新增 Harness-native Agent/Tool durable audit,修正文档、issue 与 OpenSpec strict 缺陷。
|
||||
- 为旧 V012 数据库增加幂等 V013 兼容迁移,并校准可重复 payment-timeout demo。
|
||||
|
||||
## Non-goals
|
||||
|
||||
- 不实现真实 CLS 或生产业务 MySQL Tool datasource。
|
||||
- 不修改三类 Intent、DiagnosisDraft、EvidenceGuard、SemanticGuard 或 Release Policy 语义。
|
||||
- 不保留 legacy endpoint、兼容分支、Graph 或第二套 Tool Call ID。
|
||||
|
||||
## Classification
|
||||
|
||||
- Scale: `complex`
|
||||
- Interface impact: L4 breaking HTTP/frontend cleanup
|
||||
- OpenSpec: `single-react-cleanup-e2e`
|
||||
@@ -1,111 +0,0 @@
|
||||
# Decisions: single-react-cleanup-e2e
|
||||
|
||||
## Discover Status
|
||||
|
||||
- Checkpoint: Discover
|
||||
- Capability source: `sm-flow` + `grill-with-docs` + `gitnexus-refactoring`。
|
||||
- GitNexus index 停在 `2362665`,当前为 `bc36248`;刷新会改写用户已修改的 `AGENTS.md`,因此不安全。使用 OpenSpec/devflow、`rg` 全引用扫描、源码阅读、编译和测试作为 fallback。
|
||||
- AGENTS.md 指定的 `codebase-retrieval` 与 LSP 工具在当前环境不可用,已显式记录限制。
|
||||
- Scale: complex。涉及 L4 endpoint 删除、跨模块物理清理、Tool/Trace ownership、安全持久化和 live E2E。
|
||||
|
||||
## Question Pool
|
||||
|
||||
| # | 维度 | 问题 | 模式 | 状态 |
|
||||
|---|---|---|---|---|
|
||||
| Q1 | 范围 | 哪些旧 Agent/Service/Hook/Session 只有自引用测试,哪些仍在生产可达? | evidence-driven | 已解决 |
|
||||
| Q2 | 协议 | 阶段 7 是否必须删除 `/api/ai_ops` 与旧 Session endpoints? | evidence-driven | 已解决 |
|
||||
| Q3 | Tool | RAG/log 旧实现哪些可复用,哪些 Agent-facing contract/副作用必须删除? | evidence-driven | 已解决 |
|
||||
| Q4 | Trace | 新 Harness 如何在不泄漏 raw/prompt/thought 的前提下满足 AgentStep/ToolInvocation E2E? | evidence-driven | 已解决 |
|
||||
| Q5 | 文档 | ISS-012/ISS-013 和现有架构/Demo 文档如何收口? | evidence-driven | 已解决 |
|
||||
| Q6 | 验收 | 最终 live E2E 必须证明哪些 exact-run 事实,哪些外部系统明确不声称 live? | evidence-driven | 已解决 |
|
||||
| Q7 | 回滚 | L4 endpoint 删除如何迁移与回滚? | evidence-driven | 已解决 |
|
||||
|
||||
## Evidence-driven
|
||||
|
||||
| 结论 | 证据来源 | 是否已汇报用户 |
|
||||
|---|---|---|
|
||||
| `ChatService` 没有生产调用方,只剩自身单元/Smoke tests。 | `rg ChatService` | 已汇报 |
|
||||
| `/api/ai_ops` 仍由 bundled frontend 按钮调用,并运行 Supervisor + Planner + Executor 多 Agent。 | `AiOpsController`、`AiOpsService`、`app.js`、`index.html` | 已汇报 |
|
||||
| ISS-014 总体验收要求旧多 Agent/Graph 不存在,阶段 6B 只暂时保持 AiOps,阶段 7 负责清理/处置。 | ISS-014、阶段 6B design/acceptance | 已汇报 |
|
||||
| `/api/chat/clear` 与 session info/runs 没有 frontend caller;Redis SessionManager 只由该 Controller 和测试使用。 | controller/frontend/session 引用扫描 | 已汇报 |
|
||||
| `LookupKnowledgeTool` 和 `QueryLogsTools` 被新 Harness adapter 复用,但仍携带旧 `@Tool`、ThreadLocal/recorder 副作用。 | `HarnessChatConfiguration`、Tool source | 已汇报 |
|
||||
| 新 ToolBoundary 写 Redis canonical invocation,但没有 `tool_invocation` durable audit;最终 DB E2E 会缺 Tool rows。 | Harness boundary/config 引用扫描 | 已汇报 |
|
||||
| 旧 `AgentLoggingHook` 仍回退 ThreadLocal,并持久化 thought/model正文;不满足新安全边界。 | `AgentLoggingHook.java` | 已汇报 |
|
||||
| 当前架构、Agent、Harness 和 lifecycle 文档仍描述 Planner/Executor/Verifier/Composer 与 AIOps 双入口。 | `mvp/architecture/*.md` | 已汇报 |
|
||||
|
||||
## User-interview
|
||||
|
||||
- 无新增 user-interview。唯一公开 Chat、旧多 Agent/Graph 物理删除、无兼容分支、最终 E2E 和外部 Mock 边界均已由 ISS-014 与用户的逐阶段自动执行授权冻结。
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- 删除 legacy AiOps endpoint 而不是迁移到第二个 use case;所有诊断统一进入 `/api/chat` 的 Intent Router。
|
||||
- 删除旧 Session endpoints/Redis conversation context;安全 PreviousTurn 只来自 `diagnosis_run.published_result`。
|
||||
- RAG/log 查询实现保留为 Harness backend,移除 `@Tool` 和旧 recorder/session dedup;Agent 只看 ACI callbacks。
|
||||
- 新 Agent audit hook 只写角色/数量/Tool 名称/耗时等 metadata,不写模型输入正文、输出正文、Thought 或 Tool arguments。
|
||||
- Tool durable audit 通过 Harness port + JPA adapter fail-open 写入;Redis canonical store failure 仍 fail-closed,DB audit failure 只记录日志,不改变 Tool observation。
|
||||
- 删除 endpoint 的迁移无兼容层;bundled frontend 同 commit 删除按钮/consumer,回滚整体回滚 commit。
|
||||
- 不创建 ADR:方向已由 ISS-014 冻结,本 change 只完成最终落地与验收。
|
||||
|
||||
## OpenSpec Backfill
|
||||
|
||||
- 需进入 design/spec/tasks:删除清单、唯一 endpoint、Harness-native trace、Tool durable audit schema/safety、Tool backend 解耦、文档/issue 收口、strict validation、live E2E/log/DB acceptance 与回滚。
|
||||
|
||||
## Cross-artifact Alignment
|
||||
|
||||
| 上游 -> 下游 | 检查内容 | 状态 |
|
||||
|---|---|---|
|
||||
| ISS-014/brief -> proposal | 阶段 7 物理清理、文档、最终 Maven/log/DB E2E、Mock 外部 Tool 边界 | 已对齐 |
|
||||
| proposal -> design | 删除闭包、Tool backend 复用、安全 Agent/Tool audit、L4 migration/rollback | 已对齐 |
|
||||
| design -> specs/tasks | ownership、禁止泄漏、exact identity、strict validation、live E2E 均有 requirement 与切片 | 已对齐 |
|
||||
| specs -> tasks | 8 组可观察 requirements 覆盖删除、audit、docs、verification 和最终 E2E | 已对齐 |
|
||||
|
||||
## Architecture Audit
|
||||
|
||||
- Capability source: `zoom-out`,使用 Diagnosis Harness、Diagnosis Agent、Canonical Invocation、Durable Audit、Diagnosis Trace 和 Chat SSE Contract 术语。
|
||||
- 最终链路为 `browser -> ChatController -> ChatApplicationUseCase -> Harness -> Diagnosis Agent -> ACI Tools -> Guards -> SSE`,没有第二业务入口或业务 Graph。
|
||||
- Redis canonical invocation 是短期完整 Tool 真理源;MySQL ToolInvocation 是长期有界 metadata audit,两者禁止双写 raw payload。
|
||||
- `chat_session` JPA entity 属于当前 Run/PreviousTurn 目录,Redis SessionContext 属于旧 conversation memory;删除时必须区分。
|
||||
- 最大风险是 backend 的旧 Tool annotation/recorder 隐式暴露和 audit 内容泄漏;design/tasks 已加入独占 discovery、negative serialization、context startup 与 live DB inspection。
|
||||
|
||||
## Interface Impact
|
||||
|
||||
- Level: L4 breaking HTTP/frontend contract。
|
||||
- 删除 `/api/ai_ops`、`/api/chat/clear`、`/api/chat/session/{sessionId}` 和 `/runs`;保留唯一 `/api/chat` SSE 与 Trace API。
|
||||
- bundled frontend 同 commit 删除 AiOps 按钮/consumer;外部 caller 迁移到 `/api/chat`,无兼容 branch。
|
||||
- 回滚必须整体回滚阶段 7 commit,不能单独恢复旧 endpoint/Tool annotations。
|
||||
|
||||
## Apply Verification Status
|
||||
|
||||
- Follow-up current-document audit found and corrected stale runtime semantics in the tracked payment-timeout PowerShell demo and `mvp/tables`: old JSON Chat parsing, Redis SessionContext history, Planner/Verifier identities, full Tool payload persistence, and Chat/AiOps Run descriptions are no longer presented as current behavior.
|
||||
- `mvp/demo/scripts/run-payment-timeout-demo.ps1` now strictly validates `metadata -> status* -> content|failure -> done`, captures exact session/run identity, and fetches exact Trace without writing feedback. PowerShell parser validation and two in-memory SSE contract samples passed.
|
||||
- Current architecture/demo/table scan excluding explicit `archive/` and ignored local `output/` artifacts: 0 legacy runtime matches.
|
||||
- Follow-up `openspec validate --all --strict`: 22 passed, 0 failed; `git diff --check`: passed.
|
||||
- Initial environment checks reported missing injected variables. Per user direction, credentials were restored to ignored `application-local.yml`; no credential was added to Git or emitted in the archive.
|
||||
- `mvn -q -DskipTests compile`: passed.
|
||||
- `node --check src/main/resources/static/app.js`: passed.
|
||||
- `openspec validate --all --strict`: 22 passed, 0 failed.
|
||||
- Deterministic regression suite excluding credential-dependent MySQL/Redis/Milvus tests: 60 suites, 221 tests, 0 failures, 0 errors, 3 skipped.
|
||||
- `SemanticGuardTest` interruption assertion failed once under the credential-dependent full-suite run, then passed three isolated repetitions and the deterministic regression suite; classified as load-sensitive test timing, not a reproduced product regression.
|
||||
- `mvn -q -DskipTests package`: passed.
|
||||
- Production legacy path scan, audit sensitive-payload scan, and legacy backend Tool contract scan: 0 matches.
|
||||
- The approved external-network run connected to MySQL/Redis/Milvus/model services. Flyway repair aligned the old V012 checksum and V013 reconciled the missing release-contract columns/index.
|
||||
- Maven startup validated all 13 migrations, passed JPA schema validation and started Tomcat 9900 with Harness/Audit beans.
|
||||
- Final exact live run: session `mvp-demo-payment-timeout-stage7-20260722-1741`, run `363f481c-33b8-42e7-8699-428a6ec61806`, SSE `metadata -> status -> status -> status -> content -> done`, outcome `FALLBACK`.
|
||||
- Exact MySQL evidence: one `DIAGNOSIS/SUCCESS/FALLBACK` run, two metadata-only `diagnosis_agent` steps with null Thought, and two READY/EVIDENCE_FOUND Tool audits for `lookup_knowledge` and Mock `query_logs`.
|
||||
- Tasks 4.2-4.5 are complete. Real CLS and production business MySQL Tool datasource remain explicit non-goals.
|
||||
|
||||
## Apply Conflict Classification
|
||||
|
||||
- **Code deviation**: `DiagnosisRun` enum mapping expected native ENUM while V012/V013 define VARCHAR. Fixed ORM column definitions; OpenSpec unchanged.
|
||||
- **Code deviation**: production `ObjectMapper` lacked Java Time modules, causing canonical Redis `STORE_ERROR`. Fixed mapper registration and bound the store test to the production mapper.
|
||||
- **Code deviation**: Mock empty log results used `success=false`, conflicting with the specified `NO_EVIDENCE` projection. Fixed backend success semantics and the stale test assertion.
|
||||
- **Code deviation**: RAG backend logs exposed raw query/rewritten query content. Replaced with bounded counts/category metadata and verified the final Tool execution window contains no prohibited payload.
|
||||
- **Acceptance fixture drift**: the payment-timeout demo requested the removed metrics Tool and encouraged an unbounded investigation. Updated the fixture to the current two-Tool Mock acceptance scope and explicit stopping boundary.
|
||||
|
||||
## Commit Gate Preflight
|
||||
|
||||
- proposal、design、两份 specs 和 tasks 完整;新 capability 与 modified capability 的范围无 gap。
|
||||
- Question pool 全部 evidence-driven 并已汇报,无 user-interview、未判级接口或未接受架构风险。
|
||||
- 删除清单区分 current JPA metadata 与 legacy Redis Session,Tool backend 与 Agent-facing contract,canonical truth 与 durable audit。
|
||||
- live E2E 明确要求真实应用/模型链和 exact ID;真实 CLS/生产业务 MySQL 明确不在验收声称范围。
|
||||
@@ -1,26 +0,0 @@
|
||||
# Evidence: single-react-cleanup-e2e
|
||||
|
||||
## Repository Evidence
|
||||
|
||||
- 生产引用扫描确认旧 `ChatService` 仅剩自身测试,`/api/ai_ops` 与旧 Session endpoints 属于第二条公开/状态链。
|
||||
- Harness adapters 复用 `LookupKnowledgeTool`/`QueryLogsTools` backend;旧 `@Tool`、ThreadLocal、recorder 和 topic discovery contract 已移除。
|
||||
- `HarnessAgentAuditHook` 只写 message count/roles、Tool names、text presence 和 duration;`thought` 保持空。
|
||||
- ToolBoundary durable audit 只写 exact identity、状态、稳定错误码、耗时和字节数;Redis canonical invocation 仍是短期完整 Tool 真理源。
|
||||
|
||||
## Live Findings
|
||||
|
||||
- 远端库已登记旧 V012 checksum,但缺少 `diagnosis_run.intent/release_outcome/published_result`。Flyway repair 后,幂等 V013 补齐三列与索引,fresh database 上为 no-op。
|
||||
- Hibernate 6 将无 `columnDefinition` 的字符串枚举校验为原生 ENUM;`DiagnosisRun` 已显式映射到 V012/V013 的 `VARCHAR(32/16)`。
|
||||
- 生产 `WebConfig` 的裸 `ObjectMapper` 无法序列化 canonical record 的 `Instant`,导致所有 Tool 在 begin 阶段返回 `STORE_ERROR`;改为自动注册模块,并让 store 测试使用生产 mapper。
|
||||
- Mock `query_logs` 把 0 命中错误表达为 `success=false`,与 `NO_EVIDENCE` contract 冲突;现以成功查询 + 空数组表达无证据。
|
||||
- live 日志发现 RAG backend 打印原始 query/rewrittenQuery/keywords;已改为字符数、命中数、类别数和耗时 metadata。
|
||||
|
||||
## Final Exact-run Evidence
|
||||
|
||||
- sessionId: `mvp-demo-payment-timeout-stage7-20260722-1741`
|
||||
- runId: `363f481c-33b8-42e7-8699-428a6ec61806`
|
||||
- SSE: `metadata -> status -> status -> status -> content -> done`
|
||||
- outcome: `FALLBACK`; diagnosis_run: `DIAGNOSIS / SUCCESS / FALLBACK`
|
||||
- AgentStep: 2 rows,均为 `diagnosis_agent`,`thought IS NULL`,model input/output 仅 metadata。
|
||||
- ToolInvocation: 2 rows,`lookup_knowledge` 与 `query_logs` 均为 `READY/EVIDENCE_FOUND`,同一 exact identity,无错误。
|
||||
- `query_logs` 明确为 Mock;Agent-facing `query_mysql` 未配置生产业务 datasource,也未声称 live。
|
||||
@@ -1,68 +0,0 @@
|
||||
# Diagnosis 信息增益停止契约 验收
|
||||
|
||||
## 结果
|
||||
|
||||
已接受。OpenSpec tasks 37/37 完成;用户确认归档 OpenSpec、提交并推送。
|
||||
|
||||
## 验证
|
||||
|
||||
### 静态验证
|
||||
|
||||
- 命令/检查:`openspec validate diagnosis-information-gain-stop-contract --strict`
|
||||
- 结果:passed
|
||||
- 备注:Committed OpenSpec 与最终 tasks 一致
|
||||
|
||||
- 命令/检查:OpenSpec delta → main specs 同步(6 个 capability)
|
||||
- 结果:passed
|
||||
- 备注:新建 `openspec/specs/diagnosis-information-gain-stop-contract/`,并更新 5 个既有 main specs
|
||||
|
||||
- 命令/检查:对照 OpenSpec 与代码路径(progress tracker、interceptor、release、trace)
|
||||
- 结果:passed
|
||||
- 备注:Task 8 行为与 design/spec 对齐
|
||||
|
||||
### 脚本验证
|
||||
|
||||
- 命令:`mvn -q "-Dtest=DiagnosisProgressTrackerTest,HarnessToolInterceptorTest,DiagnosisReleaseUseCaseTest,DiagnosisAgentUseCaseTest,HarnessChatConfigurationTest" test`
|
||||
- 结果:passed(exit 0)
|
||||
- 备注:覆盖协议 violation_type、可修正 observation、连续协议错误 STOP、Release fail-closed、Agent 受控停止
|
||||
|
||||
- 命令:历史全量回归 `mvn -q -Dtest='!MilvusConnectionTest' test`(tasks 6.2/7.5 阶段)
|
||||
- 结果:passed(`Tests=292, Failures=0, Errors=0, Skipped=3`)
|
||||
- 备注:未设置 `MILVUS_TOKEN` 时 `MilvusConnectionTest` 失败属外部凭据边界,非本变更回归
|
||||
|
||||
### 浏览器/人工验证
|
||||
|
||||
- 步骤:Maven 启动真实应用;Query `诊断切换企业失败的问题`;named SSE + logs + `scripts/query_mysql.py` 按 exact sessionId/runId 核对
|
||||
- 结果:passed
|
||||
- 备注:
|
||||
- `sessionId=iss016-final-20260726-a`
|
||||
- `runId=3ab22ed7-d0ed-45d8-b928-dce5790c0542`
|
||||
- SSE:`SAFE_FALLBACK` / `MISSING_REQUIRED_CONTEXT` / `done.outcome=FALLBACK`
|
||||
- DB:`status=SUCCESS`、`intent=DIAGNOSIS`、`release_outcome=FALLBACK`、`tool_call_count=0`、`total_token_count=2890`
|
||||
- Trace:`RUN_STARTED -> ROUTING_* -> AGENT_MODEL_STEP -> EVIDENCE_GUARD_INITIAL -> RELEASE_DECISION/FALLBACK -> RUN_FINISHED/FALLBACK`
|
||||
|
||||
### 未验证
|
||||
|
||||
- 本轮 Archive 未再重跑全量 `mvn test` 与完整 live SSE E2E;依赖 Apply 阶段记录与本轮 focused tests。
|
||||
- 真实 Provider 下连续协议错误的 live E2E 未单独复跑;协议停止由 focused/scripted loop 覆盖。
|
||||
- ISS-015 阶段 2(Evidence Repair Schema)与阶段 3(Reasoning 治理)不在本 change 范围。
|
||||
|
||||
## 已完成范围
|
||||
|
||||
- 信息增益停止、scope 去重、STOP_REQUIRED、ProgressSnapshot、统一 Release
|
||||
- Token 审计与 Tool 拒绝 Trace
|
||||
- 协议修复反馈 + `PROGRESS_PROTOCOL_VIOLATED` 兜底停止
|
||||
- 文档:ISS-015 阶段 1、ISS-016、架构文档、glossary 术语、devflow 档案
|
||||
|
||||
## 已知限制
|
||||
|
||||
- 重复检测只比较确定性 `tool_name + normalized_scope`,不做自然语言语义去重。
|
||||
- 协议错误阈值默认 2,与无增益阈值独立配置。
|
||||
- 无安全 ProgressSnapshot 的受控停止继续 fail closed,不伪造用户可见事实。
|
||||
- 公开 SSE/前端协议无新增字段;模型侧 Tool Envelope 是已确认 L3 变更。
|
||||
|
||||
## 交接
|
||||
|
||||
- 下一步:OpenSpec 已用户确认归档;代码提交并推送到当前分支。
|
||||
- OpenSpec 归档确认:用户确认归档(“执行,完后提交推送”)
|
||||
- 归档位置:`openspec/changes/archive/2026-07-27-diagnosis-information-gain-stop-contract/`
|
||||
@@ -1,45 +0,0 @@
|
||||
# Diagnosis 信息增益停止契约 Brief
|
||||
|
||||
## 背景
|
||||
|
||||
- 用户目标:未知问题、空证据或缺少查询条件时,Diagnosis 能以正常业务 Fallback 结束,而不是空转到预算耗尽或 `INTERNAL_FAILURE`。
|
||||
- 当前问题:停止主要依赖模型自觉结束或硬预算;缺少信息增益回传、确定性饱和停止、协议修复反馈和统一 Release。
|
||||
- 关联 OpenSpec:`openspec/changes/diagnosis-information-gain-stop-contract/`(归档后见 `openspec/changes/archive/2026-07-27-diagnosis-information-gain-stop-contract/`)
|
||||
- 关联 Issue:ISS-016(承接 ISS-015 阶段 1 硬停止)
|
||||
- devflow 分档:complex
|
||||
- 接口影响:L3(模型可见 Tool Envelope 有意变更;公开 HTTP/SSE 与业务 Tool backend 不变)
|
||||
|
||||
## 范围
|
||||
|
||||
### 本次要做
|
||||
|
||||
- Run 内二值信息增益 `GAINED / NO_GAIN`、连续无增益阈值与 `COLLECTING / SATURATED`。
|
||||
- 服务端注册的 Tool Call Envelope:`previous_observation + input`。
|
||||
- 确定性 `NO_GAIN`(`NO_EVIDENCE`、重复 `tool_name + normalized_scope`)。
|
||||
- 一次 `STOP_REQUIRED` 收尾机会与受控停止异常。
|
||||
- Canonical 控制视图 / 模型白名单观察双视图;RAG 保留 `relevance_level`。
|
||||
- Tool loop 结束时一次性投影 `ProgressSnapshot`。
|
||||
- `DiagnosisReleaseUseCase` 统一有结论、无结论、信息饱和、预算终止、协议违规停止的发布。
|
||||
- 可修正 `INVALID_PROGRESS_PROTOCOL` observation,以及独立 `PROGRESS_PROTOCOL_VIOLATED` 兜底停止。
|
||||
- 模型 Token 组件/轮次审计与 `TOOL_REQUEST_REJECTED` 安全 Trace。
|
||||
- Prompt、配置、focused/回归测试与真实 named SSE E2E。
|
||||
|
||||
### 本次不做
|
||||
|
||||
- `new_count`、`next_action`、多级质量分数、独立 Judge。
|
||||
- 自然语言语义去重。
|
||||
- 第二套诊断生命周期状态。
|
||||
- 公开 HTTP/SSE 字段或前端进度协议新增。
|
||||
- ISS-015 Reasoning 原文审计治理与 Evidence Repair Schema 注入。
|
||||
|
||||
### 影响区域
|
||||
|
||||
- `harness.progress`、`HarnessToolInterceptor`、`HarnessEvidenceTools`
|
||||
- `DiagnosisAgentUseCase` / Prompt / Release / Application 预算兜底迁移
|
||||
- Trace 审计、配置绑定、ISS-015/016 与架构文档
|
||||
|
||||
## OpenSpec 对齐
|
||||
|
||||
- proposal 覆盖状态:已覆盖
|
||||
- specs 覆盖状态:已覆盖(6 个 capability delta,已同步 main specs)
|
||||
- tasks 覆盖状态:已覆盖(37/37 完成)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user