Skip to content

Commit b7ffeba

Browse files
aj1126CopilotCopilot
authored
v1.2.0 - Core Engine Optimization & Semantic Analytics | (Sprints 1-3) + Review Feedback/Regression Fixes (#11)
* feat: Enhance analytics with TF-IDF calculation and CSV report generation - Added TF-IDF analysis to diagnostic analytics for keyword extraction. - Implemented CSV report generation in the delivery module. - Improved file ingestion with caching and fingerprinting for efficiency. - Enhanced predictive analytics with weighted moving average forecasting. - Updated prescriptive analytics to handle missing metadata more gracefully. - Introduced GitHub Actions CI pipeline for automated testing across multiple Node.js versions. * feat: complete v1.2.0 pipeline (concurrency, memoization, tf-idf, and cross-linking) * docs: update readme usage flags and architectural pipeline notes - Added advanced CLI flags (--workers, --clear-cache, --format=csv) to the root README.md usage scope. - Updated docs/architecture.md to detail v1.2.0 pipeline enhancements, including multithreaded worker pool mechanics and semantic vector cross-linking via TF-IDF / Cosine Similarity. - Verified all documentation structures and ran local test runner pipelines cleanly. * addition of usage section and formatting readme * readme formatting * chore: remove analytics cache file * chore: add .analytics_cache.json to .gitignore * fix: validate workers argument and handle symlinks in file ingestion Co-authored-by: Copilot <copilot@github.com> * fix: address PR review security and concurrency feedback * chore: add explicit workflow token permissions * fix(analytics): base forecast on doc dates and optimize worker IPC memory - Fixes domain logic in predictive analytics by switching the timeline basis from the OS file modification time to actual parsed document dates. This prevents modern download timestamps from invalidating historical UAP forecasting. - Resolves worker IPC performance bottlenecks by calculating word frequencies directly inside the worker thread pool rather than passing massive raw string arrays across the boundary. - Mitigates main-thread blocking in diagnostic analytics by capping the O(N²) TF-IDF cosine similarity matrix calculations to a maximum of 500 files. - Adds backwards-compatibility layers in descriptive and diagnostic modules to gracefully handle legacy cache formats without crashing. - Refines watch mode path exclusions in the index file to use a strictly scoped regex for the data exports directory. * fix review feedback gaps * fix workflow token permissions * fix pipeline/watch/cache regressions and modernize test workflow * Address latest PR review thread regressions --------- Co-authored-by: Copilot <copilot@github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent cabb04b commit b7ffeba

20 files changed

Lines changed: 796 additions & 284 deletions

.github/workflows/test.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Node.js CI Pipeline
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
test:
14+
runs-on: ubuntu-latest
15+
strategy:
16+
matrix:
17+
node-version: [20.x, 22.x]
18+
19+
steps:
20+
- uses: actions/checkout@v3
21+
22+
- name: Use Node.js ${{ matrix.node-version }}
23+
uses: actions/setup-node@v3
24+
with:
25+
node-version: ${{ matrix.node-version }}
26+
cache: 'npm'
27+
28+
- name: Clean Install and Test
29+
run: |
30+
npm ci
31+
npm test
32+
npm run docs:check

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Thumbs.db
3232
.env.local
3333
copilot-chat-history.json
3434
*.traineddata
35+
.analytics_cache.json
3536

3637
# =========================
3738
# Bot Specific: Data & Media

.husky/pre-commit

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env sh
2+
3+
npm run docs:generate || exit 1
4+
git add docs/ || exit 1
5+
npm test || exit 1
6+
npm run docs:check || exit 1

README.md

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,17 @@ The current Node ingestion pipeline only analyzes text-oriented files.
8080
| `.csv` | Ingested by the active Node pipeline |
8181
| `.log` | Ingested by the active Node pipeline |
8282
| `.pdf` | Ingested by the active Node pipeline |
83+
| `.png` | Ingested by the active Node pipeline |
84+
| `.jpg` | Ingested by the active Node pipeline |
85+
| `.jpeg` | Ingested by the active Node pipeline |
8386
<!-- GENERATED:supported-file-types:END -->
8487

8588
## Repository Layout
8689

8790
<!-- GENERATED:repo-layout:START -->
8891
- `src/index.js` — Node CLI entry point.
8992
- `src/pipeline.js` — Pipeline coordinator that assembles all analytics tiers.
90-
- `src/ingestion/file-ingestion.js` — Read-only recursive file ingestion for supported text files.
93+
- `src/ingestion/file-ingestion.js` — Read-only recursive file ingestion for supported files.
9194
- `src/analytics/` — Descriptive, diagnostic, predictive, and prescriptive analytics modules.
9295
- `test/pipeline.test.js` — Node test coverage for core pipeline behavior.
9396
- `docs/architecture.md` — Hand-authored architecture overview for current and planned system design.
@@ -125,6 +128,99 @@ The bot must never modify, move, or delete ingested source files. Ingestion is r
125128
- When adding analytics, classify behavior under one of the four analytics tiers.
126129
- Update [docs/architecture.md](docs/architecture.md) when implementation changes affect current-vs-planned system boundaries.
127130

131+
132+
<br>
133+
134+
135+
136+
## ⚙️ Installation & Setup
137+
138+
**Prerequisites:** Ensure you have [Node.js](https://nodejs.org/) installed (version 18, 20, or 22+ recommended).
139+
140+
1. **Clone the repository:**
141+
```bash
142+
git clone https://github.com/aj1126/uap_analyticsbot.git
143+
cd uap_analyticsbot
144+
145+
```
146+
147+
148+
2. **Install dependencies:**
149+
This project installs as a standard Node.js CLI package, so there are no extra native build steps required for the current worker-thread ingestion flow. Simply run:
150+
```bash
151+
npm install
152+
153+
```
154+
155+
156+
3. **Verify the installation:**
157+
Run the local test suite to ensure the multithreaded worker pool and caching engine are functioning correctly on your machine:
158+
```bash
159+
npm test
160+
161+
```
162+
163+
164+
*(If all tests pass green, you are ready to start analyzing documents!)*
165+
166+
167+
---
168+
169+
<br>
170+
171+
172+
173+
174+
## Usage
175+
176+
177+
To run the AnalyticsBot, simply pass the target directory containing your text files as the first argument:
178+
179+
```bash
180+
node src/index.js ./my_folder/
181+
182+
```
183+
184+
By default, this will parse the documents and output a formatted JSON report directly to your console.
185+
186+
### 👀 Watch Mode
187+
188+
Keep the pipeline running in the background. It will automatically re-analyze the documents and recalculate the math whenever you add, edit, or delete a file in the target directory:
189+
190+
```bash
191+
node src/index.js ./my_folder/ --watch
192+
193+
```
194+
195+
### 🖨️ Report Generation
196+
197+
Instead of dumping JSON directly to the console, you can generate formatted report files that are automatically saved to the `/data_exports/` directory:
198+
199+
```bash
200+
node src/index.js ./my_folder/ --format=md
201+
202+
```
203+
204+
*(Supports `md` for Markdown or `csv` for spreadsheet datasets).*
205+
206+
207+
---
208+
<br>
209+
210+
### 🚀 Advanced Usage
211+
212+
The v1.2.0 AnalyticsBot engine supports multithreading and memoization caching. You can control these via CLI arguments:
213+
214+
* `node src/index.js ./my_folder --workers=4` : Manually set the number of Node.js worker threads (defaults to max CPU cores).
215+
* `node src/index.js ./my_folder --clear-cache` : Bypasses the `.analytics_cache.json` file and forces a fresh read of all documents.
216+
* `node src/index.js ./my_folder --format=csv` : Exports the final report as a spreadsheet-compatible `.csv` file.
217+
218+
<br>
219+
<br>
220+
<br>
221+
222+
223+
128224
## 🚀 Planned Technical Optimizations
129225

130226
### 1. Performance & Infrastructure

docs/USER_GUIDE.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,16 @@ npm start -- "C:\Path\To\Folder" > analytics_report.json
5656

5757
## Supported File Types
5858

59-
Currently, the ingestion engine natively parses the following text-based extensions:
59+
Currently, the ingestion engine natively parses the following extensions:
6060
* `.txt`
6161
* `.md`
6262
* `.json`
6363
* `.csv`
6464
* `.log`
65-
66-
*(Note: Binary and multimedia extraction, such as PDF parsing and Image OCR, are tracked for a future development stage).*
65+
* `.pdf`
66+
* `.png`
67+
* `.jpg`
68+
* `.jpeg`
6769

6870
## Testing & Validation
6971

docs/architecture.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,31 @@
44

55
The repository currently ships a Node.js CLI-centered analytics flow:
66

7-
1. **CLI Orchestrator (`src/index.js`)** resolves the source directory and writes the final report to stdout.
8-
2. **Read-Only Ingestion (`src/ingestion/file-ingestion.js`)** recursively scans supported text files, streams file content, and extracts words, dates, locations, and filesystem metadata.
7+
1. **CLI Orchestrator (`src/index.js`)** resolves the source directory, supports watch mode, and routes report output to stdout or export files.
8+
2. **Read-Only Ingestion (`src/ingestion/file-ingestion.js`)** recursively scans supported text files, dispatches parsing work to Node.js worker threads, memoizes compatible results in `.analytics_cache.json`, and extracts words, dates, locations, and filesystem metadata.
99
3. **Analytics Pipeline (`src/pipeline.js`)** builds the descriptive, diagnostic, predictive, and prescriptive tiers from the ingested file set.
10-
4. **Output Layer** returns a single structured JSON report for the requested directory.
10+
4. **Output Layer** returns structured JSON or saves Markdown / CSV exports for the requested directory.
11+
12+
### v1.2.0 Pipeline Architecture
13+
* **Ingestion (Multithreaded):** Utilizes Node.js `worker_threads` and file-stat fingerprinting (`.analytics_cache.json`) to bypass redundant processing and drastically speed up execution.
14+
* **Semantic Analytics:** Employs a TF-IDF weighting engine to filter generic stop-words and a Cosine Similarity math engine to automatically cluster related UAP documents based on vector distance.
1115

1216
## Current Runtime Boundaries
1317

1418
Implemented today:
1519

1620
- recursive read-only ingestion for `.txt`, `.md`, `.json`, `.csv`, and `.log`
21+
- multithreaded parsing with fingerprint-based cache reuse for compatible ingestions
1722
- tokenization plus lightweight date/location extraction
1823
- descriptive, diagnostic, predictive, and prescriptive analytics modules
19-
- JSON report delivery through the Node CLI
24+
- JSON, Markdown, and CSV report delivery through the Node CLI
25+
- directory watch mode that re-runs the pipeline after file changes
2026

2127
Not yet implemented in the active system:
2228

2329
- binary or multimedia extraction
2430
- Named Entity Recognition (NER)
25-
- dashboard or alternate export formats
26-
- background scheduling or directory watching
31+
- dashboard or background scheduling
2732

2833
## Planned Expansion
2934

docs/docs-source.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"description": "Auto-generate CHANGELOG.md, bump the semantic version, and create a Git release tag based on conventional commit history."
2727
}
2828
],
29-
"supportedFileTypes": [".txt", ".md", ".json", ".csv", ".log", ".pdf"],
29+
"supportedFileTypes": [".txt", ".md", ".json", ".csv", ".log", ".pdf", ".png", ".jpg", ".jpeg"],
3030
"repoLayout": [
3131
{
3232
"path": "src/index.js",
@@ -38,7 +38,7 @@
3838
},
3939
{
4040
"path": "src/ingestion/file-ingestion.js",
41-
"description": "Read-only recursive file ingestion for supported text files."
41+
"description": "Read-only recursive file ingestion for supported files."
4242
},
4343
{
4444
"path": "src/analytics/",

package-lock.json

Lines changed: 18 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
"main": "src/index.js",
77
"scripts": {
88
"start": "node src/index.js",
9-
"test": "node --test",
9+
"test": "node --test --experimental-test-coverage",
1010
"docs:generate": "node scripts/generate-docs.js",
1111
"docs:check": "node scripts/generate-docs.js --check && node scripts/validate-docs.js",
12+
"prepare": "husky",
1213
"release": "commit-and-tag-version",
1314
"postrelease": "git push --follow-tags && gh release create v%npm_package_version% --notes-file CHANGELOG.md --title \"Release v%npm_package_version%\""
1415
},
@@ -29,6 +30,7 @@
2930
"tesseract.js": "^7.0.0"
3031
},
3132
"devDependencies": {
32-
"commit-and-tag-version": "^12.7.3"
33+
"commit-and-tag-version": "^12.7.3",
34+
"husky": "^9.1.7"
3335
}
3436
}

src/analytics/descriptive.js

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,43 @@
1-
function countBy(items) {
2-
return items.reduce((counts, item) => {
3-
counts[item] = (counts[item] ?? 0) + 1;
4-
return counts;
5-
}, {});
6-
}
7-
81
function sortEntriesDescending(record) {
92
return Object.entries(record).sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0]));
103
}
114

125
function buildDescriptiveAnalytics(files) {
13-
const allWords = files.flatMap((file) => file.words);
14-
const allDates = files.flatMap((file) => file.dates);
15-
const allLocations = files.flatMap((file) => file.locations);
6+
const allDates = files.flatMap((file) => file.dates || []);
7+
const allLocations = files.flatMap((file) => file.locations || []);
8+
9+
const globalWordFrequency = {};
10+
const glossarySet = new Set();
1611

17-
const wordFrequency = countBy(allWords);
12+
// Iterate through files using the new memory-efficient object format
13+
files.forEach((file) => {
14+
if (file.wordFrequency) {
15+
for (const [word, count] of Object.entries(file.wordFrequency)) {
16+
globalWordFrequency[word] = (globalWordFrequency[word] || 0) + count;
17+
glossarySet.add(word);
18+
}
19+
} else if (file.words) {
20+
// Backwards compatibility layer
21+
for (const word of file.words) {
22+
globalWordFrequency[word] = (globalWordFrequency[word] || 0) + 1;
23+
glossarySet.add(word);
24+
}
25+
}
26+
});
1827

1928
return {
2029
fileCount: files.length,
21-
glossary: [...new Set(allWords)].sort(),
22-
wordFrequency,
23-
topWords: sortEntriesDescending(wordFrequency).slice(0, 10).map(([word, count]) => ({ word, count })),
30+
glossary: [...glossarySet].sort(),
31+
wordFrequency: globalWordFrequency,
32+
topWords: sortEntriesDescending(globalWordFrequency).slice(0, 10).map(([word, count]) => ({ word, count })),
2433
dates: [...new Set(allDates)].sort(),
2534
locations: [...new Set(allLocations)].sort(),
2635
files: files.map((file) => ({
2736
path: file.relativePath,
28-
extension: file.extension, // <-- FIX: Added extension propagation
37+
extension: file.extension,
2938
size: file.size,
3039
modifiedAt: file.modifiedAt,
31-
wordCount: file.words.length,
40+
wordCount: file.totalWords || (file.words ? file.words.length : 0),
3241
dates: file.dates,
3342
locations: file.locations,
3443
metadata: file.metadata || {}

0 commit comments

Comments
 (0)