@hivelore/core 0.36.0 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -2166,6 +2166,85 @@ declare function suggestSensorSeed(body: string, anchorPaths: string[], options?
2166
2166
  */
2167
2167
  declare function suggestSensorFromMemory(body: string, anchorPaths: string[], options?: SensorSuggestionOptions): Sensor | null;
2168
2168
 
2169
+ /**
2170
+ * Post-incident test scaffolding — turn a captured lesson (`mem_tried` / attempt / gotcha) into a
2171
+ * PENDING test file the team fills in, then arms as a command-sensor oracle.
2172
+ *
2173
+ * This is the behaviour-harness bridge's on-ramp: `mem_tried` records *what* failed and *why*, but a
2174
+ * command sensor needs the team's own test as the oracle — and someone has to write it. This module
2175
+ * removes that friction by generating the test skeleton (header provenance + a pending test + a
2176
+ * commented example derived from the lesson) plus the exact `sensors propose --kind test` line.
2177
+ *
2178
+ * DOCTRINE: this NEVER arms a sensor. It only writes a stub and prints the wiring command. Arming
2179
+ * stays with `propose_sensor`, the sole validated writer of live sensors (silent-on-current /
2180
+ * fires-on-bad). The generated test is deliberately PENDING (todo/skip) so the suite stays green and
2181
+ * an empty stub can't masquerade as a passing oracle. Pure: no I/O — the caller writes the file.
2182
+ */
2183
+ type TestFramework = "vitest" | "jest" | "pytest" | "gotest";
2184
+ declare const TEST_FRAMEWORKS: readonly TestFramework[];
2185
+ interface PostIncidentLesson {
2186
+ /** Memory id the scaffold is generated from. */
2187
+ memoryId: string;
2188
+ /** Short "what was tried / what failed" title (the lesson's heading). */
2189
+ title: string;
2190
+ /** Why it failed / must not be used. */
2191
+ whyFailed?: string;
2192
+ /** The correct approach / expected behaviour. */
2193
+ instead?: string;
2194
+ /** Incident provenance (ticket/prod ref) carried into the sensor when armed. */
2195
+ incident?: string;
2196
+ /** Anchor paths — used to scope the sensor and to place the test near the code. */
2197
+ paths?: string[];
2198
+ }
2199
+ interface TestScaffold {
2200
+ framework: TestFramework;
2201
+ /** Suggested project-relative path for the generated test file. */
2202
+ relPath: string;
2203
+ /** File contents (a pending test with provenance + a commented example). */
2204
+ content: string;
2205
+ /** Command that runs ONLY this test — becomes the sensor's oracle command once filled in. */
2206
+ runCommand: string;
2207
+ /** Ready-to-run wiring command: arms the test as a deterministic gate AFTER it is written. */
2208
+ proposeCommand: string;
2209
+ }
2210
+ interface ScaffoldOptions {
2211
+ framework: TestFramework;
2212
+ /** Override the generated file path (project-relative). Wins over baseDir. */
2213
+ outPath?: string;
2214
+ /**
2215
+ * Repo-relative directory of the package that owns the incident (monorepo awareness). The default
2216
+ * test path and run command are placed inside it. Empty/omitted → repo root.
2217
+ */
2218
+ baseDir?: string;
2219
+ }
2220
+ /** Map a user-supplied framework string (with common aliases) to a TestFramework, or null. */
2221
+ declare function normalizeFramework(input: string): TestFramework | null;
2222
+ /**
2223
+ * Pure framework decision from already-gathered facts (a package.json's deps + non-JS signals). The
2224
+ * FS walking that produces these facts is I/O and lives in the caller (cli/mcp), keeping core pure.
2225
+ */
2226
+ declare function pickTestFramework(pkg: {
2227
+ dependencies?: Record<string, string>;
2228
+ devDependencies?: Record<string, string>;
2229
+ } | null, signals?: {
2230
+ goMod?: boolean;
2231
+ pySignal?: boolean;
2232
+ }): TestFramework;
2233
+ /** Strip the `YYYY-MM-DD-<type>-` id prefix to the descriptive slug (`importing-momentjs`). */
2234
+ declare function lessonShortName(memoryId: string): string;
2235
+ /**
2236
+ * Parse the "what / why / instead" fields out of an attempt/gotcha memory body — the shape written
2237
+ * by `mem_tried` (`# <what>`, `**Why it failed / do NOT use:** …`, `**Instead, use:** …`). Pure so
2238
+ * the CLI can hand it a loaded body without re-implementing the parse.
2239
+ */
2240
+ declare function parseLessonFields(body: string): {
2241
+ title?: string;
2242
+ whyFailed?: string;
2243
+ instead?: string;
2244
+ };
2245
+ /** Build a scaffold for the given lesson + framework. Pure — the caller writes `content` to `relPath`. */
2246
+ declare function scaffoldPostIncidentTest(lesson: PostIncidentLesson, options: ScaffoldOptions): TestScaffold;
2247
+
2169
2248
  /**
2170
2249
  * First-agent bootstrap state — is the repo's knowledge layer filled enough for later agents to rely on?
2171
2250
  *
@@ -3014,4 +3093,4 @@ interface AgentContext {
3014
3093
  }
3015
3094
  declare function detectAgentContext(env?: Record<string, string | undefined>): AgentContext;
3016
3095
 
3017
- export { AUTOPILOT_DEFAULTS, type Activation, type ActivationContext, ActivationSchema, type AgentContext, type Anchor, AnchorSchema, type AntiPatternGate, type AppliedConflictResolution, type AstExport, type AutoPromoteRule, BRIDGE_MARKERS, BRIDGE_TARGETS, BRIDGE_TARGET_PATH, BRIEFING_MARKER_TTL_MS, BRIEFING_PRESET_DEFAULTS, type BootstrapAssessment, type BootstrapGap, type BootstrapGate, type BootstrapMetrics, type BootstrapState, type BootstrapStateInput, type BreakingChange, type BridgeFileOutput, type BridgeMemoryEntry, type BridgeSensor, type BridgeTarget, type BriefingBudgetNumbers, type BriefingBudgetPreset, type BriefingMarker, type BriefingProofLineOptions, type BudgetPart, type BudgetSlice, type BuildCodeMapOptions, CHARS_PER_TOKEN, CODE_MAP_DEFAULT_EXCLUDE, CODE_MAP_DEFAULT_INCLUDE, CODE_MAP_FILE, CODE_STOPWORDS, CONFIG_FILE, type CaughtForYouOptions, type CaughtForYouRow, type CaughtForYouSummary, type CodeExport, type CodeExportKind, type CodeFileEntry, type CodeMap, type CodeMapQueryOptions, type CollectTimelineOpts, type CommandSensorSpec, type ConfidenceLevel, type ConfidenceThresholds, type ConflictCandidatePair, type ConflictCandidatesOpts, type ConflictResolution, type ContractDiffResult, type ContractFile, type ContractSnapshot, type CoverageGap, type CoverageOptions, CrossRepoProvenanceSchema, type CrossRepoReport, type CrossRepoSource, DECAY_DAYS, DEFAULT_AUTO_PROMOTE_RULE, DEFAULT_BRIEFING_EXCLUDE_TAGS, DEFAULT_CONFIDENCE_THRESHOLDS, DEFAULT_CONFIG, DEFAULT_DORMANT_DAYS, DEFAULT_PRIORITY_SIGNALS, type DashboardOptions, type DashboardReport, type DepChange, type DepTrackResult, type DependencySnapshot, type DetectStacksInput, type DetectableStack, type DocFrequency, type DormantRow, type DraftOptions, type DraftsOptions, ENV_WORKAROUND_TAGS, type EvalDelta, type EvalHistoryEntry, type EvalReport, type EvalSpec, type EvalTrend, type FailureCoverageOptions, type FailureObservation, type FeedbackAdjustment, type FeedbackAdjustmentAction, type FeedbackAdjustmentOptions, type Finding, type FindingFormat, type FindingSeverity, GUESSABLE_THRESHOLD, type GateMissProposal, type GatePrecision, type GatePrecisionDelta, type GatePrecisionMetricDelta, type GateTuningSuggestion, type GenerateBridgesOptions, type GitCommit, type GitWatchPlan, type GitWatchState, HAIVE_DIR, HAIVE_OWNED_FILES, HANDOFF_FILENAME, HIVELORE_ATTRIBUTION, type HaiveConfig, type HaivePaths, type HotFile, type HotFileSource, type ImpactOptions, type ImpactRow, type ImpactScore, type ImpactSummary, type ImpactTier, type InvalidMemoryFile, type LexicalRankResult, type LoadedMemory, MEMORIES_DIR, MIN_WORD_LEN, type Memory, type MemoryDraft, type MemoryFrontmatter, MemoryFrontmatterSchema, type MemoryPriority, type MemoryScope, MemoryScopeSchema, type MemoryStatus, MemoryStatusSchema, type MemoryType, MemoryTypeSchema, type MemoryUsage, type MergeResult, type MetricDelta, PREVENTION_DEBOUNCE_MS, PROJECT_CONTEXT_FILE, PROJECT_CONTEXT_THROTTLE_MS, type PreventionEvent, type PreventionEventDetail, type PreventionReceipt, type PreventionReceiptRow, type PreventionRow, type PreventionSource, type PreventionTrend, type PrioritySignals, type ProposedSensorVerdict, RUNTIME_JOURNAL_FILENAME, type RecurrenceReport, type RecurrenceRow, type ResolveProjectInfo, type RetirementSignal, type RetrievalAggregate, type RetrievalCase, type RetrievalCaseResult, type RuntimeJournalEntry, SEED_QUALITY_FLOOR, SENSOR_ABSENT_LOOKBACK, SENSOR_ABSENT_WINDOW, SESSION_RECAP_TTL_MS, STACK_PACK_TAG, type SeedProposal, type SelfEvalOptions, type Sensor, type SensorAggregate, type SensorCase, type SensorCaseResult, type SensorEvaluation, type SensorEvaluationOutcome, type SensorEvaluationStage, type SensorFlap, type SensorHealth, type SensorHit, type SensorRow, SensorSchema, type SensorSeed, type SensorSelfCheck, type SensorSuggestionOptions, type SensorTarget, type SessionHandoffData, type SkillActivation, type TimelineEntry, type TopicStatusPair, type TruncateOptions, type TruncateResult, USAGE_FILE, USAGE_LOG_DIR, USAGE_LOG_FILE, type UncapturedFailure, type UsageAggregate, type UsageEvent, type UsageIndex, type VerifyOptions, type VerifyResult, addedLinesFromDiff, aggregateRetrieval, aggregateSensors, aggregateUsage, allocateBudget, antiPatternGateParams, appendEvalHistory, appendPreventionEvent, appendRuntimeJournalEntry, appendSensorEvaluations, appendUsageEvent, applyConflictResolution, applyFeedbackAdjustment, assessBootstrapState, assessSensorHealth, bridgeMemorySummary, briefingMarkerPath, briefingMarkersDir, briefingProofLine, buildCodeMap, buildCoverageIndex, buildDashboard, buildDocFrequency, buildFrontmatter, buildHandoffMarkdown, buildPreventionReceipt, buildReport, bumpRead, classifyMemoryPriority, codeMapPath, collectTimelineEntries, compactAutoRecapBody, compareEvalReports, compareGatePrecision, compareImpact, compileRegexSensor, componentOf, computeEvalTrend, computeGatePrecision, computeImpact, computePreventionTrend, computeRecurrence, computeScopeHash, configPath, contractLockPath, countSourceFilesOnDisk, deriveConfidence, detectAgentContext, detectStacksFromManifests, diffContract, diffHasDistinctiveOverlap, distinctiveCap, draftsFromFindings, emptyUsage, emptyUsageIndex, enforcementDir, estimateTokens, evalHistoryPath, evaluateSkillActivation, existingGateMissShas, extractActionsBriefBody, extractReferencedPaths, extractSensorExamples, extractSnippet, filterNewDrafts, findCoverageGaps, findLexicalConflictPairs, findProjectRoot, findTopicStatusConflictPairs, findUncapturedFailures, findingBody, findingToDraft, firstMemoryOneLine, gatePassedShas, generateBridges, getUsage, globToRegExp, handoffAgeMs, handoffFilePath, hasRecentBriefingMarker, hashProjectContext, incidentSuffix, inferModulesFromPaths, isAutoPromoteEligible, isAutoRecap, isCovered, isDecaying, isDistinctiveToken, isEnvWorkaroundMemory, isFreshIsoDate, isGlobPath, isLikelyGuessable, isNoiseSubject, isRetiredMemory, isSensorScannablePath, isSkill, isSkillSuppressed, isStackPackSeed, isStylisticRule, isTemplateProjectContext, judgeProposedSensor, listMarkdownFilesRecursive, literalMatchesAllTokens, literalMatchesAnyToken, loadCodeMap, loadConfig, loadConfigSync, loadEvalHistory, loadMemoriesFromDir, loadMemoriesFromDirDetailed, loadMemory, loadPreventionEvents, loadSensorLedger, loadUsageIndex, looksLikeGenericAdvice, meetsSeedQualityFloor, memoryFilePath, memoryHasExcludedTag, memoryMatchesAnchorPaths, mergeHotFiles, mergeMemoryVersions, moduleNameOf, newMemoryId, normalizeFindingSeverity, normalizeSessionId, overallScore, parseEslintJson, parseFileAst, parseFindings, parseMemory, parseNpmAudit, parseSarif, parseSince, parseSonar, pathsOverlap, pickSnippetNeedle, planConflictResolution, planGitWatch, prepareBridgeData, preventionLogPath, priorityRank, prioritySignals, projectContextRecentlyEmitted, proposeGateMissDrafts, proposeSeedsFromCommits, pullCrossRepoSources, quarantineNote, queryCodeMap, rankMemoriesLexical, readRecentBriefingMarker, readRuntimeJournalTail, readSessionHandoff, readUsageEvents, recommendFeedbackAdjustment, recordApplied, recordPrevention, recordPreventionHits, recordProjectContextEmission, recordRejection, relPathFrom, renderBootstrapChecklist, renderCaughtForYou, renderPreventionReceipt, renderPreventionReceiptShare, resolveBriefingBudget, resolveHaivePaths, resolveManifestFiles, resolveProjectInfo, retirementSignal, revertedShaFromCommit, runRegexSensor, runSensors, runtimeJournalPath, saveCodeMap, saveConfig, saveUsageIndex, scannableSensorTargets, scoreRetrievalCase, scoreSensorCase, selectCommandSensors, sensorAppliesToPath, sensorLedgerPath, sensorPatternBrittleness, sensorPromotedAtMap, sensorSelfCheck, sensorTargetsFromDiff, serializeMemory, snapshotContract, specificityScore, stripPrivate, suggestGate, suggestSensorFromMemory, suggestSensorSeed, suggestTopicKey, summarizeCaughtForYou, summarizeImpact, synthesizeSelfEvalCases, tallyHotFiles, titleFromBody, tokenizeQuery, tokenizeWords, trackDependencies, trackReads, truncateToTokens, usageLogPath, usageLogSize, usagePath, verifyAnchor, watchContracts, withQuarantineNote, withoutQuarantineNote, writeBriefingMarker, writeSessionHandoff };
3096
+ export { AUTOPILOT_DEFAULTS, type Activation, type ActivationContext, ActivationSchema, type AgentContext, type Anchor, AnchorSchema, type AntiPatternGate, type AppliedConflictResolution, type AstExport, type AutoPromoteRule, BRIDGE_MARKERS, BRIDGE_TARGETS, BRIDGE_TARGET_PATH, BRIEFING_MARKER_TTL_MS, BRIEFING_PRESET_DEFAULTS, type BootstrapAssessment, type BootstrapGap, type BootstrapGate, type BootstrapMetrics, type BootstrapState, type BootstrapStateInput, type BreakingChange, type BridgeFileOutput, type BridgeMemoryEntry, type BridgeSensor, type BridgeTarget, type BriefingBudgetNumbers, type BriefingBudgetPreset, type BriefingMarker, type BriefingProofLineOptions, type BudgetPart, type BudgetSlice, type BuildCodeMapOptions, CHARS_PER_TOKEN, CODE_MAP_DEFAULT_EXCLUDE, CODE_MAP_DEFAULT_INCLUDE, CODE_MAP_FILE, CODE_STOPWORDS, CONFIG_FILE, type CaughtForYouOptions, type CaughtForYouRow, type CaughtForYouSummary, type CodeExport, type CodeExportKind, type CodeFileEntry, type CodeMap, type CodeMapQueryOptions, type CollectTimelineOpts, type CommandSensorSpec, type ConfidenceLevel, type ConfidenceThresholds, type ConflictCandidatePair, type ConflictCandidatesOpts, type ConflictResolution, type ContractDiffResult, type ContractFile, type ContractSnapshot, type CoverageGap, type CoverageOptions, CrossRepoProvenanceSchema, type CrossRepoReport, type CrossRepoSource, DECAY_DAYS, DEFAULT_AUTO_PROMOTE_RULE, DEFAULT_BRIEFING_EXCLUDE_TAGS, DEFAULT_CONFIDENCE_THRESHOLDS, DEFAULT_CONFIG, DEFAULT_DORMANT_DAYS, DEFAULT_PRIORITY_SIGNALS, type DashboardOptions, type DashboardReport, type DepChange, type DepTrackResult, type DependencySnapshot, type DetectStacksInput, type DetectableStack, type DocFrequency, type DormantRow, type DraftOptions, type DraftsOptions, ENV_WORKAROUND_TAGS, type EvalDelta, type EvalHistoryEntry, type EvalReport, type EvalSpec, type EvalTrend, type FailureCoverageOptions, type FailureObservation, type FeedbackAdjustment, type FeedbackAdjustmentAction, type FeedbackAdjustmentOptions, type Finding, type FindingFormat, type FindingSeverity, GUESSABLE_THRESHOLD, type GateMissProposal, type GatePrecision, type GatePrecisionDelta, type GatePrecisionMetricDelta, type GateTuningSuggestion, type GenerateBridgesOptions, type GitCommit, type GitWatchPlan, type GitWatchState, HAIVE_DIR, HAIVE_OWNED_FILES, HANDOFF_FILENAME, HIVELORE_ATTRIBUTION, type HaiveConfig, type HaivePaths, type HotFile, type HotFileSource, type ImpactOptions, type ImpactRow, type ImpactScore, type ImpactSummary, type ImpactTier, type InvalidMemoryFile, type LexicalRankResult, type LoadedMemory, MEMORIES_DIR, MIN_WORD_LEN, type Memory, type MemoryDraft, type MemoryFrontmatter, MemoryFrontmatterSchema, type MemoryPriority, type MemoryScope, MemoryScopeSchema, type MemoryStatus, MemoryStatusSchema, type MemoryType, MemoryTypeSchema, type MemoryUsage, type MergeResult, type MetricDelta, PREVENTION_DEBOUNCE_MS, PROJECT_CONTEXT_FILE, PROJECT_CONTEXT_THROTTLE_MS, type PostIncidentLesson, type PreventionEvent, type PreventionEventDetail, type PreventionReceipt, type PreventionReceiptRow, type PreventionRow, type PreventionSource, type PreventionTrend, type PrioritySignals, type ProposedSensorVerdict, RUNTIME_JOURNAL_FILENAME, type RecurrenceReport, type RecurrenceRow, type ResolveProjectInfo, type RetirementSignal, type RetrievalAggregate, type RetrievalCase, type RetrievalCaseResult, type RuntimeJournalEntry, SEED_QUALITY_FLOOR, SENSOR_ABSENT_LOOKBACK, SENSOR_ABSENT_WINDOW, SESSION_RECAP_TTL_MS, STACK_PACK_TAG, type ScaffoldOptions, type SeedProposal, type SelfEvalOptions, type Sensor, type SensorAggregate, type SensorCase, type SensorCaseResult, type SensorEvaluation, type SensorEvaluationOutcome, type SensorEvaluationStage, type SensorFlap, type SensorHealth, type SensorHit, type SensorRow, SensorSchema, type SensorSeed, type SensorSelfCheck, type SensorSuggestionOptions, type SensorTarget, type SessionHandoffData, type SkillActivation, TEST_FRAMEWORKS, type TestFramework, type TestScaffold, type TimelineEntry, type TopicStatusPair, type TruncateOptions, type TruncateResult, USAGE_FILE, USAGE_LOG_DIR, USAGE_LOG_FILE, type UncapturedFailure, type UsageAggregate, type UsageEvent, type UsageIndex, type VerifyOptions, type VerifyResult, addedLinesFromDiff, aggregateRetrieval, aggregateSensors, aggregateUsage, allocateBudget, antiPatternGateParams, appendEvalHistory, appendPreventionEvent, appendRuntimeJournalEntry, appendSensorEvaluations, appendUsageEvent, applyConflictResolution, applyFeedbackAdjustment, assessBootstrapState, assessSensorHealth, bridgeMemorySummary, briefingMarkerPath, briefingMarkersDir, briefingProofLine, buildCodeMap, buildCoverageIndex, buildDashboard, buildDocFrequency, buildFrontmatter, buildHandoffMarkdown, buildPreventionReceipt, buildReport, bumpRead, classifyMemoryPriority, codeMapPath, collectTimelineEntries, compactAutoRecapBody, compareEvalReports, compareGatePrecision, compareImpact, compileRegexSensor, componentOf, computeEvalTrend, computeGatePrecision, computeImpact, computePreventionTrend, computeRecurrence, computeScopeHash, configPath, contractLockPath, countSourceFilesOnDisk, deriveConfidence, detectAgentContext, detectStacksFromManifests, diffContract, diffHasDistinctiveOverlap, distinctiveCap, draftsFromFindings, emptyUsage, emptyUsageIndex, enforcementDir, estimateTokens, evalHistoryPath, evaluateSkillActivation, existingGateMissShas, extractActionsBriefBody, extractReferencedPaths, extractSensorExamples, extractSnippet, filterNewDrafts, findCoverageGaps, findLexicalConflictPairs, findProjectRoot, findTopicStatusConflictPairs, findUncapturedFailures, findingBody, findingToDraft, firstMemoryOneLine, gatePassedShas, generateBridges, getUsage, globToRegExp, handoffAgeMs, handoffFilePath, hasRecentBriefingMarker, hashProjectContext, incidentSuffix, inferModulesFromPaths, isAutoPromoteEligible, isAutoRecap, isCovered, isDecaying, isDistinctiveToken, isEnvWorkaroundMemory, isFreshIsoDate, isGlobPath, isLikelyGuessable, isNoiseSubject, isRetiredMemory, isSensorScannablePath, isSkill, isSkillSuppressed, isStackPackSeed, isStylisticRule, isTemplateProjectContext, judgeProposedSensor, lessonShortName, listMarkdownFilesRecursive, literalMatchesAllTokens, literalMatchesAnyToken, loadCodeMap, loadConfig, loadConfigSync, loadEvalHistory, loadMemoriesFromDir, loadMemoriesFromDirDetailed, loadMemory, loadPreventionEvents, loadSensorLedger, loadUsageIndex, looksLikeGenericAdvice, meetsSeedQualityFloor, memoryFilePath, memoryHasExcludedTag, memoryMatchesAnchorPaths, mergeHotFiles, mergeMemoryVersions, moduleNameOf, newMemoryId, normalizeFindingSeverity, normalizeFramework, normalizeSessionId, overallScore, parseEslintJson, parseFileAst, parseFindings, parseLessonFields, parseMemory, parseNpmAudit, parseSarif, parseSince, parseSonar, pathsOverlap, pickSnippetNeedle, pickTestFramework, planConflictResolution, planGitWatch, prepareBridgeData, preventionLogPath, priorityRank, prioritySignals, projectContextRecentlyEmitted, proposeGateMissDrafts, proposeSeedsFromCommits, pullCrossRepoSources, quarantineNote, queryCodeMap, rankMemoriesLexical, readRecentBriefingMarker, readRuntimeJournalTail, readSessionHandoff, readUsageEvents, recommendFeedbackAdjustment, recordApplied, recordPrevention, recordPreventionHits, recordProjectContextEmission, recordRejection, relPathFrom, renderBootstrapChecklist, renderCaughtForYou, renderPreventionReceipt, renderPreventionReceiptShare, resolveBriefingBudget, resolveHaivePaths, resolveManifestFiles, resolveProjectInfo, retirementSignal, revertedShaFromCommit, runRegexSensor, runSensors, runtimeJournalPath, saveCodeMap, saveConfig, saveUsageIndex, scaffoldPostIncidentTest, scannableSensorTargets, scoreRetrievalCase, scoreSensorCase, selectCommandSensors, sensorAppliesToPath, sensorLedgerPath, sensorPatternBrittleness, sensorPromotedAtMap, sensorSelfCheck, sensorTargetsFromDiff, serializeMemory, snapshotContract, specificityScore, stripPrivate, suggestGate, suggestSensorFromMemory, suggestSensorSeed, suggestTopicKey, summarizeCaughtForYou, summarizeImpact, synthesizeSelfEvalCases, tallyHotFiles, titleFromBody, tokenizeQuery, tokenizeWords, trackDependencies, trackReads, truncateToTokens, usageLogPath, usageLogSize, usagePath, verifyAnchor, watchContracts, withQuarantineNote, withoutQuarantineNote, writeBriefingMarker, writeSessionHandoff };
package/dist/index.js CHANGED
@@ -3758,8 +3758,8 @@ var BRIDGE_MARKERS = {
3758
3758
  };
3759
3759
  function bridgeMemorySummary(body) {
3760
3760
  const firstLine = body.split("\n").map((l) => l.replace(/^#+\s*/, "").trim()).find((l) => l.length > 0) ?? "";
3761
- const oneLine = firstLine.replace(/\s+/g, " ");
3762
- return oneLine.length > 140 ? oneLine.slice(0, 137) + "\u2026" : oneLine;
3761
+ const oneLine2 = firstLine.replace(/\s+/g, " ");
3762
+ return oneLine2.length > 140 ? oneLine2.slice(0, 137) + "\u2026" : oneLine2;
3763
3763
  }
3764
3764
  function prepareBridgeData(memories, sensors, opts) {
3765
3765
  const max = opts?.maxMemories ?? 8;
@@ -4486,6 +4486,139 @@ function escapeRegExp(value) {
4486
4486
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4487
4487
  }
4488
4488
 
4489
+ // src/test-scaffold.ts
4490
+ var TEST_FRAMEWORKS = ["vitest", "jest", "pytest", "gotest"];
4491
+ function normalizeFramework(input) {
4492
+ const v = input.trim().toLowerCase();
4493
+ if (v === "vitest") return "vitest";
4494
+ if (v === "jest") return "jest";
4495
+ if (v === "pytest" || v === "py" || v === "python") return "pytest";
4496
+ if (v === "go" || v === "gotest" || v === "go-test") return "gotest";
4497
+ return null;
4498
+ }
4499
+ function pickTestFramework(pkg, signals = {}) {
4500
+ const deps = { ...pkg?.dependencies, ...pkg?.devDependencies };
4501
+ if (deps.vitest) return "vitest";
4502
+ if (deps.jest || deps["ts-jest"]) return "jest";
4503
+ if (signals.goMod) return "gotest";
4504
+ if (signals.pySignal) return "pytest";
4505
+ return "vitest";
4506
+ }
4507
+ function joinRel(baseDir, rest) {
4508
+ const base = (baseDir ?? "").replace(/^\/+|\/+$/g, "");
4509
+ return base ? `${base}/${rest}` : rest;
4510
+ }
4511
+ function lessonShortName(memoryId) {
4512
+ const stripped = memoryId.replace(
4513
+ /^\d{4}-\d{2}-\d{2}-(?:attempt|gotcha|decision|convention|architecture|glossary|skill|session_recap)-/,
4514
+ ""
4515
+ );
4516
+ const slug = (stripped || memoryId).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
4517
+ return slug || "incident";
4518
+ }
4519
+ function snake(slug) {
4520
+ return slug.replace(/-/g, "_").replace(/[^a-z0-9_]/gi, "").replace(/^_+|_+$/g, "") || "incident";
4521
+ }
4522
+ function pascal(slug) {
4523
+ return slug.split(/[^a-z0-9]+/i).filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("") || "Incident";
4524
+ }
4525
+ function oneLine(text) {
4526
+ return (text ?? "").replace(/\s+/g, " ").trim();
4527
+ }
4528
+ function parseLessonFields(body) {
4529
+ const title = body.match(/^#\s+(.+?)\s*$/m)?.[1]?.trim();
4530
+ const whyFailed = body.match(/\*\*Why it failed[^:]*:\*\*\s*([^\n]+)/i)?.[1]?.trim();
4531
+ const instead = body.match(/\*\*Instead,\s*use:\*\*\s*([^\n]+)/i)?.[1]?.trim();
4532
+ return { title, whyFailed, instead };
4533
+ }
4534
+ function proposeCommand(lesson, runCommand) {
4535
+ const parts = [
4536
+ `hivelore sensors propose ${lesson.memoryId}`,
4537
+ "--kind test",
4538
+ `--command ${JSON.stringify(runCommand)}`
4539
+ ];
4540
+ if (lesson.incident) parts.push(`--incident ${JSON.stringify(lesson.incident)}`);
4541
+ const scope = (lesson.paths ?? []).filter(Boolean);
4542
+ if (scope.length > 0) parts.push(`--paths ${JSON.stringify(scope.join(","))}`);
4543
+ return parts.join(" ");
4544
+ }
4545
+ function header(lesson, comment) {
4546
+ const lines = [
4547
+ `Post-incident guard generated by Hivelore from ${lesson.memoryId}.`,
4548
+ ...lesson.incident ? [`Incident: ${lesson.incident}`] : [],
4549
+ `What failed: ${oneLine(lesson.title)}`,
4550
+ ...lesson.whyFailed ? [`Why: ${oneLine(lesson.whyFailed)}`] : [],
4551
+ ...lesson.instead ? [`Expected / fix: ${oneLine(lesson.instead)}`] : [],
4552
+ "",
4553
+ "TODO: replace the pending test with a real check that FAILS on the incident and",
4554
+ "PASSES once the fix is in place. Then arm it as a deterministic gate:"
4555
+ ];
4556
+ return lines.map(comment).join("\n");
4557
+ }
4558
+ function scaffoldPostIncidentTest(lesson, options) {
4559
+ const framework = options.framework;
4560
+ const short = lessonShortName(lesson.memoryId);
4561
+ const desc = oneLine(lesson.title) || short;
4562
+ let relPath;
4563
+ let runCommand;
4564
+ let content;
4565
+ if (framework === "vitest" || framework === "jest") {
4566
+ relPath = options.outPath ?? joinRel(options.baseDir, `tests/incidents/${short}.test.ts`);
4567
+ runCommand = framework === "vitest" ? `npx vitest run ${relPath}` : `npx jest ${relPath}`;
4568
+ const hc = (l) => l ? `// ${l}` : "//";
4569
+ const importLine = framework === "vitest" ? `import { describe, it, expect } from "vitest";
4570
+
4571
+ ` : "";
4572
+ content = `${header(lesson, hc)}
4573
+ // ${proposeCommand(lesson, runCommand)}
4574
+
4575
+ ` + importLine + `describe(${JSON.stringify(desc)}, () => {
4576
+ it.todo("reproduces ${lesson.memoryId} and stays fixed");
4577
+
4578
+ // it("guards the incident", () => {
4579
+ // // Arrange the state that caused the incident, then assert the fixed behaviour.
4580
+ // expect(subjectUnderTest()).toBe(/* expected */);
4581
+ // });
4582
+ });
4583
+ `;
4584
+ } else if (framework === "pytest") {
4585
+ const fn = snake(short);
4586
+ relPath = options.outPath ?? joinRel(options.baseDir, `tests/incidents/test_${fn}.py`);
4587
+ runCommand = `pytest ${relPath}`;
4588
+ const hc = (l) => l ? `# ${l}` : "#";
4589
+ content = `${header(lesson, hc)}
4590
+ # ${proposeCommand(lesson, runCommand)}
4591
+
4592
+ import pytest
4593
+
4594
+
4595
+ @pytest.mark.skip(reason="TODO: write the post-incident assertion, then arm the sensor")
4596
+ def test_${fn}():
4597
+ # Arrange the state that caused the incident, then assert the fixed behaviour.
4598
+ assert subject_under_test() == expected
4599
+ `;
4600
+ } else {
4601
+ const fn = pascal(short);
4602
+ const dir = options.outPath ? options.outPath.replace(/\/[^/]+$/, "") : joinRel(options.baseDir, "incidents");
4603
+ relPath = options.outPath ?? joinRel(options.baseDir, `incidents/incident_${snake(short)}_test.go`);
4604
+ runCommand = `go test ./${dir}/`;
4605
+ const hc = (l) => l ? `// ${l}` : "//";
4606
+ content = `${header(lesson, hc)}
4607
+ // ${proposeCommand(lesson, runCommand)}
4608
+
4609
+ package incidents
4610
+
4611
+ import "testing"
4612
+
4613
+ func Test${fn}(t *testing.T) {
4614
+ t.Skip("TODO: write the post-incident assertion, then arm the sensor")
4615
+ // Arrange the state that caused the incident, then assert the fixed behaviour.
4616
+ }
4617
+ `;
4618
+ }
4619
+ return { framework, relPath, content, runCommand, proposeCommand: proposeCommand(lesson, runCommand) };
4620
+ }
4621
+
4489
4622
  // src/bootstrap-state.ts
4490
4623
  var CONTAINER_DIRS = /* @__PURE__ */ new Set([
4491
4624
  "packages",
@@ -5562,17 +5695,17 @@ function compactAutoRecapBody(body, maxChars = 600) {
5562
5695
  if (!isAutoRecap(body)) return body;
5563
5696
  const goalMatch = body.match(/##+\s*Goal[^\n]*\n+([^\n]+)/i);
5564
5697
  const callsMatch = body.match(/Auto-captured session \(([^)]+)\)/i);
5565
- const header = goalMatch?.[1]?.trim() ? `_${goalMatch[1].trim()}_` : callsMatch ? `_Auto-captured session (${callsMatch[1]})._` : "_Auto-captured session._";
5698
+ const header2 = goalMatch?.[1]?.trim() ? `_${goalMatch[1].trim()}_` : callsMatch ? `_Auto-captured session (${callsMatch[1]})._` : "_Auto-captured session._";
5566
5699
  const discMatch = body.match(/##+\s*Discoveries[^\n]*\n([\s\S]*?)(?=\n##+\s|\n*$)/i);
5567
5700
  const discovery = discMatch?.[1]?.trim() ?? "";
5568
5701
  const trivialDiscovery = discovery === "" || /^no (new memories|surprising)/i.test(discovery) || /No new memories saved this session\.?$/i.test(discovery);
5569
5702
  if (trivialDiscovery) {
5570
- return `${header}
5703
+ return `${header2}
5571
5704
 
5572
5705
  _No notable discoveries captured. Run post_task / \`mem_session_end\` for a richer recap._`;
5573
5706
  }
5574
5707
  const trimmed = discovery.length > maxChars ? discovery.slice(0, maxChars) + "\u2026" : discovery;
5575
- return `${header}
5708
+ return `${header2}
5576
5709
 
5577
5710
  **Discoveries:**
5578
5711
  ${trimmed}`;
@@ -5749,6 +5882,7 @@ export {
5749
5882
  SESSION_RECAP_TTL_MS,
5750
5883
  STACK_PACK_TAG,
5751
5884
  SensorSchema,
5885
+ TEST_FRAMEWORKS,
5752
5886
  USAGE_FILE,
5753
5887
  USAGE_LOG_DIR,
5754
5888
  USAGE_LOG_FILE,
@@ -5853,6 +5987,7 @@ export {
5853
5987
  isStylisticRule,
5854
5988
  isTemplateProjectContext,
5855
5989
  judgeProposedSensor,
5990
+ lessonShortName,
5856
5991
  listMarkdownFilesRecursive,
5857
5992
  literalMatchesAllTokens,
5858
5993
  literalMatchesAnyToken,
@@ -5876,11 +6011,13 @@ export {
5876
6011
  moduleNameOf,
5877
6012
  newMemoryId,
5878
6013
  normalizeFindingSeverity,
6014
+ normalizeFramework,
5879
6015
  normalizeSessionId,
5880
6016
  overallScore,
5881
6017
  parseEslintJson,
5882
6018
  parseFileAst,
5883
6019
  parseFindings,
6020
+ parseLessonFields,
5884
6021
  parseMemory,
5885
6022
  parseNpmAudit,
5886
6023
  parseSarif,
@@ -5888,6 +6025,7 @@ export {
5888
6025
  parseSonar,
5889
6026
  pathsOverlap,
5890
6027
  pickSnippetNeedle,
6028
+ pickTestFramework,
5891
6029
  planConflictResolution,
5892
6030
  planGitWatch,
5893
6031
  prepareBridgeData,
@@ -5928,6 +6066,7 @@ export {
5928
6066
  saveCodeMap,
5929
6067
  saveConfig,
5930
6068
  saveUsageIndex,
6069
+ scaffoldPostIncidentTest,
5931
6070
  scannableSensorTargets,
5932
6071
  scoreRetrievalCase,
5933
6072
  scoreSensorCase,