Files
natsnet/docs/plans/phases/phase-2-verification.md
Joseph Doherty 6021d8445e docs: link completion criteria to Gitea issues and add issue tracking guidance
- Created 52 Gitea issues across milestones 1-7, one per completion criterion
- Each criterion now links to its corresponding issue ([#N](url) format)
- Milestone Tracking sections updated with Issue Updates subsection:
  when/how to comment, close issues via CLI or web UI
- Phases 4-7 criteria converted from plain bullets to checkbox format
2026-02-26 06:50:08 -05:00

352 lines
12 KiB
Markdown

# Phase 2: Verification of Captured Items
## Objective
Verify that the Phase 1 decomposition captured every Go source file, function,
test, and dependency accurately. Compare database counts against independent
baselines derived directly from the filesystem. Identify and fix any gaps before
proceeding to library mapping and porting.
## Prerequisites
- Phase 1 is complete (`porting.db` is populated).
- The Go source at `golang/nats-server/` has not changed since the Phase 1
analyzer run. If the source was updated, re-run the Phase 1 analyzer first.
- `dotnet`, `sqlite3`, `find`, `grep`, and `wc` are available on your PATH.
## Source and Target Locations
| Component | Path |
|---|---|
| Go source code | `golang/` (specifically `golang/nats-server/`) |
| .NET ported version | `dotnet/` |
## Milestone Tracking
This phase corresponds to **Milestone 2** in [Gitea](https://gitea.dohertylan.com/dohertj2/natsnet/milestone/2). When starting this phase, verify the milestone is open. Assign relevant issues to this milestone as work progresses.
### Issue Updates
Each completion criterion has a corresponding Gitea issue. Update issues as you work:
- **Starting a criterion**: Add a comment noting work has begun
- **Blocked**: Add a comment describing the blocker
- **Complete**: Close the issue with a comment summarizing the result (e.g., counts, verification output)
Close issues via CLI:
```bash
curl -s -X PATCH "https://gitea.dohertylan.com/api/v1/repos/dohertj2/natsnet/issues/{N}" \
-H "Content-Type: application/json" \
-H "Authorization: token $GITEA_TOKEN" \
-d '{"state":"closed"}'
```
Or close via the Gitea web UI.
## Steps
### Step 1: Generate the summary report
Start with a high-level view of what the database contains:
```bash
dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db
```
Record the counts for modules, features, unit tests, and library mappings. These
are the numbers you will verify in subsequent steps.
### Step 2: Count Go source files on disk
Count non-test `.go` files under the server directory (the scope of the analyzer):
```bash
find golang/nats-server/server -name "*.go" ! -name "*_test.go" ! -path "*/configs/*" ! -path "*/testdata/*" | wc -l
```
This should produce approximately 109 files. Compare this count against the
number of distinct `go_file` values in the features table:
```bash
sqlite3 porting.db "SELECT COUNT(DISTINCT go_file) FROM features;"
```
If the database count is lower, some source files may have been skipped. Check
the analyzer stderr output for warnings, or list the missing files:
```bash
sqlite3 porting.db "SELECT DISTINCT go_file FROM features ORDER BY go_file;" > /tmp/db_files.txt
find golang/nats-server/server -name "*.go" ! -name "*_test.go" ! -path "*/configs/*" ! -path "*/testdata/*" -exec realpath --relative-to=golang/nats-server {} \; | sort > /tmp/disk_files.txt
diff /tmp/db_files.txt /tmp/disk_files.txt
```
### Step 3: Count Go test files on disk
```bash
find golang/nats-server/server -name "*_test.go" ! -path "*/configs/*" ! -path "*/testdata/*" | wc -l
```
This should produce approximately 85 files. Compare against distinct test files
in the database:
```bash
sqlite3 porting.db "SELECT COUNT(DISTINCT go_file) FROM unit_tests;"
```
### Step 4: Compare function counts
Count all exported and unexported functions in source files on disk:
```bash
grep -r "^func " golang/nats-server/server/ --include="*.go" --exclude="*_test.go" | grep -v "/configs/" | grep -v "/testdata/" | wc -l
```
Compare against the features count from the database:
```bash
sqlite3 porting.db "SELECT COUNT(*) FROM features;"
```
The numbers should be close. Small discrepancies can occur because:
- The `grep` approach counts lines starting with `func` which may miss functions
with preceding comments on the same line or multi-line signatures.
- The AST parser used by the analyzer is more accurate; it finds all `func`
declarations regardless of formatting.
If the database count is significantly lower (more than 5% off), investigate.
### Step 5: Compare test function counts
Count test functions on disk:
```bash
grep -r "^func Test" golang/nats-server/server/ --include="*_test.go" | wc -l
```
Also count benchmarks:
```bash
grep -r "^func Benchmark" golang/nats-server/server/ --include="*_test.go" | wc -l
```
Compare the combined total against the unit_tests table:
```bash
sqlite3 porting.db "SELECT COUNT(*) FROM unit_tests;"
```
### Step 6: Run the phase check command
The PortTracker has a built-in Phase 1 checklist that verifies all tables are
populated:
```bash
dotnet run --project tools/NatsNet.PortTracker -- phase check 1 --db porting.db
```
All items except "All libraries mapped" should show `[x]`.
### Step 7: Check for orphaned items
Look for features that are not linked to any module (should be zero):
```bash
sqlite3 porting.db "SELECT COUNT(*) FROM features WHERE module_id NOT IN (SELECT id FROM modules);"
```
Look for tests that are not linked to any module (should be zero):
```bash
sqlite3 porting.db "SELECT COUNT(*) FROM unit_tests WHERE module_id NOT IN (SELECT id FROM modules);"
```
Look for test-to-feature links that point to non-existent features:
```bash
sqlite3 porting.db "SELECT COUNT(*) FROM unit_tests WHERE feature_id IS NOT NULL AND feature_id NOT IN (SELECT id FROM features);"
```
Look for dependencies that reference non-existent source or target items:
```bash
sqlite3 porting.db "
SELECT COUNT(*) FROM dependencies
WHERE (source_type = 'module' AND source_id NOT IN (SELECT id FROM modules))
OR (target_type = 'module' AND target_id NOT IN (SELECT id FROM modules))
OR (source_type = 'feature' AND source_id NOT IN (SELECT id FROM features))
OR (target_type = 'feature' AND target_id NOT IN (SELECT id FROM features))
OR (source_type = 'unit_test' AND source_id NOT IN (SELECT id FROM unit_tests))
OR (target_type = 'unit_test' AND target_id NOT IN (SELECT id FROM unit_tests));
"
```
All of these queries should return 0.
### Step 8: Review the largest modules
The largest modules are the most likely to have issues. List modules sorted by
feature count:
```bash
sqlite3 porting.db "
SELECT m.id, m.name, m.go_line_count,
COUNT(f.id) as feature_count
FROM modules m
LEFT JOIN features f ON f.module_id = m.id
GROUP BY m.id
ORDER BY feature_count DESC
LIMIT 10;
"
```
For each of the top 3 modules, do a manual spot-check:
```bash
dotnet run --project tools/NatsNet.PortTracker -- module show <id> --db porting.db
```
Scroll through the features list and verify that the functions look correct
(check a few against the actual Go source file).
### Step 9: Validate the dependency graph
Check for any circular module dependencies (modules that depend on each other):
```bash
sqlite3 porting.db "
SELECT d1.source_id, d1.target_id
FROM dependencies d1
JOIN dependencies d2
ON d1.source_type = d2.target_type AND d1.source_id = d2.target_id
AND d1.target_type = d2.source_type AND d1.target_id = d2.source_id
WHERE d1.source_type = 'module' AND d1.target_type = 'module';
"
```
Circular dependencies are not necessarily wrong (Go packages can have them via
interfaces), but they should be reviewed.
Check which items are blocked by unported dependencies:
```bash
dotnet run --project tools/NatsNet.PortTracker -- dependency blocked --db porting.db
```
And confirm that at least some items are ready to port (have no unported deps):
```bash
dotnet run --project tools/NatsNet.PortTracker -- dependency ready --db porting.db
```
### Step 10: Verify library import completeness
Ensure every external import found in the source is tracked:
```bash
sqlite3 porting.db "SELECT COUNT(*) FROM library_mappings;"
```
Cross-check against a manual count of unique non-stdlib imports:
```bash
grep -rh "\"" golang/nats-server/server/ --include="*.go" | \
grep -oP '"\K[^"]+' | \
grep '\.' | \
sort -u | \
wc -l
```
This is an approximate check. The AST-based analyzer is more accurate than grep
for import extraction, but the numbers should be in the same ballpark.
### Step 11: Export a verification snapshot
Save the current state as a markdown report for your records:
```bash
dotnet run --project tools/NatsNet.PortTracker -- report export \
--format md \
--output docs/reports/phase-2-verification.md \
--db porting.db
```
## Completion Criteria
Phase 2 is complete when ALL of the following are true:
- [ ] [#9](https://gitea.dohertylan.com/dohertj2/natsnet/issues/9) Source file counts on disk match distinct `go_file` counts in the database
(within a small margin for intentionally excluded directories).
- [ ] [#10](https://gitea.dohertylan.com/dohertj2/natsnet/issues/10) Feature counts from `grep` are within 5% of the database count (AST is the
authoritative source).
- [ ] [#11](https://gitea.dohertylan.com/dohertj2/natsnet/issues/11) Test function counts from `grep` match the database count closely.
- [ ] [#12](https://gitea.dohertylan.com/dohertj2/natsnet/issues/12) No orphaned features (all linked to valid modules).
- [ ] [#13](https://gitea.dohertylan.com/dohertj2/natsnet/issues/13) No orphaned tests (all linked to valid modules).
- [ ] [#14](https://gitea.dohertylan.com/dohertj2/natsnet/issues/14) No broken test-to-feature links.
- [ ] [#15](https://gitea.dohertylan.com/dohertj2/natsnet/issues/15) No dangling dependency references.
- [ ] [#16](https://gitea.dohertylan.com/dohertj2/natsnet/issues/16) Dependency graph is reviewed -- circular deps (if any) are acknowledged.
- [ ] [#17](https://gitea.dohertylan.com/dohertj2/natsnet/issues/17) `dependency ready` returns at least one item (the graph has valid roots).
- [ ] [#18](https://gitea.dohertylan.com/dohertj2/natsnet/issues/18) Library mappings table contains all external imports.
- [ ] [#19](https://gitea.dohertylan.com/dohertj2/natsnet/issues/19) `phase check 1` passes with all items except "All libraries mapped" checked.
- [ ] Close the Phase 2 milestone in Gitea:
```bash
curl -s -X PATCH "https://gitea.dohertylan.com/api/v1/repos/dohertj2/natsnet/milestones/2" \
-H "Content-Type: application/json" \
-H "Authorization: token $GITEA_TOKEN" \
-d '{"state":"closed"}'
```
Or close it via the Gitea web UI at https://gitea.dohertylan.com/dohertj2/natsnet/milestone/2
## Troubleshooting
### File count mismatch is large
If the disk file count exceeds the database count by more than a few files,
re-run the analyzer with stderr visible:
```bash
./tools/go-analyzer/go-analyzer \
--source golang/nats-server \
--db porting.db \
--schema porting-schema.sql 2>&1 | tee /tmp/analyzer.log
```
Search for warnings:
```bash
grep "Warning" /tmp/analyzer.log
```
Common causes:
- Files with build tags that prevent parsing (e.g., `//go:build ignore`).
- Files in excluded directories (`configs/`, `testdata/`).
- Syntax errors in Go files that the parser cannot handle.
### Feature count is significantly different
The AST parser counts every `func` declaration, including unexported helper
functions. The `grep` baseline only matches lines starting with `func `. If
features that have multiline signatures like:
```go
func (s *Server) handleConnection(
conn net.Conn,
) {
```
...they will be missed by grep but found by the AST parser. Trust the database
count as authoritative.
### Orphaned records found
If orphaned records exist, the analyzer may have a bug or the database was
partially populated from a prior run. The safest fix is to:
1. Delete the database: `rm porting.db`
2. Re-run Phase 1 from Step 1.
### Tests not linked to features
The analyzer uses naming conventions to link tests to features (e.g.,
`TestConnect` maps to a feature containing `Connect`). If many tests show
`feature_id = NULL`, this is expected for tests whose names do not follow the
convention. These links can be manually added later if needed.