oh-my-opencode 4.12.1 → 4.13.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/README.md +1 -1
- package/THIRD-PARTY-NOTICES.md +1 -1
- package/dist/agents/sisyphus-agent-factory.d.ts +9 -0
- package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +31 -0
- package/dist/cli/index.js +896 -669
- package/dist/cli-node/index.js +896 -669
- package/dist/config/schema/codegraph.d.ts +1 -0
- package/dist/config/schema/oh-my-opencode-config.d.ts +2 -0
- package/dist/config/schema/runtime-fallback.d.ts +1 -0
- package/dist/features/background-agent/background-task-marker.d.ts +8 -0
- package/dist/features/background-agent/fallback-retry-handler.d.ts +1 -0
- package/dist/features/background-agent/manager.d.ts +1 -0
- package/dist/features/background-agent/parent-wake-dedupe.d.ts +1 -0
- package/dist/features/background-agent/parent-wake-notifier-types.d.ts +2 -0
- package/dist/features/background-agent/parent-wake-notifier.d.ts +1 -0
- package/dist/features/background-agent/parent-wake-window-recovery.d.ts +2 -0
- package/dist/hooks/runtime-fallback/auto-retry-dispatch.d.ts +2 -2
- package/dist/hooks/runtime-fallback/auto-retry-timeout.d.ts +2 -2
- package/dist/hooks/runtime-fallback/auto-retry.d.ts +1 -1
- package/dist/hooks/runtime-fallback/fallback-state-snapshot.d.ts +13 -0
- package/dist/hooks/runtime-fallback/types.d.ts +8 -0
- package/dist/index.js +708 -413
- package/dist/oh-my-opencode.schema.json +8 -0
- package/dist/plugin/runtime-skill-resolver.d.ts +35 -0
- package/dist/plugin/skill-context.d.ts +9 -0
- package/dist/skills/frontend/ATTRIBUTION.md +32 -8
- package/dist/skills/frontend/references/design/airbnb.md +3 -0
- package/dist/skills/frontend/references/design/airtable.md +3 -0
- package/dist/skills/frontend/references/design/apple.md +3 -0
- package/dist/skills/frontend/references/design/binance.md +3 -0
- package/dist/skills/frontend/references/design/bmw.md +3 -0
- package/dist/skills/frontend/references/design/bugatti.md +3 -0
- package/dist/skills/frontend/references/design/cal.md +3 -0
- package/dist/skills/frontend/references/design/claude.md +3 -0
- package/dist/skills/frontend/references/design/clay.md +3 -0
- package/dist/skills/frontend/references/design/clickhouse.md +3 -0
- package/dist/skills/frontend/references/design/cohere.md +3 -0
- package/dist/skills/frontend/references/design/coinbase.md +3 -0
- package/dist/skills/frontend/references/design/composio.md +3 -0
- package/dist/skills/frontend/references/design/cursor.md +3 -0
- package/dist/skills/frontend/references/design/elevenlabs.md +3 -0
- package/dist/skills/frontend/references/design/expo.md +3 -0
- package/dist/skills/frontend/references/design/ferrari.md +3 -0
- package/dist/skills/frontend/references/design/figma.md +3 -0
- package/dist/skills/frontend/references/design/framer.md +3 -0
- package/dist/skills/frontend/references/design/hashicorp.md +3 -0
- package/dist/skills/frontend/references/design/ibm.md +3 -0
- package/dist/skills/frontend/references/design/imagegen-frontend-web.md +380 -79
- package/dist/skills/frontend/references/design/intercom.md +3 -0
- package/dist/skills/frontend/references/design/kraken.md +3 -0
- package/dist/skills/frontend/references/design/lamborghini.md +3 -0
- package/dist/skills/frontend/references/design/linear.app.md +3 -0
- package/dist/skills/frontend/references/design/lovable.md +3 -0
- package/dist/skills/frontend/references/design/mastercard.md +3 -0
- package/dist/skills/frontend/references/design/meta.md +3 -0
- package/dist/skills/frontend/references/design/minimax.md +3 -0
- package/dist/skills/frontend/references/design/mintlify.md +3 -0
- package/dist/skills/frontend/references/design/miro.md +3 -0
- package/dist/skills/frontend/references/design/mistral.ai.md +3 -0
- package/dist/skills/frontend/references/design/mongodb.md +3 -0
- package/dist/skills/frontend/references/design/nike.md +3 -0
- package/dist/skills/frontend/references/design/notion.md +3 -0
- package/dist/skills/frontend/references/design/nvidia.md +3 -0
- package/dist/skills/frontend/references/design/ollama.md +3 -0
- package/dist/skills/frontend/references/design/opencode.ai.md +3 -0
- package/dist/skills/frontend/references/design/pinterest.md +3 -0
- package/dist/skills/frontend/references/design/playstation.md +3 -0
- package/dist/skills/frontend/references/design/posthog.md +3 -0
- package/dist/skills/frontend/references/design/raycast.md +3 -0
- package/dist/skills/frontend/references/design/renault.md +3 -0
- package/dist/skills/frontend/references/design/replicate.md +3 -0
- package/dist/skills/frontend/references/design/resend.md +3 -0
- package/dist/skills/frontend/references/design/revolut.md +3 -0
- package/dist/skills/frontend/references/design/runwayml.md +3 -0
- package/dist/skills/frontend/references/design/sanity.md +3 -0
- package/dist/skills/frontend/references/design/sentry.md +3 -0
- package/dist/skills/frontend/references/design/shopify.md +3 -0
- package/dist/skills/frontend/references/design/spacex.md +3 -0
- package/dist/skills/frontend/references/design/spotify.md +3 -0
- package/dist/skills/frontend/references/design/starbucks.md +3 -0
- package/dist/skills/frontend/references/design/stitch-skill.md +1 -1
- package/dist/skills/frontend/references/design/stripe.md +3 -0
- package/dist/skills/frontend/references/design/supabase.md +3 -0
- package/dist/skills/frontend/references/design/superhuman.md +3 -0
- package/dist/skills/frontend/references/design/taste-skill.md +1188 -208
- package/dist/skills/frontend/references/design/tesla.md +3 -0
- package/dist/skills/frontend/references/design/theverge.md +3 -0
- package/dist/skills/frontend/references/design/together.ai.md +3 -0
- package/dist/skills/frontend/references/design/uber.md +3 -0
- package/dist/skills/frontend/references/design/vercel.md +3 -0
- package/dist/skills/frontend/references/design/vodafone.md +3 -0
- package/dist/skills/frontend/references/design/voltagent.md +3 -0
- package/dist/skills/frontend/references/design/warp.md +3 -0
- package/dist/skills/frontend/references/design/webflow.md +3 -0
- package/dist/skills/frontend/references/design/wired.md +3 -0
- package/dist/skills/frontend/references/design/wise.md +3 -0
- package/dist/skills/frontend/references/design/x.ai.md +3 -0
- package/dist/skills/frontend/references/design/zapier.md +3 -0
- package/dist/skills/frontend/references/ui-ux-db/README.md +501 -115
- package/dist/skills/frontend/references/ui-ux-db/data/charts.csv +26 -26
- package/dist/skills/frontend/references/ui-ux-db/data/colors.csv +162 -97
- package/dist/skills/frontend/references/ui-ux-db/data/icons.csv +105 -100
- package/dist/skills/frontend/references/ui-ux-db/data/landing.csv +22 -18
- package/dist/skills/frontend/references/ui-ux-db/data/products.csv +162 -97
- package/dist/skills/frontend/references/ui-ux-db/data/stacks/flutter.csv +53 -53
- package/dist/skills/frontend/references/ui-ux-db/data/stacks/html-tailwind.csv +56 -56
- package/dist/skills/frontend/references/ui-ux-db/data/stacks/nextjs.csv +53 -53
- package/dist/skills/frontend/references/ui-ux-db/data/stacks/react.csv +54 -54
- package/dist/skills/frontend/references/ui-ux-db/data/stacks/svelte.csv +54 -54
- package/dist/skills/frontend/references/ui-ux-db/data/stacks/swiftui.csv +51 -51
- package/dist/skills/frontend/references/ui-ux-db/data/stacks/vue.csv +50 -50
- package/dist/skills/frontend/references/ui-ux-db/data/styles.csv +17 -0
- package/dist/skills/frontend/references/ui-ux-db/data/typography.csv +17 -1
- package/dist/skills/frontend/references/ui-ux-db/data/ui-reasoning.csv +162 -101
- package/dist/skills/frontend/references/ui-ux-db/data/web-interface.csv +30 -30
- package/dist/skills/frontend/references/ui-ux-db/scripts/core.py +31 -22
- package/dist/skills/frontend/references/ui-ux-db/scripts/design_system.py +150 -69
- package/dist/skills/frontend/references/ui-ux-db/scripts/search.py +3 -3
- package/dist/skills/lcx-doctor/SKILL.md +1 -1
- package/dist/skills/ultimate-browsing/ATTRIBUTION.md +105 -0
- package/dist/skills/ultimate-browsing/SKILL.md +140 -0
- package/dist/skills/ultimate-browsing/engine/__init__.py +24 -0
- package/dist/skills/ultimate-browsing/engine/__main__.py +106 -0
- package/dist/skills/ultimate-browsing/engine/bias_check.py +174 -0
- package/dist/skills/ultimate-browsing/engine/curl_probe.py +91 -0
- package/dist/skills/ultimate-browsing/engine/executor.py +192 -0
- package/dist/skills/ultimate-browsing/engine/fetch_chain.py +268 -0
- package/dist/skills/ultimate-browsing/engine/referers.py +15 -0
- package/dist/skills/ultimate-browsing/engine/result_schema.py +45 -0
- package/dist/skills/ultimate-browsing/engine/summary.py +37 -0
- package/dist/skills/ultimate-browsing/engine/templates/package.json +11 -0
- package/dist/skills/ultimate-browsing/engine/templates/playwright_mobile_chrome.js +129 -0
- package/dist/skills/ultimate-browsing/engine/templates/playwright_real_chrome.js +167 -0
- package/dist/skills/ultimate-browsing/engine/tests/test_fetch_chain.py +77 -0
- package/dist/skills/ultimate-browsing/engine/tests/test_playwright_templates.py +282 -0
- package/dist/skills/ultimate-browsing/engine/url_transforms.py +98 -0
- package/dist/skills/ultimate-browsing/engine/validators.py +216 -0
- package/dist/skills/ultimate-browsing/engine/waf_detector.py +214 -0
- package/dist/skills/ultimate-browsing/engine/waf_profiles.yaml +162 -0
- package/dist/skills/ultimate-browsing/references/agent-reach/README.md +79 -0
- package/dist/skills/ultimate-browsing/references/agent-reach/career.md +29 -0
- package/dist/skills/ultimate-browsing/references/agent-reach/dev.md +62 -0
- package/dist/skills/ultimate-browsing/references/agent-reach/search.md +33 -0
- package/dist/skills/ultimate-browsing/references/agent-reach/social.md +207 -0
- package/dist/skills/ultimate-browsing/references/agent-reach/video.md +115 -0
- package/dist/skills/ultimate-browsing/references/agent-reach/web.md +76 -0
- package/dist/skills/ultimate-browsing/references/chrome-stealth.md +120 -0
- package/dist/skills/ultimate-browsing/references/insane-search/README.md +319 -0
- package/dist/skills/ultimate-browsing/references/insane-search/cache-archive.md +83 -0
- package/dist/skills/ultimate-browsing/references/insane-search/fallback.md +159 -0
- package/dist/skills/ultimate-browsing/references/insane-search/jina.md +130 -0
- package/dist/skills/ultimate-browsing/references/insane-search/json-api.md +133 -0
- package/dist/skills/ultimate-browsing/references/insane-search/media.md +123 -0
- package/dist/skills/ultimate-browsing/references/insane-search/metadata.md +116 -0
- package/dist/skills/ultimate-browsing/references/insane-search/naver.md +107 -0
- package/dist/skills/ultimate-browsing/references/insane-search/playwright.md +142 -0
- package/dist/skills/ultimate-browsing/references/insane-search/public-api.md +119 -0
- package/dist/skills/ultimate-browsing/references/insane-search/rss.md +123 -0
- package/dist/skills/ultimate-browsing/references/insane-search/tls-impersonate.md +186 -0
- package/dist/skills/ultimate-browsing/references/insane-search/twitter.md +104 -0
- package/dist/skills/ultimate-browsing/scripts/cookie_crypto.py +75 -0
- package/dist/skills/ultimate-browsing/scripts/cookie_domains.py +38 -0
- package/dist/skills/ultimate-browsing/scripts/cookie_paths.py +112 -0
- package/dist/skills/ultimate-browsing/scripts/extract_cookies.py +280 -0
- package/dist/skills/ultimate-browsing/scripts/tests/test_cookie_domain_filter.py +110 -0
- package/dist/skills/ultimate-browsing/scripts/tests/test_extract_cookies.py +245 -0
- package/dist/skills/ultraresearch/ATTRIBUTION.md +49 -0
- package/dist/skills/ultraresearch/SKILL.md +23 -4
- package/dist/skills/ulw-plan/SKILL.md +4 -1
- package/dist/tools/delegate-task/sync-task-deps.d.ts +8 -6
- package/dist/tools/skill-mcp/tools.d.ts +1 -1
- package/dist/tui.js +9 -1
- package/package.json +16 -14
- package/packages/omo-codex/THIRD-PARTY-NOTICES.md +27 -4
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/README.md +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +134 -42
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/codegraph/LICENSE +21 -0
- package/packages/omo-codex/plugin/components/codegraph/NODE-RUNTIME-LICENSES.md +2951 -0
- package/packages/omo-codex/plugin/components/codegraph/NOTICE +16 -0
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +323 -39
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +292 -19
- package/packages/omo-codex/plugin/components/codegraph/package.json +9 -3
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +75 -0
- package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +29 -13
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +20 -7
- package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +1 -243
- package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +91 -0
- package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +1 -1
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +68 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve-node-support.test.ts +11 -1
- package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +133 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +1 -113
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +8 -1
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-trust-boundary.test.ts +63 -0
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-availability.test.ts +106 -0
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +150 -0
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/dist/cli.js +3 -3
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/src/sparkshell-awareness.ts +3 -3
- package/packages/omo-codex/plugin/components/rules/test/sparkshell-awareness.test.ts +33 -9
- package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/SKILL.md +59 -32
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-guide.mjs +17 -16
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-state.mjs +70 -3
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-worktree.mjs +113 -0
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team.mjs +63 -4
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/explorer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +5 -4
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +24 -3
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +8 -7
- package/packages/omo-codex/plugin/components/ulw-loop/test/skill-contract.test.ts +1 -1
- package/packages/omo-codex/plugin/package-lock.json +112 -13
- package/packages/omo-codex/plugin/package.json +2 -2
- package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +133 -0
- package/packages/omo-codex/plugin/scripts/auto-update-release-notes.mjs +135 -0
- package/packages/omo-codex/plugin/scripts/auto-update.mjs +33 -133
- package/packages/omo-codex/plugin/scripts/materialize-shared-upstreams.mjs +41 -0
- package/packages/omo-codex/plugin/shared/src/config-loader.ts +20 -2
- package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +16 -0
- package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +32 -8
- package/packages/omo-codex/plugin/skills/frontend/references/design/airbnb.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/airtable.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/apple.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/binance.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/bmw.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/bugatti.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/cal.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/claude.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/clay.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/clickhouse.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/cohere.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/coinbase.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/composio.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/cursor.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/elevenlabs.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/expo.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/ferrari.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/figma.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/framer.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/hashicorp.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/ibm.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/imagegen-frontend-web.md +380 -79
- package/packages/omo-codex/plugin/skills/frontend/references/design/intercom.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/kraken.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/lamborghini.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/linear.app.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/lovable.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/mastercard.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/meta.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/minimax.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/mintlify.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/miro.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/mistral.ai.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/mongodb.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/nike.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/notion.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/nvidia.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/ollama.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/opencode.ai.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/pinterest.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/playstation.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/posthog.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/raycast.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/renault.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/replicate.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/resend.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/revolut.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/runwayml.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/sanity.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/sentry.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/shopify.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/spacex.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/spotify.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/starbucks.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/stitch-skill.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/design/stripe.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/supabase.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/superhuman.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/taste-skill.md +1188 -208
- package/packages/omo-codex/plugin/skills/frontend/references/design/tesla.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/theverge.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/together.ai.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/uber.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/vercel.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/vodafone.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/voltagent.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/warp.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/webflow.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/wired.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/wise.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/x.ai.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/zapier.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/README.md +501 -115
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/charts.csv +26 -26
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/colors.csv +162 -97
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/icons.csv +105 -100
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/landing.csv +22 -18
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/products.csv +162 -97
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/stacks/flutter.csv +53 -53
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/stacks/html-tailwind.csv +56 -56
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/stacks/nextjs.csv +53 -53
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/stacks/react.csv +54 -54
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/stacks/svelte.csv +54 -54
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/stacks/swiftui.csv +51 -51
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/stacks/vue.csv +50 -50
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/styles.csv +17 -0
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/typography.csv +17 -1
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/ui-reasoning.csv +162 -101
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/data/web-interface.csv +30 -30
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/scripts/core.py +31 -22
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/scripts/design_system.py +150 -69
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/scripts/search.py +3 -3
- package/packages/omo-codex/plugin/skills/lcx-doctor/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/teammode/SKILL.md +59 -32
- package/packages/omo-codex/plugin/skills/teammode/scripts/team-guide.mjs +17 -16
- package/packages/omo-codex/plugin/skills/teammode/scripts/team-state.mjs +70 -3
- package/packages/omo-codex/plugin/skills/teammode/scripts/team-worktree.mjs +113 -0
- package/packages/omo-codex/plugin/skills/teammode/scripts/team.mjs +63 -4
- package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +105 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +140 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/__init__.py +24 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/__main__.py +106 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/bias_check.py +174 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/curl_probe.py +91 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/executor.py +192 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/fetch_chain.py +268 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/referers.py +15 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/result_schema.py +45 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/summary.py +37 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +11 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/playwright_mobile_chrome.js +129 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/playwright_real_chrome.js +167 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_fetch_chain.py +77 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_playwright_templates.py +282 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/url_transforms.py +98 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/validators.py +216 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/waf_detector.py +214 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/waf_profiles.yaml +162 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/README.md +79 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/career.md +29 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/dev.md +62 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/search.md +33 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/social.md +207 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/video.md +115 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/web.md +76 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +120 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +319 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/cache-archive.md +83 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/fallback.md +159 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/jina.md +130 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/json-api.md +133 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/media.md +123 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/metadata.md +116 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/naver.md +107 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/playwright.md +142 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/public-api.md +119 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/rss.md +123 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/tls-impersonate.md +186 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/twitter.md +104 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/scripts/cookie_crypto.py +75 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/scripts/cookie_domains.py +38 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/scripts/cookie_paths.py +112 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/scripts/extract_cookies.py +280 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/scripts/tests/test_cookie_domain_filter.py +110 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/scripts/tests/test_extract_cookies.py +245 -0
- package/packages/omo-codex/plugin/skills/ultraresearch/ATTRIBUTION.md +49 -0
- package/packages/omo-codex/plugin/skills/ultraresearch/SKILL.md +23 -4
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +8 -7
- package/packages/omo-codex/plugin/test/aggregate-build.test.mjs +2 -1
- package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +95 -0
- package/packages/omo-codex/plugin/test/auto-update-restart-notice.test.mjs +12 -3
- package/packages/omo-codex/plugin/test/component-codegraph-mcp-smoke.test.mjs +76 -0
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +1 -0
- package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +87 -0
- package/packages/omo-codex/plugin/test/teammode-thread-title.test.mjs +169 -0
- package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +246 -0
- package/packages/omo-codex/plugin/test/ultraresearch-skill-contract.test.mjs +30 -0
- package/packages/omo-codex/scripts/install-cli-args.test.mjs +1 -1
- package/packages/omo-codex/scripts/install-config-git-bash.test.mjs +23 -0
- package/packages/omo-codex/scripts/install-delegated-command.test.mjs +76 -4
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +520 -216
- package/packages/omo-codex/scripts/install-local-entrypoint.test.mjs +40 -3
- package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +32 -8
- package/packages/shared-skills/skills/frontend/references/design/airbnb.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/airtable.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/apple.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/binance.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/bmw.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/bugatti.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/cal.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/claude.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/clay.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/clickhouse.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/cohere.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/coinbase.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/composio.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/cursor.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/elevenlabs.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/expo.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/ferrari.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/figma.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/framer.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/hashicorp.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/ibm.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/imagegen-frontend-web.md +380 -79
- package/packages/shared-skills/skills/frontend/references/design/intercom.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/kraken.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/lamborghini.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/linear.app.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/lovable.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/mastercard.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/meta.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/minimax.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/mintlify.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/miro.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/mistral.ai.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/mongodb.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/nike.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/notion.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/nvidia.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/ollama.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/opencode.ai.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/pinterest.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/playstation.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/posthog.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/raycast.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/renault.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/replicate.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/resend.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/revolut.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/runwayml.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/sanity.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/sentry.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/shopify.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/spacex.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/spotify.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/starbucks.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/stitch-skill.md +1 -1
- package/packages/shared-skills/skills/frontend/references/design/stripe.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/supabase.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/superhuman.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/taste-skill.md +1188 -208
- package/packages/shared-skills/skills/frontend/references/design/tesla.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/theverge.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/together.ai.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/uber.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/vercel.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/vodafone.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/voltagent.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/warp.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/webflow.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/wired.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/wise.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/x.ai.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/zapier.md +3 -0
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/README.md +501 -115
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/charts.csv +26 -26
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/colors.csv +162 -97
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/icons.csv +105 -100
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/landing.csv +22 -18
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/products.csv +162 -97
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/stacks/flutter.csv +53 -53
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/stacks/html-tailwind.csv +56 -56
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/stacks/nextjs.csv +53 -53
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/stacks/react.csv +54 -54
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/stacks/svelte.csv +54 -54
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/stacks/swiftui.csv +51 -51
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/stacks/vue.csv +50 -50
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/styles.csv +17 -0
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/typography.csv +17 -1
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/ui-reasoning.csv +162 -101
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/data/web-interface.csv +30 -30
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/scripts/core.py +31 -22
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/scripts/design_system.py +150 -69
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/scripts/search.py +3 -3
- package/packages/shared-skills/skills/lcx-doctor/SKILL.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +105 -0
- package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +140 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/__init__.py +24 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/__main__.py +106 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/bias_check.py +174 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/curl_probe.py +91 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/executor.py +192 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/fetch_chain.py +268 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/referers.py +15 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/result_schema.py +45 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/summary.py +37 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +11 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/templates/playwright_mobile_chrome.js +129 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/templates/playwright_real_chrome.js +167 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_fetch_chain.py +77 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_playwright_templates.py +282 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/url_transforms.py +98 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/validators.py +216 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/waf_detector.py +214 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/waf_profiles.yaml +162 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/README.md +79 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/career.md +29 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/dev.md +62 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/search.md +33 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/social.md +207 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/video.md +115 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/web.md +76 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +120 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +319 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/cache-archive.md +83 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/fallback.md +159 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/jina.md +130 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/json-api.md +133 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/media.md +123 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/metadata.md +116 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/naver.md +107 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/playwright.md +142 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/public-api.md +119 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/rss.md +123 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/tls-impersonate.md +186 -0
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/twitter.md +104 -0
- package/packages/shared-skills/skills/ultimate-browsing/scripts/cookie_crypto.py +75 -0
- package/packages/shared-skills/skills/ultimate-browsing/scripts/cookie_domains.py +38 -0
- package/packages/shared-skills/skills/ultimate-browsing/scripts/cookie_paths.py +112 -0
- package/packages/shared-skills/skills/ultimate-browsing/scripts/extract_cookies.py +280 -0
- package/packages/shared-skills/skills/ultimate-browsing/scripts/tests/test_cookie_domain_filter.py +110 -0
- package/packages/shared-skills/skills/ultimate-browsing/scripts/tests/test_extract_cookies.py +245 -0
- package/packages/shared-skills/skills/ultraresearch/ATTRIBUTION.md +49 -0
- package/packages/shared-skills/skills/ultraresearch/SKILL.md +23 -4
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +4 -1
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.d.ts +0 -2
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.d.ts +0 -32
|
@@ -9,8 +9,6 @@ import { fileURLToPath } from "node:url";
|
|
|
9
9
|
import { resolveAutoUpdatePlan, runAutoUpdateCheck } from "../scripts/auto-update.mjs";
|
|
10
10
|
|
|
11
11
|
const SCRIPT_PATH = fileURLToPath(new URL("../scripts/auto-update.mjs", import.meta.url));
|
|
12
|
-
const STARTED_NOTICE =
|
|
13
|
-
"[LazyCodex] Auto-update started in the background: v1.0.0 -> v1.0.1. Tell the user a new LazyCodex version is installing and that they should start a new Codex session after it completes to apply it.";
|
|
14
12
|
const COMPLETED_NOTICE =
|
|
15
13
|
"[LazyCodex] Auto-update completed: v1.0.0 -> v1.0.1. This session is already running the new version. Tell the user the auto-update was applied.";
|
|
16
14
|
|
|
@@ -26,6 +24,17 @@ function autoUpdateEnv(root, extra = {}) {
|
|
|
26
24
|
};
|
|
27
25
|
}
|
|
28
26
|
|
|
27
|
+
function assertStartedNotice(notices) {
|
|
28
|
+
assert.equal(notices.length, 1);
|
|
29
|
+
const [notice] = notices;
|
|
30
|
+
assert.equal(typeof notice, "string");
|
|
31
|
+
assert.match(notice, /v1\.0\.0 -> v1\.0\.1/);
|
|
32
|
+
assert.match(notice, /Auto-update started in the background/i);
|
|
33
|
+
assert.match(notice, /new Codex session after it completes/i);
|
|
34
|
+
assert.match(notice, /user's preferred tone/i);
|
|
35
|
+
assert.match(notice, /Release notes for v1\.0\.1 were not available/);
|
|
36
|
+
}
|
|
37
|
+
|
|
29
38
|
test("#given a newer version #when resolving auto update plan #then plan carries current and latest versions", () => {
|
|
30
39
|
const plan = resolveAutoUpdatePlan({
|
|
31
40
|
env: { LAZYCODEX_CURRENT_VERSION: "1.0.0", LAZYCODEX_LATEST_VERSION: "1.0.1" },
|
|
@@ -54,7 +63,7 @@ test("#given a newer version #when waited update succeeds #then returns update-s
|
|
|
54
63
|
|
|
55
64
|
assert.equal(result.started, true);
|
|
56
65
|
assert.equal(result.status, 0);
|
|
57
|
-
|
|
66
|
+
assertStartedNotice(result.notices);
|
|
58
67
|
const state = JSON.parse(await readFile(env.LAZYCODEX_AUTO_UPDATE_STATE_PATH, "utf8"));
|
|
59
68
|
assert.deepEqual(state.pendingNotice, {
|
|
60
69
|
fromVersion: "1.0.0",
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { chmodSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import test from "node:test";
|
|
7
|
+
|
|
8
|
+
import { root } from "./aggregate-plugin-fixture.mjs";
|
|
9
|
+
|
|
10
|
+
const MCP_SMOKE_TIMEOUT_MS = 45_000;
|
|
11
|
+
|
|
12
|
+
test("#given built CodeGraph MCP wrapper #when an MCP client initializes #then the resolved child responds over stdio", () => {
|
|
13
|
+
const tempRoot = mkdtempSync(join(tmpdir(), "omo-codex-codegraph-mcp-smoke-"));
|
|
14
|
+
try {
|
|
15
|
+
const fakeBinaryPath = join(tempRoot, "codegraph-fake.cjs");
|
|
16
|
+
writeFileSync(
|
|
17
|
+
fakeBinaryPath,
|
|
18
|
+
[
|
|
19
|
+
"#!/usr/bin/env node",
|
|
20
|
+
"const readline = require('node:readline');",
|
|
21
|
+
"const rl = readline.createInterface({ input: process.stdin });",
|
|
22
|
+
"rl.on('line', (line) => {",
|
|
23
|
+
" const request = JSON.parse(line);",
|
|
24
|
+
" if (request.method !== 'initialize') return;",
|
|
25
|
+
" process.stdout.write(JSON.stringify({",
|
|
26
|
+
" jsonrpc: '2.0',",
|
|
27
|
+
" id: request.id,",
|
|
28
|
+
" result: {",
|
|
29
|
+
" protocolVersion: request.params?.protocolVersion ?? '2024-11-05',",
|
|
30
|
+
" capabilities: { tools: { listChanged: false } },",
|
|
31
|
+
" serverInfo: { name: 'fake-codegraph', version: '0.0.0' }",
|
|
32
|
+
" }",
|
|
33
|
+
" }) + '\\n');",
|
|
34
|
+
"});",
|
|
35
|
+
"",
|
|
36
|
+
].join("\n"),
|
|
37
|
+
);
|
|
38
|
+
chmodSync(fakeBinaryPath, 0o755);
|
|
39
|
+
|
|
40
|
+
const result = spawnSync(process.execPath, [join(root, "components", "codegraph", "dist", "serve.js")], {
|
|
41
|
+
cwd: root,
|
|
42
|
+
encoding: "utf8",
|
|
43
|
+
env: {
|
|
44
|
+
...process.env,
|
|
45
|
+
HOME: tempRoot,
|
|
46
|
+
OMO_CODEGRAPH_BIN: fakeBinaryPath,
|
|
47
|
+
},
|
|
48
|
+
input: `${JSON.stringify({
|
|
49
|
+
jsonrpc: "2.0",
|
|
50
|
+
id: 1,
|
|
51
|
+
method: "initialize",
|
|
52
|
+
params: {
|
|
53
|
+
capabilities: {},
|
|
54
|
+
clientInfo: { name: "lazycodex-smoke", version: "0.0.0" },
|
|
55
|
+
protocolVersion: "2024-11-05",
|
|
56
|
+
},
|
|
57
|
+
})}\n`,
|
|
58
|
+
timeout: MCP_SMOKE_TIMEOUT_MS,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
assert.equal(result.status, 0, `stderr: ${result.stderr}`);
|
|
62
|
+
assert.equal(result.stderr, "");
|
|
63
|
+
const response = JSON.parse(result.stdout.trim());
|
|
64
|
+
assert.deepEqual(response, {
|
|
65
|
+
jsonrpc: "2.0",
|
|
66
|
+
id: 1,
|
|
67
|
+
result: {
|
|
68
|
+
capabilities: { tools: { listChanged: false } },
|
|
69
|
+
protocolVersion: "2024-11-05",
|
|
70
|
+
serverInfo: { name: "fake-codegraph", version: "0.0.0" },
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
} finally {
|
|
74
|
+
rmSync(tempRoot, { recursive: true, force: true });
|
|
75
|
+
}
|
|
76
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
|
|
6
|
+
import { root } from "./aggregate-plugin-fixture.mjs";
|
|
7
|
+
import { cleanupTeamRoot, createTeamRoot, runTeam, teamDir } from "./teammode-safety-fixture.mjs";
|
|
8
|
+
|
|
9
|
+
// The teammode guide.md is what every member actually reads. The real run of leader session
|
|
10
|
+
// 019eed1e- proved members default to silence: 10 members, ~6 min, 4 end-of-work reports, zero
|
|
11
|
+
// peer messages, zero mid-task reports, zero send_message_to_thread calls - because the prose said
|
|
12
|
+
// "over-communicate relentlessly" (aspirational, no trigger) and never named the tool or targets.
|
|
13
|
+
// These tests pin the fix: a concrete push-communication protocol is the default the manual renders.
|
|
14
|
+
|
|
15
|
+
function buildTwoMemberTeam(tempRoot, sessionId) {
|
|
16
|
+
runTeam(tempRoot, "init", "--name", "Comms", "--session-name", "frequent", "--session", sessionId);
|
|
17
|
+
runTeam(tempRoot, "add-member", "--team", sessionId, "--id", "A", "--name", "alpha", "--focus", "slice one", "--lens", "area", "--deliverable", "x");
|
|
18
|
+
runTeam(tempRoot, "add-member", "--team", sessionId, "--id", "B", "--name", "beta", "--focus", "slice two", "--lens", "area", "--deliverable", "y");
|
|
19
|
+
runTeam(tempRoot, "bind-thread", "--team", sessionId, "--id", "A", "--thread", "thread-A");
|
|
20
|
+
runTeam(tempRoot, "bind-thread", "--team", sessionId, "--id", "B", "--thread", "thread-B");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function readGuide(tempRoot, sessionId) {
|
|
24
|
+
return readFileSync(join(teamDir(tempRoot, sessionId), "guide.md"), "utf8");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
test("#given a bound team #when the member field manual renders #then it names the cross-thread tool and the team.json address book", () => {
|
|
28
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-comms-");
|
|
29
|
+
try {
|
|
30
|
+
buildTwoMemberTeam(tempRoot, "comms-tool");
|
|
31
|
+
const guide = readGuide(tempRoot, "comms-tool");
|
|
32
|
+
|
|
33
|
+
// then - members are told the concrete TOOL to reach leader+peers, not left to narrate
|
|
34
|
+
assert.match(guide, /codex_app\.send_message_to_thread/, "guide must name the cross-thread messaging tool");
|
|
35
|
+
// then - members are pointed at the concrete address book in team.json
|
|
36
|
+
assert.match(guide, /leader\.sessionId/, "guide must say the leader thread id is team.json leader.sessionId");
|
|
37
|
+
assert.match(guide, /members\[\]\.threadId/, "guide must say peer thread ids are team.json members[].threadId");
|
|
38
|
+
} finally {
|
|
39
|
+
cleanupTeamRoot(tempRoot);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("#given a bound team #when the member field manual renders #then it gives concrete per-moment cadence triggers, not aspirational 'constantly'", () => {
|
|
44
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-comms-");
|
|
45
|
+
try {
|
|
46
|
+
buildTwoMemberTeam(tempRoot, "comms-cadence");
|
|
47
|
+
const guide = readGuide(tempRoot, "comms-cadence");
|
|
48
|
+
|
|
49
|
+
// then - a concrete heartbeat cadence the model can bind to
|
|
50
|
+
assert.match(guide, /every few tool calls/, "guide must give a concrete heartbeat trigger");
|
|
51
|
+
assert.match(guide, /WORKING:/, "guide must keep the WORKING heartbeat marker");
|
|
52
|
+
assert.match(guide, /BLOCKED:/, "guide must keep the BLOCKED marker");
|
|
53
|
+
// then - an explicit peer-notify rule so cross-cutting findings are pushed, not siloed
|
|
54
|
+
assert.match(guide, /to a \*\*peer\*\*/, "guide must have an explicit peer-notify rule");
|
|
55
|
+
assert.match(guide, /touches their slice/, "guide must trigger peer messages on slice-touching findings");
|
|
56
|
+
// then - the end-only directive that previously won is gone (it licensed batch-at-the-end reporting)
|
|
57
|
+
assert.doesNotMatch(guide, /the moment your work is complete/, "the standalone end-only report directive must be removed");
|
|
58
|
+
} finally {
|
|
59
|
+
cleanupTeamRoot(tempRoot);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("#given a member bootstrap trigger #when it is generated #then it points at the push tool and a continuous cadence, not an end-of-work report", () => {
|
|
64
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-comms-");
|
|
65
|
+
try {
|
|
66
|
+
buildTwoMemberTeam(tempRoot, "comms-bootstrap");
|
|
67
|
+
const prompt = runTeam(tempRoot, "member-prompt", "--team", "comms-bootstrap", "--id", "A").stdout;
|
|
68
|
+
|
|
69
|
+
// then - the first thing a member reads tells it to push via the tool as it works
|
|
70
|
+
assert.match(prompt, /codex_app\.send_message_to_thread/, "bootstrap must name the push tool");
|
|
71
|
+
assert.match(prompt, /never just one report at the end/, "bootstrap must reject end-only reporting");
|
|
72
|
+
// then - it no longer frames reporting as a one-shot completion event
|
|
73
|
+
assert.doesNotMatch(prompt, /report to the leader the moment you are done/, "the end-only bootstrap line must be removed");
|
|
74
|
+
} finally {
|
|
75
|
+
cleanupTeamRoot(tempRoot);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("#given the leader-facing SKILL.md #when it describes communication #then it requires --session so members can reach the leader and frames members as pushing", () => {
|
|
80
|
+
const skill = readFileSync(join(root, "components", "teammode", "skills", "teammode", "SKILL.md"), "utf8");
|
|
81
|
+
|
|
82
|
+
// then - the leader is told members PUSH to it (not only that the leader sends)
|
|
83
|
+
assert.match(skill, /Members push to you/i, "SKILL.md must frame members as pushing to the leader");
|
|
84
|
+
// then - the --session requirement is stated WITH its reason (member->leader push needs a real leader thread)
|
|
85
|
+
assert.match(skill, /--session <your own thread id>/, "SKILL.md must require init --session <your own thread id>");
|
|
86
|
+
assert.match(skill, /stuck polling|cannot report to you/i, "SKILL.md must explain why --session matters");
|
|
87
|
+
});
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import test from "node:test";
|
|
4
|
+
|
|
5
|
+
import { cleanupTeamRoot, createTeamRoot, readTeamJson, runTeam, runTeamRaw, teamJsonPath } from "./teammode-safety-fixture.mjs";
|
|
6
|
+
|
|
7
|
+
function addMember(tempRoot, sessionId, { id, name, focus, lens, deliverable }) {
|
|
8
|
+
const args = ["add-member", "--team", sessionId, "--id", id, "--focus", focus, "--lens", lens, "--deliverable", deliverable];
|
|
9
|
+
if (name !== undefined) args.push("--name", name);
|
|
10
|
+
return runTeam(tempRoot, ...args);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
test("#given two members with distinct names #when added #then each thread title is per-member and the two never collide", () => {
|
|
14
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-title-");
|
|
15
|
+
try {
|
|
16
|
+
runTeam(tempRoot, "init", "--name", "Recovery", "--session-name", "app-server-research", "--session", "title-distinct");
|
|
17
|
+
addMember(tempRoot, "title-distinct", { id: "A", name: "app-server-lifecycle", focus: "app-server thread lifecycle", lens: "area", deliverable: "lifecycle map" });
|
|
18
|
+
addMember(tempRoot, "title-distinct", { id: "B", name: "mailbox-delivery", focus: "mailbox live-delivery path", lens: "ownership", deliverable: "delivery audit" });
|
|
19
|
+
|
|
20
|
+
const team = readTeamJson(tempRoot, "title-distinct");
|
|
21
|
+
const byId = Object.fromEntries(team.members.map((m) => [m.id, m]));
|
|
22
|
+
|
|
23
|
+
// then - the title carries the member's own name, not a fixed team-wide session name
|
|
24
|
+
assert.equal(byId.A.threadTitle, "[Recovery] app-server-lifecycle");
|
|
25
|
+
assert.equal(byId.B.threadTitle, "[Recovery] mailbox-delivery");
|
|
26
|
+
// then - the member name is recorded for identity
|
|
27
|
+
assert.equal(byId.A.name, "app-server-lifecycle");
|
|
28
|
+
assert.equal(byId.B.name, "mailbox-delivery");
|
|
29
|
+
// then - no two members share a title (the core bug)
|
|
30
|
+
assert.notEqual(byId.A.threadTitle, byId.B.threadTitle);
|
|
31
|
+
} finally {
|
|
32
|
+
cleanupTeamRoot(tempRoot);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("#given a member added without an explicit name #when state is read #then the title falls back to the focus, never a shared session name", () => {
|
|
37
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-title-fallback-");
|
|
38
|
+
try {
|
|
39
|
+
runTeam(tempRoot, "init", "--name", "Recovery", "--session-name", "shared-session", "--session", "title-fallback");
|
|
40
|
+
addMember(tempRoot, "title-fallback", { id: "A", focus: "installer config", lens: "area", deliverable: "x" });
|
|
41
|
+
addMember(tempRoot, "title-fallback", { id: "B", focus: "runtime qa", lens: "perspective", deliverable: "y" });
|
|
42
|
+
|
|
43
|
+
const team = readTeamJson(tempRoot, "title-fallback");
|
|
44
|
+
const byId = Object.fromEntries(team.members.map((m) => [m.id, m]));
|
|
45
|
+
|
|
46
|
+
// then - fallback uses the member's own focus, so titles still differ per member
|
|
47
|
+
assert.equal(byId.A.threadTitle, "[Recovery] installer config");
|
|
48
|
+
assert.equal(byId.B.threadTitle, "[Recovery] runtime qa");
|
|
49
|
+
assert.notEqual(byId.A.threadTitle, byId.B.threadTitle);
|
|
50
|
+
} finally {
|
|
51
|
+
cleanupTeamRoot(tempRoot);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("#given a member name already exists #when add-member receives the same name with different spacing and case #then state is not partially mutated", () => {
|
|
56
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-title-duplicate-name-");
|
|
57
|
+
try {
|
|
58
|
+
runTeam(tempRoot, "init", "--name", "Recovery", "--session-name", "shared-session", "--session", "title-duplicate-name");
|
|
59
|
+
addMember(tempRoot, "title-duplicate-name", {
|
|
60
|
+
id: "A",
|
|
61
|
+
name: "App Server",
|
|
62
|
+
focus: "app-server lifecycle",
|
|
63
|
+
lens: "area",
|
|
64
|
+
deliverable: "lifecycle map",
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const result = runTeamRaw(
|
|
68
|
+
tempRoot,
|
|
69
|
+
"add-member",
|
|
70
|
+
"--team",
|
|
71
|
+
"title-duplicate-name",
|
|
72
|
+
"--id",
|
|
73
|
+
"B",
|
|
74
|
+
"--name",
|
|
75
|
+
" app server ",
|
|
76
|
+
"--focus",
|
|
77
|
+
"mailbox delivery",
|
|
78
|
+
"--lens",
|
|
79
|
+
"ownership",
|
|
80
|
+
"--deliverable",
|
|
81
|
+
"delivery audit",
|
|
82
|
+
);
|
|
83
|
+
const team = readTeamJson(tempRoot, "title-duplicate-name");
|
|
84
|
+
|
|
85
|
+
assert.notEqual(result.status, 0);
|
|
86
|
+
assert.match(result.stderr, /member name "app server" duplicates "App Server"/);
|
|
87
|
+
assert.equal(team.members.length, 1);
|
|
88
|
+
assert.deepEqual(
|
|
89
|
+
team.members.map((member) => ({ id: member.id, name: member.name, threadTitle: member.threadTitle })),
|
|
90
|
+
[{ id: "A", name: "App Server", threadTitle: "[Recovery] App Server" }],
|
|
91
|
+
);
|
|
92
|
+
} finally {
|
|
93
|
+
cleanupTeamRoot(tempRoot);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("#given persisted team.json has duplicate member names #when a command loads the team #then stale state is rejected", () => {
|
|
98
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-title-stale-duplicate-name-");
|
|
99
|
+
try {
|
|
100
|
+
runTeam(tempRoot, "init", "--name", "Recovery", "--session-name", "shared-session", "--session", "title-stale-duplicate-name");
|
|
101
|
+
addMember(tempRoot, "title-stale-duplicate-name", {
|
|
102
|
+
id: "A",
|
|
103
|
+
name: "App Server",
|
|
104
|
+
focus: "app-server lifecycle",
|
|
105
|
+
lens: "area",
|
|
106
|
+
deliverable: "lifecycle map",
|
|
107
|
+
});
|
|
108
|
+
addMember(tempRoot, "title-stale-duplicate-name", {
|
|
109
|
+
id: "B",
|
|
110
|
+
name: "Mailbox Delivery",
|
|
111
|
+
focus: "mailbox delivery",
|
|
112
|
+
lens: "ownership",
|
|
113
|
+
deliverable: "delivery audit",
|
|
114
|
+
});
|
|
115
|
+
const path = teamJsonPath(tempRoot, "title-stale-duplicate-name");
|
|
116
|
+
const team = JSON.parse(readFileSync(path, "utf8"));
|
|
117
|
+
team.members[1].name = " app server ";
|
|
118
|
+
writeFileSync(path, `${JSON.stringify(team, null, 2)}\n`);
|
|
119
|
+
|
|
120
|
+
const result = runTeamRaw(tempRoot, "status", "--team", "title-stale-duplicate-name");
|
|
121
|
+
|
|
122
|
+
assert.notEqual(result.status, 0);
|
|
123
|
+
assert.match(result.stderr, /member name " app server " duplicates "App Server"/);
|
|
124
|
+
} finally {
|
|
125
|
+
cleanupTeamRoot(tempRoot);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test("#given persisted team.json has duplicate thread titles with distinct member names #when bind-thread runs #then state is rejected before activation", () => {
|
|
130
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-title-stale-duplicate-title-");
|
|
131
|
+
try {
|
|
132
|
+
runTeam(tempRoot, "init", "--name", "Recovery", "--session-name", "shared-session", "--session", "title-stale-duplicate-title");
|
|
133
|
+
addMember(tempRoot, "title-stale-duplicate-title", {
|
|
134
|
+
id: "A",
|
|
135
|
+
name: "App Server",
|
|
136
|
+
focus: "app-server lifecycle",
|
|
137
|
+
lens: "area",
|
|
138
|
+
deliverable: "lifecycle map",
|
|
139
|
+
});
|
|
140
|
+
addMember(tempRoot, "title-stale-duplicate-title", {
|
|
141
|
+
id: "B",
|
|
142
|
+
name: "Mailbox Delivery",
|
|
143
|
+
focus: "mailbox delivery",
|
|
144
|
+
lens: "ownership",
|
|
145
|
+
deliverable: "delivery audit",
|
|
146
|
+
});
|
|
147
|
+
const path = teamJsonPath(tempRoot, "title-stale-duplicate-title");
|
|
148
|
+
const team = JSON.parse(readFileSync(path, "utf8"));
|
|
149
|
+
team.members[0].threadTitle = "[Legacy] Alpha";
|
|
150
|
+
team.members[1].threadTitle = "[Legacy] Alpha";
|
|
151
|
+
writeFileSync(path, `${JSON.stringify(team, null, 2)}\n`);
|
|
152
|
+
|
|
153
|
+
const result = runTeamRaw(tempRoot, "bind-thread", "--team", "title-stale-duplicate-title", "--id", "A", "--thread", "thread-a");
|
|
154
|
+
const persisted = readTeamJson(tempRoot, "title-stale-duplicate-title");
|
|
155
|
+
|
|
156
|
+
assert.notEqual(result.status, 0);
|
|
157
|
+
assert.match(result.stderr, /member threadTitle "\[Legacy\] Alpha" duplicates "\[Legacy\] Alpha"/);
|
|
158
|
+
assert.deepEqual(
|
|
159
|
+
persisted.members.map((member) => ({ id: member.id, status: member.status, threadId: member.threadId })),
|
|
160
|
+
[
|
|
161
|
+
{ id: "A", status: "pending", threadId: null },
|
|
162
|
+
{ id: "B", status: "pending", threadId: null },
|
|
163
|
+
],
|
|
164
|
+
);
|
|
165
|
+
assert.equal(persisted.log.some((entry) => entry.event === "bind-thread"), false);
|
|
166
|
+
} finally {
|
|
167
|
+
cleanupTeamRoot(tempRoot);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
|
|
7
|
+
import { cleanupTeamRoot, createTeamRoot, readTeamJson, runTeam, runTeamRaw, teamDir, teamJsonPath } from "./teammode-safety-fixture.mjs";
|
|
8
|
+
|
|
9
|
+
function memberWorktreePath(tempRoot, sessionId, memberId) {
|
|
10
|
+
return join(tempRoot, ".omo", "teams", sessionId, "worktrees", memberId);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Compare two on-disk paths regardless of OS: realpathSync canonicalizes separators, drive-letter
|
|
14
|
+
// case (Windows), and symlinks (macOS /var -> /private/var). Returns false if either side is gone.
|
|
15
|
+
function samePath(a, b) {
|
|
16
|
+
try {
|
|
17
|
+
return realpathSync(a) === realpathSync(b);
|
|
18
|
+
} catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function git(cwd, ...args) {
|
|
24
|
+
const result = spawnSync("git", args, { cwd, encoding: "utf8" });
|
|
25
|
+
assert.equal(result.status, 0, `git ${args.join(" ")} failed: ${result.stderr || result.stdout}`);
|
|
26
|
+
return result.stdout;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// A real git repo on a known base branch so worktree-add/integrate exercise real git, not mocks.
|
|
30
|
+
function initGitRepo(cwd, { baseBranch = "main" } = {}) {
|
|
31
|
+
git(cwd, "init", "-b", baseBranch);
|
|
32
|
+
git(cwd, "config", "user.email", "team@example.com");
|
|
33
|
+
git(cwd, "config", "user.name", "Teammode Test");
|
|
34
|
+
writeFileSync(join(cwd, "file.txt"), "base\n");
|
|
35
|
+
git(cwd, "add", "file.txt");
|
|
36
|
+
git(cwd, "commit", "-m", "base commit");
|
|
37
|
+
return baseBranch;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function bootstrapTeam(cwd, sessionId, { worktree = false, baseBranch = "main" } = {}) {
|
|
41
|
+
const args = ["init", "--name", "WT", "--session-name", "wt-session", "--session", sessionId, "--base-branch", baseBranch];
|
|
42
|
+
if (worktree) args.push("--worktree");
|
|
43
|
+
runTeam(cwd, ...args);
|
|
44
|
+
runTeam(cwd, "add-member", "--team", sessionId, "--id", "A", "--focus", "alpha slice", "--lens", "area", "--deliverable", "a");
|
|
45
|
+
runTeam(cwd, "add-member", "--team", sessionId, "--id", "B", "--focus", "beta slice", "--lens", "ownership", "--deliverable", "b");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// The branch each worktree is checked out on. Branch refs are "/"-delimited on every OS, so this
|
|
49
|
+
// is a separator-proof way to assert which worktrees git knows about (porcelain paths are not).
|
|
50
|
+
function worktreeBranches(cwd) {
|
|
51
|
+
return git(cwd, "worktree", "list", "--porcelain")
|
|
52
|
+
.split("\n")
|
|
53
|
+
.filter((line) => line.startsWith("branch "))
|
|
54
|
+
.map((line) => line.slice("branch ".length).replace("refs/heads/", ""));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function branchExists(cwd, branch) {
|
|
58
|
+
return spawnSync("git", ["rev-parse", "--verify", "--quiet", `refs/heads/${branch}`], { cwd, encoding: "utf8" }).status === 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
test("#given a worktree team #when worktree-add A #then a real git worktree on a derived branch is created and recorded", () => {
|
|
62
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-wt-add-");
|
|
63
|
+
try {
|
|
64
|
+
initGitRepo(tempRoot);
|
|
65
|
+
bootstrapTeam(tempRoot, "wt-add", { worktree: true });
|
|
66
|
+
|
|
67
|
+
const result = runTeam(tempRoot, "worktree-add", "--team", "wt-add", "--id", "A");
|
|
68
|
+
|
|
69
|
+
// then - git itself knows about the worktree on the member branch
|
|
70
|
+
const expectedBranch = "team/wt-add/A";
|
|
71
|
+
assert.equal(branchExists(tempRoot, expectedBranch), true, "member branch must exist");
|
|
72
|
+
assert.ok(worktreeBranches(tempRoot).includes(expectedBranch), "git worktree list must include the member branch");
|
|
73
|
+
|
|
74
|
+
// then - team.json records the worktree for the member (compare by realpath: OS-agnostic)
|
|
75
|
+
const expectedPath = memberWorktreePath(tempRoot, "wt-add", "A");
|
|
76
|
+
const member = readTeamJson(tempRoot, "wt-add").members.find((m) => m.id === "A");
|
|
77
|
+
assert.ok(existsSync(member.worktree.path) && samePath(member.worktree.path, expectedPath), "worktree.path must point at the member worktree dir");
|
|
78
|
+
assert.equal(member.worktree.branch, expectedBranch);
|
|
79
|
+
assert.ok(samePath(member.cwd, expectedPath), "cwd must be the member worktree dir");
|
|
80
|
+
|
|
81
|
+
// then - the leader is told the exact cd target
|
|
82
|
+
assert.match(result.stdout, /cd /);
|
|
83
|
+
assert.match(result.stdout, /A/);
|
|
84
|
+
} finally {
|
|
85
|
+
cleanupTeamRoot(tempRoot);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("#given worktree-add ran #when the field manual is regenerated #then it flips the member's guide to ISOLATION IS ON with the derived branch", () => {
|
|
90
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-wt-guide-");
|
|
91
|
+
try {
|
|
92
|
+
initGitRepo(tempRoot);
|
|
93
|
+
bootstrapTeam(tempRoot, "wt-guide", { worktree: false });
|
|
94
|
+
// before: no isolation, so the manual tells members to signal collisions instead
|
|
95
|
+
assert.match(readFileSync(join(teamDir(tempRoot, "wt-guide"), "guide.md"), "utf8"), /does not use isolated git worktrees/);
|
|
96
|
+
|
|
97
|
+
runTeam(tempRoot, "worktree-add", "--team", "wt-guide", "--id", "A");
|
|
98
|
+
|
|
99
|
+
const guide = readFileSync(join(teamDir(tempRoot, "wt-guide"), "guide.md"), "utf8");
|
|
100
|
+
assert.match(guide, /ISOLATION IS ON/);
|
|
101
|
+
assert.match(guide, /team\/wt-guide\/A/, "the member's row must show its derived worktree branch");
|
|
102
|
+
} finally {
|
|
103
|
+
cleanupTeamRoot(tempRoot);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test("#given a team initialized WITHOUT --worktree #when worktree-add is called mid-run #then it auto-enables isolation (conflict-triggered)", () => {
|
|
108
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-wt-autoenable-");
|
|
109
|
+
try {
|
|
110
|
+
initGitRepo(tempRoot);
|
|
111
|
+
bootstrapTeam(tempRoot, "wt-auto", { worktree: false });
|
|
112
|
+
assert.equal(readTeamJson(tempRoot, "wt-auto").worktree.enabled, false, "precondition: worktree starts disabled");
|
|
113
|
+
|
|
114
|
+
runTeam(tempRoot, "worktree-add", "--team", "wt-auto", "--id", "A");
|
|
115
|
+
|
|
116
|
+
const team = readTeamJson(tempRoot, "wt-auto");
|
|
117
|
+
assert.equal(team.worktree.enabled, true, "worktree-add must flip the team into isolation mode");
|
|
118
|
+
assert.ok(worktreeBranches(tempRoot).includes("team/wt-auto/A"), "git must have created the member worktree");
|
|
119
|
+
} finally {
|
|
120
|
+
cleanupTeamRoot(tempRoot);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test("#given an existing member worktree #when worktree-add runs again #then it is a safe no-op that reports the existing worktree", () => {
|
|
125
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-wt-idem-");
|
|
126
|
+
try {
|
|
127
|
+
initGitRepo(tempRoot);
|
|
128
|
+
bootstrapTeam(tempRoot, "wt-idem", { worktree: true });
|
|
129
|
+
runTeam(tempRoot, "worktree-add", "--team", "wt-idem", "--id", "A");
|
|
130
|
+
|
|
131
|
+
const second = runTeam(tempRoot, "worktree-add", "--team", "wt-idem", "--id", "A");
|
|
132
|
+
|
|
133
|
+
assert.match(second.stdout, /exist/i, "re-running must report the worktree already exists, not crash");
|
|
134
|
+
assert.equal(worktreeBranches(tempRoot).filter((b) => b === "team/wt-idem/A").length, 1, "no duplicate worktree");
|
|
135
|
+
} finally {
|
|
136
|
+
cleanupTeamRoot(tempRoot);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test("#given a member worktree #when worktree-remove A #then git drops it and team.json clears the path", () => {
|
|
141
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-wt-remove-");
|
|
142
|
+
try {
|
|
143
|
+
initGitRepo(tempRoot);
|
|
144
|
+
bootstrapTeam(tempRoot, "wt-rm", { worktree: true });
|
|
145
|
+
runTeam(tempRoot, "worktree-add", "--team", "wt-rm", "--id", "A");
|
|
146
|
+
assert.ok(worktreeBranches(tempRoot).includes("team/wt-rm/A"));
|
|
147
|
+
|
|
148
|
+
runTeam(tempRoot, "worktree-remove", "--team", "wt-rm", "--id", "A");
|
|
149
|
+
|
|
150
|
+
assert.ok(!worktreeBranches(tempRoot).includes("team/wt-rm/A"), "git worktree list must no longer include the removed worktree");
|
|
151
|
+
const member = readTeamJson(tempRoot, "wt-rm").members.find((m) => m.id === "A");
|
|
152
|
+
assert.equal(member.worktree.path, null);
|
|
153
|
+
} finally {
|
|
154
|
+
cleanupTeamRoot(tempRoot);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test("#given a member committed work in its worktree #when integrate --id A #then the base branch gets a NO-FF merge commit", () => {
|
|
159
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-wt-integrate-");
|
|
160
|
+
try {
|
|
161
|
+
initGitRepo(tempRoot);
|
|
162
|
+
bootstrapTeam(tempRoot, "wt-int", { worktree: true });
|
|
163
|
+
runTeam(tempRoot, "worktree-add", "--team", "wt-int", "--id", "A");
|
|
164
|
+
|
|
165
|
+
// member A does work inside its own worktree and commits
|
|
166
|
+
const wtA = join(tempRoot, ".omo", "teams", "wt-int", "worktrees", "A");
|
|
167
|
+
writeFileSync(join(wtA, "alpha.txt"), "alpha work\n");
|
|
168
|
+
git(wtA, "add", "alpha.txt");
|
|
169
|
+
git(wtA, "commit", "-m", "alpha: add alpha.txt");
|
|
170
|
+
|
|
171
|
+
runTeam(tempRoot, "integrate", "--team", "wt-int", "--id", "A");
|
|
172
|
+
|
|
173
|
+
// then - base branch carries the member's file via a merge commit (not a fast-forward / squash)
|
|
174
|
+
const mergeCommits = git(tempRoot, "log", "main", "--merges", "--oneline");
|
|
175
|
+
assert.notEqual(mergeCommits.trim(), "", "integrate must produce a merge commit on the base branch");
|
|
176
|
+
const tracked = git(tempRoot, "ls-files");
|
|
177
|
+
assert.match(tracked, /alpha\.txt/, "the member's committed file must be present on the base branch");
|
|
178
|
+
} finally {
|
|
179
|
+
cleanupTeamRoot(tempRoot);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
test("#given two members edited the same line #when integrate hits the conflict #then it stops, reports the conflicting member, and exits non-zero", () => {
|
|
184
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-wt-conflict-");
|
|
185
|
+
try {
|
|
186
|
+
initGitRepo(tempRoot);
|
|
187
|
+
bootstrapTeam(tempRoot, "wt-conf", { worktree: true });
|
|
188
|
+
runTeam(tempRoot, "worktree-add", "--team", "wt-conf", "--id", "A");
|
|
189
|
+
runTeam(tempRoot, "worktree-add", "--team", "wt-conf", "--id", "B");
|
|
190
|
+
|
|
191
|
+
const wtA = join(tempRoot, ".omo", "teams", "wt-conf", "worktrees", "A");
|
|
192
|
+
writeFileSync(join(wtA, "file.txt"), "A changed the line\n");
|
|
193
|
+
git(wtA, "commit", "-am", "A edits file.txt");
|
|
194
|
+
const wtB = join(tempRoot, ".omo", "teams", "wt-conf", "worktrees", "B");
|
|
195
|
+
writeFileSync(join(wtB, "file.txt"), "B changed the line\n");
|
|
196
|
+
git(wtB, "commit", "-am", "B edits file.txt");
|
|
197
|
+
|
|
198
|
+
runTeam(tempRoot, "integrate", "--team", "wt-conf", "--id", "A");
|
|
199
|
+
const conflict = runTeamRaw(tempRoot, "integrate", "--team", "wt-conf", "--id", "B");
|
|
200
|
+
|
|
201
|
+
assert.notEqual(conflict.status, 0, "a merge conflict must surface as a non-zero exit");
|
|
202
|
+
assert.match(`${conflict.stdout}${conflict.stderr}`, /conflict/i);
|
|
203
|
+
assert.match(`${conflict.stdout}${conflict.stderr}`, /\bB\b/);
|
|
204
|
+
} finally {
|
|
205
|
+
cleanupTeamRoot(tempRoot);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
test("#given a member branch that cannot be merged #when integrate runs #then it surfaces git's real reason, not a fake conflict", () => {
|
|
210
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-wt-fatal-");
|
|
211
|
+
try {
|
|
212
|
+
initGitRepo(tempRoot);
|
|
213
|
+
bootstrapTeam(tempRoot, "wt-fatal", { worktree: true });
|
|
214
|
+
runTeam(tempRoot, "worktree-add", "--team", "wt-fatal", "--id", "A");
|
|
215
|
+
// point member A at a branch that does not exist: a fatal git error, NOT a content conflict
|
|
216
|
+
const team = readTeamJson(tempRoot, "wt-fatal");
|
|
217
|
+
team.members.find((m) => m.id === "A").worktree.branch = "ghost-branch-404";
|
|
218
|
+
writeFileSync(teamJsonPath(tempRoot, "wt-fatal"), `${JSON.stringify(team, null, 2)}\n`);
|
|
219
|
+
|
|
220
|
+
const result = runTeamRaw(tempRoot, "integrate", "--team", "wt-fatal", "--id", "A");
|
|
221
|
+
|
|
222
|
+
const out = `${result.stdout}${result.stderr}`;
|
|
223
|
+
assert.notEqual(result.status, 0);
|
|
224
|
+
assert.match(out, /could not integrate|not something we can merge|ghost-branch-404/i, "must surface git's actual reason");
|
|
225
|
+
assert.doesNotMatch(out, /Conflicting files/, "a non-conflict failure must NOT be mislabeled as a merge conflict");
|
|
226
|
+
} finally {
|
|
227
|
+
cleanupTeamRoot(tempRoot);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
test("#given a member id that is not a safe path segment #when worktree-add runs #then it refuses instead of escaping the team dir", () => {
|
|
232
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-wt-escape-");
|
|
233
|
+
try {
|
|
234
|
+
initGitRepo(tempRoot);
|
|
235
|
+
runTeam(tempRoot, "init", "--name", "WT", "--session-name", "wt", "--session", "wt-escape", "--base-branch", "main", "--worktree");
|
|
236
|
+
runTeam(tempRoot, "add-member", "--team", "wt-escape", "--id", "A", "--focus", "alpha", "--lens", "area", "--deliverable", "a");
|
|
237
|
+
// craft an unsafe member id directly in state, then try to provision a worktree for it
|
|
238
|
+
mkdirSync(join(tempRoot, "sentinel"), { recursive: true });
|
|
239
|
+
const result = runTeamRaw(tempRoot, "worktree-add", "--team", "wt-escape", "--id", "../../sentinel");
|
|
240
|
+
|
|
241
|
+
assert.notEqual(result.status, 0);
|
|
242
|
+
assert.match(`${result.stdout}${result.stderr}`, /unsafe|no member|escape/i);
|
|
243
|
+
} finally {
|
|
244
|
+
cleanupTeamRoot(tempRoot);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
@@ -172,3 +172,33 @@ test("#given ultraresearch team communication #when the raise law is inspected #
|
|
|
172
172
|
);
|
|
173
173
|
}
|
|
174
174
|
});
|
|
175
|
+
|
|
176
|
+
test("#given ultraresearch non-code verification #when the gate is inspected #then a claim ledger / verified-claims data-flow-lock exists", async () => {
|
|
177
|
+
for (const copy of await readUltraresearchCopies()) {
|
|
178
|
+
assert.match(
|
|
179
|
+
copy.content,
|
|
180
|
+
/claim ledger|verified-claims/i,
|
|
181
|
+
`${copy.label}: body must define the non-code claim-ledger verification gate`,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test("#given ultraresearch claim ledger #when ownership is inspected #then workers never write the ledger / verified-claims artifact", async () => {
|
|
187
|
+
for (const copy of await readUltraresearchCopies()) {
|
|
188
|
+
assert.doesNotMatch(
|
|
189
|
+
copy.content,
|
|
190
|
+
/worker[^.]*\b(?:write|append|create)s?\b[^.]*(?:ledger|verified-claims)/i,
|
|
191
|
+
`${copy.label}: workers must not be instructed to write/append/create the ledger or verified-claims`,
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
test("#given ultraresearch blocked sources #when escalation is inspected #then it routes through the ultimate-browsing skill", async () => {
|
|
197
|
+
for (const copy of await readUltraresearchCopies()) {
|
|
198
|
+
assert.match(
|
|
199
|
+
copy.content,
|
|
200
|
+
/ultimate-browsing/,
|
|
201
|
+
`${copy.label}: body must escalate blocked sources via the ultimate-browsing skill`,
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
});
|