sverklo 0.28.2 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/dist/bin/sverklo.js +166 -4
- package/dist/bin/sverklo.js.map +1 -1
- package/dist/src/indexer/parser-tree-sitter.js +0 -1
- package/dist/src/indexer/parser-tree-sitter.js.map +1 -1
- package/dist/src/init-global.js +25 -24
- package/dist/src/init-global.js.map +1 -1
- package/dist/src/init.js +1 -0
- package/dist/src/init.js.map +1 -1
- package/dist/src/marketing/campaign-cycle.d.ts +13 -0
- package/dist/src/marketing/campaign-cycle.js +107 -0
- package/dist/src/marketing/campaign-cycle.js.map +1 -0
- package/dist/src/marketing/content-quality.d.ts +11 -0
- package/dist/src/marketing/content-quality.js +51 -0
- package/dist/src/marketing/content-quality.js.map +1 -0
- package/dist/src/marketing/content-seeding.d.ts +2 -0
- package/dist/src/marketing/content-seeding.js +105 -0
- package/dist/src/marketing/content-seeding.js.map +1 -0
- package/dist/src/marketing/decisions.d.ts +10 -0
- package/dist/src/marketing/decisions.js +142 -0
- package/dist/src/marketing/decisions.js.map +1 -0
- package/dist/src/marketing/index.d.ts +12 -0
- package/dist/src/marketing/index.js +13 -0
- package/dist/src/marketing/index.js.map +1 -0
- package/dist/src/marketing/models.d.ts +189 -0
- package/dist/src/marketing/models.js +5 -0
- package/dist/src/marketing/models.js.map +1 -0
- package/dist/src/marketing/opportunity-scout.d.ts +8 -0
- package/dist/src/marketing/opportunity-scout.js +73 -0
- package/dist/src/marketing/opportunity-scout.js.map +1 -0
- package/dist/src/marketing/profile-health.d.ts +2 -0
- package/dist/src/marketing/profile-health.js +96 -0
- package/dist/src/marketing/profile-health.js.map +1 -0
- package/dist/src/marketing/report.d.ts +4 -0
- package/dist/src/marketing/report.js +67 -0
- package/dist/src/marketing/report.js.map +1 -0
- package/dist/src/marketing/scoring.d.ts +5 -0
- package/dist/src/marketing/scoring.js +89 -0
- package/dist/src/marketing/scoring.js.map +1 -0
- package/dist/src/marketing/status.d.ts +3 -0
- package/dist/src/marketing/status.js +58 -0
- package/dist/src/marketing/status.js.map +1 -0
- package/dist/src/marketing/storage.d.ts +29 -0
- package/dist/src/marketing/storage.js +99 -0
- package/dist/src/marketing/storage.js.map +1 -0
- package/dist/src/marketing/test-fixtures.d.ts +7 -0
- package/dist/src/marketing/test-fixtures.js +31 -0
- package/dist/src/marketing/test-fixtures.js.map +1 -0
- package/dist/src/marketing/validation.d.ts +9 -0
- package/dist/src/marketing/validation.js +66 -0
- package/dist/src/marketing/validation.js.map +1 -0
- package/dist/src/prove.d.ts +6 -2
- package/dist/src/prove.js +119 -24
- package/dist/src/prove.js.map +1 -1
- package/dist/src/server/tools/review-diff.js +0 -1
- package/dist/src/server/tools/review-diff.js.map +1 -1
- package/dist/src/utils/logger.js +2 -0
- package/dist/src/utils/logger.js.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/marketing/report.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,uBAAuB,CAAC,KAAoB;IAC1D,MAAM,KAAK,GAAG,CAAC,oBAAoB,KAAK,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;IACzD,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,cAAc,KAAK,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;QACrD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,mBAAmB,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC;QAClD,KAAK,CAAC,IAAI,CAAC,wBAAwB,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAC5D,KAAK,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,iBAAiB,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC;QACrD,KAAK,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAChD,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAoB;IACtD,MAAM,KAAK,GAAG,CAAC,oBAAoB,KAAK,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,CAAC;IAClC,IAAI,CAAC,KAAK;QAAE,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,+BAA+B,CAAC;IACtE,KAAK,CAAC,IAAI,CAAC,kBAAkB,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC;IACpD,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACnD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;QAClD,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;QACpD,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACnC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAoB;IAC5D,MAAM,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC;IACpC,IAAI,CAAC,MAAM;QAAE,OAAO,qBAAqB,KAAK,CAAC,QAAQ,2CAA2C,CAAC;IACnG,MAAM,KAAK,GAAG,CAAC,qBAAqB,KAAK,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1D,KAAK,CAAC,IAAI,CAAC,UAAU,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IACrC,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC;IAC/C,KAAK,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACvD,KAAK,CAAC,IAAI,CAAC,cAAc,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC;IACnD,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC;IAC/C,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,iBAAiB,KAAK,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC;QAC/D,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,qBAAqB,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC;QACtD,KAAK,CAAC,IAAI,CAAC,qBAAqB,GAAG,CAAC,uBAAuB,EAAE,CAAC,CAAC;QAC/D,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { OpportunityScore, ScoreLevel, TrendSnapshotItem } from "./models.js";
|
|
2
|
+
export declare function scoreValue(level: ScoreLevel): number;
|
|
3
|
+
export declare function scoreLevelFromNumber(value: number): ScoreLevel;
|
|
4
|
+
export declare function computeOpportunityScore(item: TrendSnapshotItem, now?: string): OpportunityScore;
|
|
5
|
+
export declare function opportunityTopic(text: string): string;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const RELEVANCE_TERMS = [
|
|
2
|
+
"sverklo",
|
|
3
|
+
"code intelligence",
|
|
4
|
+
"codebase",
|
|
5
|
+
"repo",
|
|
6
|
+
"repository",
|
|
7
|
+
"mcp",
|
|
8
|
+
"memory",
|
|
9
|
+
"agent",
|
|
10
|
+
"coding agent",
|
|
11
|
+
"developer",
|
|
12
|
+
"local-first",
|
|
13
|
+
"ai coding",
|
|
14
|
+
"blast radius",
|
|
15
|
+
"symbol graph",
|
|
16
|
+
];
|
|
17
|
+
const RISK_TERMS = [
|
|
18
|
+
"controversy",
|
|
19
|
+
"lawsuit",
|
|
20
|
+
"harassment",
|
|
21
|
+
"hate",
|
|
22
|
+
"security breach",
|
|
23
|
+
"private leak",
|
|
24
|
+
"competitor drama",
|
|
25
|
+
"cursor vs",
|
|
26
|
+
"windsurf vs",
|
|
27
|
+
"claude vs",
|
|
28
|
+
];
|
|
29
|
+
const UNRELATED_TERMS = ["sports", "celebrity", "recipe", "weather", "crypto pump", "giveaway"];
|
|
30
|
+
export function scoreValue(level) {
|
|
31
|
+
if (level === "high")
|
|
32
|
+
return 3;
|
|
33
|
+
if (level === "medium")
|
|
34
|
+
return 2;
|
|
35
|
+
return 1;
|
|
36
|
+
}
|
|
37
|
+
export function scoreLevelFromNumber(value) {
|
|
38
|
+
if (value >= 3)
|
|
39
|
+
return "high";
|
|
40
|
+
if (value >= 2)
|
|
41
|
+
return "medium";
|
|
42
|
+
return "low";
|
|
43
|
+
}
|
|
44
|
+
export function computeOpportunityScore(item, now = new Date().toISOString()) {
|
|
45
|
+
const text = `${item.text} ${item.source_context}`.toLowerCase();
|
|
46
|
+
const matches = RELEVANCE_TERMS.filter((term) => text.includes(term));
|
|
47
|
+
const unrelated = UNRELATED_TERMS.some((term) => text.includes(term));
|
|
48
|
+
const risky = RISK_TERMS.some((term) => text.includes(term));
|
|
49
|
+
const ageHours = item.observed_at ? Math.max(0, Date.parse(now) - Date.parse(item.observed_at)) / 36e5 : 24;
|
|
50
|
+
const sverkloRelevance = unrelated ? "low" : scoreLevelFromNumber(matches.length >= 3 ? 3 : matches.length >= 1 ? 2 : 1);
|
|
51
|
+
const audienceFit = unrelated ? "low" : scoreLevelFromNumber(matches.some((term) => term.includes("developer") || term.includes("code")) ? 3 : matches.length ? 2 : 1);
|
|
52
|
+
const urgency = scoreLevelFromNumber(ageHours <= 24 ? 3 : ageHours <= 168 ? 2 : 1);
|
|
53
|
+
const novelty = scoreLevelFromNumber(text.includes("new") || text.includes("launch") || text.includes("release") ? 3 : 2);
|
|
54
|
+
const credibilityImpact = scoreLevelFromNumber(matches.some((term) => term.includes("local") || term.includes("memory") || term.includes("mcp")) ? 3 : matches.length ? 2 : 1);
|
|
55
|
+
const brandSafetyRisk = risky ? "high" : text.includes("competitor") ? "medium" : "low";
|
|
56
|
+
const positive = scoreValue(audienceFit) +
|
|
57
|
+
scoreValue(sverkloRelevance) +
|
|
58
|
+
scoreValue(urgency) +
|
|
59
|
+
scoreValue(novelty) +
|
|
60
|
+
scoreValue(credibilityImpact);
|
|
61
|
+
const riskPenalty = brandSafetyRisk === "high" ? 25 : brandSafetyRisk === "medium" ? 10 : 0;
|
|
62
|
+
const total = Math.max(0, Math.min(100, Math.round((positive / 15) * 100 - riskPenalty)));
|
|
63
|
+
const reasons = [
|
|
64
|
+
`${sverkloRelevance} Sverklo relevance`,
|
|
65
|
+
`${audienceFit} audience fit`,
|
|
66
|
+
`${urgency} timing urgency`,
|
|
67
|
+
`${brandSafetyRisk} brand-safety risk`,
|
|
68
|
+
];
|
|
69
|
+
return {
|
|
70
|
+
audience_fit: audienceFit,
|
|
71
|
+
sverklo_relevance: sverkloRelevance,
|
|
72
|
+
urgency,
|
|
73
|
+
novelty,
|
|
74
|
+
credibility_impact: credibilityImpact,
|
|
75
|
+
brand_safety_risk: brandSafetyRisk,
|
|
76
|
+
total,
|
|
77
|
+
reasons,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export function opportunityTopic(text) {
|
|
81
|
+
return text
|
|
82
|
+
.replace(/https?:\/\/\S+/g, "")
|
|
83
|
+
.replace(/[^\w\s-]/g, "")
|
|
84
|
+
.trim()
|
|
85
|
+
.split(/\s+/)
|
|
86
|
+
.slice(0, 8)
|
|
87
|
+
.join(" ");
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=scoring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoring.js","sourceRoot":"","sources":["../../../src/marketing/scoring.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export function buildStatusSummary(cycle) {
|
|
2
|
+
if (!cycle) {
|
|
3
|
+
return {
|
|
4
|
+
status: "not_initialized",
|
|
5
|
+
profile_score: 0,
|
|
6
|
+
content_coverage_days: 0,
|
|
7
|
+
next_action: "Initialize a marketing workspace and run a campaign cycle",
|
|
8
|
+
counts: { opportunities: 0, content_items: 0, profile_recommendations: 0, pending_decisions: 0 },
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
const contentItems = cycle.content_queue?.items ?? [];
|
|
12
|
+
const recommendations = cycle.profile_report?.recommendations ?? [];
|
|
13
|
+
const pendingOpportunities = cycle.opportunities.filter((item) => item.status === "needs_review" || item.status === "briefed").length;
|
|
14
|
+
const pendingContent = contentItems.filter((item) => item.approval_status === "draft" || item.approval_status === "needs_revision").length;
|
|
15
|
+
const pendingProfile = recommendations.filter((item) => item.status === "proposed").length;
|
|
16
|
+
const nextAction = nextActionFor(cycle, pendingOpportunities, pendingContent, pendingProfile);
|
|
17
|
+
return {
|
|
18
|
+
cycle_id: cycle.cycle_id,
|
|
19
|
+
status: cycle.status,
|
|
20
|
+
profile_score: cycle.profile_report?.score ?? 0,
|
|
21
|
+
content_coverage_days: cycle.content_queue?.coverage_days ?? 0,
|
|
22
|
+
top_opportunity_id: cycle.opportunities[0]?.opportunity_id,
|
|
23
|
+
next_action: nextAction,
|
|
24
|
+
top_blocker: cycle.top_blocker,
|
|
25
|
+
counts: {
|
|
26
|
+
opportunities: cycle.opportunities.length,
|
|
27
|
+
content_items: contentItems.length,
|
|
28
|
+
profile_recommendations: recommendations.length,
|
|
29
|
+
pending_decisions: pendingOpportunities + pendingContent + pendingProfile,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function renderStatusText(summary) {
|
|
34
|
+
if (summary.status === "not_initialized")
|
|
35
|
+
return `Sverklo marketing: ${summary.next_action}\n`;
|
|
36
|
+
return [
|
|
37
|
+
`Sverklo marketing: ${summary.status}`,
|
|
38
|
+
`Cycle: ${summary.cycle_id}`,
|
|
39
|
+
`Profile score: ${summary.profile_score}`,
|
|
40
|
+
`Content coverage days: ${summary.content_coverage_days}`,
|
|
41
|
+
`Top opportunity: ${summary.top_opportunity_id ?? "none"}`,
|
|
42
|
+
`Next action: ${summary.next_action}`,
|
|
43
|
+
`Top blocker: ${summary.top_blocker ?? "none"}`,
|
|
44
|
+
`Counts: ${summary.counts.opportunities} opportunities, ${summary.counts.content_items} content items, ${summary.counts.profile_recommendations} profile recommendations, ${summary.counts.pending_decisions} pending decisions`,
|
|
45
|
+
].join("\n") + "\n";
|
|
46
|
+
}
|
|
47
|
+
function nextActionFor(cycle, pendingOpportunities, pendingContent, pendingProfile) {
|
|
48
|
+
if (cycle.status === "ready")
|
|
49
|
+
return "Campaign is ready for operator-managed posting";
|
|
50
|
+
if (pendingOpportunities > 0)
|
|
51
|
+
return `Approve or reject ${pendingOpportunities} opportunity briefs`;
|
|
52
|
+
if (pendingContent > 0)
|
|
53
|
+
return `Review ${pendingContent} content drafts`;
|
|
54
|
+
if (pendingProfile > 0)
|
|
55
|
+
return `Review ${pendingProfile} profile recommendations`;
|
|
56
|
+
return cycle.top_blocker ? `Resolve blocker: ${cycle.top_blocker}` : "Run a campaign cycle with fresh inputs";
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/marketing/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { CampaignCycle, CampaignWorkspace, OperatorDecision } from "./models.js";
|
|
2
|
+
export interface MarketingPaths {
|
|
3
|
+
root: string;
|
|
4
|
+
workspace: string;
|
|
5
|
+
inputs: string;
|
|
6
|
+
cycles: string;
|
|
7
|
+
reports: string;
|
|
8
|
+
decisions: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function resolveMarketingWorkspace(path?: string): string;
|
|
11
|
+
export declare function marketingPaths(root: string): MarketingPaths;
|
|
12
|
+
export declare function ensureMarketingDirs(root: string): MarketingPaths;
|
|
13
|
+
export declare function jsonFile<T>(path: string): T;
|
|
14
|
+
export declare function maybeJsonFile<T>(path: string): T | undefined;
|
|
15
|
+
export declare function writeJsonFile(path: string, value: unknown): void;
|
|
16
|
+
export declare function initMarketingWorkspace(input: {
|
|
17
|
+
workspacePath?: string;
|
|
18
|
+
accountHandle: string;
|
|
19
|
+
now?: string;
|
|
20
|
+
}): CampaignWorkspace;
|
|
21
|
+
export declare function loadMarketingWorkspace(workspacePath?: string): CampaignWorkspace;
|
|
22
|
+
export declare function saveMarketingWorkspace(workspacePath: string | undefined, workspace: CampaignWorkspace): void;
|
|
23
|
+
export declare function cyclePath(root: string, cycleId: string): string;
|
|
24
|
+
export declare function saveCampaignCycle(workspacePath: string | undefined, cycle: CampaignCycle): void;
|
|
25
|
+
export declare function loadCampaignCycle(workspacePath: string | undefined, cycleId: string): CampaignCycle;
|
|
26
|
+
export declare function loadActiveCampaignCycle(workspacePath: string | undefined, workspace: CampaignWorkspace): CampaignCycle | undefined;
|
|
27
|
+
export declare function appendOperatorDecision(workspacePath: string | undefined, decision: OperatorDecision): void;
|
|
28
|
+
export declare function reportPath(workspacePath: string | undefined, cycleId: string, kind: string): string;
|
|
29
|
+
export declare function writeReport(workspacePath: string | undefined, cycleId: string, kind: string, content: string): void;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync, } from "node:fs";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { DEFAULT_POSITIONING_PHRASES as PHRASES } from "./models.js";
|
|
4
|
+
export function resolveMarketingWorkspace(path) {
|
|
5
|
+
return resolve(path ?? ".sverklo/marketing");
|
|
6
|
+
}
|
|
7
|
+
export function marketingPaths(root) {
|
|
8
|
+
return {
|
|
9
|
+
root,
|
|
10
|
+
workspace: join(root, "workspace.json"),
|
|
11
|
+
inputs: join(root, "inputs"),
|
|
12
|
+
cycles: join(root, "cycles"),
|
|
13
|
+
reports: join(root, "reports"),
|
|
14
|
+
decisions: join(root, "decisions.jsonl"),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function ensureMarketingDirs(root) {
|
|
18
|
+
const paths = marketingPaths(root);
|
|
19
|
+
for (const dir of [paths.root, paths.inputs, paths.cycles, paths.reports]) {
|
|
20
|
+
mkdirSync(dir, { recursive: true });
|
|
21
|
+
}
|
|
22
|
+
return paths;
|
|
23
|
+
}
|
|
24
|
+
export function jsonFile(path) {
|
|
25
|
+
return JSON.parse(readFileSync(path, "utf-8"));
|
|
26
|
+
}
|
|
27
|
+
export function maybeJsonFile(path) {
|
|
28
|
+
if (!existsSync(path))
|
|
29
|
+
return undefined;
|
|
30
|
+
return jsonFile(path);
|
|
31
|
+
}
|
|
32
|
+
export function writeJsonFile(path, value) {
|
|
33
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
34
|
+
writeFileSync(path, JSON.stringify(value, null, 2) + "\n");
|
|
35
|
+
}
|
|
36
|
+
export function initMarketingWorkspace(input) {
|
|
37
|
+
const root = resolveMarketingWorkspace(input.workspacePath);
|
|
38
|
+
const paths = ensureMarketingDirs(root);
|
|
39
|
+
const now = input.now ?? new Date().toISOString();
|
|
40
|
+
const existing = maybeJsonFile(paths.workspace);
|
|
41
|
+
const workspace = {
|
|
42
|
+
workspace_id: existing?.workspace_id ?? `workspace-${Date.now()}`,
|
|
43
|
+
account_handle: input.accountHandle,
|
|
44
|
+
active_cycle_id: existing?.active_cycle_id,
|
|
45
|
+
positioning_phrases: existing?.positioning_phrases?.length
|
|
46
|
+
? existing.positioning_phrases
|
|
47
|
+
: [...PHRASES],
|
|
48
|
+
blocked_topics: existing?.blocked_topics ?? [],
|
|
49
|
+
created_at: existing?.created_at ?? now,
|
|
50
|
+
updated_at: now,
|
|
51
|
+
};
|
|
52
|
+
writeJsonFile(paths.workspace, workspace);
|
|
53
|
+
return workspace;
|
|
54
|
+
}
|
|
55
|
+
export function loadMarketingWorkspace(workspacePath) {
|
|
56
|
+
const root = resolveMarketingWorkspace(workspacePath);
|
|
57
|
+
const path = marketingPaths(root).workspace;
|
|
58
|
+
if (!existsSync(path)) {
|
|
59
|
+
throw new Error(`marketing workspace not initialized: ${root}`);
|
|
60
|
+
}
|
|
61
|
+
return jsonFile(path);
|
|
62
|
+
}
|
|
63
|
+
export function saveMarketingWorkspace(workspacePath, workspace) {
|
|
64
|
+
const root = resolveMarketingWorkspace(workspacePath);
|
|
65
|
+
ensureMarketingDirs(root);
|
|
66
|
+
writeJsonFile(marketingPaths(root).workspace, workspace);
|
|
67
|
+
}
|
|
68
|
+
export function cyclePath(root, cycleId) {
|
|
69
|
+
return join(marketingPaths(root).cycles, `${cycleId}.json`);
|
|
70
|
+
}
|
|
71
|
+
export function saveCampaignCycle(workspacePath, cycle) {
|
|
72
|
+
const root = resolveMarketingWorkspace(workspacePath);
|
|
73
|
+
ensureMarketingDirs(root);
|
|
74
|
+
writeJsonFile(cyclePath(root, cycle.cycle_id), cycle);
|
|
75
|
+
}
|
|
76
|
+
export function loadCampaignCycle(workspacePath, cycleId) {
|
|
77
|
+
const root = resolveMarketingWorkspace(workspacePath);
|
|
78
|
+
return jsonFile(cyclePath(root, cycleId));
|
|
79
|
+
}
|
|
80
|
+
export function loadActiveCampaignCycle(workspacePath, workspace) {
|
|
81
|
+
if (!workspace.active_cycle_id)
|
|
82
|
+
return undefined;
|
|
83
|
+
const root = resolveMarketingWorkspace(workspacePath);
|
|
84
|
+
const path = cyclePath(root, workspace.active_cycle_id);
|
|
85
|
+
return maybeJsonFile(path);
|
|
86
|
+
}
|
|
87
|
+
export function appendOperatorDecision(workspacePath, decision) {
|
|
88
|
+
const root = resolveMarketingWorkspace(workspacePath);
|
|
89
|
+
const paths = ensureMarketingDirs(root);
|
|
90
|
+
appendFileSync(paths.decisions, JSON.stringify(decision) + "\n");
|
|
91
|
+
}
|
|
92
|
+
export function reportPath(workspacePath, cycleId, kind) {
|
|
93
|
+
const root = resolveMarketingWorkspace(workspacePath);
|
|
94
|
+
return join(marketingPaths(root).reports, `${cycleId}-${kind}.md`);
|
|
95
|
+
}
|
|
96
|
+
export function writeReport(workspacePath, cycleId, kind, content) {
|
|
97
|
+
writeFileSync(reportPath(workspacePath, cycleId, kind), content.endsWith("\n") ? content : `${content}\n`);
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/marketing/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CampaignWorkspace, EvidenceCatalog, ProfileSnapshot, RecentPostsSnapshot, TrendSnapshot } from "./models.js";
|
|
2
|
+
export declare function fixtureJson<T>(name: string): T;
|
|
3
|
+
export declare function trendFixture(): TrendSnapshot;
|
|
4
|
+
export declare function evidenceFixture(): EvidenceCatalog;
|
|
5
|
+
export declare function recentPostsFixture(): RecentPostsSnapshot;
|
|
6
|
+
export declare function profileFixture(): ProfileSnapshot;
|
|
7
|
+
export declare function workspaceFixture(overrides?: Partial<CampaignWorkspace>): CampaignWorkspace;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
const fixturesDir = join(dirname(fileURLToPath(import.meta.url)), "fixtures");
|
|
5
|
+
export function fixtureJson(name) {
|
|
6
|
+
return JSON.parse(readFileSync(join(fixturesDir, name), "utf-8"));
|
|
7
|
+
}
|
|
8
|
+
export function trendFixture() {
|
|
9
|
+
return fixtureJson("trend-snapshot.json");
|
|
10
|
+
}
|
|
11
|
+
export function evidenceFixture() {
|
|
12
|
+
return fixtureJson("evidence.json");
|
|
13
|
+
}
|
|
14
|
+
export function recentPostsFixture() {
|
|
15
|
+
return fixtureJson("recent-posts.json");
|
|
16
|
+
}
|
|
17
|
+
export function profileFixture() {
|
|
18
|
+
return fixtureJson("profile-snapshot.json");
|
|
19
|
+
}
|
|
20
|
+
export function workspaceFixture(overrides = {}) {
|
|
21
|
+
return {
|
|
22
|
+
workspace_id: "workspace-test",
|
|
23
|
+
account_handle: "@sverklo",
|
|
24
|
+
positioning_phrases: ["local-first code intel", "repo memory for coding agents"],
|
|
25
|
+
blocked_topics: [],
|
|
26
|
+
created_at: "2026-05-30T15:00:00Z",
|
|
27
|
+
updated_at: "2026-05-30T15:00:00Z",
|
|
28
|
+
...overrides,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=test-fixtures.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-fixtures.js","sourceRoot":"","sources":["../../../src/marketing/test-fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AASzC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;AAE9E,MAAM,UAAU,WAAW,CAAI,IAAY;IACzC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAM,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,WAAW,CAAgB,qBAAqB,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,WAAW,CAAkB,eAAe,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,WAAW,CAAsB,mBAAmB,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,WAAW,CAAkB,uBAAuB,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,YAAwC,EAAE;IACzE,OAAO;QACL,YAAY,EAAE,gBAAgB;QAC9B,cAAc,EAAE,UAAU;QAC1B,mBAAmB,EAAE,CAAC,wBAAwB,EAAE,+BAA+B,CAAC;QAChF,cAAc,EAAE,EAAE;QAClB,UAAU,EAAE,sBAAsB;QAClC,UAAU,EAAE,sBAAsB;QAClC,GAAG,SAAS;KACb,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CampaignWorkspace, EvidenceCatalog, OperatorDecision, ProfileSnapshot, RecentPostsSnapshot, TrendSnapshot } from "./models.js";
|
|
2
|
+
export declare function normalizeAccountHandle(handle: string): string;
|
|
3
|
+
export declare function assertTrendSnapshot(snapshot: TrendSnapshot): void;
|
|
4
|
+
export declare function assertProfileSnapshot(snapshot: ProfileSnapshot): void;
|
|
5
|
+
export declare function assertRecentPostsSnapshot(snapshot: RecentPostsSnapshot): void;
|
|
6
|
+
export declare function assertEvidenceCatalog(catalog: EvidenceCatalog): void;
|
|
7
|
+
export declare function assertDecision(decision: OperatorDecision): void;
|
|
8
|
+
export declare function textMatchesBlockedTopic(workspace: CampaignWorkspace, text: string): string | undefined;
|
|
9
|
+
export declare function looksPrivateOrConfidential(text: string): boolean;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export function normalizeAccountHandle(handle) {
|
|
2
|
+
const trimmed = handle.trim();
|
|
3
|
+
if (!trimmed)
|
|
4
|
+
throw new Error("account handle is required");
|
|
5
|
+
const normalized = trimmed.startsWith("@") ? trimmed : `@${trimmed}`;
|
|
6
|
+
if (!/^@[A-Za-z0-9_]{1,15}$/.test(normalized)) {
|
|
7
|
+
throw new Error(`invalid account handle: ${handle}`);
|
|
8
|
+
}
|
|
9
|
+
return normalized;
|
|
10
|
+
}
|
|
11
|
+
export function assertTrendSnapshot(snapshot) {
|
|
12
|
+
if (!snapshot || !snapshot.captured_at || !snapshot.source_label) {
|
|
13
|
+
throw new Error("trend snapshot requires captured_at and source_label");
|
|
14
|
+
}
|
|
15
|
+
if (!Array.isArray(snapshot.items))
|
|
16
|
+
throw new Error("trend snapshot items must be an array");
|
|
17
|
+
for (const item of snapshot.items) {
|
|
18
|
+
if (!item.id || !item.text || !item.source_context) {
|
|
19
|
+
throw new Error("each trend item requires id, text, and source_context");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function assertProfileSnapshot(snapshot) {
|
|
24
|
+
if (!snapshot || !snapshot.captured_at)
|
|
25
|
+
throw new Error("profile snapshot requires captured_at");
|
|
26
|
+
normalizeAccountHandle(snapshot.account_handle);
|
|
27
|
+
if (!snapshot.display_name.trim())
|
|
28
|
+
throw new Error("profile snapshot requires display_name");
|
|
29
|
+
if (!snapshot.bio.trim())
|
|
30
|
+
throw new Error("profile snapshot requires bio");
|
|
31
|
+
}
|
|
32
|
+
export function assertRecentPostsSnapshot(snapshot) {
|
|
33
|
+
if (!snapshot || !snapshot.captured_at)
|
|
34
|
+
throw new Error("recent posts snapshot requires captured_at");
|
|
35
|
+
if (!Array.isArray(snapshot.posts))
|
|
36
|
+
throw new Error("recent posts must be an array");
|
|
37
|
+
for (const post of snapshot.posts) {
|
|
38
|
+
if (!post.id || !post.text || !post.posted_at) {
|
|
39
|
+
throw new Error("each recent post requires id, text, and posted_at");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function assertEvidenceCatalog(catalog) {
|
|
44
|
+
if (!catalog || !Array.isArray(catalog.items))
|
|
45
|
+
throw new Error("evidence catalog requires items");
|
|
46
|
+
for (const item of catalog.items) {
|
|
47
|
+
if (!item.evidence_id || !item.claim || !item.source_type || !item.source_path_or_url || !item.verified_at) {
|
|
48
|
+
throw new Error("each evidence item requires id, claim, source_type, source_path_or_url, and verified_at");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export function assertDecision(decision) {
|
|
53
|
+
if (!decision.target_type || !decision.target_id || !decision.decision || !decision.created_at) {
|
|
54
|
+
throw new Error("decision requires target_type, target_id, decision, and created_at");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export function textMatchesBlockedTopic(workspace, text) {
|
|
58
|
+
const lower = text.toLowerCase();
|
|
59
|
+
return workspace.blocked_topics.find((topic) => topic.trim() && lower.includes(topic.toLowerCase()));
|
|
60
|
+
}
|
|
61
|
+
export function looksPrivateOrConfidential(text) {
|
|
62
|
+
return (/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i.test(text) ||
|
|
63
|
+
/\b(?:\+?\d[\d .-]{8,}\d)\b/.test(text) ||
|
|
64
|
+
/\b(api[_-]?key|secret|password|private customer|confidential)\b/i.test(text));
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/marketing/validation.ts"],"names":[],"mappings":"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"}
|
package/dist/src/prove.d.ts
CHANGED
|
@@ -29,6 +29,10 @@ export interface ProveIndex {
|
|
|
29
29
|
getImpact(targetName: string, limit?: number): ImpactResult[];
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
export
|
|
33
|
-
export
|
|
32
|
+
export type ProveFormat = "text" | "markdown";
|
|
33
|
+
export interface ProveReportOptions {
|
|
34
|
+
format?: ProveFormat;
|
|
35
|
+
}
|
|
36
|
+
export declare function buildProveReport(indexer: ProveIndex, projectPath: string, options?: ProveReportOptions): string;
|
|
37
|
+
export declare function runProve(projectPath: string, options?: ProveReportOptions): Promise<string>;
|
|
34
38
|
export {};
|