@lazyingart/agintiflow 0.20.47 → 0.20.49

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.
@@ -0,0 +1,1123 @@
1
+ # AgInTiFlow Skill Mesh Sharing Design
2
+
3
+ ## Goal
4
+
5
+ AgInTiFlow should let different users benefit from skills, tool patterns, command policies, profiles, and troubleshooting lessons learned by other users without uploading private transcripts, source code, file paths, secrets, or artifacts.
6
+
7
+ The proposed feature name is **Skill Mesh**.
8
+
9
+ Implementation note as of v0.20.48:
10
+
11
+ - `aginti skillmesh` and `/skillmesh` exist as the first conservative MVP.
12
+ - The shipped implementation uses signed JSON skill packs first, not tarballs, to avoid archive traversal and executable-file risk.
13
+ - Relay nodes can run without model/API keys via `aginti skillmesh serve`.
14
+ - Relay nodes can persist after reboot with `aginti skillmesh service install`; system services require sudo, while user services need systemd lingering for boot persistence.
15
+ - Community imports install disabled by default and cannot override built-in skills.
16
+ - Sync is explicit and metadata-first; no continuous background polling is enabled yet.
17
+
18
+ User-facing command:
19
+
20
+ ```text
21
+ /skillmesh
22
+ ```
23
+
24
+ CLI command:
25
+
26
+ ```bash
27
+ aginti skillmesh
28
+ ```
29
+
30
+ Useful aliases can be added later:
31
+
32
+ ```text
33
+ /skill-sync
34
+ /skill-share
35
+ aginti skillsync
36
+ ```
37
+
38
+ Product default should be **Record + Share Reviewed Skills**. This sounds active, but the implementation must still be conservative: it records locally by default, shares only reviewed/high-value skill packs, syncs slowly during idle time, and never uploads raw logs or raw sessions.
39
+
40
+ The sync philosophy should be **slow, strict, and high-signal**. Skill Mesh is not chat, telemetry streaming, or a real-time swarm bus. It should exchange only reviewed, deduplicated, high-value capability packs during idle time.
41
+
42
+ ## Core Modes
43
+
44
+ The selector for `/skillmesh` should have three modes:
45
+
46
+ 1. **Disabled**
47
+
48
+ No housekeeping export, no community sync, no skill suggestions from shared feeds. Raw local session history still stays in `~/.agintiflow/sessions/` if normal sessions are enabled, but no Skill Mesh aggregation is used.
49
+
50
+ 2. **Record Locally**
51
+
52
+ AgInTiFlow records sanitized local capability metadata into `~/.agintiflow/housekeeping/`. This includes model/tool names, selected skill ids, command categories, outcome hashes, and short redacted previews. It does not upload anything.
53
+
54
+ 3. **Record + Share Reviewed Packs**
55
+
56
+ AgInTiFlow records locally and allows the user to review/export/share **skill packs**. Sharing must never mean uploading raw sessions automatically. It should mean publishing a small reviewed package containing reusable Markdown skills, task profile hints, safe command policy patterns, test snippets, and metadata. This should be the default mode for the product, with strict text in settings explaining what is and is not shared.
57
+
58
+ Better label in UI:
59
+
60
+ ```text
61
+ Record + Share Reviewed Skills
62
+ ```
63
+
64
+ Settings page explanatory text:
65
+
66
+ ```text
67
+ Skill sharing improves AgInTiFlow's skill set across users. Sharing is strict: AgInTiFlow never uploads raw chats, raw session logs, project source files, .env files, keys, browser storage, or artifacts by default. Only reviewed, redacted, high-value skill packs can be shared, and shared skills are deduplicated and verified before they can enter the mesh.
68
+ ```
69
+
70
+ When the user selects **Disabled**, show:
71
+
72
+ ```text
73
+ Skill Mesh is disabled. AgInTiFlow will not record local skill-learning metadata and will not share or receive reviewed skill packs. Enabling Record + Share Reviewed Skills can improve the shared skill set, but sharing remains strict and never uploads raw sessions or secrets.
74
+ ```
75
+
76
+ Avoid label:
77
+
78
+ ```text
79
+ Auto-share logs
80
+ ```
81
+
82
+ because that is the wrong privacy model.
83
+
84
+ ## How Users Communicate Without Sharing Raw Sessions
85
+
86
+ Users communicate through **capability artifacts**, not through transcripts.
87
+
88
+ Shared artifact types:
89
+
90
+ - `SKILL.md` files with frontmatter and workflow guidance.
91
+ - Task profile patches or suggestions.
92
+ - Command-policy examples, such as safe git pull/merge/rebase patterns.
93
+ - Tool recipes, such as Android emulator screenshot capture or LaTeX compile fallback.
94
+ - Smoke tests that prove a skill/tool pattern works.
95
+ - Failure postmortems rewritten as generic lessons.
96
+ - Model routing hints, such as which model is reliable for which class of task.
97
+
98
+ Never share by default:
99
+
100
+ - Raw prompts.
101
+ - Raw model responses.
102
+ - Raw `events.jsonl`.
103
+ - Source files from the user project.
104
+ - Absolute paths.
105
+ - Shell output containing environment variables.
106
+ - Screenshots/images/PDFs unless the user explicitly includes them in a reviewed example.
107
+ - Provider keys, npm tokens, SSH data, cookies, auth headers, or `.env` content.
108
+
109
+ ## Local Pipeline
110
+
111
+ The local machine should have a lightweight housekeeping pipeline:
112
+
113
+ ```text
114
+ session events
115
+ -> redaction and path masking
116
+ -> local housekeeping ledger
117
+ -> candidate capability extractor
118
+ -> user review queue
119
+ -> signed skill pack
120
+ -> optional share/sync
121
+ ```
122
+
123
+ Existing foundation:
124
+
125
+ ```text
126
+ ~/.agintiflow/housekeeping/events.jsonl
127
+ ~/.agintiflow/housekeeping/capabilities.json
128
+ ```
129
+
130
+ Future local folders:
131
+
132
+ ```text
133
+ ~/.agintiflow/skillmesh/
134
+ config.json
135
+ identity.json
136
+ inbox/
137
+ outbox/
138
+ reviewed/
139
+ rejected/
140
+ feeds/
141
+ trusted-keys/
142
+ ```
143
+
144
+ Candidate skill packs should stay local until reviewed.
145
+
146
+ ## Slow Sync And Value Gate
147
+
148
+ Skill Mesh should avoid heavy or frequent communication.
149
+
150
+ Default sync behavior:
151
+
152
+ - No sync while an agent run is active.
153
+ - No sync while shell tools, browser tools, package installs, tests, or model calls are running.
154
+ - Sync only during idle windows.
155
+ - Add jitter so many clients do not sync at the same second.
156
+ - Cap outbound submissions per day.
157
+ - Cap inbound downloads per sync.
158
+ - Prefer metadata sync first, pack download second.
159
+ - Never use Skill Mesh as a live coordination channel for active agent tasks.
160
+
161
+ Suggested defaults:
162
+
163
+ ```json
164
+ {
165
+ "syncPolicy": {
166
+ "enabled": false,
167
+ "idleOnly": true,
168
+ "minIdleSeconds": 90,
169
+ "minIntervalMinutes": 360,
170
+ "jitterMinutes": 30,
171
+ "maxOutboundPacksPerDay": 3,
172
+ "maxInboundPacksPerSync": 20,
173
+ "metadataFirst": true,
174
+ "downloadRequiresUserReview": true
175
+ }
176
+ }
177
+ ```
178
+
179
+ The local scheduler should be simple:
180
+
181
+ ```text
182
+ if skillmesh.mode != "share": skip
183
+ if agent is running: skip
184
+ if last sync too recent: skip
185
+ if no reviewed outbox packs and no feed refresh due: skip
186
+ fetch feed metadata
187
+ dedupe against local database
188
+ download only selected/high-trust candidates
189
+ upload only reviewed outbound packs
190
+ ```
191
+
192
+ ### Value Scoring
193
+
194
+ The candidate extractor should not share every local observation. It should rank candidates and export only the most useful.
195
+
196
+ Signals that increase value:
197
+
198
+ - The same failure happened more than once and a reusable fix was found.
199
+ - A new skill/tool recipe was used successfully with verification.
200
+ - A command policy pattern prevented a dangerous or stuck command.
201
+ - A generated smoke test caught a real regression.
202
+ - A workflow applies across many projects, not only one user folder.
203
+ - The candidate contains acceptance criteria and verification commands.
204
+ - The candidate is small and self-contained.
205
+
206
+ Signals that reduce value:
207
+
208
+ - It mentions private project names, file paths, users, servers, or proprietary APIs.
209
+ - It depends on a very specific local machine layout.
210
+ - It duplicates an existing core skill.
211
+ - It only says generic advice.
212
+ - It was not verified by a test, command, screenshot, or file evidence.
213
+ - It requires secrets, sudo passwords, or private accounts.
214
+
215
+ Example scoring:
216
+
217
+ ```json
218
+ {
219
+ "minShareScore": 80,
220
+ "weights": {
221
+ "verified": 30,
222
+ "reusedAcrossSessions": 20,
223
+ "hasSmokeTest": 20,
224
+ "hasClearTrigger": 10,
225
+ "smallAndGeneric": 10,
226
+ "duplicatesExistingSkill": -40,
227
+ "containsPrivateContext": -100
228
+ }
229
+ }
230
+ ```
231
+
232
+ Only reviewed packs above the threshold should enter the share outbox.
233
+
234
+ ## Deduplication Database
235
+
236
+ Both clients and relay servers need a database to avoid duplication and noisy sync.
237
+
238
+ Local database:
239
+
240
+ ```text
241
+ ~/.agintiflow/skillmesh/index.sqlite
242
+ ```
243
+
244
+ Relay database:
245
+
246
+ ```text
247
+ ~/.aginti-skill-relay/index.sqlite
248
+ ```
249
+
250
+ Core tables:
251
+
252
+ ```sql
253
+ CREATE TABLE packs (
254
+ pack_hash TEXT PRIMARY KEY,
255
+ canonical_id TEXT NOT NULL,
256
+ name TEXT NOT NULL,
257
+ version TEXT NOT NULL,
258
+ author_key_id TEXT NOT NULL,
259
+ status TEXT NOT NULL,
260
+ trust_level TEXT NOT NULL,
261
+ value_score INTEGER NOT NULL DEFAULT 0,
262
+ created_at TEXT NOT NULL,
263
+ received_at TEXT NOT NULL,
264
+ last_seen_at TEXT NOT NULL,
265
+ metadata_json TEXT NOT NULL
266
+ );
267
+
268
+ CREATE TABLE pack_signatures (
269
+ pack_hash TEXT NOT NULL,
270
+ key_id TEXT NOT NULL,
271
+ signature TEXT NOT NULL,
272
+ verified INTEGER NOT NULL DEFAULT 0,
273
+ PRIMARY KEY (pack_hash, key_id)
274
+ );
275
+
276
+ CREATE TABLE installed_packs (
277
+ pack_hash TEXT PRIMARY KEY,
278
+ enabled INTEGER NOT NULL DEFAULT 0,
279
+ installed_at TEXT NOT NULL,
280
+ source_feed TEXT NOT NULL DEFAULT ''
281
+ );
282
+
283
+ CREATE TABLE rejected_packs (
284
+ pack_hash TEXT PRIMARY KEY,
285
+ reason TEXT NOT NULL,
286
+ rejected_at TEXT NOT NULL
287
+ );
288
+ ```
289
+
290
+ Hash strategy:
291
+
292
+ - `pack_hash`: SHA-256 of the canonical tarball bytes.
293
+ - `canonical_id`: stable hash of normalized semantic content, excluding timestamps and signatures.
294
+ - `skill_hash`: SHA-256 of normalized `SKILL.md` body and frontmatter.
295
+ - `policy_hash`: SHA-256 of normalized command-policy JSON.
296
+
297
+ Deduplication should use both exact and semantic hashes:
298
+
299
+ - If `pack_hash` exists, skip.
300
+ - If `canonical_id` exists with the same or higher version, skip.
301
+ - If a skill body hash matches a core skill, mark as duplicate.
302
+ - If a pack is rejected locally, do not re-download it unless the hash changes.
303
+
304
+ Relay response should support metadata-only dedupe:
305
+
306
+ ```json
307
+ {
308
+ "feedVersion": 1,
309
+ "packs": [
310
+ {
311
+ "packHash": "sha256:...",
312
+ "canonicalId": "skill:android-emulator-screenshot:...",
313
+ "name": "android-emulator-screenshot",
314
+ "version": "0.1.0",
315
+ "valueScore": 92,
316
+ "trustLevel": "community-reviewed",
317
+ "downloadUrl": "/packs/sha256-....tgz",
318
+ "metadataUrl": "/packs/sha256-.../metadata.json"
319
+ }
320
+ ]
321
+ }
322
+ ```
323
+
324
+ Clients should send only hashes when asking what is new:
325
+
326
+ ```http
327
+ POST /sync/metadata
328
+ ```
329
+
330
+ ```json
331
+ {
332
+ "clientProtocol": 1,
333
+ "knownPackHashes": ["sha256:..."],
334
+ "knownCanonicalIds": ["skill:..."],
335
+ "acceptedTrustLevels": ["core", "trusted-publisher", "community-reviewed"]
336
+ }
337
+ ```
338
+
339
+ This keeps routine communication small.
340
+
341
+ ## Skill Pack Format
342
+
343
+ A shared skill pack should be a normal directory or tarball:
344
+
345
+ ```text
346
+ skillpack.json
347
+ skills/<skill-id>/SKILL.md
348
+ profiles/<profile-id>.json
349
+ policies/<policy-id>.json
350
+ tests/<test-id>.js
351
+ examples/<example-id>/README.md
352
+ ```
353
+
354
+ `skillpack.json` should include:
355
+
356
+ ```json
357
+ {
358
+ "schema": 1,
359
+ "name": "android-emulator-screenshot",
360
+ "version": "0.1.0",
361
+ "author": "local-user-or-org",
362
+ "license": "Apache-2.0",
363
+ "createdAt": "2026-05-04T00:00:00.000Z",
364
+ "source": "reviewed-local-learning",
365
+ "privacy": {
366
+ "rawSessionsIncluded": false,
367
+ "secretsRedacted": true,
368
+ "pathsMasked": true,
369
+ "requiresHumanReview": true
370
+ },
371
+ "contents": {
372
+ "skills": ["android-emulator-screenshot"],
373
+ "profiles": ["android"],
374
+ "tests": ["android-screenshot-smoke"]
375
+ },
376
+ "signature": {
377
+ "algorithm": "ed25519",
378
+ "publicKeyId": "..."
379
+ }
380
+ }
381
+ ```
382
+
383
+ The pack should be installable locally:
384
+
385
+ ```bash
386
+ aginti skillmesh import ./android-emulator-screenshot.skillpack.tgz
387
+ ```
388
+
389
+ and exportable:
390
+
391
+ ```bash
392
+ aginti skillmesh export android-emulator-screenshot
393
+ ```
394
+
395
+ ## Trust Model
396
+
397
+ Skill Mesh should treat shared capabilities like dependencies.
398
+
399
+ Trust levels:
400
+
401
+ - **Core**: shipped by the npm package.
402
+ - **Trusted publisher**: signed by LazyingArt or a configured team key.
403
+ - **Community reviewed**: available from a feed, but not automatically active.
404
+ - **Local experimental**: created on this machine.
405
+ - **Blocked**: rejected by the user or a policy rule.
406
+
407
+ Installing a skill pack should show:
408
+
409
+ - Author.
410
+ - Signature status.
411
+ - Files included.
412
+ - Tools/commands it recommends.
413
+ - Whether it changes command policy.
414
+ - Whether it adds tests.
415
+ - Whether it has examples.
416
+
417
+ Default import behavior:
418
+
419
+ ```text
420
+ download -> verify -> preview -> install disabled -> user enables
421
+ ```
422
+
423
+ Do not auto-enable community skills that can cause shell, git, network, browser, or file-writing behavior.
424
+
425
+ ## Server And P2P Options
426
+
427
+ There are three viable distribution modes.
428
+
429
+ ### 1. No Server: npm-Only Sharing
430
+
431
+ This is the safest and simplest.
432
+
433
+ Flow:
434
+
435
+ ```text
436
+ users learn locally -> useful lessons become PRs or releases -> npm package ships updated skills
437
+ ```
438
+
439
+ Pros:
440
+
441
+ - Strong review.
442
+ - Easy install and update.
443
+ - No user data service.
444
+ - Good for stable core skills.
445
+
446
+ Cons:
447
+
448
+ - Slower feedback loop.
449
+ - Less community experimentation.
450
+
451
+ ### 2. Skill Relay Server
452
+
453
+ Use an ECS machine as a lightweight relay/index. Suggested product name:
454
+
455
+ ```text
456
+ AgInTi Skill Relay
457
+ ```
458
+
459
+ The relay should store only reviewed skill packs and feed metadata.
460
+
461
+ Server responsibilities:
462
+
463
+ - Receive signed skill packs.
464
+ - Reject raw session uploads.
465
+ - Run redaction/sanity checks.
466
+ - Compute hashes and deduplicate.
467
+ - Expose feed indexes.
468
+ - Serve downloads.
469
+ - Keep reputation/signature metadata.
470
+ - Optionally maintain review status.
471
+ - Rate-limit clients and publishers.
472
+ - Maintain dedupe indexes by exact and semantic hash.
473
+ - Support metadata-only sync.
474
+ - Quarantine untrusted uploads before feed publication.
475
+
476
+ Server should not:
477
+
478
+ - Store raw `~/.agintiflow/sessions`.
479
+ - Store raw project source.
480
+ - Store provider keys.
481
+ - Execute uploaded code.
482
+ - Auto-push updates to clients.
483
+ - Accept anonymous bulk uploads without rate limits.
484
+ - Act as a general file-sharing server.
485
+ - Serve packs that failed redaction or archive policy checks.
486
+
487
+ Possible server command:
488
+
489
+ ```bash
490
+ aginti-skill-relay serve --host 0.0.0.0 --port 7377 --data ~/.aginti-skill-relay
491
+ ```
492
+
493
+ Client sync:
494
+
495
+ ```bash
496
+ aginti skillmesh feed add lazyingart https://skills.flow.lazying.art/feed.json
497
+ aginti skillmesh sync
498
+ aginti skillmesh inbox
499
+ ```
500
+
501
+ ### Strict Server Contract
502
+
503
+ The relay should be defensive by default.
504
+
505
+ Inbound upload checks:
506
+
507
+ - Require authenticated publisher identity or a temporary upload token.
508
+ - Require signed `skillpack.json`.
509
+ - Require archive size under a small limit, for example 2 MB initially.
510
+ - Require max file count, for example 100 files.
511
+ - Require all paths to be relative and normalized.
512
+ - Reject symlinks, hardlinks, device files, absolute paths, and `..` path traversal.
513
+ - Reject executable binaries by default.
514
+ - Reject nested archives by default.
515
+ - Reject any archive containing raw session filenames.
516
+ - Scan every text file for token/secret patterns.
517
+ - Require `privacy.rawSessionsIncluded=false`.
518
+ - Require `privacy.requiresHumanReview=true` unless the publisher is trusted.
519
+ - Put uploads into `pending` before public feed inclusion.
520
+
521
+ Outbound feed checks:
522
+
523
+ - Serve only approved or trusted packs.
524
+ - Include content hashes and signature metadata.
525
+ - Include trust level and review status.
526
+ - Do not expose uploader IPs or private client metadata.
527
+ - Keep feed response small and cacheable.
528
+ - Use ETag/If-None-Match for low traffic.
529
+
530
+ Abuse controls:
531
+
532
+ - Per-IP rate limits.
533
+ - Per-publisher daily upload limits.
534
+ - Maximum pending queue size.
535
+ - Manual blocklist for bad keys, bad IPs, and bad pack hashes.
536
+ - Audit log of decisions without storing raw private content.
537
+
538
+ The relay should fail closed: if validation cannot prove a pack is safe, the pack stays private/pending.
539
+
540
+ ### Strict Client Contract
541
+
542
+ Clients must also be defensive.
543
+
544
+ Before upload:
545
+
546
+ - Export only reviewed packs from `~/.agintiflow/skillmesh/reviewed/`.
547
+ - Run local redaction scan.
548
+ - Run archive policy scan.
549
+ - Show a human-readable manifest preview.
550
+ - Require explicit confirmation unless the publisher key is configured for unattended sharing.
551
+ - Upload only pack metadata first if possible.
552
+
553
+ Before download/install:
554
+
555
+ - Fetch metadata first.
556
+ - Deduplicate locally.
557
+ - Verify signature when present.
558
+ - Reject packs with unsupported schema.
559
+ - Reject packs requiring disabled capabilities.
560
+ - Install community packs disabled by default.
561
+ - Show diff/manifest before enabling.
562
+ - Never let a downloaded pack directly change provider keys, `.env`, shell policy, or auto-update settings.
563
+
564
+ Client setting:
565
+
566
+ ```json
567
+ {
568
+ "downloadPolicy": {
569
+ "autoDownloadMetadata": true,
570
+ "autoDownloadPacks": false,
571
+ "autoEnableSkills": false,
572
+ "allowPolicyChanges": false,
573
+ "allowExecutableTests": false
574
+ }
575
+ }
576
+ ```
577
+
578
+ ### 3. P2P Mesh
579
+
580
+ True P2P can come later. It is harder because NAT traversal, identity, signatures, spam, and moderation become product concerns.
581
+
582
+ Pragmatic first step:
583
+
584
+ - Use the ECS server as a rendezvous and relay.
585
+ - Keep client identity keypairs local.
586
+ - Sign every skill pack.
587
+ - Let users subscribe to feeds rather than broadcast everything.
588
+
589
+ This gives most of the value of P2P without building a fragile distributed network first.
590
+
591
+ ### Volunteer Shared Nodes
592
+
593
+ A volunteer shared node is a user-run relay that can exchange reviewed skill packs with the major node and with trusted peers.
594
+
595
+ Modes:
596
+
597
+ - **Client only**: syncs with feeds, does not accept inbound connections.
598
+ - **Volunteer node**: serves a local feed and accepts reviewed pack submissions from configured peers.
599
+ - **Major node**: public, stable relay operated by LazyingArt or a trusted maintainer.
600
+
601
+ Volunteer nodes should be opt-in and conservative:
602
+
603
+ ```bash
604
+ aginti skillmesh node init
605
+ aginti skillmesh node check-public
606
+ aginti skillmesh node serve --port 7377
607
+ ```
608
+
609
+ Node health checks:
610
+
611
+ - Public URL configured.
612
+ - TLS available or explicitly disabled for LAN-only.
613
+ - `/health` reachable from outside if public.
614
+ - Feed endpoint reachable.
615
+ - Upload endpoint protected.
616
+ - Data directory not inside a project repo.
617
+ - Rate limits enabled.
618
+ - Pack quarantine enabled.
619
+
620
+ If a machine is behind LAN/NAT, the user can provide an external tunnel:
621
+
622
+ ```bash
623
+ ngrok http 7377
624
+ aginti skillmesh node set-url https://example.ngrok-free.app
625
+ aginti skillmesh node check-public
626
+ ```
627
+
628
+ The node should not guess that it is public. It should verify from an external check endpoint or ask the major relay to call back:
629
+
630
+ ```text
631
+ local node -> major node: please verify https://example.ngrok-free.app/health with nonce abc
632
+ major node -> local node: GET /health?nonce=abc
633
+ local node -> major node: verification succeeds
634
+ ```
635
+
636
+ Only verified nodes should be listed as reachable peers.
637
+
638
+ ### Verified Node Admission
639
+
640
+ A node can join the mesh only after a currently verified node can connect to it and complete the designed verification API.
641
+
642
+ Default admission authority:
643
+
644
+ ```text
645
+ skills.flow.lazying.art
646
+ ```
647
+
648
+ This means a LAN machine exposed by ngrok or a public `ip:port` is not trusted just because the user typed a URL. The major node must verify it first.
649
+
650
+ Admission flow:
651
+
652
+ ```text
653
+ candidate node starts local relay
654
+ candidate node sets public URL, for example ngrok URL or https://ip:port
655
+ candidate node asks major node to verify
656
+ major node creates nonce and expected callback challenge
657
+ major node calls candidate /health and /node/verify endpoints
658
+ candidate proves it owns the local node identity key
659
+ major node checks protocol version, TLS/public URL, feed endpoint, upload protection, rate limits, and quarantine
660
+ major node adds candidate to node list as verified
661
+ verified node appears in feed metadata for optional peer sync
662
+ ```
663
+
664
+ Verification API shape:
665
+
666
+ ```http
667
+ POST /nodes/register
668
+ GET /health?nonce=<nonce>
669
+ POST /node/verify
670
+ GET /feed.json
671
+ ```
672
+
673
+ Candidate registration payload:
674
+
675
+ ```json
676
+ {
677
+ "nodeId": "ed25519:key-id",
678
+ "publicUrl": "https://example.ngrok-free.app",
679
+ "role": "volunteer",
680
+ "protocol": 1,
681
+ "capabilities": ["feed", "metadata-sync"],
682
+ "signature": "signature over publicUrl + nonce"
683
+ }
684
+ ```
685
+
686
+ Major node checks:
687
+
688
+ - Public URL is reachable from the major node.
689
+ - Node identity signature verifies.
690
+ - `/health` returns the expected nonce.
691
+ - `/feed.json` is valid and small.
692
+ - Upload endpoint is either disabled or protected.
693
+ - Node advertises idle/slow sync policy.
694
+ - Node does not claim to accept raw sessions.
695
+ - Node version/protocol is compatible.
696
+
697
+ Node list table:
698
+
699
+ ```sql
700
+ CREATE TABLE verified_nodes (
701
+ node_id TEXT PRIMARY KEY,
702
+ public_url TEXT NOT NULL,
703
+ role TEXT NOT NULL,
704
+ protocol INTEGER NOT NULL,
705
+ status TEXT NOT NULL,
706
+ first_verified_at TEXT NOT NULL,
707
+ last_verified_at TEXT NOT NULL,
708
+ last_seen_at TEXT NOT NULL,
709
+ failure_count INTEGER NOT NULL DEFAULT 0,
710
+ metadata_json TEXT NOT NULL
711
+ );
712
+ ```
713
+
714
+ Removal policy:
715
+
716
+ - Recheck verified nodes occasionally, for example every 6-24 hours.
717
+ - If a node fails once, mark `degraded`.
718
+ - If it fails repeatedly, mark `offline`.
719
+ - If it stays offline beyond a threshold, remove it from the public node list.
720
+ - Keep the historical record locally for audit, but do not advertise unavailable nodes.
721
+
722
+ Suggested thresholds:
723
+
724
+ ```json
725
+ {
726
+ "nodeVerification": {
727
+ "recheckIntervalHours": 12,
728
+ "degradedAfterFailures": 1,
729
+ "offlineAfterFailures": 3,
730
+ "removeAfterOfflineDays": 7
731
+ }
732
+ }
733
+ ```
734
+
735
+ ## ECS Deployment Role
736
+
737
+ The Alibaba Cloud ECS host can run a Skill Relay node.
738
+
739
+ Recommended architecture:
740
+
741
+ ```text
742
+ nginx or caddy
743
+ -> aginti-skill-relay node process
744
+ -> ~/.aginti-skill-relay/index.sqlite
745
+ -> ~/.aginti-skill-relay/packs/
746
+ ```
747
+
748
+ Minimum endpoints:
749
+
750
+ ```text
751
+ GET /health
752
+ GET /feed.json
753
+ GET /packs/<hash>.tgz
754
+ POST /submit
755
+ GET /packs/<hash>/metadata.json
756
+ ```
757
+
758
+ Major node role:
759
+
760
+ - Stable public rendezvous point.
761
+ - Canonical community feed.
762
+ - Deduplication authority for public packs.
763
+ - Optional verification callback service for volunteer nodes.
764
+ - Optional relay for metadata exchange between trusted nodes.
765
+ - Not a raw memory server.
766
+
767
+ Recommended domain:
768
+
769
+ ```text
770
+ skills.flow.lazying.art
771
+ ```
772
+
773
+ Possible deployment command on `sshem`:
774
+
775
+ ```bash
776
+ npm install -g @lazyingart/agintiflow
777
+ aginti skillmesh serve \
778
+ --role major \
779
+ --host 127.0.0.1 \
780
+ --port 7377 \
781
+ --data ~/.aginti-skill-relay \
782
+ --public-url https://skills.flow.lazying.art
783
+ ```
784
+
785
+ With nginx/caddy terminating TLS:
786
+
787
+ ```text
788
+ https://skills.flow.lazying.art
789
+ -> 127.0.0.1:7377
790
+ ```
791
+
792
+ Initial server config:
793
+
794
+ ```json
795
+ {
796
+ "role": "major",
797
+ "publicUrl": "https://skills.flow.lazying.art",
798
+ "dataDir": "~/.aginti-skill-relay",
799
+ "acceptUploads": true,
800
+ "requireSignatures": true,
801
+ "requireReview": true,
802
+ "maxPackBytes": 2097152,
803
+ "maxFilesPerPack": 100,
804
+ "rateLimits": {
805
+ "submitPerIpPerHour": 10,
806
+ "submitPerPublisherPerDay": 20,
807
+ "metadataPerIpPerMinute": 60
808
+ }
809
+ }
810
+ ```
811
+
812
+ ### Major Node Bootstrap On `sshem`
813
+
814
+ The `sshem` ECS machine should be treated as the first **major node**. Other users who enable `Record + Share Reviewed Skills` can sync with it, but the node should still accept only reviewed/signed packs and should publish feeds slowly.
815
+
816
+ Host assumptions from the current ECS login:
817
+
818
+ ```text
819
+ OS: Ubuntu 24.04 LTS
820
+ role: public major relay
821
+ service user: aginti-relay
822
+ data: /var/lib/aginti-skill-relay
823
+ logs: /var/log/aginti-skill-relay
824
+ public domain: skills.flow.lazying.art
825
+ internal port: 7377
826
+ ```
827
+
828
+ Bootstrap outline:
829
+
830
+ ```bash
831
+ sudo adduser --system --group --home /var/lib/aginti-skill-relay aginti-relay
832
+ sudo mkdir -p /var/lib/aginti-skill-relay /var/log/aginti-skill-relay
833
+ sudo chown -R aginti-relay:aginti-relay /var/lib/aginti-skill-relay /var/log/aginti-skill-relay
834
+ npm install -g @lazyingart/agintiflow
835
+ ```
836
+
837
+ Service command:
838
+
839
+ ```bash
840
+ sudo -u aginti-relay aginti skillmesh serve \
841
+ --role major \
842
+ --host 127.0.0.1 \
843
+ --port 7377 \
844
+ --data /var/lib/aginti-skill-relay \
845
+ --public-url https://skills.flow.lazying.art
846
+ ```
847
+
848
+ Systemd shape:
849
+
850
+ ```ini
851
+ [Unit]
852
+ Description=AgInTi Skill Relay
853
+ After=network-online.target
854
+ Wants=network-online.target
855
+
856
+ [Service]
857
+ Type=simple
858
+ User=aginti-relay
859
+ Group=aginti-relay
860
+ WorkingDirectory=/var/lib/aginti-skill-relay
861
+ Environment=NODE_ENV=production
862
+ ExecStart=/usr/bin/env aginti skillmesh serve --role major --host 127.0.0.1 --port 7377 --data /var/lib/aginti-skill-relay --public-url https://skills.flow.lazying.art
863
+ Restart=on-failure
864
+ RestartSec=5
865
+ NoNewPrivileges=true
866
+ PrivateTmp=true
867
+ ProtectSystem=strict
868
+ ProtectHome=true
869
+ ReadWritePaths=/var/lib/aginti-skill-relay /var/log/aginti-skill-relay
870
+
871
+ [Install]
872
+ WantedBy=multi-user.target
873
+ ```
874
+
875
+ Nginx/Caddy should terminate TLS and proxy only the relay domain to `127.0.0.1:7377`. The relay process itself should not bind directly to `0.0.0.0` on the major node unless there is no reverse proxy.
876
+
877
+ Firewall:
878
+
879
+ ```text
880
+ allow 22/tcp for SSH
881
+ allow 80/tcp for ACME HTTP challenge if needed
882
+ allow 443/tcp for HTTPS
883
+ deny public 7377/tcp
884
+ ```
885
+
886
+ Backups:
887
+
888
+ - Back up `index.sqlite`, `packs/`, `trusted-keys/`, and `review-state/`.
889
+ - Do not back up temporary upload quarantine forever; expire rejected uploads.
890
+ - Keep audit logs but rotate them.
891
+ - Never back up or store submitted raw sessions because those should be rejected before persistence.
892
+
893
+ Major node publishing cadence:
894
+
895
+ ```text
896
+ incoming upload -> quarantine -> validation -> pending review -> approved feed batch
897
+ feed batch interval: 30-60 minutes
898
+ metadata cache: ETag + max-age
899
+ pack files: immutable by hash
900
+ ```
901
+
902
+ Major node failure mode:
903
+
904
+ - If validation worker fails, uploads stay pending.
905
+ - If database write fails, upload fails.
906
+ - If redaction scanner fails, upload is rejected or held pending.
907
+ - If feed generation fails, keep serving the last known good feed.
908
+ - If disk usage is high, stop accepting uploads before serving breaks.
909
+
910
+ Submission policy:
911
+
912
+ - Require signed packs.
913
+ - Require `privacy.rawSessionsIncluded=false`.
914
+ - Reject archives containing `.env`, `.git`, `.aginti-sessions`, `.sessions`, `events.jsonl`, `state.json`, `storage-state.json`, or obvious private paths.
915
+ - Run content scans for token patterns.
916
+ - Put new packs into `pending` until approved or trusted.
917
+ - Reject too frequent submissions.
918
+ - Reject duplicate exact hashes immediately.
919
+ - Merge duplicate semantic packs into the same canonical record.
920
+
921
+ ## Sync Frequency Policy
922
+
923
+ Skill Mesh should be closer to package update checks than chat messages.
924
+
925
+ Default sync cadence:
926
+
927
+ ```text
928
+ metadata refresh: every 6-12 hours
929
+ pack upload: idle-only, max 3/day by default
930
+ pack download: manual review or trusted feed only
931
+ major relay feed publish: batch every 30-60 minutes
932
+ volunteer node peer sync: every 12-24 hours
933
+ ```
934
+
935
+ Reasons:
936
+
937
+ - Skills are slow-changing knowledge.
938
+ - Frequent sync increases privacy and abuse risk.
939
+ - Low-frequency sync makes server costs predictable.
940
+ - Idle-only sync avoids interfering with agent work.
941
+ - Batch publishing gives time for validation and review.
942
+
943
+ The UI should show sync state:
944
+
945
+ ```text
946
+ Skill Mesh: Record + Share Reviewed Skills
947
+ last sync: 2026-05-04 13:06
948
+ next sync: after 18:58, idle-only
949
+ outbox: 1 reviewed pack pending
950
+ inbox: 4 new candidates, 0 enabled
951
+ relay: skills.flow.lazying.art healthy
952
+ ```
953
+
954
+ ## Commands
955
+
956
+ Interactive:
957
+
958
+ ```text
959
+ /skillmesh
960
+ ```
961
+
962
+ Selector:
963
+
964
+ ```text
965
+ Skill Mesh
966
+ > Record + Share Reviewed Skills
967
+ Record Locally
968
+ Disabled
969
+ ```
970
+
971
+ CLI:
972
+
973
+ ```bash
974
+ aginti skillmesh status
975
+ aginti skillmesh off
976
+ aginti skillmesh record
977
+ aginti skillmesh share
978
+ aginti skillmesh review
979
+ aginti skillmesh export <name>
980
+ aginti skillmesh import <file-or-url>
981
+ aginti skillmesh feed add <name> <url>
982
+ aginti skillmesh sync
983
+ aginti skillmesh serve
984
+ aginti skillmesh node init
985
+ aginti skillmesh node check-public
986
+ aginti skillmesh node set-url <url>
987
+ ```
988
+
989
+ Config:
990
+
991
+ ```json
992
+ {
993
+ "mode": "share",
994
+ "feeds": [],
995
+ "shareRequiresReview": true,
996
+ "autoInstallSharedSkills": false,
997
+ "trustedPublishers": [],
998
+ "syncPolicy": {
999
+ "idleOnly": true,
1000
+ "minIntervalMinutes": 360,
1001
+ "maxOutboundPacksPerDay": 3
1002
+ }
1003
+ }
1004
+ ```
1005
+
1006
+ Environment override:
1007
+
1008
+ ```bash
1009
+ AGINTIFLOW_SKILLMESH=off
1010
+ AGINTIFLOW_SKILLMESH=record
1011
+ AGINTIFLOW_SKILLMESH=share
1012
+ ```
1013
+
1014
+ ## Safety Rules
1015
+
1016
+ Hard rules:
1017
+
1018
+ - Never upload raw session directories.
1019
+ - Never upload `.aginti-sessions/` or `.sessions/`.
1020
+ - Never upload `.env`, `.npmrc`, SSH keys, browser storage, cookies, or auth tokens.
1021
+ - Never enable shared skills automatically if they affect shell, git, network, filesystem writes, browser auth, or package installation.
1022
+ - Keep the sharing state visible through `aginti skillmesh status`.
1023
+
1024
+ Good defaults:
1025
+
1026
+ - `Record + Share Reviewed Skills` for product default, because it can improve the shared skill set while still requiring strict reviewed-pack sharing.
1027
+ - `Record Locally` for users who want learning logs but no network sharing.
1028
+ - Shared packs install disabled until enabled.
1029
+ - ECS relay accepts uploads only after local pack validation.
1030
+ - Sync is idle-only and low-frequency.
1031
+ - Metadata sync happens before pack transfer.
1032
+ - Deduplication happens before download or upload.
1033
+
1034
+ ## Implementation Stages
1035
+
1036
+ ### Stage 1: Local Skill Mesh
1037
+
1038
+ - Add `/skillmesh` selector with three modes.
1039
+ - Store config in `~/.agintiflow/skillmesh/config.json`.
1040
+ - Add `aginti skillmesh status`.
1041
+ - Keep using the existing housekeeping ledger.
1042
+ - Add local review queue from housekeeping candidates.
1043
+
1044
+ ### Stage 2: Skill Pack Export/Import
1045
+
1046
+ - Add `aginti skillmesh export`.
1047
+ - Add `aginti skillmesh import`.
1048
+ - Support signature generation and verification.
1049
+ - Install imported skills disabled by default.
1050
+
1051
+ ### Stage 3: Relay Server
1052
+
1053
+ - Add a separate npm binary:
1054
+
1055
+ ```bash
1056
+ npm install -g @lazyingart/aginti-skill-relay
1057
+ aginti-skill-relay serve
1058
+ ```
1059
+
1060
+ or keep it inside AgInTiFlow:
1061
+
1062
+ ```bash
1063
+ aginti skillmesh serve
1064
+ ```
1065
+
1066
+ Recommendation: start inside AgInTiFlow for speed, split into `@lazyingart/aginti-skill-relay` once the protocol stabilizes.
1067
+
1068
+ Stage 3 should include:
1069
+
1070
+ - SQLite dedupe database.
1071
+ - Pack archive validator.
1072
+ - Secret scanner.
1073
+ - Signature verifier.
1074
+ - Pending/reviewed/rejected states.
1075
+ - Metadata-only sync endpoint.
1076
+ - Public reachability check for volunteer nodes.
1077
+ - Nginx/Caddy deployment docs for ECS.
1078
+
1079
+ ### Stage 4: Community Feed And Review
1080
+
1081
+ - Add feed subscription.
1082
+ - Add pending inbox.
1083
+ - Add publisher trust list.
1084
+ - Add simple moderation state on the relay.
1085
+ - Publish stable reviewed skills through npm releases.
1086
+
1087
+ ### Stage 5: Volunteer Node Federation
1088
+
1089
+ - Add volunteer node mode.
1090
+ - Add ngrok/public URL configuration.
1091
+ - Add major-node callback verification.
1092
+ - Add peer allowlists.
1093
+ - Add low-frequency node-to-node metadata sync.
1094
+ - Keep major node as the default rendezvous and dedupe authority.
1095
+ - Remove nodes from the advertised node list when repeated reachability checks fail.
1096
+
1097
+ ## Naming Recommendation
1098
+
1099
+ Use:
1100
+
1101
+ ```text
1102
+ Skill Mesh
1103
+ /skillmesh
1104
+ aginti skillmesh
1105
+ AgInTi Skill Relay
1106
+ ```
1107
+
1108
+ Why:
1109
+
1110
+ - `Skill Mesh` describes distributed capability sharing without promising raw P2P networking immediately.
1111
+ - `Skill Relay` is honest for the ECS role: it relays and indexes reviewed packs.
1112
+ - The names are short enough for CLI and clear enough for docs.
1113
+
1114
+ Avoid:
1115
+
1116
+ ```text
1117
+ Skill Cloud
1118
+ Skill Brain
1119
+ Auto Learn Share
1120
+ Swarm Memory
1121
+ ```
1122
+
1123
+ because they imply centralized memory, automatic uploads, or raw agent transcript sharing.