@getbourdon/participants 0.3.1 → 0.4.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.
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * Network-shaped participant base — port of `participants/_network_base.py`
3
4
  * (v0.3 adapter contract). Same `exportL5` / `exportSessions` half as a file
@@ -0,0 +1,35 @@
1
+ /**
2
+ * StackBlitz Bolt.new participant — port of `participants/bolt.py`.
3
+ *
4
+ * Bolt.new builds and runs full-stack apps in WebContainers, in the browser,
5
+ * so nothing useful lands on the user's machine. It federates through an
6
+ * export directory; see {@link ExportStoreParticipant} for the store layout
7
+ * and the mechanics this shares with Lovable and v0.
8
+ */
9
+ import { type EntityModel, type SessionModel, type VisibilityPolicyModel } from "@getbourdon/l5";
10
+ import { ExportStoreParticipant, type ExportStoreConfig } from "../export-store-base.js";
11
+ type Dict = Record<string, unknown>;
12
+ export declare const AGENT_ID = "bolt";
13
+ export declare const AGENT_TYPE = "code-assistant";
14
+ export declare const ROLE_NARRATIVE: string;
15
+ export declare const DEFAULT_POLICY: VisibilityPolicyModel;
16
+ /**
17
+ * One `projects.json` record to an Entity.
18
+ *
19
+ * Bolt caps the name at 80 characters, falls back to a generated summary when
20
+ * the record has no description, and inserts its own tag only when absent —
21
+ * all three differ from Lovable's mapper, deliberately. See the note in
22
+ * export-store-base.ts.
23
+ */
24
+ export declare function projectToEntity(record: Dict): EntityModel | null;
25
+ /** One `sessions/<id>.json` record to a Session, or null with no usable date. */
26
+ export declare function sessionToRecord(record: Dict, fallbackDate: string | null): SessionModel | null;
27
+ export declare const BOLT_CONFIG: ExportStoreConfig;
28
+ export declare class BoltParticipant extends ExportStoreParticipant {
29
+ constructor(options?: {
30
+ stateDir?: string;
31
+ env?: NodeJS.ProcessEnv;
32
+ });
33
+ static defaultNativePath(home?: string): string;
34
+ }
35
+ export {};
@@ -0,0 +1,95 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ /**
3
+ * StackBlitz Bolt.new participant — port of `participants/bolt.py`.
4
+ *
5
+ * Bolt.new builds and runs full-stack apps in WebContainers, in the browser,
6
+ * so nothing useful lands on the user's machine. It federates through an
7
+ * export directory; see {@link ExportStoreParticipant} for the store layout
8
+ * and the mechanics this shares with Lovable and v0.
9
+ */
10
+ import { Visibility, makeEntity, makeSession, makeVisibilityPolicy, } from "@getbourdon/l5";
11
+ import { redactText } from "@getbourdon/redaction";
12
+ import { ExportStoreParticipant, isoDate, parseVisibility, safeStr, safeStrList, } from "../export-store-base.js";
13
+ export const AGENT_ID = "bolt";
14
+ export const AGENT_TYPE = "code-assistant";
15
+ export const ROLE_NARRATIVE = "StackBlitz Bolt.new in-browser AI development environment. Builds, executes, " +
16
+ "and iterates full-stack applications in WebContainers from chat. Bourdon " +
17
+ "reads exported project and session state so other agents recognize what " +
18
+ "Bolt.new has developed.";
19
+ export const DEFAULT_POLICY = makeVisibilityPolicy({
20
+ default: Visibility.TEAM,
21
+ private_tags: ["personal", "credential", "secret", "client-confidential", "private"],
22
+ team_tags: ["bolt", "project", "webcontainer", "stackblitz"],
23
+ });
24
+ const MAX_SUMMARY_CHARS = 320;
25
+ const MAX_KEY_ACTION_CHARS = 300;
26
+ const NAME_LIMIT = 80;
27
+ /**
28
+ * One `projects.json` record to an Entity.
29
+ *
30
+ * Bolt caps the name at 80 characters, falls back to a generated summary when
31
+ * the record has no description, and inserts its own tag only when absent —
32
+ * all three differ from Lovable's mapper, deliberately. See the note in
33
+ * export-store-base.ts.
34
+ */
35
+ export function projectToEntity(record) {
36
+ const rawName = record.name;
37
+ if (typeof rawName !== "string" || !rawName)
38
+ return null;
39
+ const name = safeStr(rawName, NAME_LIMIT);
40
+ if (!name)
41
+ return null;
42
+ const summary = safeStr(record.description ?? "", MAX_SUMMARY_CHARS) || `Bolt.new project ${name}`;
43
+ const tags = safeStrList(record.tags, 40);
44
+ if (!tags.includes("bolt"))
45
+ tags.unshift("bolt");
46
+ const updated = isoDate(record.updated_at);
47
+ const archived = Boolean(record.archived ?? false);
48
+ return makeEntity({
49
+ name,
50
+ type: "project",
51
+ summary,
52
+ tags,
53
+ last_touched: updated,
54
+ valid_from: isoDate(record.created_at),
55
+ valid_to: archived ? updated : null,
56
+ visibility: parseVisibility(record.visibility),
57
+ });
58
+ }
59
+ /** One `sessions/<id>.json` record to a Session, or null with no usable date. */
60
+ export function sessionToRecord(record, fallbackDate) {
61
+ const date = isoDate(record.date) ?? fallbackDate;
62
+ if (!date)
63
+ return null;
64
+ const project = String(record.project ?? "").trim();
65
+ return makeSession({
66
+ date,
67
+ cwd: null, // cloud agent: there is no local working directory to name
68
+ project_focus: project ? [redactText(project, 120)] : [],
69
+ key_actions: safeStrList(record.key_actions, MAX_KEY_ACTION_CHARS),
70
+ files_touched: safeStrList(record.files_touched),
71
+ visibility: parseVisibility(record.visibility),
72
+ });
73
+ }
74
+ export const BOLT_CONFIG = {
75
+ agentId: AGENT_ID,
76
+ agentType: AGENT_TYPE,
77
+ displayName: "Bolt.new",
78
+ directoryName: ".bolt",
79
+ stateEnvVar: "BOLT_STATE_DIR",
80
+ roleNarrative: ROLE_NARRATIVE,
81
+ capabilities: ["in-browser-dev", "webcontainers", "full-stack-generation"],
82
+ policy: DEFAULT_POLICY,
83
+ label: "Bolt.new",
84
+ initCommand: "bourdon bolt init",
85
+ projectToEntity,
86
+ sessionToRecord,
87
+ };
88
+ export class BoltParticipant extends ExportStoreParticipant {
89
+ constructor(options = {}) {
90
+ super(BOLT_CONFIG, options);
91
+ }
92
+ static defaultNativePath(home) {
93
+ return ExportStoreParticipant.defaultNativePath(".bolt", home);
94
+ }
95
+ }
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * Cascade (Windsurf) participant — convention-file reader. Port of
3
4
  * `participants/cascade.py`.
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * Claude Code automations participant — publishes background-run memory as L5
3
4
  * evidence. Port of `participants/claude_code_automations.py`.
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * Claude Code participant — reads agent-brain + auto-memory + MCP knowledge
3
4
  * graph. Port of `participants/claude_code.py`.
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * Claude Desktop · Code participant — the Claude desktop app's GUI "Claude Code"
3
4
  * surface. Port of `participants/claude_desktop_code.py` (+ the shared
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * Claude Desktop · Co-Work participant — the richest of the two Claude-desktop
3
4
  * surfaces. Port of `participants/claude_desktop_cowork.py` (+ the shared
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * Codex automations participant — publishes read-only Codex background/automation
3
4
  * run memory into Bourdon as L5 evidence. Port of
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * Codex session-index title lookup — narrow port of the three
3
4
  * `session_thread_titles` helpers in `participants/codex.py`.
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * GitHub Copilot · Automations participant — convention-file reader. Port of
3
4
  * `participants/copilot_automations.py`.
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * GitHub Copilot CLI participant — normalize the `copilot` terminal agent's
3
4
  * SQLite session store into L5. Port of `participants/copilot_cli.py`.
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * GitHub Copilot · VS Code participant — reads the GUI Copilot Chat extension's
3
4
  * per-workspace transcripts + repo-scoped memory. Port of
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * GitHub Copilot (local convention) participant — reads the convention-based
3
4
  * memory file at `~/.copilot-bourdon/memory.md`. Port of `participants/copilot.py`.
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * Cursor automations participant — publish background agent run memory as L5
3
4
  * evidence. Port of `participants/cursor_automations.py`.
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * Cursor participant — reads Cursor's (the AI-first IDE) SQLite-backed
3
4
  * workspace/composer state and normalizes it into L5. Port of
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * GitHub-embedded Copilot participant — the v0.3 network-adapter reference.
3
4
  * Port of `participants/github_copilot.py`.
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * Hermes participant — normalize Hermes Agent (Nous Research) memory + sessions
3
4
  * into L5. Port of `participants/hermes.py`.
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Lovable participant — port of `participants/lovable.py`.
3
+ *
4
+ * Lovable builds full-stack web apps from chat in the cloud, so nothing useful
5
+ * lands on the user's machine. It federates through an export directory; see
6
+ * {@link ExportStoreParticipant} for the store layout and the mechanics this
7
+ * shares with Bolt.new and v0.
8
+ *
9
+ * ⚠ The mapper below is NOT Bolt's with the names swapped, and must not be
10
+ * refactored into it. Lovable's oracle differs in four ways, each reproduced
11
+ * exactly here:
12
+ *
13
+ * 1. the project name is capped at 120 characters, not 80;
14
+ * 2. a record with no description yields a NULL summary, where Bolt
15
+ * synthesizes `"Bolt.new project <name>"`;
16
+ * 3. the `"lovable"` tag is APPENDED unconditionally, so a record that
17
+ * already carries it ends up with it twice — Bolt inserts only if absent;
18
+ * 4. `updated_at` falls back to `created_at`, where Bolt leaves
19
+ * `last_touched` null.
20
+ *
21
+ * (3) also means the tag lands LAST rather than first. None of this is
22
+ * defensible design; all of it is what the oracle does, and the mirror's job
23
+ * is to agree with the oracle, not to improve on it. Fixing any of it is an
24
+ * oracle-side change the conformance fixtures would have to absorb first.
25
+ */
26
+ import { type EntityModel, type SessionModel, type VisibilityPolicyModel } from "@getbourdon/l5";
27
+ import { ExportStoreParticipant, type ExportStoreConfig } from "../export-store-base.js";
28
+ type Dict = Record<string, unknown>;
29
+ export declare const AGENT_ID = "lovable";
30
+ export declare const AGENT_TYPE = "code-assistant";
31
+ export declare const ROLE_NARRATIVE: string;
32
+ export declare const DEFAULT_POLICY: VisibilityPolicyModel;
33
+ /** One `projects.json` record to an Entity. See the four notes in the header. */
34
+ export declare function projectToEntity(record: Dict): EntityModel | null;
35
+ /** One `sessions/<id>.json` record to a Session, or null with no usable date. */
36
+ export declare function sessionToRecord(record: Dict, fallbackDate: string | null): SessionModel | null;
37
+ export declare const LOVABLE_CONFIG: ExportStoreConfig;
38
+ export declare class LovableParticipant extends ExportStoreParticipant {
39
+ constructor(options?: {
40
+ stateDir?: string;
41
+ env?: NodeJS.ProcessEnv;
42
+ });
43
+ static defaultNativePath(home?: string): string;
44
+ }
45
+ export {};
@@ -0,0 +1,108 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ /**
3
+ * Lovable participant — port of `participants/lovable.py`.
4
+ *
5
+ * Lovable builds full-stack web apps from chat in the cloud, so nothing useful
6
+ * lands on the user's machine. It federates through an export directory; see
7
+ * {@link ExportStoreParticipant} for the store layout and the mechanics this
8
+ * shares with Bolt.new and v0.
9
+ *
10
+ * ⚠ The mapper below is NOT Bolt's with the names swapped, and must not be
11
+ * refactored into it. Lovable's oracle differs in four ways, each reproduced
12
+ * exactly here:
13
+ *
14
+ * 1. the project name is capped at 120 characters, not 80;
15
+ * 2. a record with no description yields a NULL summary, where Bolt
16
+ * synthesizes `"Bolt.new project <name>"`;
17
+ * 3. the `"lovable"` tag is APPENDED unconditionally, so a record that
18
+ * already carries it ends up with it twice — Bolt inserts only if absent;
19
+ * 4. `updated_at` falls back to `created_at`, where Bolt leaves
20
+ * `last_touched` null.
21
+ *
22
+ * (3) also means the tag lands LAST rather than first. None of this is
23
+ * defensible design; all of it is what the oracle does, and the mirror's job
24
+ * is to agree with the oracle, not to improve on it. Fixing any of it is an
25
+ * oracle-side change the conformance fixtures would have to absorb first.
26
+ */
27
+ import { Visibility, makeEntity, makeSession, makeVisibilityPolicy, } from "@getbourdon/l5";
28
+ import { redactText } from "@getbourdon/redaction";
29
+ import { ExportStoreParticipant, isoDate, parseVisibility, safeStrList, } from "../export-store-base.js";
30
+ export const AGENT_ID = "lovable";
31
+ export const AGENT_TYPE = "code-assistant";
32
+ export const ROLE_NARRATIVE = "Cloud app-building agent. Designs, builds, and iterates full-stack web " +
33
+ "applications from chat. Bourdon reads exported project and session state " +
34
+ "so other agents recognize what Lovable has built.";
35
+ export const DEFAULT_POLICY = makeVisibilityPolicy({
36
+ default: Visibility.TEAM,
37
+ private_tags: ["personal", "credential", "secret", "client-confidential"],
38
+ team_tags: ["lovable", "project", "client"],
39
+ });
40
+ const MAX_SUMMARY_CHARS = 320;
41
+ const MAX_KEY_ACTION_CHARS = 300;
42
+ const NAME_LIMIT = 120;
43
+ /** One `projects.json` record to an Entity. See the four notes in the header. */
44
+ export function projectToEntity(record) {
45
+ const name = String(record.name ?? "").trim();
46
+ if (!name)
47
+ return null;
48
+ const summary = record.description;
49
+ // (2) absent description -> null, not a synthesized sentence.
50
+ const summaryText = summary === null || summary === undefined || summary === ""
51
+ ? null
52
+ : redactText(String(summary), MAX_SUMMARY_CHARS);
53
+ // (3) unconditional append: a record already tagged "lovable" gets it twice.
54
+ const tags = safeStrList(record.tags);
55
+ tags.push("lovable");
56
+ const archived = Boolean(record.archived);
57
+ // (4) updated_at falls back to created_at.
58
+ const updated = isoDate(record.updated_at) ?? isoDate(record.created_at);
59
+ return makeEntity({
60
+ name: redactText(name, NAME_LIMIT), // (1) 120, not 80
61
+ type: "project",
62
+ summary: summaryText,
63
+ tags,
64
+ last_touched: updated,
65
+ valid_from: isoDate(record.created_at),
66
+ valid_to: archived ? updated : null,
67
+ visibility: parseVisibility(record.visibility),
68
+ });
69
+ }
70
+ /** One `sessions/<id>.json` record to a Session, or null with no usable date. */
71
+ export function sessionToRecord(record, fallbackDate) {
72
+ const date = isoDate(record.date) ?? fallbackDate;
73
+ if (!date)
74
+ return null;
75
+ const project = String(record.project ?? "").trim();
76
+ return makeSession({
77
+ date,
78
+ cwd: null, // cloud agent: there is no local working directory to name
79
+ project_focus: project ? [redactText(project, 120)] : [],
80
+ key_actions: safeStrList(record.key_actions, MAX_KEY_ACTION_CHARS),
81
+ // ⚠ No limit, so these are NOT redacted — the oracle's behaviour. Bolt and
82
+ // v0 redact the same field. Flagged, not silently corrected.
83
+ files_touched: safeStrList(record.files_touched),
84
+ visibility: parseVisibility(record.visibility),
85
+ });
86
+ }
87
+ export const LOVABLE_CONFIG = {
88
+ agentId: AGENT_ID,
89
+ agentType: AGENT_TYPE,
90
+ displayName: "Lovable",
91
+ directoryName: ".lovable",
92
+ stateEnvVar: "LOVABLE_STATE_DIR",
93
+ roleNarrative: ROLE_NARRATIVE,
94
+ capabilities: ["app-building", "full-stack-generation", "deploy-preview"],
95
+ policy: DEFAULT_POLICY,
96
+ label: "Lovable",
97
+ initCommand: "bourdon lovable init",
98
+ projectToEntity,
99
+ sessionToRecord,
100
+ };
101
+ export class LovableParticipant extends ExportStoreParticipant {
102
+ constructor(options = {}) {
103
+ super(LOVABLE_CONFIG, options);
104
+ }
105
+ static defaultNativePath(home) {
106
+ return ExportStoreParticipant.defaultNativePath(".lovable", home);
107
+ }
108
+ }
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * OpenClaw participant — network-shaped, QUARANTINED-CLASS. Port of
3
4
  * `participants/openclaw.py` (v0.9.0, spec R4/D9).
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Vercel v0 participant — port of `participants/v0.py`.
3
+ *
4
+ * v0 generates React / Next.js / Tailwind UI and full-stack web apps from
5
+ * chat, entirely server-side, so nothing useful lands on the user's machine.
6
+ * It federates through an export directory; see {@link ExportStoreParticipant}
7
+ * for the store layout and the mechanics this shares with Bolt.new and
8
+ * Lovable. The mapper below is byte-for-byte Bolt's rule with v0's own name
9
+ * and tag — that is the oracle's shape, not a shortcut taken here.
10
+ */
11
+ import { type EntityModel, type SessionModel, type VisibilityPolicyModel } from "@getbourdon/l5";
12
+ import { ExportStoreParticipant, type ExportStoreConfig } from "../export-store-base.js";
13
+ type Dict = Record<string, unknown>;
14
+ export declare const AGENT_ID = "v0";
15
+ export declare const AGENT_TYPE = "code-assistant";
16
+ export declare const ROLE_NARRATIVE: string;
17
+ export declare const DEFAULT_POLICY: VisibilityPolicyModel;
18
+ /**
19
+ * One `projects.json` record to an Entity.
20
+ *
21
+ * Caps the name at 80 characters, falls back to a generated summary when the
22
+ * record has no description, and inserts its own tag only when absent. All
23
+ * three differ from Lovable's mapper, deliberately. See the note in
24
+ * export-store-base.ts.
25
+ */
26
+ export declare function projectToEntity(record: Dict): EntityModel | null;
27
+ /** One `sessions/<id>.json` record to a Session, or null with no usable date. */
28
+ export declare function sessionToRecord(record: Dict, fallbackDate: string | null): SessionModel | null;
29
+ export declare const V0_CONFIG: ExportStoreConfig;
30
+ export declare class V0Participant extends ExportStoreParticipant {
31
+ constructor(options?: {
32
+ stateDir?: string;
33
+ env?: NodeJS.ProcessEnv;
34
+ });
35
+ static defaultNativePath(home?: string): string;
36
+ }
37
+ export {};
@@ -0,0 +1,97 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ /**
3
+ * Vercel v0 participant — port of `participants/v0.py`.
4
+ *
5
+ * v0 generates React / Next.js / Tailwind UI and full-stack web apps from
6
+ * chat, entirely server-side, so nothing useful lands on the user's machine.
7
+ * It federates through an export directory; see {@link ExportStoreParticipant}
8
+ * for the store layout and the mechanics this shares with Bolt.new and
9
+ * Lovable. The mapper below is byte-for-byte Bolt's rule with v0's own name
10
+ * and tag — that is the oracle's shape, not a shortcut taken here.
11
+ */
12
+ import { Visibility, makeEntity, makeSession, makeVisibilityPolicy, } from "@getbourdon/l5";
13
+ import { redactText } from "@getbourdon/redaction";
14
+ import { ExportStoreParticipant, isoDate, parseVisibility, safeStr, safeStrList, } from "../export-store-base.js";
15
+ export const AGENT_ID = "v0";
16
+ export const AGENT_TYPE = "code-assistant";
17
+ export const ROLE_NARRATIVE = "Vercel v0 generative UI and full-stack web builder. Designs and iterates " +
18
+ "React, Next.js, and Tailwind components and web applications from chat. " +
19
+ "Bourdon reads exported project and session state so other agents recognize " +
20
+ "what v0 has designed and constructed.";
21
+ export const DEFAULT_POLICY = makeVisibilityPolicy({
22
+ default: Visibility.TEAM,
23
+ private_tags: ["personal", "credential", "secret", "client-confidential", "private"],
24
+ team_tags: ["v0", "project", "client", "ui", "component"],
25
+ });
26
+ const MAX_SUMMARY_CHARS = 320;
27
+ const MAX_KEY_ACTION_CHARS = 300;
28
+ const NAME_LIMIT = 80;
29
+ /**
30
+ * One `projects.json` record to an Entity.
31
+ *
32
+ * Caps the name at 80 characters, falls back to a generated summary when the
33
+ * record has no description, and inserts its own tag only when absent. All
34
+ * three differ from Lovable's mapper, deliberately. See the note in
35
+ * export-store-base.ts.
36
+ */
37
+ export function projectToEntity(record) {
38
+ const rawName = record.name;
39
+ if (typeof rawName !== "string" || !rawName)
40
+ return null;
41
+ const name = safeStr(rawName, NAME_LIMIT);
42
+ if (!name)
43
+ return null;
44
+ const summary = safeStr(record.description ?? "", MAX_SUMMARY_CHARS) || `v0 project ${name}`;
45
+ const tags = safeStrList(record.tags, 40);
46
+ if (!tags.includes("v0"))
47
+ tags.unshift("v0");
48
+ const updated = isoDate(record.updated_at);
49
+ const archived = Boolean(record.archived ?? false);
50
+ return makeEntity({
51
+ name,
52
+ type: "project",
53
+ summary,
54
+ tags,
55
+ last_touched: updated,
56
+ valid_from: isoDate(record.created_at),
57
+ valid_to: archived ? updated : null,
58
+ visibility: parseVisibility(record.visibility),
59
+ });
60
+ }
61
+ /** One `sessions/<id>.json` record to a Session, or null with no usable date. */
62
+ export function sessionToRecord(record, fallbackDate) {
63
+ const date = isoDate(record.date) ?? fallbackDate;
64
+ if (!date)
65
+ return null;
66
+ const project = String(record.project ?? "").trim();
67
+ return makeSession({
68
+ date,
69
+ cwd: null, // cloud agent: there is no local working directory to name
70
+ project_focus: project ? [redactText(project, 120)] : [],
71
+ key_actions: safeStrList(record.key_actions, MAX_KEY_ACTION_CHARS),
72
+ files_touched: safeStrList(record.files_touched),
73
+ visibility: parseVisibility(record.visibility),
74
+ });
75
+ }
76
+ export const V0_CONFIG = {
77
+ agentId: AGENT_ID,
78
+ agentType: AGENT_TYPE,
79
+ displayName: "Vercel v0",
80
+ directoryName: ".v0",
81
+ stateEnvVar: "V0_STATE_DIR",
82
+ roleNarrative: ROLE_NARRATIVE,
83
+ capabilities: ["generative-ui", "full-stack-web", "react-nextjs"],
84
+ policy: DEFAULT_POLICY,
85
+ label: "v0",
86
+ initCommand: "bourdon v0 init",
87
+ projectToEntity,
88
+ sessionToRecord,
89
+ };
90
+ export class V0Participant extends ExportStoreParticipant {
91
+ constructor(options = {}) {
92
+ super(V0_CONFIG, options);
93
+ }
94
+ static defaultNativePath(home) {
95
+ return ExportStoreParticipant.defaultNativePath(".v0", home);
96
+ }
97
+ }
package/dist/registry.js CHANGED
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * Participant discovery — a STATIC TS registry replacing Python's `pkgutil`
3
4
  * package scan + entry-point duck-type (`participants/__init__.py`).
@@ -15,6 +16,7 @@
15
16
  * interface conformance (checked structurally via {@link isParticipant}).
16
17
  */
17
18
  import { isParticipant } from "./base.js";
19
+ import { BoltParticipant } from "./readers/bolt.js";
18
20
  import { CascadeParticipant } from "./readers/cascade.js";
19
21
  import { ClaudeCodeParticipant } from "./readers/claude-code.js";
20
22
  import { ClaudeCodeAutomationsParticipant } from "./readers/claude-code-automations.js";
@@ -27,6 +29,8 @@ import { CopilotCliParticipant } from "./readers/copilot-cli.js";
27
29
  import { CopilotVscodeParticipant } from "./readers/copilot-vscode.js";
28
30
  import { CursorParticipant } from "./readers/cursor.js";
29
31
  import { CursorAutomationsParticipant } from "./readers/cursor-automations.js";
32
+ import { LovableParticipant } from "./readers/lovable.js";
33
+ import { V0Participant } from "./readers/v0.js";
30
34
  import { GitHubCopilotParticipant } from "./readers/github-copilot.js";
31
35
  import { HermesParticipant } from "./readers/hermes.js";
32
36
  import { OpenClawParticipant } from "./readers/openclaw.js";
@@ -37,6 +41,7 @@ import { OpenClawParticipant } from "./readers/openclaw.js";
37
41
  * codex — the ~2.6k-line turn-compiler reader — is the only one still deferred.
38
42
  */
39
43
  export const FIRST_PARTY = [
44
+ BoltParticipant,
40
45
  CascadeParticipant,
41
46
  ClaudeCodeParticipant,
42
47
  ClaudeCodeAutomationsParticipant,
@@ -49,6 +54,8 @@ export const FIRST_PARTY = [
49
54
  CopilotVscodeParticipant,
50
55
  CursorParticipant,
51
56
  CursorAutomationsParticipant,
57
+ LovableParticipant,
58
+ V0Participant,
52
59
  GitHubCopilotParticipant,
53
60
  HermesParticipant,
54
61
  OpenClawParticipant,
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
1
2
  /**
2
3
  * Shared read-only SQLite + normalization helpers — port of
3
4
  * `participants/_sqlite_base.py`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getbourdon/participants",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "description": "Bourdon participants — the external-agent → L5 reader layer (BUSL-1.1). Each participant normalizes a foreign agent's native memory store into a visibility-filtered, redacted L5 manifest: read-only SQLite readers (better-sqlite3 mode=ro: hermes), file/convention readers (claude-code), and network readers (github-copilot) with a TTL JSON cache + lazy AuthProvider that never persists a token. Four invariants enforced in code, not by trust: visibility-filter-before-emission, deterministic exportL5, healthCheck never throws, redact every native string. Discovery is a static TS registry (agent_id-sorted, first-wins, log-and-skip) replacing Python's pkgutil scan. Python (pip install bourdon) is the oracle; this mirror asserts against @getbourdon/conformance native_stores fixtures.",
5
5
  "license": "BUSL-1.1",
6
6
  "type": "module",
@@ -35,15 +35,15 @@
35
35
  "dependencies": {
36
36
  "smol-toml": "^1.7.1",
37
37
  "yaml": "^2.6.1",
38
- "@getbourdon/l5": "0.4.0",
39
- "@getbourdon/redaction": "0.1.5"
38
+ "@getbourdon/l5": "0.5.0",
39
+ "@getbourdon/redaction": "0.2.0"
40
40
  },
41
41
  "optionalDependencies": {
42
42
  "better-sqlite3": "^12.2.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/better-sqlite3": "^7.6.12",
46
- "@getbourdon/conformance": "0.7.0"
46
+ "@getbourdon/conformance": "0.9.0"
47
47
  },
48
48
  "scripts": {
49
49
  "build": "tsup",