From 5e00671baae7fe888ad89e1fafa815a1a4b195b8 Mon Sep 17 00:00:00 2001 From: alwkala Date: Wed, 2 Sep 2026 06:01:30 +0300 Subject: [PATCH 1/2] Update tidyfactor-design.skill --- dist/tidyfactor-design.skill | Bin 15605757 -> 15605757 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/dist/tidyfactor-design.skill b/dist/tidyfactor-design.skill index 279de5dfe34cb5d5a71c3900245a4d52eff047a1..6e5725a5c4e34f5d699f4ab2995b842b8dd35c0e 100644 GIT binary patch delta 942 zcmXYwX_U=n7{I&TTgnm|8pYVMRmvzLOU9CHA(EIeRF+qoYOn!c+PpA-?Kko-uL{DEfvlOt<=AFJW=DKa!DmSXQHg4 zy47Q;qTB|t3*o5paB{O?RyGc1chgvEh8V+(F^&nm1TV!3co|-f6|oXl#wvIPR>f*q z9k0YJtbsN0D$K@Ocr{*wwXqK7U|p<-^|1jq#A~q;HpV8{6r167cs<^L&GAOO30q(; zw#1w97HoyB@m6euZSgj2hwZTgcEsDU6Xs!O?1Ejf8{UE4@lNc4J+T+|#y)r#_QihK zAMeHiI1ul_L3l3?#`|yx4#j-DA0NPB_#i%n594qgfg^DgK7ylh435P|@i82SkK+^g zBtC`XaRN@nr|}t_gp+X!K8w%cRGfy-;|n+)3vdR`#24`;1ZUxFoP%?*5a;21d>I$u zE4UDga1p+Wi*X4q#U#Fluj3oI4By1Ja5=8PmH0NkgR5{gzKd({J$xV6;s^L4uEUS; zV_c7);0D}?pW(@Jrl|J8&nK;8*xH?!s?yH}1i`xDQjfAHT)# z@Bn^~Kj1+;gg@d>_%j~HU+`D_4UgbaJchsHANVK!g@5Be_%9yE6L=C&;b|1!!zGlnr;=aOtFfTNQ!-ZLap|MFKaAF+`?#?{H#Kc0%aD{dr0mPs zHH8*SrLt6_BxYW}?|;4i=s3q6y64>cd7gWo=iYzrJ-dBFg|lH+?$I@otQk8$3OlBw zjDot=bWmA3u4z~nHVVtGCh^#0F^(5u0+Uz{%VPzsh?VeStc+Fg60C~V z@KUUfH82BfVlBK3GqE;aj#uE7SO>GPF4n`Vus&Xm4X`0L!p7JHo8mQiEnbJs@Or!f zn`1V%z#H)BP#W^9dZur1z#?eJD?kGEk5%)yR$JKlkv@J_r7@5XzuGj_qQ*bTem zy?7t?!27W$K7hUOL3{{%*ZsI1b0-1biM}z!z~MzJ!x74=3XkoQl&Bd>NFJS^;<2KAL!#oo!5KTE z&ShQUuVfXT`8Uc8akX^x|5n*SW7AQaz>0L#DsUnlwGM4rXQKI4LfWmiS%n7@HVpB9 e2|ERHl6DB>CCv$i;o|&^U?^;y434T}e&QV4X&^}e From 14b6026e9853fde08b32edbe8a876a5e3f198163 Mon Sep 17 00:00:00 2001 From: alwkala Date: Wed, 2 Sep 2026 06:55:59 +0300 Subject: [PATCH 2/2] release(design): v1.8.0 declarative decision gates, staleness tracking & manifest v1.1.0 --- .tidyfactor | 4 +- CHANGELOG.md | 11 +++ brand.json | 4 +- dist/tidyfactor-design.skill | Bin 15605757 -> 15608214 bytes dist/tidyfactor-design/.tidyfactor | 4 +- dist/tidyfactor-design/CHANGELOG.md | 11 +++ dist/tidyfactor-design/brand.json | 4 +- dist/tidyfactor-design/package.json | 2 +- .../references/workflows/brief.md | 62 +++++++++----- dist/tidyfactor-design/tools/build-skill.js | 1 + manifest.json | 77 +++++++++++++++++- package.json | 2 +- references/workflows/brief.md | 62 +++++++++----- tools/build-skill.js | 1 + 14 files changed, 191 insertions(+), 54 deletions(-) diff --git a/.tidyfactor b/.tidyfactor index 82fafa3..085507c 100644 --- a/.tidyfactor +++ b/.tidyfactor @@ -2,10 +2,10 @@ "ecosystem": "tidyfactor", "track": "design", "name": "tidyfactor-design", - "version": "1.7.0", + "version": "1.8.0", "npmPackage": "@alwkala/tidyfactor-design", "github": "https://github.com/TidyFactor/Design", - "skillFile": "../tidyfactor-design-v1.7.0.skill", + "skillFile": "../tidyfactor-design-v1.8.0.skill", "category": "design-system", "type": "interactive-prototyping", "outputs": [ diff --git a/CHANGELOG.md b/CHANGELOG.md index 04ca2b6..cd42149 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ All notable changes to the **[@tidyfactor/design](https://www.npmjs.com/package/@tidyfactor/design)** package will be documented in this file. +## [1.8.0] - 2026-09-02 + +### ⚑ Added β€” Declarative Decision Gates, Staleness Tracking & Manifest v1.1.0 +- **Declarative `decision_gates[]` Contract (`manifest.json`)**: Formally declared Required Decisions (`audience_mode`, `surface_type`, `tone_school`), priority ranks, discovery sources, and conservative fallbacks conforming to `skill-manifest.decision-gates.schema.json`. +- **Mechanical Context Delta Resolution (`workflows/brief.md`)**: Replaced heuristic agent arbitration with a deterministic set-difference algorithm: $\text{Unknowns} = \text{Required Decisions} - (\text{Discovered Facts} \cup \text{Brain KIs})$. +- **Local Staleness Tracking (`track_staleness: true`)**: Implemented local hash checking on `brand.json` within `.tidyfactor/design-brief.snapshot.json`β€”re-opening modified parameters into `Unknowns` without network or MCP round-trips. +- **SSOT Single-Direction Push Architecture**: Enforced local snapshot as the sole immutable source of truth, with Brain MCP persistence acting strictly as an outbound replica via `--sync-brain`. +- **Tooling Consolidation**: Unified media optimization under `scripts/optimize_images.py` across `manifest.json`, `assets.md`, and documentation. + +--- + ## [1.7.0] - 2026-09-02 ### 🧠 Added β€” Sovereign Brain MCP Integration & Deterministic Fail-Open Protocol diff --git a/brand.json b/brand.json index a4ee2de..30ff51b 100644 --- a/brand.json +++ b/brand.json @@ -1,12 +1,12 @@ { "name": "TidyFactor Design", - "version": "1.7.0", + "version": "1.8.0", "schemaVersion": "brand-core-v2", "meta": { "product": "TidyFactor Design System", "tagline": "Code-Native Interactive Prototyping Engine", "description": "A zero-bundler, framework-free design system and UI prototyping engine with pluggable CSS foundations and full Arabic/RTL support.", - "version": "1.7.0", + "version": "1.8.0", "lastUpdated": "2026-09-02" }, "identity": { diff --git a/dist/tidyfactor-design.skill b/dist/tidyfactor-design.skill index 6e5725a5c4e34f5d699f4ab2995b842b8dd35c0e..9c49cd7a4f521d79197ffa657ec6cdb052719508 100644 GIT binary patch delta 20853 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 KvJor6MgI#lbiFkI diff --git a/dist/tidyfactor-design/.tidyfactor b/dist/tidyfactor-design/.tidyfactor index 82fafa3..085507c 100644 --- a/dist/tidyfactor-design/.tidyfactor +++ b/dist/tidyfactor-design/.tidyfactor @@ -2,10 +2,10 @@ "ecosystem": "tidyfactor", "track": "design", "name": "tidyfactor-design", - "version": "1.7.0", + "version": "1.8.0", "npmPackage": "@alwkala/tidyfactor-design", "github": "https://github.com/TidyFactor/Design", - "skillFile": "../tidyfactor-design-v1.7.0.skill", + "skillFile": "../tidyfactor-design-v1.8.0.skill", "category": "design-system", "type": "interactive-prototyping", "outputs": [ diff --git a/dist/tidyfactor-design/CHANGELOG.md b/dist/tidyfactor-design/CHANGELOG.md index 04ca2b6..cd42149 100644 --- a/dist/tidyfactor-design/CHANGELOG.md +++ b/dist/tidyfactor-design/CHANGELOG.md @@ -2,6 +2,17 @@ All notable changes to the **[@tidyfactor/design](https://www.npmjs.com/package/@tidyfactor/design)** package will be documented in this file. +## [1.8.0] - 2026-09-02 + +### ⚑ Added β€” Declarative Decision Gates, Staleness Tracking & Manifest v1.1.0 +- **Declarative `decision_gates[]` Contract (`manifest.json`)**: Formally declared Required Decisions (`audience_mode`, `surface_type`, `tone_school`), priority ranks, discovery sources, and conservative fallbacks conforming to `skill-manifest.decision-gates.schema.json`. +- **Mechanical Context Delta Resolution (`workflows/brief.md`)**: Replaced heuristic agent arbitration with a deterministic set-difference algorithm: $\text{Unknowns} = \text{Required Decisions} - (\text{Discovered Facts} \cup \text{Brain KIs})$. +- **Local Staleness Tracking (`track_staleness: true`)**: Implemented local hash checking on `brand.json` within `.tidyfactor/design-brief.snapshot.json`β€”re-opening modified parameters into `Unknowns` without network or MCP round-trips. +- **SSOT Single-Direction Push Architecture**: Enforced local snapshot as the sole immutable source of truth, with Brain MCP persistence acting strictly as an outbound replica via `--sync-brain`. +- **Tooling Consolidation**: Unified media optimization under `scripts/optimize_images.py` across `manifest.json`, `assets.md`, and documentation. + +--- + ## [1.7.0] - 2026-09-02 ### 🧠 Added β€” Sovereign Brain MCP Integration & Deterministic Fail-Open Protocol diff --git a/dist/tidyfactor-design/brand.json b/dist/tidyfactor-design/brand.json index a4ee2de..30ff51b 100644 --- a/dist/tidyfactor-design/brand.json +++ b/dist/tidyfactor-design/brand.json @@ -1,12 +1,12 @@ { "name": "TidyFactor Design", - "version": "1.7.0", + "version": "1.8.0", "schemaVersion": "brand-core-v2", "meta": { "product": "TidyFactor Design System", "tagline": "Code-Native Interactive Prototyping Engine", "description": "A zero-bundler, framework-free design system and UI prototyping engine with pluggable CSS foundations and full Arabic/RTL support.", - "version": "1.7.0", + "version": "1.8.0", "lastUpdated": "2026-09-02" }, "identity": { diff --git a/dist/tidyfactor-design/package.json b/dist/tidyfactor-design/package.json index 0c2bff2..c6e2ee2 100644 --- a/dist/tidyfactor-design/package.json +++ b/dist/tidyfactor-design/package.json @@ -1,6 +1,6 @@ { "name": "@tidyfactor/design", - "version": "1.7.0", + "version": "1.8.0", "description": "TidyFactor Design track β€” code-native UI design lifecycle engine (Figma alternative) with Contextual Decision Layer (CDL)", "main": "SKILL.md", "bin": { diff --git a/dist/tidyfactor-design/references/workflows/brief.md b/dist/tidyfactor-design/references/workflows/brief.md index 55ad3f2..d47e3ec 100644 --- a/dist/tidyfactor-design/references/workflows/brief.md +++ b/dist/tidyfactor-design/references/workflows/brief.md @@ -1,36 +1,56 @@ # Workflow: brief -Discovers and records core design system baselines (Foundation, School, Typography, Archetype) using the Contextual Decision Layer (CDL). +Discovers and records core design system baselines (Audience Mode, Surface Type, Tone School) using declarative Context Delta Resolution. --- -## Steps +## πŸ“‹ Step 0: Mechanical Context Delta Resolution -1. **Check Existing State (Local Auto-Sensing First)**: - - Scan workspace for `BRAND-GUIDELINES.md`, `brand.json`, and `.tidyfactor/design-brief.md`. - - If present, immediately extract tokens, typography, and palette baselines without prompting. +Evaluate the declared decision contract in `manifest.json["decision_gates"]["brief"]`: -2. **Check Active MCP Acceleration (Fail-Open Fallback)**: - - If local files do not exist AND `search_knowledge_base` is available in active agent tools: - Query `search_knowledge_base(query="design tokens", scope="project")` for existing project baselines. - - If MCP is unavailable, empty, or returns error: Silently proceed to Step 3 with 0ms delay. +$$\text{Unknowns} = \text{Required Decisions} - (\text{Discovered Facts} \cup \text{Brain KIs})$$ -3. **Conduct Structured Discovery (Max 3 Questions)**: - - If parameters remain unresolved, present at most 3 concise multiple-choice options: - 1. **CSS Foundation (D1)**: (A) Native CSS (Default), (B) Tailwind CSS, (C) daisyUI, (D) Pico CSS. - 2. **Design School (D2)**: (A) Swiss Modern, (B) Neo-Brutalism, (C) Editorial Luxury, (D) Egyptian / Regional Heritage. - 3. **Layout Archetype (D4)**: (A) Split Hero Canvas, (B) Narrative Editorial, (C) Command Dashboard. +1. **Local Discovery & Staleness Check**: + - Check `.tidyfactor/design-brief.snapshot.json` and `brand.json`. + - If `brand.json` has changed since the snapshot was saved (`track_staleness: true`), invalidate the cached value and mark `surface_type` / `tone_school` as `Unknown`. +2. **Optional Brain MCP Lookup (Fail-Open)**: + - If decisions remain Unknown and `search_knowledge_base` is active, query `search_knowledge_base(query="design context", scope="project")`. + - If absent or empty, proceed with 0ms silent bypass. +3. **Delta Evaluation**: + - If $\text{Unknowns} = \emptyset$: Skip all questioning immediately and emit confirmed baseline. + - If $\text{Unknowns} \neq \emptyset$: Proceed to Step 1 for **only the missing keys**. -4. **Record Decisions**: - - Persist confirmed parameters into `.tidyfactor/design-brief.md`. +--- + +## πŸ’¬ Step 1: Surgical Micro-Discovery (Only for Unknown Decisions) + +> **Anti-Bot Constraint**: Never greet the user or ask for facts already resolved on disk. Present at most `max_interactive_questions` (3) sorted by priority: + +- **Audience Mode (Priority 1)**: `(A) act` (Default), `(B) inspire`, `(C) evaluate`, `(D) learn`. +- **Surface Type (Priority 2)**: `(A) landing` (Default), `(B) dashboard`, `(C) product`, `(D) editorial`, `(E) interface`, `(F) minimal`. +- **Tone School (Priority 3)**: `(A) minimal` (Default), `(B) neo-brutalism`, `(C) luxury`, `(D) swiss`, `(E) bento`, `(F) heritage-nilotic`, `(G) heritage-kufic`. + +--- + +## πŸ’Ύ Step 2: SSOT Local Persistence & Outbound Push + +1. **Write Local SSOT**: Persist resolved choices + source file hashes to `.tidyfactor/design-brief.snapshot.json` and `.tidyfactor/design-brief.md`. +2. **Outbound Push to Brain (`--sync-brain`)**: + - If and ONLY IF invoked with `--sync-brain`, push the resolved `design_context` KI via `extract_knowledge_item`. + - The local snapshot remains the immutable source of truth. + +--- + +## 🎯 Step 3: Summary & Actionable Handoff -5. **Report Summary**: - - Present a concise baseline summary and suggest next action (`/init`, `/tokens`, `/components`). +Display a concise 4-line baseline summary and suggest next action (`/tokens`, `/layout`, `/components`). --- ## Validation checklist -- [ ] `.tidyfactor/design-brief.md` exists and contains confirmed values for D1–D5. -- [ ] No more than 3 questions were asked in a single round. -- [ ] Design baseline conforms to `references/memory/quality-bar.md`. +- [ ] Evaluated Context Delta Resolution against `manifest.json["decision_gates"]`. +- [ ] Only truly Unknown decisions were surfaced to the user. +- [ ] `.tidyfactor/design-brief.snapshot.json` and `.tidyfactor/design-brief.md` written as local SSOT. +- [ ] If `--sync-brain` was passed, outbound push was executed without blocking local output. +- [ ] Baseline conforms to `references/memory/quality-bar.md`. diff --git a/dist/tidyfactor-design/tools/build-skill.js b/dist/tidyfactor-design/tools/build-skill.js index a2ea5e5..7a9cc00 100644 --- a/dist/tidyfactor-design/tools/build-skill.js +++ b/dist/tidyfactor-design/tools/build-skill.js @@ -68,6 +68,7 @@ function build() { log('staging single-source-of-truth files from repo root...'); const whitelist = [ 'SKILL.md', + 'manifest.json', 'references', 'memory', 'templates', diff --git a/manifest.json b/manifest.json index 66c97bf..73bcf7d 100644 --- a/manifest.json +++ b/manifest.json @@ -1,5 +1,5 @@ { - "manifest_schema_version": "1.0.0", + "manifest_schema_version": "1.1.0", "skill_id": "tidyfactor-design", "skill_root_anchor": "self", "tools": [ @@ -40,7 +40,7 @@ { "name": "optimize_media", "description": "Compresses images, removes backgrounds, and generates WebP variants.", - "entrypoint": { "runtime": "python3", "script": "scripts/optimize_assets.py" }, + "entrypoint": { "runtime": "python3", "script": "scripts/optimize_images.py" }, "invocation": { "cli_pattern": "{runtime} \"{skill_root}/{script}\" --target \"{target_path}\" {flags}", "args": [ @@ -55,5 +55,78 @@ }, "invoked_by_commands": ["assets"] } + ], + "decision_gates": [ + { + "command": "brief", + "description": "Design Context Gate β€” determines audience mode, surface type, and design school before scaffolding.", + "max_interactive_questions": 3, + "decisions": [ + { + "key": "audience_mode", + "description": "What should this surface primarily do for the visitor?", + "type": "enum", + "options": ["inspire", "evaluate", "act", "learn"], + "default": "act", + "priority": 1, + "discovery": [ + { "source": "local_file", "path": ".tidyfactor/design-brief.snapshot.json", "field": "audience_mode" }, + { "source": "brain_ki", "ki_type": "design_context", "field": "audience_mode" } + ], + "persist_to": { + "local": { "path": ".tidyfactor/design-brief.snapshot.json", "field": "audience_mode" }, + "brain_ki": { + "ki_type": "design_context", + "field": "audience_mode", + "sync_direction": "outbound_push_only", + "requires_flag": "--sync-brain" + } + } + }, + { + "key": "surface_type", + "description": "What kind of layout archetype is this surface?", + "type": "enum", + "options": ["landing", "dashboard", "product", "editorial", "interface", "minimal", "spatial", "auto"], + "default": "landing", + "priority": 2, + "discovery": [ + { "source": "local_file", "path": "brand.json", "field": "surfaceType", "track_staleness": true }, + { "source": "workspace_scan", "path": "pages/", "field": "dominant_page_type" }, + { "source": "brain_ki", "ki_type": "design_context", "field": "surface_type" } + ], + "persist_to": { + "local": { "path": ".tidyfactor/design-brief.snapshot.json", "field": "surface_type" }, + "brain_ki": { + "ki_type": "design_context", + "field": "surface_type", + "sync_direction": "outbound_push_only", + "requires_flag": "--sync-brain" + } + } + }, + { + "key": "tone_school", + "description": "What aesthetic design school should visual styling follow?", + "type": "enum", + "options": ["minimal", "neo-brutalism", "luxury", "swiss", "bento", "heritage-nilotic", "heritage-kufic", "corporate"], + "default": "minimal", + "priority": 3, + "discovery": [ + { "source": "local_file", "path": "brand.json", "field": "voice", "track_staleness": true }, + { "source": "brain_ki", "ki_type": "design_context", "field": "tone_school" } + ], + "persist_to": { + "local": { "path": ".tidyfactor/design-brief.snapshot.json", "field": "tone_school" }, + "brain_ki": { + "ki_type": "design_context", + "field": "tone_school", + "sync_direction": "outbound_push_only", + "requires_flag": "--sync-brain" + } + } + } + ] + } ] } diff --git a/package.json b/package.json index 0c2bff2..c6e2ee2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tidyfactor/design", - "version": "1.7.0", + "version": "1.8.0", "description": "TidyFactor Design track β€” code-native UI design lifecycle engine (Figma alternative) with Contextual Decision Layer (CDL)", "main": "SKILL.md", "bin": { diff --git a/references/workflows/brief.md b/references/workflows/brief.md index 55ad3f2..d47e3ec 100644 --- a/references/workflows/brief.md +++ b/references/workflows/brief.md @@ -1,36 +1,56 @@ # Workflow: brief -Discovers and records core design system baselines (Foundation, School, Typography, Archetype) using the Contextual Decision Layer (CDL). +Discovers and records core design system baselines (Audience Mode, Surface Type, Tone School) using declarative Context Delta Resolution. --- -## Steps +## πŸ“‹ Step 0: Mechanical Context Delta Resolution -1. **Check Existing State (Local Auto-Sensing First)**: - - Scan workspace for `BRAND-GUIDELINES.md`, `brand.json`, and `.tidyfactor/design-brief.md`. - - If present, immediately extract tokens, typography, and palette baselines without prompting. +Evaluate the declared decision contract in `manifest.json["decision_gates"]["brief"]`: -2. **Check Active MCP Acceleration (Fail-Open Fallback)**: - - If local files do not exist AND `search_knowledge_base` is available in active agent tools: - Query `search_knowledge_base(query="design tokens", scope="project")` for existing project baselines. - - If MCP is unavailable, empty, or returns error: Silently proceed to Step 3 with 0ms delay. +$$\text{Unknowns} = \text{Required Decisions} - (\text{Discovered Facts} \cup \text{Brain KIs})$$ -3. **Conduct Structured Discovery (Max 3 Questions)**: - - If parameters remain unresolved, present at most 3 concise multiple-choice options: - 1. **CSS Foundation (D1)**: (A) Native CSS (Default), (B) Tailwind CSS, (C) daisyUI, (D) Pico CSS. - 2. **Design School (D2)**: (A) Swiss Modern, (B) Neo-Brutalism, (C) Editorial Luxury, (D) Egyptian / Regional Heritage. - 3. **Layout Archetype (D4)**: (A) Split Hero Canvas, (B) Narrative Editorial, (C) Command Dashboard. +1. **Local Discovery & Staleness Check**: + - Check `.tidyfactor/design-brief.snapshot.json` and `brand.json`. + - If `brand.json` has changed since the snapshot was saved (`track_staleness: true`), invalidate the cached value and mark `surface_type` / `tone_school` as `Unknown`. +2. **Optional Brain MCP Lookup (Fail-Open)**: + - If decisions remain Unknown and `search_knowledge_base` is active, query `search_knowledge_base(query="design context", scope="project")`. + - If absent or empty, proceed with 0ms silent bypass. +3. **Delta Evaluation**: + - If $\text{Unknowns} = \emptyset$: Skip all questioning immediately and emit confirmed baseline. + - If $\text{Unknowns} \neq \emptyset$: Proceed to Step 1 for **only the missing keys**. -4. **Record Decisions**: - - Persist confirmed parameters into `.tidyfactor/design-brief.md`. +--- + +## πŸ’¬ Step 1: Surgical Micro-Discovery (Only for Unknown Decisions) + +> **Anti-Bot Constraint**: Never greet the user or ask for facts already resolved on disk. Present at most `max_interactive_questions` (3) sorted by priority: + +- **Audience Mode (Priority 1)**: `(A) act` (Default), `(B) inspire`, `(C) evaluate`, `(D) learn`. +- **Surface Type (Priority 2)**: `(A) landing` (Default), `(B) dashboard`, `(C) product`, `(D) editorial`, `(E) interface`, `(F) minimal`. +- **Tone School (Priority 3)**: `(A) minimal` (Default), `(B) neo-brutalism`, `(C) luxury`, `(D) swiss`, `(E) bento`, `(F) heritage-nilotic`, `(G) heritage-kufic`. + +--- + +## πŸ’Ύ Step 2: SSOT Local Persistence & Outbound Push + +1. **Write Local SSOT**: Persist resolved choices + source file hashes to `.tidyfactor/design-brief.snapshot.json` and `.tidyfactor/design-brief.md`. +2. **Outbound Push to Brain (`--sync-brain`)**: + - If and ONLY IF invoked with `--sync-brain`, push the resolved `design_context` KI via `extract_knowledge_item`. + - The local snapshot remains the immutable source of truth. + +--- + +## 🎯 Step 3: Summary & Actionable Handoff -5. **Report Summary**: - - Present a concise baseline summary and suggest next action (`/init`, `/tokens`, `/components`). +Display a concise 4-line baseline summary and suggest next action (`/tokens`, `/layout`, `/components`). --- ## Validation checklist -- [ ] `.tidyfactor/design-brief.md` exists and contains confirmed values for D1–D5. -- [ ] No more than 3 questions were asked in a single round. -- [ ] Design baseline conforms to `references/memory/quality-bar.md`. +- [ ] Evaluated Context Delta Resolution against `manifest.json["decision_gates"]`. +- [ ] Only truly Unknown decisions were surfaced to the user. +- [ ] `.tidyfactor/design-brief.snapshot.json` and `.tidyfactor/design-brief.md` written as local SSOT. +- [ ] If `--sync-brain` was passed, outbound push was executed without blocking local output. +- [ ] Baseline conforms to `references/memory/quality-bar.md`. diff --git a/tools/build-skill.js b/tools/build-skill.js index a2ea5e5..7a9cc00 100644 --- a/tools/build-skill.js +++ b/tools/build-skill.js @@ -68,6 +68,7 @@ function build() { log('staging single-source-of-truth files from repo root...'); const whitelist = [ 'SKILL.md', + 'manifest.json', 'references', 'memory', 'templates',