+16
-16
docs/git-history.json
+16
-16
docs/git-history.json
···
1
1
[
2
2
{
3
-
"hash": "6ced3f0b015af1c9126559a393996576402cfd03",
4
-
"short_hash": "6ced3f0",
3
+
"hash": "a90f3a813fd9527e8e59bb1da242e7b67555a8eb",
4
+
"short_hash": "a90f3a8",
5
5
"author": "Ariel M. Lighty",
6
-
"date": "2025-12-26T14:12:46-05:00",
7
-
"message": "fix extension flow: create user_source_follows, auto-search, time display\n\nBackend (extension-import.ts):\n- Now creates user_source_follows entries linking upload to source accounts\n- Without these, get-upload-details returned empty (queries FROM user_source_follows)\n- Uses bulkCreate return value (Map<username, id>) to create links\n\nFrontend (App.tsx):\n- handleLoadUpload now detects if upload has no matches yet\n- Sets isSearching: true for new uploads\n- Automatically triggers searchAllUsers for new uploads\n- Saves results after search completes\n- Changed platform from hardcoded \"tiktok\" to \"twitter\"\n\nFrontend (HistoryTab.tsx):\n- Fixed time display: removed \"Uploaded\" prefix\n- Now shows \"about 5 hours ago\" instead of \"Uploaded in about 5 hours\"\n- formatRelativeTime with addSuffix already provides complete sentence\n\nResolves:\n- Empty results on page load\n- No automatic searching\n- History navigation not working (will work after search)\n- Grammatically incorrect time display",
8
-
"files_changed": 5
6
+
"date": "2025-12-26T16:11:04-05:00",
7
+
"message": "fix: pass onProgressUpdate and onComplete callbacks to searchAllUsers",
8
+
"files_changed": 3
9
9
},
10
10
{
11
11
"hash": "6ced3f0b015af1c9126559a393996576402cfd03",
···
32
32
"files_changed": 4
33
33
},
34
34
{
35
-
"hash": "95636330f387598f55017eda668fb9f91ccde509",
36
-
"short_hash": "9563633",
35
+
"hash": "9ca734749fbaa014828f8437afc5e515610afd31",
36
+
"short_hash": "9ca7347",
37
37
"author": "Ariel M. Lighty",
38
-
"date": "2025-12-26T13:35:52-05:00",
39
-
"message": "fix extension api-client: unwrap ApiResponse.data structure\n\nBackend endpoints use successResponse() which wraps data in:\n { success: true, data: {...} }\n\nExtension was expecting flat response structure, causing:\n- uploadToATlast to return undefined (missing importId, redirectUrl)\n- checkSession to return wrapped object instead of user data\n- Invalid URL error: \"http://127.0.0.1:8888undefined\"\n\nFixed both uploadToATlast and checkSession to access apiResponse.data",
40
-
"files_changed": 2
38
+
"date": "2025-12-26T13:37:24-05:00",
39
+
"message": "update documentation: extension ready for testing after API response fix",
40
+
"files_changed": 4
41
41
},
42
42
{
43
43
"hash": "95636330f387598f55017eda668fb9f91ccde509",
···
88
88
"files_changed": 3
89
89
},
90
90
{
91
-
"hash": "ba29fd68872913ba0a587aa7f29f97b3d373a732",
92
-
"short_hash": "ba29fd6",
91
+
"hash": "32cdee3aeac7ef986df47e0fff786b5f7471e55b",
92
+
"short_hash": "32cdee3",
93
93
"author": "Ariel M. Lighty",
94
94
"date": "2025-12-25T13:22:32-05:00",
95
95
"message": "configure Netlify dev for monorepo with --filter flag\n\nFixed Netlify CLI monorepo detection issue by using --filter flag:\n- Updated root package.json scripts to use 'npx netlify-cli dev --filter @atlast/web'\n- Updated netlify.toml [dev] section to use npm with --prefix for framework command\n- Added monorepo development instructions to CLAUDE.md\n- Documented Windows Git Bash compatibility issue with netlify command\n\nSolution: Use 'npx netlify-cli dev --filter @atlast/web' to bypass monorepo\nproject selection prompt and specify which workspace package to run.\n\nDev server now runs successfully at http://localhost:8888 with all backend\nfunctions loaded.",
96
-
"files_changed": 5
96
+
"files_changed": 4
97
97
},
98
98
{
99
-
"hash": "32cdee3aeac7ef986df47e0fff786b5f7471e55b",
100
-
"short_hash": "32cdee3",
99
+
"hash": "ba29fd68872913ba0a587aa7f29f97b3d373a732",
100
+
"short_hash": "ba29fd6",
101
101
"author": "Ariel M. Lighty",
102
102
"date": "2025-12-25T13:22:32-05:00",
103
103
"message": "configure Netlify dev for monorepo with --filter flag\n\nFixed Netlify CLI monorepo detection issue by using --filter flag:\n- Updated root package.json scripts to use 'npx netlify-cli dev --filter @atlast/web'\n- Updated netlify.toml [dev] section to use npm with --prefix for framework command\n- Added monorepo development instructions to CLAUDE.md\n- Documented Windows Git Bash compatibility issue with netlify command\n\nSolution: Use 'npx netlify-cli dev --filter @atlast/web' to bypass monorepo\nproject selection prompt and specify which workspace package to run.\n\nDev server now runs successfully at http://localhost:8888 with all backend\nfunctions loaded.",
104
-
"files_changed": 4
104
+
"files_changed": 5
105
105
},
106
106
{
107
107
"hash": "c3e7afad396d130791d801a85cbfc9643bcd6309",
+88
docs/graph-data.json
+88
docs/graph-data.json
···
3486
3486
"created_at": "2025-12-26T20:20:22.507291300-05:00",
3487
3487
"updated_at": "2025-12-26T20:20:22.507291300-05:00",
3488
3488
"metadata_json": "{\"branch\":\"master\",\"confidence\":95}"
3489
+
},
3490
+
{
3491
+
"id": 318,
3492
+
"change_id": "371f788d-46df-4651-b338-f9310f8ae810",
3493
+
"node_type": "goal",
3494
+
"title": "Fix results not saving to database and timestamp timezone issue",
3495
+
"description": null,
3496
+
"status": "pending",
3497
+
"created_at": "2025-12-26T20:37:03.493239600-05:00",
3498
+
"updated_at": "2025-12-26T20:37:03.493239600-05:00",
3499
+
"metadata_json": "{\"branch\":\"master\",\"confidence\":90}"
3500
+
},
3501
+
{
3502
+
"id": 319,
3503
+
"change_id": "28681ed9-6d12-476e-a60d-291ee2034952",
3504
+
"node_type": "observation",
3505
+
"title": "save-results has hasRecentUpload check that skips saving if upload created within 5 seconds - extension-import creates upload then save-results is called immediately, gets skipped!",
3506
+
"description": null,
3507
+
"status": "pending",
3508
+
"created_at": "2025-12-26T20:37:34.735156200-05:00",
3509
+
"updated_at": "2025-12-26T20:37:34.735156200-05:00",
3510
+
"metadata_json": "{\"branch\":\"master\",\"confidence\":100}"
3511
+
},
3512
+
{
3513
+
"id": 320,
3514
+
"change_id": "04f6a182-c5a1-4844-b186-24605a8e74a9",
3515
+
"node_type": "action",
3516
+
"title": "Fix save-results to skip duplicate check for extension uploads and handle timestamps correctly",
3517
+
"description": null,
3518
+
"status": "pending",
3519
+
"created_at": "2025-12-26T20:38:45.703038700-05:00",
3520
+
"updated_at": "2025-12-26T20:38:45.703038700-05:00",
3521
+
"metadata_json": "{\"branch\":\"master\",\"confidence\":95}"
3522
+
},
3523
+
{
3524
+
"id": 321,
3525
+
"change_id": "ac843fbc-1953-4b61-8ef3-4c88c98572f5",
3526
+
"node_type": "outcome",
3527
+
"title": "Fixed save-results to check if upload exists by ID instead of recent time check - extension flow now saves matches",
3528
+
"description": null,
3529
+
"status": "pending",
3530
+
"created_at": "2025-12-26T20:39:45.657720100-05:00",
3531
+
"updated_at": "2025-12-26T20:39:45.657720100-05:00",
3532
+
"metadata_json": "{\"branch\":\"master\",\"confidence\":95}"
3489
3533
}
3490
3534
],
3491
3535
"edges": [
···
6876
6920
"weight": 1.0,
6877
6921
"rationale": "Goal achieved",
6878
6922
"created_at": "2025-12-26T20:20:26.885283800-05:00"
6923
+
},
6924
+
{
6925
+
"id": 309,
6926
+
"from_node_id": 317,
6927
+
"to_node_id": 318,
6928
+
"from_change_id": "3a24a4a2-b4d0-4629-a29b-b33994d50e75",
6929
+
"to_change_id": "371f788d-46df-4651-b338-f9310f8ae810",
6930
+
"edge_type": "leads_to",
6931
+
"weight": 1.0,
6932
+
"rationale": "New issues found",
6933
+
"created_at": "2025-12-26T20:37:06.303637800-05:00"
6934
+
},
6935
+
{
6936
+
"id": 310,
6937
+
"from_node_id": 318,
6938
+
"to_node_id": 319,
6939
+
"from_change_id": "371f788d-46df-4651-b338-f9310f8ae810",
6940
+
"to_change_id": "28681ed9-6d12-476e-a60d-291ee2034952",
6941
+
"edge_type": "leads_to",
6942
+
"weight": 1.0,
6943
+
"rationale": "Root cause found",
6944
+
"created_at": "2025-12-26T20:37:37.527168300-05:00"
6945
+
},
6946
+
{
6947
+
"id": 311,
6948
+
"from_node_id": 319,
6949
+
"to_node_id": 320,
6950
+
"from_change_id": "28681ed9-6d12-476e-a60d-291ee2034952",
6951
+
"to_change_id": "04f6a182-c5a1-4844-b186-24605a8e74a9",
6952
+
"edge_type": "leads_to",
6953
+
"weight": 1.0,
6954
+
"rationale": "Action to fix",
6955
+
"created_at": "2025-12-26T20:38:48.486046-05:00"
6956
+
},
6957
+
{
6958
+
"id": 312,
6959
+
"from_node_id": 320,
6960
+
"to_node_id": 321,
6961
+
"from_change_id": "04f6a182-c5a1-4844-b186-24605a8e74a9",
6962
+
"to_change_id": "ac843fbc-1953-4b61-8ef3-4c88c98572f5",
6963
+
"edge_type": "leads_to",
6964
+
"weight": 1.0,
6965
+
"rationale": "Implementation complete",
6966
+
"created_at": "2025-12-26T20:39:48.757903800-05:00"
6879
6967
}
6880
6968
]
6881
6969
}
+14
-16
packages/functions/src/save-results.ts
+14
-16
packages/functions/src/save-results.ts
···
66
66
const matchRepo = new MatchRepository();
67
67
let matchedCount = 0;
68
68
69
-
const hasRecent = await uploadRepo.hasRecentUpload(context.did);
70
-
if (hasRecent) {
71
-
console.log(
72
-
`User ${context.did} already saved within 5 seconds, skipping duplicate`,
69
+
// Check if this specific upload already exists
70
+
const existingUpload = await uploadRepo.getUpload(uploadId, context.did);
71
+
72
+
if (!existingUpload) {
73
+
// Upload doesn't exist - create it (file upload flow)
74
+
await uploadRepo.createUpload(
75
+
uploadId,
76
+
context.did,
77
+
sourcePlatform,
78
+
results.length,
79
+
0,
73
80
);
74
-
return successResponse({
75
-
success: true,
76
-
message: "Recently saved",
77
-
});
81
+
} else {
82
+
// Upload exists (extension flow) - just update it with matches
83
+
console.log(`[save-results] Updating existing upload ${uploadId} with matches`);
78
84
}
79
-
80
-
await uploadRepo.createUpload(
81
-
uploadId,
82
-
context.did,
83
-
sourcePlatform,
84
-
results.length,
85
-
0,
86
-
);
87
85
88
86
const allUsernames = results.map((r) => r.sourceUser.username);
89
87
const sourceAccountIdMap = await sourceAccountRepo.bulkCreate(