archik 0.20.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-rose-700:oklch(51.4% .222 16.935);--spacing:.25rem;--container-3xl:48rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-semibold:600;--tracking-tight:-.025em;--radius-md:.375rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.z-50{z-index:50}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-auto{margin-top:auto}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.h-full{height:100%}.min-h-0{min-height:calc(var(--spacing) * 0)}.w-72{width:calc(var(--spacing) * 72)}.w-full{width:100%}.max-w-3xl{max-width:var(--container-3xl)}.flex-1{flex:1}.grow{flex-grow:1}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.resize{resize:both}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.items-baseline{align-items:baseline}.items-center{align-items:center}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.p-1{padding:calc(var(--spacing) * 1)}.p-2{padding:calc(var(--spacing) * 2)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-4{padding-top:calc(var(--spacing) * 4)}.text-center{text-align:center}.text-left{text-align:left}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.whitespace-pre-wrap{white-space:pre-wrap}.text-rose-700{color:var(--color-rose-700)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.underline{text-decoration-line:underline}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media(hover:hover){.hover\:no-underline:hover{text-decoration-line:none}}}:root,[data-theme=light]{--archik-canvas:#f8fafc;--archik-panel:#fff;--archik-surface:#f1f5f9;--archik-surface-hover:#e2e8f0;--archik-fg:#0f172a;--archik-fg-dim:#475569;--archik-fg-muted:#94a3b8;--archik-border:#e2e8f0;--archik-border-strong:#cbd5e1;--archik-accent:#2563eb;--archik-accent-bright:#3b82f6;--archik-magenta:#db2777;--archik-success:#10b981;--archik-warning:#d97706;--archik-danger:#e11d48;--archik-node-fill:#fff;--archik-node-fill-tinted:#f1f5f9;--archik-node-fill-frame:#fff;--archik-node-stroke:#0f172a;--archik-node-stroke-soft:#475569;--archik-container-border:#94a3b8;--archik-node-text:#0f172a;--archik-node-text-dim:#475569;--archik-node-caption:#64748b;--archik-node-chrome-dot:#cbd5f5;--archik-edge-filled:#0f172a;--archik-edge-open:#334155;--archik-edge-dim:#64748b;--archik-edge-async:#2563eb;--archik-grid-minor:#e2e8f0;--archik-grid-major:#cbd5e1;--archik-selected:#2563eb;--archik-selected-glow:#2563eb2e;--archik-status-proposed:#6366f1;--archik-status-deprecated:#d97706;color-scheme:light}[data-theme=dark]{--archik-canvas:#000;--archik-panel:#0a0a0a;--archik-surface:#161616;--archik-surface-hover:#222;--archik-fg:#fff;--archik-fg-dim:#c8c8c8;--archik-fg-muted:#9a9a9a;--archik-border:#262626;--archik-border-strong:#3d3d3d;--archik-accent:#22d3ee;--archik-accent-bright:#67e8f9;--archik-magenta:#f472b6;--archik-success:#34d399;--archik-warning:#fbbf24;--archik-danger:#fb7185;--archik-node-fill:#0c0c0c;--archik-node-fill-tinted:#181818;--archik-node-fill-frame:#101010;--archik-node-stroke:#3d3d3d;--archik-node-stroke-soft:#2a2a2a;--archik-container-border:#4a4a4a;--archik-node-text:#fff;--archik-node-text-dim:#d6d6d6;--archik-node-caption:#67e8f9;--archik-node-chrome-dot:#3a3a3a;--archik-edge-filled:#ededed;--archik-edge-open:#b0b0b0;--archik-edge-dim:#7a7a7a;--archik-edge-async:#67e8f9;--archik-grid-minor:#0f0f0f;--archik-grid-major:#1c1c1c;--archik-selected:#22d3ee;--archik-selected-glow:#22d3ee47;--archik-status-proposed:#818cf8;--archik-status-deprecated:#fbbf24;color-scheme:dark}html,body,#root{background:var(--archik-canvas);height:100%;color:var(--archik-fg);-webkit-font-smoothing:antialiased;margin:0;font-family:Inter,system-ui,sans-serif}.archik-panel{background:var(--archik-panel);border:1px solid var(--archik-border);border-radius:8px}.archik-input{background:var(--archik-surface);color:var(--archik-fg);border:1px solid var(--archik-border);font:inherit;border-radius:4px;outline:none;padding:4px 8px;font-size:12px;transition:border-color .12s,box-shadow .12s}.archik-input:focus{border-color:var(--archik-accent);box-shadow:0 0 0 3px var(--archik-selected-glow)}.archik-btn{background:var(--archik-surface);color:var(--archik-fg);border:1px solid var(--archik-border);cursor:pointer;border-radius:4px;align-items:center;gap:4px;padding:5px 10px;font-size:12px;font-weight:500;transition:background .12s,border-color .12s,color .12s;display:inline-flex}.archik-btn:hover{background:var(--archik-surface-hover);border-color:var(--archik-border-strong)}.archik-btn:disabled{opacity:.5;cursor:not-allowed}.archik-focus-step{width:22px;height:22px;color:var(--archik-fg-dim);cursor:pointer;background:0 0;border:none;border-radius:5px;justify-content:center;align-items:center;padding:0;transition:background .12s,color .12s;display:inline-flex}.archik-focus-step:hover:not(:disabled){background:var(--archik-accent)}@supports (color:color-mix(in lab,red,red)){.archik-focus-step:hover:not(:disabled){background:color-mix(in srgb,var(--archik-accent) 22%,transparent)}}.archik-focus-step:hover:not(:disabled){color:var(--archik-accent)}.archik-focus-step:focus-visible{outline:2px solid var(--archik-accent);outline-offset:1px}.archik-focus-step:disabled{opacity:.4;cursor:not-allowed}.archik-btn-primary{background:var(--archik-accent);border-color:var(--archik-accent);color:#000}.archik-btn-primary:hover{background:var(--archik-accent-bright);border-color:var(--archik-accent-bright)}[data-theme=light] .archik-btn-primary{color:#fff}.archik-btn-danger{color:var(--archik-danger);border-color:var(--archik-danger);background:0 0;border-style:dashed}.archik-btn-danger:hover{background:var(--archik-danger);color:#000;border-style:solid}.archik-pill{letter-spacing:.02em;border:1px solid #0000;border-radius:999px;align-items:center;gap:4px;padding:2px 8px;font-size:11px;display:inline-flex}.archik-pill--info{color:var(--archik-accent);border-color:var(--archik-border-strong);background:var(--archik-accent)}@supports (color:color-mix(in lab,red,red)){.archik-pill--info{background:color-mix(in oklab,var(--archik-accent) 8%,transparent)}}.archik-pill--success{color:var(--archik-success);background:var(--archik-success)}@supports (color:color-mix(in lab,red,red)){.archik-pill--success{background:color-mix(in oklab,var(--archik-success) 12%,transparent)}}.archik-pill--warning{color:var(--archik-warning);background:var(--archik-warning)}@supports (color:color-mix(in lab,red,red)){.archik-pill--warning{background:color-mix(in oklab,var(--archik-warning) 14%,transparent)}}.archik-pill--danger{color:var(--archik-danger);background:var(--archik-danger)}@supports (color:color-mix(in lab,red,red)){.archik-pill--danger{background:color-mix(in oklab,var(--archik-danger) 14%,transparent)}}.archik-label{letter-spacing:.12em;text-transform:uppercase;color:var(--archik-fg-muted);margin-bottom:4px;font-size:10px;display:block}.archik-mono{color:var(--archik-fg);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.archik-divider{border-top:1px solid var(--archik-border)}.archik-grid{background-color:var(--archik-canvas);background-image:radial-gradient(var(--archik-grid-minor) 1px,transparent 1px),radial-gradient(var(--archik-grid-major) 1px,transparent 1px);background-position:0 0,0 0;background-size:20px 20px,100px 100px}.archik-selected-glow{filter:drop-shadow(0 0 6px var(--archik-selected-glow)) drop-shadow(0 0 2px var(--archik-selected-glow));animation:1.8s ease-in-out infinite archikPulse}[data-archik-node-id][data-archik-status=proposed]{opacity:.82}[data-archik-node-id][data-archik-status=proposed] rect,[data-archik-node-id][data-archik-status=proposed] path,[data-archik-node-id][data-archik-status=proposed] ellipse,[data-archik-node-id][data-archik-status=proposed] line{stroke:var(--archik-status-proposed);stroke-dasharray:5 3}[data-archik-node-id][data-archik-status=deprecated]{opacity:.7}[data-archik-node-id][data-archik-status=deprecated] rect,[data-archik-node-id][data-archik-status=deprecated] path,[data-archik-node-id][data-archik-status=deprecated] ellipse,[data-archik-node-id][data-archik-status=deprecated] line{stroke:var(--archik-status-deprecated);stroke-dasharray:2 4}[data-archik-node-id][data-archik-status=deprecated] text{text-decoration:line-through;text-decoration-thickness:1px;-webkit-text-decoration-color:var(--archik-status-deprecated);text-decoration-color:var(--archik-status-deprecated)}.archik-layer-label{letter-spacing:.08em;fill:var(--archik-fg-muted);font-size:9px;font-weight:700}@keyframes archikPulse{0%,to{filter:drop-shadow(0 0 4px var(--archik-selected-glow)) drop-shadow(0 0 1px var(--archik-selected-glow))}50%{filter:drop-shadow(0 0 12px var(--archik-selected-glow)) drop-shadow(0 0 3px var(--archik-selected-glow))}}.archik-modal-overlay{z-index:50;background:var(--archik-canvas);justify-content:center;align-items:center;display:flex;position:fixed;inset:0}@supports (color:color-mix(in lab,red,red)){.archik-modal-overlay{background:color-mix(in oklab,var(--archik-canvas) 70%,transparent)}}.archik-modal-overlay{-webkit-backdrop-filter:blur(4px);animation:.14s ease-out archikFadeIn}.archik-modal{background:var(--archik-panel);border:1px solid var(--archik-border);width:360px;max-width:calc(100vw - 32px);box-shadow:0 12px 40px #00000059,0 0 0 1px var(--archik-border-strong);border-radius:8px;padding:16px;animation:.2s cubic-bezier(.2,.8,.2,1) archikModalIn}.archik-selected-outline{fill:none;stroke:var(--archik-selected);stroke-width:2px;pointer-events:none}@keyframes archikEdgeFlow{0%{stroke-dashoffset:0}to{stroke-dashoffset:calc(-1 * var(--archik-dash-period,8) * 1px)}}.archik-edge-flowing{animation:1.4s linear infinite archikEdgeFlow}@media(prefers-reduced-motion:reduce){.archik-edge-flowing{animation:none}}.archik-popover{background:var(--archik-panel);border:1px solid var(--archik-border-strong);border-radius:6px;flex-direction:column;max-height:min(80vh,600px);padding:4px;animation:.16s cubic-bezier(.2,.8,.2,1) archikModalIn;display:flex;overflow:hidden;box-shadow:0 12px 32px #00000059}.archik-menu-item{width:100%;color:var(--archik-fg);cursor:pointer;text-align:left;background:0 0;border:0;border-radius:4px;align-items:center;gap:8px;padding:6px 10px;font-size:12px;display:flex}.archik-menu-item:hover{background:var(--archik-surface-hover)}.archik-menu-item--danger{color:var(--archik-danger)}@keyframes archikFadeIn{0%{opacity:0}to{opacity:1}}@keyframes archikModalIn{0%{opacity:0;transform:translateY(8px)scale(.98)}to{opacity:1;transform:none}}.archik-drawer-shell{flex-direction:column;min-width:0;transition:width .22s cubic-bezier(.2,.8,.2,1),opacity .2s,margin-left .22s cubic-bezier(.2,.8,.2,1);display:flex;overflow:hidden}.archik-drawer-shell--open{opacity:1;width:320px;margin-left:16px}.archik-drawer-shell--closed{opacity:0;pointer-events:none;width:0;margin-left:0}.archik-drawer-content{flex-shrink:0;width:320px;height:100%}.archik-drawer-fade{animation:.22s ease-out archikFadeIn}.archik-zoom-btn{min-width:28px;height:24px;padding:0 8px}.archik-sheet-handle{flex-shrink:0;justify-content:center;align-items:center;padding:10px 12px 2px;display:none;position:relative}.archik-sheet-grip{background:var(--archik-border-strong);border-radius:2px;width:36px;height:4px}.archik-sheet-close{width:32px;height:32px;color:var(--archik-fg-dim);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;font-size:13px;display:flex;position:absolute;top:2px;right:8px}.archik-sheet-close:hover{background:var(--archik-surface-hover);color:var(--archik-fg)}@media(max-width:768px){.archik-main{padding:0!important}.archik-main>.archik-panel{border:0;border-radius:0}.archik-drawer-shell{z-index:40;margin-left:0;transition:transform .22s cubic-bezier(.2,.8,.2,1),opacity .2s;position:fixed;bottom:0;left:0;right:0}.archik-drawer-shell--open{width:auto;margin-left:0;transform:translateY(0)}.archik-drawer-shell--closed{width:auto;margin-left:0;transform:translateY(100%)}.archik-drawer-content{border-bottom:0;border-radius:14px 14px 0 0;flex-direction:column;width:100%;height:60dvh;display:flex}.archik-drawer-content>:not(.archik-sheet-handle){flex:1;min-height:0;height:auto!important}.archik-sheet-handle{display:flex}}@media(pointer:coarse){.archik-btn{min-height:36px;padding:8px 12px}.archik-zoom-btn{min-width:40px;height:40px;padding:0 10px}.archik-focus-step{width:32px;height:32px}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}
@@ -14,8 +14,8 @@
14
14
  }
15
15
  } catch {}
16
16
  </script>
17
- <script type="module" crossorigin src="/assets/index-Bn3qR7Cx.js"></script>
18
- <link rel="stylesheet" crossorigin href="/assets/index-DUgLHSFs.css">
17
+ <script type="module" crossorigin src="/assets/index-C3mFLYOG.js"></script>
18
+ <link rel="stylesheet" crossorigin href="/assets/index-D6TFArum.css">
19
19
  </head>
20
20
  <body>
21
21
  <div id="root"></div>
@@ -8,13 +8,22 @@
8
8
 
9
9
  I move from **brief → structural model → build plan → code**. Each step is a reviewable artifact, gated by a HITL accept before the next one is produced. If implementation invalidates the model, I stop coding and fix the model first.
10
10
 
11
- The **structural model** (archik diagram — nodes, nesting via `parentId` and sub-files, edges) says *what exists* and *which way dependencies flow*. `archik drift` and `archik smells` check it against the real code. Code is the last artifact, not the first.
11
+ The **architecture style** (`style:` in the model — layered, hexagonal, clean, modular monolith or feature slices) is the architect's choice of structure; archik enforces it on every change and draws the board in its lanes. The **structural model** (archik diagram — nodes, nesting via `parentId` and sub-files, edges) says *what exists* and *which way dependencies flow*. **Decision records** in `.archik/decisions/` say *why* it is shaped that way — one per accepted change. `archik drift` and `archik smells` check it against the real code. Code is the last artifact, not the first.
12
+
13
+ **The architect can steer directly.** Moving a box, drawing or deleting an edge, or setting a layer on the canvas saves the change with its decision record — the model is then ahead of the code. `npx archik gap` lists what the code must change; `/archik:realize` closes that list.
12
14
 
13
15
  Two gate types:
14
16
 
15
17
  - **Canvas gate** — `/archik:accept` on the rendered diff. Used for the structural sidecar.
16
18
  - **Plan gate** — user replies "approve". Used for the build plan before any code edits.
17
19
 
20
+ ### Match gates to reversibility
21
+
22
+ `archik suggest set` labels every change a **one-way door** (hard to undo) or a **two-way door** (easy to undo):
23
+
24
+ - **One-way door** — adds a data store, queue/stream, external system, gateway/auth/cdn, cloud or LLM node, a new edge to an external system, a top-level module; or removes a built node or moves one to another parent. Two separate stops: canvas gate first, then the plan gate. If it adds data, an outside system or public traffic, the decision record must also say how it is **secured, observed and rolled back** (`crossCutting`) — `suggest set` refuses it otherwise.
25
+ - **Two-way door** — everything else (an internal function, a new edge inside a module, a description, a lifecycle flip). One stop: stage the sidecar and show the build plan in the same message; `/archik:accept` approves both.
26
+
18
27
  ### Match ritual to scope
19
28
 
20
29
  Not every task needs the full loop. Skip the modeling phases and just edit when the change is:
@@ -30,8 +39,8 @@ Run the loop when the change introduces new behavior, a new structural shape, or
30
39
  **DISCOVER → DESIGN → DECIDE → BUILD → VERIFY**, with one critical back-edge: if BUILD reveals the model is wrong, stop coding and loop back to DESIGN.
31
40
 
32
41
  - **DISCOVER** — `npx archik q stats / list`, `npx archik smells`, `ls` source dirs. Read before write.
33
- - **DESIGN** — structural sidecar with rationale (boundaries, nesting, dependency direction).
34
- - **DECIDE** — `/archik:accept` on the structural sidecar.
42
+ - **DESIGN** — structural sidecar plus its decision record (context, decision, alternatives, consequences).
43
+ - **DECIDE** — `/archik:accept` on the structural sidecar. Accept writes the decision record.
35
44
  - **BUILD** — numbered plan → "approve" → execute in small commits. Tests-first when the behavior is clearly bounded.
36
45
  - **VERIFY** — validate, tests, lint, build, `archik drift`, `archik smells`, eyeball UI. Stage the `proposed → active` flip.
37
46
 
@@ -45,7 +54,7 @@ I'd run the loop like this:
45
54
 
46
55
  1. **DISCOVER** — `npx archik q list`, `npx archik q describe auth-service`, peek at `src/auth/`. Find that an `auth-service` node already handles login.
47
56
 
48
- 2. **DESIGN** — `npx archik suggest set` adding two `proposed` nodes under the `auth` module: a `reset-handler` and an `email-sender` that talks to the email provider (modelled as `external`). Two new edges: `reset-handler → email-sender (calls)`, `reset-handler → auth-service (writes)`. Dependencies flow one way — nothing in `auth-service` imports the handler. Wait for **`/archik:accept`** on the canvas.
57
+ 2. **DESIGN** — `npx archik suggest set` adding two `proposed` nodes under the `auth` module: a `reset-handler` and an `email-sender` that talks to the email provider (modelled as `external`). Two new edges: `reset-handler → email-sender (calls)`, `reset-handler → auth-service (writes)`. Dependencies flow one way — nothing in `auth-service` imports the handler. The draft's decision record: *context* — users who lose their password open support tickets; *decision* — self-service reset by emailed one-time link; *alternatives* — admin-only reset, SMS codes; *consequences* — we now depend on an email provider and must expire tokens. It adds an external system, so `suggest set` calls it a **one-way door** and the record also needs *crossCutting*: tokens are single-use and expire in 15 minutes, the provider key lives in the secret store (security); reset requests and send failures are counted and alerted (observability); a feature flag turns the reset link off (rollback). Wait for **`/archik:accept`** on the canvas; accept writes `.archik/decisions/0004-password-reset-by-email.md`.
49
58
 
50
59
  3. **BUILD plan** — `src/auth/resetHandler.ts` (request + verify), `src/auth/emailSender.ts` (provider client), `tests/auth/reset.happy.spec.ts`, `tests/auth/reset.expired.spec.ts`. Each new edge maps to a real call. Out of scope: rate limiting (next milestone). Wait for "approve".
51
60
 
@@ -68,50 +77,59 @@ The recommended opener is **`/archik:bootstrap`** (with or without an inline bri
68
77
 
69
78
  2. **Read the current state** with `ls -F`, `npx archik q list` (only relevant if archik is already populated), and `npx archik smells` (when code exists).
70
79
 
71
- 3. **Surface genuine ambiguities** — usually 2–4 questions about scope, target users, hard constraints, or non-obvious tradeoffs. Skip questions whose answers are in the brief.
80
+ 3. **Agree the architecture style.** Ask which structure the system should follow (`npx archik style list`), recommend one that fits the brief (a small service: layered; rich domain with many integrations: hexagonal or clean; several teams in one deployable: modular monolith; many independent features: feature slices), and put the user's choice in the first sidecar as `style:`.
81
+
82
+ 4. **Surface genuine ambiguities** — usually 2–4 questions about scope, target users, hard constraints, or non-obvious tradeoffs. Skip questions whose answers are in the brief.
72
83
 
73
- 4. **Stage the structural model** via `npx archik suggest set` — every node the finished system needs, marked `status: proposed`, parented to a top-level `module`. Wait for **`/archik:accept`** on the canvas (formal gate).
84
+ 5. **Stage the structural model** via `npx archik suggest set` — the **first milestone in detail** (every node and edge it needs, `status: proposed`, each top-level node in its style `layer`), and the rest of the system as a few coarse `module` placeholders (one per later area, `status: proposed`, one-line description). Wait for **`/archik:accept`** on the canvas (formal gate).
74
85
 
75
- 5. **The whole architecture lives on day one as `proposed`.** Milestones flip subsets from `proposed` to `active` (with `sourcePath`) as code lands. The set of nodes a milestone flips IS the milestone.
86
+ 6. **Detail grows with the work.** Don't model what you can't yet know. Each milestone first details its own area (a sidecar that replaces the placeholder's insides), then flips those nodes from `proposed` to `active` (with `sourcePath`) as code lands. The set of nodes a milestone flips IS the milestone.
76
87
 
77
88
  ## Per-milestone rhythm
78
89
 
79
- Every milestone follows the same shape. Two gate types apply — **canvas gate** (`/archik:accept`) and **plan gate** ("approve"):
90
+ Every milestone follows the same shape. Two gate types apply — **canvas gate** (`/archik:accept`) and **plan gate** ("approve") — merged into one stop for two-way doors:
80
91
 
81
- 1. **Structural sidecar** — `/archik:suggest <feature>`. Stages the proposed end-state for this milestone via `npx archik suggest set` under the hood. Rationale in 2–4 bullets.
92
+ 1. **Structural sidecar** — `/archik:suggest <feature>`. Stages the proposed end-state for this milestone via `npx archik suggest set` under the hood, with its decision record. Note whether `suggest set` called it a one-way or two-way door.
82
93
  2. **`/archik:accept` on the structural diagram** — formal canvas gate.
83
- 3. **BUILD plan** — one-line goal, deps, files with paths and signatures, non-obvious bits, acceptance gate, out-of-scope items, the `proposed → active` flip this milestone will produce. Each new edge must map to a real call in the plan.
84
- 4. **"approve" on the plan** — plan gate. Don't start editing files until approved.
94
+ 3. **BUILD plan** — start from `npx archik gap` (the exact code work the model now asks for), then: one-line goal, deps, files with paths and signatures, non-obvious bits, acceptance gate, out-of-scope items, the `proposed → active` flip this milestone will produce. Each new edge must map to a real call in the plan. For a one-way door with `crossCutting`, the plan also lands what it promised: the security control, the signal you will watch, the rollback path.
95
+ 4. **"approve" on the plan** — plan gate. Don't start editing files until approved. *Two-way door:* steps 1–4 collapse — show the plan together with the sidecar, and `/archik:accept` approves both.
85
96
  5. **Execute** — small commits, narrate non-obvious decisions, declare back-edges to DESIGN openly when they happen.
86
- 6. **Verify** — project tests → lint → build → `npx archik drift` → `npx archik smells` → aesthetic eyeball (if UI). No new folder loop should close the milestone.
87
- 7. **Stage the `proposed → active` sidecar** — `/archik:suggest "flip <list> to active"`. Flips nodes/edges with their `sourcePath` now on disk.
97
+ 6. **Verify** — project tests → lint → build → `npx archik drift` → `npx archik smells` → aesthetic eyeball (if UI). No **new** folder loop or oversized file should close the milestone (with a committed baseline, `smells` marks them NEW). For a one-way door, check the `crossCutting` promises exist in the code before the flip to `active`.
98
+ 7. **Stage the `proposed → active` sidecar** — `/archik:suggest "flip <list> to active"`. Flips nodes/edges with their `sourcePath` now on disk. Its decision record is short: what landed, and that drift now checks it.
88
99
  8. **Hand off** — list what to eyeball; wait for `/archik:accept` and (if there's a deploy) confirm deploy is green.
89
100
  9. **Commit + push** — only after the user confirms.
90
101
 
91
102
  ## Hard rules
92
103
 
93
104
  1. **Structure → plan → code. In that order.** The accepted diagram defines what to build. Code lands last.
94
- 2. **Two gate types.** The structural model gets a **canvas gate** (`/archik:accept`). The build plan gets an **approval gate** ("approve"). Don't conflate them — `/archik:accept` only works on structural sidecars.
95
- 3. **Dependencies flow one way.** Sibling folders must not import each other. `npx archik smells` reports folder loops with the real imports as evidence — fix them, don't invent labels for them.
105
+ 2. **Gates match reversibility.** One-way doors get two stops: a **canvas gate** (`/archik:accept`) on the model, then an **approval gate** ("approve") on the plan. Two-way doors get one stop: sidecar and plan shown together, one `/archik:accept`. Never skip review of a one-way door to save time.
106
+ 3. **Dependencies flow one way.** The declared style's rule is law: `suggest set` rejects a dependency that breaks it, and a change that seems to need one is a question for the architect, not a workaround. Sibling folders must not import each other. `npx archik smells` reports folder loops with the real imports as evidence — fix them, don't invent labels for them.
96
107
  4. **Stop at every milestone boundary.** Summarize what shipped, run verifications (`archik drift` and `archik smells`), ask for the visual ack before continuing.
97
108
  5. **Boring underneath.** No experimental framework features unless explicitly requested. Match the stack the brief specifies.
98
109
  6. **No scope creep.** Out-of-scope items go in `FUTURE.md`, not the current milestone.
99
110
  7. **Back-edge from BUILD lands on the model.** If implementation reveals the structural model is wrong, fix it with a fresh sidecar. Never paper over.
100
- 8. **Don't add comments that restate code.** Add a comment only when the WHY is non-obvious.
111
+ 8. **Every structural change says why.** Each sidecar carries a decision record; accept writes it to `.archik/decisions/`. Records are never edited — to change course, a new record lists the old numbers in `supersedes`.
112
+ 9. **Don't add comments that restate code.** Add a comment only when the WHY is non-obvious.
101
113
 
102
114
  ## What each phase produces
103
115
 
104
116
  ### DISCOVER
117
+ - `npx archik style` — the structure the code must follow, and where each node sits.
105
118
  - `npx archik q stats` and `npx archik q list` to ground in the current diagram.
106
119
  - `npx archik smells` to see folder loops and oversized files in the code.
120
+ - Past decision records in `.archik/decisions/` for the area you will touch — don't undo a choice without knowing why it was made.
107
121
  - `ls -F` of relevant source dirs.
108
122
  - A mental map of what exists vs what the request needs.
109
123
  - No code, no diagram changes yet.
110
124
 
111
125
  ### DESIGN
126
+ - Fit the change to the style: each new top-level node gets the `layer` (or module) its job belongs to; dependencies follow the rule (`npx archik q describe <id>` shows what a node may use).
112
127
  - One-line intent.
113
128
  - 1–3 clarifying questions only when there's genuine ambiguity.
114
129
  - A sidecar staged via `npx archik suggest set --note "..."` containing the **full proposed end-state**.
130
+ - A decision record in the draft (`metadata.suggestion.decision`): **context** (the problem and forces, not the solution), **decision**, **alternatives** (at least one real option not chosen), **consequences** (what gets easier *and* harder). `suggest set` refuses a draft without it.
131
+ - For changes that add data, an outside system or public traffic: `crossCutting` with **security** (who can reach it, secrets, data exposure), **observability** (how you will see it work or fail) and **rollback** (how to undo it safely).
132
+ - Model only what this milestone needs in detail; later areas stay coarse placeholders.
115
133
  - New code-bearing nodes use `status: proposed` and may omit `sourcePath`.
116
134
  - Containers via `parentId`; a big subsystem gets its own sub-file via `archikFile`.
117
135
  - `description` on every node explains *what it does*, not *what kind it is*.
@@ -120,6 +138,7 @@ Every milestone follows the same shape. Two gate types apply — **canvas gate**
120
138
 
121
139
  ### DECIDE
122
140
  - The user runs `/archik:accept` (apply) or `/archik:reject` (with a reason).
141
+ - On accept: the decision record lands in `.archik/decisions/NNNN-<slug>.md`, with the model change listed as evidence.
123
142
  - On reject: ask one specific question pinned to one axis — boundary / relationship / scope / naming / composition / lifecycle. Treat the answer as a hard constraint, re-stage. Never silently retry the same draft.
124
143
 
125
144
  ### BUILD
@@ -136,11 +155,12 @@ Every milestone follows the same shape. Two gate types apply — **canvas gate**
136
155
  2. Lint — clean.
137
156
  3. Build / typecheck — clean.
138
157
  4. `npx archik validate` — schema + cross-file + constraint checks clean.
139
- 5. `npx archik drift` — structural model matches disk.
140
- 6. `npx archik smells` — no new folder loops or oversized files. `--fail-on-warn` for CI gates.
141
- 7. Aesthetic eyeball when there's a UI — share a screenshot, ask before declaring done.
142
- 8. Stage the `proposed → active` sidecar — flip nodes/edges with `sourcePath`.
143
- 9. Commit (with a Co-Authored-By line) and push — only after user confirms.
158
+ 5. `npx archik drift` — structural model matches disk; `npx archik gap` — "the code matches the model".
159
+ 6. `npx archik smells` — no **new** folder loops or oversized files. On existing code, run `npx archik smells --update-baseline` once and commit `.archik/smells-baseline.json`; `--fail-on-warn` then fails CI only on new findings. Tighten the baseline when findings are fixed.
160
+ 7. For one-way doors: the record's `crossCutting` promises (security control, signal, rollback path) exist in the code.
161
+ 8. Aesthetic eyeball when there's a UI — share a screenshot, ask before declaring done.
162
+ 9. Stage the `proposed → active` sidecar — flip nodes/edges with `sourcePath`.
163
+ 10. Commit (with a Co-Authored-By line) and push — only after user confirms.
144
164
 
145
165
  ## Archik commands I use
146
166
 
@@ -154,7 +174,7 @@ Every milestone follows the same shape. Two gate types apply — **canvas gate**
154
174
  - `npx archik suggest set --note "<one-liner>" - <<'YAML' ... YAML` — stage a structural sidecar (full document).
155
175
 
156
176
  **Lifecycle:**
157
- - `npx archik suggest accept | reject | show` — structural sidecar lifecycle.
177
+ - `npx archik suggest accept | reject | show` — structural sidecar lifecycle. Accept writes the decision record.
158
178
  - `npx archik validate` — schema + cross-file + constraint checks.
159
179
 
160
180
  **Verification & rendering:**
@@ -167,6 +187,8 @@ Every milestone follows the same shape. Two gate types apply — **canvas gate**
167
187
  - **Editing `.archik/main.archik.yaml` by hand** — forbidden; always go through `suggest set`.
168
188
  - **Writing prose-only summaries instead of staging a sidecar** — every structural change must produce a reviewable artifact.
169
189
  - **Skipping the BUILD-plan HITL** — diagram acceptance is not implicit code approval.
190
+ - **A decision record with only upsides** — consequences must name what gets harder too; alternatives must be options you really weighed.
191
+ - **Editing an old decision record** — records are history. Stage a new decision that `supersedes` it.
170
192
  - **Renaming an `id` mid-flow** — forbidden; remove the old and add a new one. Renames break diff and require manual re-link in code.
171
193
  - **Labelling a smell without evidence** — name a folder loop by the imports `archik smells` shows, not by a made-up category.
172
194
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archik",
3
- "version": "0.20.0",
3
+ "version": "0.22.0",
4
4
  "description": "The shared vocabulary between you and Claude Code, at the engineering level. Plain-YAML architecture diagrams with a live browser canvas, headless SVG render in CI, and an installable Claude skill so the model treats the diagram as the spec.",
5
5
  "keywords": [
6
6
  "architecture",
@@ -9,6 +9,9 @@ description: Use whenever .archik/main.archik.yaml or architecture.archik.yaml e
9
9
 
10
10
  - **The YAML is the source of truth.** `.archik/main.archik.yaml` (and any `*.archik.yaml` sub-files) describe the system the user is building. The browser canvas is just a stateless projection of that file.
11
11
  - **The CLI is your only interface to it.** You never read, write, or edit archik files directly. Every read goes through `npx archik q ...`; every write goes through `npx archik suggest set` → user accepts via `/archik:accept`.
12
+ - **Every change says why.** A draft carries a short decision record (context, decision, alternatives, consequences). Accept writes it to `.archik/decisions/NNNN-<slug>.md`. The diagram is the *what*; the records are the *why*. Read past records before you change a structure they explain — they are plain markdown, so reading them directly is fine (the "CLI only" rule is about the YAML model files).
13
+ - **The architect chose a structure — follow it.** If the model declares a `style` (layered, hexagonal, clean, modular-monolith, feature-slices), run `npx archik style` before you design anything. Every new node goes in a layer (or module) that fits its job, and every dependency follows the style's rule — `suggest set` rejects one that breaks it. Put the code where the layer says: an adapter's code lives with the adapters, not inside the core. If the change seems to need a dependency the style forbids, that is a design question for the user — ask, don't work around it.
14
+ - **The architect steers the model; you make the code follow.** The architect may change the architecture directly on the canvas — move a box into another module, draw or delete an edge, set a layer — and save it with a decision record. The model is then ahead of the code. `npx archik gap` lists exactly what the code must change (move / create code, remove or add imports, style breaks, nodes to finish). When the user says the architecture changed, or runs `/archik:realize`, work that list until `gap` says the code matches the model. A `proposed` node's `sourcePath` is where its code is *planned* to live.
12
15
  - **Two command surfaces:** the user types `/archik:*` slash commands; you run `npx archik ...` directly. They're not interchangeable — see the tables below.
13
16
  - **One change to ship, not the whole system.** When a user hands you a brief on a fresh project, never say "let me sketch your whole system." Propose the smallest structure that delivers the first piece of value. New code-bearing nodes start `status: proposed` (the code doesn't exist on disk yet) and flip to `status: active` when the code lands in BUILD. The project's commitments live in the YAML, not in the chat log.
14
17
  - **Read the learned overlay at session start.** If `.archik/evolution/learned.md` exists, read it (with the Read tool — it is docs, not an archik YAML) before your first archik action and treat every note as binding guidance. Each note is a lesson this project's evolution loop gathered from real usage and a human approved. After a suggestion of yours is rejected, run `npx archik evolution reflect` — repeated rejections become proposals the user can review.
@@ -29,6 +32,7 @@ These are the user's entry points. They're triggered by the user typing `/archik
29
32
  | `/archik:dev` | Open the live canvas |
30
33
  | `/archik:accept` | Apply the pending sidecar suggestion |
31
34
  | `/archik:reject` | Discard the pending sidecar suggestion |
35
+ | `/archik:realize` | Make the code match the model the architect changed (works `archik gap`) |
32
36
  | `/archik:self-evolving <idea>` | Design a self-evolving architecture for the user's idea, using the pattern library |
33
37
 
34
38
  The full protocol for each lives at `commands/<name>.md` in the repo (or `.claude/commands/archik/<name>.md` once installed in a project). Follow it when invoked.
@@ -48,7 +52,11 @@ These are the verbs you reach for during the loop. Default to `npx archik` (no g
48
52
  | Verify edges against the code | `npx archik drift --edges [--json]` |
49
53
  | Validate a file | `npx archik validate <path>` |
50
54
  | Spot over-complex files / hubs | `npx archik complexity [--fail-on-warn]` |
55
+ | See the architecture style + where nodes sit | `npx archik style` (`list` for all styles) |
56
+ | What the code must change to match the model | `npx archik gap [--json] [--all]` |
57
+ | Where a node sits / what it may use | `npx archik q describe <id>` (the `style:` line) |
51
58
  | Find folder loops / oversized files | `npx archik smells [dir] [--json] [--fail-on-warn]` |
59
+ | Accept today's smells as known debt | `npx archik smells --update-baseline` (commit `.archik/smells-baseline.json`) |
52
60
  | Stage a proposed change | `npx archik suggest set --note '…' - <<'YAML' … YAML` |
53
61
  | Show / accept / reject pending | `npx archik suggest show \| accept \| reject` |
54
62
  | Render an SVG | `npx archik render --out diagram.svg` |
@@ -79,9 +87,9 @@ Every structural change runs the loop. Don't skip phases; don't silently retry o
79
87
  └─────┬──────┘ exists.
80
88
  │
81
89
  ┌─────▼──────┐ Frame intent in one line + 1–3 sharp clarifying Qs.
82
- │ DESIGN │ Stage sidecar (`suggest set`) with rationale:
83
- │ │ bounded contexts, sync vs async, composition,
84
- └─────┬──────┘ alternatives rejected. ◄── reject + reason ──┐
90
+ │ DESIGN │ Stage sidecar (`suggest set`) with its decision
91
+ │ │ record: context, decision, alternatives,
92
+ └─────┬──────┘ consequences. ◄── reject + reason ──┐
85
93
  │ │
86
94
  ┌─────▼──────┐ Canvas diff: accept | reject (why?) | revise. │
87
95
  │ DECIDE │ ───────────────────────────────────────────────────►┤
@@ -100,10 +108,10 @@ Every structural change runs the loop. Don't skip phases; don't silently retry o
100
108
 
101
109
  | Phase | Driver | Tool you reach for |
102
110
  | -------- | ------------- | --------------------------------------------------- |
103
- | Discover | Claude | `npx archik q ...` + `npx archik affected` + `npx archik smells` + `ls` |
104
- | Design | Claude → User | sidecar via `suggest set` |
105
- | Decide | User | `/archik:accept` or `/archik:reject` (HITL gate) |
106
- | Build | Claude → User | numbered plan (HITL approval), then small commits |
111
+ | Discover | Claude | `npx archik style` + `npx archik q ...` + `npx archik affected` + `npx archik smells` + `ls` + past records in `.archik/decisions/` |
112
+ | Design | Claude → User | sidecar via `suggest set`, with its decision record |
113
+ | Decide | User | `/archik:accept` or `/archik:reject` (HITL gate) — one-way doors alone, two-way doors together with the plan |
114
+ | Build | Claude → User | numbered plan (own HITL approval for one-way doors), then small commits |
107
115
  | Verify | Claude | `npx archik validate` + tests + `drift` + `smells` + SVG regen |
108
116
 
109
117
  **Two non-obvious feedback edges:**
@@ -172,9 +180,37 @@ edges:
172
180
  from: payments-worker
173
181
  to: order-events
174
182
  relationship: subscribes
183
+ metadata:
184
+ suggestion:
185
+ decision:
186
+ context: Orders-api charges Stripe inline, so a slow Stripe call blocks checkout and a Stripe outage fails orders.
187
+ decision: Move charging to a payments worker that subscribes to order.placed on the order-events stream.
188
+ alternatives:
189
+ - Keep the inline call with a shorter timeout and retries
190
+ - Call a payments service synchronously over HTTP
191
+ consequences: Checkout no longer waits on Stripe; payment becomes eventually consistent, so the UI must show a "payment pending" state.
192
+ crossCutting:
193
+ security: The worker alone holds the Stripe key (secret store); events carry order ids, not card data.
194
+ observability: Consumer lag and failed-charge count on the payments dashboard, alert on lag over 5 minutes.
195
+ rollback: A flag switches checkout back to the inline call; the stream is additive.
175
196
  YAML
176
197
  ```
177
198
 
199
+ **The decision record is required** — `suggest set` refuses a draft without it, and accept writes it to `.archik/decisions/`. Write it for the reader who arrives in a year:
200
+
201
+ - **context** — the problem and the forces (load, failure modes, team limits). Facts, not the solution.
202
+ - **decision** — what you chose, in one or two sentences.
203
+ - **alternatives** — real options you weighed and did not choose. At least one. "Do nothing" counts when it was a real option.
204
+ - **consequences** — what gets easier AND what gets harder. A record with only upsides is not finished.
205
+ - **crossCutting** — required when the change adds data, an outside system or public traffic (the CLI tells you). **security**: who can reach it, secrets, data exposure. **observability**: the signal that shows it working or failing. **rollback**: how to undo it safely. Real answers — the build plan must land them.
206
+ - **supersedes** (optional) — record numbers this one replaces, e.g. `["0003"]`. Old records are never edited.
207
+
208
+ **One-way vs two-way doors.** `suggest set` and `suggest show` label each change. A **one-way door** (hard to undo) adds a data store, queue/stream, external system, gateway/auth/cdn, cloud or LLM node, a new edge to an external system or a top-level module, or removes a built node, or moves one to another parent. Hand it off alone and say why it is hard to undo; the build plan gets its own approval after accept. A **two-way door** is everything else — show the build plan in the same hand-off, and one `/archik:accept` approves both. Never skip review of a one-way door to save time.
209
+
210
+ **Model only what you know.** On a new project, model the first milestone in detail and the rest as coarse `proposed` module placeholders; detail each area when its milestone starts.
211
+
212
+ For a mechanical change (flip `proposed → active` after code lands), keep it short: context = what landed, decision = mark it active, alternative = keep it proposed until deploy, consequence = drift now checks it.
213
+
178
214
  The CLI parses, schema-validates, checks cross-file references, stamps `metadata.suggestion`, and atomically writes the sidecar. If it exits non-zero, the error includes a hint pointing at the wrong field — fix the heredoc and re-run. **Never edit the sidecar by hand.**
179
215
 
180
216
  ```bash
@@ -190,6 +226,7 @@ npx archik validate .archik/main.archik.yaml # schema + cross-file + constrain
190
226
  npx archik drift # diagram vs source tree
191
227
  npx archik affected --json # what did this change touch? who depends on it?
192
228
  npx archik smells # folder loops + oversized files, from the code
229
+ # (with a baseline, only NEW findings count)
193
230
  npx archik render --out docs/architecture.svg # if the project commits an SVG
194
231
  ```
195
232
 
@@ -211,6 +248,9 @@ version: "1.0"
211
248
  name: Payments internals
212
249
  nodes: [ ... ]
213
250
  edges: [ ... ]
251
+ metadata:
252
+ suggestion:
253
+ decision: { context: ..., decision: ..., alternatives: [...], consequences: ... }
214
254
  YAML
215
255
  npx archik suggest accept .archik/payments.archik.yaml
216
256
 
@@ -225,6 +265,9 @@ nodes:
225
265
  ... (every other node)
226
266
  edges:
227
267
  ... (every edge)
268
+ metadata:
269
+ suggestion:
270
+ decision: { context: ..., decision: ..., alternatives: [...], consequences: ... }
228
271
  YAML
229
272
  ```
230
273
 
@@ -343,6 +386,7 @@ Run a candidate through this checklist before staging a sidecar. Each item is a
343
386
  - **Bounded contexts.** Name the context this change belongs to. A change spanning two contexts usually means a missing third (orchestrator, port, gateway).
344
387
  - **Async at context boundaries.** Default cross-context coupling to `publishes` / `subscribes` over a stream/queue. `http_call` across contexts is allowed but should be justified (sync-required RPC, query for read-side data).
345
388
  - **Composition over sprawl.** Group related nodes under a `module` parent via `parentId`. Flat top-level lists past ~8 nodes are a smell. Run `npx archik complexity` to catch this objectively — it flags over-large files, over-stuffed containers, hub nodes, and deep nesting, each with a concrete fix.
389
+ - **Follow the declared style.** Layered: depend down only, outside systems only from infrastructure. Hexagonal: adapters plug into ports; the core and its ports never know an adapter or an outside system — add a port in the core and an adapter that implements it. Clean: inward only. Modular monolith: talk to another module only through its interface / port node. Feature slices: no slice uses another — move shared needs to a shared module. A new node without a `layer` (layered kinds) is skipped by the checks, so always set one on new top-level nodes.
346
390
  - **No folder loops.** Dependencies between sibling folders should flow one way. Run `npx archik smells` — it reads the code (no model needed) and reports folder loops with the real `file imports "specifier"` lines as evidence, plus the cheapest import to cut. Name smells by that evidence; don't invent labels.
347
391
  - **Ports & adapters at the edge.** External integrations sit behind an `external` node, never inline in a service. Port (interface) + adapter (concrete) is preferred when the integration could swap.
348
392
  - **Public traffic → gateway/auth upstream.** Anything user-facing routes through a `gateway`/`auth` node, not directly to a service.
@@ -429,7 +473,14 @@ npx archik complexity [path] [--json] # advisory report: over-large files, hub
429
473
  [--fail-on-warn] # exit 1 if any finding (CI / pre-commit gate)
430
474
  [--max-nodes N] [--max-edges N] [--max-children N]
431
475
  [--max-degree N] [--max-depth N] # override the strict defaults
476
+ npx archik gap [--json] [--all] # what the code must change to match the model
477
+ [--fail-on-gap] # (move/create code, imports, style, finish)
478
+ npx archik style [list] [--json] # the architecture style: rule, layers / modules,
479
+ # violations; list = every style + its YAML
432
480
  npx archik smells [dir] [--json] # folder loops + oversized files, read from TS/JS code
481
+ [--fail-on-warn] # exit 1 on findings (only NEW ones if a baseline exists)
482
+ [--update-baseline] # save today's findings to .archik/smells-baseline.json
483
+ [--baseline <file>] # use another baseline file
433
484
  [--max-file-lines N] # line limit per file (default 500)
434
485
  [--fail-on-warn] # exit 1 if any smell (CI gate)
435
486
  npx archik render --out diagram.svg --theme light|dark
@@ -450,11 +501,16 @@ npx archik otel check --graph <deps.json> [--json]
450
501
 
451
502
  npx archik suggest show [--json]
452
503
  suggest set <draft|-> # validate + stage a sidecar
453
- --note '<text>' # set metadata.suggestion.note
504
+ # (draft needs metadata.suggestion.decision)
505
+ --note '<text>' # set metadata.suggestion.note (record title)
454
506
  --main <path> # override main file detection
455
507
  --allow-orphan # permit a sidecar with no main on disk
456
508
  --json # structured output
457
- suggest accept | reject
509
+ suggest accept | reject # accept writes .archik/decisions/NNNN-*.md
510
+
511
+ npx archik migrate [--dry-run] # bring this project's archik files up to the
512
+ # installed version; if validate says a key
513
+ # was "removed in archik 0.20", run this
458
514
 
459
515
  npx archik dev | start | stop | status # canvas server lifecycle
460
516
  npx archik watch # re-render to SVG on save