productfoo 0.0.0-stage → 1.0.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/LICENSE +201 -0
- package/README.md +338 -2
- package/bin/foo +3 -0
- package/bin/foo.mjs +42 -0
- package/commands/bug.md +31 -0
- package/commands/discovery.md +28 -0
- package/commands/ideate.md +27 -0
- package/commands/init.md +28 -0
- package/commands/pitch.md +27 -0
- package/commands/preview.md +25 -0
- package/commands/research.md +31 -0
- package/commands/roast.md +27 -0
- package/commands/spec.md +30 -0
- package/config/pricing.yaml +198 -0
- package/config/routing-policy.yaml +171 -0
- package/dist-public/src/activeModel.d.ts +83 -0
- package/dist-public/src/activeModel.js +331 -0
- package/dist-public/src/agentAdapters.d.ts +122 -0
- package/dist-public/src/agentAdapters.js +178 -0
- package/dist-public/src/agentState.d.ts +43 -0
- package/dist-public/src/agentState.js +177 -0
- package/dist-public/src/bugCapsule.d.ts +94 -0
- package/dist-public/src/bugCapsule.js +227 -0
- package/dist-public/src/bugCapture.d.ts +26 -0
- package/dist-public/src/bugCapture.js +251 -0
- package/dist-public/src/bugOwnerLog.d.ts +93 -0
- package/dist-public/src/bugOwnerLog.js +304 -0
- package/dist-public/src/bugReportStore.d.ts +48 -0
- package/dist-public/src/bugReportStore.js +860 -0
- package/dist-public/src/bugSpecContext.d.ts +7 -0
- package/dist-public/src/bugSpecContext.js +129 -0
- package/dist-public/src/channelFreshness.d.ts +25 -0
- package/dist-public/src/channelFreshness.js +194 -0
- package/dist-public/src/cli.d.ts +30 -0
- package/dist-public/src/cli.js +1667 -0
- package/dist-public/src/cliArgs.d.ts +7 -0
- package/dist-public/src/cliArgs.js +44 -0
- package/dist-public/src/codeCatalog.d.ts +41 -0
- package/dist-public/src/codeCatalog.js +197 -0
- package/dist-public/src/commandContract.d.ts +84 -0
- package/dist-public/src/commandContract.js +390 -0
- package/dist-public/src/commandUsage.d.ts +3 -0
- package/dist-public/src/commandUsage.js +30 -0
- package/dist-public/src/commands/agent.d.ts +60 -0
- package/dist-public/src/commands/agent.js +1353 -0
- package/dist-public/src/commands/asp.d.ts +8 -0
- package/dist-public/src/commands/asp.js +669 -0
- package/dist-public/src/commands/evalCmd.d.ts +4 -0
- package/dist-public/src/commands/evalCmd.js +405 -0
- package/dist-public/src/commands/login.d.ts +25 -0
- package/dist-public/src/commands/login.js +94 -0
- package/dist-public/src/commands/loop.d.ts +16 -0
- package/dist-public/src/commands/loop.js +619 -0
- package/dist-public/src/commands/reconcile.d.ts +41 -0
- package/dist-public/src/commands/reconcile.js +292 -0
- package/dist-public/src/commands/runtime.d.ts +1 -0
- package/dist-public/src/commands/runtime.js +36 -0
- package/dist-public/src/commands/scanRedact.d.ts +8 -0
- package/dist-public/src/commands/scanRedact.js +266 -0
- package/dist-public/src/commands/setup.d.ts +28 -0
- package/dist-public/src/commands/setup.js +398 -0
- package/dist-public/src/commands/shared.d.ts +17 -0
- package/dist-public/src/commands/shared.js +147 -0
- package/dist-public/src/commands/source.d.ts +1 -0
- package/dist-public/src/commands/source.js +134 -0
- package/dist-public/src/commands/specCmd.d.ts +24 -0
- package/dist-public/src/commands/specCmd.js +794 -0
- package/dist-public/src/commands/update.d.ts +61 -0
- package/dist-public/src/commands/update.js +244 -0
- package/dist-public/src/comprehensionSignal.d.ts +20 -0
- package/dist-public/src/comprehensionSignal.js +166 -0
- package/dist-public/src/conductor/diversity.d.ts +48 -0
- package/dist-public/src/conductor/diversity.js +423 -0
- package/dist-public/src/conductor/engine.d.ts +7 -0
- package/dist-public/src/conductor/engine.js +295 -0
- package/dist-public/src/conductor/families/ideate.d.ts +2 -0
- package/dist-public/src/conductor/families/ideate.js +255 -0
- package/dist-public/src/conductor/families/interview.d.ts +2 -0
- package/dist-public/src/conductor/families/interview.js +39 -0
- package/dist-public/src/conductor/families/specSwarm.d.ts +2 -0
- package/dist-public/src/conductor/families/specSwarm.js +146 -0
- package/dist-public/src/conductor/familyDelivery.d.ts +6 -0
- package/dist-public/src/conductor/familyDelivery.js +37 -0
- package/dist-public/src/conductor/familyPackArtifact.d.ts +4 -0
- package/dist-public/src/conductor/familyPackArtifact.js +260 -0
- package/dist-public/src/conductor/ideateDecision.d.ts +6 -0
- package/dist-public/src/conductor/ideateDecision.js +237 -0
- package/dist-public/src/conductor/pack.d.ts +26 -0
- package/dist-public/src/conductor/pack.js +75 -0
- package/dist-public/src/conductor/types.d.ts +111 -0
- package/dist-public/src/conductor/types.js +7 -0
- package/dist-public/src/configPath.d.ts +2 -0
- package/dist-public/src/configPath.js +7 -0
- package/dist-public/src/discoveryArtifacts.d.ts +54 -0
- package/dist-public/src/discoveryArtifacts.js +467 -0
- package/dist-public/src/discoveryCommand.d.ts +127 -0
- package/dist-public/src/discoveryCommand.js +2148 -0
- package/dist-public/src/discoveryConnections.d.ts +339 -0
- package/dist-public/src/discoveryConnections.js +613 -0
- package/dist-public/src/discoveryDocs.d.ts +129 -0
- package/dist-public/src/discoveryDocs.js +577 -0
- package/dist-public/src/discoveryEvidence.d.ts +59 -0
- package/dist-public/src/discoveryEvidence.js +198 -0
- package/dist-public/src/discoveryFireflies.d.ts +25 -0
- package/dist-public/src/discoveryFireflies.js +551 -0
- package/dist-public/src/discoveryGmail.d.ts +12 -0
- package/dist-public/src/discoveryGmail.js +466 -0
- package/dist-public/src/discoveryGong.d.ts +12 -0
- package/dist-public/src/discoveryGong.js +491 -0
- package/dist-public/src/discoveryLearningRouting.d.ts +90 -0
- package/dist-public/src/discoveryLearningRouting.js +405 -0
- package/dist-public/src/discoveryMatching.d.ts +26 -0
- package/dist-public/src/discoveryMatching.js +73 -0
- package/dist-public/src/discoveryOutlook.d.ts +12 -0
- package/dist-public/src/discoveryOutlook.js +492 -0
- package/dist-public/src/discoveryProcess.d.ts +221 -0
- package/dist-public/src/discoveryProcess.js +703 -0
- package/dist-public/src/discoveryProof.d.ts +143 -0
- package/dist-public/src/discoveryProof.js +529 -0
- package/dist-public/src/discoveryProviders.d.ts +152 -0
- package/dist-public/src/discoveryProviders.js +756 -0
- package/dist-public/src/discoveryReadiness.d.ts +219 -0
- package/dist-public/src/discoveryReadiness.js +672 -0
- package/dist-public/src/discoveryReconcile.d.ts +57 -0
- package/dist-public/src/discoveryReconcile.js +424 -0
- package/dist-public/src/discoverySlack.d.ts +12 -0
- package/dist-public/src/discoverySlack.js +452 -0
- package/dist-public/src/discoverySources.d.ts +56 -0
- package/dist-public/src/discoverySources.js +322 -0
- package/dist-public/src/discoverySync.d.ts +52 -0
- package/dist-public/src/discoverySync.js +151 -0
- package/dist-public/src/discoverySynthesis.d.ts +57 -0
- package/dist-public/src/discoverySynthesis.js +215 -0
- package/dist-public/src/discoveryTeams.d.ts +12 -0
- package/dist-public/src/discoveryTeams.js +516 -0
- package/dist-public/src/discoveryZoom.d.ts +12 -0
- package/dist-public/src/discoveryZoom.js +523 -0
- package/dist-public/src/elicitationSurface.d.ts +13 -0
- package/dist-public/src/elicitationSurface.js +77 -0
- package/dist-public/src/errorReport.d.ts +99 -0
- package/dist-public/src/errorReport.js +443 -0
- package/dist-public/src/errorTaxonomy.d.ts +84 -0
- package/dist-public/src/errorTaxonomy.js +189 -0
- package/dist-public/src/evalCalibration.d.ts +82 -0
- package/dist-public/src/evalCalibration.js +169 -0
- package/dist-public/src/evalChecks.d.ts +21 -0
- package/dist-public/src/evalChecks.js +295 -0
- package/dist-public/src/evalCompile.d.ts +56 -0
- package/dist-public/src/evalCompile.js +58 -0
- package/dist-public/src/evalImprove.d.ts +60 -0
- package/dist-public/src/evalImprove.js +175 -0
- package/dist-public/src/evalJudge.d.ts +47 -0
- package/dist-public/src/evalJudge.js +143 -0
- package/dist-public/src/evalLabels.d.ts +100 -0
- package/dist-public/src/evalLabels.js +287 -0
- package/dist-public/src/evalRecord.d.ts +68 -0
- package/dist-public/src/evalRecord.js +165 -0
- package/dist-public/src/evalRoast.d.ts +88 -0
- package/dist-public/src/evalRoast.js +249 -0
- package/dist-public/src/evidenceIntake.d.ts +66 -0
- package/dist-public/src/evidenceIntake.js +356 -0
- package/dist-public/src/feedback.d.ts +78 -0
- package/dist-public/src/feedback.js +294 -0
- package/dist-public/src/firefliesClient.d.ts +106 -0
- package/dist-public/src/firefliesClient.js +258 -0
- package/dist-public/src/firstMoveTensions.d.ts +10 -0
- package/dist-public/src/firstMoveTensions.js +93 -0
- package/dist-public/src/gitRun.d.ts +21 -0
- package/dist-public/src/gitRun.js +50 -0
- package/dist-public/src/githubReconcile.d.ts +94 -0
- package/dist-public/src/githubReconcile.js +205 -0
- package/dist-public/src/gmailNango.d.ts +131 -0
- package/dist-public/src/gmailNango.js +329 -0
- package/dist-public/src/gongNango.d.ts +118 -0
- package/dist-public/src/gongNango.js +308 -0
- package/dist-public/src/grammarGate.d.ts +13 -0
- package/dist-public/src/grammarGate.js +72 -0
- package/dist-public/src/harnessGates.d.ts +65 -0
- package/dist-public/src/harnessGates.js +168 -0
- package/dist-public/src/humanSurfaceEval.d.ts +19 -0
- package/dist-public/src/humanSurfaceEval.js +156 -0
- package/dist-public/src/ideate.d.ts +43 -0
- package/dist-public/src/ideate.js +255 -0
- package/dist-public/src/ideateContext.d.ts +11 -0
- package/dist-public/src/ideateContext.js +83 -0
- package/dist-public/src/index.d.ts +2 -0
- package/dist-public/src/index.js +4 -0
- package/dist-public/src/initCommand.d.ts +25 -0
- package/dist-public/src/initCommand.js +558 -0
- package/dist-public/src/interviewGate.d.ts +25 -0
- package/dist-public/src/interviewGate.js +126 -0
- package/dist-public/src/jsonFile.d.ts +2 -0
- package/dist-public/src/jsonFile.js +22 -0
- package/dist-public/src/loopBudget.d.ts +182 -0
- package/dist-public/src/loopBudget.js +494 -0
- package/dist-public/src/loopContracts.d.ts +35 -0
- package/dist-public/src/loopContracts.js +364 -0
- package/dist-public/src/machineState.d.ts +1 -0
- package/dist-public/src/machineState.js +9 -0
- package/dist-public/src/notionNango.d.ts +93 -0
- package/dist-public/src/notionNango.js +279 -0
- package/dist-public/src/orchestrationResult.d.ts +11 -0
- package/dist-public/src/orchestrationResult.js +73 -0
- package/dist-public/src/outlookNango.d.ts +124 -0
- package/dist-public/src/outlookNango.js +327 -0
- package/dist-public/src/packetCorrections.d.ts +40 -0
- package/dist-public/src/packetCorrections.js +172 -0
- package/dist-public/src/packetGlossary.d.ts +6 -0
- package/dist-public/src/packetGlossary.js +42 -0
- package/dist-public/src/packetIndex.d.ts +54 -0
- package/dist-public/src/packetIndex.js +744 -0
- package/dist-public/src/packetIndexEntry.d.ts +3 -0
- package/dist-public/src/packetIndexEntry.js +128 -0
- package/dist-public/src/packetIndexServe.d.ts +13 -0
- package/dist-public/src/packetIndexServe.js +113 -0
- package/dist-public/src/packetIndexWorker.d.ts +7 -0
- package/dist-public/src/packetIndexWorker.js +45 -0
- package/dist-public/src/packetLifecycle.d.ts +30 -0
- package/dist-public/src/packetLifecycle.js +127 -0
- package/dist-public/src/packetReconcile.d.ts +73 -0
- package/dist-public/src/packetReconcile.js +386 -0
- package/dist-public/src/packetStatus.d.ts +125 -0
- package/dist-public/src/packetStatus.js +770 -0
- package/dist-public/src/packetValidation.d.ts +17 -0
- package/dist-public/src/packetValidation.js +333 -0
- package/dist-public/src/packetVerify.d.ts +73 -0
- package/dist-public/src/packetVerify.js +303 -0
- package/dist-public/src/packetWrite.d.ts +52 -0
- package/dist-public/src/packetWrite.js +448 -0
- package/dist-public/src/pitch.d.ts +38 -0
- package/dist-public/src/pitch.js +154 -0
- package/dist-public/src/processMemo.d.ts +8 -0
- package/dist-public/src/processMemo.js +23 -0
- package/dist-public/src/productDetect.d.ts +30 -0
- package/dist-public/src/productDetect.js +376 -0
- package/dist-public/src/profile.d.ts +62 -0
- package/dist-public/src/profile.js +334 -0
- package/dist-public/src/questionModel.d.ts +46 -0
- package/dist-public/src/questionModel.js +74 -0
- package/dist-public/src/questionText.d.ts +7 -0
- package/dist-public/src/questionText.js +38 -0
- package/dist-public/src/redactConfig.d.ts +2 -0
- package/dist-public/src/redactConfig.js +11 -0
- package/dist-public/src/redactEngine.d.ts +59 -0
- package/dist-public/src/redactEngine.js +509 -0
- package/dist-public/src/redactGate.d.ts +63 -0
- package/dist-public/src/redactGate.js +209 -0
- package/dist-public/src/repoRead.d.ts +29 -0
- package/dist-public/src/repoRead.js +160 -0
- package/dist-public/src/research.d.ts +242 -0
- package/dist-public/src/research.js +1314 -0
- package/dist-public/src/researchCompletion.d.ts +34 -0
- package/dist-public/src/researchCompletion.js +123 -0
- package/dist-public/src/researchExecution.d.ts +47 -0
- package/dist-public/src/researchExecution.js +309 -0
- package/dist-public/src/researchFormat.d.ts +21 -0
- package/dist-public/src/researchFormat.js +77 -0
- package/dist-public/src/researchGate.d.ts +86 -0
- package/dist-public/src/researchGate.js +1036 -0
- package/dist-public/src/researchReceipt.d.ts +76 -0
- package/dist-public/src/researchReceipt.js +148 -0
- package/dist-public/src/researchRender.d.ts +2 -0
- package/dist-public/src/researchRender.js +267 -0
- package/dist-public/src/researchSigningKey.d.ts +19 -0
- package/dist-public/src/researchSigningKey.js +95 -0
- package/dist-public/src/riskClassify.d.ts +42 -0
- package/dist-public/src/riskClassify.js +149 -0
- package/dist-public/src/routines.d.ts +42 -0
- package/dist-public/src/routines.js +269 -0
- package/dist-public/src/routingPolicy.d.ts +172 -0
- package/dist-public/src/routingPolicy.js +646 -0
- package/dist-public/src/secretInput.d.ts +8 -0
- package/dist-public/src/secretInput.js +89 -0
- package/dist-public/src/selfCheck.d.ts +7 -0
- package/dist-public/src/selfCheck.js +473 -0
- package/dist-public/src/selfCheckCache.d.ts +29 -0
- package/dist-public/src/selfCheckCache.js +147 -0
- package/dist-public/src/severityClass.d.ts +15 -0
- package/dist-public/src/severityClass.js +22 -0
- package/dist-public/src/skillClientPolicy.d.ts +8 -0
- package/dist-public/src/skillClientPolicy.js +16 -0
- package/dist-public/src/skillLocal.d.ts +98 -0
- package/dist-public/src/skillLocal.js +463 -0
- package/dist-public/src/skillTreeDigest.d.ts +9 -0
- package/dist-public/src/skillTreeDigest.js +64 -0
- package/dist-public/src/slackNango.d.ts +62 -0
- package/dist-public/src/slackNango.js +208 -0
- package/dist-public/src/social/arxiv.d.ts +19 -0
- package/dist-public/src/social/arxiv.js +96 -0
- package/dist-public/src/social/github.d.ts +2 -0
- package/dist-public/src/social/github.js +78 -0
- package/dist-public/src/social/hackernews.d.ts +2 -0
- package/dist-public/src/social/hackernews.js +67 -0
- package/dist-public/src/social/index.d.ts +10 -0
- package/dist-public/src/social/index.js +79 -0
- package/dist-public/src/social/reddit.d.ts +2 -0
- package/dist-public/src/social/reddit.js +125 -0
- package/dist-public/src/social/types.d.ts +73 -0
- package/dist-public/src/social/types.js +61 -0
- package/dist-public/src/social/xml.d.ts +10 -0
- package/dist-public/src/social/xml.js +49 -0
- package/dist-public/src/social/youtube.d.ts +7 -0
- package/dist-public/src/social/youtube.js +217 -0
- package/dist-public/src/sourceIngress.d.ts +488 -0
- package/dist-public/src/sourceIngress.js +1651 -0
- package/dist-public/src/specAfter.d.ts +187 -0
- package/dist-public/src/specAfter.js +814 -0
- package/dist-public/src/specBudget.d.ts +124 -0
- package/dist-public/src/specBudget.js +424 -0
- package/dist-public/src/specDecisionSignals.d.ts +38 -0
- package/dist-public/src/specDecisionSignals.js +121 -0
- package/dist-public/src/specLinkedCommits.d.ts +7 -0
- package/dist-public/src/specLinkedCommits.js +107 -0
- package/dist-public/src/specSections.d.ts +105 -0
- package/dist-public/src/specSections.js +718 -0
- package/dist-public/src/statusGlyphs.d.ts +18 -0
- package/dist-public/src/statusGlyphs.js +75 -0
- package/dist-public/src/swarmCommand.d.ts +10 -0
- package/dist-public/src/swarmCommand.js +96 -0
- package/dist-public/src/teamsNango.d.ts +114 -0
- package/dist-public/src/teamsNango.js +301 -0
- package/dist-public/src/tokenStore.d.ts +10 -0
- package/dist-public/src/tokenStore.js +77 -0
- package/dist-public/src/trustEnvelope.d.ts +78 -0
- package/dist-public/src/trustEnvelope.js +392 -0
- package/dist-public/src/untrustedText.d.ts +6 -0
- package/dist-public/src/untrustedText.js +20 -0
- package/dist-public/src/updateNotice.d.ts +41 -0
- package/dist-public/src/updateNotice.js +290 -0
- package/dist-public/src/vendorYaml.d.ts +1 -0
- package/dist-public/src/vendorYaml.js +7374 -0
- package/dist-public/src/workflowRunActuals.d.ts +67 -0
- package/dist-public/src/workflowRunActuals.js +184 -0
- package/dist-public/src/zendeskDiscovery.d.ts +12 -0
- package/dist-public/src/zendeskDiscovery.js +513 -0
- package/dist-public/src/zendeskNango.d.ts +131 -0
- package/dist-public/src/zendeskNango.js +344 -0
- package/dist-public/src/zoomNango.d.ts +106 -0
- package/dist-public/src/zoomNango.js +351 -0
- package/docs/CHANGELOG.md +32 -0
- package/docs/THIRD_PARTY_NOTICES.md +36 -0
- package/package.json +71 -4
- package/schemas/bug-capsule-receipt.schema.json +54 -0
- package/schemas/bug-capsule.schema.json +189 -0
- package/schemas/discovery-evidence-envelope.schema.json +79 -0
- package/schemas/discovery-processing-receipt.schema.json +71 -0
- package/schemas/discovery-service-contract.schema.json +189 -0
- package/skills/AGENTS.md +32 -0
- package/skills/README.md +287 -0
- package/skills/bug/SKILL.md +49 -0
- package/skills/build-preview-spec/SKILL.md +103 -0
- package/skills/capture-external-artifact/SKILL.md +23 -0
- package/skills/capture-external-artifact/agents/openai.yaml +4 -0
- package/skills/capture-external-artifact/references/extractor-libraries.md +27 -0
- package/skills/check-spec-health/SKILL.md +45 -0
- package/skills/check-spec-health/agents/openai.yaml +4 -0
- package/skills/competitive-positioning/SKILL.md +86 -0
- package/skills/competitive-positioning/agents/openai.yaml +4 -0
- package/skills/cpo-lens/SKILL.md +398 -0
- package/skills/cpo-lens/agents/openai.yaml +4 -0
- package/skills/create-prd/SKILL.md +26 -0
- package/skills/create-prd/agents/openai.yaml +4 -0
- package/skills/customer-discovery/SKILL.md +192 -0
- package/skills/design-system/SKILL.md +49 -0
- package/skills/design-system/agents/openai.yaml +4 -0
- package/skills/discussion-guide/SKILL.md +75 -0
- package/skills/discussion-guide/agents/openai.yaml +4 -0
- package/skills/firecrawl-research-papers/SKILL.md +96 -0
- package/skills/firecrawl-research-papers/agents/openai.yaml +4 -0
- package/skills/foo-roast/SKILL.md +325 -0
- package/skills/generate-gtm-brief/SKILL.md +41 -0
- package/skills/generate-gtm-brief/agents/openai.yaml +4 -0
- package/skills/generate-gtm-brief/references/gtm-brief-template.md +56 -0
- package/skills/gong-quotes/SKILL.md +43 -0
- package/skills/gong-quotes/agents/openai.yaml +4 -0
- package/skills/grill-me/SKILL.md +27 -0
- package/skills/grill-me/agents/openai.yaml +4 -0
- package/skills/ideate/SKILL.md +180 -0
- package/skills/ideate/references/family-packs.md +5 -0
- package/skills/initiative-tracker/SKILL.md +23 -0
- package/skills/initiative-tracker/agents/openai.yaml +4 -0
- package/skills/interop-review/SKILL.md +25 -0
- package/skills/interop-review/agents/openai.yaml +4 -0
- package/skills/interview-me/SKILL.md +404 -0
- package/skills/interview-me/agents/openai.yaml +4 -0
- package/skills/loop-library-audit/SKILL.md +123 -0
- package/skills/pitch/SKILL.md +110 -0
- package/skills/pitch/references/opportunity-assessment.md +136 -0
- package/skills/pitch/references/prfaq-template.md +54 -0
- package/skills/pmm-release-briefing/SKILL.md +27 -0
- package/skills/pmm-release-briefing/agents/openai.yaml +4 -0
- package/skills/pmm-release-briefing/references/variant-generalized.md +16 -0
- package/skills/positioning-messaging/SKILL.md +70 -0
- package/skills/positioning-messaging/agents/openai.yaml +4 -0
- package/skills/positioning-messaging/references/guest-insights.md +1400 -0
- package/skills/preview-swarm/SKILL.md +418 -0
- package/skills/preview-swarm/agents/openai.yaml +4 -0
- package/skills/preview-swarm/references/html-effectiveness-build-previews.md +168 -0
- package/skills/product-copywriting/SKILL.md +127 -0
- package/skills/product-copywriting/agents/openai.yaml +4 -0
- package/skills/product-copywriting/references/foo-voice.md +26 -0
- package/skills/product-shape-interview/SKILL.md +219 -0
- package/skills/product-shape-interview/agents/openai.yaml +4 -0
- package/skills/ready-for-release/SKILL.md +39 -0
- package/skills/ready-for-release/agents/openai.yaml +4 -0
- package/skills/redact-transcripts/SKILL.md +23 -0
- package/skills/redact-transcripts/agents/openai.yaml +4 -0
- package/skills/research-brief/SKILL.md +48 -0
- package/skills/research-brief/agents/openai.yaml +4 -0
- package/skills/research-refresh/SKILL.md +63 -0
- package/skills/research-refresh/references/worked-cases.md +44 -0
- package/skills/review-loop/SKILL.md +200 -0
- package/skills/review-spec/SKILL.md +32 -0
- package/skills/review-spec/agents/openai.yaml +4 -0
- package/skills/rfc-from-research/SKILL.md +42 -0
- package/skills/rfc-from-research/agents/openai.yaml +4 -0
- package/skills/rfc-from-research/references/rfc-pattern.md +69 -0
- package/skills/skill-registry.yaml +810 -0
- package/skills/spec-cleanup/SKILL.md +103 -0
- package/skills/spec-cleanup/agents/openai.yaml +4 -0
- package/skills/spec-swarm/SKILL.md +87 -0
- package/skills/spec-swarm/agents/openai.yaml +4 -0
- package/skills/spec-swarm/template/SKILL.template.md +94 -0
- package/skills/spec-swarm/template/personas/accessibility-inclusion.md +40 -0
- package/skills/spec-swarm/template/personas/ai-technical-pm.md +69 -0
- package/skills/spec-swarm/template/personas/analytics-engineering.md +39 -0
- package/skills/spec-swarm/template/personas/applied-ai-eval.md +64 -0
- package/skills/spec-swarm/template/personas/business-gm-pm.md +67 -0
- package/skills/spec-swarm/template/personas/consumer-craft-pm.md +68 -0
- package/skills/spec-swarm/template/personas/content-design.md +40 -0
- package/skills/spec-swarm/template/personas/cpo.md +42 -0
- package/skills/spec-swarm/template/personas/data-science.md +42 -0
- package/skills/spec-swarm/template/personas/developer-experience.md +65 -0
- package/skills/spec-swarm/template/personas/dx-product.md +70 -0
- package/skills/spec-swarm/template/personas/field.md +43 -0
- package/skills/spec-swarm/template/personas/finance-cfo.md +40 -0
- package/skills/spec-swarm/template/personas/growth-pm.md +67 -0
- package/skills/spec-swarm/template/personas/platform-pm.md +67 -0
- package/skills/spec-swarm/template/personas/pmm.md +43 -0
- package/skills/spec-swarm/template/personas/principal-product-designer.md +42 -0
- package/skills/spec-swarm/template/personas/product-ops-program.md +41 -0
- package/skills/spec-swarm/template/personas/qa-release.md +41 -0
- package/skills/spec-swarm/template/personas/responsible-ai-safety.md +64 -0
- package/skills/spec-swarm/template/personas/security-privacy-legal.md +40 -0
- package/skills/spec-swarm/template/personas/strategy-competitive.md +41 -0
- package/skills/spec-swarm/template/personas/technical-architect.md +42 -0
- package/skills/spec-swarm/template/personas/technical-lead.md +43 -0
- package/skills/spec-swarm/template/personas/user-research.md +41 -0
- package/skills/spec-swarm-accessibility-inclusion/SKILL.md +95 -0
- package/skills/spec-swarm-accessibility-inclusion/agents/openai.yaml +4 -0
- package/skills/spec-swarm-ai-technical-pm/SKILL.md +124 -0
- package/skills/spec-swarm-analytics-engineering/SKILL.md +94 -0
- package/skills/spec-swarm-analytics-engineering/agents/openai.yaml +4 -0
- package/skills/spec-swarm-applied-ai-eval/SKILL.md +120 -0
- package/skills/spec-swarm-business-gm-pm/SKILL.md +122 -0
- package/skills/spec-swarm-consumer-craft-pm/SKILL.md +122 -0
- package/skills/spec-swarm-content-design/SKILL.md +95 -0
- package/skills/spec-swarm-content-design/agents/openai.yaml +4 -0
- package/skills/spec-swarm-cpo/SKILL.md +94 -0
- package/skills/spec-swarm-cpo/agents/openai.yaml +4 -0
- package/skills/spec-swarm-data-science/SKILL.md +95 -0
- package/skills/spec-swarm-data-science/agents/openai.yaml +4 -0
- package/skills/spec-swarm-developer-experience/SKILL.md +121 -0
- package/skills/spec-swarm-dx-product/SKILL.md +126 -0
- package/skills/spec-swarm-field/SKILL.md +96 -0
- package/skills/spec-swarm-field/agents/openai.yaml +4 -0
- package/skills/spec-swarm-finance-cfo/SKILL.md +95 -0
- package/skills/spec-swarm-finance-cfo/agents/openai.yaml +4 -0
- package/skills/spec-swarm-growth-pm/SKILL.md +122 -0
- package/skills/spec-swarm-platform-pm/SKILL.md +122 -0
- package/skills/spec-swarm-pmm/SKILL.md +96 -0
- package/skills/spec-swarm-pmm/agents/openai.yaml +4 -0
- package/skills/spec-swarm-principal-product-designer/SKILL.md +95 -0
- package/skills/spec-swarm-principal-product-designer/agents/openai.yaml +4 -0
- package/skills/spec-swarm-product-ops-program/SKILL.md +96 -0
- package/skills/spec-swarm-product-ops-program/agents/openai.yaml +4 -0
- package/skills/spec-swarm-qa-release/SKILL.md +96 -0
- package/skills/spec-swarm-qa-release/agents/openai.yaml +4 -0
- package/skills/spec-swarm-responsible-ai-safety/SKILL.md +120 -0
- package/skills/spec-swarm-security-privacy-legal/SKILL.md +95 -0
- package/skills/spec-swarm-security-privacy-legal/agents/openai.yaml +4 -0
- package/skills/spec-swarm-strategy-competitive/SKILL.md +96 -0
- package/skills/spec-swarm-strategy-competitive/agents/openai.yaml +4 -0
- package/skills/spec-swarm-technical-architect/SKILL.md +95 -0
- package/skills/spec-swarm-technical-architect/agents/openai.yaml +4 -0
- package/skills/spec-swarm-technical-lead/SKILL.md +96 -0
- package/skills/spec-swarm-technical-lead/agents/openai.yaml +4 -0
- package/skills/spec-swarm-user-research/SKILL.md +95 -0
- package/skills/spec-swarm-user-research/agents/openai.yaml +4 -0
- package/skills/strategy-check/SKILL.md +170 -0
- package/skills/strategy-check/agents/openai.yaml +4 -0
- package/skills/study-digest/SKILL.md +41 -0
- package/skills/synthetic-customer/SKILL.md +68 -0
- package/skills/update-cli-spec/SKILL.md +69 -0
- package/skills/update-cli-spec/agents/openai.yaml +4 -0
- package/skills/voc-researcher/SKILL.md +45 -0
- package/skills/voc-researcher/agents/openai.yaml +4 -0
- package/skills-lock.json +35 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export type ModelFamily = string;
|
|
2
|
+
export type ModelConfidence = "confirmed" | "assumed";
|
|
3
|
+
export declare const UNKNOWN_FAMILY = "unknown";
|
|
4
|
+
export declare const UNKNOWN_MODEL = "unknown";
|
|
5
|
+
/**
|
|
6
|
+
* Model families foo default-denies for autonomous work (glm-model-awareness-v0
|
|
7
|
+
* R-005): weaker self-correction makes them a degraded verifier of their own
|
|
8
|
+
* loop, and the inference-egress boundary is not yet in place.
|
|
9
|
+
*
|
|
10
|
+
* This is the ONE source of truth. It used to be an inline `family === "glm"`
|
|
11
|
+
* check in the loop command, which meant `foo estimate` — knowing nothing about
|
|
12
|
+
* it — would cheerfully recommend a cheaper GLM build that `foo loop estimate
|
|
13
|
+
* --agree` then refuses. Any surface that offers a model as an option must be
|
|
14
|
+
* able to ask this question.
|
|
15
|
+
*/
|
|
16
|
+
export declare const AUTONOMY_DENIED_FAMILIES: ReadonlySet<string>;
|
|
17
|
+
export declare function autonomyDenied(family: string | undefined | null): boolean;
|
|
18
|
+
export declare const ANTHROPIC_BASE_DEFAULT = "https://api.anthropic.com";
|
|
19
|
+
export type ActiveModel = {
|
|
20
|
+
/** Friendly provider name: e.g. "anthropic" (native), "z.ai", "fireworks", or the host. */
|
|
21
|
+
provider: string;
|
|
22
|
+
/** Coarse model family (data-driven), used for pricing-key canonicalization and family signals. */
|
|
23
|
+
family: ModelFamily;
|
|
24
|
+
/** Resolved worker model id — the pricing/budget key for the acting model. */
|
|
25
|
+
worker: string;
|
|
26
|
+
/** Resolved verifier model id. */
|
|
27
|
+
verifier: string;
|
|
28
|
+
/** confirmed = explicit declaration or genuinely-native; assumed = inferred from a base URL. */
|
|
29
|
+
confidence: ModelConfidence;
|
|
30
|
+
/** Is the harness pointed off its native provider? */
|
|
31
|
+
routed: boolean;
|
|
32
|
+
/** Active API base for the harness's provider (drives count_tokens routing). */
|
|
33
|
+
baseUrl: string;
|
|
34
|
+
/** count_tokens endpoint derived from baseUrl — never a hardcoded provider literal. */
|
|
35
|
+
countTokensUrl: string;
|
|
36
|
+
/** Provenance of the resolution (which signal won). */
|
|
37
|
+
source: string;
|
|
38
|
+
/**
|
|
39
|
+
* Worded, human-readable findings: roster-data degradation and labeled
|
|
40
|
+
* "unknown model" honesty (R-003). Empty when everything resolved cleanly.
|
|
41
|
+
* Plain text only — the caller owns glyph gating.
|
|
42
|
+
*/
|
|
43
|
+
findings: string[];
|
|
44
|
+
};
|
|
45
|
+
export type RosterEntry = {
|
|
46
|
+
id: string;
|
|
47
|
+
family: string;
|
|
48
|
+
roles: readonly string[];
|
|
49
|
+
modelMarkers: readonly string[];
|
|
50
|
+
hostMarkers: readonly string[];
|
|
51
|
+
provider: string | null;
|
|
52
|
+
/** Wire format for direct panel calls (multi-model-research-panel-v0 R-005): "anthropic" | "openai" | null. */
|
|
53
|
+
wire: string | null;
|
|
54
|
+
/**
|
|
55
|
+
* Routing tier this model serves (model-orchestrator-v0 R-001). Null when the
|
|
56
|
+
* roster does not place it — the routing policy then resolves it to the
|
|
57
|
+
* conservative tier with a worded finding rather than guessing (R-013).
|
|
58
|
+
*/
|
|
59
|
+
routingTier?: string | null;
|
|
60
|
+
/** Optional per-model task-type override; empty means "whatever the tier says". */
|
|
61
|
+
routingTaskTypes?: readonly string[];
|
|
62
|
+
};
|
|
63
|
+
export type ModelRoster = {
|
|
64
|
+
/** Basename of the data file, e.g. "pricing.yaml". */
|
|
65
|
+
source: string;
|
|
66
|
+
/** False when the data file is missing/unreadable — resolution degrades, never blocks. */
|
|
67
|
+
available: boolean;
|
|
68
|
+
nativeProvider: string;
|
|
69
|
+
nativeFamily: string;
|
|
70
|
+
nativeBaseUrl: string;
|
|
71
|
+
nativeHosts: readonly string[];
|
|
72
|
+
multiModelHosts: readonly {
|
|
73
|
+
marker: string;
|
|
74
|
+
provider: string;
|
|
75
|
+
}[];
|
|
76
|
+
entries: readonly RosterEntry[];
|
|
77
|
+
/** Worded degradation findings carried into every resolution. */
|
|
78
|
+
findings: readonly string[];
|
|
79
|
+
};
|
|
80
|
+
export declare function loadModelRoster(root?: string): ModelRoster;
|
|
81
|
+
export declare function deriveCountTokensUrl(baseUrl: string): string;
|
|
82
|
+
export declare function resolveActiveModel(env?: NodeJS.ProcessEnv, roster?: ModelRoster): ActiveModel;
|
|
83
|
+
export declare function describeActiveModel(active: ActiveModel): string | null;
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
// The single authoritative active-model resolver (glm-model-awareness-v0 / T-001,
|
|
2
|
+
// R-001, D-003; data-driven since model-roster-data-v0 R-001).
|
|
3
|
+
//
|
|
4
|
+
// foo silently assumed Anthropic/Opus everywhere a model fact was needed: pricing,
|
|
5
|
+
// loop-budget estimation, and the count_tokens endpoint were all hardcoded to Claude
|
|
6
|
+
// models and api.anthropic.com. But a coding harness (Claude Code first) can be pointed
|
|
7
|
+
// at a different model via a compatible endpoint — concretely GLM served by z.ai
|
|
8
|
+
// (Anthropic-compatible) or Fireworks (OpenAI-compatible). Because of server-side model
|
|
9
|
+
// mapping the harness still reports "Claude", so the active model is invisible and foo
|
|
10
|
+
// emits a confident, Opus-priced, wrong number with no signal it is guessing.
|
|
11
|
+
//
|
|
12
|
+
// D-003 is the load-bearing rule: there is exactly ONE place that resolves the active
|
|
13
|
+
// provider/model, and every model-aware subsystem (pricing, budget key, count_tokens
|
|
14
|
+
// routing, provenance) reads only from it. No second source that can drift from the base
|
|
15
|
+
// URL the harness actually calls. This module is that source.
|
|
16
|
+
//
|
|
17
|
+
// model-roster-data-v0 R-001 moves the *constants* out: the worker/verifier roster,
|
|
18
|
+
// provider host markers, and detection hints live in the committed, dated pricing.yaml
|
|
19
|
+
// (loaded by loadModelRoster), so a model rename or a new provider is a data-only
|
|
20
|
+
// change. The resolver contract — one source, explicit precedence, honest confidence —
|
|
21
|
+
// is unchanged; this module holds zero model-name literals.
|
|
22
|
+
//
|
|
23
|
+
// Precedence (R-001): an explicit declaration wins; inference from the base URL is the
|
|
24
|
+
// fallback; native default (from the data file) is the default.
|
|
25
|
+
// 1. FOO_MODEL / FOO_ACTOR_MODEL (+ FOO_ACTOR_PROVIDER) -> confirmed
|
|
26
|
+
// 2. ANTHROPIC_BASE_URL / OPENAI_BASE_URL off a native host -> inferred, "assumed"
|
|
27
|
+
// 3. nothing routed -> native default, confirmed
|
|
28
|
+
//
|
|
29
|
+
// Confidence is honest by construction: only an explicit foo-level declaration (or the
|
|
30
|
+
// genuinely-native default) is "confirmed". Anything inferred from an endpoint override
|
|
31
|
+
// is "assumed" — because the harness's own model env may not match the provider's
|
|
32
|
+
// server-side mapping — and that drives the ⚠️ provenance tag (R-004 / T-004).
|
|
33
|
+
//
|
|
34
|
+
// Unknown-model honesty (model-roster-data-v0 R-003): a model id absent from the data
|
|
35
|
+
// file resolves as itself with a labeled "unknown model" finding and token-only
|
|
36
|
+
// handling downstream — never a silent fallback to another model's rates (the exact
|
|
37
|
+
// bug class this module was built to kill). A missing/unreadable data file degrades
|
|
38
|
+
// the same way: the resolver never blocks, it gets honest.
|
|
39
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
40
|
+
import { configPath } from "./configPath.js";
|
|
41
|
+
import { parse as parseYaml } from "./vendorYaml.js";
|
|
42
|
+
export const UNKNOWN_FAMILY = "unknown";
|
|
43
|
+
export const UNKNOWN_MODEL = "unknown";
|
|
44
|
+
/**
|
|
45
|
+
* Model families foo default-denies for autonomous work (glm-model-awareness-v0
|
|
46
|
+
* R-005): weaker self-correction makes them a degraded verifier of their own
|
|
47
|
+
* loop, and the inference-egress boundary is not yet in place.
|
|
48
|
+
*
|
|
49
|
+
* This is the ONE source of truth. It used to be an inline `family === "glm"`
|
|
50
|
+
* check in the loop command, which meant `foo estimate` — knowing nothing about
|
|
51
|
+
* it — would cheerfully recommend a cheaper GLM build that `foo loop estimate
|
|
52
|
+
* --agree` then refuses. Any surface that offers a model as an option must be
|
|
53
|
+
* able to ask this question.
|
|
54
|
+
*/
|
|
55
|
+
export const AUTONOMY_DENIED_FAMILIES = new Set(["glm"]);
|
|
56
|
+
export function autonomyDenied(family) {
|
|
57
|
+
return typeof family === "string" && AUTONOMY_DENIED_FAMILIES.has(family);
|
|
58
|
+
}
|
|
59
|
+
// Provider label (not a model name) and default base for the case where nothing is
|
|
60
|
+
// routed and the roster itself is unavailable — the harness's native endpoint.
|
|
61
|
+
const NATIVE_PROVIDER_FALLBACK = "anthropic";
|
|
62
|
+
export const ANTHROPIC_BASE_DEFAULT = "https://api.anthropic.com";
|
|
63
|
+
const ROSTER_SOURCE = "pricing.yaml";
|
|
64
|
+
function isObj(value) {
|
|
65
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
66
|
+
}
|
|
67
|
+
function strOf(value) {
|
|
68
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
69
|
+
}
|
|
70
|
+
function strArray(value) {
|
|
71
|
+
if (!Array.isArray(value))
|
|
72
|
+
return [];
|
|
73
|
+
return value.filter((item) => typeof item === "string" && item.length > 0);
|
|
74
|
+
}
|
|
75
|
+
function degradedRoster(finding) {
|
|
76
|
+
return {
|
|
77
|
+
source: ROSTER_SOURCE,
|
|
78
|
+
available: false,
|
|
79
|
+
nativeProvider: NATIVE_PROVIDER_FALLBACK,
|
|
80
|
+
nativeFamily: UNKNOWN_FAMILY,
|
|
81
|
+
nativeBaseUrl: ANTHROPIC_BASE_DEFAULT,
|
|
82
|
+
nativeHosts: [],
|
|
83
|
+
multiModelHosts: [],
|
|
84
|
+
entries: [],
|
|
85
|
+
findings: [finding],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
// Load the model roster (identity, roles, detection) from the committed data file.
|
|
89
|
+
// Missing or unreadable data degrades to an honest "unknown" roster with a worded
|
|
90
|
+
// finding — it never throws, because model *resolution* must never block (D-006:
|
|
91
|
+
// detection is a signal, not a boundary).
|
|
92
|
+
export function loadModelRoster(root = process.cwd()) {
|
|
93
|
+
const file = configPath(root, ROSTER_SOURCE);
|
|
94
|
+
if (!existsSync(file)) {
|
|
95
|
+
return degradedRoster(`model roster unavailable: ${ROSTER_SOURCE} missing at repo root or in config/ — active model resolves as unknown; token-only handling`);
|
|
96
|
+
}
|
|
97
|
+
let doc;
|
|
98
|
+
try {
|
|
99
|
+
doc = parseYaml(readFileSync(file, "utf8"));
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
return degradedRoster(`model roster unavailable: ${ROSTER_SOURCE} unreadable (${error instanceof Error ? error.message : String(error)}) — active model resolves as unknown; token-only handling`);
|
|
103
|
+
}
|
|
104
|
+
if (!isObj(doc))
|
|
105
|
+
return degradedRoster(`model roster unavailable: ${ROSTER_SOURCE} is not a mapping — active model resolves as unknown; token-only handling`);
|
|
106
|
+
const roster = isObj(doc.roster) ? doc.roster : {};
|
|
107
|
+
const providers = isObj(doc.providers) ? doc.providers : {};
|
|
108
|
+
const models = isObj(doc.models) ? doc.models : {};
|
|
109
|
+
const entries = Object.entries(models).map(([id, raw]) => {
|
|
110
|
+
const model = isObj(raw) ? raw : {};
|
|
111
|
+
const detect = isObj(model.detect) ? model.detect : {};
|
|
112
|
+
const routing = isObj(model.routing) ? model.routing : {};
|
|
113
|
+
return {
|
|
114
|
+
id,
|
|
115
|
+
family: strOf(model.family) ?? UNKNOWN_FAMILY,
|
|
116
|
+
roles: strArray(model.roles),
|
|
117
|
+
modelMarkers: strArray(detect.model_markers).map((m) => m.toLowerCase()),
|
|
118
|
+
hostMarkers: strArray(detect.host_markers).map((m) => m.toLowerCase()),
|
|
119
|
+
provider: strOf(detect.provider),
|
|
120
|
+
wire: strOf(model.wire),
|
|
121
|
+
routingTier: strOf(routing.tier),
|
|
122
|
+
routingTaskTypes: strArray(routing.task_types),
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
const multiModelHosts = (Array.isArray(providers.multi_model_hosts) ? providers.multi_model_hosts : [])
|
|
126
|
+
.filter(isObj)
|
|
127
|
+
.map((entry) => ({ marker: strOf(entry.marker) ?? "", provider: strOf(entry.provider) ?? "" }))
|
|
128
|
+
.filter((entry) => entry.marker.length > 0 && entry.provider.length > 0);
|
|
129
|
+
const findings = [];
|
|
130
|
+
if (entries.length === 0) {
|
|
131
|
+
findings.push(`model roster degraded: ${ROSTER_SOURCE} has no models — active model resolves as unknown; token-only handling`);
|
|
132
|
+
}
|
|
133
|
+
else if (!entries.some((entry) => entry.family !== UNKNOWN_FAMILY)) {
|
|
134
|
+
findings.push(`model roster degraded: ${ROSTER_SOURCE} models carry no roster fields (family/roles/detect) — detection limited`);
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
source: ROSTER_SOURCE,
|
|
138
|
+
available: true,
|
|
139
|
+
nativeProvider: strOf(roster.native_provider) ?? NATIVE_PROVIDER_FALLBACK,
|
|
140
|
+
nativeFamily: strOf(roster.native_family) ?? UNKNOWN_FAMILY,
|
|
141
|
+
nativeBaseUrl: strOf(roster.native_base_url) ?? ANTHROPIC_BASE_DEFAULT,
|
|
142
|
+
nativeHosts: strArray(providers.native_hosts).map((h) => h.toLowerCase()),
|
|
143
|
+
multiModelHosts,
|
|
144
|
+
entries,
|
|
145
|
+
findings,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
// --- Resolution helpers (all read only the roster data) ----------------------
|
|
149
|
+
function hostOf(url) {
|
|
150
|
+
const trimmed = url?.trim();
|
|
151
|
+
if (!trimmed)
|
|
152
|
+
return null;
|
|
153
|
+
try {
|
|
154
|
+
return new URL(trimmed).host.toLowerCase();
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
const match = trimmed.replace(/^https?:\/\//, "").replace(/^\/+/, "").match(/^([^/]+)/);
|
|
158
|
+
return match ? match[1].toLowerCase() : null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function providerFromHost(roster, host) {
|
|
162
|
+
for (const entry of roster.entries) {
|
|
163
|
+
if (entry.hostMarkers.some((marker) => host.includes(marker)))
|
|
164
|
+
return entry.provider ?? entry.family;
|
|
165
|
+
}
|
|
166
|
+
for (const multi of roster.multiModelHosts) {
|
|
167
|
+
if (host.includes(multi.marker))
|
|
168
|
+
return multi.provider;
|
|
169
|
+
}
|
|
170
|
+
return host;
|
|
171
|
+
}
|
|
172
|
+
// Family detection: a model id/hint marker wins over a host marker (a multi-model
|
|
173
|
+
// host only means a family when the model id says so — that ordering is why e.g.
|
|
174
|
+
// Fireworks carries no host marker in the data file).
|
|
175
|
+
function detectFamily(roster, host, modelHint) {
|
|
176
|
+
const hint = modelHint?.toLowerCase() ?? null;
|
|
177
|
+
if (hint) {
|
|
178
|
+
for (const entry of roster.entries) {
|
|
179
|
+
if (entry.modelMarkers.some((marker) => hint.includes(marker)))
|
|
180
|
+
return entry.family;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (host) {
|
|
184
|
+
for (const entry of roster.entries) {
|
|
185
|
+
if (entry.hostMarkers.some((marker) => host.includes(marker)))
|
|
186
|
+
return entry.family;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return UNKNOWN_FAMILY;
|
|
190
|
+
}
|
|
191
|
+
// The family's default worker/verifier mix, from per-model `roles` in the data file.
|
|
192
|
+
function familyRoster(roster, family) {
|
|
193
|
+
if (family === UNKNOWN_FAMILY)
|
|
194
|
+
return { worker: null, verifier: null };
|
|
195
|
+
const inFamily = roster.entries.filter((entry) => entry.family === family);
|
|
196
|
+
return {
|
|
197
|
+
worker: inFamily.find((entry) => entry.roles.includes("worker"))?.id ?? null,
|
|
198
|
+
verifier: inFamily.find((entry) => entry.roles.includes("verifier"))?.id ?? null,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
// Friendly provider label for an unrouted family (e.g. a declared GLM model with no
|
|
202
|
+
// base-URL override reads its provider from the family's detection entry).
|
|
203
|
+
function familyProvider(roster, family) {
|
|
204
|
+
if (family === UNKNOWN_FAMILY)
|
|
205
|
+
return null;
|
|
206
|
+
return roster.entries.find((entry) => entry.family === family && entry.provider)?.provider ?? null;
|
|
207
|
+
}
|
|
208
|
+
function isKnownModel(roster, id) {
|
|
209
|
+
return roster.entries.some((entry) => entry.id === id);
|
|
210
|
+
}
|
|
211
|
+
// R-003 unknown-model honesty: label anything the data file cannot vouch for.
|
|
212
|
+
function modelFindings(roster, worker, verifier) {
|
|
213
|
+
const findings = [...roster.findings];
|
|
214
|
+
const flag = (id) => {
|
|
215
|
+
if (id === UNKNOWN_MODEL) {
|
|
216
|
+
findings.push("unknown model: the active model could not be resolved (no declaration, no roster match) — token-only handling, no default-model rates assumed");
|
|
217
|
+
}
|
|
218
|
+
else if (roster.available && !isKnownModel(roster, id)) {
|
|
219
|
+
findings.push(`unknown model: ${id} is not in ${roster.source} — token-only handling, no default-model rates assumed`);
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
flag(worker);
|
|
223
|
+
if (verifier !== worker)
|
|
224
|
+
flag(verifier);
|
|
225
|
+
return [...new Set(findings)];
|
|
226
|
+
}
|
|
227
|
+
// Derive the count_tokens endpoint from the active base URL (R-003). The Anthropic-shaped
|
|
228
|
+
// path (z.ai mirrors it under /api/anthropic) is `<base>/v1/messages/count_tokens`. This is
|
|
229
|
+
// the only place that endpoint is built, so it always follows the harness.
|
|
230
|
+
export function deriveCountTokensUrl(baseUrl) {
|
|
231
|
+
return `${baseUrl.replace(/\/+$/, "")}/v1/messages/count_tokens`;
|
|
232
|
+
}
|
|
233
|
+
// Resolve the active provider/model from the single source. Reads the environment and
|
|
234
|
+
// the committed roster data only; pure given (env, roster) and testable. Every
|
|
235
|
+
// model-aware subsystem calls this and nothing else.
|
|
236
|
+
export function resolveActiveModel(env = process.env, roster = loadModelRoster()) {
|
|
237
|
+
const declaredModel = env.FOO_MODEL?.trim() || env.FOO_ACTOR_MODEL?.trim() || null;
|
|
238
|
+
const declaredProvider = env.FOO_ACTOR_PROVIDER?.trim() || null;
|
|
239
|
+
const nativeHosts = new Set(roster.nativeHosts);
|
|
240
|
+
const anthropicHost = hostOf(env.ANTHROPIC_BASE_URL);
|
|
241
|
+
const openaiHost = hostOf(env.OPENAI_BASE_URL ?? env.OPENAI_API_BASE);
|
|
242
|
+
let routedHost = null;
|
|
243
|
+
let routedBase = null;
|
|
244
|
+
let routedSource = null;
|
|
245
|
+
if (anthropicHost && !nativeHosts.has(anthropicHost)) {
|
|
246
|
+
routedHost = anthropicHost;
|
|
247
|
+
routedBase = (env.ANTHROPIC_BASE_URL ?? "").trim();
|
|
248
|
+
routedSource = "ANTHROPIC_BASE_URL";
|
|
249
|
+
}
|
|
250
|
+
else if (openaiHost && !nativeHosts.has(openaiHost)) {
|
|
251
|
+
routedHost = openaiHost;
|
|
252
|
+
routedBase = (env.OPENAI_BASE_URL ?? env.OPENAI_API_BASE ?? "").trim();
|
|
253
|
+
routedSource = env.OPENAI_BASE_URL ? "OPENAI_BASE_URL" : "OPENAI_API_BASE";
|
|
254
|
+
}
|
|
255
|
+
const routed = Boolean(routedHost);
|
|
256
|
+
const harnessModelHint = env.ANTHROPIC_MODEL?.trim() || env.OPENAI_MODEL?.trim() || null;
|
|
257
|
+
// 1. Explicit declaration wins — confirmed. The declared id is honored as-is: an id
|
|
258
|
+
// the data file does not know gets an "unknown model" finding (R-003), never a
|
|
259
|
+
// silent canonicalization onto another model's pricing key.
|
|
260
|
+
if (declaredModel) {
|
|
261
|
+
const family = detectFamily(roster, routedHost, declaredModel);
|
|
262
|
+
const mix = familyRoster(roster, family);
|
|
263
|
+
const worker = declaredModel;
|
|
264
|
+
const verifier = isKnownModel(roster, declaredModel) ? mix.verifier ?? declaredModel : declaredModel;
|
|
265
|
+
const provider = declaredProvider ??
|
|
266
|
+
(routedHost ? providerFromHost(roster, routedHost) : familyProvider(roster, family) ?? roster.nativeProvider);
|
|
267
|
+
const baseUrl = routedBase || roster.nativeBaseUrl;
|
|
268
|
+
return {
|
|
269
|
+
provider,
|
|
270
|
+
family,
|
|
271
|
+
worker,
|
|
272
|
+
verifier,
|
|
273
|
+
confidence: "confirmed",
|
|
274
|
+
routed,
|
|
275
|
+
baseUrl,
|
|
276
|
+
countTokensUrl: deriveCountTokensUrl(baseUrl),
|
|
277
|
+
source: env.FOO_MODEL ? "FOO_MODEL" : "FOO_ACTOR_MODEL",
|
|
278
|
+
findings: modelFindings(roster, worker, verifier),
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
// 2. Inference from a base-URL override — assumed (the honest tag). A recognized
|
|
282
|
+
// family resolves to that family's roster mix (server-side mapping makes the raw
|
|
283
|
+
// hint unreliable, so the family pricing key is the honest resolution); an
|
|
284
|
+
// unrecognized one resolves to the hint or "unknown" with a finding.
|
|
285
|
+
if (routed && routedHost && routedBase) {
|
|
286
|
+
const family = detectFamily(roster, routedHost, harnessModelHint);
|
|
287
|
+
const mix = familyRoster(roster, family);
|
|
288
|
+
const worker = mix.worker ?? harnessModelHint ?? UNKNOWN_MODEL;
|
|
289
|
+
const verifier = mix.verifier ?? harnessModelHint ?? UNKNOWN_MODEL;
|
|
290
|
+
return {
|
|
291
|
+
provider: providerFromHost(roster, routedHost),
|
|
292
|
+
family,
|
|
293
|
+
worker,
|
|
294
|
+
verifier,
|
|
295
|
+
confidence: "assumed",
|
|
296
|
+
routed: true,
|
|
297
|
+
baseUrl: routedBase,
|
|
298
|
+
countTokensUrl: deriveCountTokensUrl(routedBase),
|
|
299
|
+
source: `${routedSource} (server-side model mapping may differ)`,
|
|
300
|
+
findings: modelFindings(roster, worker, verifier),
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
// 3. Native default — from the data file. Confirmed only when the roster actually
|
|
304
|
+
// vouches for the native mix; a degraded roster resolves honestly as unknown.
|
|
305
|
+
const family = roster.nativeFamily;
|
|
306
|
+
const mix = familyRoster(roster, family);
|
|
307
|
+
const worker = mix.worker ?? UNKNOWN_MODEL;
|
|
308
|
+
const verifier = mix.verifier ?? worker;
|
|
309
|
+
return {
|
|
310
|
+
provider: roster.nativeProvider,
|
|
311
|
+
family,
|
|
312
|
+
worker,
|
|
313
|
+
verifier,
|
|
314
|
+
confidence: worker === UNKNOWN_MODEL ? "assumed" : "confirmed",
|
|
315
|
+
routed: false,
|
|
316
|
+
baseUrl: roster.nativeBaseUrl,
|
|
317
|
+
countTokensUrl: deriveCountTokensUrl(roster.nativeBaseUrl),
|
|
318
|
+
source: "native default",
|
|
319
|
+
findings: modelFindings(roster, worker, verifier),
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
// One-line, human-only provenance description. Returns null when the active model is the
|
|
323
|
+
// genuinely-native default with nothing to flag (no signal worth showing). The caller owns
|
|
324
|
+
// glyph-gating (TTY-only, never into --json/contracts) — this returns plain text.
|
|
325
|
+
export function describeActiveModel(active) {
|
|
326
|
+
if (!active.routed && active.confidence === "confirmed" && active.findings.length === 0)
|
|
327
|
+
return null;
|
|
328
|
+
const tag = active.confidence === "assumed" ? "model: unconfirmed" : `model: ${active.worker}`;
|
|
329
|
+
const where = active.routed ? `routed to ${active.provider}` : `native ${active.provider}`;
|
|
330
|
+
return `${where} — ${tag} (${active.family}); pricing/token follow the active model`;
|
|
331
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
export type RuntimeId = "claude" | "codex" | "cursor" | "github-actions";
|
|
2
|
+
export type AdapterSupport = "supported" | "planned";
|
|
3
|
+
export type TriggerKind = "manual" | "schedule" | "event";
|
|
4
|
+
export interface AgentAdapter {
|
|
5
|
+
id: RuntimeId;
|
|
6
|
+
label: string;
|
|
7
|
+
/** supported = productfoo can emit a working binding today; planned = mapped, not yet emitted. */
|
|
8
|
+
support: AdapterSupport;
|
|
9
|
+
/** Runtime config home, where a committed binding would live. null when external (e.g. CI). */
|
|
10
|
+
config_dir: string | null;
|
|
11
|
+
/** Can this runtime run one routine pass non-interactively? Required for any unattended trigger. */
|
|
12
|
+
can_run_headless: boolean;
|
|
13
|
+
/** Trigger kinds this runtime can arm natively. */
|
|
14
|
+
trigger_mechanisms: TriggerKind[];
|
|
15
|
+
/**
|
|
16
|
+
* Headless invocation template for one pass. {prompt} is the routine's pass
|
|
17
|
+
* instruction; {packet} is the packet dir. null when the runtime cannot yet
|
|
18
|
+
* be driven headless. Templates are illustrative bindings, not a promise the
|
|
19
|
+
* binary exists on PATH — the emitted artifact is reviewed before it is armed.
|
|
20
|
+
*/
|
|
21
|
+
invoke_template: string | null;
|
|
22
|
+
/** What we would need to fit this runtime fully (the honest gap). */
|
|
23
|
+
notes: string;
|
|
24
|
+
}
|
|
25
|
+
export type HarnessAdapterStatus = "ready" | "missing" | "drift" | "unsupported";
|
|
26
|
+
export type HarnessAdapterId = "codex" | "claude-code" | "cursor" | "opencode" | "grok";
|
|
27
|
+
export type HarnessCommandFormat = "markdown" | "toml";
|
|
28
|
+
export type HarnessCommandSupport = "supported" | "planned";
|
|
29
|
+
export interface HarnessCommandDirs {
|
|
30
|
+
global: string | null;
|
|
31
|
+
project: string | null;
|
|
32
|
+
}
|
|
33
|
+
export interface HarnessCommandAdapter {
|
|
34
|
+
id: HarnessAdapterId;
|
|
35
|
+
label: string;
|
|
36
|
+
/** The real per-scope command directories. Replaces the aspirational shared `.agents/commands`. */
|
|
37
|
+
commandsDir: HarnessCommandDirs;
|
|
38
|
+
/** Filename extension for emitted command files: ".md" | ".prompt.md" | ".toml". */
|
|
39
|
+
commandExtension: string;
|
|
40
|
+
/** Content format productfoo must emit. "markdown" ships today; "toml" is not yet emittable. */
|
|
41
|
+
commandFormat: HarnessCommandFormat;
|
|
42
|
+
/** Plugin skills use <id>/SKILL.md instead of flat command files. */
|
|
43
|
+
commandLayout?: "flat" | "skills";
|
|
44
|
+
/**
|
|
45
|
+
* Command-surface support (D-002): "supported" = directory AND format are
|
|
46
|
+
* verified and emittable; "planned" = mapped honestly but NOT installed
|
|
47
|
+
* (unverified dir or un-emittable format). `unsupportedReason` names the gap.
|
|
48
|
+
*/
|
|
49
|
+
support: HarnessCommandSupport;
|
|
50
|
+
unsupportedReason?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Flat (non-plugin) harnesses prefix productfoo's commands (e.g. `foo-spec`) so they
|
|
53
|
+
* group together and cannot collide with a user's own `/spec`. Plugin harnesses
|
|
54
|
+
* namespace instead and leave this unset.
|
|
55
|
+
*/
|
|
56
|
+
commandPrefix?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Setup/readiness path for the command surface. This is an adapter surface,
|
|
59
|
+
* not a productfoo core dependency; unknown harnesses can still call `foo` directly.
|
|
60
|
+
*/
|
|
61
|
+
projectPath: string;
|
|
62
|
+
/**
|
|
63
|
+
* Namespaced command wrapper, when a harness supports a plugin-like command
|
|
64
|
+
* surface. Plain command adapters leave this unset and use the `commandPrefix`
|
|
65
|
+
* convention instead.
|
|
66
|
+
*/
|
|
67
|
+
plugin?: {
|
|
68
|
+
dir: string;
|
|
69
|
+
name: string;
|
|
70
|
+
manifestRelPath: string;
|
|
71
|
+
};
|
|
72
|
+
/** Personal Codex marketplace entry required to install this plugin. */
|
|
73
|
+
marketplace?: {
|
|
74
|
+
manifestRelPath: string;
|
|
75
|
+
name: string;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Directory-derived namespace: the harness types commands as /<ns>:<id>
|
|
79
|
+
* because they live in a subdirectory named <ns> of its native commands dir
|
|
80
|
+
* (no plugin, no registration). Mutually exclusive with `plugin`.
|
|
81
|
+
*/
|
|
82
|
+
commandNamespace?: string;
|
|
83
|
+
/**
|
|
84
|
+
* Namespace the HARNESS imposes in its own slash menu, independent of where
|
|
85
|
+
* the files sit. Unlike `commandNamespace`, this never affects a path.
|
|
86
|
+
* Retained for flat adapters that impose their own menu namespace.
|
|
87
|
+
*/
|
|
88
|
+
invocationNamespace?: string;
|
|
89
|
+
/**
|
|
90
|
+
* Commands to exclude from this harness (e.g., "bug" for third-party bots).
|
|
91
|
+
* When set, setup skips these command IDs for this adapter only.
|
|
92
|
+
*/
|
|
93
|
+
excludedCommands?: readonly string[];
|
|
94
|
+
/**
|
|
95
|
+
* Paths written by older productfoo adapter versions. Setup removes only productfoo-managed
|
|
96
|
+
* files/symlinks at these paths so harness-specific shims do not leak into
|
|
97
|
+
* the core contract.
|
|
98
|
+
*/
|
|
99
|
+
legacyPaths: string[];
|
|
100
|
+
legacyCommandsDir?: string;
|
|
101
|
+
legacyCommandPrefix?: string;
|
|
102
|
+
/** A retired plugin install dir (manifest + commands) that setup migrates away from. */
|
|
103
|
+
legacyPluginDir?: string;
|
|
104
|
+
}
|
|
105
|
+
export type HarnessCommandTarget = {
|
|
106
|
+
supported: true;
|
|
107
|
+
dir: string;
|
|
108
|
+
extension: string;
|
|
109
|
+
format: HarnessCommandFormat;
|
|
110
|
+
prefix: string;
|
|
111
|
+
} | {
|
|
112
|
+
supported: false;
|
|
113
|
+
reason: string;
|
|
114
|
+
};
|
|
115
|
+
export declare function resolveHarnessCommandTarget(adapter: HarnessCommandAdapter, scope: "global" | "project"): HarnessCommandTarget;
|
|
116
|
+
export declare const AGENT_ADAPTERS: Record<RuntimeId, AgentAdapter>;
|
|
117
|
+
export declare const HARNESS_COMMAND_ADAPTERS: Record<HarnessAdapterId, HarnessCommandAdapter>;
|
|
118
|
+
export declare function getAdapter(id: string): AgentAdapter | undefined;
|
|
119
|
+
export declare function supportedRuntimes(): RuntimeId[];
|
|
120
|
+
export declare function knownRuntimes(): RuntimeId[];
|
|
121
|
+
export declare function knownHarnessCommandAdapters(): HarnessAdapterId[];
|
|
122
|
+
export declare function getHarnessCommandAdapter(id: string): HarnessCommandAdapter | undefined;
|