tasks: stop tracking current task set; fix t2 integration test for emptyNote

Context:
  The current 40-task set is being split into a private holdout set plus a
  new public set. The public repo will ship a different task set that
  doesn't give away the holdout; in the meantime, stop tracking the current
  tasks/ directory so benchmarking can continue locally without exposing
  the set externally.

Changes:
  - .gitignore: add tasks/ and lab-pr68627/ (vendored PR content, also
    moving out of the public repo).
  - git rm --cached tasks/: remove from tracking (files remain on disk
    locally).
  - tests/test_integration_checks.py:
    * Module-level pytest.mark.skipif that skips the whole file when
      tasks/ is absent — so CI against the public repo (no tasks)
      stays green once the private set moves out.
    * Update the t2-node-search-patch fixture to also define emptyNote()
      since the task was hardened with that distractor. Without this, the
      integration test asserts score==1.0 but gets 0.0 (the new
      "emptyNote stays empty" test fails against a fixture that never
      defines emptyNote).

Follow-up (separate work):
  Public task set lands in a subsequent commit. Holdout access path
  (encrypted-in-repo or private-repo) gets wired into the harness's
  private_tasks_root / hidden_tasks_dir plumbing.

Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
This commit is contained in:
scoootscooob 2026-04-19 12:29:52 -07:00
parent 95b226dfed
commit deb3d5d85d
228 changed files with 24 additions and 6439 deletions

5
.gitignore vendored
View File

@ -15,3 +15,8 @@ reports/
scripts/__pycache__/
scripts/*.tmp
scripts/*.local.py
# Task set is being split into a private holdout + a new public set.
# Until the public set lands, keep the current tasks/ local-only.
tasks/
lab-pr68627/

View File

@ -1,74 +0,0 @@
"""Shared search helper for v0.5 verifiers.
Verifiers must accept artifacts wherever the agent wrote them. The OpenClaw
agent's AGENTS.md instructs it to capture notes in memory/YYYY-MM-DD.md, so
many tasks end up with content in memory/ rather than the workspace path the
verifier originally expected.
This module is copied into each asset pack rather than imported, because
verifiers run from the per-run workspace where the package isn't installed.
"""
from __future__ import annotations
from pathlib import Path
EXCLUDE_FRAGMENTS = (
"verify_",
"/.git/",
"/.openclaw/",
"BOOTSTRAP.md",
"IDENTITY.md",
"AGENTS.md",
"USER.md",
"SOUL.md",
"HEARTBEAT.md",
"MEMORY.md",
)
TEXT_SUFFIXES = (".md", ".txt", ".json", ".yaml", ".yml", ".csv", ".log",
".jsonl", ".html", ".sh", ".py")
def iter_workspace_text_files(root: Path | str = "."):
root = Path(root)
for path in root.rglob("*"):
if not path.is_file():
continue
sp = str(path)
if any(frag in sp for frag in EXCLUDE_FRAGMENTS):
continue
if path.suffix.lower() not in TEXT_SUFFIXES:
continue
try:
yield path, path.read_text(encoding="utf-8", errors="ignore")
except Exception:
continue
def find_with_all(needed_lower: list[str], root: str = ".") -> tuple[Path | None, str]:
"""Return the first text file containing every substring in needed_lower."""
needed = [s.lower() for s in needed_lower]
for path, text in iter_workspace_text_files(root):
text_lower = text.lower()
if all(s in text_lower for s in needed):
return path, text
return None, ""
def find_with_any(any_lower: list[str], root: str = ".") -> tuple[Path | None, str]:
"""Return the first text file containing any substring in any_lower."""
any_set = [s.lower() for s in any_lower]
for path, text in iter_workspace_text_files(root):
text_lower = text.lower()
if any(s in text_lower for s in any_set):
return path, text
return None, ""
def collect_all_text(root: str = ".") -> str:
"""Concatenate every text file in the workspace into one searchable blob."""
parts = []
for _, text in iter_workspace_text_files(root):
parts.append(text)
return "\n".join(parts)

View File

@ -1,12 +0,0 @@
from shop.cart import CartService
from shop.formatting import format_cents
def render_total(price_cents: int, quantity: int) -> str:
total = CartService().line_total(price_cents, quantity)
return format_cents(total)
if __name__ == "__main__":
print(render_total(1299, 2))

View File

@ -1,4 +0,0 @@
class CartService:
def line_total(self, price_cents: int, quantity: int) -> int:
return price_cents * quantity

View File

@ -1,4 +0,0 @@
def format_cents(value: int) -> str:
dollars = value / 100
return f"${dollars:0.2f}"

View File

@ -1,6 +0,0 @@
from app import render_total
def test_render_total():
assert render_total(1299, 2) == "$25.98"

View File

@ -1,45 +0,0 @@
from __future__ import annotations
import json
from pathlib import Path
REQUIRED_KEYS = {
"entrypoint",
"total_module",
"formatter_module",
"smoke_test",
}
def _normalize_path(value: str) -> str:
return value.strip().replace("\\", "/").removeprefix("./").lower()
def _contains_path(value: str, expected: str) -> bool:
normalized = _normalize_path(value)
return normalized == expected or normalized.endswith(expected)
def _is_valid_smoke_command(value: str) -> bool:
normalized = " ".join(value.strip().lower().split())
if "pytest" not in normalized:
return False
return (
"tests/test_smoke.py" in normalized
or "test_smoke.py" in normalized
or normalized in {"pytest -q", "python -m pytest -q", "python3 -m pytest -q"}
)
def main() -> None:
payload = json.loads(Path("architecture.json").read_text(encoding="utf-8"))
assert isinstance(payload, dict)
assert REQUIRED_KEYS.issubset(payload)
assert _contains_path(str(payload["entrypoint"]), "app.py")
assert _contains_path(str(payload["total_module"]), "shop/cart.py")
assert _contains_path(str(payload["formatter_module"]), "shop/formatting.py")
assert _is_valid_smoke_command(str(payload["smoke_test"]))
if __name__ == "__main__":
main()

View File

@ -1,6 +0,0 @@
from pricing import apply_discount
def checkout_total(subtotal: int, discount_percent: int) -> int:
return apply_discount(subtotal, discount_percent)

View File

@ -1,4 +0,0 @@
def apply_discount(subtotal_cents: int, discount_percent: int) -> int:
# BUG: this subtracts the raw percent value instead of a percentage of the subtotal.
return subtotal_cents - discount_percent

View File

@ -1,10 +0,0 @@
from cart import checkout_total
def test_percentage_discount_applies_to_full_subtotal():
assert checkout_total(2_000, 10) == 1_800
def test_zero_discount_keeps_subtotal():
assert checkout_total(1_250, 0) == 1_250

View File

@ -1,57 +0,0 @@
"""Recursive workspace search verifier."""
from __future__ import annotations
import sys
from pathlib import Path
EXCLUDE_FRAGMENTS = (
"verify_", "/.git/", "/.openclaw/",
"BOOTSTRAP.md", "IDENTITY.md", "AGENTS.md",
"USER.md", "SOUL.md", "HEARTBEAT.md",
)
TEXT_SUFFIXES = (".md", ".txt", ".json", ".yaml", ".yml", ".csv", ".log",
".jsonl", ".html", ".sh", ".py")
def iter_workspace_text_files(root: Path = Path(".")):
for path in root.rglob("*"):
if not path.is_file():
continue
sp = str(path)
if any(frag in sp for frag in EXCLUDE_FRAGMENTS):
continue
if path.suffix.lower() not in TEXT_SUFFIXES:
continue
try:
yield path, path.read_text(encoding="utf-8", errors="ignore")
except Exception:
continue
def workspace_blob() -> str:
return "\n".join(text for _, text in iter_workspace_text_files())
import re
LIST_PATTERNS = [
re.compile(r"^\s*[-*+]\s+"),
re.compile(r"^\s*\d+[.)]\s+"),
re.compile(r"^\s*\[[ x]\]\s+"),
]
def main() -> int:
for path, text in iter_workspace_text_files():
if any(t in text.lower() for t in ("dry clean", "sam", "babysit", "60")):
list_lines = sum(1 for line in text.splitlines() if any(p.match(line) for p in LIST_PATTERNS))
if list_lines >= 3:
print(f"PASS: list-formatted note found at {path} ({list_lines} list lines)")
return 0
print("FAIL: no list-structured note found anywhere in workspace")
return 1
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,56 +0,0 @@
"""Recursive workspace search verifier."""
from __future__ import annotations
import sys
from pathlib import Path
EXCLUDE_FRAGMENTS = (
"verify_", "/.git/", "/.openclaw/",
"BOOTSTRAP.md", "IDENTITY.md", "AGENTS.md",
"USER.md", "SOUL.md", "HEARTBEAT.md",
)
TEXT_SUFFIXES = (".md", ".txt", ".json", ".yaml", ".yml", ".csv", ".log",
".jsonl", ".html", ".sh", ".py")
def iter_workspace_text_files(root: Path = Path(".")):
for path in root.rglob("*"):
if not path.is_file():
continue
sp = str(path)
if any(frag in sp for frag in EXCLUDE_FRAGMENTS):
continue
if path.suffix.lower() not in TEXT_SUFFIXES:
continue
try:
yield path, path.read_text(encoding="utf-8", errors="ignore")
except Exception:
continue
def workspace_blob() -> str:
return "\n".join(text for _, text in iter_workspace_text_files())
def main() -> int:
blob = workspace_blob().lower()
if not blob:
print("FAIL: workspace contains no agent-written text files")
return 1
needed = ['dry clean', 'sam', 'babysit']
if not all(s in blob for s in needed):
missing = [s for s in needed if s not in blob]
print(f"FAIL: workspace missing required content: {missing}")
return 1
needed = ['60']
if not all(s in blob for s in needed):
missing = [s for s in needed if s not in blob]
print(f"FAIL: workspace missing required content: {missing}")
return 1
print("PASS: t1_fs_quick_note/verify_three_items.py")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,9 +0,0 @@
Dear Mr. Chen,
Thank you very much for your patience while we finalized the contract terms.
We are pleased to confirm that everything is in order and we look forward
to beginning our partnership next Tuesday afternoon. Please let us know if
you have any questions.
Best regards,
The Procurement Team

View File

@ -1,48 +0,0 @@
"""Recursive workspace search verifier."""
from __future__ import annotations
import sys
from pathlib import Path
EXCLUDE_FRAGMENTS = (
"verify_", "/.git/", "/.openclaw/",
"BOOTSTRAP.md", "IDENTITY.md", "AGENTS.md",
"USER.md", "SOUL.md", "HEARTBEAT.md",
)
TEXT_SUFFIXES = (".md", ".txt", ".json", ".yaml", ".yml", ".csv", ".log",
".jsonl", ".html", ".sh", ".py")
def iter_workspace_text_files(root: Path = Path(".")):
for path in root.rglob("*"):
if not path.is_file():
continue
sp = str(path)
if any(frag in sp for frag in EXCLUDE_FRAGMENTS):
continue
if path.suffix.lower() not in TEXT_SUFFIXES:
continue
try:
yield path, path.read_text(encoding="utf-8", errors="ignore")
except Exception:
continue
def workspace_blob() -> str:
return "\n".join(text for _, text in iter_workspace_text_files())
def main() -> int:
for path, text in iter_workspace_text_files():
if not any("\u4e00" <= ch <= "\u9fff" for ch in text):
continue
if "" in text:
print(f"PASS: formal register (您) used in {path}")
return 0
print("FAIL: no Chinese text using formal 您 found in workspace")
return 1
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,51 +0,0 @@
"""Recursive workspace search verifier."""
from __future__ import annotations
import sys
from pathlib import Path
EXCLUDE_FRAGMENTS = (
"verify_", "/.git/", "/.openclaw/",
"BOOTSTRAP.md", "IDENTITY.md", "AGENTS.md",
"USER.md", "SOUL.md", "HEARTBEAT.md",
)
TEXT_SUFFIXES = (".md", ".txt", ".json", ".yaml", ".yml", ".csv", ".log",
".jsonl", ".html", ".sh", ".py")
def iter_workspace_text_files(root: Path = Path(".")):
for path in root.rglob("*"):
if not path.is_file():
continue
sp = str(path)
if any(frag in sp for frag in EXCLUDE_FRAGMENTS):
continue
if path.suffix.lower() not in TEXT_SUFFIXES:
continue
try:
yield path, path.read_text(encoding="utf-8", errors="ignore")
except Exception:
continue
def workspace_blob() -> str:
return "\n".join(text for _, text in iter_workspace_text_files())
def main() -> int:
for path, text in iter_workspace_text_files():
if not any("\u4e00" <= ch <= "\u9fff" for ch in text):
continue
if "Dear Mr. Chen" in text or "The Procurement Team" in text:
continue # the original english source
if len(text.strip()) < 20:
continue
print(f"PASS: Chinese translation present at {path}")
return 0
print("FAIL: no non-trivial Chinese translation found anywhere in workspace")
return 1
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,18 +0,0 @@
from typing import Iterable
def load_rows(lines: Iterable[str]) -> list[dict[str, str | int]]:
rows: list[dict[str, str | int]] = []
for line in lines:
line = line.strip()
if not line or line.startswith("#"):
continue
raw_name, raw_count = line.split(",", 1)
rows.append(
{
"name": raw_name.strip().lower(),
"count": int(raw_count.strip()),
}
)
return rows

View File

@ -1,20 +0,0 @@
def summarize_inventory(lines: list[str]) -> dict[str, int]:
"""Aggregate counts per item. Case-insensitive bucketing but the output
key uses the FIRST-seen display case (so a user-facing report keeps the
original capitalization as entered)."""
summary: dict[str, int] = {}
display_name: dict[str, str] = {} # lowercase key -> first-seen original
for line in lines:
line = line.strip()
if not line or line.startswith("#"):
continue
raw_name, raw_count = line.split(",", 1)
original = raw_name.strip()
key = original.lower()
count = int(raw_count.strip())
if key not in display_name:
display_name[key] = original
# Aggregate under the display-name (first-seen case)
display = display_name[key]
summary[display] = summary.get(display, 0) + count
return summary

View File

@ -1,22 +0,0 @@
from csv_loader import load_rows
from report_builder import summarize_inventory
def test_load_rows_skips_comments_and_normalizes_names():
# load_rows returns lowercase-normalized names (matches stored SKU keys).
rows = load_rows(["# ignore", " Apples , 2 ", "bananas,5"])
assert rows == [{"name": "apples", "count": 2}, {"name": "bananas", "count": 5}]
def test_summarize_inventory_aggregates_case_insensitively_preserving_display_case():
# summarize_inventory aggregates case-insensitively BUT keeps the first-seen
# original display case (APPLES + apples both roll up under "APPLES").
# This is distinct from load_rows's lowercase normalization — any shared
# helper must accommodate BOTH behaviors without duplicating the parsing.
summary = summarize_inventory(["APPLES,2", "apples,3", "pears,1"])
assert summary == {"APPLES": 5, "pears": 1}
def test_summarize_inventory_preserves_first_seen_case_across_variants():
summary = summarize_inventory(["Bread,1", "BREAD,2", "bread,3"])
assert summary == {"Bread": 6}

View File

@ -1,27 +0,0 @@
from __future__ import annotations
import subprocess
import sys
from pathlib import Path
def main() -> None:
parsing = Path("parsing.py").read_text(encoding="utf-8")
csv_loader = Path("csv_loader.py").read_text(encoding="utf-8")
report_builder = Path("report_builder.py").read_text(encoding="utf-8")
assert "def parse_inventory_row" in parsing
assert "from parsing import parse_inventory_row" in csv_loader
assert "from parsing import parse_inventory_row" in report_builder
completed = subprocess.run(
[sys.executable, "-m", "pytest", "-q"],
check=False,
capture_output=True,
text=True,
)
assert completed.returncode == 0, completed.stdout + completed.stderr
if __name__ == "__main__":
main()

View File

@ -1,14 +0,0 @@
import re
EMOJI_RE = re.compile(r"[\U0001F300-\U0001FAFF]")
def normalize_title(text: str) -> str:
cleaned = " ".join(text.split())
cleaned = EMOJI_RE.sub("", cleaned)
return cleaned.strip().title()
def normalize_tags(raw: str) -> list[str]:
return [part.strip().lower() for part in raw.split(",") if part.strip()]

View File

@ -1,74 +0,0 @@
from __future__ import annotations
import subprocess
import sys
from pathlib import Path
BUGGY_EMOJI = """import re
EMOJI_RE = re.compile(r"[\\U0001F300-\\U0001FAFF]")
def normalize_title(text: str) -> str:
cleaned = " ".join(text.split())
return cleaned.strip().title()
def normalize_tags(raw: str) -> list[str]:
return [part.strip().lower() for part in raw.split(",") if part.strip()]
"""
BUGGY_TAGS = """import re
EMOJI_RE = re.compile(r"[\\U0001F300-\\U0001FAFF]")
def normalize_title(text: str) -> str:
cleaned = " ".join(text.split())
cleaned = EMOJI_RE.sub("", cleaned)
return cleaned.strip().title()
def normalize_tags(raw: str) -> list[str]:
return [part.strip().lower() for part in raw.split(",")]
"""
def _run_pytest(*args: str) -> subprocess.CompletedProcess[str]:
return subprocess.run(
[sys.executable, "-m", "pytest", "-q", *args],
check=False,
capture_output=True,
text=True,
)
def _expect_mutant_failure(normalizer_path: Path, mutant_source: str, label: str) -> None:
backup = normalizer_path.read_text(encoding="utf-8")
normalizer_path.write_text(mutant_source, encoding="utf-8")
try:
result = _run_pytest("tests/test_normalizer.py")
assert result.returncode != 0, f"student tests did not catch mutant: {label}"
finally:
normalizer_path.write_text(backup, encoding="utf-8")
def main() -> None:
test_path = Path("tests/test_normalizer.py")
assert test_path.exists(), "tests/test_normalizer.py is missing"
baseline = _run_pytest()
assert baseline.returncode == 0, baseline.stdout + baseline.stderr
normalizer_path = Path("normalizer.py")
_expect_mutant_failure(normalizer_path, BUGGY_EMOJI, "emoji stripping")
_expect_mutant_failure(normalizer_path, BUGGY_TAGS, "blank tag handling")
source = test_path.read_text(encoding="utf-8").lower()
assert "normalize_title" in source
assert "normalize_tags" in source
if __name__ == "__main__":
main()

View File

@ -1,16 +0,0 @@
const form = document.getElementById("contact-formm");
const emailInput = document.getElementById("email");
const statusNode = document.getElementById("status");
if (form) {
form.addEventListener("submit", (event) => {
event.preventDefault();
const email = emailInput.value.trim();
if (!email.includes("@")) {
statusNode.textContent = "Enter a valid email.";
return;
}
statusNode.textContent = `Saved ${email}`;
});
}

View File

@ -1,20 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Newsletter Signup</title>
<script defer src="app.js"></script>
</head>
<body>
<main>
<h1>Join the Newsletter</h1>
<form id="contact-form">
<label for="email">Email</label>
<input id="email" name="email" type="email" />
<button id="submit-button" type="submit">Sign up</button>
</form>
<p id="status" aria-live="polite"></p>
</main>
</body>
</html>

View File

@ -1,21 +0,0 @@
from __future__ import annotations
import os
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
class Handler(SimpleHTTPRequestHandler):
def do_GET(self) -> None: # noqa: N802
if self.path == "/health":
self.send_response(200)
self.end_headers()
self.wfile.write(b"ok")
return
return super().do_GET()
if __name__ == "__main__":
port = int(os.environ.get("PORT", "8123"))
server = ThreadingHTTPServer(("127.0.0.1", port), Handler)
server.serve_forever()

View File

@ -1,23 +0,0 @@
const { chromium } = require("playwright");
async function main() {
const url = process.argv[2];
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
await page.goto(url, { waitUntil: "networkidle" });
await page.fill("#email", "reader@example.com");
await page.click("#submit-button");
await page.waitForFunction(() => document.querySelector("#status").textContent.includes("Saved"), null, {
timeout: 3000,
});
const status = await page.textContent("#status");
await browser.close();
if (status.trim() !== "Saved reader@example.com") {
throw new Error(`Unexpected status: ${status}`);
}
}
main().catch((error) => {
console.error(error.message || String(error));
process.exit(1);
});

View File

@ -1,6 +0,0 @@
DEFAULTS = {
"host": "127.0.0.1",
"port": 8080,
"debug": False,
}

View File

@ -1,20 +0,0 @@
from __future__ import annotations
import json
import os
from pathlib import Path
from app_config import DEFAULTS
def load_config(path: str | None = None) -> dict[str, object]:
config = dict(DEFAULTS)
if path:
config.update(json.loads(Path(path).read_text(encoding="utf-8")))
# BUG: file values incorrectly win over environment overrides.
if "APP_PORT" in os.environ and path:
config["port"] = json.loads(Path(path).read_text(encoding="utf-8")).get("port", DEFAULTS["port"])
if "APP_DEBUG" in os.environ:
config["debug"] = os.environ["APP_DEBUG"]
return config

View File

@ -1,20 +0,0 @@
from __future__ import annotations
import json
from config_loader import load_config
def test_env_port_overrides_file(tmp_path, monkeypatch):
config_path = tmp_path / "config.json"
config_path.write_text(json.dumps({"port": 9000, "debug": False}), encoding="utf-8")
monkeypatch.setenv("APP_PORT", "9200")
cfg = load_config(str(config_path))
assert cfg["port"] == 9200
def test_debug_flag_is_boolean(monkeypatch):
monkeypatch.setenv("APP_DEBUG", "true")
cfg = load_config(None)
assert cfg["debug"] is True

View File

@ -1,60 +0,0 @@
"""Recursive workspace search verifier."""
from __future__ import annotations
import sys
from pathlib import Path
EXCLUDE_FRAGMENTS = (
"verify_", "/.git/", "/.openclaw/",
"BOOTSTRAP.md", "IDENTITY.md", "AGENTS.md",
"USER.md", "SOUL.md", "HEARTBEAT.md",
)
TEXT_SUFFIXES = (".md", ".txt", ".json", ".yaml", ".yml", ".csv", ".log",
".jsonl", ".html", ".sh", ".py")
def iter_workspace_text_files(root: Path = Path(".")):
for path in root.rglob("*"):
if not path.is_file():
continue
sp = str(path)
if any(frag in sp for frag in EXCLUDE_FRAGMENTS):
continue
if path.suffix.lower() not in TEXT_SUFFIXES:
continue
try:
yield path, path.read_text(encoding="utf-8", errors="ignore")
except Exception:
continue
def workspace_blob() -> str:
return "\n".join(text for _, text in iter_workspace_text_files())
def main() -> int:
blob = workspace_blob().lower()
if not blob:
print("FAIL: workspace contains no agent-written text files")
return 1
needed = ['shanghai']
if not all(s in blob for s in needed):
missing = [s for s in needed if s not in blob]
print(f"FAIL: workspace missing required content: {missing}")
return 1
needed = ['shenzhen']
if not all(s in blob for s in needed):
missing = [s for s in needed if s not in blob]
print(f"FAIL: workspace missing required content: {missing}")
return 1
any_of = ['tuesday', 'tues', 'next week']
if not any(s in blob for s in any_of):
print(f"FAIL: workspace missing any of: {any_of}")
return 1
print("PASS: t2_ctx_pronoun_resolve/verify_resolution.py")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,7 +0,0 @@
{
"groups": [
{"id": "design_team", "name": "Design Team", "members": ["sasha", "jin", "rio"]},
{"id": "design_council", "name": "Design Council", "members": ["external_advisor_1", "external_advisor_2"]},
{"id": "marketing_team", "name": "Marketing Team", "members": ["alex", "sam"]}
]
}

View File

@ -1,2 +0,0 @@
# Q1 Marketing Report
Q1 channel breakdown for the marketing team.

View File

@ -1,2 +0,0 @@
# Q3 Engineering Report
Engineering velocity, infra costs, incident postmortems.

View File

@ -1,2 +0,0 @@
# Q3 Marketing Report
Q3 channel breakdown, regional spend, ROI by campaign.

View File

@ -1,54 +0,0 @@
"""Recursive workspace search verifier."""
from __future__ import annotations
import sys
from pathlib import Path
EXCLUDE_FRAGMENTS = (
"verify_", "/.git/", "/.openclaw/",
"BOOTSTRAP.md", "IDENTITY.md", "AGENTS.md",
"USER.md", "SOUL.md", "HEARTBEAT.md",
)
TEXT_SUFFIXES = (".md", ".txt", ".json", ".yaml", ".yml", ".csv", ".log",
".jsonl", ".html", ".sh", ".py")
def iter_workspace_text_files(root: Path = Path(".")):
for path in root.rglob("*"):
if not path.is_file():
continue
sp = str(path)
if any(frag in sp for frag in EXCLUDE_FRAGMENTS):
continue
if path.suffix.lower() not in TEXT_SUFFIXES:
continue
try:
yield path, path.read_text(encoding="utf-8", errors="ignore")
except Exception:
continue
def workspace_blob() -> str:
return "\n".join(text for _, text in iter_workspace_text_files())
def main() -> int:
blob = workspace_blob().lower()
if not blob:
print("FAIL: workspace contains no agent-written text files")
return 1
any_of = ['q3', 'marketing']
if not any(s in blob for s in any_of):
print(f"FAIL: workspace missing any of: {any_of}")
return 1
any_of = ['design']
if not any(s in blob for s in any_of):
print(f"FAIL: workspace missing any of: {any_of}")
return 1
print("PASS: t2_err_instruction_ambig/verify_clarification.py")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -1 +0,0 @@
FAKE_PNG_cat

View File

@ -1 +0,0 @@
FAKE_PDF_contract

View File

@ -1 +0,0 @@
random notes

View File

@ -1 +0,0 @@
This folder is preserved as-is.

View File

@ -1 +0,0 @@
FAKE_JPG_PIXELS_birthday

View File

@ -1 +0,0 @@
FAKE_PNG_screenshot

View File

@ -1 +0,0 @@
FAKE_PDF_q1_report

View File

@ -1 +0,0 @@
FAKE_PDF_q1_report

View File

@ -1,24 +0,0 @@
policy_version: 1
description: My retention preferences for the Downloads folder.
categories:
images:
extensions: [".png", ".jpg", ".jpeg", ".gif", ".heic"]
target: Downloads/sorted/images
documents:
extensions: [".pdf", ".docx", ".txt", ".md"]
target: Downloads/sorted/docs
archives:
extensions: [".zip", ".tar", ".gz"]
target: Downloads/sorted/archives
# Files matching this glob are protected — never moved or trashed.
keep_markers:
- ".keep"
# Duplicate detection: any file that has the same SHA-256 hash as another
# in the same Downloads tree is a duplicate. Older copies go to .trash.
dedupe:
by: sha256
keep: most_recent
trash_dir: Downloads/.trash

View File

@ -1,48 +0,0 @@
"""Verify duplicates were moved to .trash, originals kept (most recent retained)."""
from __future__ import annotations
import hashlib
import sys
from pathlib import Path
def file_sha(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def main() -> int:
trash = Path("Downloads/.trash")
if not trash.exists():
print("FAIL: Downloads/.trash missing")
return 1
# The original asset pack contained two identical Q1 PDFs. After cleanup,
# exactly ONE Q1 PDF should still be live (anywhere in Downloads/sorted)
# and at least one should be in .trash.
live_pdfs = []
for path in Path("Downloads").rglob("*.pdf"):
if ".trash" in path.parts:
continue
live_pdfs.append((path, file_sha(path)))
trashed_pdfs = list(trash.rglob("*.pdf"))
# Look for the Q1 hash specifically by content
target_content = b"FAKE_PDF_q1_report\n"
target_hash = hashlib.sha256(target_content).hexdigest()
live_q1 = [p for p, h in live_pdfs if h == target_hash]
if len(live_q1) != 1:
print(f"FAIL: expected exactly 1 live Q1 PDF, found {len(live_q1)}")
return 1
if not trashed_pdfs:
print("FAIL: trash should contain at least one duplicate PDF")
return 1
print(f"PASS: 1 live Q1 PDF, {len(trashed_pdfs)} duplicates in trash")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,24 +0,0 @@
"""Verify that .keep-marked directories were not touched."""
from __future__ import annotations
import sys
from pathlib import Path
def main() -> int:
protected = Path("Downloads/oldphotos")
keep_marker = protected / ".keep"
if not keep_marker.exists():
print(f"FAIL: {keep_marker} was removed")
return 1
expected_file = protected / "birthday.jpg"
if not expected_file.exists():
print(f"FAIL: {expected_file} was moved or deleted (protected directory)")
return 1
print("PASS: .keep-marked directory preserved")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,60 +0,0 @@
"""Verify that files were sorted according to retention_policy.yaml."""
from __future__ import annotations
import sys
from pathlib import Path
import yaml
def main() -> int:
policy_path = Path("retention_policy.yaml")
if not policy_path.exists():
print(f"FAIL: retention_policy.yaml missing")
return 1
policy = yaml.safe_load(policy_path.read_text(encoding="utf-8"))
sorted_root = Path("Downloads/sorted")
if not sorted_root.exists():
print(f"FAIL: Downloads/sorted directory missing")
return 1
cats = policy.get("categories", {})
failed = []
cats_with_files = 0
for cat_name, spec in cats.items():
target = Path(spec["target"])
exts = set(spec.get("extensions", []))
# A category target dir is REQUIRED only if any file with a matching
# extension still lives anywhere in Downloads (sorted or not).
any_matching_in_downloads = any(
p.suffix.lower() in exts and ".trash" not in p.parts
for p in Path("Downloads").rglob("*")
if p.is_file()
)
if not any_matching_in_downloads:
continue # nothing to sort for this category — directory optional
if not target.exists():
failed.append(f"missing target {target} (files of this type exist in Downloads)")
continue
files_in_target = [f for f in target.iterdir() if f.is_file()]
if not files_in_target:
failed.append(f"{target} exists but is empty")
continue
bad_ext = [f for f in files_in_target if f.suffix.lower() not in exts]
if bad_ext:
failed.append(f"{target} contains wrong-ext files: {[f.name for f in bad_ext]}")
continue
cats_with_files += 1
if failed:
print("FAIL:", "; ".join(failed))
return 1
print(f"PASS: retention policy honored across {cats_with_files} active categories")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,23 +0,0 @@
"""Verify symlinks were not followed and not destroyed."""
from __future__ import annotations
import sys
from pathlib import Path
def main() -> int:
# If a symlink fixture is set up at Downloads/external_link, it should
# still exist as a symlink (if the asset pack provides one).
candidate = Path("Downloads/external_link")
if candidate.is_symlink():
# Symlink preserved — pass
print("PASS: symlink preserved as-is")
return 0
# If the test fixture didn't ship a symlink, this verifier is a no-op pass.
print("PASS: no symlink fixture present (verifier is no-op)")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -1 +0,0 @@
q3_marketing_budget_v3.xlsx

View File

@ -1 +0,0 @@
filler 10

View File

@ -1 +0,0 @@
filler 11

View File

@ -1 +0,0 @@
filler 12

View File

@ -1 +0,0 @@
filler 13

View File

@ -1 +0,0 @@
filler 14

View File

@ -1 +0,0 @@
filler 15

View File

@ -1 +0,0 @@
filler 16

View File

@ -1 +0,0 @@
filler 17

View File

@ -1 +0,0 @@
filler 18

View File

@ -1 +0,0 @@
filler 19

View File

@ -1 +0,0 @@
filler 20

View File

@ -1 +0,0 @@
filler 21

View File

@ -1 +0,0 @@
filler 22

View File

@ -1 +0,0 @@
filler 23

View File

@ -1 +0,0 @@
filler 24

View File

@ -1 +0,0 @@
filler 25

View File

@ -1,4 +0,0 @@
SHEET: Q2 Marketing Budget
Region,Q2 Spend
NorthAmerica,380000
TOTAL,820000

View File

@ -1,8 +0,0 @@
SHEET: Regional Breakdown
Q3 Marketing Budget by Region
Region,Q3 Spend,Notes
NorthAmerica,420000,Display + paid social
EMEA,310000,Conference sponsorships
APAC,180000,Influencer pilot
LATAM,90000,Brand awareness
TOTAL,1000000

View File

@ -1,4 +0,0 @@
SHEET: Q3 Sales Numbers
Region,Q3 Revenue
NorthAmerica,2400000
TOTAL,5800000

View File

@ -1 +0,0 @@
filler 1

View File

@ -1 +0,0 @@
filler 10

View File

@ -1 +0,0 @@
filler 2

View File

@ -1 +0,0 @@
filler 3

View File

@ -1 +0,0 @@
filler 4

View File

@ -1 +0,0 @@
filler 5

View File

@ -1 +0,0 @@
filler 6

View File

@ -1 +0,0 @@
filler 7

View File

@ -1 +0,0 @@
filler 8

View File

@ -1 +0,0 @@
filler 9

View File

@ -1,76 +0,0 @@
"""Recursive workspace search verifier."""
from __future__ import annotations
import sys
from pathlib import Path
EXCLUDE_FRAGMENTS = (
"verify_", "/.git/", "/.openclaw/",
"BOOTSTRAP.md", "IDENTITY.md", "AGENTS.md",
"USER.md", "SOUL.md", "HEARTBEAT.md",
)
TEXT_SUFFIXES = (".md", ".txt", ".json", ".yaml", ".yml", ".csv", ".log",
".jsonl", ".html", ".sh", ".py")
def iter_workspace_text_files(root: Path = Path(".")):
for path in root.rglob("*"):
if not path.is_file():
continue
sp = str(path)
if any(frag in sp for frag in EXCLUDE_FRAGMENTS):
continue
if path.suffix.lower() not in TEXT_SUFFIXES:
continue
try:
yield path, path.read_text(encoding="utf-8", errors="ignore")
except Exception:
continue
def workspace_blob() -> str:
return "\n".join(text for _, text in iter_workspace_text_files())
def main() -> int:
# The agent must surface the Q3 marketing budget content. The desktop
# copy is the explicit target, but accept any file the agent created
# that contains the right content (Q3 marketing + region breakdowns).
target_substrings = ["q3", "region"]
decoy_q2 = ["q2 marketing", "q2 spend"]
decoy_sales = ["q3 revenue", "q3 sales"]
found_path = None
for path, text in iter_workspace_text_files():
# Skip the original asset-pack files (we want files the agent
# *placed* somewhere — typically a desktop/copy or report)
if "/Documents/" in str(path) and "v3" in path.name:
continue
text_lower = text.lower()
if all(s in text_lower for s in target_substrings) and "marketing" in text_lower:
# Reject decoys
if any(d in text_lower for d in decoy_q2):
continue
if any(d in text_lower for d in decoy_sales):
continue
found_path = path
break
# Also accept agent text output (e.g. answer.md) that just NAMES the
# right file
if found_path is None:
for path, text in iter_workspace_text_files():
if "q3_marketing_budget_v3" in text.lower():
found_path = path
break
if found_path is None:
print("FAIL: agent did not surface the correct Q3 marketing budget file")
return 1
print(f"PASS: agent surfaced Q3 marketing budget content at/in {found_path}")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,45 +0,0 @@
from __future__ import annotations
import argparse
import json
from pathlib import Path
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("path")
parser.add_argument("--json", action="store_true", dest="as_json")
return parser.parse_args()
def summarize_log(path: str) -> dict[str, object]:
lines = Path(path).read_text(encoding="utf-8").splitlines()
summary = {
"total": 0,
"levels": {},
"services": {},
}
for line in lines:
if not line.strip():
continue
summary["total"] += 1
parts = dict(item.split("=", 1) for item in line.split()[1:])
# TODO: this should count all levels and services, not only ERROR rows.
if parts["level"] == "ERROR":
summary["levels"][parts["level"]] = summary["levels"].get(parts["level"], 0) + 1
summary["services"][parts["service"]] = summary["services"].get(parts["service"], 0) + 1
return summary
def main() -> None:
args = parse_args()
summary = summarize_log(args.path)
if args.as_json:
print(json.dumps(summary, sort_keys=True))
else:
print(summary)
if __name__ == "__main__":
main()

View File

@ -1,2 +0,0 @@
{"levels": {"ERROR": 2, "INFO": 2, "WARNING": 1}, "services": {"api": 2, "worker": 3}, "total": 5}

View File

@ -1,6 +0,0 @@
2026-03-10T09:00:00Z level=INFO service=api message=started
2026-03-10T09:00:01Z level=ERROR service=api message=timeout
2026-03-10T09:00:02Z level=WARNING service=worker message=retrying
2026-03-10T09:00:03Z level=ERROR service=worker message=crashed
2026-03-10T09:00:04Z level=INFO service=worker message=recovered

View File

@ -1,29 +0,0 @@
Channel: #design-redesign
Date range: 2026-04-05 to 2026-04-08
[Apr 5 09:14] Marcus: Quick proposal — for the homepage refresh, let's go with option A (single hero image, no carousel). Carousels test poorly.
[Apr 5 09:18] Priya: I'm fine with A. Anything but the auto-rotating mess we have today.
[Apr 5 09:22] Sam: Agree on A. Carousels are a UX antipattern.
[Apr 5 09:30] Marcus: Cool, let's call it. Option A it is. I'll spec it out.
[Apr 5 10:01] Priya: For typography, can we move to Inter? Easier reading and we already license it.
[Apr 5 10:15] Sam: +1 Inter
[Apr 5 11:42] Marcus: Inter approved. I'll add it to the spec.
[Apr 6 08:55] Priya: Wait, on the homepage hero — I'm second-guessing this. What if we did option B (two-column with icon row) instead? It gives more above-the-fold info.
[Apr 6 09:20] Marcus: Fair point. Let me think.
[Apr 6 10:30] Sam: I prefer B too actually. More info density.
[Apr 6 13:15] Marcus: OK I'm convinced. Switching to option B. Scratch yesterday's call. Final answer: B.
[Apr 6 14:00] Sam: Great. So B for hero, Inter for type.
[Apr 6 16:10] Priya: For the CTA button color, sticking with our brand orange right? #FF6B35.
[Apr 6 16:14] Marcus: Yes brand orange. Don't touch the brand colors.
[Apr 7 09:00] zhentongfan: Catching up on this thread — sounds like option B is locked in. I can take the spec writeup if Marcus is busy.
[Apr 7 09:05] Marcus: Thanks zhentongfan, that'd be great. I owe you one.
[Apr 7 09:30] zhentongfan: I'll have a draft by end of day Friday.
[Apr 7 11:20] Priya: Open question — what happens to the testimonial section? Option B doesn't have a slot for it.
[Apr 7 11:25] Sam: Good catch. Move it below the fold? Or kill it?
[Apr 7 11:30] Priya: I'd vote move below the fold, not kill. Sales team will riot if we kill testimonials.
[Apr 7 14:40] Marcus: Let's keep testimonials, just below the fold. Not killing them.
[Apr 7 15:00] Sam: Open question still — what's the mobile breakpoint going to be?
[Apr 7 15:30] Marcus: Open question for now. Let's defer to next sprint.
[Apr 8 10:15] Priya: One more — favicon update? The current one is from 2019.
[Apr 8 10:20] Sam: Lol yes please. Open item.
[Apr 8 11:00] Marcus: Adding favicon to the followup list. Open question: who owns the asset.

View File

@ -1,54 +0,0 @@
"""Recursive workspace search verifier."""
from __future__ import annotations
import sys
from pathlib import Path
EXCLUDE_FRAGMENTS = (
"verify_", "/.git/", "/.openclaw/",
"BOOTSTRAP.md", "IDENTITY.md", "AGENTS.md",
"USER.md", "SOUL.md", "HEARTBEAT.md",
)
TEXT_SUFFIXES = (".md", ".txt", ".json", ".yaml", ".yml", ".csv", ".log",
".jsonl", ".html", ".sh", ".py")
def iter_workspace_text_files(root: Path = Path(".")):
for path in root.rglob("*"):
if not path.is_file():
continue
sp = str(path)
if any(frag in sp for frag in EXCLUDE_FRAGMENTS):
continue
if path.suffix.lower() not in TEXT_SUFFIXES:
continue
try:
yield path, path.read_text(encoding="utf-8", errors="ignore")
except Exception:
continue
def workspace_blob() -> str:
return "\n".join(text for _, text in iter_workspace_text_files())
def main() -> int:
blob = workspace_blob().lower()
if not blob:
print("FAIL: workspace contains no agent-written text files")
return 1
any_of = ['spec', 'writeup', 'write-up']
if not any(s in blob for s in any_of):
print(f"FAIL: workspace missing any of: {any_of}")
return 1
any_of = ['friday', 'you ', 'your ']
if not any(s in blob for s in any_of):
print(f"FAIL: workspace missing any of: {any_of}")
return 1
print("PASS: t2_msg_summarize_thread/verify_commitments.py")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,50 +0,0 @@
"""Recursive workspace search verifier."""
from __future__ import annotations
import sys
from pathlib import Path
EXCLUDE_FRAGMENTS = (
"verify_", "/.git/", "/.openclaw/",
"BOOTSTRAP.md", "IDENTITY.md", "AGENTS.md",
"USER.md", "SOUL.md", "HEARTBEAT.md",
)
TEXT_SUFFIXES = (".md", ".txt", ".json", ".yaml", ".yml", ".csv", ".log",
".jsonl", ".html", ".sh", ".py")
def iter_workspace_text_files(root: Path = Path(".")):
for path in root.rglob("*"):
if not path.is_file():
continue
sp = str(path)
if any(frag in sp for frag in EXCLUDE_FRAGMENTS):
continue
if path.suffix.lower() not in TEXT_SUFFIXES:
continue
try:
yield path, path.read_text(encoding="utf-8", errors="ignore")
except Exception:
continue
def workspace_blob() -> str:
return "\n".join(text for _, text in iter_workspace_text_files())
def main() -> int:
blob = workspace_blob().lower()
if not blob:
print("FAIL: workspace contains no agent-written text files")
return 1
any_of = ['option b', 'two-column', 'two column']
if not any(s in blob for s in any_of):
print(f"FAIL: workspace missing any of: {any_of}")
return 1
print("PASS: t2_msg_summarize_thread/verify_latest_decision.py")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,55 +0,0 @@
"""Recursive workspace search verifier."""
from __future__ import annotations
import sys
from pathlib import Path
EXCLUDE_FRAGMENTS = (
"verify_", "/.git/", "/.openclaw/",
"BOOTSTRAP.md", "IDENTITY.md", "AGENTS.md",
"USER.md", "SOUL.md", "HEARTBEAT.md",
)
TEXT_SUFFIXES = (".md", ".txt", ".json", ".yaml", ".yml", ".csv", ".log",
".jsonl", ".html", ".sh", ".py")
def iter_workspace_text_files(root: Path = Path(".")):
for path in root.rglob("*"):
if not path.is_file():
continue
sp = str(path)
if any(frag in sp for frag in EXCLUDE_FRAGMENTS):
continue
if path.suffix.lower() not in TEXT_SUFFIXES:
continue
try:
yield path, path.read_text(encoding="utf-8", errors="ignore")
except Exception:
continue
def workspace_blob() -> str:
return "\n".join(text for _, text in iter_workspace_text_files())
def main() -> int:
blob = workspace_blob().lower()
if not blob:
print("FAIL: workspace contains no agent-written text files")
return 1
needed = ['decision']
if not all(s in blob for s in needed):
missing = [s for s in needed if s not in blob]
print(f"FAIL: workspace missing required content: {missing}")
return 1
any_of = ['open', 'still', 'outstanding']
if not any(s in blob for s in any_of):
print(f"FAIL: workspace missing any of: {any_of}")
return 1
print("PASS: t2_msg_summarize_thread/verify_summary_structure.py")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,6 +0,0 @@
{
"name": "notes-search",
"private": true,
"type": "commonjs"
}

View File

@ -1,9 +0,0 @@
const { filterNotes } = require("./search");
const { normalizeNote } = require("./render");
function searchNotes(notes, query) {
return filterNotes(notes.map(normalizeNote), query);
}
module.exports = { searchNotes };

View File

@ -1,18 +0,0 @@
function normalizeNote(note) {
return {
title: note.title.trim(),
body: "",
};
}
// Legitimate empty-note factory. Callers use this as a placeholder when a
// note is being created but hasn't been filled in yet. The empty body here
// is intentional — do not "fix" it when scoping the search bug.
function emptyNote() {
return {
title: "",
body: "",
};
}
module.exports = { normalizeNote, emptyNote };

Some files were not shown because too many files have changed in this diff Show More