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,128 @@
|
|
|
1
|
+
// Per-packet index derivation (cli-performance-v0 R-001).
|
|
2
|
+
//
|
|
3
|
+
// One module on purpose: the serial path in packetIndex.ts and the worker
|
|
4
|
+
// threads (packetIndexWorker.ts) must run the exact same reader, or the two
|
|
5
|
+
// paths drift. Each packet's tasks.yaml is read once and parsed once, spec.md
|
|
6
|
+
// is read once, and every derivation below consumes those single results —
|
|
7
|
+
// previously five reads + two YAML parses per packet (720 readFileSync across
|
|
8
|
+
// 141 packets, with 68% of self-time in the YAML parser).
|
|
9
|
+
//
|
|
10
|
+
// Pure with respect to the repo tree: reads only the packet's own files (plus
|
|
11
|
+
// the retired-packet verdict tail of events.jsonl). Throws on malformed input;
|
|
12
|
+
// callers decide the rendering.
|
|
13
|
+
import { readFileSync } from "node:fs";
|
|
14
|
+
import path from "node:path";
|
|
15
|
+
import { parse as parseYaml } from "./vendorYaml.js";
|
|
16
|
+
import { isRetired } from "./packetLifecycle.js";
|
|
17
|
+
import { derivePacketStatusFromInputs } from "./packetStatus.js";
|
|
18
|
+
import { deriveSpecDecisionSignals } from "./specDecisionSignals.js";
|
|
19
|
+
export function readPacketInput(dir, file) {
|
|
20
|
+
try {
|
|
21
|
+
return readFileSync(path.join(dir, file), "utf8");
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
// Mirror the shared reader's canonical missing-file message so a packet
|
|
25
|
+
// whose file vanishes between listing and reading renders the same error
|
|
26
|
+
// row `derivePacketStatus` produced before the refactor (exported for the
|
|
27
|
+
// malformed-input tests that pin this message).
|
|
28
|
+
if (error.code === "ENOENT")
|
|
29
|
+
throw new Error(`${file} missing in ${dir}`);
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function asRecord(value) {
|
|
34
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
35
|
+
}
|
|
36
|
+
function str(value) {
|
|
37
|
+
return typeof value === "string" && value.trim() !== "" ? value.trim() : null;
|
|
38
|
+
}
|
|
39
|
+
// The task list comes from the shared derivePacketStatus reader (D-002), fed
|
|
40
|
+
// the already-parsed tasks.yaml; the only field this index still reads from
|
|
41
|
+
// that document directly is `updated`.
|
|
42
|
+
function updatedFromTasksDoc(tasksDoc) {
|
|
43
|
+
return str(asRecord(tasksDoc).updated);
|
|
44
|
+
}
|
|
45
|
+
function readIntent(specText) {
|
|
46
|
+
let inIntent = false;
|
|
47
|
+
for (const line of specText.split(/\r?\n/)) {
|
|
48
|
+
if (/^##\s+/.test(line)) {
|
|
49
|
+
inIntent = /^##\s+Intent\s*$/i.test(line);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (inIntent && line.trim() !== "") {
|
|
53
|
+
const sentence = line.trim().split(/(?<=[.!?])\s/)[0];
|
|
54
|
+
return sentence.length > 180 ? `${sentence.slice(0, 177)}...` : sentence;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
function readDecisionSignals(root, packetDir, specText) {
|
|
60
|
+
return deriveSpecDecisionSignals(specText, path.relative(root, path.join(packetDir, "spec.md")));
|
|
61
|
+
}
|
|
62
|
+
function bucketOf(s) {
|
|
63
|
+
// A retirement verdict outranks task math: a killed packet with 0/7 done is
|
|
64
|
+
// not "open" backlog, it is retired intent (packet-lifecycle-v0 R-003).
|
|
65
|
+
if (isRetired(s.lifecycle))
|
|
66
|
+
return "retired";
|
|
67
|
+
if (s.tasks.total > 0 && s.tasks.done === s.tasks.total)
|
|
68
|
+
return "proven";
|
|
69
|
+
if (s.tasks.done === 0 && s.tasks.doing === 0)
|
|
70
|
+
return "open";
|
|
71
|
+
return "progress";
|
|
72
|
+
}
|
|
73
|
+
// Derive one packet's index entry: the single-pass read/parse/derive unit.
|
|
74
|
+
// A malformed packet never throws out of here — it renders as an error row
|
|
75
|
+
// (blank status + the error message), exactly as the index always rendered.
|
|
76
|
+
export function derivePacketEntry(root, dir) {
|
|
77
|
+
try {
|
|
78
|
+
// Single pass (R-001): read tasks.yaml once, parse it once, read spec.md
|
|
79
|
+
// once — every derivation below consumes those results.
|
|
80
|
+
const tasksDoc = parseYaml(readPacketInput(dir, "tasks.yaml"));
|
|
81
|
+
const specText = readPacketInput(dir, "spec.md");
|
|
82
|
+
const status = derivePacketStatusFromInputs(dir, { tasksDoc, specText });
|
|
83
|
+
return {
|
|
84
|
+
...status,
|
|
85
|
+
updated: updatedFromTasksDoc(tasksDoc),
|
|
86
|
+
intent: readIntent(specText),
|
|
87
|
+
decision_signals: readDecisionSignals(root, dir, specText),
|
|
88
|
+
bucket: bucketOf(status),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
const blank = {
|
|
93
|
+
packet: path.basename(dir),
|
|
94
|
+
spec_id: path.basename(dir),
|
|
95
|
+
title: null,
|
|
96
|
+
lifecycle: null,
|
|
97
|
+
lifecycle_stored: null,
|
|
98
|
+
lifecycle_effective: "in_flight",
|
|
99
|
+
lifecycle_drift: false,
|
|
100
|
+
stage: null,
|
|
101
|
+
mode: null,
|
|
102
|
+
tasks: { total: 0, done: 0, doing: 0, blocked: 0, todo: 0, dropped: 0 },
|
|
103
|
+
proof: { checks_total: 0, checks_done: 0 },
|
|
104
|
+
requirements: { total: 0, covered: 0 },
|
|
105
|
+
requirement_priorities: {},
|
|
106
|
+
completed: [],
|
|
107
|
+
task_list: [],
|
|
108
|
+
blocked: [],
|
|
109
|
+
stale: [],
|
|
110
|
+
open_questions: [],
|
|
111
|
+
next_action: { kind: "none", reason: "Packet status could not be read." },
|
|
112
|
+
decision_findings: [],
|
|
113
|
+
next: null,
|
|
114
|
+
drift: { restamp: false },
|
|
115
|
+
verdict: null,
|
|
116
|
+
deep_checked: false,
|
|
117
|
+
};
|
|
118
|
+
return {
|
|
119
|
+
...blank,
|
|
120
|
+
updated: null,
|
|
121
|
+
intent: null,
|
|
122
|
+
decision_signals: deriveSpecDecisionSignals(""),
|
|
123
|
+
task_list: [],
|
|
124
|
+
bucket: "open",
|
|
125
|
+
error: error instanceof Error ? error.message : String(error),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Server } from "node:http";
|
|
2
|
+
import { type PacketIndexEntry } from "./packetIndex.js";
|
|
3
|
+
export declare const DEFAULT_SERVE_PORT = 8000;
|
|
4
|
+
export declare const DEFAULT_SERVE_HOST = "127.0.0.1";
|
|
5
|
+
export declare function indexStateHash(index: PacketIndexEntry[]): string;
|
|
6
|
+
export declare function injectLiveReload(html: string, pollMs?: number): string;
|
|
7
|
+
export interface ServeOptions {
|
|
8
|
+
port?: number;
|
|
9
|
+
pollMs?: number;
|
|
10
|
+
host?: string;
|
|
11
|
+
deriveIndex?: (root: string) => PacketIndexEntry[];
|
|
12
|
+
}
|
|
13
|
+
export declare function serveIndex(root: string, options?: ServeOptions): Server;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Live mode for the packet index (packet_index_v0). Serves the same
|
|
2
|
+
// self-contained HTML that `--html` writes, but re-rendered from each packet's
|
|
3
|
+
// tasks.yaml on every request, and tells the browser to reload only when the
|
|
4
|
+
// derived spec state actually changes — so an open rollover does not collapse on
|
|
5
|
+
// a timer. Read-only: it renders from disk and writes nothing.
|
|
6
|
+
import { createServer } from "node:http";
|
|
7
|
+
import { createHash } from "node:crypto";
|
|
8
|
+
import { readdirSync, statSync } from "node:fs";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import { derivePacketIndex, renderIndexHtml } from "./packetIndex.js";
|
|
11
|
+
export const DEFAULT_SERVE_PORT = 8000;
|
|
12
|
+
// Bind to loopback by default: the dashboard is unauthenticated, so it must not
|
|
13
|
+
// be reachable from the local network (security-review-remediation-v0 R-003).
|
|
14
|
+
export const DEFAULT_SERVE_HOST = "127.0.0.1";
|
|
15
|
+
const DEFAULT_POLL_MS = 2000;
|
|
16
|
+
// A content fingerprint of the derived index. The browser reloads only when this
|
|
17
|
+
// changes, so formatting-stable polls never thrash the page.
|
|
18
|
+
export function indexStateHash(index) {
|
|
19
|
+
return createHash("sha1").update(JSON.stringify(index)).digest("hex");
|
|
20
|
+
}
|
|
21
|
+
// Inject a poll-and-reload client before </body>. It reloads only when the state
|
|
22
|
+
// hash changes, preserving scroll and open rollovers until something moves.
|
|
23
|
+
export function injectLiveReload(html, pollMs = DEFAULT_POLL_MS) {
|
|
24
|
+
const script = [
|
|
25
|
+
"<script>",
|
|
26
|
+
"(function(){var last=null;",
|
|
27
|
+
"function tick(){",
|
|
28
|
+
"fetch('/__state',{cache:'no-store'}).then(function(r){return r.json();}).then(function(s){",
|
|
29
|
+
"if(last!==null&&s.hash!==last){location.reload();return;}",
|
|
30
|
+
"last=s.hash;setTimeout(tick," + pollMs + ");",
|
|
31
|
+
"}).catch(function(){setTimeout(tick," + pollMs + ");});",
|
|
32
|
+
"}tick();})();",
|
|
33
|
+
"</script>",
|
|
34
|
+
].join("");
|
|
35
|
+
return html.includes("</body>") ? html.replace("</body>", `${script}\n</body>`) : html + script;
|
|
36
|
+
}
|
|
37
|
+
// A cheap fingerprint of everything derivePacketIndex reads: the recursive
|
|
38
|
+
// shape of <root>/specs, hashed from each file's relative path, mtime, and
|
|
39
|
+
// size. Statting ~3 files per packet is far cheaper than re-reading and
|
|
40
|
+
// re-parsing them, so an unchanged specs tree (the common case for an open
|
|
41
|
+
// dashboard) can skip re-derivation entirely (cli-performance-v0 R-004).
|
|
42
|
+
// Deterministic within the walk: entries are sorted so directory order never
|
|
43
|
+
// leaks into the hash. Throws (ENOENT) when specs/ is missing — the request
|
|
44
|
+
// handler's generic 500 path, same as a failing derivation.
|
|
45
|
+
function specsTreeFingerprint(root) {
|
|
46
|
+
const specsDir = path.join(root, "specs");
|
|
47
|
+
const hash = createHash("sha1");
|
|
48
|
+
const walk = (dir, rel) => {
|
|
49
|
+
const entries = readdirSync(dir, { withFileTypes: true }).sort((a, b) => (a.name < b.name ? -1 : 1));
|
|
50
|
+
for (const entry of entries) {
|
|
51
|
+
const relPath = rel ? `${rel}/${entry.name}` : entry.name;
|
|
52
|
+
const abs = path.join(dir, entry.name);
|
|
53
|
+
if (entry.isDirectory()) {
|
|
54
|
+
walk(abs, relPath);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (!entry.isFile())
|
|
58
|
+
continue;
|
|
59
|
+
const stats = statSync(abs);
|
|
60
|
+
hash.update(`${relPath}\0${stats.mtimeMs}\0${stats.size}\0`);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
walk(specsDir, "");
|
|
64
|
+
return hash.digest("hex");
|
|
65
|
+
}
|
|
66
|
+
// Start the live dashboard server and return the listening server so callers
|
|
67
|
+
// (and tests) can read its address and close it. The index is derived from disk
|
|
68
|
+
// at most once per change to the specs tree: a state check re-derives only when
|
|
69
|
+
// the fingerprint moves, and the page render reuses the same derivation — so
|
|
70
|
+
// uncommitted tasks.yaml edits still show up immediately, but an unchanged poll
|
|
71
|
+
// costs a directory stat walk, not a full re-derivation (cli-performance-v0 R-004).
|
|
72
|
+
export function serveIndex(root, options = {}) {
|
|
73
|
+
const pollMs = options.pollMs ?? DEFAULT_POLL_MS;
|
|
74
|
+
const derive = options.deriveIndex ?? derivePacketIndex;
|
|
75
|
+
// Per-server cache, not module state: parallel servers (tests, two roots)
|
|
76
|
+
// must never see each other's derivations.
|
|
77
|
+
let cache = null;
|
|
78
|
+
const derivedState = () => {
|
|
79
|
+
const fingerprint = specsTreeFingerprint(root);
|
|
80
|
+
if (cache && cache.fingerprint === fingerprint)
|
|
81
|
+
return cache;
|
|
82
|
+
const index = derive(root);
|
|
83
|
+
cache = { fingerprint, index, hash: indexStateHash(index) };
|
|
84
|
+
return cache;
|
|
85
|
+
};
|
|
86
|
+
const server = createServer((req, res) => {
|
|
87
|
+
const url = (req.url ?? "/").split("?")[0];
|
|
88
|
+
try {
|
|
89
|
+
if (url === "/__state") {
|
|
90
|
+
res.writeHead(200, { "content-type": "application/json", "cache-control": "no-store" });
|
|
91
|
+
res.end(JSON.stringify({ hash: derivedState().hash }));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (url === "/" || url === "/packet-index.html" || url === "/index.html") {
|
|
95
|
+
const html = injectLiveReload(renderIndexHtml(derivedState().index), pollMs);
|
|
96
|
+
res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" });
|
|
97
|
+
res.end(html);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
res.writeHead(404, { "content-type": "text/plain" });
|
|
101
|
+
res.end("not found");
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
// Never disclose internals (stack traces, filesystem paths) to the client.
|
|
105
|
+
// Log the detail server-side for the operator; return a generic message.
|
|
106
|
+
console.error("packet-index dashboard render error:", error instanceof Error ? (error.stack ?? error.message) : String(error));
|
|
107
|
+
res.writeHead(500, { "content-type": "text/plain" });
|
|
108
|
+
res.end("dashboard render error");
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
server.listen(options.port ?? DEFAULT_SERVE_PORT, options.host ?? DEFAULT_SERVE_HOST);
|
|
112
|
+
return server;
|
|
113
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Worker entry for the packet index's parallel per-packet derivation
|
|
2
|
+
// (cli-performance-v0 R-001).
|
|
3
|
+
//
|
|
4
|
+
// Message-free by design: the parent blocks synchronously in Atomics.wait
|
|
5
|
+
// (derivePacketIndex must stay synchronous for its callers), so it could not
|
|
6
|
+
// receive a postMessage while blocked. Results instead cross through this
|
|
7
|
+
// worker's SharedArrayBuffer slot: header cell (0 pending, 1 done, 2 failed),
|
|
8
|
+
// a byte-length cell, then the JSON-encoded entries.
|
|
9
|
+
//
|
|
10
|
+
// Each packet is still read once and parsed once (derivePacketEntry); workers
|
|
11
|
+
// only split the packets across cores.
|
|
12
|
+
import { workerData } from "node:worker_threads";
|
|
13
|
+
import { derivePacketEntry } from "./packetIndexEntry.js";
|
|
14
|
+
// Slot layout: [Int32 header][Int32 byteLength][Uint8 region].
|
|
15
|
+
const LENGTH_OFFSET = 4;
|
|
16
|
+
const REGION_OFFSET = 8;
|
|
17
|
+
const DONE = 1;
|
|
18
|
+
const FAILED = 2;
|
|
19
|
+
function finish(sab, slotBase, state, payload) {
|
|
20
|
+
const header = new Int32Array(sab, slotBase, 1);
|
|
21
|
+
if (payload) {
|
|
22
|
+
new Int32Array(sab, slotBase + LENGTH_OFFSET, 1)[0] = payload.byteLength;
|
|
23
|
+
new Uint8Array(sab, slotBase + REGION_OFFSET, payload.byteLength).set(payload);
|
|
24
|
+
}
|
|
25
|
+
Atomics.store(header, 0, state);
|
|
26
|
+
Atomics.notify(header, 0);
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
const data = workerData;
|
|
30
|
+
const entries = data.dirs.map((dir) => derivePacketEntry(data.root, dir));
|
|
31
|
+
const encoded = new TextEncoder().encode(JSON.stringify(entries));
|
|
32
|
+
const capacity = data.regionBytes - REGION_OFFSET;
|
|
33
|
+
if (encoded.byteLength > capacity) {
|
|
34
|
+
// Chunk too large for its slot: flag it and let the parent fall back to
|
|
35
|
+
// the serial path rather than truncating output.
|
|
36
|
+
finish(data.sab, data.slotBase, FAILED);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
finish(data.sab, data.slotBase, DONE, encoded);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
const data = workerData;
|
|
44
|
+
finish(data.sab, data.slotBase, FAILED);
|
|
45
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type JsonObject } from "./packetWrite.js";
|
|
2
|
+
export declare const VERDICT_STATES: readonly ["parked", "killed", "active", "done"];
|
|
3
|
+
export type VerdictState = (typeof VERDICT_STATES)[number];
|
|
4
|
+
export declare const RETIRED_LIFECYCLES: Set<string>;
|
|
5
|
+
export declare function isRetired(lifecycle: string | null | undefined): lifecycle is "parked" | "killed";
|
|
6
|
+
export declare const TERMINAL_LIFECYCLES: Set<string>;
|
|
7
|
+
export declare function isTerminal(lifecycle: string | null | undefined): boolean;
|
|
8
|
+
export declare const LIFECYCLE_EVENT_TYPE = "com.adaptivespec.packet.lifecycle_changed";
|
|
9
|
+
export type VerdictOptions = {
|
|
10
|
+
packetDir: string;
|
|
11
|
+
state: VerdictState;
|
|
12
|
+
reason: string;
|
|
13
|
+
actor?: {
|
|
14
|
+
type?: string;
|
|
15
|
+
id?: string;
|
|
16
|
+
};
|
|
17
|
+
now?: Date;
|
|
18
|
+
};
|
|
19
|
+
export type VerdictResult = {
|
|
20
|
+
event: JsonObject;
|
|
21
|
+
from: string | null;
|
|
22
|
+
to: VerdictState;
|
|
23
|
+
};
|
|
24
|
+
export declare function recordVerdict(options: VerdictOptions): VerdictResult;
|
|
25
|
+
export type VerdictRecord = {
|
|
26
|
+
state: string;
|
|
27
|
+
reason: string | null;
|
|
28
|
+
at: string | null;
|
|
29
|
+
};
|
|
30
|
+
export declare function latestVerdict(packetDir: string, limit?: number): VerdictRecord | null;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// Packet lifecycle verdicts (packet-lifecycle-v0).
|
|
2
|
+
//
|
|
3
|
+
// productfoo could already say todo/doing/done/blocked — but not "we decided not to
|
|
4
|
+
// do this." Abandonment is a verdict, and a tool whose thesis is that verdicts
|
|
5
|
+
// carry reasons needs a recorded, reversible way to retire intent. Two terminal
|
|
6
|
+
// states close that gap:
|
|
7
|
+
// - parked: still plausible, deliberately deferred; may come back.
|
|
8
|
+
// - killed: the idea is dead or superseded; it will not come back as-is.
|
|
9
|
+
// Completion is the third terminal verdict (packet-lifecycle-truth-v0 R-003):
|
|
10
|
+
// - done: the work shipped and its proofs are in — the same audited
|
|
11
|
+
// mechanism as retirement, so every terminal transition rides one trail.
|
|
12
|
+
// All REQUIRE a reason (R-002): an unreasoned verdict is exactly the silent
|
|
13
|
+
// bookkeeping this module exists to prevent. `active` reopens a terminal packet
|
|
14
|
+
// (also with a reason), so every transition is reversible and auditable.
|
|
15
|
+
//
|
|
16
|
+
// The verdict lives in two places, written together:
|
|
17
|
+
// - spec.md frontmatter `lifecycle:` — the canonical stamp the status/index
|
|
18
|
+
// readers already consume;
|
|
19
|
+
// - a `com.adaptivespec.packet.lifecycle_changed` event carrying {from, to,
|
|
20
|
+
// reason} — the append-only audit trail (and B1-guarded via appendEvent).
|
|
21
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
22
|
+
import path from "node:path";
|
|
23
|
+
import { appendEvent } from "./packetWrite.js";
|
|
24
|
+
export const VERDICT_STATES = ["parked", "killed", "active", "done"];
|
|
25
|
+
export const RETIRED_LIFECYCLES = new Set(["parked", "killed"]);
|
|
26
|
+
export function isRetired(lifecycle) {
|
|
27
|
+
return typeof lifecycle === "string" && RETIRED_LIFECYCLES.has(lifecycle);
|
|
28
|
+
}
|
|
29
|
+
// Terminal states end a packet's story: retirement (parked/killed) and
|
|
30
|
+
// completion (done, plus the legacy `built` stamp some packets carry). A
|
|
31
|
+
// terminal header is a recorded disposition, so the lifecycle-truth reader
|
|
32
|
+
// (packet-lifecycle-truth-v0 R-001) never flags it as drift over task math —
|
|
33
|
+
// a parked packet at 0% tasks is a decision, not a contradiction.
|
|
34
|
+
export const TERMINAL_LIFECYCLES = new Set(["parked", "killed", "done", "built"]);
|
|
35
|
+
export function isTerminal(lifecycle) {
|
|
36
|
+
return typeof lifecycle === "string" && TERMINAL_LIFECYCLES.has(lifecycle);
|
|
37
|
+
}
|
|
38
|
+
export const LIFECYCLE_EVENT_TYPE = "com.adaptivespec.packet.lifecycle_changed";
|
|
39
|
+
// --- Frontmatter restamp -----------------------------------------------------
|
|
40
|
+
// Rewrites only the `lifecycle:` (and `updated:`) lines inside the leading
|
|
41
|
+
// frontmatter block; every other byte of spec.md is preserved. A missing
|
|
42
|
+
// lifecycle line is inserted before the closing delimiter rather than guessed
|
|
43
|
+
// into position.
|
|
44
|
+
function restampFrontmatter(specPath, lifecycle, isoDate) {
|
|
45
|
+
const text = readFileSync(specPath, "utf8");
|
|
46
|
+
const lines = text.split("\n");
|
|
47
|
+
if (lines[0]?.trim() !== "---")
|
|
48
|
+
throw new Error(`spec.md has no YAML frontmatter to restamp: ${specPath}`);
|
|
49
|
+
let close = -1;
|
|
50
|
+
for (let i = 1; i < lines.length; i += 1) {
|
|
51
|
+
if (lines[i].trim() === "---") {
|
|
52
|
+
close = i;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (close === -1)
|
|
57
|
+
throw new Error(`spec.md frontmatter never closes: ${specPath}`);
|
|
58
|
+
let from = null;
|
|
59
|
+
let stamped = false;
|
|
60
|
+
for (let i = 1; i < close; i += 1) {
|
|
61
|
+
const m = lines[i].match(/^lifecycle:\s*(\S+)/);
|
|
62
|
+
if (m) {
|
|
63
|
+
from = m[1];
|
|
64
|
+
lines[i] = `lifecycle: ${lifecycle}`;
|
|
65
|
+
stamped = true;
|
|
66
|
+
}
|
|
67
|
+
else if (/^updated:\s*/.test(lines[i])) {
|
|
68
|
+
lines[i] = `updated: ${isoDate}`;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (!stamped) {
|
|
72
|
+
lines.splice(close, 0, `lifecycle: ${lifecycle}`);
|
|
73
|
+
}
|
|
74
|
+
writeFileSync(specPath, lines.join("\n"));
|
|
75
|
+
return { from };
|
|
76
|
+
}
|
|
77
|
+
export function recordVerdict(options) {
|
|
78
|
+
if (!VERDICT_STATES.includes(options.state)) {
|
|
79
|
+
throw new Error(`invalid verdict state: ${options.state} (expected ${VERDICT_STATES.join(" | ")})`);
|
|
80
|
+
}
|
|
81
|
+
const reason = options.reason?.trim();
|
|
82
|
+
if (!reason) {
|
|
83
|
+
throw new Error(`a ${options.state} verdict requires --reason: the reason is the product record, not decoration`);
|
|
84
|
+
}
|
|
85
|
+
const specPath = path.join(options.packetDir, "spec.md");
|
|
86
|
+
if (!existsSync(specPath) || !existsSync(path.join(options.packetDir, "tasks.yaml"))) {
|
|
87
|
+
throw new Error(`not a packet directory (missing spec.md or tasks.yaml): ${options.packetDir}`);
|
|
88
|
+
}
|
|
89
|
+
const now = options.now ?? new Date();
|
|
90
|
+
const { from } = restampFrontmatter(specPath, options.state, now.toISOString().slice(0, 10));
|
|
91
|
+
// Event second: if the stamp threw (bad frontmatter), no ledger line is left
|
|
92
|
+
// claiming a verdict that spec.md does not carry.
|
|
93
|
+
const event = appendEvent({
|
|
94
|
+
packetDir: options.packetDir,
|
|
95
|
+
type: LIFECYCLE_EVENT_TYPE,
|
|
96
|
+
data: { from, to: options.state, reason },
|
|
97
|
+
actor: options.actor,
|
|
98
|
+
now,
|
|
99
|
+
});
|
|
100
|
+
return { event, from, to: options.state };
|
|
101
|
+
}
|
|
102
|
+
// Latest lifecycle_changed event, scanned from the ledger tail. Bounded and
|
|
103
|
+
// skip-on-malformed like every other ledger read; returns null when no verdict
|
|
104
|
+
// event exists (e.g. a hand-stamped frontmatter with no trail).
|
|
105
|
+
export function latestVerdict(packetDir, limit = 500) {
|
|
106
|
+
const eventsPath = path.join(packetDir, "events.jsonl");
|
|
107
|
+
if (!existsSync(eventsPath))
|
|
108
|
+
return null;
|
|
109
|
+
const lines = readFileSync(eventsPath, "utf8").split(/\r?\n/).filter((l) => l.trim());
|
|
110
|
+
for (const line of lines.slice(-limit).reverse()) {
|
|
111
|
+
try {
|
|
112
|
+
const e = JSON.parse(line);
|
|
113
|
+
if (e.type !== LIFECYCLE_EVENT_TYPE)
|
|
114
|
+
continue;
|
|
115
|
+
const data = (e.data ?? {});
|
|
116
|
+
return {
|
|
117
|
+
state: typeof data.to === "string" ? data.to : "unknown",
|
|
118
|
+
reason: typeof data.reason === "string" ? data.reason : null,
|
|
119
|
+
at: typeof e.time === "string" ? e.time : null,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { type SourceId } from "./sourceIngress.js";
|
|
2
|
+
export type JsonObject = Record<string, unknown>;
|
|
3
|
+
export type Task = {
|
|
4
|
+
id: string;
|
|
5
|
+
agreement: string;
|
|
6
|
+
status?: string;
|
|
7
|
+
touches?: string[];
|
|
8
|
+
};
|
|
9
|
+
export type ChangedFileClass = {
|
|
10
|
+
path: string;
|
|
11
|
+
state: "agreed" | "unagreed" | "unmapped";
|
|
12
|
+
mapped_tasks: string[];
|
|
13
|
+
mapped_task_agreements: Record<string, string>;
|
|
14
|
+
};
|
|
15
|
+
export type ReconcileOptions = {
|
|
16
|
+
packetDir: string;
|
|
17
|
+
root: string;
|
|
18
|
+
changedFiles?: string[];
|
|
19
|
+
gitDiff?: boolean;
|
|
20
|
+
taskNoun?: string;
|
|
21
|
+
jiraEvidencePath?: string;
|
|
22
|
+
};
|
|
23
|
+
export type ReconcileReport = {
|
|
24
|
+
spec_id: unknown;
|
|
25
|
+
packet: string;
|
|
26
|
+
changed_files: Array<{
|
|
27
|
+
path: string;
|
|
28
|
+
state: "agreed" | "unagreed" | "unmapped";
|
|
29
|
+
mapped_tasks: string[];
|
|
30
|
+
mapped_task_agreements: Record<string, string>;
|
|
31
|
+
}>;
|
|
32
|
+
findings: JsonObject[];
|
|
33
|
+
summary: string;
|
|
34
|
+
work_system?: JiraWorkSystemReport;
|
|
35
|
+
};
|
|
36
|
+
export declare function parseReconcileArgs(args: string[]): {
|
|
37
|
+
changedFiles: string[];
|
|
38
|
+
gitDiff: boolean;
|
|
39
|
+
jiraEvidencePath?: string;
|
|
40
|
+
};
|
|
41
|
+
export declare function gitChangedFiles(root: string): string[];
|
|
42
|
+
export declare function classifyChangedFiles(tasks: Task[], changedFileInputs: string[], noun?: string): {
|
|
43
|
+
changed_files: ChangedFileClass[];
|
|
44
|
+
findings: JsonObject[];
|
|
45
|
+
};
|
|
46
|
+
export type JiraEvidenceFixture = {
|
|
47
|
+
provider: "jira";
|
|
48
|
+
site: string;
|
|
49
|
+
observed_at: string;
|
|
50
|
+
scope: unknown;
|
|
51
|
+
issues: Array<{
|
|
52
|
+
issue: unknown;
|
|
53
|
+
cites_task?: string;
|
|
54
|
+
}>;
|
|
55
|
+
};
|
|
56
|
+
export type JiraWorkSystemReport = {
|
|
57
|
+
source_id: SourceId;
|
|
58
|
+
site: string;
|
|
59
|
+
observed_at: string;
|
|
60
|
+
scope: string;
|
|
61
|
+
admitted: number;
|
|
62
|
+
excluded: number;
|
|
63
|
+
findings: JsonObject[];
|
|
64
|
+
task_conclusions: JsonObject[];
|
|
65
|
+
};
|
|
66
|
+
export declare const JIRA_STALE_DAYS = 30;
|
|
67
|
+
export declare function jiraWorkSystemReconcile(opts: {
|
|
68
|
+
packetDir: string;
|
|
69
|
+
fixture: JiraEvidenceFixture;
|
|
70
|
+
tasks: Task[];
|
|
71
|
+
}): JiraWorkSystemReport;
|
|
72
|
+
export declare function readJiraEvidenceFixture(root: string, fixturePath: string): JiraEvidenceFixture;
|
|
73
|
+
export declare function reconcilePacket(options: ReconcileOptions): ReconcileReport;
|