yongol — השדרה של SaaS מקודד בינה מלאכותית תמונה: נוצרה על ידי AI

אם ה-AI ממשיך לדרוס את הקוד שלכם, אם vibe coding קרס ב-200 endpoints, אם אתם רוצים להעביר את עומס העבודה של ה-AI מקוד למפרטים – yongol הוא השדרה הזו.

ה-Endpoint ה-200

אתה בונה SaaS עם vibe coding. בהתחלה זה מהיר. 5 טבלאות, 12 endpoints — עשרים דקות וזה עובד.

אבל אחרי 50 endpoints, משהו מוזר קורה. ה-AI מייצר היום תבנית שסותרת את של אתמול. אחרי 100, פיצ’רים קיימים נשברים בשקט. אחרי 200, הוספת פיצ’ר אחד עולה פי 10 מעשרת הראשונים.

דוח DORA 2025 הוכיח זאת אמפירית — כלי AI מגדילים תפוקה ב-2-18%, אבל במקביל מגדילים את שיעור כשלון השינויים ואת העבודה החוזרת[1]. AI הוא “מראה ומכפיל” שמגביר חולשות של תהליכים קיימים.

לא בגלל שהמודל טיפש.


החלטות ומימוש

שלושה דברים שזורים בקוד מקור:

  • החלטות משתמש — העמודה הזו היא BIGINT, ה-endpoint הזה רק לבעלים, הדפדוף מבוסס cursor.
  • לוגיקה עסקית — מדיניות תמחור, תהליכי עבודה, כללי מחזור חיים.
  • פרטי מימוש — שמות משתנים, סדר קריאות לספריות, עטיפת שגיאות.

כש-AI קורא את הקוד הזה, הוא לא יכול להבדיל בין שורה שהיא החלטה לשורה שהיא פרט. אז כשהוא “מרפקטר” או “מנקה”, הוא דורס בשקט החלטות שחשב שהן פרטים. המשתמש מבחין רק אחרי שההתנהגות כבר שגויה. ב-1972, Parnas אמר “הסתר החלטות עיצוב שצפויות להשתנות מאחורי ממשקים”[2] — הוא דיבר לבני אדם. אבל עכשיו ש-AI עורך קוד, אלא אם ההבחנה בין החלטות לפרטים קיימת במדיום עצמו, אף אחד — בן אדם או מודל — לא יכול לשמור עליה.

זו הסיבה ש-vibe coding קורס ב-200 endpoints. מודל גדול יותר לא פותר את זה. המדיום — קוד גולמי — פשוט לא משמר החלטות. כל מודל בסוף נתקל באותה קיר.


השדרה

השדרה היא העצם הראשונה שמניחים כשבונים ספינה. היא נושאת את משקל הגוף, מונעת נדנוד צדדי, וכל מבנה אחר נבנה מעליה. ספינה שנבנתה בלי שדרה צפה במים שקטים אבל מתעוותת כשבאים הגלים.

SaaS שנבנה עם vibe coding — אותו דבר. צף כשהוא קטן. מתעוות כשהוא גדל.

yongol הוא השדרה של SaaS מקודד בינה מלאכותית.

Harness with reins — לא מודל גדול יותר, אלא מושכות מדויקות יותר. מאמת דטרמיניסטי שופט כל תוצר, רצ’ט כופה התקדמות, והמכונה מחליטה אם העבודה הושלמה.


להוציא החלטות מהקוד

הליבה של yongol פשוטה. להפריד החלטות מקוד.

עשרה מפרטים הצהרתיים (SSOT) כל אחד מטפל באחריות אחת:

SSOTאחריות
features.yamlקטלוג פיצ’רים — מה לבנות
manifest.yamlהגדרות פרויקט — אימות, middleware, תשתית
OpenAPIחוזה API — נתיבים, פרמטרים, תגובות
SQL DDL + sqlcמודל נתונים — טבלאות, עמודות, אילוצים, שאילתות
SSaCזרימת שירות — רצף החלטות בתוך endpoint
Regoהרשאות — מי יכול לעשות מה
Mermaid stateDiagramמעברי מצב — מחזורי חיים של ישויות
FuncSpecפונקציות מותאמות — לוגיקה שלא ניתנת לביטוי כ-CRUD
Hurlתרחישי בדיקה — טריכוטומיה smoke, scenario, invariant
STMLFrontend — Semantic Template Markup Language (HTML מבוסס תכונות data-*)

שמונה מתוך עשרה הם תקני תעשייה (OpenAPI, SQL, sqlc, Rego, Mermaid, Hurl, YAML). רק SSaC ו-STML הם DSL שנוצרו על ידי yongol. מה ש-AI צריך ללמוד מאפס ממוזער.

כל SSOT מכיל רק החלטות. בלי פרטי מימוש. AI עורך SSOT; yongol generate מרנדר קוד מהם. החלטות חיות לצמיתות ב-SSOT; הקוד הוא הקרנה חד-פעמית.


אכיפת עקביות

החלטות מפוזרות עכשיו על פני עשרה קבצים, אז סתירות יכולות להופיע. DDL אומר BIGINT אבל OpenAPI אומר string? SSaC מצהיר @auth אבל ל-Rego אין כלל מתאים? לדיאגרמת המצבים יש מעבר אבל ל-SSaC אין פונקציה מתאימה?

SSOT סותר הוא החלטה פגומה. לא משנה כמה הקוד נקי, אם ההחלטות מתנגשות — ההתנהגות שגויה.

yongol validate תופס את זה.

✓ manifest        ✓ openapi_ddl       ✓ ssac_rego
✓ openapi         ✓ openapi_ssac      ✓ ssac_authz
✓ ddl             ✓ hurl_openapi      ✓ ssac_sqlc
✓ query           ✓ hurl_statemachine ✓ ddl_statemachine
✓ ssac            ✓ hurl_manifest     ✓ ddl_rego
✓ statemachine    ✓ openapi_manifest  ✓ rego_manifest
✓ rego            ✓ ssac_ddl          ✓ stml_openapi
✓ hurl            ✓ ssac_statemachine
✓ funcspec        ✓ ssac_func

0 errors, 0 warnings

קודם מאמת כל SSOT בנפרד, ואז מריץ בדיקות צולבות בין שכבות. כ-287 כללים בודקים כל הפניה סמלית בין כל עשרת ה-SSOT. אם קיימת סתירה אחת, הקומפילציה נדחית. סקירת הספרות השיטתית של Torres ואחרים[3] ציינה שרוב כלי ניהול המודלים מטפלים רק בעקביות בתוך מודל בודד, ומשאירים אימות צולב בין מודלים הטרוגניים כבעיה פתוחה — yongol validate ממלא בדיוק את הפער הזה.

ה-AI כותב בחופשיות. יוצא מהפסים — validate תופס מיד. חופש על פסים.


yongol next — פקודת הרצ’ט

בעוד yongol validate מציג את כל השגיאות בבת אחת, yongol next מציג שגיאות אחת אחת. זה הרצ’ט.

$ yongol next specs/

[ERROR] DDL-003: users.id must be BIGINT, got INT
  file: specs/db/users.sql:2
  ▶ Fix this error. Then run `yongol next specs/`.

ההוראה היחידה שסוכן AI צריך היא משפט אחד: “הרץ yongol next specs/ ותקן שגיאות עד שיהיו 0.”

תקן את השגיאה, הבאה מופיעה. עבור את כולן וזה עוצר:

$ yongol next specs/

✓ All validations passed. 0 errors.

הסוכן לא מכריז “סיימתי”. המכונה פוסקת “עוד נשאר” או “הכל עבר”. לסוכן אין סמכות על שיפוט הסיום.


יצירת פרויקט וניהול פיצ’רים

yongol init

מייצר אוטומטית פיגום SSOT מ-features.yaml.

yongol init Myapp features.yaml "My workflow automation SaaS"
cd Myapp && yongol validate specs     # 0 errors

manifest, שלדי operationId ב-OpenAPI, קבצי שלד SSaC, כללי הרשאות Rego, בדיקות smoke של Hurl, והגדרות sqlc נוצרים בבת אחת. הפרויקט מתחיל במצב עובר yongol validate מההתחלה.

yongol features add / remove

הוספה או הסרה של פיצ’רים:

yongol features add new_features.yaml         # יצירת שלדי SSaC ל-operationIds חדשים
yongol features remove ExportWorkflow --yes    # מחיקת operationId + שלדי SSaC

yongol import

יצירת חבילות לקוח Go ממפרטי OpenAPI חיצוניים (Stripe, GitHub, וכו’):

yongol import https://api.stripe.com/openapi.yaml ./external/

קריאה לפונקציות שנוצרו ב-SSaC עם @call <pkg>.<Func>({...}).


operationId הוא אבן הקשת

איך קושרים עשר שכבות יחד? עם מזהה PascalCase אחד.

הזן את ה-operationId ExecuteWorkflow:

── Feature Chain: ExecuteWorkflow ──

  OpenAPI    api/openapi.yaml                POST /workflows/{id}/execute
  SSaC       service/workflow/execute_workflow.ssac   @get @empty @auth @state @call @publish @response
  DDL        db/workflows.sql                CREATE TABLE workflows
  DDL        db/execution_logs.sql           CREATE TABLE execution_logs
  Rego       policy/authz.rego               resource: workflow
  StateDiag  states/workflow.md              diagram: workflow → ExecuteWorkflow
  FuncSpec   func/billing/check_credits.go   @func billing.CheckCredits
  FuncSpec   func/billing/deduct_credit.go   @func billing.DeductCredit
  FuncSpec   func/worker/process_actions.go  @func worker.ProcessActions
  FuncSpec   func/webhook/deliver.go         @func webhook.Deliver
  Hurl       tests/scenario-happy-path.hurl  scenario: scenario-happy-path.hurl

ממפרט API לסכמת מסד נתונים, ממדיניות הרשאות למעברי מצב, ממימוש פונקציות לתרחישי בדיקה — הטופולוגיה המלאה של פיצ’ר אחד על מסך אחד. עשרות grep מוחלפים בפקודה אחת.

operationId הוא אבן הקשת כי באפליקציית full-stack, היחידה של פיצ’ר היא ה-API endpoint. משתמש לוחץ על כפתור, API נקרא, ואותו API חותך כל שכבה אחרת. שם אחד משרשר פיזית עשר שכבות.


SSaC — למה DSL מותאם

שמונה מ-10 ה-SSOT של yongol הם תקני תעשייה. רק SSaC (Service Sequences as Code) ו-STML נוצרו על ידי yongol. SSaC לוכד החלטות זרימת שירות.

הפער ש-SSaC ממלא. הסתכל על הספקטרום של כלים הצהרתיים: בקצה אחד תקני חוזה (OpenAPI, SQL, Rego) — הם מצהירים מה אבל לא באיזה סדר. בקצה השני זמני ריצה של workflow (Temporal, Inngest, Restate) — אלה קוד. החלטות ופרטי מימוש מתמזגים מחדש באותו קובץ. SSaC יושב בפער ביניהם: “בתוך endpoint בודד, מה קורה, באיזה סדר, עם אילו שומרים.”

ל-SSaC יש סה"כ 16 הערות. ניתן ללמוד ממדריך של עמוד אחד.

רשימת הערות SSaC מלאה

הערהתפקידפורמט
@getקריאת DBType var = Model.Method({args})
@postיצירת שורהType var = Model.Method({args})
@putעדכון שורה (ללא החזרה)Model.Method({args})
@deleteמחיקת שורהModel.Method({args})
@emptyשומר nil → 404var "message" [STATUS]
@existsשומר not-nil → 409var "message" [STATUS]
@authבדיקת הרשאה"action" "resource" {inputs} "message" [STATUS]
@stateמעבר מכונת מצביםdiagram {inputs} "transition" "message" [STATUS]
@callקריאת פונקציה[Type var =] pkg.Func({args})
@evalשומר פרדיקט (true → שגיאה)pkg.Func({args}) "message" STATUS
@publishפרסום לתור"topic" {payload}
@subscribeפונקציית טריגר תור"topic"
@verify-passwordהתחברות (מוגן תזמון)Model.col=source Model.hash vs source -> var STATUS "msg"
@responseהחזרת JSON{ field: var, ... } או var
@no-paginationפטור מכלל דפדוף(רמת פונקציה)
@state-neutralפטור מכלל מכונת מצבים(רמת פונקציה)

דוגמת SSaC — AcceptProposal

הרשאה + מכונות מצבים כפולות + נאמנות + תור:

package service

import "github.com/org/project/internal/billing"

// @get Proposal p = Proposal.FindByID({ID: request.id})
// @empty p "Proposal not found" 404
// @get Gig gig = Gig.FindByID({ID: p.GigID})
// @empty gig "Gig not found" 404
// @auth "AcceptProposal" "gig" {ResourceID: request.id} "Forbidden" 403
// @state proposal {status: p.Status} "AcceptProposal" "Cannot accept" 409
// @state gig {status: gig.Status} "AcceptProposal" "Cannot accept on gig" 409
// @put Proposal.UpdateStatus({ID: p.ID, Status: "accepted"})
// @put Gig.AssignFreelancer({ID: gig.ID, FreelancerID: p.FreelancerID, Status: "in_progress"})
// @call billing.HoldEscrowResponse escrow = billing.HoldEscrow({GigID: gig.ID, Amount: gig.Budget})
// @publish "proposal.accepted" {GigID: gig.ID, FreelancerID: p.FreelancerID}
// @get Proposal updated = Proposal.FindByID({ID: p.ID})
// @response { proposal: updated }
func AcceptProposal() {}

16 שורות. 10 הערות. שתי מכונות מצבים, הרשאה, נאמנות, אירוע תור, תגובה — כל החלטה גלויה, כל פרט נעדר.


מדד ביצועים: ZenFlow

ZenFlow — SaaS אוטומציית workflow רב-דיירים.

שלבתיאורזמןמצטבר
בנייה ראשונית10 endpoints, 6 טבלאות, auth, מכונת מצבים13 דק'13 דק'
+ ניהול גרסאותשכפול workflow, רשימת גרסאות6 דק'19 דק'
+ Webhookswebhook CRUD, backend תור6 דק'25 דק'
+ שוק תבניותדפדוף cursor, שכפול חוצה-ארגון3 דק'28 דק'
+ קבצים מצורפיםדוחות ביצוע, backend קבצים4 דק'32 דק'
+ תזמוןתזמון cron, backend session6 דק'38 דק'
+ יומני ביקורתדפדוף offset, backend cache3 דק'41 דק'
+ לוח מחווניםjoins יחסים, סוגי תגובת func7 דק'48 דק'
+ פעולות אצווההכנסה המונית jsonb14 דק'62 דק'
+ API חיצוניfunc geocoding, הוספת עמודה3 דק'65 דק'
+ עדכון מותנהתבנית sentinel, הקצאה אוטומטית4 דק'69 דק'

סופי: 32 endpoints, 14 טבלאות, 47 בקשות Hurl. 11/11 שלבים עברו.

הוספת פיצ’רים מעולם לא האטה. בדיקות קיימות מעולם לא נשברו. הקיר של 200 endpoints לא היה קיים.

מדד ביצועים Opus 4.7 — 32 endpoints, 14 טבלאות, 47 בקשות Hurl, כ-69 דק’. מדד ביצועים Sonnet 4.6 — 32 endpoints, 9 טבלאות, 37 בקשות Hurl, כ-43 דק'.


yongol agent

LLM מתקן אוטומטית קבצי SSOT דרך לולאת validate-fix.

yongol agent specs/ --model ollama:gemma4:e4b --max-rounds 20

שגיאות validate מוחזרות ל-LLM, ה-LLM מתקן אותן, והאימות רץ שוב. הלולאה חוזרת עד 0 שגיאות. עובד אפילו עם מודל מקומי של 4.5B (Gemma4).

backends נתמכים: ollama (מקומי), xai (Grok), gemini.


אפשר לערוך קוד שנוצר

כן. yongol generate משמר עריכות משתמש בהרצה חוזרת:

  • כל קובץ שנוצר מקבל הערת //yg:checked llm=yongol-gen hash=<8hex>.
  • אם ה-hash שונה, הקובץ מסומן כ-preserved ומדולג ב-generate הבא.
  • yongol status מציג קבצים preserved וסחף חוזה (שגיאות PRV-01/PRV-02).
  • לתיעוד כוונה, הוסף //yg:preserve reason="..." (אופציונלי). לביטול preserve, מחק את הקובץ.

פונקציות ומודלים מובנים

פונקציות מובנות (נקראות דרך @call ב-SSaC)

חבילהפונקציהתיאור
authhashPassword, verifyPasswordגיבוב/אימות bcrypt
authissueToken, verifyToken, refreshTokenאסימוני JWT
authgenerateResetTokenאיפוס סיסמה
cryptoencrypt, decryptAES-256-GCM
cryptogenerateOTP, verifyOTPTOTP
storageuploadFile, deleteFile, presignURLS3
mailsendEmail, sendTemplateEmailSMTP
textgenerateSlug, sanitizeHTML, truncateTextעיבוד טקסט
imageogImage, thumbnailיצירת תמונות

מודלים מובנים (מוגדרים דרך manifest.yaml)

חבילהממשקBackendשימוש SSaC
sessionSessionModel (Set/Get/Delete + TTL)PostgreSQL, Memorysession.Session.Get({key: ...})
cacheCacheModel (Set/Get/Delete + TTL)PostgreSQL, Memorycache.Cache.Set({key: ..., value: ..., ttl: ...})
fileFileModel (Upload/Download/Delete)S3, LocalFilefile.File.Upload({key: ..., body: ...})
queuesingleton Pub/Sub (Publish/Subscribe)PostgreSQL, Memory@publish "topic" {payload}

יצירת מיגרציות DDL אוטומטית

yongol generate מזהה שינויי DDL ומייצר אוטומטית קבצי מיגרציה.

specs/db/
└── users.sql                         # SSOT — ערוך כאן

artifacts/db/
├── .latest_schema.sql                # תמונת בסיס
└── migrations/
    ├── 0001_initial.up.sql
    ├── 0001_initial.down.sql
    ├── 0002_add_users_email.up.sql
    └── 0002_add_users_email.down.sql

שינויים עמומים (שינוי שם עמודות, המרת סוגים, backfill NOT NULL) מובהרים עם רמזים בהערות DDL (-- @rename, -- @cast, -- @backfill, -- @data_migration, -- @allow_destructive). שישה כללים (MIG-001 עד MIG-006) שומרים על שינויים מסוכנים. ההפעלה בפועל על מסד הנתונים מואצלת לכלים סטנדרטיים כמו golang-migrate, flyway, וכו'.


למה מודל גדול יותר הוא לא התשובה

“GPT-6 יפתור את זה.”

לא יפתור. הבעיה היא לא אינטליגנציה של מודל — זה המדיום.

קוד כמדיום לא מבדיל בין החלטות למימוש. כל מודל שקורא את הקוד רואה טקסט שבו החלטות ופרטים שזורים. לא משנה כמה המודל חכם, אם המדיום לא מספק את ההבחנה, המודל לא יכול לעשות אותה.

yongol משנה את המדיום. הוא מעביר את מה ש-AI עורך מקוד למפרטים הצהרתיים. מכיוון שמפרטים מכילים רק החלטות ללא פרטי מימוש, AI לעולם לא יכול לטעות בהחלטה כפרט. הישרדות ההחלטות הופכת בלתי תלויה בגודל המודל.

LLM קטן שעורך רק SSOT, עם validate שמספק משוב מדויק בכל שגיאה, יכול לשמור על אותה שלמות החלטות כמו מודל הרבה יותר גדול שעורך קוד גולמי. yongol מגשר על הפער.


בדיקות זמן ריצה

בדיקות Hurl כולן נכתבות על ידי המשתמש. כתוב אותן ב-specs/tests/ ו-yongol generate משקף ל-artifacts/tests/. באימות, כללים XOH-01 עד XOH-09 בודקים צולב Hurl מול OpenAPI, מכונות מצבים, ו-manifest.auth.

hurl --test --variable host=http://localhost:8080 artifacts/my-project/tests/*.hurl

שלוש קטגוריות:

  • smoke.hurl — בדיקות smoke של endpoints
  • scenario-*.hurl — בדיקות תרחישים עסקיים
  • invariant-*.hurl — בדיקות invariants חוצות endpoints

מצב נוכחי

יצירת backend Go+Gin: Beta — עובד מקצה לקצה. יצירת frontend React: Alpha (בפיתוח).


להתחיל

שיטה 1: התקנת Skill (מומלץ)

npx skills add park-jun-woo/yongol

התקן את ה-skill של yongol בסוכן ה-AI שלך (Claude Code, Cursor, Copilot ועוד). הסוכן לומד את תהליך העבודה בהתקנה.

/yongol בנה SaaS משימות רב-דיירים עם auth ו-CRUD.

שיטה 2: התקנה ישירה

דורש Go 1.25+ ו-gcc (תלות cgo: pg_query_go מקשר libpg_query לפירוש DDL).

git clone https://github.com/park-jun-woo/yongol && cd yongol
make install
yongol validate examples/zenflow

0 errors, 0 warnings.

כוון AI למפרטים האלה ותגיד לו להוסיף פיצ’ר. validate מניח את הפסים; ה-AI רץ עליהם. אין קיר.


מקורות

  1. Google DORA Team. DORA State of AI-Assisted Software Development 2025. Google Cloud, 2025. dora.dev/dora-report-2025
  2. David L. Parnas. “On the Criteria to Be Used in Decomposing Systems into Modules.” Communications of the ACM 15(12): 1053-1058, 1972. doi:10.1145/361598.361623
  3. Weslley Torres, Mark G.J. van den Brand, Alexander Serebrenik. “A Systematic Literature Review of Cross-Domain Model Consistency Checking by Model Management Tools.” Software and Systems Modeling 20(3): 897-916, 2021. doi:10.1007/s10270-020-00834-1
  4. Deepak Babu Piskala. “Spec-Driven Development: From Code to Contract in the Age of AI Coding Assistants.” arXiv:2602.00180, January 2026. arxiv.org/abs/2602.00180
  5. Ehsani et al. “When AI Code Doesn’t Stick: An Empirical Study on Reverted Changes Introduced by AI Coding Agents.” MSR 2026 Mining Challenge, April 2026. 2026.msrconf.org
  6. Anton Jansen, Jan Bosch. “Software Architecture as a Set of Architectural Design Decisions.” EWSA 2005, LNCS 3527, Springer, 2005. semanticscholar.org
  7. Marco Brambilla, Jordi Cabot, Manuel Wimmer. Model-Driven Software Engineering in Practice. 2nd ed., Springer, 2017. doi:10.1007/978-3-031-02546-4
  8. GitClear. AI Copilot Code Quality 2025. February 2025. gitclear.com

מאמרים קשורים

קוד: github.com/park-jun-woo/yongol


יומן שינויים

תאריךשינויים
2026-05-18פרסום ראשוני
2026-05-19נוסף מדד ביצועים Opus. עודכנו 10 SSOT
2026-05-21סנכרון README: עדכון מדדי ביצועים (Opus 32ep/14tbl/47hurl/69min, Sonnet 32ep/9tbl/37hurl/43min), נוספה הצהרת “Harness with reins”, נוספה דוגמת SSaC (AcceptProposal), נוספה פקודת yongol agent, נוסף מערכת Preserve, נוספה רשימת פונקציות/מודלים מובנים, נוספה יצירת מיגרציות DDL אוטומטית, נוסף תיאור STML, נוסף קישור למאמר ifeval-ratchet
2026-05-26סנכרון v0.6.10: נוספה פקודת רצ’ט yongol next, נוספו yongol init/features add/features remove יצירה וניהול פרויקט, נוסף yongol import ייבוא OpenAPI חיצוני, נוספה רשימת הערות SSaC מלאה (16) (@eval, @subscribe, @verify-password, @no-pagination, @state-neutral), טריכוטומיה של בדיקות Hurl (smoke/scenario/invariant), סעיף בדיקות זמן ריצה, פירוט Preserve (קודי שגיאה PRV), הרחבת רמזי מיגרציה DDL (@data_migration, @allow_destructive, כללי MIG), מצב נוכחי (Go+Gin Beta, React Alpha), התקנה מחולקת ל-2 שיטות