chore(int9): שער-סטטי ל-INV-INT9 — issues.update({status}) רק במסלול sync-case-status (legal-ai #618) #14
Reference in New Issue
Block a user
Delete Branch "chore/618-inv-int9-ci-gate"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
מה זה עושה
אוכף את INV-INT9 — בעלות-כתיבה יחידה על
issue.status.ל-
issue.statusכותב לגיטימי אחד בפלאגין: הג'ובsync-case-status(
ctx.jobs.register("sync-case-status", …),src/worker.ts:898), והקריאה היחידה בכל הריפויושבת בתוכו (
src/worker.ts:991). עד היום האכיפה הייתה code-review בלבד — וזה בדיוק מהשאפשר את legal-ai #446 (flip-flop
done → in_progress): כותב שני שנכנס בלי שאיש שם לב.איך
scripts/int9-guard.mjsscripts/fixtures/int9/*.ts(5)--self-test, מחוץ ל-src/בכוונהpackage.jsonnpm run int9:guard·npm run int9:guard:self-testטוקנייזר תו-תו (מחרוזות · template עם
${}מקונן · הערות · רגקס-ליטרלים) בונה מסכת"קוד רגיל", ומעליה: כל
jobs.register("sync-case-status", …)מגדיר טווח-תווים מותר(איזון-סוגריים), וכל
issues.update(…)שרשימת-הארגומנטים שלו מכילה את המזההstatusחייב לשבת בתוכו.
למה טווח-קוד ולא whitelist-לפי-קובץ (הדפוס של
leak_guard.pyב-legal-ai): הקריאההמותרת היחידה וכל קריאה עתידית אסורה יושבות באותו
worker.tsבן 1,795 השורות.רשימת-קבצים הייתה מתירה את כולן. הטווח נגזר מהמבנה האמיתי, ולכן שורד מעבר של הג'וב לקובץ
אחר — ושינוי שם-הג'וב מפיל את השער בקול (אומת, M3 למטה).
חריגה מכוונת:
// noqa: INT9 — <נימוק>.noqa: INT9בלי נימוק הוא הפרה בעצמו.כשל-פענוח (סוגר שלא נסגר) מפיל את השער ולא נבלע כ"נקי".
מגבלה מוצהרת: תיל-מעידה סטטי, לא הוכחה —
issues.update(id, patch)שבו אובייקט-העדכוןנבנה במקום אחר אינו נתפס. כתוב בכותרת-הסקריפט וגם בספ (
X7, legal-ai#705).⚠️ ה-PR הזה מוזג בלי קובץ ה-workflow — בכוונה
ה-Gitea Actions runner היחיד על nautilus רשום בהיקף-repo ל-
legal-aiבלבד:/repos/…/plugin-legal-ai/actions/runners→total_count: 0;/orgs/ezer-mishpati/actions/runners→total_count: 0.לכן job של הריפו הזה לא נאסף לעולם — נמדד: ריצה
3200/ job3250ישבה ב-queuedעםstarted_at: 1970-01-01, בזמן שה-runner היהbusy: falseוהריץ 7/7 שערים של legal-ai.פאנל בן 5 מומחים הכריע 4/5 שאין לשנות תשתית-ייצור אוטונומית בשביל משימת
p3-low.מיזוג
.gitea/workflows/int9-guard.yamlל-mainהיה הופך את הריפו מאפס checksלcheck תקוע-לנצח בכל PR עתידי (13 PRs ממוזגים עד היום), וגורם ל-AC2 להיראות מסופק
בזמן שהוא חסום. לכן ה-workflow יושב ב-PR נפרד וחסום — שהוא גם המדידה: ביום שיירשם
runner לריפו הזה, ה-PR ההוא יהפוך לירוק מעצמו.
עד אז השער רץ ידנית:
npm run int9:guard·npm run int9:guard:self-test.אימות שהורץ (לא "הסקריפט קיים")
מוטציה חיה על הקוד האמיתי (הוזרקה, נתפסה, שוחזרה —
src/לא נגעה ב-PR):issues.update({status})בתוךstale-case-remindersrc/worker.ts:1018· exit 1{ status }בקובץ אחר (sync-target.ts)src/sync-target.ts:153· exit 1sync-case-status-v2src/worker.ts:991· exit 1 (הטווח אינו no-op)אפס false positives על 4,255 שורות
src/הקיימות.src/לא שונתה — אין שינויהתנהגות-ריצה של הפלאגין.
Invariants
legal-ai docs/spec/X7-paperclip-client-params.md§4) — מנוהל לשער ניתן-להרצה.issue.status.מסלול-חזרה
git revertשל קומיט-המיזוג. אפס תלות בתשתית — לא נגענו ב-runner, ב-Coolify או ב-DB.Refs ezer-mishpati/legal-ai#618
ל-`issue.status` כותב לגיטימי אחד בפלאגין: הג'וב `sync-case-status` (`ctx.jobs.register("sync-case-status", …)` ב-`src/worker.ts`). עד היום האכיפה הייתה code-review בלבד — וזה בדיוק מה שאפשר את הבאג של legal-ai #446 (flip-flop `done → in_progress`), כותב שני שנכנס בלי שאיש שם לב. `scripts/int9-guard.mjs` — Node ESM חסר-תלויות. טוקנייזר תו-תו (מחרוזות/תבניות עם `${}` מקונן/הערות/רגקס-ליטרלים) בונה מסכת "קוד רגיל", ומעליה: כל `jobs.register("sync-case-status", …)` מגדיר **טווח-תווים מותר** (איזון-סוגריים), וכל `issues.update(…)` שרשימת-הארגומנטים שלו מכילה את המזהה `status` חייב לשבת בתוכו. הגרעיניות היא טווח-קוד ולא רשימת-קבצים (הדפוס של `leak_guard.py` ב-legal-ai) במכוון: הקריאה המותרת היחידה וכל קריאה עתידית אסורה יושבות באותו `worker.ts`. הטווח נגזר מהמבנה האמיתי, ולכן שורד מעבר של הג'וב לקובץ אחר — ושינוי שם-הג'וב מפיל את השער בקול במקום לפתוח חור שקט. חריגה מכוונת: `// noqa: INT9 — <נימוק>`. `noqa: INT9` בלי נימוק הוא הפרה בעצמו — אין השתקה שקטה. כשל-פענוח (סוגר שלא נסגר) מפיל את השער ולא נבלע. `--self-test` מריץ 5 פיקסצ'רים (`scripts/fixtures/int9/`, מחוץ ל-`src/` בכוונה) ומאמת ספירת-הפרות מדויקת — הוכחה שהשער נושך. **ללא חיווט-CI.** ה-runner היחיד על nautilus רשום בהיקף-repo ל-`legal-ai` בלבד (`action_runner.repo_id = 6`), ולכן job של הריפו הזה לא נאסף לעולם (נמדד: ריצה 3200 / job 3250 תקוע ב-`queued`, `started_at: 1970-01-01`). קובץ ה-workflow יושב ב-PR נפרד וחסום, כדי שלא ייכנס ל-`main` שער שמייצר check תקוע-לנצח בכל PR עתידי. עד אז: `npm run int9:guard` / `npm run int9:guard:self-test`. מגבלה מוצהרת: תיל-מעידה סטטי, לא הוכחה — `issues.update(id, patch)` שבו אובייקט-העדכון נבנה במקום אחר אינו נתפס. Refs ezer-mishpati/legal-ai#618 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>fa1bda524dtob24d816cc0chore(ci): שער-CI ל-INV-INT9 — issues.update({status}) רק במסלול sync-case-status (legal-ai #618)to chore(int9): שער-סטטי ל-INV-INT9 — issues.update({status}) רק במסלול sync-case-status (legal-ai #618)