feat: enforce hard test-tier requirement across all DevPlace workflow agents and feature-builder docs
DevPlace CI / test (push) Failing after 21m53s

Update the feature-builder agent prompt, test-maintainer agent, and all four workflow JS files (devii-tool, endpoint, feature, job-service) to codify the DevPlace test standard as a non-optional project requirement: one test file per endpoint, directory tree mirroring the URL/source path, split into three tiers (unit, api, e2e). Add explicit Test phases to devii-tool, endpoint, feature, and job-service workflows, and embed tier-specific test instructions (path mapping, fixture choice, coverage scope) directly in each workflow's meta description and TESTS constant.
This commit is contained in:
2026-06-15 12:10:14 +00:00
parent 3c7527988e
commit e1874f9b6a
71 changed files with 2198 additions and 145 deletions
+70 -8
View File
@@ -6,7 +6,8 @@ import hashlib
import logging
import math
import re
from dataclasses import dataclass
import time
from dataclasses import dataclass, field
from devplacepy import stealth
from devplacepy.config import INTERNAL_EMBED_MODEL, INTERNAL_EMBED_URL
@@ -22,6 +23,23 @@ TOKEN_PATTERN = re.compile(r"[a-z0-9]+")
class EmbedResult:
vectors: list[list[float]]
backend: str
latency_ms: int = 0
cache_hits: int = 0
@dataclass
class EmbeddingCache:
store: dict[str, list[float]] = field(default_factory=dict)
def key(self, text: str) -> str:
return hashlib.sha1((text or "").encode("utf-8")).hexdigest()
def get(self, text: str) -> list[float] | None:
return self.store.get(self.key(text))
def put(self, text: str, vector: list[float]) -> None:
if vector:
self.store[self.key(text)] = vector
def _local_vector(text: str) -> list[float]:
@@ -41,19 +59,51 @@ def _local_vector(text: str) -> list[float]:
def local_embed(texts: list[str]) -> EmbedResult:
return EmbedResult(vectors=[_local_vector(text) for text in texts], backend="local")
start = time.monotonic()
vectors = [_local_vector(text) for text in texts]
latency_ms = int((time.monotonic() - start) * 1000)
return EmbedResult(vectors=vectors, backend="local", latency_ms=latency_ms)
async def embed_texts(
texts: list[str], api_key: str, *, gateway_url: str = INTERNAL_EMBED_URL
texts: list[str],
api_key: str,
*,
gateway_url: str = INTERNAL_EMBED_URL,
cache: EmbeddingCache | None = None,
) -> EmbedResult:
if not texts:
return EmbedResult(vectors=[], backend="empty")
cache_hits = 0
pending_index: list[int] = []
pending_text: list[str] = []
resolved: list[list[float] | None] = [None] * len(texts)
if cache is not None:
for index, text in enumerate(texts):
cached_vector = cache.get(text)
if cached_vector is not None:
resolved[index] = cached_vector
cache_hits += 1
else:
pending_index.append(index)
pending_text.append(text)
else:
pending_index = list(range(len(texts)))
pending_text = list(texts)
if not pending_text:
return EmbedResult(
vectors=[vector or [] for vector in resolved],
backend="cache",
latency_ms=0,
cache_hits=cache_hits,
)
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
payload = {"model": INTERNAL_EMBED_MODEL, "input": texts}
payload = {"model": INTERNAL_EMBED_MODEL, "input": pending_text}
start = time.monotonic()
backend = "gateway"
try:
async with stealth.stealth_async_client(timeout=EMBED_TIMEOUT_SECONDS) as client:
response = await client.post(gateway_url, json=payload, headers=headers)
@@ -61,10 +111,22 @@ async def embed_texts(
raise RuntimeError(f"embed gateway returned {response.status_code}")
data = response.json()
rows = data.get("data") or []
vectors = [row.get("embedding") or [] for row in rows]
if len(vectors) != len(texts) or any(not vector for vector in vectors):
fresh = [row.get("embedding") or [] for row in rows]
if len(fresh) != len(pending_text) or any(not vector for vector in fresh):
raise RuntimeError("embed gateway returned an incomplete response")
return EmbedResult(vectors=vectors, backend="gateway")
except Exception as exc:
logger.warning("deepsearch embedding gateway failed, using local: %s", exc)
return local_embed(texts)
fresh = [_local_vector(text) for text in pending_text]
backend = "local"
latency_ms = int((time.monotonic() - start) * 1000)
for offset, index in enumerate(pending_index):
vector = fresh[offset]
resolved[index] = vector
if cache is not None:
cache.put(pending_text[offset], vector)
return EmbedResult(
vectors=[vector or [] for vector in resolved],
backend=backend,
latency_ms=latency_ms,
cache_hits=cache_hits,
)