buildanything 1.8.0 → 2.0.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.
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +9 -3
- package/CHANGELOG.md +57 -0
- package/README.md +2 -2
- package/agents/a11y-architect.md +166 -0
- package/agents/business-model.md +80 -29
- package/agents/code-architect.md +75 -0
- package/agents/code-reviewer.md +255 -0
- package/agents/code-simplifier.md +64 -0
- package/agents/design-brand-guardian.md +293 -53
- package/agents/design-critic.md +139 -0
- package/agents/design-inclusive-visuals-specialist.md +6 -19
- package/agents/design-ui-designer.md +335 -56
- package/agents/design-ux-architect.md +403 -55
- package/agents/design-ux-researcher.md +264 -49
- package/agents/engineering-ai-engineer.md +26 -36
- package/agents/engineering-backend-architect.md +185 -36
- package/agents/engineering-data-engineer.md +225 -43
- package/agents/engineering-devops-automator.md +227 -74
- package/agents/engineering-frontend-developer.md +210 -34
- package/agents/engineering-mobile-app-builder.md +6 -1
- package/agents/engineering-rapid-prototyper.md +30 -9
- package/agents/engineering-security-engineer.md +263 -61
- package/agents/engineering-senior-developer.md +128 -19
- package/agents/engineering-sre.md +84 -0
- package/agents/engineering-technical-writer.md +285 -41
- package/agents/feature-intel.md +110 -0
- package/agents/ios-app-review-guardian.md +19 -2
- package/agents/ios-foundation-models-specialist.md +20 -2
- package/agents/ios-storekit-specialist.md +9 -2
- package/agents/ios-swift-architect.md +28 -1
- package/agents/ios-swift-search.md +8 -1
- package/agents/ios-swift-ui-design.md +33 -1
- package/agents/marketing-app-store-optimizer.md +246 -64
- package/agents/planner.md +216 -0
- package/agents/pr-test-analyzer.md +63 -0
- package/agents/product-feedback-synthesizer.md +8 -2
- package/agents/refactor-cleaner.md +102 -0
- package/agents/security-reviewer.md +128 -0
- package/agents/silent-failure-hunter.md +54 -0
- package/agents/swift-build-resolver.md +119 -0
- package/agents/swift-reviewer.md +112 -0
- package/agents/tech-feasibility.md +21 -1
- package/agents/testing-api-tester.md +236 -59
- package/agents/testing-evidence-collector.md +26 -1
- package/agents/testing-performance-benchmarker.md +21 -1
- package/agents/testing-reality-checker.md +6 -1
- package/agents/visual-research.md +116 -0
- package/bin/adapters/cycle-counter-tool.ts +155 -0
- package/bin/adapters/scribe-tool.ts +71 -0
- package/bin/adapters/state-save-tool.ts +130 -0
- package/bin/adapters/write-lease-tool.ts +127 -0
- package/bin/buildanything-runtime.js +15 -0
- package/bin/buildanything-runtime.ts +328 -0
- package/bin/setup.js +83 -8
- package/commands/add-feature.md +2 -0
- package/commands/build.md +782 -266
- package/commands/fix.md +1 -1
- package/commands/self-check.md +121 -0
- package/commands/setup.md +50 -9
- package/commands/ux-review.md +2 -2
- package/commands/verify.md +6 -9
- package/docs/migration/agents.yaml +729 -0
- package/docs/migration/phase-graph.yaml +1088 -0
- package/docs/migration/sdk-host-compat.md +18 -0
- package/hooks/compile-writer-owner-cache.ts +171 -0
- package/hooks/hooks.json +36 -0
- package/hooks/pre-tool-use +19 -0
- package/hooks/pre-tool-use.ts +776 -0
- package/hooks/record-mode-transitions.ts +178 -0
- package/hooks/session-start +71 -1
- package/hooks/subagent-start +17 -0
- package/hooks/subagent-start.ts +471 -0
- package/hooks/subagent-stop +17 -0
- package/hooks/subagent-stop.ts +153 -0
- package/package.json +24 -4
- package/protocols/architecture-schema.md +171 -0
- package/protocols/decision-log.md +131 -0
- package/protocols/ios-context.md +10 -11
- package/protocols/ios-phase-branches.md +208 -33
- package/protocols/launch-readiness.md +258 -0
- package/protocols/metric-loop.md +62 -2
- package/protocols/smoke-test.md +9 -1
- package/protocols/state-schema.json +388 -0
- package/protocols/state-schema.md +172 -0
- package/protocols/verify.md +62 -2
- package/protocols/visual-dna.md +185 -0
- package/protocols/web-phase-branches.md +222 -72
- package/skills/ios/_VENDORED.md +2 -0
- package/skills/ios/app-store-connect-metadata/SKILL.md +148 -0
- package/skills/ios/asc-privacy-manifest/SKILL.md +350 -0
- package/skills/ios/hig-components-content/SKILL.md +86 -0
- package/skills/ios/hig-components-content/references/activity-views.md +79 -0
- package/skills/ios/hig-components-content/references/charts.md +180 -0
- package/skills/ios/hig-components-content/references/collections.md +48 -0
- package/skills/ios/hig-components-content/references/color-wells.md +42 -0
- package/skills/ios/hig-components-content/references/image-views.md +82 -0
- package/skills/ios/hig-components-content/references/image-wells.md +34 -0
- package/skills/ios/hig-components-content/references/lockups.md +78 -0
- package/skills/ios/hig-components-content/references/web-views.md +36 -0
- package/skills/ios/hig-components-controls/SKILL.md +88 -0
- package/skills/ios/hig-components-controls/references/combo-boxes.md +40 -0
- package/skills/ios/hig-components-controls/references/controls.md +112 -0
- package/skills/ios/hig-components-controls/references/gauges.md +74 -0
- package/skills/ios/hig-components-controls/references/labels.md +92 -0
- package/skills/ios/hig-components-controls/references/pickers.md +128 -0
- package/skills/ios/hig-components-controls/references/rating-indicators.md +38 -0
- package/skills/ios/hig-components-controls/references/segmented-controls.md +94 -0
- package/skills/ios/hig-components-controls/references/sliders.md +92 -0
- package/skills/ios/hig-components-controls/references/steppers.md +40 -0
- package/skills/ios/hig-components-controls/references/text-fields.md +88 -0
- package/skills/ios/hig-components-controls/references/text-views.md +56 -0
- package/skills/ios/hig-components-controls/references/toggles.md +127 -0
- package/skills/ios/hig-components-controls/references/token-fields.md +48 -0
- package/skills/ios/hig-components-controls/references/virtual-keyboards.md +156 -0
- package/skills/ios/hig-components-dialogs/SKILL.md +76 -0
- package/skills/ios/hig-components-dialogs/references/action-sheets.md +74 -0
- package/skills/ios/hig-components-dialogs/references/alerts.md +158 -0
- package/skills/ios/hig-components-dialogs/references/digit-entry-views.md +32 -0
- package/skills/ios/hig-components-dialogs/references/popovers.md +81 -0
- package/skills/ios/hig-components-dialogs/references/sheets.md +157 -0
- package/skills/ios/hig-components-layout/SKILL.md +99 -0
- package/skills/ios/hig-components-layout/references/boxes.md +48 -0
- package/skills/ios/hig-components-layout/references/column-views.md +44 -0
- package/skills/ios/hig-components-layout/references/lists-and-tables.md +99 -0
- package/skills/ios/hig-components-layout/references/ornaments.md +56 -0
- package/skills/ios/hig-components-layout/references/outline-views.md +64 -0
- package/skills/ios/hig-components-layout/references/panels.md +75 -0
- package/skills/ios/hig-components-layout/references/scroll-views.md +123 -0
- package/skills/ios/hig-components-layout/references/sidebars.md +109 -0
- package/skills/ios/hig-components-layout/references/split-views.md +110 -0
- package/skills/ios/hig-components-layout/references/tab-bars.md +173 -0
- package/skills/ios/hig-components-layout/references/tab-views.md +68 -0
- package/skills/ios/hig-components-layout/references/windows.md +188 -0
- package/skills/ios/hig-components-menus/SKILL.md +81 -0
- package/skills/ios/hig-components-menus/references/action-button.md +61 -0
- package/skills/ios/hig-components-menus/references/buttons.md +261 -0
- package/skills/ios/hig-components-menus/references/context-menus.md +105 -0
- package/skills/ios/hig-components-menus/references/disclosure-controls.md +84 -0
- package/skills/ios/hig-components-menus/references/dock-menus.md +40 -0
- package/skills/ios/hig-components-menus/references/edit-menus.md +88 -0
- package/skills/ios/hig-components-menus/references/menus.md +171 -0
- package/skills/ios/hig-components-menus/references/pop-up-buttons.md +70 -0
- package/skills/ios/hig-components-menus/references/pull-down-buttons.md +77 -0
- package/skills/ios/hig-components-menus/references/the-menu-bar.md +303 -0
- package/skills/ios/hig-components-menus/references/toolbars.md +256 -0
- package/skills/ios/hig-components-search/SKILL.md +68 -0
- package/skills/ios/hig-components-search/references/page-controls.md +120 -0
- package/skills/ios/hig-components-search/references/path-controls.md +40 -0
- package/skills/ios/hig-components-search/references/search-fields.md +189 -0
- package/skills/ios/hig-components-status/SKILL.md +80 -0
- package/skills/ios/hig-components-status/references/activity-rings.md +105 -0
- package/skills/ios/hig-components-status/references/progress-indicators.md +116 -0
- package/skills/ios/hig-components-status/references/status-bars.md +38 -0
- package/skills/ios/hig-components-system/SKILL.md +88 -0
- package/skills/ios/hig-components-system/references/app-clips.md +387 -0
- package/skills/ios/hig-components-system/references/app-shortcuts.md +114 -0
- package/skills/ios/hig-components-system/references/complications.md +425 -0
- package/skills/ios/hig-components-system/references/home-screen-quick-actions.md +42 -0
- package/skills/ios/hig-components-system/references/live-activities.md +442 -0
- package/skills/ios/hig-components-system/references/notifications.md +153 -0
- package/skills/ios/hig-components-system/references/top-shelf.md +135 -0
- package/skills/ios/hig-components-system/references/watch-faces.md +40 -0
- package/skills/ios/hig-components-system/references/widgets.md +517 -0
- package/skills/ios/hig-foundations/SKILL.md +98 -0
- package/skills/ios/hig-foundations/references/accessibility.md +291 -0
- package/skills/ios/hig-foundations/references/app-icons.md +210 -0
- package/skills/ios/hig-foundations/references/branding.md +44 -0
- package/skills/ios/hig-foundations/references/color.md +274 -0
- package/skills/ios/hig-foundations/references/dark-mode.md +116 -0
- package/skills/ios/hig-foundations/references/icons.md +263 -0
- package/skills/ios/hig-foundations/references/images.md +176 -0
- package/skills/ios/hig-foundations/references/immersive-experiences.md +174 -0
- package/skills/ios/hig-foundations/references/inclusion.md +189 -0
- package/skills/ios/hig-foundations/references/layout.md +425 -0
- package/skills/ios/hig-foundations/references/materials.md +238 -0
- package/skills/ios/hig-foundations/references/motion.md +103 -0
- package/skills/ios/hig-foundations/references/privacy.md +231 -0
- package/skills/ios/hig-foundations/references/right-to-left.md +206 -0
- package/skills/ios/hig-foundations/references/sf-symbols.md +310 -0
- package/skills/ios/hig-foundations/references/spatial-layout.md +142 -0
- package/skills/ios/hig-foundations/references/typography.md +1146 -0
- package/skills/ios/hig-foundations/references/writing.md +91 -0
- package/skills/ios/hig-inputs/SKILL.md +94 -0
- package/skills/ios/hig-inputs/references/apple-pencil-and-scribble.md +148 -0
- package/skills/ios/hig-inputs/references/camera-control.md +107 -0
- package/skills/ios/hig-inputs/references/digital-crown.md +83 -0
- package/skills/ios/hig-inputs/references/eyes.md +120 -0
- package/skills/ios/hig-inputs/references/focus-and-selection.md +120 -0
- package/skills/ios/hig-inputs/references/game-controls.md +156 -0
- package/skills/ios/hig-inputs/references/gestures.md +208 -0
- package/skills/ios/hig-inputs/references/gyro-and-accelerometer.md +40 -0
- package/skills/ios/hig-inputs/references/keyboards.md +234 -0
- package/skills/ios/hig-inputs/references/nearby-interactions.md +70 -0
- package/skills/ios/hig-inputs/references/pointing-devices.md +237 -0
- package/skills/ios/hig-inputs/references/remotes.md +67 -0
- package/skills/ios/hig-inputs/references/spatial-interactions.md +70 -0
- package/skills/ios/hig-patterns/SKILL.md +104 -0
- package/skills/ios/hig-patterns/references/charting-data.md +81 -0
- package/skills/ios/hig-patterns/references/collaboration-and-sharing.md +86 -0
- package/skills/ios/hig-patterns/references/drag-and-drop.md +134 -0
- package/skills/ios/hig-patterns/references/entering-data.md +69 -0
- package/skills/ios/hig-patterns/references/feedback.md +67 -0
- package/skills/ios/hig-patterns/references/file-management.md +135 -0
- package/skills/ios/hig-patterns/references/going-full-screen.md +79 -0
- package/skills/ios/hig-patterns/references/launching.md +81 -0
- package/skills/ios/hig-patterns/references/live-viewing-apps.md +79 -0
- package/skills/ios/hig-patterns/references/loading.md +59 -0
- package/skills/ios/hig-patterns/references/managing-accounts.md +107 -0
- package/skills/ios/hig-patterns/references/managing-notifications.md +99 -0
- package/skills/ios/hig-patterns/references/modality.md +82 -0
- package/skills/ios/hig-patterns/references/multitasking.md +131 -0
- package/skills/ios/hig-patterns/references/offering-help.md +117 -0
- package/skills/ios/hig-patterns/references/onboarding.md +69 -0
- package/skills/ios/hig-patterns/references/playing-audio.md +124 -0
- package/skills/ios/hig-patterns/references/playing-haptics.md +280 -0
- package/skills/ios/hig-patterns/references/playing-video.md +180 -0
- package/skills/ios/hig-patterns/references/printing.md +50 -0
- package/skills/ios/hig-patterns/references/ratings-and-reviews.md +48 -0
- package/skills/ios/hig-patterns/references/searching.md +70 -0
- package/skills/ios/hig-patterns/references/settings.md +84 -0
- package/skills/ios/hig-patterns/references/undo-and-redo.md +58 -0
- package/skills/ios/hig-patterns/references/workouts.md +76 -0
- package/skills/ios/hig-platforms/SKILL.md +84 -0
- package/skills/ios/hig-platforms/references/designing-for-games.md +159 -0
- package/skills/ios/hig-platforms/references/designing-for-ios.md +66 -0
- package/skills/ios/hig-platforms/references/designing-for-ipados.md +64 -0
- package/skills/ios/hig-platforms/references/designing-for-macos.md +70 -0
- package/skills/ios/hig-platforms/references/designing-for-tvos.md +68 -0
- package/skills/ios/hig-platforms/references/designing-for-visionos.md +85 -0
- package/skills/ios/hig-platforms/references/designing-for-watchos.md +74 -0
- package/skills/ios/hig-project-context/SKILL.md +133 -0
- package/skills/ios/hig-technologies/SKILL.md +107 -0
- package/skills/ios/hig-technologies/references/airplay.md +125 -0
- package/skills/ios/hig-technologies/references/always-on.md +62 -0
- package/skills/ios/hig-technologies/references/apple-pay.md +441 -0
- package/skills/ios/hig-technologies/references/augmented-reality.md +247 -0
- package/skills/ios/hig-technologies/references/carekit.md +224 -0
- package/skills/ios/hig-technologies/references/carplay.md +119 -0
- package/skills/ios/hig-technologies/references/game-center.md +343 -0
- package/skills/ios/hig-technologies/references/generative-ai.md +110 -0
- package/skills/ios/hig-technologies/references/healthkit.md +120 -0
- package/skills/ios/hig-technologies/references/homekit.md +343 -0
- package/skills/ios/hig-technologies/references/icloud.md +52 -0
- package/skills/ios/hig-technologies/references/id-verifier.md +73 -0
- package/skills/ios/hig-technologies/references/imessage-apps-and-stickers.md +105 -0
- package/skills/ios/hig-technologies/references/in-app-purchase.md +263 -0
- package/skills/ios/hig-technologies/references/live-photos.md +54 -0
- package/skills/ios/hig-technologies/references/mac-catalyst.md +216 -0
- package/skills/ios/hig-technologies/references/machine-learning.md +394 -0
- package/skills/ios/hig-technologies/references/maps.md +221 -0
- package/skills/ios/hig-technologies/references/nfc.md +51 -0
- package/skills/ios/hig-technologies/references/photo-editing.md +40 -0
- package/skills/ios/hig-technologies/references/researchkit.md +134 -0
- package/skills/ios/hig-technologies/references/shareplay.md +142 -0
- package/skills/ios/hig-technologies/references/shazamkit.md +47 -0
- package/skills/ios/hig-technologies/references/sign-in-with-apple.md +288 -0
- package/skills/ios/hig-technologies/references/siri.md +523 -0
- package/skills/ios/hig-technologies/references/tap-to-pay-on-iphone.md +208 -0
- package/skills/ios/hig-technologies/references/voiceover.md +90 -0
- package/skills/ios/hig-technologies/references/wallet.md +420 -0
- package/skills/ios/ios-bootstrap/SKILL.md +16 -7
- package/skills/ios/swift-actor-persistence/SKILL.md +143 -0
- package/skills/ios/swift-concurrency-6-2/SKILL.md +216 -0
- package/skills/ios/swift-protocol-di-testing/SKILL.md +190 -0
- package/skills/ios/swiftui-design-tokens/SKILL.md +475 -0
- package/skills/ios/writing-for-interfaces/SKILL.md +75 -0
- package/skills/web/accessibility/SKILL.md +146 -0
- package/skills/web/aceternity-ui/SKILL.md +719 -0
- package/skills/web/aceternity-ui/metadata.json +10 -0
- package/skills/web/api-design/SKILL.md +523 -0
- package/skills/web/chart-accessibility/SKILL.md +332 -0
- package/skills/web/composition-patterns/AGENTS.md +946 -0
- package/skills/web/composition-patterns/README.md +60 -0
- package/skills/web/composition-patterns/SKILL.md +89 -0
- package/skills/web/composition-patterns/metadata.json +11 -0
- package/skills/web/composition-patterns/rules/_sections.md +29 -0
- package/skills/web/composition-patterns/rules/_template.md +24 -0
- package/skills/web/composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
- package/skills/web/composition-patterns/rules/architecture-compound-components.md +112 -0
- package/skills/web/composition-patterns/rules/patterns-children-over-render-props.md +87 -0
- package/skills/web/composition-patterns/rules/patterns-explicit-variants.md +100 -0
- package/skills/web/composition-patterns/rules/react19-no-forwardref.md +42 -0
- package/skills/web/composition-patterns/rules/state-context-interface.md +191 -0
- package/skills/web/composition-patterns/rules/state-decouple-implementation.md +113 -0
- package/skills/web/composition-patterns/rules/state-lift-state.md +125 -0
- package/skills/web/cost-aware-llm-pipeline/SKILL.md +183 -0
- package/skills/web/database-migrations/SKILL.md +429 -0
- package/skills/web/deployment-patterns/SKILL.md +427 -0
- package/skills/web/docker-patterns/SKILL.md +364 -0
- package/skills/web/e2e-testing/SKILL.md +326 -0
- package/skills/web/lighthouse-ci/SKILL.md +361 -0
- package/skills/web/mcp-server-patterns/SKILL.md +69 -0
- package/skills/web/next-best-practices/SKILL.md +153 -0
- package/skills/web/next-best-practices/async-patterns.md +87 -0
- package/skills/web/next-best-practices/bundling.md +180 -0
- package/skills/web/next-best-practices/data-patterns.md +297 -0
- package/skills/web/next-best-practices/debug-tricks.md +105 -0
- package/skills/web/next-best-practices/directives.md +73 -0
- package/skills/web/next-best-practices/error-handling.md +227 -0
- package/skills/web/next-best-practices/file-conventions.md +140 -0
- package/skills/web/next-best-practices/font.md +245 -0
- package/skills/web/next-best-practices/functions.md +108 -0
- package/skills/web/next-best-practices/hydration-error.md +91 -0
- package/skills/web/next-best-practices/image.md +173 -0
- package/skills/web/next-best-practices/metadata.md +301 -0
- package/skills/web/next-best-practices/parallel-routes.md +287 -0
- package/skills/web/next-best-practices/route-handlers.md +146 -0
- package/skills/web/next-best-practices/rsc-boundaries.md +159 -0
- package/skills/web/next-best-practices/runtime-selection.md +39 -0
- package/skills/web/next-best-practices/scripts.md +141 -0
- package/skills/web/next-best-practices/self-hosting.md +371 -0
- package/skills/web/next-best-practices/suspense-boundaries.md +67 -0
- package/skills/web/next-cache-components/SKILL.md +411 -0
- package/skills/web/postgres-best-practices/SKILL.md +14 -0
- package/skills/web/postgres-best-practices/references/schema-design.md +9 -0
- package/skills/web/react-best-practices/AGENTS.md +3810 -0
- package/skills/web/react-best-practices/README.md +123 -0
- package/skills/web/react-best-practices/SKILL.md +149 -0
- package/skills/web/react-best-practices/metadata.json +15 -0
- package/skills/web/react-best-practices/rules/_sections.md +46 -0
- package/skills/web/react-best-practices/rules/_template.md +28 -0
- package/skills/web/react-best-practices/rules/advanced-effect-event-deps.md +56 -0
- package/skills/web/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/skills/web/react-best-practices/rules/advanced-init-once.md +42 -0
- package/skills/web/react-best-practices/rules/advanced-use-latest.md +39 -0
- package/skills/web/react-best-practices/rules/async-api-routes.md +38 -0
- package/skills/web/react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
- package/skills/web/react-best-practices/rules/async-defer-await.md +82 -0
- package/skills/web/react-best-practices/rules/async-dependencies.md +51 -0
- package/skills/web/react-best-practices/rules/async-parallel.md +28 -0
- package/skills/web/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/skills/web/react-best-practices/rules/bundle-analyzable-paths.md +63 -0
- package/skills/web/react-best-practices/rules/bundle-barrel-imports.md +60 -0
- package/skills/web/react-best-practices/rules/bundle-conditional.md +31 -0
- package/skills/web/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/skills/web/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/skills/web/react-best-practices/rules/bundle-preload.md +50 -0
- package/skills/web/react-best-practices/rules/client-event-listeners.md +74 -0
- package/skills/web/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/skills/web/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/skills/web/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/skills/web/react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/skills/web/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/skills/web/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/skills/web/react-best-practices/rules/js-cache-storage.md +70 -0
- package/skills/web/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/skills/web/react-best-practices/rules/js-early-exit.md +50 -0
- package/skills/web/react-best-practices/rules/js-flatmap-filter.md +60 -0
- package/skills/web/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/skills/web/react-best-practices/rules/js-index-maps.md +37 -0
- package/skills/web/react-best-practices/rules/js-length-check-first.md +49 -0
- package/skills/web/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/skills/web/react-best-practices/rules/js-request-idle-callback.md +105 -0
- package/skills/web/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/skills/web/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/skills/web/react-best-practices/rules/rendering-activity.md +26 -0
- package/skills/web/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/skills/web/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/skills/web/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/skills/web/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/skills/web/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/skills/web/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/skills/web/react-best-practices/rules/rendering-resource-hints.md +85 -0
- package/skills/web/react-best-practices/rules/rendering-script-defer-async.md +68 -0
- package/skills/web/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/skills/web/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/skills/web/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/skills/web/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/skills/web/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/skills/web/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/skills/web/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/skills/web/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/skills/web/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/skills/web/react-best-practices/rules/rerender-memo.md +44 -0
- package/skills/web/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/skills/web/react-best-practices/rules/rerender-no-inline-components.md +82 -0
- package/skills/web/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/skills/web/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
- package/skills/web/react-best-practices/rules/rerender-transitions.md +40 -0
- package/skills/web/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
- package/skills/web/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/skills/web/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/skills/web/react-best-practices/rules/server-auth-actions.md +96 -0
- package/skills/web/react-best-practices/rules/server-cache-lru.md +41 -0
- package/skills/web/react-best-practices/rules/server-cache-react.md +76 -0
- package/skills/web/react-best-practices/rules/server-dedup-props.md +65 -0
- package/skills/web/react-best-practices/rules/server-hoist-static-io.md +149 -0
- package/skills/web/react-best-practices/rules/server-no-shared-module-state.md +50 -0
- package/skills/web/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/skills/web/react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
- package/skills/web/react-best-practices/rules/server-serialization.md +38 -0
- package/skills/web/seo/SKILL.md +154 -0
- package/skills/web/web-design-guidelines/SKILL.md +39 -0
- package/skills/web/zap-scan-config/SKILL.md +444 -0
- package/skills/web/zap-scan-config/assets/.gitkeep +9 -0
- package/skills/web/zap-scan-config/assets/github_action.yml +207 -0
- package/skills/web/zap-scan-config/assets/gitlab_ci.yml +226 -0
- package/skills/web/zap-scan-config/assets/zap_automation.yaml +196 -0
- package/skills/web/zap-scan-config/assets/zap_context.xml +192 -0
- package/skills/web/zap-scan-config/references/EXAMPLE.md +40 -0
- package/skills/web/zap-scan-config/references/api_testing_guide.md +475 -0
- package/skills/web/zap-scan-config/references/authentication_guide.md +431 -0
- package/skills/web/zap-scan-config/references/false_positive_handling.md +427 -0
- package/skills/web/zap-scan-config/references/owasp_mapping.md +255 -0
- package/src/lrr/aggregator.ts +80 -0
- package/src/orchestrator/hooks/context-header.ts +95 -0
- package/src/orchestrator/hooks/token-accounting-emitter.ts +77 -0
- package/src/orchestrator/hooks/token-accounting.ts +101 -0
- package/src/orchestrator/mcp/cycle-counter.ts +129 -0
- package/src/orchestrator/mcp/scribe.ts +283 -0
- package/src/orchestrator/mcp/state-save.ts +149 -0
- package/src/orchestrator/mcp/write-lease.ts +167 -0
- package/src/orchestrator/phase4-shared-context.ts +41 -0
- package/src/orchestrator/schemas/backward-edge.ts +46 -0
- package/agents/agentic-identity-trust.md +0 -121
- package/agents/data-consolidation-agent.md +0 -39
- package/agents/design-image-prompt-engineer.md +0 -105
- package/agents/design-visual-storyteller.md +0 -147
- package/agents/design-whimsy-injector.md +0 -89
- package/agents/engineering-autonomous-optimization-architect.md +0 -105
- package/agents/market-intel.md +0 -35
- package/agents/marketing-instagram-curator.md +0 -111
- package/agents/marketing-reddit-community-builder.md +0 -121
- package/agents/marketing-social-media-strategist.md +0 -74
- package/agents/marketing-tiktok-strategist.md +0 -123
- package/agents/marketing-twitter-engager.md +0 -124
- package/agents/marketing-wechat-official-account.md +0 -143
- package/agents/marketing-xiaohongshu-specialist.md +0 -136
- package/agents/marketing-zhihu-strategist.md +0 -160
- package/agents/product-behavioral-nudge-engine.md +0 -78
- package/agents/project-management-experiment-tracker.md +0 -102
- package/agents/report-distribution-agent.md +0 -43
- package/agents/risk-analysis.md +0 -45
- package/agents/sales-data-extraction-agent.md +0 -46
- package/agents/specialized-cultural-intelligence-strategist.md +0 -65
- package/agents/specialized-developer-advocate.md +0 -146
- package/agents/support-analytics-reporter.md +0 -133
- package/agents/support-executive-summary-generator.md +0 -64
- package/agents/support-finance-tracker.md +0 -145
- package/agents/support-legal-compliance-checker.md +0 -129
- package/agents/support-support-responder.md +0 -91
- package/agents/testing-accessibility-auditor.md +0 -110
- package/agents/testing-test-results-analyzer.md +0 -97
- package/agents/testing-tool-evaluator.md +0 -76
- package/agents/testing-workflow-optimizer.md +0 -99
- package/agents/user-research.md +0 -40
- package/protocols/brainstorm.md +0 -99
- package/protocols/design.md +0 -269
- package/protocols/planning.md +0 -87
- package/skills/ios/ios-hig/SKILL.md +0 -41
- package/skills/ios/ios-hig/references/accessibility.md +0 -81
- package/skills/ios/ios-hig/references/content.md +0 -142
- package/skills/ios/ios-hig/references/feedback.md +0 -123
- package/skills/ios/ios-hig/references/interaction.md +0 -199
- package/skills/ios/ios-hig/references/performance-platform.md +0 -129
- package/skills/ios/ios-hig/references/privacy-permissions.md +0 -181
- package/skills/ios/ios-hig/references/visual-design.md +0 -84
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export type Verdict = 'PASS' | 'CONCERNS' | 'BLOCK';
|
|
2
|
+
export interface ChapterResult {
|
|
3
|
+
chapter: string;
|
|
4
|
+
verdict: Verdict;
|
|
5
|
+
override_blocks_launch: boolean;
|
|
6
|
+
findings: Array<{ severity: string; description: string; related_decision_id?: string }>;
|
|
7
|
+
follow_up_spawned?: boolean;
|
|
8
|
+
follow_up_confirmed?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface AggregateResult {
|
|
12
|
+
combined_verdict: 'PRODUCTION READY' | 'NEEDS WORK' | 'BLOCKED';
|
|
13
|
+
triggered_rule: number;
|
|
14
|
+
chapters: ChapterResult[];
|
|
15
|
+
star_rule_triggered?: boolean;
|
|
16
|
+
star_rule_decision_ids?: string[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function aggregate(chapters: ChapterResult[]): AggregateResult {
|
|
20
|
+
// Rule 1: ANY override_blocks_launch → BLOCKED
|
|
21
|
+
if (chapters.some(c => c.override_blocks_launch))
|
|
22
|
+
return { combined_verdict: 'BLOCKED', triggered_rule: 1, chapters };
|
|
23
|
+
|
|
24
|
+
// Rule 6: contradictions between chapters on typed fields → BLOCKED
|
|
25
|
+
// Two chapters contradict if they reference the same finding description
|
|
26
|
+
// but assign conflicting verdicts (one PASS, one BLOCK on the same topic).
|
|
27
|
+
const findingsByDesc = new Map<string, Set<Verdict>>();
|
|
28
|
+
for (const ch of chapters) {
|
|
29
|
+
for (const f of ch.findings) {
|
|
30
|
+
const key = f.description.toLowerCase().trim();
|
|
31
|
+
if (!findingsByDesc.has(key)) findingsByDesc.set(key, new Set());
|
|
32
|
+
findingsByDesc.get(key)!.add(ch.verdict);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
for (const [desc, verdicts] of findingsByDesc) {
|
|
36
|
+
if (verdicts.has('PASS') && verdicts.has('BLOCK')) {
|
|
37
|
+
return {
|
|
38
|
+
combined_verdict: 'BLOCKED', triggered_rule: 6, chapters,
|
|
39
|
+
cross_chapter_contradiction: desc,
|
|
40
|
+
} as AggregateResult;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Rule 5: follow_up spawned AND confirmed → treat as BLOCK
|
|
45
|
+
const effectiveChapters = chapters.map(c => ({
|
|
46
|
+
...c,
|
|
47
|
+
verdict: (c.follow_up_spawned && c.follow_up_confirmed ? 'BLOCK' : c.verdict) as Verdict,
|
|
48
|
+
}));
|
|
49
|
+
|
|
50
|
+
// Rule 2: ALL PASS and 0 follow-ups → PRODUCTION READY
|
|
51
|
+
if (effectiveChapters.every(c => c.verdict === 'PASS') && !chapters.some(c => c.follow_up_spawned))
|
|
52
|
+
return { combined_verdict: 'PRODUCTION READY', triggered_rule: 2, chapters };
|
|
53
|
+
|
|
54
|
+
// Rule 3: ANY BLOCK → NEEDS WORK
|
|
55
|
+
if (effectiveChapters.some(c => c.verdict === 'BLOCK'))
|
|
56
|
+
return { combined_verdict: 'NEEDS WORK', triggered_rule: 3, chapters };
|
|
57
|
+
|
|
58
|
+
// Rule 4: ANY CONCERNS → NEEDS WORK
|
|
59
|
+
if (effectiveChapters.some(c => c.verdict === 'CONCERNS'))
|
|
60
|
+
return { combined_verdict: 'NEEDS WORK', triggered_rule: 4, chapters };
|
|
61
|
+
|
|
62
|
+
return { combined_verdict: 'PRODUCTION READY', triggered_rule: 2, chapters };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** ⭐⭐ Star rule: on BLOCK, find related_decision_id and route back to authoring phase */
|
|
66
|
+
export function applyStarRule(result: AggregateResult): AggregateResult {
|
|
67
|
+
if (result.combined_verdict === 'NEEDS WORK' || result.combined_verdict === 'BLOCKED') {
|
|
68
|
+
const blockFindings = result.chapters
|
|
69
|
+
.filter(c => c.verdict === 'BLOCK')
|
|
70
|
+
.flatMap(c => c.findings.filter(f => f.related_decision_id));
|
|
71
|
+
if (blockFindings.length > 0) {
|
|
72
|
+
return {
|
|
73
|
+
...result,
|
|
74
|
+
star_rule_triggered: true,
|
|
75
|
+
star_rule_decision_ids: blockFindings.map(f => f.related_decision_id!),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return { ...result, star_rule_triggered: false };
|
|
80
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
3
|
+
|
|
4
|
+
export interface ContextHeaderInput {
|
|
5
|
+
projectType: 'web' | 'ios';
|
|
6
|
+
phase: number;
|
|
7
|
+
iosFeatures?: Record<string, boolean>;
|
|
8
|
+
visualDnaPath?: string; // path to visual-dna.md
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface RenderedHeader {
|
|
12
|
+
content: string;
|
|
13
|
+
hash: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Cache: rendered header keyed by phase + input hash for automatic invalidation */
|
|
17
|
+
let cachedHeader: RenderedHeader | null = null;
|
|
18
|
+
let cachedPhase: number | null = null;
|
|
19
|
+
let cachedInputHash: string | null = null;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Compute a hash of the variable inputs that affect the rendered header.
|
|
23
|
+
* Used to detect mid-phase mutations (e.g., ios_features changing within a phase).
|
|
24
|
+
*/
|
|
25
|
+
function inputHash(input: ContextHeaderInput): string {
|
|
26
|
+
const key = JSON.stringify({
|
|
27
|
+
projectType: input.projectType,
|
|
28
|
+
phase: input.phase,
|
|
29
|
+
iosFeatures: input.iosFeatures ?? null,
|
|
30
|
+
visualDnaPath: input.visualDnaPath ?? null,
|
|
31
|
+
});
|
|
32
|
+
return createHash('sha256').update(key).digest('hex').slice(0, 16);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Render the CONTEXT header for a phase.
|
|
37
|
+
* Called once at phase boundary; result reused for all dispatches in that phase.
|
|
38
|
+
* Automatically invalidates if inputs change within the same phase
|
|
39
|
+
* (e.g., ios_features mutating mid-build per spec pass criteria).
|
|
40
|
+
*/
|
|
41
|
+
export function renderContextHeader(input: ContextHeaderInput): RenderedHeader {
|
|
42
|
+
const currentInputHash = inputHash(input);
|
|
43
|
+
// Return cached if same phase AND same inputs
|
|
44
|
+
if (cachedPhase === input.phase && cachedInputHash === currentInputHash && cachedHeader) return cachedHeader;
|
|
45
|
+
|
|
46
|
+
const lines: string[] = ['CONTEXT:'];
|
|
47
|
+
lines.push(` project_type: ${input.projectType}`);
|
|
48
|
+
lines.push(` phase: ${input.phase}`);
|
|
49
|
+
|
|
50
|
+
// DNA: only for web, phase >= 4
|
|
51
|
+
if (input.projectType === 'web' && input.phase >= 4 && input.visualDnaPath) {
|
|
52
|
+
if (existsSync(input.visualDnaPath)) {
|
|
53
|
+
const dna = readFileSync(input.visualDnaPath, 'utf-8');
|
|
54
|
+
const summary = dna.split('\n').slice(0, 5).join('\n').trim();
|
|
55
|
+
lines.push(` dna: ${summary}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// iOS features: only for ios
|
|
60
|
+
if (input.projectType === 'ios' && input.iosFeatures) {
|
|
61
|
+
const enabled = Object.entries(input.iosFeatures)
|
|
62
|
+
.filter(([, v]) => v)
|
|
63
|
+
.map(([k]) => k);
|
|
64
|
+
if (enabled.length > 0) {
|
|
65
|
+
lines.push(` ios_features: [${enabled.join(', ')}]`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
lines.push('');
|
|
70
|
+
lines.push('TASK:');
|
|
71
|
+
|
|
72
|
+
const content = lines.join('\n');
|
|
73
|
+
const hash = createHash('sha256').update(content).digest('hex').slice(0, 16);
|
|
74
|
+
|
|
75
|
+
cachedHeader = { content, hash };
|
|
76
|
+
cachedPhase = input.phase;
|
|
77
|
+
cachedInputHash = currentInputHash;
|
|
78
|
+
return cachedHeader;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Invalidate the cache (call on phase boundary or state mutation).
|
|
83
|
+
*/
|
|
84
|
+
export function invalidateCache(): void {
|
|
85
|
+
cachedHeader = null;
|
|
86
|
+
cachedPhase = null;
|
|
87
|
+
cachedInputHash = null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Check if the cache is valid for a given phase.
|
|
92
|
+
*/
|
|
93
|
+
export function isCacheValid(phase: number): boolean {
|
|
94
|
+
return cachedPhase === phase && cachedHeader !== null;
|
|
95
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase-boundary + Task-completion token accounting emitter (task 3.4.2).
|
|
3
|
+
*
|
|
4
|
+
* Subscribes to SDK assistant+result message `usage` fields.
|
|
5
|
+
* At every phase boundary and Task tool call completion, calls
|
|
6
|
+
* recordUsage() to append a cost line to docs/plans/build-log.md.
|
|
7
|
+
*
|
|
8
|
+
* Spec: MIGRATION-PLAN-FINAL.md §4 Stage 3 G3
|
|
9
|
+
* Depends on: src/orchestrator/hooks/token-accounting.ts (task 3.4.1)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { recordUsage, type TokenUsage, type AccountingEntry } from './token-accounting';
|
|
13
|
+
|
|
14
|
+
const DEFAULT_BUILD_LOG = 'docs/plans/build-log.md';
|
|
15
|
+
|
|
16
|
+
export interface SdkUsageMessage {
|
|
17
|
+
input_tokens?: number;
|
|
18
|
+
output_tokens?: number;
|
|
19
|
+
cache_creation_input_tokens?: number;
|
|
20
|
+
cache_read_input_tokens?: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface PhaseContext {
|
|
24
|
+
phase: number;
|
|
25
|
+
step: string;
|
|
26
|
+
buildLogPath?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface TaskContext extends PhaseContext {
|
|
30
|
+
task: string;
|
|
31
|
+
subagent_type: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Extract TokenUsage from an SDK usage message.
|
|
36
|
+
* SDK field names differ slightly from our internal format.
|
|
37
|
+
*/
|
|
38
|
+
export function extractUsage(msg: SdkUsageMessage): TokenUsage {
|
|
39
|
+
return {
|
|
40
|
+
input_tokens: msg.input_tokens ?? 0,
|
|
41
|
+
output_tokens: msg.output_tokens ?? 0,
|
|
42
|
+
cache_read: msg.cache_read_input_tokens ?? 0,
|
|
43
|
+
cache_create: msg.cache_creation_input_tokens ?? 0,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Emit a cost line at a phase boundary.
|
|
49
|
+
* Called by the orchestrator after each phase completes.
|
|
50
|
+
*/
|
|
51
|
+
export function emitPhaseBoundary(
|
|
52
|
+
ctx: PhaseContext,
|
|
53
|
+
usage: SdkUsageMessage,
|
|
54
|
+
): AccountingEntry {
|
|
55
|
+
return recordUsage(ctx.buildLogPath ?? DEFAULT_BUILD_LOG, {
|
|
56
|
+
phase: ctx.phase,
|
|
57
|
+
step: ctx.step,
|
|
58
|
+
usage: extractUsage(usage),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Emit a cost line at task completion.
|
|
64
|
+
* Called after each Task tool call returns from a subagent dispatch.
|
|
65
|
+
*/
|
|
66
|
+
export function emitTaskCompletion(
|
|
67
|
+
ctx: TaskContext,
|
|
68
|
+
usage: SdkUsageMessage,
|
|
69
|
+
): AccountingEntry {
|
|
70
|
+
return recordUsage(ctx.buildLogPath ?? DEFAULT_BUILD_LOG, {
|
|
71
|
+
phase: ctx.phase,
|
|
72
|
+
step: ctx.step,
|
|
73
|
+
task: ctx.task,
|
|
74
|
+
subagent_type: ctx.subagent_type,
|
|
75
|
+
usage: extractUsage(usage),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { writeFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
|
|
4
|
+
export interface TokenUsage {
|
|
5
|
+
input_tokens: number;
|
|
6
|
+
output_tokens: number;
|
|
7
|
+
cache_read?: number;
|
|
8
|
+
cache_create?: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface AccountingEntry {
|
|
12
|
+
timestamp: string;
|
|
13
|
+
phase: number;
|
|
14
|
+
step: string;
|
|
15
|
+
task?: string;
|
|
16
|
+
subagent_type?: string;
|
|
17
|
+
usage: TokenUsage;
|
|
18
|
+
cost_usd: number;
|
|
19
|
+
cumulative_usd: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Running cumulative cost across the build */
|
|
23
|
+
let cumulativeCost = 0;
|
|
24
|
+
|
|
25
|
+
/** Pricing per million tokens (sonnet defaults) */
|
|
26
|
+
const PRICING = {
|
|
27
|
+
input: 3.0,
|
|
28
|
+
output: 15.0,
|
|
29
|
+
cache_read: 0.30,
|
|
30
|
+
cache_create: 3.75,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Calculate cost from token usage.
|
|
35
|
+
*/
|
|
36
|
+
export function calculateCost(usage: TokenUsage): number {
|
|
37
|
+
const inputCost = (usage.input_tokens / 1_000_000) * PRICING.input;
|
|
38
|
+
const outputCost = (usage.output_tokens / 1_000_000) * PRICING.output;
|
|
39
|
+
const cacheReadCost = ((usage.cache_read ?? 0) / 1_000_000) * PRICING.cache_read;
|
|
40
|
+
const cacheCreateCost = ((usage.cache_create ?? 0) / 1_000_000) * PRICING.cache_create;
|
|
41
|
+
return Math.round((inputCost + outputCost + cacheReadCost + cacheCreateCost) * 10000) / 10000;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Record a token usage entry and append to build-log.md.
|
|
46
|
+
*/
|
|
47
|
+
export function recordUsage(
|
|
48
|
+
buildLogPath: string,
|
|
49
|
+
entry: Omit<AccountingEntry, 'cost_usd' | 'cumulative_usd' | 'timestamp'>,
|
|
50
|
+
): AccountingEntry {
|
|
51
|
+
const cost = calculateCost(entry.usage);
|
|
52
|
+
cumulativeCost += cost;
|
|
53
|
+
|
|
54
|
+
const record: AccountingEntry = {
|
|
55
|
+
timestamp: new Date().toISOString(),
|
|
56
|
+
...entry,
|
|
57
|
+
cost_usd: cost,
|
|
58
|
+
cumulative_usd: Math.round(cumulativeCost * 10000) / 10000,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const line = formatLogLine(record);
|
|
62
|
+
const dir = dirname(buildLogPath);
|
|
63
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
64
|
+
writeFileSync(buildLogPath, line + '\n', { flag: 'a' });
|
|
65
|
+
|
|
66
|
+
return record;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Format an accounting entry as a build-log line.
|
|
71
|
+
*/
|
|
72
|
+
export function formatLogLine(entry: AccountingEntry): string {
|
|
73
|
+
const meta = [`phase=${entry.phase}`, `step=${entry.step}`];
|
|
74
|
+
if (entry.task) meta.push(`task=${entry.task}`);
|
|
75
|
+
if (entry.subagent_type) meta.push(`subagent_type=${entry.subagent_type}`);
|
|
76
|
+
|
|
77
|
+
const tokens = [
|
|
78
|
+
`input_tokens=${entry.usage.input_tokens}`,
|
|
79
|
+
`output_tokens=${entry.usage.output_tokens}`,
|
|
80
|
+
];
|
|
81
|
+
if (entry.usage.cache_read) tokens.push(`cache_read=${entry.usage.cache_read}`);
|
|
82
|
+
if (entry.usage.cache_create) tokens.push(`cache_create=${entry.usage.cache_create}`);
|
|
83
|
+
tokens.push(`cost_usd=${entry.cost_usd}`);
|
|
84
|
+
tokens.push(`cumulative_usd=${entry.cumulative_usd}`);
|
|
85
|
+
|
|
86
|
+
return `[${entry.timestamp}] ${meta.join(' ')}\n${tokens.join(' ')}`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Get current cumulative cost.
|
|
91
|
+
*/
|
|
92
|
+
export function getCumulativeCost(): number {
|
|
93
|
+
return cumulativeCost;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Reset cumulative cost (for testing).
|
|
98
|
+
*/
|
|
99
|
+
export function reset(): void {
|
|
100
|
+
cumulativeCost = 0;
|
|
101
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cycle_counter_check MCP handler (Stage 4, A6 semantic).
|
|
3
|
+
*
|
|
4
|
+
* Authoritative semantic: escalation fires when NEW counter value > max_cycles.
|
|
5
|
+
* max_cycles = 2 → first two attempts allow, third escalates.
|
|
6
|
+
*
|
|
7
|
+
* Dual counter: per-decision AND per-target-phase. Escalation when EITHER exceeds cap.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { InFlightBackwardEdge, BackwardRoutingCounters } from '../schemas/backward-edge';
|
|
11
|
+
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Types
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
export interface CycleCheckInput {
|
|
17
|
+
decision_id: string;
|
|
18
|
+
target_phase: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface CycleCheckResult {
|
|
22
|
+
action: 'allow' | 'escalate_to_user';
|
|
23
|
+
decision_count: number;
|
|
24
|
+
phase_count: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface CounterState extends BackwardRoutingCounters {}
|
|
28
|
+
|
|
29
|
+
const DEFAULT_MAX_CYCLES = 2;
|
|
30
|
+
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Core handler (tasks 4.2.1, 4.2.2, 4.2.3)
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Check and increment the cycle counter for a backward-routing edge.
|
|
37
|
+
* Returns allow for the first max_cycles attempts, escalate_to_user after.
|
|
38
|
+
*
|
|
39
|
+
* Mutates the state object in place — caller must persist via a single
|
|
40
|
+
* atomic state_save combining counter increment + in_flight_backward_edge
|
|
41
|
+
* write (A3 crash-seam protocol).
|
|
42
|
+
*/
|
|
43
|
+
export function cycleCounterCheck(
|
|
44
|
+
state: CounterState,
|
|
45
|
+
input: CycleCheckInput,
|
|
46
|
+
maxCycles: number = DEFAULT_MAX_CYCLES,
|
|
47
|
+
): CycleCheckResult {
|
|
48
|
+
if (!input.decision_id) throw new Error('decision_id is required');
|
|
49
|
+
if (!input.target_phase) throw new Error('target_phase is required');
|
|
50
|
+
|
|
51
|
+
// Initialize counters if missing
|
|
52
|
+
state.backward_routing_count ??= {};
|
|
53
|
+
state.backward_routing_count_by_target_phase ??= {};
|
|
54
|
+
|
|
55
|
+
// Atomically increment both counters
|
|
56
|
+
const decisionCount = (state.backward_routing_count[input.decision_id] ?? 0) + 1;
|
|
57
|
+
const phaseCount = (state.backward_routing_count_by_target_phase[input.target_phase] ?? 0) + 1;
|
|
58
|
+
|
|
59
|
+
state.backward_routing_count[input.decision_id] = decisionCount;
|
|
60
|
+
state.backward_routing_count_by_target_phase[input.target_phase] = phaseCount;
|
|
61
|
+
|
|
62
|
+
// Write in_flight_backward_edge (A3 crash-seam) — single atomic state_save
|
|
63
|
+
state.in_flight_backward_edge = {
|
|
64
|
+
decision_id: input.decision_id,
|
|
65
|
+
target_phase: input.target_phase,
|
|
66
|
+
counter_value: decisionCount,
|
|
67
|
+
started_at: new Date().toISOString(),
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// Escalation: EITHER counter exceeds cap → escalate
|
|
71
|
+
const action: CycleCheckResult['action'] =
|
|
72
|
+
(decisionCount > maxCycles || phaseCount > maxCycles)
|
|
73
|
+
? 'escalate_to_user'
|
|
74
|
+
: 'allow';
|
|
75
|
+
|
|
76
|
+
return { action, decision_count: decisionCount, phase_count: phaseCount };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Edge lifecycle helpers
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Clear the in-flight backward edge (called by target phase on re-entry).
|
|
85
|
+
* Caller must persist via state_save.
|
|
86
|
+
*/
|
|
87
|
+
export function clearInFlightEdge(state: CounterState): void {
|
|
88
|
+
delete state.in_flight_backward_edge;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Handle stale edge on --resume (A3 crash recovery).
|
|
93
|
+
* If edge is older than threshold, decrement both counters and clear the edge.
|
|
94
|
+
* Returns true if a stale edge was cleaned up.
|
|
95
|
+
*/
|
|
96
|
+
export function handleStaleEdge(state: CounterState, thresholdMs: number = 60_000): boolean {
|
|
97
|
+
const edge = state.in_flight_backward_edge;
|
|
98
|
+
if (!edge) return false;
|
|
99
|
+
|
|
100
|
+
const age = Date.now() - new Date(edge.started_at).getTime();
|
|
101
|
+
if (age <= thresholdMs) return false; // edge is fresh, standard resume
|
|
102
|
+
|
|
103
|
+
// Edge never completed — decrement per-decision counter
|
|
104
|
+
const decCurrent = state.backward_routing_count[edge.decision_id] ?? 0;
|
|
105
|
+
if (decCurrent > 0) {
|
|
106
|
+
state.backward_routing_count[edge.decision_id] = decCurrent - 1;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Decrement per-target-phase counter
|
|
110
|
+
const phaseCurrent = state.backward_routing_count_by_target_phase[edge.target_phase] ?? 0;
|
|
111
|
+
if (phaseCurrent > 0) {
|
|
112
|
+
state.backward_routing_count_by_target_phase[edge.target_phase] = phaseCurrent - 1;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
delete state.in_flight_backward_edge;
|
|
116
|
+
return true; // stale edge handled
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
// Test helpers
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
|
|
123
|
+
/** Create a fresh empty CounterState. For testing only. */
|
|
124
|
+
export function createEmptyState(): CounterState {
|
|
125
|
+
return {
|
|
126
|
+
backward_routing_count: {},
|
|
127
|
+
backward_routing_count_by_target_phase: {},
|
|
128
|
+
};
|
|
129
|
+
}
|