feat: release 2.2.0 with PC-only tests and execution reliability fixes

Unify task scheduling and queue state, fix Android input and observation recovery, preserve screenshot paths, and match final review criteria accurately. Add collapsible copyable results and publish the complete 2.1.0 upgrade notes. Validation: 3189 backend tests, 326 frontend tests, 24 client tests, production build and quality gates.
This commit is contained in:
chenmingxuan committed 2026-10-27 01:13:41 +08:00
1 parent fac4ccb760
commit be6e8c2abd
79 files changed
+2263 -277

No files matched your search

+7
View File
@@ -54,6 +54,13 @@ def input_state(node: dict[str, Any]) -> dict[str, Any]:
}
def expected_input_state(text: str, clear_existing: bool) -> str | None:
"""Empty replacement means clear; empty append has no value postcondition."""
if text:
return "present"
return "empty" if clear_existing else None
def verify_input(elements: list[dict], target: dict | None = None) -> str:
"""Verify value presence against a fresh tree, without returning its value.
+41 -2
View File
@@ -53,7 +53,11 @@ SAVE_NOTE_DOCSTRING = (
" will be overwritten."
)
SAVE_NOTE_ARG_KEY_DESC = "The unique key under which to save or overwrite the note."
SAVE_NOTE_ARG_CONTENT_DESC = "The text content to write to the note."
_ARTIFACT_REFERENCE_RULE = (
" Copy artifact paths exactly from successful tool receipts (trace_path for task-local "
"evidence); never rebuild a path from the session directory and filename."
)
SAVE_NOTE_ARG_CONTENT_DESC = "The text content to write to the note." + _ARTIFACT_REFERENCE_RULE
APPEND_NOTE_DOCSTRING = (
"[NOTE] Appends text content to an existing note in persistent memory with"
@@ -62,7 +66,7 @@ APPEND_NOTE_DOCSTRING = (
" note does not exist, it will be created."
)
APPEND_NOTE_ARG_KEY_DESC = "The key of the note to append to."
APPEND_NOTE_ARG_CONTENT_DESC = "The text content to append to the note."
APPEND_NOTE_ARG_CONTENT_DESC = "The text content to append to the note." + _ARTIFACT_REFERENCE_RULE
UPDATE_NOTE_DOCSTRING = (
"[NOTE] Updates a note by replacing a specific target string with"
@@ -77,6 +81,7 @@ UPDATE_NOTE_ARG_TARGET_DESC = (
)
UPDATE_NOTE_ARG_REPLACEMENT_DESC = (
"The new replacement content to insert instead of the target content."
+ _ARTIFACT_REFERENCE_RULE
)
@@ -146,8 +151,40 @@ def read_note_content(
return content
def validate_artifact_note_paths(base_dir: str | Path, content: str) -> None:
"""Reject missing root-level references to existing task artifacts, without guessing."""
root = Path(base_dir).resolve()
if not any(prefix in content for prefix in (str(root), root.as_posix())):
return
artifacts = root / "artifacts"
if not artifacts.is_dir() or not artifacts.resolve().is_relative_to(root):
return
candidates: dict[Path, list[str]] = {}
for path in artifacts.rglob("*"):
if not path.is_file() or not path.resolve().is_relative_to(root):
continue
misplaced = root / path.name
if misplaced.exists():
continue
for spelling in {str(misplaced), misplaced.as_posix()}:
if re.search(re.escape(spelling) + r"(?![\w./\\-])", content):
candidates.setdefault(misplaced, []).append(str(path))
break
if candidates:
details = "; ".join(
f"{missing} does not exist; saved candidates: {', '.join(paths)}"
for missing, paths in candidates.items()
)
raise ValueError(
"Artifact reference has omitted its artifact directory. "
+ details
+ ". Re-read the tool receipt and use its exact trace_path; note was not changed."
)
def save_note_content(base_dir: str | Path, key: str, content: str) -> None:
"""Saves or overwrites the raw content of a note."""
validate_artifact_note_paths(base_dir, content)
notes_dir = get_notes_dir(base_dir)
notes_dir.mkdir(parents=True, exist_ok=True)
file_path = get_note_file_path(base_dir, key)
@@ -211,6 +248,7 @@ def save_verified_note(base_dir: str | Path, key: str, content: str) -> dict:
def append_note_content(base_dir: str | Path, key: str, content: str) -> None:
"""Appends raw content to a note, inserting a newline if the file is not empty and lacks a trailing newline."""
validate_artifact_note_paths(base_dir, content)
notes_dir = get_notes_dir(base_dir)
notes_dir.mkdir(parents=True, exist_ok=True)
file_path = get_note_file_path(base_dir, key)
@@ -379,6 +417,7 @@ def update_note_content(
# Phase 4: Write and Return, or Not Found Error
if new_content_to_write is not None:
validate_artifact_note_paths(base_dir, replacement)
file_path.write_text(new_content_to_write, encoding="utf-8")
if key == "task_plan":
try: