@treeseed/dsh-chapters 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/LICENSE +14 -0
  2. package/README.md +644 -0
  3. package/cordis.patch.yml +88 -0
  4. package/docs/architecture.md +460 -0
  5. package/docs/contract.md +375 -0
  6. package/docs/development.md +437 -0
  7. package/docs/host-compaction-seam.md +117 -0
  8. package/docs/knowledge-repo.md +730 -0
  9. package/docs/provider.md +98 -0
  10. package/docs/verify.md +200 -0
  11. package/lib/archive.d.ts +88 -0
  12. package/lib/archive.js +114 -0
  13. package/lib/archive.js.map +1 -0
  14. package/lib/arrival.d.ts +23 -0
  15. package/lib/arrival.js +86 -0
  16. package/lib/arrival.js.map +1 -0
  17. package/lib/artifact-query.d.ts +53 -0
  18. package/lib/artifact-query.js +130 -0
  19. package/lib/artifact-query.js.map +1 -0
  20. package/lib/client.js +234 -0
  21. package/lib/client.js.map +1 -0
  22. package/lib/commands.d.ts +28 -0
  23. package/lib/commands.js +305 -0
  24. package/lib/commands.js.map +1 -0
  25. package/lib/compose.d.ts +30 -0
  26. package/lib/compose.js +131 -0
  27. package/lib/compose.js.map +1 -0
  28. package/lib/continue-core.d.ts +153 -0
  29. package/lib/continue-core.js +252 -0
  30. package/lib/continue-core.js.map +1 -0
  31. package/lib/engine-core.d.ts +219 -0
  32. package/lib/engine-core.js +405 -0
  33. package/lib/engine-core.js.map +1 -0
  34. package/lib/engine.d.ts +211 -0
  35. package/lib/engine.js +571 -0
  36. package/lib/engine.js.map +1 -0
  37. package/lib/enrich-queue.d.ts +66 -0
  38. package/lib/enrich-queue.js +100 -0
  39. package/lib/enrich-queue.js.map +1 -0
  40. package/lib/enrich-store.d.ts +31 -0
  41. package/lib/enrich-store.js +103 -0
  42. package/lib/enrich-store.js.map +1 -0
  43. package/lib/enrich-wire.d.ts +73 -0
  44. package/lib/enrich-wire.js +209 -0
  45. package/lib/enrich-wire.js.map +1 -0
  46. package/lib/enrich.d.ts +73 -0
  47. package/lib/enrich.js +150 -0
  48. package/lib/enrich.js.map +1 -0
  49. package/lib/gitops.d.ts +107 -0
  50. package/lib/gitops.js +539 -0
  51. package/lib/gitops.js.map +1 -0
  52. package/lib/index.d.ts +81 -0
  53. package/lib/index.js +305 -0
  54. package/lib/index.js.map +1 -0
  55. package/lib/indexing.d.ts +85 -0
  56. package/lib/indexing.js +212 -0
  57. package/lib/indexing.js.map +1 -0
  58. package/lib/injections.d.ts +66 -0
  59. package/lib/injections.js +83 -0
  60. package/lib/injections.js.map +1 -0
  61. package/lib/notice.d.ts +60 -0
  62. package/lib/notice.js +84 -0
  63. package/lib/notice.js.map +1 -0
  64. package/lib/provider.d.ts +44 -0
  65. package/lib/provider.js +66 -0
  66. package/lib/provider.js.map +1 -0
  67. package/lib/redact.d.ts +24 -0
  68. package/lib/redact.js +85 -0
  69. package/lib/redact.js.map +1 -0
  70. package/lib/registry.d.ts +120 -0
  71. package/lib/registry.js +130 -0
  72. package/lib/registry.js.map +1 -0
  73. package/lib/render.d.ts +40 -0
  74. package/lib/render.js +280 -0
  75. package/lib/render.js.map +1 -0
  76. package/lib/repo.d.ts +78 -0
  77. package/lib/repo.js +184 -0
  78. package/lib/repo.js.map +1 -0
  79. package/lib/rules-commands.d.ts +24 -0
  80. package/lib/rules-commands.js +138 -0
  81. package/lib/rules-commands.js.map +1 -0
  82. package/lib/rules.d.ts +90 -0
  83. package/lib/rules.js +185 -0
  84. package/lib/rules.js.map +1 -0
  85. package/lib/search.d.ts +48 -0
  86. package/lib/search.js +152 -0
  87. package/lib/search.js.map +1 -0
  88. package/lib/signature.d.ts +28 -0
  89. package/lib/signature.js +149 -0
  90. package/lib/signature.js.map +1 -0
  91. package/lib/store.d.ts +130 -0
  92. package/lib/store.js +235 -0
  93. package/lib/store.js.map +1 -0
  94. package/lib/sync.d.ts +183 -0
  95. package/lib/sync.js +719 -0
  96. package/lib/sync.js.map +1 -0
  97. package/lib/tools.d.ts +84 -0
  98. package/lib/tools.js +581 -0
  99. package/lib/tools.js.map +1 -0
  100. package/lib/treedx/client.d.ts +57 -0
  101. package/lib/treedx/client.js +82 -0
  102. package/lib/treedx/client.js.map +1 -0
  103. package/lib/treedx/provider.d.ts +39 -0
  104. package/lib/treedx/provider.js +479 -0
  105. package/lib/treedx/provider.js.map +1 -0
  106. package/lib/treedx/state.d.ts +27 -0
  107. package/lib/treedx/state.js +65 -0
  108. package/lib/treedx/state.js.map +1 -0
  109. package/lib/types.d.ts +100 -0
  110. package/lib/types.js +19 -0
  111. package/lib/types.js.map +1 -0
  112. package/lib/vocabulary.d.ts +41 -0
  113. package/lib/vocabulary.js +118 -0
  114. package/lib/vocabulary.js.map +1 -0
  115. package/package.json +132 -0
  116. package/presets/chapters/agent.cordis.yml +272 -0
  117. package/presets/chapters/preset.yml +3 -0
  118. package/presets/probe-roots/agent.cordis.yml +11 -0
  119. package/presets/probe-roots/preset.yml +3 -0
package/lib/sync.d.ts ADDED
@@ -0,0 +1,183 @@
1
+ import { type ProviderKind, type SyncProvider } from './provider.ts';
2
+ import { type VocabOpts } from './vocabulary.ts';
3
+ /** A linked knowledge project (record §2.1, §8): one record per linked
4
+ * workspace cwd; deepest-cwd match resolves the active project. */
5
+ export interface ProjectRecord {
6
+ projectKey: string;
7
+ slug: string;
8
+ remote: string;
9
+ harnessId: string;
10
+ linkedAt: string;
11
+ /** Workspace cwd this record was linked from (deepest-prefix match, record §8). */
12
+ cwd: string;
13
+ /** Transport kind (§15 amendment); absent = 'git' (pre-provider records). */
14
+ kind?: ProviderKind;
15
+ /** TreeDX: the server-assigned repository id (resolved at link time). */
16
+ repoId?: string | undefined;
17
+ }
18
+ export interface SyncResult {
19
+ ok: boolean;
20
+ /** What actually happened, for the status command and tests. */
21
+ steps: string[];
22
+ detail: string;
23
+ /** 'synced' only when the remote accepted the push; 'local-only' when the
24
+ * mirror is current but the remote did not take it (record §5.3). */
25
+ mode: 'synced' | 'local-only';
26
+ }
27
+ /**
28
+ * Per-project credentials — stored under the DSH HOME, never the workspace
29
+ * (user directive 2026-09-18: the project tree is the agent's reading room;
30
+ * the plugin is the only accessor). 0600 file per projectKey. Note honestly:
31
+ * same-uid files are a hygiene boundary, not a cryptographic one — the real
32
+ * guarantee is that the plugin never echoes the token anywhere an agent sees.
33
+ */
34
+ export declare const tokenPath: (projectKey: string) => string;
35
+ export declare function readToken(cwd: string, storeRoot: string, projectKey: string): string | undefined;
36
+ export declare function writeToken(projectKey: string, token: string): void;
37
+ export interface SyncOpts {
38
+ /** Workspace root — the store and the mirror both live under it. */
39
+ cwd: string;
40
+ /** Store root relative to cwd (`.dsh-chapters`). */
41
+ storeRoot: string;
42
+ /** Mirror directory relative to cwd (`.dsh-knowledge`). */
43
+ cloneDir: string;
44
+ project: ProjectRecord;
45
+ /** Per-harness token for this project (record §2.1); undefined for file remotes. */
46
+ token?: string;
47
+ /** Collection files to (re)publish: one JSONL file per session's signatures. */
48
+ collections?: {
49
+ sessionId: string;
50
+ lines: string[];
51
+ }[];
52
+ /** P2 §6.3 vocabulary pass over the mirror's chapters (undefined = off). */
53
+ vocab?: VocabPassOpts;
54
+ /** Force a run even when the lock is held (tests). Default false. */
55
+ force?: boolean;
56
+ /** Transport provider (tests inject a fake; default resolves from the
57
+ * project record's kind via src/provider.ts — 'git' when absent). */
58
+ provider?: SyncProvider;
59
+ }
60
+ /**
61
+ * Deepest-cwd match (record §8): the active knowledge project for a
62
+ * workspace path. Shared by the notice line, the scheduler, and the commands.
63
+ */
64
+ export declare function projectForCwd(records: Iterable<[string, ProjectRecord]>, cwd: string): ProjectRecord | undefined;
65
+ /** The mirror directory, relative to the workspace (record §3.1). */
66
+ export declare const DEFAULT_CLONE_DIR = ".dsh-knowledge";
67
+ /**
68
+ * File lock around store transactions and clone ops (§5.2): the host-plane
69
+ * plugin and the realm engine may be different module instances in the same
70
+ * process, so an in-process mutex is not safe — a file is the honest lock.
71
+ * Stale locks (>10 min) are stolen; live ones make runSync skip, not block.
72
+ */
73
+ export declare function syncLockPath(storeDir: string): string;
74
+ /**
75
+ * Map workspace-store files to repo paths (record §2.2):
76
+ * <storeRoot>/<rootSession>/chapters/x.md → chapters/<projectKey>/<rootSession>/x.md
77
+ * <storeRoot>/<rootSession>/artifacts/ab/ab….txt → artifacts/<projectKey>/ab/ab….txt
78
+ * Artifacts are content-addressed and shared across sessions, so their
79
+ * per-session prefix is dropped; chapters keep it.
80
+ */
81
+ export declare function planStoreToRepo(storeDir: string, projectKey: string): {
82
+ abs: string;
83
+ rel: string;
84
+ }[];
85
+ export declare const statusFilePath: (cwd: string, storeRoot: string) => string;
86
+ /**
87
+ * Build the Layer-2 index inside the clone (record §10.2): entries from every
88
+ * chapter/rule file (frontmatter), curation facts from every harness's
89
+ * curation.jsonl, the manifest from the clone's index/manifest.json. Returns
90
+ * true when shards or the manifest changed (the commit step then ships them).
91
+ * Deterministic: the index is a pure function of the clone's corpus, so any
92
+ * machine can rebuild it identically (the recovery path, record §10.2).
93
+ */
94
+ export declare function buildIndexInClone(cloneDir: string): boolean;
95
+ export interface VocabPassOpts extends VocabOpts {
96
+ /** write applied aliases? false (shadow) = report only — the default */
97
+ apply: boolean;
98
+ }
99
+ /**
100
+ * One sync pass (record §5): lock → ensure clone (offline init fallback) →
101
+ * publish → commit → pull → push. Failure semantics §5.3: EVERY remote-path
102
+ * failure (clone, pull, push) degrades to local-only mode — the mirror stays
103
+ * current for search and the status file says so with detail; only a local
104
+ * commit failure or lock loss returns without a current mirror. A diverged
105
+ * pull rebuilds the mirror from the remote (safe: the mirror is transport,
106
+ * the store is truth, §3.1). ok=true means the remote accepted the push.
107
+ */
108
+ export declare function runSync(opts: SyncOpts): Promise<SyncResult>;
109
+ /**
110
+ * Pull-only pass for the pre-fork refresh point (record §5.1): ensure the
111
+ * mirror exists (clone, offline-init fallback) and ff-pull it. Never throws,
112
+ * never pushes, never commits — a read-side refresh.
113
+ */
114
+ export declare function runPull(opts: Omit<SyncOpts, 'force'>): Promise<{
115
+ ok: boolean;
116
+ detail: string;
117
+ }>;
118
+ /**
119
+ * A workspace-scoped collections reader for the scheduler (§5): only session
120
+ * trees whose store directory lives in THIS workspace publish. Shared by the
121
+ * host plugin and the realm engine (the two schedulers are the same code over
122
+ * different module copies — the file lock keeps them honest).
123
+ */
124
+ export declare function makeCollectionsReader(sessions: () => IterableIterator<[string, import('./registry.ts').SessionState]>, storeRoot: string): (cwd: string) => {
125
+ sessionId: string;
126
+ lines: string[];
127
+ }[];
128
+ /**
129
+ * The debounced scheduler (§5.2: "consecutive archive events within the
130
+ * configured window coalesce into one push"). Pure wiring — the plane that
131
+ * owns it (host plugin or realm engine) injects how to find the project, the
132
+ * token, and the collection files. Never throws; a failed pass lands in the
133
+ * status file like any other.
134
+ */
135
+ export interface SyncSchedulerDeps {
136
+ storeRoot: string;
137
+ cloneDir?: string;
138
+ debounceMs: number;
139
+ resolveProject(cwd: string): ProjectRecord | undefined;
140
+ tokenFor(cwd: string, projectKey: string): string | undefined;
141
+ /** Collection JSONL lines per session, read from the registry (may be empty). */
142
+ collectionsFor(cwd: string): {
143
+ sessionId: string;
144
+ lines: string[];
145
+ }[];
146
+ /** P2 §6.3 vocabulary pass options for every scheduled pass (undefined = off). */
147
+ vocab?: VocabPassOpts;
148
+ /** Injectable timer (tests). Defaults to setTimeout/clearTimeout. */
149
+ setTimer?: (fn: () => void, ms: number) => {
150
+ cancel(): void;
151
+ };
152
+ provider?: SyncProvider;
153
+ /** P2: fired after a REAL sync pass completes (success or degraded) — the
154
+ * enrichment queue's natural idle point. Not fired for 'no project
155
+ * linked' early-outs (nothing was published, nothing to enrich). */
156
+ onSyncDone?: (cwd: string, ok: boolean) => void;
157
+ }
158
+ export interface SyncScheduler {
159
+ /** Debounced push after an archive event (compaction/fork). */
160
+ schedule(cwd: string, why: string): void;
161
+ /** Immediate pass (a link, an explicit sync). An explicit project wins
162
+ * over the cwd lookup — a re-link must sync the NEW record, not whichever
163
+ * record the cwd tie-break happens to pick. */
164
+ run(cwd: string, why: string, project?: ProjectRecord): Promise<SyncResult>;
165
+ /** Pre-fork refresh (§5.1): pull-only, bounded, never blocks long. */
166
+ pullFor(cwd: string): Promise<{
167
+ ok: boolean;
168
+ detail: string;
169
+ }>;
170
+ hasPending(cwd: string): boolean;
171
+ /** Await any in-flight/scheduled pass (tests + shutdown). */
172
+ drain(): Promise<void>;
173
+ }
174
+ export declare function createSyncScheduler(deps: SyncSchedulerDeps): SyncScheduler;
175
+ /** Read the last sync status (for /chapters-status). Null when never run. */
176
+ export declare function readSyncStatus(cwd: string, storeRoot: string): {
177
+ at: string;
178
+ projectKey: string;
179
+ lastOk: boolean;
180
+ mode?: string;
181
+ detail: string;
182
+ steps: string[];
183
+ } | null;