@cordfuse/crosstalk 5.0.0-alpha.2

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.
Files changed (52) hide show
  1. package/bin/crosstalk.js +111 -0
  2. package/package.json +46 -0
  3. package/src/actor.ts +106 -0
  4. package/src/attach.ts +118 -0
  5. package/src/channel.ts +62 -0
  6. package/src/chat.ts +203 -0
  7. package/src/cursor.ts +48 -0
  8. package/src/dispatch.ts +519 -0
  9. package/src/dlq.ts +263 -0
  10. package/src/filenames.ts +28 -0
  11. package/src/frontmatter.ts +26 -0
  12. package/src/init.ts +157 -0
  13. package/src/open.ts +183 -0
  14. package/src/send.ts +80 -0
  15. package/src/status.ts +114 -0
  16. package/src/transport.ts +303 -0
  17. package/src/turnq.ts +59 -0
  18. package/src/upgrade.ts +213 -0
  19. package/src/wake.ts +8 -0
  20. package/template/.amazonq/rules/crosstalk.md +2 -0
  21. package/template/.continue/rules/crosstalk.md +7 -0
  22. package/template/.cursor/rules/crosstalk.mdc +7 -0
  23. package/template/.github/copilot-instructions.md +2 -0
  24. package/template/.windsurfrules +2 -0
  25. package/template/AGENTS.md +2 -0
  26. package/template/ANTIGRAVITY.md +2 -0
  27. package/template/CLAUDE.md +2 -0
  28. package/template/GEMINI.md +2 -0
  29. package/template/OPENCODE.md +2 -0
  30. package/template/QWEN.md +2 -0
  31. package/template/README.md +22 -0
  32. package/template/local/CROSSTALK.md +4 -0
  33. package/template/upstream/CROSSTALK-VERSION +1 -0
  34. package/template/upstream/CROSSTALK.md +589 -0
  35. package/template/upstream/JITTER.md +24 -0
  36. package/template/upstream/OPERATOR.md +60 -0
  37. package/template/upstream/PROTOCOL.md +180 -0
  38. package/template/upstream/actors/cloud-architect.md +83 -0
  39. package/template/upstream/actors/concierge.md +105 -0
  40. package/template/upstream/actors/devops-engineer.md +83 -0
  41. package/template/upstream/actors/documentation-engineer.md +107 -0
  42. package/template/upstream/actors/infrastructure-engineer.md +83 -0
  43. package/template/upstream/actors/junior-developer.md +83 -0
  44. package/template/upstream/actors/precise-generalist.md +48 -0
  45. package/template/upstream/actors/product-manager.md +83 -0
  46. package/template/upstream/actors/qa-engineer.md +83 -0
  47. package/template/upstream/actors/security-engineer.md +92 -0
  48. package/template/upstream/actors/senior-generalist-engineer.md +111 -0
  49. package/template/upstream/actors/senior-software-engineer.md +94 -0
  50. package/template/upstream/actors/skeptic.md +89 -0
  51. package/template/upstream/actors/technical-writer.md +89 -0
  52. package/template/upstream/actors/ux-designer.md +83 -0
package/src/upgrade.ts ADDED
@@ -0,0 +1,213 @@
1
+ // crosstalk upgrade — sync the transport's upstream/ against the runtime's
2
+ // bundled template.
3
+ //
4
+ // The transport's upstream/ contains runtime-managed files: spec, agent
5
+ // orientation prompts, protocol version pin, default actor profiles. When
6
+ // the operator updates their runtime (via `npm update -g @cordfuse/crosstalk`),
7
+ // the bundled template ships with a newer spec; this command copies those
8
+ // files into the operator's transport so they catch up.
9
+ //
10
+ // What this command DOES touch:
11
+ // - upstream/CROSSTALK.md, PROTOCOL.md, OPERATOR.md, JITTER.md
12
+ // - upstream/CROSSTALK-VERSION
13
+ // - upstream/actors/ (default actor profile starter set)
14
+ //
15
+ // What this command NEVER touches:
16
+ // - local/ — operator-owned actor profiles and identity
17
+ // - hosts/ — operator-owned host file
18
+ // - data/ — channels and memories
19
+ // - cursors/, dlq/, errors/ — dispatcher-owned runtime state
20
+ // - root pointer files (CLAUDE.md etc.) — only updated if a --pointers flag
21
+ // is passed, since they rarely change and overwriting them surprises
22
+ // operators who've customized them
23
+ //
24
+ // Usage:
25
+ // crosstalk upgrade — sync upstream/ from runtime template
26
+ // crosstalk upgrade --dry-run — show what would change, no writes
27
+ // crosstalk upgrade --pointers — also overwrite the 11 entry pointer files
28
+
29
+ import { existsSync, readFileSync, writeFileSync, cpSync, statSync, readdirSync } from 'fs';
30
+ import { resolve, join, dirname, relative } from 'path';
31
+ import { fileURLToPath } from 'url';
32
+
33
+ const transportRoot = resolve(process.cwd());
34
+ const argv = process.argv.slice(2);
35
+ const dryRun = argv.includes('--dry-run');
36
+ const updatePointers = argv.includes('--pointers');
37
+
38
+ const POINTER_FILES = [
39
+ 'CLAUDE.md', 'AGENTS.md', 'GEMINI.md', 'QWEN.md', 'ANTIGRAVITY.md', 'OPENCODE.md',
40
+ '.windsurfrules',
41
+ '.amazonq/rules/crosstalk.md',
42
+ '.continue/rules/crosstalk.md',
43
+ '.cursor/rules/crosstalk.mdc',
44
+ '.github/copilot-instructions.md',
45
+ ];
46
+
47
+ function locateTemplate(): string {
48
+ const thisFileDir = dirname(fileURLToPath(import.meta.url));
49
+ const runtimeRoot = resolve(thisFileDir, '..');
50
+ const candidates = [
51
+ join(runtimeRoot, 'template'),
52
+ join(runtimeRoot, '..', 'transport'),
53
+ ];
54
+ const found = candidates.find((c) => existsSync(join(c, 'upstream', 'CROSSTALK-VERSION')));
55
+ if (!found) {
56
+ console.error('crosstalk upgrade: cannot find the bundled transport template.');
57
+ console.error('Looked in:');
58
+ for (const c of candidates) console.error(` ${c}`);
59
+ process.exit(1);
60
+ }
61
+ return found;
62
+ }
63
+
64
+ function readVersion(p: string): string | null {
65
+ try { return readFileSync(p, 'utf-8').trim(); } catch { return null; }
66
+ }
67
+
68
+ function listFilesRelative(dir: string): string[] {
69
+ const out: string[] = [];
70
+ const walk = (d: string, prefix: string): void => {
71
+ if (!existsSync(d)) return;
72
+ for (const entry of readdirSync(d)) {
73
+ const full = join(d, entry);
74
+ const rel = prefix ? `${prefix}/${entry}` : entry;
75
+ const st = statSync(full);
76
+ if (st.isDirectory()) walk(full, rel);
77
+ else out.push(rel);
78
+ }
79
+ };
80
+ walk(dir, '');
81
+ return out;
82
+ }
83
+
84
+ function classifyChange(templatePath: string, transportPath: string): 'add' | 'modify' | 'unchanged' {
85
+ if (!existsSync(transportPath)) return 'add';
86
+ const a = readFileSync(templatePath, 'utf-8');
87
+ const b = readFileSync(transportPath, 'utf-8');
88
+ return a === b ? 'unchanged' : 'modify';
89
+ }
90
+
91
+ // ── Sanity checks ─────────────────────────────────────────────────────
92
+
93
+ const transportVersionPath = join(transportRoot, 'upstream', 'CROSSTALK-VERSION');
94
+ if (!existsSync(transportVersionPath)) {
95
+ console.error(`crosstalk upgrade: not a transport (no upstream/CROSSTALK-VERSION).`);
96
+ console.error(`Run from inside a transport directory, or use 'crosstalk init' to scaffold one.`);
97
+ process.exit(2);
98
+ }
99
+
100
+ const templateDir = locateTemplate();
101
+ const templateUpstream = join(templateDir, 'upstream');
102
+ const transportUpstream = join(transportRoot, 'upstream');
103
+
104
+ const fromVersion = readVersion(transportVersionPath) ?? '?';
105
+ const toVersion = readVersion(join(templateUpstream, 'CROSSTALK-VERSION')) ?? '?';
106
+
107
+ // Detect downgrade.
108
+ const parseMM = (v: string): [number, number] => {
109
+ const m = v.match(/^(\d+)\.(\d+)/);
110
+ return m ? [Number(m[1]), Number(m[2])] : [0, 0];
111
+ };
112
+ const [fromMaj, fromMin] = parseMM(fromVersion);
113
+ const [toMaj, toMin] = parseMM(toVersion);
114
+ const isDowngrade = toMaj < fromMaj || (toMaj === fromMaj && toMin < fromMin);
115
+ if (isDowngrade) {
116
+ console.error(`crosstalk upgrade: bundled template is OLDER than your transport.`);
117
+ console.error(` transport: ${fromVersion}`);
118
+ console.error(` template: ${toVersion}`);
119
+ console.error(`Your runtime is older than the runtime that scaffolded this transport.`);
120
+ console.error(`To upgrade your runtime: npm update -g @cordfuse/crosstalk`);
121
+ process.exit(3);
122
+ }
123
+
124
+ console.log(`crosstalk upgrade${dryRun ? ' (dry-run)' : ''}`);
125
+ console.log('');
126
+ console.log(` transport CROSSTALK-VERSION: ${fromVersion}`);
127
+ console.log(` template CROSSTALK-VERSION: ${toVersion}`);
128
+ console.log('');
129
+
130
+ // ── Plan the changes ──────────────────────────────────────────────────
131
+
132
+ const upstreamFiles = listFilesRelative(templateUpstream);
133
+ const changes: { rel: string; kind: 'add' | 'modify' | 'unchanged' }[] = [];
134
+
135
+ for (const rel of upstreamFiles) {
136
+ const fromPath = join(templateUpstream, rel);
137
+ const toPath = join(transportUpstream, rel);
138
+ changes.push({ rel, kind: classifyChange(fromPath, toPath) });
139
+ }
140
+
141
+ const adds = changes.filter((c) => c.kind === 'add');
142
+ const mods = changes.filter((c) => c.kind === 'modify');
143
+ const same = changes.filter((c) => c.kind === 'unchanged');
144
+
145
+ console.log(`upstream/ changes:`);
146
+ console.log(` ${adds.length} new file${adds.length === 1 ? '' : 's'}`);
147
+ console.log(` ${mods.length} modified`);
148
+ console.log(` ${same.length} unchanged`);
149
+
150
+ if (adds.length > 0 || mods.length > 0) {
151
+ console.log('');
152
+ for (const c of [...adds, ...mods].slice(0, 20)) {
153
+ console.log(` [${c.kind === 'add' ? '+' : '~'}] upstream/${c.rel}`);
154
+ }
155
+ if (adds.length + mods.length > 20) {
156
+ console.log(` … and ${adds.length + mods.length - 20} more`);
157
+ }
158
+ }
159
+
160
+ if (updatePointers) {
161
+ console.log('');
162
+ console.log(`pointer files (with --pointers):`);
163
+ for (const pf of POINTER_FILES) {
164
+ const fromPath = join(templateDir, pf);
165
+ const toPath = join(transportRoot, pf);
166
+ if (!existsSync(fromPath)) continue;
167
+ const kind = classifyChange(fromPath, toPath);
168
+ if (kind !== 'unchanged') console.log(` [${kind === 'add' ? '+' : '~'}] ${pf}`);
169
+ }
170
+ }
171
+
172
+ // ── Apply or stop ─────────────────────────────────────────────────────
173
+
174
+ if (dryRun) {
175
+ console.log('');
176
+ console.log('Dry run — no changes written. Re-run without --dry-run to apply.');
177
+ process.exit(0);
178
+ }
179
+
180
+ if (adds.length === 0 && mods.length === 0 && !updatePointers) {
181
+ console.log('');
182
+ console.log('Already in sync. Nothing to do.');
183
+ process.exit(0);
184
+ }
185
+
186
+ console.log('');
187
+ console.log('Applying...');
188
+
189
+ // Copy upstream/ recursively. cpSync with force=true handles both add and modify.
190
+ cpSync(templateUpstream, transportUpstream, { recursive: true, force: true });
191
+ console.log(` ✓ upstream/ synced`);
192
+
193
+ if (updatePointers) {
194
+ for (const pf of POINTER_FILES) {
195
+ const fromPath = join(templateDir, pf);
196
+ const toPath = join(transportRoot, pf);
197
+ if (!existsSync(fromPath)) continue;
198
+ const targetDir = dirname(toPath);
199
+ if (!existsSync(targetDir)) {
200
+ cpSync(targetDir, targetDir, { recursive: true });
201
+ }
202
+ cpSync(fromPath, toPath, { force: true });
203
+ }
204
+ console.log(` ✓ pointer files synced`);
205
+ }
206
+
207
+ console.log('');
208
+ console.log(`Spec ${fromVersion} → ${toVersion}.`);
209
+ console.log(`Commit the upstream/ changes when ready:`);
210
+ console.log(` git add upstream/${updatePointers ? ' ' + POINTER_FILES.slice(0, 3).join(' ') + ' ...' : ''}`);
211
+ console.log(` git commit -m "spec: upgrade to ${toVersion}"`);
212
+ console.log('');
213
+ console.log('Your local/, hosts/, data/, cursors/, dlq/, errors/ were not touched.');
package/src/wake.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { writeFileSync, mkdirSync } from 'fs';
2
+ import { resolve, join } from 'path';
3
+
4
+ const transportRoot = resolve(process.cwd());
5
+ const wakeDir = join(transportRoot, '.turnq');
6
+ mkdirSync(wakeDir, { recursive: true });
7
+ writeFileSync(join(wakeDir, 'wake.signal'), `${Date.now()}\n`);
8
+ console.log('wake signal sent');
@@ -0,0 +1,2 @@
1
+ Read [local/CROSSTALK.md](local/CROSSTALK.md) for your identity configuration (if you are a dispatched actor).
2
+ Read [upstream/CROSSTALK.md](upstream/CROSSTALK.md) for the protocol specification.
@@ -0,0 +1,7 @@
1
+ ---
2
+ name: Crosstalk Transport
3
+ alwaysApply: true
4
+ ---
5
+
6
+ Read [local/CROSSTALK.md](local/CROSSTALK.md) for your identity configuration (if you are a dispatched actor).
7
+ Read [upstream/CROSSTALK.md](upstream/CROSSTALK.md) for the protocol specification.
@@ -0,0 +1,7 @@
1
+ ---
2
+ description: Crosstalk transport agent instructions
3
+ applyTo: "**"
4
+ ---
5
+
6
+ Read [local/CROSSTALK.md](local/CROSSTALK.md) for your identity configuration (if you are a dispatched actor).
7
+ Read [upstream/CROSSTALK.md](upstream/CROSSTALK.md) for the protocol specification.
@@ -0,0 +1,2 @@
1
+ Read [local/CROSSTALK.md](local/CROSSTALK.md) for your identity configuration (if you are a dispatched actor).
2
+ Read [upstream/CROSSTALK.md](upstream/CROSSTALK.md) for the protocol specification.
@@ -0,0 +1,2 @@
1
+ Read [local/CROSSTALK.md](local/CROSSTALK.md) for your identity configuration (if you are a dispatched actor).
2
+ Read [upstream/CROSSTALK.md](upstream/CROSSTALK.md) for the protocol specification.
@@ -0,0 +1,2 @@
1
+ Read [local/CROSSTALK.md](local/CROSSTALK.md) for your identity configuration (if you are a dispatched actor).
2
+ Read [upstream/CROSSTALK.md](upstream/CROSSTALK.md) for the protocol specification.
@@ -0,0 +1,2 @@
1
+ Read [local/CROSSTALK.md](local/CROSSTALK.md) for your identity configuration (if you are a dispatched actor).
2
+ Read [upstream/CROSSTALK.md](upstream/CROSSTALK.md) for the protocol specification.
@@ -0,0 +1,2 @@
1
+ Read [local/CROSSTALK.md](local/CROSSTALK.md) for your identity configuration (if you are a dispatched actor).
2
+ Read [upstream/CROSSTALK.md](upstream/CROSSTALK.md) for the protocol specification.
@@ -0,0 +1,2 @@
1
+ Read [local/CROSSTALK.md](local/CROSSTALK.md) for your identity configuration (if you are a dispatched actor).
2
+ Read [upstream/CROSSTALK.md](upstream/CROSSTALK.md) for the protocol specification.
@@ -0,0 +1,2 @@
1
+ Read [local/CROSSTALK.md](local/CROSSTALK.md) for your identity configuration (if you are a dispatched actor).
2
+ Read [upstream/CROSSTALK.md](upstream/CROSSTALK.md) for the protocol specification.
@@ -0,0 +1,2 @@
1
+ Read [local/CROSSTALK.md](local/CROSSTALK.md) for your identity configuration (if you are a dispatched actor).
2
+ Read [upstream/CROSSTALK.md](upstream/CROSSTALK.md) for the protocol specification.
@@ -0,0 +1,22 @@
1
+ # Transport template
2
+
3
+ This directory is the scaffold for a Crosstalk transport — the markdown + folder structure that becomes an operator's transport when they run:
4
+
5
+ ```sh
6
+ crosstalk init my-transport
7
+ ```
8
+
9
+ ## What's here
10
+
11
+ - `upstream/` — runtime-managed. Protocol spec (`CROSSTALK.md`, `PROTOCOL.md`, `OPERATOR.md`, `JITTER.md`), version pin (`CROSSTALK-VERSION`), default actor profiles (`actors/`). **Operators don't edit these.** The runtime can re-sync them when a new spec version ships.
12
+ - `local/` — operator-owned. Custom actor profiles (`actors/`), local identity config (`CROSSTALK.md`). Operators edit these freely.
13
+ - `hosts/` — host files declaring which actors run where, per-actor tier configurations.
14
+ - Agent entry pointer files at root (`CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, etc.) — these direct agents to the right files when their CLI starts up in the transport directory.
15
+
16
+ ## How a transport is born
17
+
18
+ `crosstalk init` copies this entire `transport/` tree to the operator's chosen directory, then initializes it as a git repo. From that moment on, the operator's transport is independent — they own it, customize `local/`, declare hosts in `hosts/`, and dispatch runs against it.
19
+
20
+ ## Spec reference
21
+
22
+ The canonical protocol specification lives in `upstream/CROSSTALK.md`. The version pin lives in `upstream/CROSSTALK-VERSION`.
@@ -0,0 +1,4 @@
1
+ ---
2
+ name: CONFIGURE
3
+ email: CONFIGURE
4
+ ---
@@ -0,0 +1 @@
1
+ 5.0