@sellable/mcp 0.1.136 → 0.1.138
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/agents/post-find-leads-filter-scout.md +19 -25
- package/agents/post-find-leads-message-scout.md +21 -0
- package/agents/registry.json +9 -16
- package/agents/source-scout-linkedin-engagement.md +2 -2
- package/dist/engage-memory.d.ts +13 -0
- package/dist/engage-memory.js +129 -34
- package/dist/identity-compiler.d.ts +119 -0
- package/dist/identity-compiler.js +344 -0
- package/dist/identity-memory.d.ts +49 -0
- package/dist/identity-memory.js +89 -0
- package/dist/index-dev.js +0 -0
- package/dist/index.js +0 -0
- package/dist/tools/bootstrap.js +1 -1
- package/dist/tools/engage-memory.js +2 -2
- package/dist/tools/navigation.js +3 -0
- package/dist/tools/prompts.d.ts +1 -4
- package/dist/tools/prompts.js +3 -3
- package/package.json +1 -1
- package/skills/craft-message/SKILL.md +13 -4
- package/skills/create-campaign/references/brief-template.md +2 -1
- package/skills/create-campaign-v2/SKILL.md +150 -1342
- package/skills/create-campaign-v2/core/flow.v2.json +471 -1970
- package/skills/create-post/SKILL.md +54 -9
- package/skills/engage/SKILL.md +37 -15
- package/skills/engage/core/README.md +18 -12
- package/skills/generate-messages/SKILL.md +15 -5
- package/skills/interview/SKILL.md +183 -89
- package/skills/interview/references/anti-ai-audit.md +101 -0
- package/skills/interview/references/compiler-schema.md +94 -0
- package/skills/interview/references/legacy-linkedin-interview.md +118 -0
- package/skills/interview/references/question-bank.md +123 -0
- package/skills/interview/references/reference-curation.md +68 -0
- package/skills/interview/references/voice-capture-method.md +62 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
You are Lead Fit Builder for Sellable create-campaign-v2.
|
|
2
2
|
|
|
3
|
-
Your job starts only after
|
|
4
|
-
|
|
3
|
+
Your job starts only after the lead source has been approved or auto-confirmed
|
|
4
|
+
and the bounded review batch exists in the campaign table.
|
|
5
5
|
Work only on the lead filter branch. Do not source new leads, draft messages,
|
|
6
6
|
import leads, create campaigns, or ask the user questions. Your only live
|
|
7
7
|
campaign mutation is calling `save_rubrics` after the production rubrics are
|
|
@@ -9,41 +9,38 @@ ready.
|
|
|
9
9
|
|
|
10
10
|
Required inputs:
|
|
11
11
|
|
|
12
|
-
- `
|
|
13
|
-
- `
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
12
|
+
- `campaignId`
|
|
13
|
+
- campaign revision or `campaignUpdatedAt`
|
|
14
|
+
- campaign brief content
|
|
15
|
+
- selected source decision and provider/list state
|
|
16
|
+
- `selectedLeadListId`
|
|
17
|
+
- `workflowTableId`
|
|
18
|
+
- imported review-batch rows, including row ids/hash when available
|
|
19
|
+
- filter choice
|
|
17
20
|
|
|
18
21
|
Required first steps:
|
|
19
22
|
|
|
20
|
-
1.
|
|
21
|
-
|
|
23
|
+
1. Verify the campaign/source/table ids from the parent thread match the live
|
|
24
|
+
campaign context.
|
|
25
|
+
2. Load the filter-leads reference before designing rubrics:
|
|
22
26
|
`get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "references/filter-leads.md" })`.
|
|
23
27
|
3. Treat campaign state and the campaign table sample as the input of record.
|
|
24
|
-
|
|
28
|
+
Do not require or hunt for local markdown/json artifacts.
|
|
25
29
|
|
|
26
30
|
Owned outputs:
|
|
27
31
|
|
|
28
32
|
- Durable campaign rubrics via `save_rubrics({ campaignOfferId, leadScoringRubrics })`
|
|
29
33
|
when the filter is confirmed and production-shaped rubrics are safe to write.
|
|
30
34
|
`save_rubrics` is the durable writer.
|
|
31
|
-
-
|
|
32
|
-
- `rubric.json` debug artifact after the durable campaign write
|
|
35
|
+
- concise filter/rubric summary returned to the parent thread
|
|
33
36
|
|
|
34
|
-
Do not write or modify
|
|
35
|
-
|
|
36
|
-
- `message-validation.md`
|
|
37
|
-
- `message-review.md`
|
|
38
|
-
- `approval-packet.md`
|
|
39
|
-
- `brief.md`
|
|
40
|
-
- `lead-review.md`
|
|
41
|
-
- `lead-sample.json`
|
|
37
|
+
Do not write or modify local markdown/json artifacts. Durable output is only
|
|
38
|
+
via `save_rubrics` plus the parent-thread summary.
|
|
42
39
|
|
|
43
40
|
Process:
|
|
44
41
|
|
|
45
|
-
1. Preserve the approved source decision and
|
|
46
|
-
|
|
42
|
+
1. Preserve the approved source decision and review-batch sample math supplied
|
|
43
|
+
by the parent; do not re-run sourcing.
|
|
47
44
|
2. Turn the sample's good-fit and false-positive patterns into a strict but
|
|
48
45
|
campaign-native filter.
|
|
49
46
|
3. Include keep rules, exclude rules, sample false positives, pass-rate /
|
|
@@ -56,14 +53,11 @@ Process:
|
|
|
56
53
|
6. If status is `confirmed`, call `save_rubrics` with 2-5 production-shaped
|
|
57
54
|
active `leadScoringRubrics` before reporting success. If `save_rubrics`
|
|
58
55
|
fails, stop and report the blocker; do not claim the filter is persisted.
|
|
59
|
-
7. Write `lead-filter.md` and `rubric.json` only as debug artifacts after
|
|
60
|
-
campaign persistence succeeds.
|
|
61
56
|
|
|
62
57
|
Return a concise final status with:
|
|
63
58
|
|
|
64
59
|
- filter status: `confirmed`, `confirm-with-user`, or `revise-find-leads`
|
|
65
60
|
- whether `save_rubrics` succeeded and how many active rubrics were persisted
|
|
66
|
-
- artifacts written
|
|
67
61
|
- strongest keep rules
|
|
68
62
|
- strongest exclusion rules
|
|
69
63
|
- expected pass-rate / yield impact
|
|
@@ -80,6 +80,27 @@ When reporting branch runtime proof, use this shape under
|
|
|
80
80
|
Do not tell the UI to show Message Draft Builder as running unless this proof
|
|
81
81
|
exists and points at the current non-empty bounded review batch.
|
|
82
82
|
|
|
83
|
+
## Basis Changes And Rewrites
|
|
84
|
+
|
|
85
|
+
The first completed recommendation is the default message review candidate.
|
|
86
|
+
Do not automatically retry or regenerate only because Lead Fit Builder finished,
|
|
87
|
+
rubrics were saved, Filter Leads completed, enrichment cells populated, or more
|
|
88
|
+
row data became available after this branch started.
|
|
89
|
+
|
|
90
|
+
Treat later filter/enrichment data as optional rewrite context. If campaign id,
|
|
91
|
+
brief hash, selected source, `selectedLeadListId`, `workflowTableId`, and
|
|
92
|
+
review-batch row ids/hash still match, keep the initial recommendation usable
|
|
93
|
+
and report `status: ready` with `basisStatus: "usable_initial"` or
|
|
94
|
+
`"enriched_rewrite_available"`. The parent thread may offer the user a choice
|
|
95
|
+
to keep the initial draft or rewrite with enriched/filter data, but the rewrite
|
|
96
|
+
must be explicit user opt-in.
|
|
97
|
+
|
|
98
|
+
Retry or regenerate without asking only when the initial recommendation is
|
|
99
|
+
missing, failed, structurally invalid, unsafe, or mismatched on campaign id,
|
|
100
|
+
brief hash, selected source, `selectedLeadListId`, `workflowTableId`, or
|
|
101
|
+
review-batch rows. Filter/rubric/enrichment basis drift alone is not a stale
|
|
102
|
+
blocker.
|
|
103
|
+
|
|
83
104
|
## Hard Rules
|
|
84
105
|
|
|
85
106
|
- Do not call product Generate Message cells. This worker drafts the template
|
package/agents/registry.json
CHANGED
|
@@ -158,22 +158,20 @@
|
|
|
158
158
|
"displayName": "Lead Fit Builder",
|
|
159
159
|
"target": "filter-leads",
|
|
160
160
|
"inputs": [
|
|
161
|
-
"
|
|
162
|
-
"
|
|
163
|
-
"
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
"lead-filter.md"
|
|
167
|
-
],
|
|
168
|
-
"optionalProducesArtifacts": [
|
|
169
|
-
"rubric.json"
|
|
161
|
+
"campaignId",
|
|
162
|
+
"campaignBrief",
|
|
163
|
+
"source decision and selectedLeadList/source state",
|
|
164
|
+
"workflowTableId",
|
|
165
|
+
"imported review-batch rows"
|
|
170
166
|
],
|
|
167
|
+
"producesArtifacts": [],
|
|
168
|
+
"optionalProducesArtifacts": [],
|
|
171
169
|
"ownership": "lead quality, false-positive patterns, keep/exclude rules, ability-to-pay checks, and production rubric translation only",
|
|
172
170
|
"codex": {
|
|
173
171
|
"description": "Lead Fit Builder for campaign-backed lead filtering and rubric persistence after source approval.",
|
|
174
172
|
"model": "gpt-5.5",
|
|
175
173
|
"modelReasoningEffort": "high",
|
|
176
|
-
"sandboxMode": "
|
|
174
|
+
"sandboxMode": "read-only",
|
|
177
175
|
"nicknameCandidates": [
|
|
178
176
|
"Lead Fit Builder",
|
|
179
177
|
"Fit Builder",
|
|
@@ -181,17 +179,12 @@
|
|
|
181
179
|
]
|
|
182
180
|
},
|
|
183
181
|
"claude": {
|
|
184
|
-
"description": "Use proactively as Lead Fit Builder after lead source approval to persist campaign rubrics
|
|
182
|
+
"description": "Use proactively as Lead Fit Builder after lead source approval to persist campaign rubrics from campaign state.",
|
|
185
183
|
"model": "inherit",
|
|
186
184
|
"background": true,
|
|
187
185
|
"maxTurns": 8,
|
|
188
186
|
"color": "yellow",
|
|
189
187
|
"tools": [
|
|
190
|
-
"Read",
|
|
191
|
-
"Write",
|
|
192
|
-
"Edit",
|
|
193
|
-
"Grep",
|
|
194
|
-
"Glob",
|
|
195
188
|
"mcp__sellable__get_subskill_prompt",
|
|
196
189
|
"mcp__sellable__get_subskill_asset",
|
|
197
190
|
"mcp__sellable__save_rubrics"
|
|
@@ -9,8 +9,8 @@ Required first step:
|
|
|
9
9
|
"signal-discovery", campaignOfferId, confirmed: true })` and include that same
|
|
10
10
|
`campaignOfferId` plus `currentStep: "signal-discovery"` in `search_signals`
|
|
11
11
|
so the owning search route can show the source lane with current find-leads
|
|
12
|
-
narration and user options. Treat that as a campaign-attached persisted
|
|
13
|
-
|
|
12
|
+
narration and user options. Treat that as a campaign-attached persisted search;
|
|
13
|
+
do not run a post-mint search without the campaign ID. If no campaign
|
|
14
14
|
ID is supplied, run campaignless preview mode.
|
|
15
15
|
|
|
16
16
|
Use the inherited Sellable MCP tools when available:
|
package/dist/engage-memory.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type IdentityMemoryChunk, type IdentityMemoryDirectory } from "./identity-memory.js";
|
|
1
2
|
export interface EngageStyleGuide {
|
|
2
3
|
markdown: string;
|
|
3
4
|
updatedAt: string;
|
|
@@ -20,6 +21,18 @@ export interface EngageMemory {
|
|
|
20
21
|
styleGuide?: EngageStyleGuide;
|
|
21
22
|
provenSearches: ProvenSearch[];
|
|
22
23
|
trackedPeople: TrackedPerson[];
|
|
24
|
+
identity?: IdentityMemoryChunk;
|
|
25
|
+
company?: IdentityMemoryChunk;
|
|
26
|
+
antiAiStyle?: IdentityMemoryChunk;
|
|
27
|
+
proofLedger?: IdentityMemoryChunk;
|
|
28
|
+
winsLedger?: IdentityMemoryChunk;
|
|
29
|
+
storyBank?: IdentityMemoryChunk;
|
|
30
|
+
answerBank?: IdentityMemoryChunk;
|
|
31
|
+
contextModes?: IdentityMemoryChunk;
|
|
32
|
+
decisionRules?: IdentityMemoryChunk;
|
|
33
|
+
changeLog?: IdentityMemoryChunk;
|
|
34
|
+
transcripts?: IdentityMemoryDirectory;
|
|
35
|
+
references?: IdentityMemoryDirectory;
|
|
23
36
|
}
|
|
24
37
|
/** Check if a sender has per-sender config directory. */
|
|
25
38
|
export declare function senderHasConfig(senderId: string): boolean;
|
package/dist/engage-memory.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
|
+
import * as os from "os";
|
|
2
3
|
import * as path from "path";
|
|
4
|
+
import { readIdentityMemory, } from "./identity-memory.js";
|
|
3
5
|
// ── Config directory resolution ────────────────────────────────────────────
|
|
4
6
|
function resolveConfigsDir() {
|
|
5
7
|
const candidates = [];
|
|
@@ -11,6 +13,7 @@ function resolveConfigsDir() {
|
|
|
11
13
|
candidates.push(path.resolve(path.dirname(process.argv[1]), "../../.sellable/configs"));
|
|
12
14
|
}
|
|
13
15
|
candidates.push(path.resolve(process.cwd(), ".sellable/configs"));
|
|
16
|
+
candidates.push(path.resolve(os.homedir(), ".sellable/configs"));
|
|
14
17
|
for (const candidate of candidates) {
|
|
15
18
|
if (fs.existsSync(candidate)) {
|
|
16
19
|
return candidate;
|
|
@@ -44,22 +47,21 @@ function writeFile(relPath, content) {
|
|
|
44
47
|
fs.writeFileSync(fullPath, content);
|
|
45
48
|
}
|
|
46
49
|
// ── Sender-scoped path resolution ─────────────────────────────────────────
|
|
47
|
-
/** Per-sender file
|
|
48
|
-
* Falls back to legacy flat path when senderId is omitted or sender dir doesn't exist. */
|
|
50
|
+
/** Per-sender reads fall back by file so partial sender dirs do not hide flat memory. */
|
|
49
51
|
function senderPath(senderId, fileName, flatFallback) {
|
|
50
52
|
if (senderId) {
|
|
51
|
-
const
|
|
52
|
-
const senderFile = `${senderDir}/${fileName}`;
|
|
53
|
-
// If sender dir exists, always use it (even if file doesn't exist yet — it'll be created)
|
|
54
|
-
if (fs.existsSync(path.join(getConfigsDir(), senderDir))) {
|
|
55
|
-
return senderFile;
|
|
56
|
-
}
|
|
57
|
-
// If the file exists in sender dir (dir just created), use it
|
|
53
|
+
const senderFile = `senders/${senderId}/${fileName}`;
|
|
58
54
|
if (fs.existsSync(path.join(getConfigsDir(), senderFile))) {
|
|
59
55
|
return senderFile;
|
|
60
56
|
}
|
|
61
57
|
}
|
|
62
|
-
|
|
58
|
+
return flatFallback;
|
|
59
|
+
}
|
|
60
|
+
/** Per-sender writes are deterministic when a sender ID is supplied. */
|
|
61
|
+
function senderWritePath(senderId, fileName, flatFallback) {
|
|
62
|
+
if (senderId) {
|
|
63
|
+
return `senders/${senderId}/${fileName}`;
|
|
64
|
+
}
|
|
63
65
|
return flatFallback;
|
|
64
66
|
}
|
|
65
67
|
/** Check if a sender has per-sender config directory. */
|
|
@@ -119,39 +121,132 @@ function buildMarkdownTable(headers, rows) {
|
|
|
119
121
|
// ── Style guide ────────────────────────────────────────────────────────────
|
|
120
122
|
const FLAT_STYLE_CORE_PATH = "writing/styleguide-core.md";
|
|
121
123
|
const STYLE_COMMENTS_PATH = "writing/comments.md";
|
|
122
|
-
|
|
124
|
+
const LEGACY_AUDIENCE_ICP_PATH = "audience/icp.md";
|
|
125
|
+
const LEGACY_FAQS_CORE_PATH = "faqs/core.md";
|
|
126
|
+
function readStyleGuide(senderId, identityMemory) {
|
|
123
127
|
const corePath = senderPath(senderId, "styleguide-core.md", FLAT_STYLE_CORE_PATH);
|
|
124
128
|
const core = readFile(corePath);
|
|
125
129
|
// comments.md is always shared
|
|
126
130
|
const comments = readFile(STYLE_COMMENTS_PATH);
|
|
127
|
-
if (!
|
|
128
|
-
|
|
131
|
+
if (!hasCoreIdentityMemory(identityMemory)) {
|
|
132
|
+
if (!core && !comments)
|
|
133
|
+
return undefined;
|
|
134
|
+
const legacyParts = [];
|
|
135
|
+
if (core)
|
|
136
|
+
legacyParts.push(core.trim());
|
|
137
|
+
if (comments)
|
|
138
|
+
legacyParts.push(comments.trim());
|
|
139
|
+
return {
|
|
140
|
+
markdown: legacyParts.join("\n\n"),
|
|
141
|
+
updatedAt: latestUpdatedAt([corePath, STYLE_COMMENTS_PATH]),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
129
144
|
const parts = [];
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
145
|
+
const sourcePaths = [];
|
|
146
|
+
parts.push("# Sellable Core Identity Memory");
|
|
147
|
+
appendCoreSection(parts, sourcePaths, "Core Identity", identityMemory.identity);
|
|
148
|
+
appendCoreSection(parts, sourcePaths, "Core Company", identityMemory.company);
|
|
149
|
+
appendCoreSection(parts, sourcePaths, "Core Anti-AI Writing Style", identityMemory.antiAiStyle);
|
|
150
|
+
appendCoreSection(parts, sourcePaths, "Core Proof Ledger", identityMemory.proofLedger);
|
|
151
|
+
appendCoreSection(parts, sourcePaths, "Core Wins Ledger", identityMemory.winsLedger);
|
|
152
|
+
appendCoreSection(parts, sourcePaths, "Core Story Bank", identityMemory.storyBank);
|
|
153
|
+
appendCoreSection(parts, sourcePaths, "Core Answer Bank", identityMemory.answerBank);
|
|
154
|
+
appendCoreSection(parts, sourcePaths, "Core Context Modes", identityMemory.contextModes);
|
|
155
|
+
appendCoreSection(parts, sourcePaths, "Core Decision Rules", identityMemory.decisionRules);
|
|
156
|
+
appendCoreSection(parts, sourcePaths, "Core Change Log", identityMemory.changeLog);
|
|
157
|
+
appendCoreDirectoryIndex(parts, sourcePaths, "Core Transcripts Index", identityMemory.transcripts);
|
|
158
|
+
appendCoreDirectoryIndex(parts, sourcePaths, "Core References Index", identityMemory.references);
|
|
159
|
+
if (core) {
|
|
160
|
+
appendCompatibilitySection(parts, sourcePaths, {
|
|
161
|
+
title: senderId
|
|
162
|
+
? "Legacy Compatibility: Connected Sender Style Guide"
|
|
163
|
+
: "Legacy Compatibility: Style Guide",
|
|
164
|
+
relativePath: corePath,
|
|
165
|
+
markdown: core,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
if (comments) {
|
|
169
|
+
appendCompatibilitySection(parts, sourcePaths, {
|
|
170
|
+
title: "Legacy Compatibility: Comment Rules",
|
|
171
|
+
relativePath: STYLE_COMMENTS_PATH,
|
|
172
|
+
markdown: comments,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
const legacyAudienceIcp = readFile(LEGACY_AUDIENCE_ICP_PATH);
|
|
176
|
+
if (!identityMemory.company && legacyAudienceIcp) {
|
|
177
|
+
appendCompatibilitySection(parts, sourcePaths, {
|
|
178
|
+
title: "Legacy Compatibility: Audience ICP",
|
|
179
|
+
relativePath: LEGACY_AUDIENCE_ICP_PATH,
|
|
180
|
+
markdown: legacyAudienceIcp,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
const legacyFaqsCore = readFile(LEGACY_FAQS_CORE_PATH);
|
|
184
|
+
if (!identityMemory.proofLedger && legacyFaqsCore) {
|
|
185
|
+
appendCompatibilitySection(parts, sourcePaths, {
|
|
186
|
+
title: "Legacy Compatibility: FAQ Proof",
|
|
187
|
+
relativePath: LEGACY_FAQS_CORE_PATH,
|
|
188
|
+
markdown: legacyFaqsCore,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
markdown: parts.join("\n\n"),
|
|
193
|
+
updatedAt: latestUpdatedAt(sourcePaths),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function hasCoreIdentityMemory(identityMemory) {
|
|
197
|
+
return Boolean(identityMemory.identity ||
|
|
198
|
+
identityMemory.company ||
|
|
199
|
+
identityMemory.antiAiStyle ||
|
|
200
|
+
identityMemory.proofLedger ||
|
|
201
|
+
identityMemory.winsLedger ||
|
|
202
|
+
identityMemory.storyBank ||
|
|
203
|
+
identityMemory.answerBank ||
|
|
204
|
+
identityMemory.contextModes ||
|
|
205
|
+
identityMemory.decisionRules ||
|
|
206
|
+
identityMemory.changeLog ||
|
|
207
|
+
identityMemory.transcripts?.index ||
|
|
208
|
+
identityMemory.references?.index);
|
|
209
|
+
}
|
|
210
|
+
function appendCoreSection(parts, sourcePaths, title, chunk) {
|
|
211
|
+
if (!chunk)
|
|
212
|
+
return;
|
|
213
|
+
parts.push(`## ${title}: ${chunk.source.relativePath}\n\n${chunk.markdown.trim()}`);
|
|
214
|
+
sourcePaths.push(chunk.source.relativePath);
|
|
215
|
+
}
|
|
216
|
+
function appendCoreDirectoryIndex(parts, sourcePaths, title, directory) {
|
|
217
|
+
if (!directory?.index)
|
|
218
|
+
return;
|
|
219
|
+
appendCoreSection(parts, sourcePaths, title, directory.index);
|
|
220
|
+
}
|
|
221
|
+
function appendCompatibilitySection(parts, sourcePaths, section) {
|
|
222
|
+
parts.push(`## ${section.title} (${section.relativePath})\n\n${section.markdown.trim()}`);
|
|
223
|
+
sourcePaths.push(section.relativePath);
|
|
224
|
+
}
|
|
225
|
+
function latestUpdatedAt(relativePaths) {
|
|
226
|
+
const latest = relativePaths.reduce((max, relativePath) => {
|
|
227
|
+
const fullPath = path.join(getConfigsDir(), relativePath);
|
|
228
|
+
if (!fs.existsSync(fullPath))
|
|
229
|
+
return max;
|
|
230
|
+
return Math.max(max, fs.statSync(fullPath).mtime.getTime());
|
|
231
|
+
}, 0);
|
|
232
|
+
return new Date(latest).toISOString();
|
|
146
233
|
}
|
|
147
234
|
export function getEngageMemory(senderId) {
|
|
148
|
-
const
|
|
235
|
+
const identityMemory = readIdentityMemory({ connectedSenderId: senderId });
|
|
236
|
+
const styleGuide = readStyleGuide(senderId, identityMemory);
|
|
149
237
|
const provenSearches = readProvenSearches(senderId);
|
|
150
238
|
const trackedPeople = readTrackedPeople(senderId);
|
|
151
|
-
return {
|
|
239
|
+
return {
|
|
240
|
+
memory: {
|
|
241
|
+
styleGuide,
|
|
242
|
+
provenSearches,
|
|
243
|
+
trackedPeople,
|
|
244
|
+
...identityMemory,
|
|
245
|
+
},
|
|
246
|
+
};
|
|
152
247
|
}
|
|
153
248
|
export function setStyleGuide(markdown, senderId) {
|
|
154
|
-
const corePath =
|
|
249
|
+
const corePath = senderWritePath(senderId, "styleguide-core.md", FLAT_STYLE_CORE_PATH);
|
|
155
250
|
writeFile(corePath, markdown + "\n");
|
|
156
251
|
const updatedAt = new Date().toISOString();
|
|
157
252
|
return { styleGuide: { markdown, updatedAt } };
|
|
@@ -202,7 +297,7 @@ function writeProvenSearches(searches, senderId) {
|
|
|
202
297
|
Yielded: String(s.totalYielded),
|
|
203
298
|
"Hit Rate": s.avgHitRate.toFixed(2),
|
|
204
299
|
}));
|
|
205
|
-
const filePath =
|
|
300
|
+
const filePath = senderWritePath(senderId, "proven-searches.md", FLAT_PROVEN_SEARCHES_PATH);
|
|
206
301
|
const table = buildMarkdownTable(PROVEN_HEADERS, rows);
|
|
207
302
|
writeFile(filePath, PROVEN_SEARCHES_HEADER + table + "\n");
|
|
208
303
|
}
|
|
@@ -251,7 +346,7 @@ const INFLUENCER_HEADERS = [
|
|
|
251
346
|
"Include in Discovery",
|
|
252
347
|
];
|
|
253
348
|
function readTrackedPeople(senderId) {
|
|
254
|
-
const filePath =
|
|
349
|
+
const filePath = senderWritePath(senderId, "influencers.md", FLAT_INFLUENCERS_PATH);
|
|
255
350
|
const content = readFile(filePath);
|
|
256
351
|
if (!content)
|
|
257
352
|
return [];
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
export interface IdentityGeneratedSectionProposal {
|
|
2
|
+
relativePath: string;
|
|
3
|
+
key: string;
|
|
4
|
+
markdown: string;
|
|
5
|
+
}
|
|
6
|
+
export interface IdentityProofEntryProposal {
|
|
7
|
+
key?: string;
|
|
8
|
+
claim: string;
|
|
9
|
+
source?: string;
|
|
10
|
+
confidence?: string;
|
|
11
|
+
allowedUse?: string;
|
|
12
|
+
privacy?: string;
|
|
13
|
+
notes?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface IdentityWinEntryProposal {
|
|
16
|
+
key?: string;
|
|
17
|
+
title: string;
|
|
18
|
+
proofType?: string;
|
|
19
|
+
outcome?: string;
|
|
20
|
+
source?: string;
|
|
21
|
+
permission?: string;
|
|
22
|
+
confidence?: string;
|
|
23
|
+
publicSafety?: string;
|
|
24
|
+
allowedUse?: string;
|
|
25
|
+
notes?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface IdentityStoryEntryProposal {
|
|
28
|
+
key?: string;
|
|
29
|
+
title: string;
|
|
30
|
+
setup?: string;
|
|
31
|
+
moment?: string;
|
|
32
|
+
lesson?: string;
|
|
33
|
+
source?: string;
|
|
34
|
+
contexts?: string;
|
|
35
|
+
privacy?: string;
|
|
36
|
+
notes?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface IdentityAnswerEntryProposal {
|
|
39
|
+
key?: string;
|
|
40
|
+
question: string;
|
|
41
|
+
answer: string;
|
|
42
|
+
topicTags?: string;
|
|
43
|
+
source?: string;
|
|
44
|
+
useContexts?: string;
|
|
45
|
+
confidence?: string;
|
|
46
|
+
privacy?: string;
|
|
47
|
+
derivedMemoryLinks?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface IdentityRuleEntryProposal {
|
|
50
|
+
key?: string;
|
|
51
|
+
title: string;
|
|
52
|
+
rule: string;
|
|
53
|
+
source?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface IdentityAntiAiBanProposal {
|
|
56
|
+
key?: string;
|
|
57
|
+
pattern: string;
|
|
58
|
+
rule: string;
|
|
59
|
+
context?: string;
|
|
60
|
+
source?: string;
|
|
61
|
+
}
|
|
62
|
+
export interface IdentityChangeLogEntryProposal {
|
|
63
|
+
key?: string;
|
|
64
|
+
date: string;
|
|
65
|
+
source?: string;
|
|
66
|
+
changed: string;
|
|
67
|
+
newRule: string;
|
|
68
|
+
}
|
|
69
|
+
export interface IdentityTranscriptIndexRowProposal {
|
|
70
|
+
key?: string;
|
|
71
|
+
title: string;
|
|
72
|
+
sourcePath: string;
|
|
73
|
+
date?: string;
|
|
74
|
+
speakers?: string;
|
|
75
|
+
targetSpeaker?: string;
|
|
76
|
+
topics?: string;
|
|
77
|
+
contextMode?: string;
|
|
78
|
+
sampleType?: string;
|
|
79
|
+
sensitivity?: string;
|
|
80
|
+
}
|
|
81
|
+
export interface IdentityTopicTranscriptProposal {
|
|
82
|
+
key?: string;
|
|
83
|
+
topicSlug: string;
|
|
84
|
+
title: string;
|
|
85
|
+
sourcePath: string;
|
|
86
|
+
targetSpeaker?: string;
|
|
87
|
+
excerpt: string;
|
|
88
|
+
}
|
|
89
|
+
export interface IdentityReferenceRowProposal {
|
|
90
|
+
key?: string;
|
|
91
|
+
category?: string;
|
|
92
|
+
indexPath?: string;
|
|
93
|
+
title: string;
|
|
94
|
+
source: string;
|
|
95
|
+
copiedPath?: string;
|
|
96
|
+
tags?: string;
|
|
97
|
+
whyItMatters?: string;
|
|
98
|
+
usageContexts?: string;
|
|
99
|
+
lastReviewed?: string;
|
|
100
|
+
}
|
|
101
|
+
export interface IdentityCompilerProposal {
|
|
102
|
+
configsDir?: string;
|
|
103
|
+
generatedSections?: IdentityGeneratedSectionProposal[];
|
|
104
|
+
proofEntries?: IdentityProofEntryProposal[];
|
|
105
|
+
winsEntries?: IdentityWinEntryProposal[];
|
|
106
|
+
storyEntries?: IdentityStoryEntryProposal[];
|
|
107
|
+
answerEntries?: IdentityAnswerEntryProposal[];
|
|
108
|
+
decisionRules?: IdentityRuleEntryProposal[];
|
|
109
|
+
antiAiBans?: IdentityAntiAiBanProposal[];
|
|
110
|
+
changeLogEntries?: IdentityChangeLogEntryProposal[];
|
|
111
|
+
transcriptIndexRows?: IdentityTranscriptIndexRowProposal[];
|
|
112
|
+
topicTranscripts?: IdentityTopicTranscriptProposal[];
|
|
113
|
+
referenceRows?: IdentityReferenceRowProposal[];
|
|
114
|
+
}
|
|
115
|
+
export interface IdentityCompilerResult {
|
|
116
|
+
configsDir: string;
|
|
117
|
+
filesChanged: string[];
|
|
118
|
+
}
|
|
119
|
+
export declare function applyIdentityCompilerProposal(proposal: IdentityCompilerProposal): IdentityCompilerResult;
|