feat(ia): IA גל-2 — איחוד-משטחים: ערוץ-למידה אחד · /operations⊇/diagnostics · MET-2/3 (#131, X17)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 9s
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 9s
גל-2 מבקלוג #127 — איחוד-משטחים לפי משטח-היעד של X17. מקיים INV-IA1/IA3/IA4 + דלתות-הספ (X6 INV-UI7/8, 07-learning §0.4, 00-constitution G2). שומר G10/INV-LRN1 (לא הוסר שום שער-אנושי — רק שער/דגל כפול). א) תיבת-אישור אחת (INV-IA1): כרטיסי "אישור הלכות"+"פסיקה חסרה" ב-/operations מצביעים ל-/approvals (לתיבת-האישורים ←) — /operations מנטר, /approvals מחליט. ב) ערוץ-למידה אחד (INV-IA3): הוסר applied_to_skill end-to-end — - UI: כפתור "סמן כ'אומץ'" + badge "אומץ" ב-lessons-tab; badge ב-curator-portrait. - API: LessonPatch, _lesson_to_json, patch call, curator recent_findings (→review_status). - db.py: list/add/update_decision_lesson לא בוחרים/כותבים applied_to_skill; הפרמטר הוסר. העמודה+אינדקס נשמרים (back-compat, ללא migration), מסומנים DEPRECATED. - types: DecisionLesson/LessonPatch/CuratorFinding. review_status='approved' = הסטטוס היחיד "זורם-לכותב" (INV-LRN1, #126). ג) MET-2/3 lost-update (INV-IA3): _append_methodology_override רץ עכשיו בטרנזקציה אחת עם SELECT ... FOR UPDATE — אין read-modify-write מתפצל מול עורך-המתודולוגיה או promote מקביל. /methodology = העורך-הקנוני; promote מבטל את ה-cache (גל-1 MET-1). ד) /operations⊇/diagnostics (INV-IA4): גוף /diagnostics חולץ ל-<SystemHealthSection/> ומורנדר ב-/operations תחת "בריאות-מערכת". /diagnostics → redirect ל-/operations. /diagnostics הוסר מהניווט. משטח-ניטור יחיד. ה) דלתות-ספ (≥3 מקורות ב-X17, אושר ע"י חיים /goal): - X6: INV-UI7 (aggregate=SSoT, mutation מבטל queryKey) + INV-UI8 (render-or-remove, חלקיות). - 07-learning §0.4: שער-אחד + טרנזקציה-אחת + applied_to_skill מוסר. - 00-constitution G2: תאום-המתודולוגיה כהפרה-ידועה-ממותנת. - X17 דלתות-ספ סומנו ✅ קודדו. בדיקות: py_compile app.py + db.py ✓ · tsc --noEmit ✓ · eslint ✓ (לבד מ-learning-panel:109 קיים-מראש). next build נכשל ב-worktree רק בגלל symlink (Turbopack) — Docker/CI תקין. api:types יתרענן בדפלוי (curator/lessons אינם response-modeled; הטיפוסים יד-כתובים עודכנו). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -213,7 +213,7 @@ CREATE TABLE IF NOT EXISTS decision_lessons (
|
||||
lesson_text TEXT NOT NULL,
|
||||
category TEXT DEFAULT 'general', -- style / structure / lexicon / tabular / general
|
||||
source TEXT DEFAULT 'manual', -- manual / curator / chair / style_analyzer
|
||||
applied_to_skill BOOLEAN DEFAULT false, -- has this been promoted into SKILL.md?
|
||||
applied_to_skill BOOLEAN DEFAULT false, -- DEPRECATED (LRN-1/INV-IA3, #131): informative-only flag, no longer read/written; review_status is the single writer gate. Column kept for back-compat (no migration).
|
||||
created_by TEXT DEFAULT 'chaim',
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now()
|
||||
@@ -2269,9 +2269,12 @@ async def update_style_corpus_metadata(
|
||||
async def list_decision_lessons(corpus_id: UUID) -> list[dict]:
|
||||
pool = await get_pool()
|
||||
async with pool.acquire() as conn:
|
||||
# applied_to_skill column retained for back-compat but no longer selected
|
||||
# (LRN-1/INV-IA3: the informative-only flag was removed from the surface;
|
||||
# review_status is the single writer gate).
|
||||
rows = await conn.fetch(
|
||||
"SELECT id, style_corpus_id, lesson_text, category, source, "
|
||||
" applied_to_skill, review_status, created_by, created_at, updated_at "
|
||||
" review_status, created_by, created_at, updated_at "
|
||||
"FROM decision_lessons WHERE style_corpus_id = $1 "
|
||||
"ORDER BY created_at DESC",
|
||||
corpus_id,
|
||||
@@ -2298,7 +2301,7 @@ async def add_decision_lesson(
|
||||
"(style_corpus_id, lesson_text, category, source, created_by, review_status) "
|
||||
"VALUES ($1, $2, $3, $4, $5, $6) "
|
||||
"RETURNING id, style_corpus_id, lesson_text, category, source, "
|
||||
" applied_to_skill, review_status, created_by, created_at, updated_at",
|
||||
" review_status, created_by, created_at, updated_at",
|
||||
corpus_id, lesson_text, category, source, created_by, review_status,
|
||||
)
|
||||
return dict(row) if row else {}
|
||||
@@ -2309,16 +2312,15 @@ async def update_decision_lesson(
|
||||
*,
|
||||
lesson_text: str | None = None,
|
||||
category: str | None = None,
|
||||
applied_to_skill: bool | None = None,
|
||||
review_status: str | None = None,
|
||||
) -> dict:
|
||||
# applied_to_skill removed (LRN-1/INV-IA3): it was an informative-only flag
|
||||
# that wrote nowhere; review_status is the single writer gate (INV-LRN1).
|
||||
sets: dict = {}
|
||||
if lesson_text is not None:
|
||||
sets["lesson_text"] = lesson_text
|
||||
if category is not None:
|
||||
sets["category"] = category
|
||||
if applied_to_skill is not None:
|
||||
sets["applied_to_skill"] = applied_to_skill
|
||||
if review_status is not None:
|
||||
sets["review_status"] = review_status
|
||||
if not sets:
|
||||
@@ -2333,7 +2335,7 @@ async def update_decision_lesson(
|
||||
row = await conn.fetchrow(
|
||||
f"UPDATE decision_lessons SET {set_clause} WHERE id = $1 "
|
||||
f"RETURNING id, style_corpus_id, lesson_text, category, source, "
|
||||
f" applied_to_skill, review_status, updated_at",
|
||||
f" review_status, updated_at",
|
||||
lesson_id, *values,
|
||||
)
|
||||
if not row:
|
||||
|
||||
Reference in New Issue
Block a user