Compare commits
3 Commits
feature/re
...
ad2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aed04e8ca4 | ||
|
|
88dc431cfa | ||
|
|
7431bfd52b |
@@ -1,204 +1,246 @@
|
||||
# ClaudeTools Project Context
|
||||
# ClaudeTools on AD2 (Dataforth Domain Controller)
|
||||
|
||||
## Identity: You Are a Coordinator
|
||||
## Identity
|
||||
|
||||
You are NOT an executor. You coordinate specialized agents and preserve your context window.
|
||||
This is the AD2 workstation instance of ClaudeTools. This machine is a Windows Server on the Dataforth LAN (192.168.0.6). Your scope is Dataforth-only -- you do not need context about other clients.
|
||||
|
||||
**Delegate ALL significant work:**
|
||||
## NO EMOJIS
|
||||
|
||||
| Operation | Delegate To |
|
||||
|-----------|------------|
|
||||
| Database queries/inserts/updates | Database Agent |
|
||||
| Production code generation | Coding Agent |
|
||||
| Code review (MANDATORY after changes) | Code Review Agent |
|
||||
| Test execution | Testing Agent |
|
||||
| Git commits/push/branch | Gitea Agent |
|
||||
| Backups/restore | Backup Agent |
|
||||
| File exploration (broad) | Explore Agent |
|
||||
| Semantic code search | deep-explore Agent (uses GrepAI) |
|
||||
| Complex reasoning | General-purpose + Sequential Thinking |
|
||||
|
||||
**Do yourself:** Simple responses, reading 1-2 files, presenting results, planning, decisions.
|
||||
**Rule:** >500 tokens of work = delegate. Code or database = ALWAYS delegate.
|
||||
|
||||
**DO NOT** query databases directly (no SSH/mysql/curl to API). **DO NOT** write production code. **DO NOT** run tests. **DO NOT** commit/push. Use the appropriate agent.
|
||||
Use ASCII markers: [OK], [ERROR], [WARNING], [SUCCESS], [INFO]
|
||||
|
||||
---
|
||||
|
||||
## Project Overview
|
||||
## Git & Sync
|
||||
|
||||
**Type:** MSP Work Tracking System | **Status:** Production-Ready (Phase 5 Complete)
|
||||
**Database:** MariaDB 10.6.22 @ 172.16.3.30:3306 | **API:** http://172.16.3.30:8001
|
||||
**Stats:** 95+ endpoints, 38 tables, JWT auth, AES-256-GCM encryption
|
||||
### Gitea Credentials (no 1Password on this machine)
|
||||
- URL: https://git.azcomputerguru.com
|
||||
- Username: mike@azcomputerguru.com
|
||||
- Password: Gptf*77ttb123!@#-git
|
||||
- URL-encoded password: Gptf%2A77ttb123%21%40%23-git
|
||||
- API Token: 9b1da4b79a38ef782268341d25a4b6880572063f
|
||||
- Remote: https://mike%40azcomputerguru.com:Gptf%2A77ttb123%21%40%23-git@git.azcomputerguru.com/azcomputerguru/claudetools.git
|
||||
|
||||
**DB Connection:** Host: 172.16.3.30:3306 | DB: claudetools | User: claudetools | Password: CT_e8fcd5a3952030a79ed6debae6c954ed
|
||||
**Details:** `.claude/agents/DATABASE_CONNECTION_INFO.md`
|
||||
### Branch: ad2
|
||||
This machine operates on the `ad2` branch. The main workstation merges into main.
|
||||
|
||||
---
|
||||
### /save behavior
|
||||
Save session logs to `session-logs/YYYY-MM-DD-session-ad2.md` (note the -ad2 suffix).
|
||||
After saving, commit and push to origin/ad2.
|
||||
|
||||
## Key Rules
|
||||
|
||||
- **NO EMOJIS** - Use ASCII markers: `[OK]`, `[ERROR]`, `[WARNING]`, `[SUCCESS]`, `[INFO]`
|
||||
- **No hardcoded credentials** - Use 1Password (`op read "op://Vault/Item/field"`) or encrypted storage
|
||||
- **SSH:** Use system OpenSSH (on Windows: `C:\Windows\System32\OpenSSH\ssh.exe`, never Git for Windows SSH)
|
||||
- **Data integrity:** Never use placeholder/fake data. Check credentials.md (op:// refs) or 1Password or ask user.
|
||||
- **Full coding standards:** `.claude/CODING_GUIDELINES.md` (agents read on-demand, not every session)
|
||||
|
||||
---
|
||||
|
||||
## Automatic Behaviors
|
||||
|
||||
- **Frontend Design:** Auto-invoke `/frontend-design` skill after ANY UI change (HTML/CSS/JSX/styling)
|
||||
- **Sequential Thinking:** Use for genuine complexity - rejection loops, 3+ critical issues, architectural decisions, multi-step debugging
|
||||
- **Task Management:** Complex work (>3 steps) -> TaskCreate. Persist to `.claude/active-tasks.json`.
|
||||
|
||||
---
|
||||
|
||||
## Context Recovery
|
||||
|
||||
When user references previous work, use `/context` command. Never ask user for info in:
|
||||
- `credentials.md` - Infrastructure reference with `op://` paths (secrets in 1Password)
|
||||
- `session-logs/` - Daily work logs (also in `projects/*/session-logs/` and `clients/*/session-logs/`)
|
||||
- `SESSION_STATE.md` - Project history
|
||||
|
||||
### 1Password Credential Access
|
||||
|
||||
Credentials are stored in 1Password across 4 vaults: **Infrastructure**, **Clients**, **Projects**, **MSP Tools**.
|
||||
|
||||
**To read a secret:** `op read "op://VaultName/ItemTitle/field_name"`
|
||||
|
||||
**Service account (non-interactive):** Set `OP_SERVICE_ACCOUNT_TOKEN` env var. Token stored in `op://Infrastructure/Service Account Auth Token: Agentic_Cli/credential`. The service account has Read & Write on all 4 vaults (except Projects which is read-only -- use desktop app auth for Projects writes).
|
||||
|
||||
**Setup on new machines:**
|
||||
1. Install 1Password CLI: https://developer.1password.com/docs/cli/get-started/
|
||||
2. Sign in: `op signin` (or use desktop app integration)
|
||||
3. For non-interactive use, add to shell config: `set -gx OP_SERVICE_ACCOUNT_TOKEN "token_value"`
|
||||
|
||||
---
|
||||
|
||||
## Commands & Skills
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `/checkpoint` | Dual checkpoint: git commit + database context |
|
||||
| `/save` | Comprehensive session log (credentials, decisions, changes) |
|
||||
| `/context` | Search session logs, credentials.md, and 1Password |
|
||||
| `/1password` | 1Password secrets management integration |
|
||||
| `/sync` | Sync config from Gitea repository |
|
||||
| `/create-spec` | Create app specification for AutoCoder |
|
||||
| `/frontend-design` | Modern frontend design patterns (auto-invoke after UI changes) |
|
||||
|
||||
---
|
||||
|
||||
## File Placement (Quick Rules)
|
||||
|
||||
- **Dataforth DOS work** -> `projects/dataforth-dos/`
|
||||
- **ClaudeTools API code** -> `api/`, `migrations/` (existing structure)
|
||||
- **Client work** -> `clients/[client-name]/`
|
||||
- **Session logs** -> project or client `session-logs/` subfolder; general -> root `session-logs/`
|
||||
- **Full guide:** `.claude/FILE_PLACEMENT_GUIDE.md` (read when saving files, not every session)
|
||||
|
||||
---
|
||||
|
||||
## Local AI (Ollama)
|
||||
|
||||
Ollama runs locally with GPU acceleration. Use it for tasks that don't need Claude-level reasoning.
|
||||
|
||||
### Available Models
|
||||
|
||||
| Model | Size | Use For |
|
||||
|-------|------|---------|
|
||||
| `qwen3:14b` | 9.3 GB | General sub-tasks: summarization, classification, data extraction, drafting |
|
||||
| `codestral:22b` | 12 GB | Code-specific sub-tasks: code generation, refactoring suggestions, docstring generation |
|
||||
| `nomic-embed-text` | 274 MB | Embeddings only (used by GrepAI, not for direct use) |
|
||||
|
||||
### GrepAI (Semantic Code Search)
|
||||
|
||||
GrepAI indexes the codebase using `nomic-embed-text` embeddings and provides semantic search via MCP server.
|
||||
|
||||
**When to use GrepAI instead of Grep/Glob:**
|
||||
- Finding code by intent ("how does authentication work") rather than exact text
|
||||
- Exploring unfamiliar areas of the codebase
|
||||
- Finding related implementations across files
|
||||
- Context recovery — searching session logs and credentials by meaning
|
||||
|
||||
**How to use:**
|
||||
- **MCP tool:** Use the `grepai` MCP server tools directly (available after MCP loads)
|
||||
- **deep-explore agent:** Delegate to the `deep-explore` agent for thorough semantic exploration
|
||||
- **CLI fallback:** `grepai search "your query" --json --compact`
|
||||
|
||||
**Maintenance:** The watcher daemon runs in the background and auto-indexes file changes. If search results seem stale, run `grepai watch --stop && grepai watch --background` to restart it.
|
||||
|
||||
### Using Ollama for Sub-Tasks
|
||||
|
||||
For bulk or repetitive work that doesn't require Claude's full reasoning, offload to local models via Ollama's API:
|
||||
|
||||
**When to use Ollama:**
|
||||
- Processing many items in a loop (e.g., summarizing 50 session logs)
|
||||
- Generating boilerplate or repetitive code patterns
|
||||
- Data extraction/classification from structured text
|
||||
- Draft content that Claude will review/refine
|
||||
- Any task where speed > quality and results will be verified
|
||||
|
||||
**When NOT to use Ollama (use Claude instead):**
|
||||
- Architectural decisions or complex reasoning
|
||||
- Security-sensitive code review
|
||||
- Tasks requiring tool use or multi-step planning
|
||||
- Final output that goes directly to production
|
||||
|
||||
**How to call Ollama:**
|
||||
```bash
|
||||
# Simple prompt
|
||||
curl -s http://localhost:11434/api/generate -d '{"model":"qwen3:14b","prompt":"Summarize this: ...","stream":false}' | jq -r '.response'
|
||||
|
||||
# Chat format
|
||||
curl -s http://localhost:11434/api/chat -d '{"model":"codestral:22b","messages":[{"role":"user","content":"Refactor this function: ..."}],"stream":false}' | jq -r '.message.content'
|
||||
### /sync behavior
|
||||
```
|
||||
git fetch origin
|
||||
git rebase origin/main
|
||||
git push origin ad2
|
||||
```
|
||||
|
||||
### Ollama Output Review Policy
|
||||
---
|
||||
|
||||
The coordinator (Claude) must review Ollama outputs based on impact level. Local models are useful but unreliable — they hallucinate, miss edge cases, and produce subtly wrong code.
|
||||
## Dataforth Network
|
||||
|
||||
**Impact levels and review requirements:**
|
||||
| Host | IP | Role | Notes |
|
||||
|------|-----|------|-------|
|
||||
| AD1 | 192.168.0.27 | Primary DC | Disk at 90%, C:\Engineering = 787 GB |
|
||||
| **AD2** | **192.168.0.6** | **This machine** | Secondary DC, TestDataDB, file shares |
|
||||
| D2TESTNAS | 192.168.0.9 | SMB1 proxy for DOS | Debian 13, Samba, SSH root/Paper123!@#-nas |
|
||||
| UDM | 192.168.0.254 | Gateway/Router | UniFi Dream Machine |
|
||||
| ESXi-122 | 192.168.0.122 | Hypervisor | ESXi |
|
||||
| ESXi-124 | 192.168.0.124 | Hypervisor | ESXi |
|
||||
| DOS stations | TS-01 to TS-30+ | Test stations | DOS 6.22, QuickBASIC ATE software |
|
||||
|
||||
| Level | Review | Examples |
|
||||
|-------|--------|----------|
|
||||
| **Critical** | ALWAYS review, verify against source | Code touching auth/security/encryption, credential handling, database migrations, production config, anything user-facing |
|
||||
| **High** | Review for correctness, spot-check details | API endpoint logic, business rules, infrastructure scripts, client-specific work |
|
||||
| **Medium** | Skim for obvious errors, trust if reasonable | Internal documentation drafts, session log summaries, data extraction from structured input, boilerplate code |
|
||||
| **Low** | Trust without review | Classification/tagging of items, reformatting text, generating placeholder content for later editing |
|
||||
|
||||
**Review process for Critical/High:**
|
||||
1. Read Ollama's full output — don't just check if it "looks right"
|
||||
2. Verify claims against actual files/data (e.g., if it says a function exists, confirm it does)
|
||||
3. Check for: hallucinated function names, wrong parameter types, missing error handling, security gaps
|
||||
4. If output is wrong or uncertain, redo the task yourself rather than patching Ollama's attempt
|
||||
|
||||
**Batch processing pattern:**
|
||||
When using Ollama for bulk tasks (e.g., processing N items), review the first 2-3 results fully before trusting the rest. If any are wrong, switch to doing it yourself or fix the prompt and reprocess.
|
||||
|
||||
**Flag to user:** If Ollama produces output for a Critical task and you are not confident in your review, tell the user explicitly: "This was generated by a local model and I'm not fully confident in [specific concern]."
|
||||
### Credentials
|
||||
- AD Sysadmin: INTRANET\sysadmin / Paper123!@#
|
||||
- D2TESTNAS SSH: root@192.168.0.9 / Paper123!@#-nas
|
||||
- D2TESTNAS Samba: guest access (no password)
|
||||
- WINS/NPS: 192.168.0.27:1812/1813
|
||||
- M365 Tenant: 7dfa3ce8-c496-4b51-ab8d-bd3dcd78b584
|
||||
- Rsync daemon (NAS): port 873, module "test", user rsync / IQ203s32119
|
||||
|
||||
---
|
||||
|
||||
## Memory (Shared Across Machines)
|
||||
## Local Resources
|
||||
|
||||
Claude Code's auto-memory is stored **in-repo** at `.claude/memory/` so it syncs via Gitea to all workstations.
|
||||
|
||||
**IMPORTANT for all machines:** Configure Claude Code to use the repo memory path, NOT the default `~/.claude/projects/` path. When the auto-memory system prompts you to write to `~/.claude/projects/-home-guru-ClaudeTools/memory/`, write to `.claude/memory/` (repo-relative) instead. The index file is `.claude/memory/MEMORY.md`.
|
||||
|
||||
This ensures memory created on one workstation (CachyOS, Mac, Windows) is available on all others after a git pull/sync.
|
||||
| Resource | Path |
|
||||
|----------|------|
|
||||
| TestDataDB app | C:\Shares\testdatadb\ |
|
||||
| Test database | C:\Shares\testdatadb\database\testdata.db (SQLite, 2.2M+ records) |
|
||||
| TestDataDB API | http://localhost:3000 |
|
||||
| Parsers | C:\Shares\testdatadb\parsers\ (multiline.js, csvline.js, shtfile.js, spec-reader.js) |
|
||||
| Templates | C:\Shares\testdatadb\templates\datasheet-exact.js |
|
||||
| Import script | C:\Shares\testdatadb\database\import.js |
|
||||
| Export script | C:\Shares\testdatadb\database\export-datasheets.js |
|
||||
| Stage import | C:\Shares\testdatadb\import-all-stage.js |
|
||||
| NAS share | \\D2TESTNAS\test (mapped as T:) |
|
||||
| Datasheets share | X:\For_Web |
|
||||
| ProdSW (BAT files) | C:\Shares\test\COMMON\ProdSW\ |
|
||||
| Sync script | C:\Shares\test\scripts\Sync-FromNAS.ps1 (bidirectional, 15-min schedule) |
|
||||
|
||||
---
|
||||
|
||||
## Reference (read on-demand, not every session)
|
||||
## DOS Update System - Batch Files
|
||||
|
||||
- **Project structure, endpoints, workflows, troubleshooting:** `.claude/REFERENCE.md`
|
||||
- **Agent definitions:** `.claude/agents/*.md`
|
||||
- **MCP servers:** `MCP_SERVERS.md`
|
||||
- **Coding standards:** `.claude/CODING_GUIDELINES.md`
|
||||
- **Shared memory:** `.claude/memory/MEMORY.md` (index) + `.claude/memory/*.md` (individual memories)
|
||||
### Boot Sequence on DOS Machines
|
||||
```
|
||||
AUTOEXEC.BAT (v4.1)
|
||||
-> STARTNET.BAT (v2.0) -- init network, map T: and X: drives
|
||||
-> ATESYNC.BAT
|
||||
-> CTONW.BAT (v5.0) -- upload test data to network
|
||||
-> CTONWTXT.BAT (v2.3) -- upload C:\STAGE\*.TXT to T:\STAGE\%MACHINE%
|
||||
-> NWTOC.BAT (v5.0) -- download updates from network
|
||||
```
|
||||
|
||||
### Current Production Versions (on AD2 & NAS)
|
||||
| File | Version | Last Update | Purpose |
|
||||
|------|---------|-------------|---------|
|
||||
| AUTOEXEC.BAT | v4.1 | 2026-03-12 | Startup config |
|
||||
| STARTNET.BAT | v2.0 | 2026-01-20 | Network init |
|
||||
| NWTOC.BAT | v5.0 | 2026-03-16 | Download updates from network |
|
||||
| CTONW.BAT | v5.0 | 2026-03-28 | Upload test data (5 steps with echo) |
|
||||
| CTONWTXT.BAT | v2.3 | 2026-03-28 | Upload Stage TXT files (no MD, dirs pre-created) |
|
||||
| CHECKUPD.BAT | v1.3 | 2026-01-20 | Check for updates |
|
||||
| UPDATE.BAT | v2.3 | 2026-01-20 | Full system backup |
|
||||
| STAGE.BAT | v1.0 | Original | Stage system file updates |
|
||||
| DEPLOY.BAT | v1.0 | 2026-01-20 | One-time deployment installer |
|
||||
|
||||
### DOS 6.22 Compatibility Rules
|
||||
- NO `IF NOT` -- unreliable on DOS 6.22. Use positive `IF EXIST` with GOTO
|
||||
- NO `IF /I` (case-insensitive compare)
|
||||
- NO `FOR /F` loops
|
||||
- NO `%COMPUTERNAME%` -- use `%MACHINE%` (set during DEPLOY)
|
||||
- `XCOPY /D` requires date parameter (`/D:mm-dd-yy`)
|
||||
- `MD` fails with error on existing directories -- pre-create dirs server-side
|
||||
- `COPY` without `/Y` hangs on overwrite prompts
|
||||
- All paths UPPERCASE for Samba compatibility
|
||||
- Line endings MUST be CRLF (0D 0A)
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2026-03-22
|
||||
## Serial Number Encoding (DOS 8.3 filenames)
|
||||
|
||||
QuickBASIC ATE encodes long serial numbers for 8.3 filenames:
|
||||
```
|
||||
First 2 digits replaced with hex letter if serial too long:
|
||||
178236-12 -> H8236-12.TXT (17 -> H, charCode 72 - 55 = 17)
|
||||
10819-1 -> A819-1.TXT (10 -> A, charCode 65 - 55 = 10)
|
||||
|
||||
Decode: letter.charCodeAt(0) - 55 = numeric prefix
|
||||
Only applies when filename starts with [A-Z] followed by digits.
|
||||
|
||||
H-prefix files have decoded SN inside the file (SN: 178236-12)
|
||||
A-prefix files have encoded SN inside the file (SN: A819-1) -- must decode to 10819-1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Test Datasheet Pipeline
|
||||
|
||||
### 5-Stage Architecture
|
||||
1. **DOS Test Programs** -> Write DAT files to C:\ATE\*LOG\ and TXT to C:\STAGE\
|
||||
2. **Boot Upload** -> CTONW.BAT copies DAT to T:\%MACHINE%\LOGS\, CTONWTXT copies TXT to T:\STAGE\%MACHINE%
|
||||
3. **NAS <-> AD2 Sync** -> Rsync every 15 min (Sync-FromNAS.ps1 scheduled task)
|
||||
4. **TestDataDB Import** -> import.js parses DAT into SQLite; export-datasheets.js generates TXT to X:\For_Web
|
||||
5. **Web Share** -> X:\For_Web\ holds validated datasheets (501K+ files)
|
||||
|
||||
### import-all-stage.js (ready to run)
|
||||
Located at `C:\Shares\testdatadb\import-all-stage.js`. Processes ~8,100 TXT files:
|
||||
- Scans \\D2TESTNAS\test\STAGE\TS-*\*.TXT
|
||||
- Decodes hex-prefix serial numbers
|
||||
- Cross-references testdata.db by (serial_number, model_number)
|
||||
- Inserts missing records as log_type='SHT'
|
||||
- Copies to X:\For_Web\{decoded_serial}.TXT
|
||||
|
||||
```
|
||||
cd C:\Shares\testdatadb
|
||||
node import-all-stage.js
|
||||
```
|
||||
|
||||
### Machine data volumes in STAGE
|
||||
| Machine | Files |
|
||||
|---------|-------|
|
||||
| TS-4L | 3,082 |
|
||||
| TS-4R | 2,741 |
|
||||
| TS-1R | 509 |
|
||||
| TS-8R | 478 |
|
||||
| TS-3R | 435 |
|
||||
| TS-11R | 325 |
|
||||
| TS-8L | 285 |
|
||||
| TS-11L | 248 |
|
||||
| TS-27 | 10 (already imported) |
|
||||
| TS-1L | 1 |
|
||||
|
||||
### Web Share Layout (X:\)
|
||||
- X:\For_Web -- Validated datasheets (production)
|
||||
- X:\For_Web_PDF -- PDF versions (4.7K files)
|
||||
- X:\Test_Datasheets -- Incoming/staging
|
||||
- X:\Bad_Datasheets -- Invalid files (18K)
|
||||
- X:\Datasheets_Log -- Processing logs
|
||||
|
||||
---
|
||||
|
||||
## Known Issues & Pending Work
|
||||
|
||||
### HIGH PRIORITY
|
||||
1. **Run import-all-stage.js** -- 8,100 TXT files need cross-referencing and ingestion
|
||||
2. **Website Upload Replacement** -- Old ASP.NET endpoints (Uploader.aspx) return 404. Need new approach.
|
||||
3. **7B Series Datasheets** -- ~830K records can't generate datasheets (missing 7BMAIN.DAT spec file). Check ENGR share.
|
||||
4. **Service Permissions** -- testdatadb runs as SYSTEM, causing file permission issues. Change to INTRANET\sysadmin.
|
||||
|
||||
### MEDIUM PRIORITY
|
||||
5. **C2 IP Blocking** -- iptables rules added to UDM for 80.76.49.18 and 45.88.91.99. Need permanent rules in UniFi UI.
|
||||
6. **MFA Enforcement** -- 19/38 users ready. Report-only until April 4, 2026. Monitor registration.
|
||||
7. **Joel Lohr Account** -- Retiring March 31. Disable account post-retirement. Auto-reply set to Dan Center.
|
||||
|
||||
---
|
||||
|
||||
## Security Incident (2026-03-27)
|
||||
|
||||
**DF-JOEL2 (192.168.0.143) compromised via phishing:**
|
||||
- Joel Lohr clicked phishing link in personal Yahoo email
|
||||
- ScreenConnect C2 installed, "Angel Raya" connected remotely
|
||||
- Two C2 backdoors deployed via PowerShell
|
||||
- C2 IPs: 80.76.49.18, 45.88.91.99 (AS399486, suspended by host)
|
||||
- IC3 Complaint: 1c32ade367084be9acd548f23705736f
|
||||
- ConnectWise Case: 03464184
|
||||
- **Remediation complete:** IPs blocked, 3 rogue clients removed, password reset, sessions revoked
|
||||
- **No lateral movement detected** (32 machines scanned clean)
|
||||
|
||||
---
|
||||
|
||||
## Key Contacts
|
||||
|
||||
| Person | Email | Role |
|
||||
|--------|-------|------|
|
||||
| John Lehman | jlehman@dataforth.com | Engineering, QB code, test specs |
|
||||
| Dan Center | dcenter@dataforth.com | Operations (replacing Joel) |
|
||||
| Peter Iliya | pIliya@dataforth.com | Applications Engineer |
|
||||
| AJ | dataforthgit@... | Engineering contact |
|
||||
| Ken Hoffman | (unresponsive) | TestDataSheetUploader author |
|
||||
| Georg Haubner | ghaubner@dataforth.com | Has pre-crypto backup on D: drive |
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference Commands
|
||||
|
||||
```powershell
|
||||
# Check BAT files on NAS
|
||||
ssh root@192.168.0.9 'ls -la /data/test/COMMON/ProdSW/'
|
||||
|
||||
# Trigger NAS sync
|
||||
Start-ScheduledTask -TaskName 'Sync-FromNAS'
|
||||
|
||||
# Check sync log
|
||||
Get-Content 'C:\Shares\test\scripts\sync-from-nas.log' -Tail 20
|
||||
|
||||
# Check TestDataDB health
|
||||
curl http://localhost:3000/health
|
||||
|
||||
# Query test records
|
||||
node -e "const db=require('better-sqlite3')('C:\\Shares\\testdatadb\\database\\testdata.db',{readonly:true});console.log(db.prepare('SELECT COUNT(*) as cnt FROM test_records').get())"
|
||||
|
||||
# Check Stage files on NAS
|
||||
ssh root@192.168.0.9 'find /data/test/STAGE -name "*.TXT" | wc -l'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2026-03-29
|
||||
|
||||
68
STAGE-IMPORT-INSTRUCTIONS.md
Normal file
68
STAGE-IMPORT-INSTRUCTIONS.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Stage TXT Import Task
|
||||
# Date: 2026-03-28
|
||||
# Context: CTONWTXT.BAT now uploads C:\STAGE\*.TXT from DOS machines to T:\STAGE\%MACHINE%\
|
||||
|
||||
## What happened
|
||||
|
||||
1. CTONWTXT.BAT was never being called -- fixed, now called from CTONW.BAT on every boot
|
||||
2. Destination changed from broken X: (Novell serve.sys check) to T:\STAGE\%MACHINE%\
|
||||
3. DOS 6.22 can't MD on existing dirs without error, so dirs are pre-created on NAS
|
||||
4. All TS-* machine folders pre-created under /data/test/STAGE/ on D2TESTNAS
|
||||
|
||||
## What needs to run
|
||||
|
||||
Save the script below as C:\Shares\testdatadb\import-all-stage.js and run it:
|
||||
|
||||
cd C:\Shares\testdatadb
|
||||
node import-all-stage.js
|
||||
|
||||
## What it does
|
||||
|
||||
- Scans \\D2TESTNAS\test\STAGE\TS-*\*.TXT (~8,100 files across 10 machines)
|
||||
- Parses each TXT datasheet (Date, Model, SN)
|
||||
- Decodes hex-prefix serial numbers for 8.3 filename encoding:
|
||||
- Letter prefix = hex digit: A=10, B=11, C=12, ..., H=17, etc.
|
||||
- Example: H8236-12.TXT has SN: 178236-12 inside the file
|
||||
- Example: A819-1.TXT has SN: A819-1 inside -> decoded to 10819-1
|
||||
- The SN line inside H-prefix files already has the full numeric serial
|
||||
- The SN line inside A-prefix files still has the encoded serial
|
||||
- Cross-references against testdata.db by (serial_number, model_number)
|
||||
- Inserts MISSING records as log_type='SHT' with test_station from folder name
|
||||
- Copies ALL files to X:\For_Web\{decoded_serial}.TXT (the web share)
|
||||
|
||||
## Machines with data
|
||||
|
||||
TS-4L: 3,082 files (largest)
|
||||
TS-4R: 2,741 files
|
||||
TS-1R: 509 files
|
||||
TS-8R: 478 files
|
||||
TS-3R: 435 files
|
||||
TS-11R: 325 files
|
||||
TS-8L: 285 files
|
||||
TS-11L: 248 files
|
||||
TS-27: 10 files (already imported this session)
|
||||
TS-1L: 1 file
|
||||
|
||||
## Serial number encoding (8.3 filename scheme)
|
||||
|
||||
The QuickBASIC ATE software encodes long serial numbers to fit DOS 8.3 filenames.
|
||||
The first two digits get replaced with a hex letter if the serial is too long:
|
||||
|
||||
178236-12 -> H8236-12.TXT (17 -> H, which is char code 72, 72-55=17)
|
||||
10819-1 -> A819-1.TXT (10 -> A, which is char code 65, 65-55=10)
|
||||
|
||||
Decode: letter.charCodeAt(0) - 55 = numeric prefix
|
||||
Only applies if filename starts with [A-Z] followed by digits.
|
||||
|
||||
## TS-27 already done
|
||||
|
||||
10 files from TS-27 were already imported earlier this session into the DB as SHT records.
|
||||
The import script uses INSERT OR REPLACE so re-running is safe.
|
||||
|
||||
## Previous CTONWTXT.BAT issues (resolved)
|
||||
|
||||
- v1.0: Never called, checked for Novell serve.sys, used X: drive parameter
|
||||
- v2.0: Called from CTONW, but used mixed-case "Stage" path -> failed on DOS
|
||||
- v2.1: All uppercase STAGE, but had MD commands that fail on existing dirs
|
||||
- v2.2: Same issue
|
||||
- v2.3: Removed MD entirely, dirs pre-created on NAS. CURRENT VERSION.
|
||||
80
Test Datasheets/weekend-update-draft.md
Normal file
80
Test Datasheets/weekend-update-draft.md
Normal file
@@ -0,0 +1,80 @@
|
||||
Subject: Test Datasheets - Weekend Update: All 73 Quatronix Sheets Generated, Work Order Search Live
|
||||
|
||||
John, Ken,
|
||||
|
||||
Quick update on progress since Friday's email. The pipeline is significantly further along.
|
||||
|
||||
## Quatronix Customer Issue - RESOLVED
|
||||
|
||||
All 73 requested datasheets have been generated (TXT + PDF). The last holdout was SCM5B49-05 (SN 177000-15) — the 5B49DATA.DAT spec file was empty, but John pointed us to 5B49_2.DAT which had the data. All 73 files are ready to send to Peter/Ginger.
|
||||
|
||||
## Model Spec Coverage Expanded
|
||||
|
||||
We went from 751 model specs to 1,470+ by loading additional spec databases:
|
||||
|
||||
| Spec File | Family | Models |
|
||||
|-----------|--------|--------|
|
||||
| 5BMAIN.DAT | SCM5B | 481 |
|
||||
| 5B45DATA.DAT | SCM5B (freq/counter) | 56 |
|
||||
| DB5B48.DAT | SCM5B (multi-bandwidth) | 3 |
|
||||
| 5B49_2.DAT | SCM5B (sample & hold) | 15 |
|
||||
| 8BMAIN.DAT | 8B | 148 |
|
||||
| DSCOUT.DAT | DSCA (output) | 23 |
|
||||
| DSCMAIN4.DAT | DSCA (input) | 391 |
|
||||
| SCTMAIN.DAT | DSCT | 103 |
|
||||
| 7BMAIN.DAT | SCM7B | 276 |
|
||||
|
||||
If there are additional spec files we're missing, let me know the paths and we'll add them.
|
||||
|
||||
## SCM7B Support Added
|
||||
|
||||
The 7B product family is now fully supported in the datasheet generator:
|
||||
- 31 test parameters (vs 20 for SCM5B)
|
||||
- Correct header ("SCM" prefix prepended to model name)
|
||||
- 120VAC Withstand / Hi-Pot (skipped for 7BPT models)
|
||||
- "Packing Check List" with blank fields (vs pre-marked checkboxes on 5B/8B)
|
||||
- "Tested by" and "QC" signature lines
|
||||
- Note: The 7B DAT format (single CSV line) doesn't include individual accuracy test points, so the accuracy table is omitted. Only the Final Test Results section is generated from DAT data.
|
||||
|
||||
## Work Order Search & Linking
|
||||
|
||||
Imported all 33,745 work order status reports from the test station Reports folders:
|
||||
- 63,263 individual test lines parsed (serial number, model, pass/fail, date/time, station)
|
||||
- 2.27 million test records linked to their work orders
|
||||
|
||||
In the web app (http://192.168.0.6:3000):
|
||||
- New "Work Order #" search field — enter a WO number to find all associated test records
|
||||
- Click the WO number in any record's detail view to see the full work order:
|
||||
- All serial numbers tested under that WO
|
||||
- Pass/fail status for each (including retests)
|
||||
- Test program and version used
|
||||
- Test station and timestamps
|
||||
- New work order reports are automatically imported when synced from the NAS
|
||||
|
||||
## Datasheet Formatting Refined
|
||||
|
||||
Compared generated datasheets against originals from the DFWDS archive and fixed column alignment to match the QuickBASIC output:
|
||||
- TAB positions match exactly (parameter names, measured values, spec limits, pass/fail)
|
||||
- Number formatting matches QB PRINT USING (right-justified, correct decimal places)
|
||||
- STR$() behavior replicated (leading space for positive numbers, dropped leading zeros)
|
||||
- Spec limit formatting matches (e.g., "+/- .03 %" not "+/- 0.03 %")
|
||||
|
||||
## View Button Updated
|
||||
|
||||
The "SHEET" button in the web app now shows a styled HTML page that matches the PDF/TXT layout — white page, monospace font, same column alignment. Includes Print and Download PDF buttons.
|
||||
|
||||
## Infrastructure
|
||||
|
||||
- Created domain service account (INTRANET\svc_testdatadb) for the TestDataDB Windows service — resolves the file permission issues we were hitting
|
||||
- Added STAGE folder sync to the NAS sync script — TXT datasheets from DOS machines will now be pulled to AD2 automatically
|
||||
- Work order report import added to sync script — new reports are ingested automatically every 15 minutes
|
||||
|
||||
## Still Open
|
||||
|
||||
1. **Website upload** — The old Uploader.aspx endpoints are dead. Need to determine the new upload mechanism for dataforth.com.
|
||||
2. **STAGE backlog** — ~8,100 TXT files on the NAS from DOS machines need to be processed (script ready, haven't run it yet).
|
||||
3. **Pending ForWeb export** — ~845K records in the database don't have TXT files in For_Web yet (mostly 7B and older records). Can batch-export as needed.
|
||||
|
||||
Let me know if you need anything else.
|
||||
|
||||
Mike
|
||||
88
scripts/Configure-TranscriptLogging.ps1
Normal file
88
scripts/Configure-TranscriptLogging.ps1
Normal file
@@ -0,0 +1,88 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Configures PowerShell transcript logging for remote sessions.
|
||||
|
||||
.DESCRIPTION
|
||||
Enables comprehensive transcript logging via registry settings,
|
||||
creates the logging directory with proper permissions, and sets up
|
||||
automatic log rotation.
|
||||
|
||||
.NOTES
|
||||
Author: ClaudeTools Automation
|
||||
Version: 1.0
|
||||
Run as Administrator
|
||||
#>
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$transcriptPath = "C:\ClaudeTools\Logs\Transcripts"
|
||||
|
||||
Write-Host "Configuring PowerShell Transcript Logging..." -ForegroundColor Cyan
|
||||
|
||||
# Create transcript directory
|
||||
if (-not (Test-Path $transcriptPath)) {
|
||||
New-Item -ItemType Directory -Path $transcriptPath -Force | Out-Null
|
||||
Write-Host "Created transcript directory: $transcriptPath" -ForegroundColor Green
|
||||
}
|
||||
|
||||
# Set permissions on transcript directory
|
||||
# Administrators: Full Control, SYSTEM: Full Control, Remote Management Users: Read/Write
|
||||
$acl = Get-Acl $transcriptPath
|
||||
$acl.SetAccessRuleProtection($true, $false) # Disable inheritance
|
||||
|
||||
# Add Administrators - Full Control
|
||||
$adminRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
|
||||
"Administrators", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
|
||||
)
|
||||
$acl.AddAccessRule($adminRule)
|
||||
|
||||
# Add SYSTEM - Full Control
|
||||
$systemRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
|
||||
"SYSTEM", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
|
||||
)
|
||||
$acl.AddAccessRule($systemRule)
|
||||
|
||||
# Add Remote Management Users - Modify (so they can write transcripts)
|
||||
$rmRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
|
||||
"Remote Management Users", "Modify", "ContainerInherit,ObjectInherit", "None", "Allow"
|
||||
)
|
||||
$acl.AddAccessRule($rmRule)
|
||||
|
||||
Set-Acl $transcriptPath $acl
|
||||
Write-Host "Set permissions on transcript directory" -ForegroundColor Green
|
||||
|
||||
# Configure PowerShell transcript logging via registry
|
||||
$psPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription"
|
||||
|
||||
if (-not (Test-Path $psPath)) {
|
||||
New-Item -Path $psPath -Force | Out-Null
|
||||
}
|
||||
|
||||
# Enable transcription
|
||||
Set-ItemProperty -Path $psPath -Name "EnableTranscripting" -Value 1 -Type DWord
|
||||
Set-ItemProperty -Path $psPath -Name "EnableInvocationHeader" -Value 1 -Type DWord
|
||||
Set-ItemProperty -Path $psPath -Name "OutputDirectory" -Value $transcriptPath -Type String
|
||||
|
||||
Write-Host "Enabled PowerShell transcription via registry" -ForegroundColor Green
|
||||
|
||||
# Also enable module logging for additional audit trail
|
||||
$modulePath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging"
|
||||
if (-not (Test-Path $modulePath)) {
|
||||
New-Item -Path $modulePath -Force | Out-Null
|
||||
}
|
||||
Set-ItemProperty -Path $modulePath -Name "EnableModuleLogging" -Value 1 -Type DWord
|
||||
|
||||
# Enable script block logging
|
||||
$scriptPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"
|
||||
if (-not (Test-Path $scriptPath)) {
|
||||
New-Item -Path $scriptPath -Force | Out-Null
|
||||
}
|
||||
Set-ItemProperty -Path $scriptPath -Name "EnableScriptBlockLogging" -Value 1 -Type DWord
|
||||
|
||||
Write-Host "Enabled module and script block logging" -ForegroundColor Green
|
||||
|
||||
Write-Host "`nTranscript logging configuration complete!" -ForegroundColor Green
|
||||
Write-Host "Transcripts will be saved to: $transcriptPath"
|
||||
|
||||
# Display current settings
|
||||
Write-Host "`n--- Current Settings ---" -ForegroundColor Yellow
|
||||
Get-ItemProperty -Path $psPath | Select-Object EnableTranscripting, EnableInvocationHeader, OutputDirectory
|
||||
87
scripts/Get-ADComputerReport.ps1
Normal file
87
scripts/Get-ADComputerReport.ps1
Normal file
@@ -0,0 +1,87 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Generates a report of all Active Directory computers.
|
||||
|
||||
.DESCRIPTION
|
||||
This script queries Active Directory for all computer accounts and exports
|
||||
key properties including name, operating system, last logon, and OU location.
|
||||
|
||||
.PARAMETER OutputPath
|
||||
Optional. Path to export CSV report. If not specified, outputs to console.
|
||||
|
||||
.PARAMETER OperatingSystem
|
||||
Optional. Filter by operating system (e.g., "Windows Server*", "*Windows 10*").
|
||||
|
||||
.EXAMPLE
|
||||
.\Get-ADComputerReport.ps1
|
||||
Lists all computers to console.
|
||||
|
||||
.EXAMPLE
|
||||
.\Get-ADComputerReport.ps1 -OperatingSystem "Windows Server*" -OutputPath "C:\ClaudeTools\Logs\servers.csv"
|
||||
Exports all Windows Server computers to CSV.
|
||||
|
||||
.NOTES
|
||||
Author: ClaudeTools Automation
|
||||
Version: 1.0
|
||||
Requires: ActiveDirectory PowerShell module
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$OutputPath,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$OperatingSystem = "*"
|
||||
)
|
||||
|
||||
# Import AD module
|
||||
Import-Module ActiveDirectory -ErrorAction Stop
|
||||
|
||||
Write-Host "Querying Active Directory computers..." -ForegroundColor Cyan
|
||||
|
||||
# Get computers with properties
|
||||
$computers = Get-ADComputer -Filter "OperatingSystem -like '$OperatingSystem'" -Properties `
|
||||
OperatingSystem,
|
||||
OperatingSystemVersion,
|
||||
LastLogonDate,
|
||||
Created,
|
||||
Enabled,
|
||||
IPv4Address,
|
||||
Description,
|
||||
DistinguishedName |
|
||||
Select-Object `
|
||||
@{N='Name';E={$_.Name}},
|
||||
@{N='OperatingSystem';E={$_.OperatingSystem}},
|
||||
@{N='OSVersion';E={$_.OperatingSystemVersion}},
|
||||
@{N='Enabled';E={$_.Enabled}},
|
||||
@{N='IPv4Address';E={$_.IPv4Address}},
|
||||
@{N='LastLogon';E={$_.LastLogonDate}},
|
||||
@{N='Created';E={$_.Created}},
|
||||
@{N='OU';E={($_.DistinguishedName -split ',',2)[1]}},
|
||||
@{N='Description';E={$_.Description}}
|
||||
|
||||
$computerCount = ($computers | Measure-Object).Count
|
||||
Write-Host "Found $computerCount computers." -ForegroundColor Green
|
||||
|
||||
if ($OutputPath) {
|
||||
$computers | Export-Csv -Path $OutputPath -NoTypeInformation
|
||||
Write-Host "Report exported to: $OutputPath" -ForegroundColor Green
|
||||
} else {
|
||||
$computers | Format-Table -AutoSize
|
||||
}
|
||||
|
||||
# Summary by OS
|
||||
Write-Host "`n--- Operating System Summary ---" -ForegroundColor Yellow
|
||||
$computers | Group-Object OperatingSystem | Sort-Object Count -Descending |
|
||||
Format-Table @{N='Operating System';E={$_.Name}}, Count -AutoSize
|
||||
|
||||
# Summary by status
|
||||
$enabledCount = ($computers | Where-Object { $_.Enabled -eq $true } | Measure-Object).Count
|
||||
$disabledCount = ($computers | Where-Object { $_.Enabled -eq $false } | Measure-Object).Count
|
||||
Write-Host "Enabled: $enabledCount | Disabled: $disabledCount"
|
||||
|
||||
# Stale computers (no logon in 90 days)
|
||||
$staleDate = (Get-Date).AddDays(-90)
|
||||
$staleCount = ($computers | Where-Object { $_.LastLogon -lt $staleDate -or $null -eq $_.LastLogon } | Measure-Object).Count
|
||||
Write-Host "Stale (no logon 90+ days): $staleCount" -ForegroundColor $(if ($staleCount -gt 0) { 'Yellow' } else { 'Green' })
|
||||
92
scripts/Get-ADUserReport.ps1
Normal file
92
scripts/Get-ADUserReport.ps1
Normal file
@@ -0,0 +1,92 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Generates a report of all Active Directory users with key properties.
|
||||
|
||||
.DESCRIPTION
|
||||
This script queries Active Directory for all user accounts and exports
|
||||
key properties including name, email, last logon, account status, and group memberships.
|
||||
|
||||
.PARAMETER OutputPath
|
||||
Optional. Path to export CSV report. If not specified, outputs to console.
|
||||
|
||||
.PARAMETER IncludeDisabled
|
||||
Switch to include disabled accounts in the report.
|
||||
|
||||
.EXAMPLE
|
||||
.\Get-ADUserReport.ps1
|
||||
Lists all enabled users to console.
|
||||
|
||||
.EXAMPLE
|
||||
.\Get-ADUserReport.ps1 -OutputPath "C:\ClaudeTools\Logs\users.csv" -IncludeDisabled
|
||||
Exports all users (including disabled) to CSV file.
|
||||
|
||||
.NOTES
|
||||
Author: ClaudeTools Automation
|
||||
Version: 1.0
|
||||
Requires: ActiveDirectory PowerShell module
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$OutputPath,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[switch]$IncludeDisabled
|
||||
)
|
||||
|
||||
# Import AD module
|
||||
Import-Module ActiveDirectory -ErrorAction Stop
|
||||
|
||||
Write-Host "Querying Active Directory users..." -ForegroundColor Cyan
|
||||
|
||||
# Build filter
|
||||
$filter = if ($IncludeDisabled) { "*" } else { "Enabled -eq 'True'" }
|
||||
|
||||
# Get users with properties
|
||||
$users = Get-ADUser -Filter $filter -Properties `
|
||||
DisplayName,
|
||||
EmailAddress,
|
||||
Department,
|
||||
Title,
|
||||
Manager,
|
||||
LastLogonDate,
|
||||
PasswordLastSet,
|
||||
PasswordNeverExpires,
|
||||
Enabled,
|
||||
Created,
|
||||
MemberOf,
|
||||
Description |
|
||||
Select-Object `
|
||||
@{N='SamAccountName';E={$_.SamAccountName}},
|
||||
@{N='DisplayName';E={$_.DisplayName}},
|
||||
@{N='Email';E={$_.EmailAddress}},
|
||||
@{N='Department';E={$_.Department}},
|
||||
@{N='Title';E={$_.Title}},
|
||||
@{N='Enabled';E={$_.Enabled}},
|
||||
@{N='LastLogon';E={$_.LastLogonDate}},
|
||||
@{N='PasswordLastSet';E={$_.PasswordLastSet}},
|
||||
@{N='PasswordNeverExpires';E={$_.PasswordNeverExpires}},
|
||||
@{N='Created';E={$_.Created}},
|
||||
@{N='GroupCount';E={($_.MemberOf | Measure-Object).Count}},
|
||||
@{N='Description';E={$_.Description}}
|
||||
|
||||
$userCount = ($users | Measure-Object).Count
|
||||
Write-Host "Found $userCount users." -ForegroundColor Green
|
||||
|
||||
if ($OutputPath) {
|
||||
$users | Export-Csv -Path $OutputPath -NoTypeInformation
|
||||
Write-Host "Report exported to: $OutputPath" -ForegroundColor Green
|
||||
} else {
|
||||
$users | Format-Table -AutoSize
|
||||
}
|
||||
|
||||
# Summary statistics
|
||||
Write-Host "`n--- Summary ---" -ForegroundColor Yellow
|
||||
Write-Host "Total Users: $userCount"
|
||||
$enabledCount = ($users | Where-Object { $_.Enabled -eq $true } | Measure-Object).Count
|
||||
$disabledCount = ($users | Where-Object { $_.Enabled -eq $false } | Measure-Object).Count
|
||||
Write-Host "Enabled: $enabledCount"
|
||||
Write-Host "Disabled: $disabledCount"
|
||||
$neverExpire = ($users | Where-Object { $_.PasswordNeverExpires -eq $true } | Measure-Object).Count
|
||||
Write-Host "Password Never Expires: $neverExpire"
|
||||
111
scripts/Get-GPOStatus.ps1
Normal file
111
scripts/Get-GPOStatus.ps1
Normal file
@@ -0,0 +1,111 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Reports on Group Policy Object status and replication.
|
||||
|
||||
.DESCRIPTION
|
||||
This script checks all GPOs in the domain and reports their status,
|
||||
including version information, links, and replication status between
|
||||
AD and SYSVOL.
|
||||
|
||||
.PARAMETER OutputPath
|
||||
Optional. Path to export CSV report. If not specified, outputs to console.
|
||||
|
||||
.PARAMETER CheckReplication
|
||||
Switch to perform detailed replication check between AD and SYSVOL.
|
||||
|
||||
.EXAMPLE
|
||||
.\Get-GPOStatus.ps1
|
||||
Lists all GPOs with basic status.
|
||||
|
||||
.EXAMPLE
|
||||
.\Get-GPOStatus.ps1 -CheckReplication -OutputPath "C:\ClaudeTools\Logs\gpo-status.csv"
|
||||
Full replication check with CSV export.
|
||||
|
||||
.NOTES
|
||||
Author: ClaudeTools Automation
|
||||
Version: 1.0
|
||||
Requires: GroupPolicy PowerShell module
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$OutputPath,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[switch]$CheckReplication
|
||||
)
|
||||
|
||||
# Import required modules
|
||||
Import-Module GroupPolicy -ErrorAction Stop
|
||||
Import-Module ActiveDirectory -ErrorAction Stop
|
||||
|
||||
Write-Host "Querying Group Policy Objects..." -ForegroundColor Cyan
|
||||
|
||||
# Get all GPOs
|
||||
$gpos = Get-GPO -All | Select-Object `
|
||||
@{N='Name';E={$_.DisplayName}},
|
||||
@{N='ID';E={$_.Id}},
|
||||
@{N='Status';E={$_.GpoStatus}},
|
||||
@{N='CreationTime';E={$_.CreationTime}},
|
||||
@{N='ModificationTime';E={$_.ModificationTime}},
|
||||
@{N='UserVersion';E={$_.User.DSVersion}},
|
||||
@{N='ComputerVersion';E={$_.Computer.DSVersion}},
|
||||
@{N='WMIFilter';E={$_.WmiFilter.Name}}
|
||||
|
||||
$gpoCount = ($gpos | Measure-Object).Count
|
||||
Write-Host "Found $gpoCount GPOs." -ForegroundColor Green
|
||||
|
||||
# Check GPO links
|
||||
Write-Host "`nChecking GPO links..." -ForegroundColor Cyan
|
||||
$gpoLinks = @()
|
||||
foreach ($gpo in (Get-GPO -All)) {
|
||||
$report = [xml](Get-GPOReport -Guid $gpo.Id -ReportType Xml)
|
||||
$links = $report.GPO.LinksTo.SOMPath
|
||||
|
||||
$gpoLinks += [PSCustomObject]@{
|
||||
Name = $gpo.DisplayName
|
||||
LinkCount = if ($links) { ($links | Measure-Object).Count } else { 0 }
|
||||
Links = if ($links) { $links -join "; " } else { "Not Linked" }
|
||||
}
|
||||
}
|
||||
|
||||
if ($CheckReplication) {
|
||||
Write-Host "`nChecking SYSVOL replication status..." -ForegroundColor Cyan
|
||||
|
||||
$domain = (Get-ADDomain).DNSRoot
|
||||
$dcs = Get-ADDomainController -Filter *
|
||||
|
||||
foreach ($dc in $dcs) {
|
||||
Write-Host " Checking $($dc.HostName)..." -ForegroundColor Gray
|
||||
$sysvolPath = "\\$($dc.HostName)\SYSVOL\$domain\Policies"
|
||||
|
||||
if (Test-Path $sysvolPath) {
|
||||
$sysvolGPOs = Get-ChildItem $sysvolPath -Directory | Where-Object { $_.Name -match '^{' }
|
||||
Write-Host " SYSVOL GPO count: $($sysvolGPOs.Count)" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host " Unable to access SYSVOL" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Output results
|
||||
if ($OutputPath) {
|
||||
$gpos | Export-Csv -Path $OutputPath -NoTypeInformation
|
||||
Write-Host "`nReport exported to: $OutputPath" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "`n--- GPO List ---" -ForegroundColor Yellow
|
||||
$gpos | Format-Table Name, Status, ModificationTime, UserVersion, ComputerVersion -AutoSize
|
||||
|
||||
Write-Host "`n--- GPO Links ---" -ForegroundColor Yellow
|
||||
$gpoLinks | Format-Table Name, LinkCount, Links -AutoSize
|
||||
}
|
||||
|
||||
# Summary
|
||||
Write-Host "`n--- Summary ---" -ForegroundColor Yellow
|
||||
Write-Host "Total GPOs: $gpoCount"
|
||||
$unlinked = ($gpoLinks | Where-Object { $_.LinkCount -eq 0 } | Measure-Object).Count
|
||||
Write-Host "Unlinked GPOs: $unlinked" -ForegroundColor $(if ($unlinked -gt 0) { 'Yellow' } else { 'Green' })
|
||||
|
||||
$disabled = ($gpos | Where-Object { $_.Status -ne 'AllSettingsEnabled' } | Measure-Object).Count
|
||||
Write-Host "Disabled/Partial GPOs: $disabled" -ForegroundColor $(if ($disabled -gt 0) { 'Yellow' } else { 'Green' })
|
||||
173
scripts/Get-ReplicationHealth.ps1
Normal file
173
scripts/Get-ReplicationHealth.ps1
Normal file
@@ -0,0 +1,173 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Checks Active Directory replication health across domain controllers.
|
||||
|
||||
.DESCRIPTION
|
||||
This script performs comprehensive AD replication health checks including
|
||||
replication status, partner connectivity, and identifies any replication failures.
|
||||
|
||||
.PARAMETER OutputPath
|
||||
Optional. Path to export results. If not specified, outputs to console.
|
||||
|
||||
.PARAMETER Detailed
|
||||
Switch to show detailed replication information per DC.
|
||||
|
||||
.EXAMPLE
|
||||
.\Get-ReplicationHealth.ps1
|
||||
Basic replication health check.
|
||||
|
||||
.EXAMPLE
|
||||
.\Get-ReplicationHealth.ps1 -Detailed -OutputPath "C:\ClaudeTools\Logs\repl-health.txt"
|
||||
Detailed check with output to file.
|
||||
|
||||
.NOTES
|
||||
Author: ClaudeTools Automation
|
||||
Version: 1.0
|
||||
Requires: ActiveDirectory PowerShell module, repadmin.exe
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$OutputPath,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[switch]$Detailed
|
||||
)
|
||||
|
||||
# Import AD module
|
||||
Import-Module ActiveDirectory -ErrorAction Stop
|
||||
|
||||
$output = @()
|
||||
$output += "=" * 60
|
||||
$output += "AD REPLICATION HEALTH REPORT"
|
||||
$output += "Generated: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
||||
$output += "=" * 60
|
||||
|
||||
Write-Host "Checking AD Replication Health..." -ForegroundColor Cyan
|
||||
|
||||
# Get all DCs
|
||||
$dcs = Get-ADDomainController -Filter *
|
||||
$output += "`nDomain Controllers Found: $($dcs.Count)"
|
||||
|
||||
foreach ($dc in $dcs) {
|
||||
$output += "`n--- $($dc.HostName) ---"
|
||||
Write-Host "Checking $($dc.HostName)..." -ForegroundColor Gray
|
||||
}
|
||||
|
||||
# Check replication summary using repadmin
|
||||
$output += "`n" + "=" * 60
|
||||
$output += "REPLICATION SUMMARY (repadmin /replsummary)"
|
||||
$output += "=" * 60
|
||||
|
||||
try {
|
||||
$replSummary = repadmin /replsummary 2>&1
|
||||
$output += $replSummary
|
||||
Write-Host "Replication summary retrieved." -ForegroundColor Green
|
||||
} catch {
|
||||
$output += "ERROR: Unable to run repadmin /replsummary"
|
||||
Write-Host "Error running repadmin" -ForegroundColor Red
|
||||
}
|
||||
|
||||
# Check for replication failures
|
||||
$output += "`n" + "=" * 60
|
||||
$output += "REPLICATION FAILURES (repadmin /showrepl * /errorsonly)"
|
||||
$output += "=" * 60
|
||||
|
||||
try {
|
||||
$replErrors = repadmin /showrepl * /errorsonly 2>&1
|
||||
if ($replErrors -match "error" -or $replErrors -match "fail") {
|
||||
$output += $replErrors
|
||||
Write-Host "Replication ERRORS detected!" -ForegroundColor Red
|
||||
} else {
|
||||
$output += "No replication errors detected."
|
||||
Write-Host "No replication errors." -ForegroundColor Green
|
||||
}
|
||||
} catch {
|
||||
$output += "ERROR: Unable to check replication errors"
|
||||
}
|
||||
|
||||
# Queue length
|
||||
$output += "`n" + "=" * 60
|
||||
$output += "REPLICATION QUEUE (repadmin /queue)"
|
||||
$output += "=" * 60
|
||||
|
||||
try {
|
||||
$replQueue = repadmin /queue 2>&1
|
||||
$output += $replQueue
|
||||
} catch {
|
||||
$output += "ERROR: Unable to check replication queue"
|
||||
}
|
||||
|
||||
if ($Detailed) {
|
||||
$output += "`n" + "=" * 60
|
||||
$output += "DETAILED REPLICATION STATUS (repadmin /showrepl)"
|
||||
$output += "=" * 60
|
||||
|
||||
try {
|
||||
$replDetail = repadmin /showrepl 2>&1
|
||||
$output += $replDetail
|
||||
} catch {
|
||||
$output += "ERROR: Unable to get detailed replication status"
|
||||
}
|
||||
|
||||
# DFSR Health (if applicable)
|
||||
$output += "`n" + "=" * 60
|
||||
$output += "DFSR SYSVOL REPLICATION STATUS"
|
||||
$output += "=" * 60
|
||||
|
||||
try {
|
||||
$dfsrStatus = Get-DfsrMember -ErrorAction SilentlyContinue
|
||||
if ($dfsrStatus) {
|
||||
$output += "DFSR Members:"
|
||||
foreach ($member in $dfsrStatus) {
|
||||
$output += " - $($member.ComputerName): $($member.DomainName)"
|
||||
}
|
||||
} else {
|
||||
$output += "DFSR not configured or FRS in use."
|
||||
}
|
||||
} catch {
|
||||
$output += "Unable to query DFSR status (may be using FRS)"
|
||||
}
|
||||
}
|
||||
|
||||
# AD Database health
|
||||
$output += "`n" + "=" * 60
|
||||
$output += "AD DATABASE INTEGRITY"
|
||||
$output += "=" * 60
|
||||
|
||||
$adDb = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters" -ErrorAction SilentlyContinue
|
||||
if ($adDb) {
|
||||
$dbPath = $adDb.'DSA Database file'
|
||||
$logPath = $adDb.'Database log files path'
|
||||
$output += "Database Path: $dbPath"
|
||||
$output += "Log Path: $logPath"
|
||||
|
||||
if (Test-Path $dbPath) {
|
||||
$dbSize = (Get-Item $dbPath).Length / 1MB
|
||||
$output += "Database Size: $([math]::Round($dbSize, 2)) MB"
|
||||
}
|
||||
}
|
||||
|
||||
# Final summary
|
||||
$output += "`n" + "=" * 60
|
||||
$output += "HEALTH CHECK COMPLETE"
|
||||
$output += "=" * 60
|
||||
|
||||
# Output results
|
||||
if ($OutputPath) {
|
||||
$output | Out-File -FilePath $OutputPath -Encoding UTF8
|
||||
Write-Host "`nReport saved to: $OutputPath" -ForegroundColor Green
|
||||
} else {
|
||||
$output | ForEach-Object { Write-Host $_ }
|
||||
}
|
||||
|
||||
# Quick status summary
|
||||
Write-Host "`n--- Quick Status ---" -ForegroundColor Yellow
|
||||
Write-Host "Domain Controllers: $($dcs.Count)"
|
||||
$errorMatch = $replErrors -match "error|fail"
|
||||
if ($errorMatch) {
|
||||
Write-Host "Replication Status: ERRORS DETECTED" -ForegroundColor Red
|
||||
} else {
|
||||
Write-Host "Replication Status: HEALTHY" -ForegroundColor Green
|
||||
}
|
||||
107
scripts/Invoke-LogRotation.ps1
Normal file
107
scripts/Invoke-LogRotation.ps1
Normal file
@@ -0,0 +1,107 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Rotates and cleans up old log files.
|
||||
|
||||
.DESCRIPTION
|
||||
Removes transcript and log files older than the specified retention period.
|
||||
Designed to run as a scheduled task daily.
|
||||
|
||||
.PARAMETER RetentionDays
|
||||
Number of days to retain log files. Default is 30.
|
||||
|
||||
.PARAMETER LogPath
|
||||
Path to the logs directory. Default is C:\ClaudeTools\Logs.
|
||||
|
||||
.PARAMETER WhatIf
|
||||
Shows what would be deleted without actually deleting.
|
||||
|
||||
.EXAMPLE
|
||||
.\Invoke-LogRotation.ps1
|
||||
Removes logs older than 30 days.
|
||||
|
||||
.EXAMPLE
|
||||
.\Invoke-LogRotation.ps1 -RetentionDays 14 -WhatIf
|
||||
Shows what would be deleted with 14-day retention.
|
||||
|
||||
.NOTES
|
||||
Author: ClaudeTools Automation
|
||||
Version: 1.0
|
||||
#>
|
||||
|
||||
[CmdletBinding(SupportsShouldProcess)]
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[int]$RetentionDays = 30,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$LogPath = "C:\ClaudeTools\Logs"
|
||||
)
|
||||
|
||||
$rotationLog = Join-Path $LogPath "rotation.log"
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
|
||||
function Write-Log {
|
||||
param([string]$Message)
|
||||
$logEntry = "[$timestamp] $Message"
|
||||
Add-Content -Path $rotationLog -Value $logEntry
|
||||
Write-Host $logEntry
|
||||
}
|
||||
|
||||
Write-Log "=== Log Rotation Started ==="
|
||||
Write-Log "Retention Period: $RetentionDays days"
|
||||
Write-Log "Log Path: $LogPath"
|
||||
|
||||
$cutoffDate = (Get-Date).AddDays(-$RetentionDays)
|
||||
$totalDeleted = 0
|
||||
$totalSizeFreed = 0
|
||||
|
||||
# Find and delete old files
|
||||
$oldFiles = Get-ChildItem -Path $LogPath -Recurse -File |
|
||||
Where-Object { $_.LastWriteTime -lt $cutoffDate -and $_.Name -ne "rotation.log" }
|
||||
|
||||
$fileCount = ($oldFiles | Measure-Object).Count
|
||||
Write-Log "Found $fileCount files older than $RetentionDays days"
|
||||
|
||||
foreach ($file in $oldFiles) {
|
||||
$fileSize = $file.Length
|
||||
$filePath = $file.FullName
|
||||
|
||||
if ($PSCmdlet.ShouldProcess($filePath, "Delete")) {
|
||||
try {
|
||||
Remove-Item $filePath -Force
|
||||
$totalDeleted++
|
||||
$totalSizeFreed += $fileSize
|
||||
Write-Log "Deleted: $filePath ($([math]::Round($fileSize/1KB, 2)) KB)"
|
||||
} catch {
|
||||
Write-Log "ERROR deleting $filePath : $_"
|
||||
}
|
||||
} else {
|
||||
Write-Log "WhatIf: Would delete $filePath ($([math]::Round($fileSize/1KB, 2)) KB)"
|
||||
}
|
||||
}
|
||||
|
||||
# Delete empty subdirectories
|
||||
$emptyDirs = Get-ChildItem -Path $LogPath -Directory -Recurse |
|
||||
Where-Object { (Get-ChildItem $_.FullName -Force).Count -eq 0 }
|
||||
|
||||
foreach ($dir in $emptyDirs) {
|
||||
if ($PSCmdlet.ShouldProcess($dir.FullName, "Remove empty directory")) {
|
||||
try {
|
||||
Remove-Item $dir.FullName -Force
|
||||
Write-Log "Removed empty directory: $($dir.FullName)"
|
||||
} catch {
|
||||
Write-Log "ERROR removing directory $($dir.FullName) : $_"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Summary
|
||||
$sizeMB = [math]::Round($totalSizeFreed / 1MB, 2)
|
||||
Write-Log "=== Rotation Complete ==="
|
||||
Write-Log "Files Deleted: $totalDeleted"
|
||||
Write-Log "Space Freed: $sizeMB MB"
|
||||
|
||||
# Show current disk usage
|
||||
$currentSize = (Get-ChildItem -Path $LogPath -Recurse -File | Measure-Object -Property Length -Sum).Sum
|
||||
$currentSizeMB = [math]::Round($currentSize / 1MB, 2)
|
||||
Write-Log "Current Log Directory Size: $currentSizeMB MB"
|
||||
177
session-logs/2026-04-03-session-ad2.md
Normal file
177
session-logs/2026-04-03-session-ad2.md
Normal file
@@ -0,0 +1,177 @@
|
||||
# Session Log - AD2 - 2026-04-03
|
||||
|
||||
## Session Summary
|
||||
|
||||
Continued test datasheet pipeline work from the 03-27/28/29 session. Major focus on:
|
||||
1. Fixing formatting issues in generated TXT datasheets (column alignment matching QuickBASIC)
|
||||
2. Adding 7B product family support to the exact-match formatter
|
||||
3. Loading additional spec files (5B49_2.DAT for the last missing Quatronix datasheet)
|
||||
4. Work order report ingestion (33K WOs, 63K lines, 2.27M records linked)
|
||||
5. UI improvements (WO search, WO detail popup, View button styled HTML)
|
||||
6. Generating full Dataforth audit document
|
||||
7. Planning and beginning PostgreSQL migration (SQLite hitting 4.4GB, queries timing out)
|
||||
8. Uninstalling SQL Server Express, installing PostgreSQL 18
|
||||
|
||||
## Key Decisions
|
||||
- PostgreSQL over SQL Server Express (no 10GB limit, better FTS, no licensing)
|
||||
- Install PG locally on AD2 (not SAGE-SQL or new VM)
|
||||
- Clean cutover (no parallel run with SQLite)
|
||||
- MSSQL Express uninstalled to free resources
|
||||
|
||||
## Credentials
|
||||
|
||||
### PostgreSQL (newly installed)
|
||||
- Host: localhost (AD2, 192.168.0.6)
|
||||
- Port: 5432
|
||||
- Superuser: postgres / DfPgSQL2026!
|
||||
- App role: testdatadb_app / DfTestDB2026!
|
||||
- Database: testdatadb
|
||||
- Service: postgresql-18 (runs as INTRANET\sysadmin)
|
||||
- Install path: C:\Program Files\PostgreSQL\18\
|
||||
- Data dir: C:\Program Files\PostgreSQL\18\data\
|
||||
|
||||
### TestDataDB (existing)
|
||||
- Service: testdatadb (runs as INTRANET\svc_testdatadb / DfSvcTDB2026!)
|
||||
- URL: http://192.168.0.6:3000
|
||||
- SQLite DB: C:\Shares\testdatadb\database\testdata.db (4.4 GB)
|
||||
|
||||
### Existing (from CLAUDE.md)
|
||||
- AD Sysadmin: INTRANET\sysadmin / Paper123!@#
|
||||
- D2TESTNAS SSH: root@192.168.0.9 / Paper123!@#-nas
|
||||
- Rsync: port 873, user rsync / IQ203s32119
|
||||
- M365 Tenant: 7dfa3ce8-c496-4b51-ab8d-bd3dcd78b584
|
||||
- Gitea: mike@azcomputerguru.com / Gptf*77ttb123!@#-git
|
||||
- Gitea API Token: 9b1da4b79a38ef782268341d25a4b6880572063f
|
||||
|
||||
## Work Completed
|
||||
|
||||
### Formatting Fixes (datasheet-exact.js)
|
||||
- Compared generated TXT against originals from X:\For_Web\2025\
|
||||
- Fixed Final Test Results column alignment to match QB TAB positions:
|
||||
- TAB(5) param name, TAB(31) measured value, TAB(60-speclen) spec, TAB(61) unit, TAB(71) PASS/FAIL
|
||||
- Added setCol() and padToCol() helpers for exact column positioning
|
||||
- Fixed STR$() emulation: leading space for positive, drops leading zero (.03 not 0.03)
|
||||
- Fixed header spacing (Date, Model, SN fields)
|
||||
- Fixed checklist spacing to match QB TAB(45)
|
||||
- Fixed separator line length (23 chars not 24)
|
||||
|
||||
### 7B Product Family Support
|
||||
- Added SCM7B DATA_LINES (31 parameters vs 20 for SCM5B)
|
||||
- Added SCM7B TSPECS (supply current, linearity, accuracy, excitation, CJC, noise, etc.)
|
||||
- Added 7B raw_data parser (single CSV line format vs multi-line for other families)
|
||||
- 7B-specific footer: 120VAC (not 240), "Packing Check List" (not "Check List"), blank checkmarks, Tested by/QC lines
|
||||
- Accuracy section suppressed for 7B (DAT format doesn't include individual test points)
|
||||
- 7B model names prepend "SCM" in header
|
||||
|
||||
### Additional Spec File: 5B49_2.DAT
|
||||
- 5B49DATA.DAT was 0 bytes (empty), John pointed to 5B49_2.DAT
|
||||
- 15 models, 93 bytes/record, added SCM5B49_FIELDS to spec-reader.js
|
||||
- Completed final missing Quatronix datasheet (177000-15, SCM5B49-05)
|
||||
- All 73/73 Quatronix datasheets now generated
|
||||
|
||||
### View Button Enhancement
|
||||
- /api/datasheet/:id now uses exact-match formatter with styled HTML
|
||||
- White page on gray background, monospace font, print-optimized
|
||||
- Includes Print and Download PDF buttons
|
||||
- Falls back to generic template if exact-match not available
|
||||
|
||||
### PDF Endpoint Fallback
|
||||
- /api/datasheet/:id/pdf falls back to generic template when exact-match fails
|
||||
- Prevents 422 errors for unsupported families
|
||||
|
||||
### Work Order Reports
|
||||
- Created parsers/wo-report.js (parses WO status report TXT format)
|
||||
- Created database/import-work-orders.js (imports WOs, creates tables, links to test records)
|
||||
- Created work_orders table (33,745 records) and work_order_lines table (63,263 records)
|
||||
- Added work_order column to test_records, 2,277,183 records linked via serial number pattern
|
||||
- Added /api/workorder/:wo and /api/workorder-search endpoints
|
||||
- Added WO# search field and clickable WO link in UI detail view
|
||||
- WO detail popup shows all test lines, pass/fail history, program version
|
||||
- Added auto-import hooks to Sync-FromNAS-rsync.ps1 for Reports and STAGE folders
|
||||
|
||||
### Sync Script Updates (Sync-FromNAS-rsync.ps1)
|
||||
- Added STAGE folder sync (NAS STAGE -> AD2)
|
||||
- Added $syncedReportFiles and $syncedStageFiles tracking
|
||||
- Added WO report auto-import after sync
|
||||
- Added STAGE TXT auto-import after sync
|
||||
- Updated status file with WO and STAGE counts
|
||||
|
||||
### Dataforth Audit Document
|
||||
- Generated C:\Users\sysadmin\Desktop\Dataforth-Audit-2026-04-02.txt
|
||||
- 22 sections: company info, network, AD computers/users/groups, GPO, DNS, shares, tasks, services, firewall, credentials, M365, security incidents, manufacturing infrastructure, pipeline, applications, backups, known issues, contacts
|
||||
|
||||
### PostgreSQL Migration (IN PROGRESS)
|
||||
- Plan approved: PostgreSQL 18 on AD2, clean cutover
|
||||
- PostgreSQL 18.3 installed via Chocolatey
|
||||
- Database cluster initialized (C:\Program Files\PostgreSQL\18\data\)
|
||||
- Service registered as postgresql-18 (runs as INTRANET\sysadmin)
|
||||
- Database created: testdatadb owned by testdatadb_app
|
||||
- SQL Server Express 2022 uninstalled
|
||||
|
||||
### SQLite Issues Documented
|
||||
- Database grown to 4.4GB
|
||||
- Single search query took 5,157 seconds (85 minutes)
|
||||
- Stats query took 216 seconds
|
||||
- WAL file grew to 454MB
|
||||
- ANALYZE ran for 30+ minutes without completing
|
||||
- SHM/WAL permission conflicts between SYSTEM and sysadmin
|
||||
|
||||
### Service Account (from previous session, still relevant)
|
||||
- INTRANET\svc_testdatadb created in OU=ServiceAccounts
|
||||
- testdatadb Windows service runs under this account
|
||||
- SeServiceLogonRight granted
|
||||
- Permissions on C:\Shares\testdatadb and C:\Shares\webshare
|
||||
|
||||
## Files Created
|
||||
- C:\Shares\testdatadb\fix-sysadmin-logon.ps1
|
||||
- C:\ClaudeTools\Test Datasheets\weekend-update-draft.md
|
||||
- C:\Users\sysadmin\Desktop\Dataforth-Audit-2026-04-02.txt
|
||||
- C:\Users\sysadmin\.claude\plans\generic-petting-lovelace.md (PG migration plan)
|
||||
|
||||
## Files Modified
|
||||
- C:\Shares\testdatadb\templates\datasheet-exact.js — Column alignment, 7B support, STR$() emulation
|
||||
- C:\Shares\testdatadb\parsers\spec-reader.js — Added 5B49 TYPE, fuzzy model matching
|
||||
- C:\Shares\testdatadb\parsers\wo-report.js — Created (WO report parser)
|
||||
- C:\Shares\testdatadb\database\import-work-orders.js — Created (WO importer)
|
||||
- C:\Shares\testdatadb\database\schema.sql — Added work_order column
|
||||
- C:\Shares\testdatadb\routes\api.js — Added WO endpoints, PDF fallback, view button exact-match
|
||||
- C:\Shares\testdatadb\public\index.html — WO search, WO popup, view button styling
|
||||
- C:\Shares\test\scripts\Sync-FromNAS-rsync.ps1 — STAGE sync, WO auto-import
|
||||
|
||||
## Database Stats (as of session end)
|
||||
- Test records: 2,294,877
|
||||
- Work orders: 33,745
|
||||
- Work order lines: 63,263
|
||||
- Records with WO linked: 2,277,183
|
||||
- ForWeb exported: ~1,436,000
|
||||
- Model specs loaded: 1,470+
|
||||
|
||||
## Pending / Next Steps
|
||||
1. **PostgreSQL Migration (Step 2-8):**
|
||||
- Create PG schema (schema-pg.sql) with tsvector FTS
|
||||
- Create database abstraction layer (db.js)
|
||||
- Migrate routes/api.js to async
|
||||
- Migrate import/export scripts
|
||||
- Build data migration script
|
||||
- Migrate 2.28M records
|
||||
- Test and cutover
|
||||
|
||||
2. **Tune PostgreSQL config:**
|
||||
- shared_buffers=1GB, work_mem=64MB, maintenance_work_mem=256MB
|
||||
|
||||
3. **MSSQL cleanup:**
|
||||
- May need reboot to fully remove SQL Server services
|
||||
|
||||
4. **Website upload:**
|
||||
- Old ASP.NET endpoints still dead (404)
|
||||
- Need to determine new upload mechanism
|
||||
|
||||
5. **Joel Lohr account:**
|
||||
- Retired March 31 — account needs to be disabled
|
||||
|
||||
## Infrastructure
|
||||
- AD2: 192.168.0.6 (Windows Server 2016)
|
||||
- PostgreSQL 18: localhost:5432 (newly installed, service running)
|
||||
- TestDataDB: localhost:3000 (SQLite, service running)
|
||||
- NAS: 192.168.0.9 (rsync port 873)
|
||||
- STAGE backlog: cleared (0 files remaining)
|
||||
Reference in New Issue
Block a user