buildanything 1.8.0 → 2.1.1
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 +17 -3
- package/CHANGELOG.md +57 -0
- package/README.md +57 -61
- package/agents/a11y-architect.md +168 -0
- package/agents/briefing-officer.md +172 -0
- package/agents/business-model.md +82 -29
- package/agents/code-architect.md +80 -0
- package/agents/code-reviewer.md +256 -0
- package/agents/code-simplifier.md +72 -0
- package/agents/design-brand-guardian.md +312 -53
- package/agents/design-critic.md +144 -0
- package/agents/design-inclusive-visuals-specialist.md +8 -19
- package/agents/design-ui-designer.md +352 -56
- package/agents/design-ux-architect.md +418 -55
- package/agents/design-ux-researcher.md +359 -49
- package/agents/engineering-ai-engineer.md +28 -36
- package/agents/engineering-backend-architect.md +187 -36
- package/agents/engineering-data-engineer.md +227 -43
- package/agents/engineering-devops-automator.md +229 -74
- package/agents/engineering-frontend-developer.md +223 -34
- package/agents/engineering-mobile-app-builder.md +8 -1
- package/agents/engineering-rapid-prototyper.md +45 -11
- package/agents/engineering-security-engineer.md +265 -61
- package/agents/engineering-senior-developer.md +141 -19
- package/agents/engineering-sre.md +86 -0
- package/agents/engineering-technical-writer.md +287 -41
- package/agents/feature-intel.md +111 -0
- package/agents/ios-app-review-guardian.md +21 -2
- package/agents/ios-foundation-models-specialist.md +22 -2
- package/agents/ios-product-reality-auditor.md +292 -0
- package/agents/ios-storekit-specialist.md +11 -2
- package/agents/ios-swift-architect.md +29 -1
- package/agents/ios-swift-search.md +9 -1
- package/agents/ios-swift-ui-design.md +40 -5
- package/agents/marketing-app-store-optimizer.md +248 -64
- package/agents/planner.md +221 -0
- package/agents/pr-test-analyzer.md +64 -0
- package/agents/product-feedback-synthesizer.md +70 -2
- package/agents/product-owner.md +163 -0
- package/agents/product-reality-auditor.md +216 -0
- package/agents/product-spec-writer.md +176 -0
- package/agents/refactor-cleaner.md +110 -0
- package/agents/security-reviewer.md +129 -0
- package/agents/silent-failure-hunter.md +55 -0
- package/agents/swift-build-resolver.md +121 -0
- package/agents/swift-reviewer.md +113 -0
- package/agents/tech-feasibility.md +26 -4
- package/agents/testing-api-tester.md +238 -59
- package/agents/testing-evidence-collector.md +50 -1
- package/agents/testing-performance-benchmarker.md +23 -1
- package/agents/testing-reality-checker.md +7 -1
- package/agents/visual-research.md +118 -0
- package/bin/adapters/cycle-counter-tool.ts +155 -0
- package/bin/adapters/scribe-tool.ts +73 -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 +241 -0
- package/bin/graph-index.js +24 -0
- package/bin/graph-index.ts +340 -0
- package/bin/mcp-servers/graph-mcp.js +26 -0
- package/bin/mcp-servers/graph-mcp.ts +481 -0
- package/bin/mcp-servers/orchestrator-mcp.js +26 -0
- package/bin/mcp-servers/orchestrator-mcp.ts +361 -0
- package/bin/setup.js +312 -76
- package/commands/add-feature.md +2 -0
- package/commands/build.md +994 -265
- package/commands/fix.md +1 -1
- package/commands/idea-sweep.md +2 -2
- package/commands/self-check.md +121 -0
- package/commands/setup.md +61 -9
- package/commands/ux-review.md +5 -5
- package/commands/verify.md +9 -9
- package/docs/migration/agents.yaml +729 -0
- package/docs/migration/phase-graph.yaml +1504 -0
- package/docs/migration/sdk-host-compat.md +18 -0
- package/hooks/compile-writer-owner-cache.ts +171 -0
- package/hooks/design-md-lint +4 -0
- package/hooks/design-md-lint.ts +295 -0
- package/hooks/hooks.json +36 -0
- package/hooks/pre-tool-use +19 -0
- package/hooks/pre-tool-use.ts +807 -0
- package/hooks/record-mode-transitions.ts +235 -0
- package/hooks/session-start +71 -1
- package/hooks/subagent-start +17 -0
- package/hooks/subagent-start.ts +472 -0
- package/hooks/subagent-stop +17 -0
- package/hooks/subagent-stop.ts +153 -0
- package/package.json +26 -4
- package/protocols/agent-prompt-authoring.md +165 -0
- package/protocols/architecture-schema.md +178 -0
- package/protocols/cleanup.md +4 -0
- package/protocols/decision-log.md +135 -0
- package/protocols/design-md-authoring.md +520 -0
- package/protocols/design-md-spec.md +362 -0
- package/protocols/fake-data-detector.md +1 -1
- package/protocols/ios-context.md +10 -11
- package/protocols/ios-fake-data-detector.md +65 -0
- package/protocols/ios-phase-branches.md +299 -39
- package/protocols/launch-readiness.md +262 -0
- package/protocols/metric-loop.md +62 -2
- package/protocols/page-spec-schema.md +234 -0
- package/protocols/product-spec-schema.md +354 -0
- package/protocols/smoke-test.md +9 -1
- package/protocols/sprint-tasks-schema.md +53 -0
- package/protocols/state-schema.json +423 -0
- package/protocols/state-schema.md +202 -0
- package/protocols/verify.md +91 -3
- package/protocols/web-phase-branches.md +395 -75
- 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 +17 -8
- 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/graph/ids.ts +86 -0
- package/src/graph/index.ts +32 -0
- package/src/graph/parser/architecture.ts +603 -0
- package/src/graph/parser/component-manifest.ts +268 -0
- package/src/graph/parser/decisions-jsonl.ts +407 -0
- package/src/graph/parser/design-md-pass2.ts +253 -0
- package/src/graph/parser/design-md.ts +477 -0
- package/src/graph/parser/page-spec.ts +496 -0
- package/src/graph/parser/product-spec.ts +930 -0
- package/src/graph/parser/screenshot.ts +342 -0
- package/src/graph/parser/sprint-tasks.ts +317 -0
- package/src/graph/storage/index.ts +1154 -0
- package/src/graph/types.ts +432 -0
- package/src/graph/util/dhash.ts +84 -0
- package/src/lrr/aggregator.ts +175 -0
- package/src/orchestrator/hooks/context-header.ts +119 -0
- package/src/orchestrator/hooks/token-accounting-emitter.ts +77 -0
- package/src/orchestrator/hooks/token-accounting.ts +112 -0
- package/src/orchestrator/mcp/cycle-counter.ts +130 -0
- package/src/orchestrator/mcp/scribe.ts +294 -0
- package/src/orchestrator/mcp/state-save.ts +149 -0
- package/src/orchestrator/mcp/write-lease.ts +184 -0
- package/src/orchestrator/phase4-shared-context.ts +57 -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,119 @@
|
|
|
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 DESIGN.md (repo root) — DNA lives in `## Overview > ### Brand DNA` block
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface RenderedHeader {
|
|
12
|
+
content: string;
|
|
13
|
+
hash: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Cache: rendered header keyed by buildId + phase + input hash for automatic invalidation */
|
|
17
|
+
let cachedHeader: RenderedHeader | null = null;
|
|
18
|
+
let cachedBuildId: string | null = null;
|
|
19
|
+
let cachedPhase: number | null = null;
|
|
20
|
+
let cachedInputHash: string | null = null;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Compute a hash of the variable inputs that affect the rendered header.
|
|
24
|
+
* Used to detect mid-phase mutations (e.g., ios_features changing within a phase).
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Extract the 7 DNA axis values from DESIGN.md `## Overview > ### Brand DNA` block.
|
|
28
|
+
* The block is a bullet list of 7 axes; we capture the bullets (one per axis)
|
|
29
|
+
* and join them with newlines. Falls back to first 5 non-frontmatter lines if
|
|
30
|
+
* the block is missing (legacy/partial files).
|
|
31
|
+
*/
|
|
32
|
+
function extractBrandDnaBlock(content: string): string {
|
|
33
|
+
const dnaMatch = content.match(/###\s+Brand DNA\s*\n([\s\S]*?)(?=\n###\s|\n##\s|$)/);
|
|
34
|
+
if (dnaMatch) return dnaMatch[1].trim().split('\n').slice(0, 7).join('\n');
|
|
35
|
+
const stripped = content.replace(/^---\n[\s\S]*?\n---\n/, '');
|
|
36
|
+
return stripped.split('\n').slice(0, 5).join('\n').trim();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function inputHash(input: ContextHeaderInput): string {
|
|
40
|
+
const key = JSON.stringify({
|
|
41
|
+
projectType: input.projectType,
|
|
42
|
+
phase: input.phase,
|
|
43
|
+
iosFeatures: input.iosFeatures ?? null,
|
|
44
|
+
visualDnaPath: input.visualDnaPath ?? null,
|
|
45
|
+
});
|
|
46
|
+
return createHash('sha256').update(key).digest('hex').slice(0, 16);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Render the CONTEXT header for a phase.
|
|
51
|
+
* Called once at phase boundary; result reused for all dispatches in that phase.
|
|
52
|
+
* Automatically invalidates if inputs change within the same phase
|
|
53
|
+
* (e.g., ios_features mutating mid-build per spec pass criteria).
|
|
54
|
+
*/
|
|
55
|
+
export function renderContextHeader(input: ContextHeaderInput, buildId: string): RenderedHeader {
|
|
56
|
+
const currentInputHash = inputHash(input);
|
|
57
|
+
// Return cached if same build, same phase, AND same inputs
|
|
58
|
+
if (
|
|
59
|
+
cachedBuildId === buildId &&
|
|
60
|
+
cachedPhase === input.phase &&
|
|
61
|
+
cachedInputHash === currentInputHash &&
|
|
62
|
+
cachedHeader
|
|
63
|
+
) return cachedHeader;
|
|
64
|
+
|
|
65
|
+
const lines: string[] = ['CONTEXT:'];
|
|
66
|
+
lines.push(` project_type: ${input.projectType}`);
|
|
67
|
+
lines.push(` phase: ${input.phase}`);
|
|
68
|
+
|
|
69
|
+
// DNA: only for web, phase >= 4. Extract the 7 axis values from
|
|
70
|
+
// DESIGN.md `## Overview > ### Brand DNA` h3 block — NOT the full file.
|
|
71
|
+
// Falls back to first 5 lines if the block is absent (legacy/partial files).
|
|
72
|
+
if (input.projectType === 'web' && input.phase >= 4 && input.visualDnaPath) {
|
|
73
|
+
if (existsSync(input.visualDnaPath)) {
|
|
74
|
+
const content = readFileSync(input.visualDnaPath, 'utf-8');
|
|
75
|
+
const summary = extractBrandDnaBlock(content);
|
|
76
|
+
lines.push(` dna: ${summary}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// iOS features: only for ios
|
|
81
|
+
if (input.projectType === 'ios' && input.iosFeatures) {
|
|
82
|
+
const enabled = Object.entries(input.iosFeatures)
|
|
83
|
+
.filter(([, v]) => v)
|
|
84
|
+
.map(([k]) => k);
|
|
85
|
+
if (enabled.length > 0) {
|
|
86
|
+
lines.push(` ios_features: [${enabled.join(', ')}]`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
lines.push('');
|
|
91
|
+
lines.push('TASK:');
|
|
92
|
+
|
|
93
|
+
const content = lines.join('\n');
|
|
94
|
+
const hash = createHash('sha256').update(content).digest('hex').slice(0, 16);
|
|
95
|
+
|
|
96
|
+
cachedBuildId = buildId;
|
|
97
|
+
cachedHeader = { content, hash };
|
|
98
|
+
cachedPhase = input.phase;
|
|
99
|
+
cachedInputHash = currentInputHash;
|
|
100
|
+
return cachedHeader;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Invalidate the cache (call on phase boundary or state mutation).
|
|
105
|
+
*/
|
|
106
|
+
export function invalidateCache(): void {
|
|
107
|
+
cachedHeader = null;
|
|
108
|
+
cachedBuildId = null;
|
|
109
|
+
cachedPhase = null;
|
|
110
|
+
cachedInputHash = null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Check if the cache is valid for a given build + phase.
|
|
115
|
+
*/
|
|
116
|
+
export function isCacheValid(phase: number, buildId?: string): boolean {
|
|
117
|
+
if (buildId !== undefined && cachedBuildId !== buildId) return false;
|
|
118
|
+
return cachedPhase === phase && cachedHeader !== null;
|
|
119
|
+
}
|
|
@@ -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,112 @@
|
|
|
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
|
+
model?: string;
|
|
18
|
+
usage: TokenUsage;
|
|
19
|
+
cost_usd: number;
|
|
20
|
+
cumulative_usd: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Running cumulative cost across the build */
|
|
24
|
+
let cumulativeCost = 0;
|
|
25
|
+
|
|
26
|
+
/** Per-model pricing per million tokens */
|
|
27
|
+
export const PRICING_TABLE: Record<string, { input: number; output: number; cache_read: number; cache_create: number }> = {
|
|
28
|
+
'claude-sonnet-4-5': { input: 3.0, output: 15.0, cache_read: 0.30, cache_create: 3.75 },
|
|
29
|
+
'claude-haiku-3-5': { input: 0.80, output: 4.0, cache_read: 0.08, cache_create: 1.00 },
|
|
30
|
+
'claude-opus-4-5': { input: 15.0, output: 75.0, cache_read: 1.50, cache_create: 18.75 },
|
|
31
|
+
};
|
|
32
|
+
const DEFAULT_PRICING = PRICING_TABLE['claude-sonnet-4-5'];
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Calculate cost from token usage.
|
|
36
|
+
* When `model` is omitted or unrecognised, Sonnet pricing is used.
|
|
37
|
+
*/
|
|
38
|
+
export function calculateCost(usage: TokenUsage, model?: string): number {
|
|
39
|
+
const pricing = (model ? PRICING_TABLE[model] : undefined) ?? DEFAULT_PRICING;
|
|
40
|
+
const inputCost = (usage.input_tokens / 1_000_000) * pricing.input;
|
|
41
|
+
const outputCost = (usage.output_tokens / 1_000_000) * pricing.output;
|
|
42
|
+
const cacheReadCost = ((usage.cache_read ?? 0) / 1_000_000) * pricing.cache_read;
|
|
43
|
+
const cacheCreateCost = ((usage.cache_create ?? 0) / 1_000_000) * pricing.cache_create;
|
|
44
|
+
return Math.round((inputCost + outputCost + cacheReadCost + cacheCreateCost) * 10000) / 10000;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Record a token usage entry and append to build-log.md.
|
|
49
|
+
*
|
|
50
|
+
* @param startingCost — optional seed value so callers can restore
|
|
51
|
+
* cumulative cost from a persisted build-log at build start.
|
|
52
|
+
* Defaults to the current in-memory cumulative cost.
|
|
53
|
+
*/
|
|
54
|
+
export function recordUsage(
|
|
55
|
+
buildLogPath: string,
|
|
56
|
+
entry: Omit<AccountingEntry, 'cost_usd' | 'cumulative_usd' | 'timestamp'>,
|
|
57
|
+
startingCost = cumulativeCost,
|
|
58
|
+
): AccountingEntry {
|
|
59
|
+
const cost = calculateCost(entry.usage, entry.model);
|
|
60
|
+
cumulativeCost = startingCost + cost;
|
|
61
|
+
|
|
62
|
+
const record: AccountingEntry = {
|
|
63
|
+
timestamp: new Date().toISOString(),
|
|
64
|
+
...entry,
|
|
65
|
+
cost_usd: cost,
|
|
66
|
+
cumulative_usd: Math.round(cumulativeCost * 10000) / 10000,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const line = formatLogLine(record);
|
|
70
|
+
const dir = dirname(buildLogPath);
|
|
71
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
72
|
+
writeFileSync(buildLogPath, line + '\n', { flag: 'a' });
|
|
73
|
+
|
|
74
|
+
return record;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Format an accounting entry as a build-log line.
|
|
79
|
+
*/
|
|
80
|
+
export function formatLogLine(entry: AccountingEntry): string {
|
|
81
|
+
const meta = [`phase=${entry.phase}`, `step=${entry.step}`];
|
|
82
|
+
if (entry.task) meta.push(`task=${entry.task}`);
|
|
83
|
+
if (entry.subagent_type) meta.push(`subagent_type=${entry.subagent_type}`);
|
|
84
|
+
if (entry.model) meta.push(`model=${entry.model}`);
|
|
85
|
+
|
|
86
|
+
const tokens = [
|
|
87
|
+
`input_tokens=${entry.usage.input_tokens}`,
|
|
88
|
+
`output_tokens=${entry.usage.output_tokens}`,
|
|
89
|
+
];
|
|
90
|
+
if (entry.usage.cache_read) tokens.push(`cache_read=${entry.usage.cache_read}`);
|
|
91
|
+
if (entry.usage.cache_create) tokens.push(`cache_create=${entry.usage.cache_create}`);
|
|
92
|
+
tokens.push(`cost_usd=${entry.cost_usd}`);
|
|
93
|
+
tokens.push(`cumulative_usd=${entry.cumulative_usd}`);
|
|
94
|
+
|
|
95
|
+
return `[${entry.timestamp}] ${meta.join(' ')}\n${tokens.join(' ')}`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Get current cumulative cost.
|
|
100
|
+
*/
|
|
101
|
+
export function getCumulativeCost(): number {
|
|
102
|
+
return cumulativeCost;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Reset cumulative cost to zero.
|
|
107
|
+
* Call at build initialisation to prevent cross-build drift
|
|
108
|
+
* when the process is long-lived.
|
|
109
|
+
*/
|
|
110
|
+
export function reset(): void {
|
|
111
|
+
cumulativeCost = 0;
|
|
112
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
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
|
+
import { STALE_EDGE_THRESHOLD_MS } from '../schemas/backward-edge';
|
|
12
|
+
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Types
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
export interface CycleCheckInput {
|
|
18
|
+
decision_id: string;
|
|
19
|
+
target_phase: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface CycleCheckResult {
|
|
23
|
+
action: 'allow' | 'escalate_to_user';
|
|
24
|
+
decision_count: number;
|
|
25
|
+
phase_count: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface CounterState extends BackwardRoutingCounters {}
|
|
29
|
+
|
|
30
|
+
const DEFAULT_MAX_CYCLES = 2;
|
|
31
|
+
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Core handler (tasks 4.2.1, 4.2.2, 4.2.3)
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Check and increment the cycle counter for a backward-routing edge.
|
|
38
|
+
* Returns allow for the first max_cycles attempts, escalate_to_user after.
|
|
39
|
+
*
|
|
40
|
+
* Mutates the state object in place — caller must persist via a single
|
|
41
|
+
* atomic state_save combining counter increment + in_flight_backward_edge
|
|
42
|
+
* write (A3 crash-seam protocol).
|
|
43
|
+
*/
|
|
44
|
+
export function cycleCounterCheck(
|
|
45
|
+
state: CounterState,
|
|
46
|
+
input: CycleCheckInput,
|
|
47
|
+
maxCycles: number = DEFAULT_MAX_CYCLES,
|
|
48
|
+
): CycleCheckResult {
|
|
49
|
+
if (!input.decision_id) throw new Error('decision_id is required');
|
|
50
|
+
if (!input.target_phase) throw new Error('target_phase is required');
|
|
51
|
+
|
|
52
|
+
// Initialize counters if missing
|
|
53
|
+
state.backward_routing_count ??= {};
|
|
54
|
+
state.backward_routing_count_by_target_phase ??= {};
|
|
55
|
+
|
|
56
|
+
// Atomically increment both counters
|
|
57
|
+
const decisionCount = (state.backward_routing_count[input.decision_id] ?? 0) + 1;
|
|
58
|
+
const phaseCount = (state.backward_routing_count_by_target_phase[input.target_phase] ?? 0) + 1;
|
|
59
|
+
|
|
60
|
+
state.backward_routing_count[input.decision_id] = decisionCount;
|
|
61
|
+
state.backward_routing_count_by_target_phase[input.target_phase] = phaseCount;
|
|
62
|
+
|
|
63
|
+
// Write in_flight_backward_edge (A3 crash-seam) — single atomic state_save
|
|
64
|
+
state.in_flight_backward_edge = {
|
|
65
|
+
decision_id: input.decision_id,
|
|
66
|
+
target_phase: input.target_phase,
|
|
67
|
+
counter_value: decisionCount,
|
|
68
|
+
started_at: new Date().toISOString(),
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Escalation: EITHER counter exceeds cap → escalate
|
|
72
|
+
const action: CycleCheckResult['action'] =
|
|
73
|
+
(decisionCount > maxCycles || phaseCount > maxCycles)
|
|
74
|
+
? 'escalate_to_user'
|
|
75
|
+
: 'allow';
|
|
76
|
+
|
|
77
|
+
return { action, decision_count: decisionCount, phase_count: phaseCount };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Edge lifecycle helpers
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Clear the in-flight backward edge (called by target phase on re-entry).
|
|
86
|
+
* Caller must persist via state_save.
|
|
87
|
+
*/
|
|
88
|
+
export function clearInFlightEdge(state: CounterState): void {
|
|
89
|
+
delete state.in_flight_backward_edge;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Handle stale edge on --resume (A3 crash recovery).
|
|
94
|
+
* If edge is older than threshold, decrement both counters and clear the edge.
|
|
95
|
+
* Returns true if a stale edge was cleaned up.
|
|
96
|
+
*/
|
|
97
|
+
export function handleStaleEdge(state: CounterState, thresholdMs: number = STALE_EDGE_THRESHOLD_MS): boolean {
|
|
98
|
+
const edge = state.in_flight_backward_edge;
|
|
99
|
+
if (!edge) return false;
|
|
100
|
+
|
|
101
|
+
const age = Date.now() - new Date(edge.started_at).getTime();
|
|
102
|
+
if (age <= thresholdMs) return false; // edge is fresh, standard resume
|
|
103
|
+
|
|
104
|
+
// Edge never completed — decrement per-decision counter
|
|
105
|
+
const decCurrent = state.backward_routing_count[edge.decision_id] ?? 0;
|
|
106
|
+
if (decCurrent > 0) {
|
|
107
|
+
state.backward_routing_count[edge.decision_id] = decCurrent - 1;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Decrement per-target-phase counter
|
|
111
|
+
const phaseCurrent = state.backward_routing_count_by_target_phase[edge.target_phase] ?? 0;
|
|
112
|
+
if (phaseCurrent > 0) {
|
|
113
|
+
state.backward_routing_count_by_target_phase[edge.target_phase] = phaseCurrent - 1;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
delete state.in_flight_backward_edge;
|
|
117
|
+
return true; // stale edge handled
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// Test helpers
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
|
|
124
|
+
/** Create a fresh empty CounterState. For testing only. */
|
|
125
|
+
export function createEmptyState(): CounterState {
|
|
126
|
+
return {
|
|
127
|
+
backward_routing_count: {},
|
|
128
|
+
backward_routing_count_by_target_phase: {},
|
|
129
|
+
};
|
|
130
|
+
}
|