cfsa-antigravity 3.0.1 → 3.0.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cfsa-antigravity",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "description": "CFSA Pipeline — Constraint-First Specification Architecture for AI agents. Production-grade from line one.",
5
5
  "scripts": {
6
6
  "changeset": "changeset",
@@ -1,6 +1,6 @@
1
1
  # Kit Sync State
2
2
 
3
3
  upstream: https://github.com/RepairYourTech/cfsa-antigravity
4
- last_synced_commit: a2ac251f783e2da4afa0c7f3b10d3d98fac585b7
5
- last_synced_at: 2026-04-15T05:09:13Z
6
- kit_version: 3.0.1
4
+ last_synced_commit: 63c31d9113ccb3f828aeb5c8a4902483cbbc2e8a
5
+ last_synced_at: 2026-04-15T09:10:27Z
6
+ kit_version: 3.0.2
@@ -1,6 +1,6 @@
1
1
  # Kit Sync State
2
2
 
3
3
  upstream: https://github.com/RepairYourTech/cfsa-antigravity
4
- last_synced_commit: a2ac251f783e2da4afa0c7f3b10d3d98fac585b7
5
- last_synced_at: 2026-04-15T05:09:13Z
6
- kit_version: 3.0.1
4
+ last_synced_commit: 63c31d9113ccb3f828aeb5c8a4902483cbbc2e8a
5
+ last_synced_at: 2026-04-15T09:10:27Z
6
+ kit_version: 3.0.2
@@ -1,6 +1,6 @@
1
1
  # Kit Sync State
2
2
 
3
3
  upstream: https://github.com/RepairYourTech/cfsa-antigravity
4
- last_synced_commit: a2ac251f783e2da4afa0c7f3b10d3d98fac585b7
5
- last_synced_at: 2026-04-15T05:09:13Z
6
- kit_version: 3.0.1
4
+ last_synced_commit: 63c31d9113ccb3f828aeb5c8a4902483cbbc2e8a
5
+ last_synced_at: 2026-04-15T09:10:27Z
6
+ kit_version: 3.0.2
@@ -2,6 +2,7 @@ import { join } from "node:path";
2
2
  import {
3
3
  chunkText,
4
4
  ensureMemoryScaffold,
5
+ getFileText,
5
6
  getMemoryRoot,
6
7
  listFilesRecursively,
7
8
  readJsonl,
@@ -84,8 +85,64 @@ export function compileMemory(options = {}) {
84
85
  const knowledge = records.filter((record) => !["pattern", "decision", "blocker"].includes(record.type));
85
86
 
86
87
  const knowledgeDir = join(memoryRoot, "wiki", "knowledge");
88
+ const specsRoot = join(memoryRoot, "wiki", "specs");
87
89
  const indexEntries = [];
88
90
  const chunkEntries = [];
91
+ const specFiles = listFilesRecursively(specsRoot)
92
+ .filter((filePath) => filePath.endsWith(".md"))
93
+ .filter((filePath) => !filePath.endsWith("README.md"))
94
+ .filter((filePath) => !filePath.endsWith(".gitkeep"));
95
+
96
+ const specTypeForPath = (relativePath) => {
97
+ if (relativePath.includes('/specs/ia/')) return 'ia-spec';
98
+ if (relativePath.includes('/specs/be/')) return 'be-spec';
99
+ if (relativePath.includes('/specs/fe/')) return 'fe-spec';
100
+ if (relativePath.includes('/specs/phases/')) return 'phase-plan';
101
+ if (relativePath.includes('/specs/ideation/')) return 'ideation';
102
+ if (relativePath.includes('/specs/audits/')) return 'audit';
103
+ if (relativePath.includes('/specs/architecture/')) return 'architecture';
104
+ return 'spec';
105
+ };
106
+
107
+ const specTitleForText = (relativePath, text) => {
108
+ const heading = text.split("\n").find((line) => line.startsWith("# "));
109
+ if (heading) {
110
+ return heading.replace(/^#\s+/, '').trim();
111
+ }
112
+ return relativePath.split('/').at(-1)?.replace(/\.md$/, '') ?? relativePath;
113
+ };
114
+
115
+ for (const filePath of specFiles) {
116
+ const text = getFileText(filePath, '');
117
+ if (!text.trim()) {
118
+ continue;
119
+ }
120
+ const relativePath = toRelativePath(projectRoot, filePath);
121
+ const type = specTypeForPath(relativePath);
122
+ const title = specTitleForText(relativePath, text);
123
+ indexEntries.push({
124
+ id: `spec:${relativePath.replace(/^\.memory\/wiki\/specs\//, '').replace(/\.md$/, '')}`,
125
+ type,
126
+ title,
127
+ path: relativePath,
128
+ source: relativePath,
129
+ agent: 'spec-vault',
130
+ timestamp: 'spec-vault',
131
+ excerpt: text.slice(0, 240),
132
+ });
133
+
134
+ for (const [index, chunk] of chunkText(text).entries()) {
135
+ chunkEntries.push({
136
+ id: `spec:${relativePath}:${index + 1}`,
137
+ parentId: `spec:${relativePath.replace(/^\.memory\/wiki\/specs\//, '').replace(/\.md$/, '')}`,
138
+ path: relativePath,
139
+ text: chunk,
140
+ });
141
+ }
142
+ }
143
+
144
+ const seenIndexEntryIds = new Set(indexEntries.map((entry) => entry.id));
145
+ const seenChunkEntryIds = new Set(chunkEntries.map((entry) => entry.id));
89
146
 
90
147
  const getRecordPath = (record) => {
91
148
  if (record.type === "pattern") {
@@ -111,24 +168,32 @@ export function compileMemory(options = {}) {
111
168
 
112
169
  for (const record of records) {
113
170
  const absolutePath = getRecordPath(record);
114
- indexEntries.push({
115
- id: record.id,
116
- type: record.type,
117
- title: record.title ?? record.id,
118
- path: toRelativePath(projectRoot, absolutePath),
119
- source: record.source,
120
- agent: record.agent,
121
- timestamp: record.timestamp,
122
- excerpt: record.text.slice(0, 240),
123
- });
171
+ if (!seenIndexEntryIds.has(record.id)) {
172
+ indexEntries.push({
173
+ id: record.id,
174
+ type: record.type,
175
+ title: record.title ?? record.id,
176
+ path: toRelativePath(projectRoot, absolutePath),
177
+ source: record.source,
178
+ agent: record.agent,
179
+ timestamp: record.timestamp,
180
+ excerpt: record.text.slice(0, 240),
181
+ });
182
+ seenIndexEntryIds.add(record.id);
183
+ }
124
184
 
125
185
  for (const [index, chunk] of chunkText(record.text).entries()) {
186
+ const chunkId = `${record.id}:${index + 1}`;
187
+ if (seenChunkEntryIds.has(chunkId)) {
188
+ continue;
189
+ }
126
190
  chunkEntries.push({
127
- id: `${record.id}:${index + 1}`,
191
+ id: chunkId,
128
192
  parentId: record.id,
129
193
  path: toRelativePath(projectRoot, absolutePath),
130
194
  text: chunk,
131
195
  });
196
+ seenChunkEntryIds.add(chunkId);
132
197
  }
133
198
  }
134
199