forkit-ai-footprints 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/LICENSE +21 -0
  2. package/PRIVACY.md +150 -0
  3. package/README.md +313 -0
  4. package/STATUS.md +136 -0
  5. package/dist/agents.d.ts +22 -0
  6. package/dist/agents.js +281 -0
  7. package/dist/aggregate.d.ts +28 -0
  8. package/dist/aggregate.js +151 -0
  9. package/dist/assets/forkit-icon-dark.png +0 -0
  10. package/dist/assets/forkit-icon-light.png +0 -0
  11. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Info.plist +5 -0
  12. package/dist/bootstrap/Forkit AI Footprint.app/Contents/MacOS/Forkit AI Footprint +0 -0
  13. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/ForkitAIFootprint.icns +0 -0
  14. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/ForkitStatusTemplate.png +0 -0
  15. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/agents.d.ts +22 -0
  16. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/agents.js +281 -0
  17. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/aggregate.d.ts +28 -0
  18. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/aggregate.js +151 -0
  19. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/assets/forkit-icon-dark.png +0 -0
  20. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/assets/forkit-icon-light.png +0 -0
  21. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/census.d.ts +3 -0
  22. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/census.js +196 -0
  23. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/cli.d.ts +32 -0
  24. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/cli.js +404 -0
  25. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/doctor.d.ts +14 -0
  26. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/doctor.js +71 -0
  27. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/endpoints.d.ts +8 -0
  28. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/endpoints.js +45 -0
  29. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/evaluate.d.ts +44 -0
  30. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/evaluate.js +102 -0
  31. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/filesystem.d.ts +11 -0
  32. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/filesystem.js +226 -0
  33. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/format.d.ts +7 -0
  34. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/format.js +78 -0
  35. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/hash.d.ts +4 -0
  36. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/hash.js +16 -0
  37. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/index.d.ts +22 -0
  38. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/index.js +58 -0
  39. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/insights.d.ts +13 -0
  40. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/insights.js +76 -0
  41. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/local-device.d.ts +19 -0
  42. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/local-device.js +81 -0
  43. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/locales.json +272 -0
  44. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/localization.d.ts +277 -0
  45. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/localization.js +55 -0
  46. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/mcp.d.ts +9 -0
  47. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/mcp.js +93 -0
  48. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/monitor.d.ts +99 -0
  49. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/monitor.js +285 -0
  50. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/base.d.ts +34 -0
  51. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/base.js +88 -0
  52. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/index.d.ts +6 -0
  53. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/index.js +24 -0
  54. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/lmstudio.d.ts +9 -0
  55. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/lmstudio.js +71 -0
  56. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/ollama.d.ts +12 -0
  57. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/ollama.js +171 -0
  58. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/openai-compatible.d.ts +10 -0
  59. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/openai-compatible.js +68 -0
  60. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/resource-evidence.d.ts +17 -0
  61. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/resource-evidence.js +52 -0
  62. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/runtime-activity.d.ts +5 -0
  63. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/runtime-activity.js +66 -0
  64. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/runtime-identity.d.ts +7 -0
  65. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/runtime-identity.js +66 -0
  66. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/server.d.ts +21 -0
  67. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/server.js +308 -0
  68. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/share-page.d.ts +75 -0
  69. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/share-page.js +167 -0
  70. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/sharing.d.ts +35 -0
  71. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/sharing.js +67 -0
  72. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/tools.d.ts +9 -0
  73. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/tools.js +106 -0
  74. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/types.d.ts +166 -0
  75. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/types.js +3 -0
  76. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/version.d.ts +4 -0
  77. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/version.js +13 -0
  78. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/index.d.ts +76 -0
  79. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/index.js +366 -0
  80. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/license +9 -0
  81. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/package.json +44 -0
  82. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/readme.md +56 -0
  83. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/vendor/fastlist-0.3.0-x64.exe +0 -0
  84. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/vendor/fastlist-0.3.0-x86.exe +0 -0
  85. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/package.json +6 -0
  86. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/runtime/node +0 -0
  87. package/dist/bootstrap/Forkit AI Footprint.app/Contents/_CodeSignature/CodeResources +931 -0
  88. package/dist/census.d.ts +3 -0
  89. package/dist/census.js +196 -0
  90. package/dist/cli.d.ts +32 -0
  91. package/dist/cli.js +404 -0
  92. package/dist/doctor.d.ts +14 -0
  93. package/dist/doctor.js +71 -0
  94. package/dist/endpoints.d.ts +8 -0
  95. package/dist/endpoints.js +45 -0
  96. package/dist/evaluate.d.ts +44 -0
  97. package/dist/evaluate.js +102 -0
  98. package/dist/filesystem.d.ts +11 -0
  99. package/dist/filesystem.js +226 -0
  100. package/dist/format.d.ts +7 -0
  101. package/dist/format.js +78 -0
  102. package/dist/hash.d.ts +4 -0
  103. package/dist/hash.js +16 -0
  104. package/dist/index.d.ts +22 -0
  105. package/dist/index.js +58 -0
  106. package/dist/insights.d.ts +13 -0
  107. package/dist/insights.js +76 -0
  108. package/dist/local-device.d.ts +19 -0
  109. package/dist/local-device.js +81 -0
  110. package/dist/locales.json +272 -0
  111. package/dist/localization.d.ts +277 -0
  112. package/dist/localization.js +55 -0
  113. package/dist/mcp.d.ts +9 -0
  114. package/dist/mcp.js +93 -0
  115. package/dist/monitor.d.ts +99 -0
  116. package/dist/monitor.js +285 -0
  117. package/dist/providers/base.d.ts +34 -0
  118. package/dist/providers/base.js +88 -0
  119. package/dist/providers/index.d.ts +6 -0
  120. package/dist/providers/index.js +24 -0
  121. package/dist/providers/lmstudio.d.ts +9 -0
  122. package/dist/providers/lmstudio.js +71 -0
  123. package/dist/providers/ollama.d.ts +12 -0
  124. package/dist/providers/ollama.js +171 -0
  125. package/dist/providers/openai-compatible.d.ts +10 -0
  126. package/dist/providers/openai-compatible.js +68 -0
  127. package/dist/resource-evidence.d.ts +17 -0
  128. package/dist/resource-evidence.js +52 -0
  129. package/dist/runtime-activity.d.ts +5 -0
  130. package/dist/runtime-activity.js +66 -0
  131. package/dist/runtime-identity.d.ts +7 -0
  132. package/dist/runtime-identity.js +66 -0
  133. package/dist/server.d.ts +21 -0
  134. package/dist/server.js +308 -0
  135. package/dist/share-page.d.ts +75 -0
  136. package/dist/share-page.js +167 -0
  137. package/dist/sharing.d.ts +35 -0
  138. package/dist/sharing.js +67 -0
  139. package/dist/tools.d.ts +9 -0
  140. package/dist/tools.js +106 -0
  141. package/dist/types.d.ts +166 -0
  142. package/dist/types.js +3 -0
  143. package/dist/version.d.ts +4 -0
  144. package/dist/version.js +13 -0
  145. package/docs/GLOBAL_DISTRIBUTION.md +79 -0
  146. package/docs/MACOS_ACCURACY_GATE.md +140 -0
  147. package/docs/MACOS_TESTER_GUIDE.md +88 -0
  148. package/examples/macos-truth.template.json +10 -0
  149. package/package.json +75 -0
  150. package/release/channels.json +41 -0
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MINIMUM_COMPARISON_SECONDS = void 0;
4
+ exports.buildAnonymousAiFootprintPreview = buildAnonymousAiFootprintPreview;
5
+ exports.authorizeAnonymousAiFootprintContribution = authorizeAnonymousAiFootprintContribution;
6
+ const node_child_process_1 = require("node:child_process");
7
+ exports.MINIMUM_COMPARISON_SECONDS = 600;
8
+ function macosMajorVersion() {
9
+ try {
10
+ const productVersion = (0, node_child_process_1.execFileSync)('/usr/bin/sw_vers', ['-productVersion'], {
11
+ encoding: 'utf8',
12
+ timeout: 2_000,
13
+ stdio: ['ignore', 'pipe', 'ignore'],
14
+ }).trim();
15
+ const major = Number(productVersion.split('.')[0]);
16
+ return Number.isInteger(major) && major > 0 ? major : 0;
17
+ }
18
+ catch {
19
+ return 0;
20
+ }
21
+ }
22
+ function buildAnonymousAiFootprintPreview(report, monitor, options = {}) {
23
+ if (report.system.platform !== 'darwin')
24
+ throw new Error('ANONYMOUS_FOOTPRINT_MACOS_REQUIRED');
25
+ if (!report.summary.storage_complete)
26
+ throw new Error('ANONYMOUS_FOOTPRINT_STORAGE_INCOMPLETE');
27
+ if (monitor.observed_seconds < exports.MINIMUM_COMPARISON_SECONDS)
28
+ throw new Error('ANONYMOUS_FOOTPRINT_MINIMUM_OBSERVATION_REQUIRED');
29
+ if (monitor.active_seconds < 0 || monitor.active_seconds > monitor.observed_seconds)
30
+ throw new Error('ANONYMOUS_FOOTPRINT_INVALID_ACTIVITY_DURATION');
31
+ const validSeconds = Math.floor(monitor.observed_seconds);
32
+ const activeSeconds = Math.min(validSeconds, Math.floor(monitor.active_seconds));
33
+ const workingProducts = monitor.products.filter((product) => product.active_seconds > 0);
34
+ return {
35
+ schema_version: '2.0',
36
+ observation: {
37
+ valid_seconds: validSeconds,
38
+ ai_active_seconds: activeSeconds,
39
+ activity_ratio: validSeconds === 0 ? 0 : Math.round((activeSeconds / validSeconds) * 1000) / 1000,
40
+ },
41
+ counts: {
42
+ supported_apps_observed_working: workingProducts.length,
43
+ supported_app_categories: [...new Set(workingProducts.map((product) => product.kind))].sort(),
44
+ local_models_discovered: report.summary.model_count,
45
+ local_models_loaded: report.summary.confirmed_running_model_count,
46
+ verified_local_runtimes_available: report.summary.available_runtime_count,
47
+ },
48
+ model_storage_bytes: report.summary.storage_bytes,
49
+ system: {
50
+ platform: 'darwin',
51
+ architecture: report.system.architecture,
52
+ os_major: options.osMajor ?? macosMajorVersion(),
53
+ },
54
+ versions: {
55
+ scanner: report.product_version,
56
+ node_major: report.system.node_major,
57
+ monitor_schema: monitor.schema_version,
58
+ },
59
+ };
60
+ }
61
+ /** Consent is separate from local preview construction. This never uploads. */
62
+ function authorizeAnonymousAiFootprintContribution(payload, consent) {
63
+ if (!consent)
64
+ throw new Error('ANONYMOUS_FOOTPRINT_CONSENT_REQUIRED');
65
+ return payload;
66
+ }
67
+ //# sourceMappingURL=sharing.js.map
@@ -0,0 +1,9 @@
1
+ import type { CensusAgent, CensusTool } from './types';
2
+ export interface ToolDetectionOptions {
3
+ homeDir: string;
4
+ env: NodeJS.ProcessEnv;
5
+ platform: NodeJS.Platform;
6
+ agents: CensusAgent[];
7
+ }
8
+ export declare function detectAiTools(options: ToolDetectionOptions): Promise<CensusTool[]>;
9
+ //# sourceMappingURL=tools.d.ts.map
package/dist/tools.js ADDED
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.detectAiTools = detectAiTools;
7
+ const promises_1 = __importDefault(require("node:fs/promises"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const hash_1 = require("./hash");
10
+ async function exists(targetPath) {
11
+ try {
12
+ await promises_1.default.access(targetPath);
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ function executableCandidates(command, platform, env) {
20
+ if (platform !== 'win32')
21
+ return [command];
22
+ const extensions = String(env.PATHEXT || '.EXE;.CMD;.BAT')
23
+ .split(';')
24
+ .map((entry) => entry.trim().toLowerCase())
25
+ .filter(Boolean);
26
+ return [command, ...extensions.map((extension) => `${command}${extension}`)];
27
+ }
28
+ async function commandExists(command, platform, env) {
29
+ const directories = String(env.PATH || env.Path || env.path || '')
30
+ .split(node_path_1.default.delimiter)
31
+ .filter(Boolean)
32
+ .slice(0, 256);
33
+ const candidates = executableCandidates(command, platform, env);
34
+ for (const directory of directories) {
35
+ for (const candidate of candidates) {
36
+ if (await exists(node_path_1.default.join(directory, candidate)))
37
+ return true;
38
+ }
39
+ }
40
+ return false;
41
+ }
42
+ function definitions(homeDir) {
43
+ return [
44
+ { name: 'Claude Code', signatures: ['claude'], commands: ['claude'], configPaths: [node_path_1.default.join(homeDir, '.claude')] },
45
+ { name: 'Codex', signatures: ['codex'], commands: ['codex'], configPaths: [node_path_1.default.join(homeDir, '.codex')], appPaths: ['/Applications/Codex.app', node_path_1.default.join(homeDir, 'Applications', 'Codex.app')] },
46
+ { name: 'Cursor', signatures: ['cursor'], commands: ['cursor'], configPaths: [node_path_1.default.join(homeDir, '.cursor')], appPaths: ['/Applications/Cursor.app', node_path_1.default.join(homeDir, 'Applications', 'Cursor.app')] },
47
+ { name: 'Windsurf', signatures: ['windsurf'], commands: ['windsurf'], configPaths: [node_path_1.default.join(homeDir, '.codeium', 'windsurf')], appPaths: ['/Applications/Windsurf.app', node_path_1.default.join(homeDir, 'Applications', 'Windsurf.app')] },
48
+ { name: 'Gemini CLI', signatures: ['gemini-cli'], commands: ['gemini'], configPaths: [node_path_1.default.join(homeDir, '.gemini')] },
49
+ { name: 'GitHub Copilot', signatures: ['github-copilot'], commands: [], configPaths: [] },
50
+ { name: 'OpenCode', signatures: ['opencode'], commands: ['opencode'], configPaths: [node_path_1.default.join(homeDir, '.config', 'opencode')] },
51
+ { name: 'OpenClaw', signatures: ['openclaw'], commands: ['openclaw'], configPaths: [node_path_1.default.join(homeDir, '.openclaw')] },
52
+ { name: 'Jan', signatures: [], commands: ['jan'], configPaths: [node_path_1.default.join(homeDir, 'Library', 'Application Support', 'Jan')], appPaths: ['/Applications/Jan.app', node_path_1.default.join(homeDir, 'Applications', 'Jan.app')] },
53
+ { name: 'LM Studio', signatures: [], commands: ['lms'], configPaths: [node_path_1.default.join(homeDir, '.lmstudio')], appPaths: ['/Applications/LM Studio.app', node_path_1.default.join(homeDir, 'Applications', 'LM Studio.app')] },
54
+ { name: 'Zed', signatures: [], commands: ['zed'], configPaths: [node_path_1.default.join(homeDir, '.zed')], appPaths: ['/Applications/Zed.app', node_path_1.default.join(homeDir, 'Applications', 'Zed.app')] },
55
+ ];
56
+ }
57
+ async function hasCopilotExtension(homeDir) {
58
+ const roots = [
59
+ node_path_1.default.join(homeDir, '.vscode', 'extensions'),
60
+ node_path_1.default.join(homeDir, '.vscode-insiders', 'extensions'),
61
+ ];
62
+ for (const root of roots) {
63
+ try {
64
+ const names = await promises_1.default.readdir(root);
65
+ if (names.some((name) => /^github\.copilot(?:-chat)?(?:-|$)/i.test(name)))
66
+ return true;
67
+ }
68
+ catch {
69
+ // Missing or unreadable extension roots are normal.
70
+ }
71
+ }
72
+ return false;
73
+ }
74
+ async function detectAiTools(options) {
75
+ const tools = [];
76
+ for (const definition of definitions(options.homeDir)) {
77
+ const detectorTypes = new Set();
78
+ const matchingAgents = options.agents.filter((agent) => definition.signatures.includes(agent.signature));
79
+ if (matchingAgents.length > 0)
80
+ detectorTypes.add('process');
81
+ const commandInstalled = (await Promise.all(definition.commands.map((command) => commandExists(command, options.platform, options.env)))).some(Boolean);
82
+ const appInstalled = options.platform === 'darwin'
83
+ && (await Promise.all((definition.appPaths ?? []).map((targetPath) => exists(targetPath)))).some(Boolean);
84
+ if (commandInstalled || appInstalled) {
85
+ detectorTypes.add('executable');
86
+ }
87
+ const configured = definition.name === 'GitHub Copilot'
88
+ ? await hasCopilotExtension(options.homeDir)
89
+ : (await Promise.all(definition.configPaths.map((targetPath) => exists(targetPath)))).some(Boolean);
90
+ if (configured)
91
+ detectorTypes.add('config');
92
+ if (detectorTypes.size === 0)
93
+ continue;
94
+ const instanceCount = matchingAgents.reduce((total, agent) => total + agent.instance_count, 0);
95
+ tools.push({
96
+ tool_id: (0, hash_1.stableId)('tool', definition.name),
97
+ name: definition.name,
98
+ evidence_status: detectorTypes.has('process') ? 'online' : 'configured',
99
+ confidence: detectorTypes.has('process') || detectorTypes.size >= 2 ? 'high' : 'medium',
100
+ detector_types: [...detectorTypes].sort(),
101
+ instance_count: instanceCount,
102
+ });
103
+ }
104
+ return tools.sort((left, right) => left.name.localeCompare(right.name));
105
+ }
106
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1,166 @@
1
+ export type Confidence = 'high' | 'medium' | 'low';
2
+ export type EvidenceStatus = 'discovered' | 'configured' | 'online' | 'confirmed-running';
3
+ export type RuntimeKind = 'ollama' | 'lmstudio' | 'openai-compatible' | 'filesystem';
4
+ export type RuntimeStatus = 'available' | 'unavailable' | 'inventory-only';
5
+ export interface CensusRuntime {
6
+ runtime_id: string;
7
+ name: RuntimeKind;
8
+ status: RuntimeStatus;
9
+ endpoint: string | null;
10
+ model_count: number;
11
+ observed_at: string;
12
+ error_code: string | null;
13
+ evidence_status: 'configured' | 'online' | 'unavailable';
14
+ }
15
+ export interface CensusModel {
16
+ model_id: string;
17
+ name: string;
18
+ runtime: RuntimeKind;
19
+ identity_kind: 'content-sha256' | 'provider-id' | 'metadata-sha256';
20
+ identity: string;
21
+ size_bytes: number | null;
22
+ modified_at: string | null;
23
+ quantization: string | null;
24
+ architecture: string | null;
25
+ parameter_size: string | null;
26
+ source: 'runtime-api' | 'filesystem';
27
+ location_hint: string | null;
28
+ confidence: Confidence;
29
+ evidence_status: 'discovered' | 'confirmed-running';
30
+ }
31
+ export type AgentKind = 'coding-agent' | 'ide-agent' | 'agent-framework' | 'mcp-server';
32
+ export interface CensusAgent {
33
+ agent_id: string;
34
+ name: string;
35
+ signature: string;
36
+ kind: AgentKind;
37
+ confidence: Confidence;
38
+ instance_count: number;
39
+ executable_names: string[];
40
+ evidence_hashes: string[];
41
+ detection_reason: string;
42
+ evidence_status: 'online';
43
+ resource_snapshot: {
44
+ cpu_percent: number | null;
45
+ memory_percent: number | null;
46
+ measurement: 'point-in-time-process-metadata';
47
+ };
48
+ }
49
+ export interface CensusTool {
50
+ tool_id: string;
51
+ name: string;
52
+ evidence_status: 'configured' | 'online';
53
+ confidence: Confidence;
54
+ detector_types: Array<'config' | 'executable' | 'process'>;
55
+ instance_count: number;
56
+ }
57
+ export interface CensusMcpConfig {
58
+ client: string;
59
+ evidence_status: 'configured';
60
+ confidence: Confidence;
61
+ server_count: number;
62
+ }
63
+ export interface CensusWarning {
64
+ code: string;
65
+ message: string;
66
+ scope: 'runtime' | 'model' | 'agent' | 'privacy' | 'system';
67
+ }
68
+ export interface CensusSummary {
69
+ runtime_count: number;
70
+ available_runtime_count: number;
71
+ model_count: number;
72
+ agent_product_count: number;
73
+ agent_process_count: number;
74
+ agent_cpu_percent: number | null;
75
+ agent_memory_percent: number | null;
76
+ tool_count: number;
77
+ mcp_config_count: number;
78
+ confirmed_running_model_count: number;
79
+ storage_bytes: number;
80
+ storage_file_count: number;
81
+ storage_complete: boolean;
82
+ storage_measurement: 'recognized-logical-file-bytes';
83
+ warning_count: number;
84
+ }
85
+ export interface CensusReport {
86
+ schema_version: '1.3';
87
+ product: 'forkit-ai-footprints';
88
+ product_version: string;
89
+ census_id: string;
90
+ generated_at: string;
91
+ system: {
92
+ platform: NodeJS.Platform;
93
+ architecture: string;
94
+ node_major: number;
95
+ };
96
+ privacy: {
97
+ mode: 'metadata-only';
98
+ raw_commands_retained: false;
99
+ model_file_contents_read: false;
100
+ config_values_emitted: false;
101
+ sensitive_content_retained: false;
102
+ remote_endpoints_allowed: false;
103
+ external_requests_made: 0;
104
+ backend_contacted: false;
105
+ account_read: false;
106
+ local_state_written: boolean;
107
+ local_state_scope: 'none' | 'device-journal-only';
108
+ };
109
+ summary: CensusSummary;
110
+ runtimes: CensusRuntime[];
111
+ models: CensusModel[];
112
+ agents: CensusAgent[];
113
+ tools: CensusTool[];
114
+ mcp_configs: CensusMcpConfig[];
115
+ guess: {
116
+ provided: number | null;
117
+ discovered: number;
118
+ difference: number | null;
119
+ };
120
+ warnings: CensusWarning[];
121
+ }
122
+ export interface RuntimeScanResult {
123
+ runtime: CensusRuntime;
124
+ models: CensusModel[];
125
+ warnings: CensusWarning[];
126
+ storage?: {
127
+ logical_bytes: number;
128
+ recognized_file_count: number;
129
+ complete: boolean;
130
+ measurement: 'recognized-logical-file-bytes';
131
+ };
132
+ }
133
+ export interface RuntimeProvider {
134
+ readonly name: RuntimeKind;
135
+ scan(observedAt: string): Promise<RuntimeScanResult>;
136
+ }
137
+ export interface ProcessEntry {
138
+ pid: number;
139
+ ppid?: number;
140
+ name?: string;
141
+ cmd?: string;
142
+ cpu_percent?: number;
143
+ memory_percent?: number;
144
+ /** Internal resident memory from the operating system. Never emitted in a Census report. */
145
+ rss_bytes?: number;
146
+ /** Internal cumulative process CPU time. Never emitted in a Census report. */
147
+ cpu_time_ms?: number;
148
+ }
149
+ export interface CensusOptions {
150
+ includeRuntimes?: boolean;
151
+ includeFilesystem?: boolean;
152
+ includeAgents?: boolean;
153
+ includeTools?: boolean;
154
+ includeMcp?: boolean;
155
+ filesystemRoots?: string[];
156
+ processEntries?: ProcessEntry[];
157
+ providers?: RuntimeProvider[];
158
+ now?: () => Date;
159
+ guess?: number | null;
160
+ homeDir?: string;
161
+ cwd?: string;
162
+ env?: NodeJS.ProcessEnv;
163
+ platform?: NodeJS.Platform;
164
+ architecture?: string;
165
+ }
166
+ //# sourceMappingURL=types.d.ts.map
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,4 @@
1
+ export declare const PRODUCT_NAME: "forkit-ai-footprints";
2
+ export declare const PRODUCT_VERSION: string;
3
+ export declare const SCHEMA_VERSION: "1.3";
4
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SCHEMA_VERSION = exports.PRODUCT_VERSION = exports.PRODUCT_NAME = void 0;
7
+ exports.PRODUCT_NAME = 'forkit-ai-footprints';
8
+ const package_json_1 = __importDefault(require("../package.json"));
9
+ // package.json is the only product-version source. npm, the CLI, native
10
+ // bundles, GitHub release tags, and package-manager metadata must derive from it.
11
+ exports.PRODUCT_VERSION = package_json_1.default.version;
12
+ exports.SCHEMA_VERSION = '1.3';
13
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1,79 @@
1
+ # Forkit AI Footprints global distribution
2
+
3
+ Status: v0.2.0 npm-first Apple Silicon macOS release approved.
4
+
5
+ ## Goal
6
+
7
+ Offer a free, professional installation path to Mac users anywhere in the
8
+ world, while ensuring npm, Homebrew, GitHub Releases, the future Mac installer,
9
+ and the website can never silently recommend different product versions.
10
+
11
+ ## One release identity
12
+
13
+ `package.json` is the only version source. The CLI imports it at build time and
14
+ the native Mac package builder reads it directly. `npm run release:check`
15
+ rejects a different lockfile version, CLI version source, native package version,
16
+ or documented status version.
17
+
18
+ `npm run release:manifest` generates the candidate release manifest under
19
+ `artifacts/release/`. The generated manifest is metadata only; generating it
20
+ does not publish anything.
21
+
22
+ ## Global channels
23
+
24
+ | Channel | Audience | Cost to users | Current state |
25
+ |---|---|---:|---|
26
+ | GitHub Release | canonical immutable source/release identity | Free | v0.2.0 release |
27
+ | npm public registry | primary Apple Silicon bootstrap; installs a persistent app in `~/Applications` | Free | v0.2.0 |
28
+ | Homebrew tap | optional future package-manager channel | Free | Tap not created |
29
+ | Signed `.pkg` | future click installation | Free to users | Blocked on paid Apple identity and notarization |
30
+
31
+ Homebrew and npm are not tied to the founder's Mac. They are global registries.
32
+ The npm command is a one-time bootstrap: it copies a self-contained GUI app into
33
+ the current user's Applications folder and opens it. Later use is through
34
+ Applications, Spotlight, Dock, or the Forkit menu-bar icon without Terminal.
35
+ The current product support claim is still macOS on Apple Silicon until broader
36
+ field validation exists.
37
+
38
+ ## Release order
39
+
40
+ 1. Bump `package.json` and `package-lock.json` together.
41
+ 2. Run tests, package smoke, real-Mac validation, and `npm run release:check`.
42
+ 3. Build the npm tarball and candidate release manifest on a clean hosted runner.
43
+ 4. Create one draft GitHub Release for `v<version>` and attach the tarball,
44
+ manifest, checksum, SBOM, and provenance evidence.
45
+ 5. After founder approval, publish the exact tested package. A brand-new npm
46
+ package requires one interactive first publication before its trusted
47
+ publisher can be configured; all later releases use GitHub Actions OIDC.
48
+ 6. Update the Homebrew tap from the immutable release URL and SHA-256.
49
+ 7. Mark a channel `available` in the release manifest only after its registry
50
+ resolves to the same version and checksum.
51
+ 8. Let Forkit.dev read the verified manifest and recommend the simplest
52
+ available channel. If coherence fails, the website must show no install CTA.
53
+
54
+ The release automation should run only for an approved release tag or a manual
55
+ release action—not for normal commits—so it does not waste GitHub Actions runs.
56
+
57
+ ## Hugging Face cache boundary
58
+
59
+ AI Footprints supports the official Hub file cache at
60
+ `~/.cache/huggingface/hub`, `$HF_HOME/hub`, `$HF_HUB_CACHE`, and the
61
+ XDG-configured equivalent. It recognizes `models--<org>--<repo>` directories
62
+ and follows snapshot links while deduplicating the same physical blob across
63
+ revisions.
64
+
65
+ `HF_XET_CACHE` is deliberately excluded. It contains transport chunks that can
66
+ be shared across files and would double-count model storage. Datasets, Spaces,
67
+ assets, incomplete downloads, and unreferenced extensionless blobs are also not
68
+ reported as model storage. The reported value is therefore exact for recognized
69
+ model artifacts inside supported roots, not the total size of every Hugging
70
+ Face cache directory.
71
+
72
+ ## Brand assets
73
+
74
+ The website's `/brand/icon-dark.svg` and `/brand/icon-light.svg` are byte-for-byte
75
+ copies of the supplied `Logo_Forkit/logo_Only/color_Dark/color_Dark.svg` and
76
+ `Logo_Forkit/logo_Only/color_Light/color_Light.svg`. The dark-outline mark is for
77
+ light surfaces; the light-outline mark is for dark surfaces. The product name
78
+ remains live text so the older “Forkit Dev” wordmark is not incorrectly presented
79
+ as the AI Footprints product name.
@@ -0,0 +1,140 @@
1
+ # macOS Accuracy and Release Gate
2
+
3
+ Forkit AI Footprints must not claim a global accuracy percentage or broaden its
4
+ platform support until this gate is reviewed. Passing local tests is necessary
5
+ but is not field accuracy.
6
+
7
+ ## Current supported claim
8
+
9
+ - operating system: macOS only;
10
+ - current real-device evidence: one Apple Silicon Mac;
11
+ - Intel Mac: not yet field validated;
12
+ - distribution: public npm bootstrap for Apple Silicon macOS;
13
+ - network: loopback runtime APIs only, with no uploader or Forkit.dev client.
14
+
15
+ ## Evidence classes
16
+
17
+ - `online`: a supported runtime API responded, or a running agent has exact
18
+ executable, explicit module, or explicit package-runner evidence;
19
+ - `configured`: installation/configuration metadata exists, without claiming a
20
+ process is active;
21
+ - `confirmed-running`: Ollama `/api/ps` reported the model as loaded;
22
+ - `discovered`: inventory evidence exists without proof of active execution.
23
+
24
+ Filesystem findings remain best-effort and low confidence. Process instance
25
+ counts are not independent-agent or user-session counts.
26
+
27
+ ## Local labelled evaluation
28
+
29
+ Each tester creates a local JSON truth file after manually checking their Mac:
30
+
31
+ ```json
32
+ {
33
+ "schema_version": "1.0",
34
+ "expected": {
35
+ "agent_signatures": ["codex"],
36
+ "tool_names": ["Codex"],
37
+ "online_runtime_names": ["ollama"],
38
+ "model_keys": ["ollama:example-model:latest"],
39
+ "mcp_clients": ["Codex"]
40
+ }
41
+ }
42
+ ```
43
+
44
+ Run:
45
+
46
+ ```bash
47
+ npm run evaluate:macos -- /absolute/path/to/local-truth.json
48
+ ```
49
+
50
+ Testers using the packed or installed CLI run the equivalent public command:
51
+
52
+ ```bash
53
+ forkit-census evaluate --truth /absolute/path/to/local-truth.json
54
+ ```
55
+
56
+ The result contains aggregate counts and metrics only. It does not contain the
57
+ truth-file item names and is not uploaded.
58
+
59
+ Each tester reviews the result and may then explicitly share that result file,
60
+ but never the truth file. The coordinator aggregates a directory of reviewed
61
+ results locally:
62
+
63
+ ```bash
64
+ forkit-census aggregate --results /absolute/path/to/macos-field-results
65
+ ```
66
+
67
+ The aggregate reports CPU, macOS-major, and Node-major coverage plus Wilson 95%
68
+ confidence intervals. It cannot enable an accuracy claim automatically. The
69
+ coordinator must separately verify one submission per independently labelled
70
+ Mac because the privacy-preserving output contains no persistent device ID.
71
+ Different Census versions must not be pooled.
72
+
73
+ The evaluator emits aggregate counts and per-surface precision/recall locally.
74
+ It does not emit item names, raw commands, full paths, credentials, or upload
75
+ anything. Truth files must not be committed because model names can be private.
76
+
77
+ ## Public-release minimums
78
+
79
+ 1. At least 100 manually labelled Macs across the latest three supported macOS
80
+ major releases and representative Apple Silicon generations.
81
+ 2. Intel Mac must remain explicitly unsupported unless separately represented
82
+ and passing.
83
+ 3. At least 300 confirmed/online positive findings with no unreviewed false
84
+ positive if a 99% precision claim is planned. Report a 95% confidence
85
+ interval, not only the point estimate.
86
+ 4. The lower 95% confidence bound for confirmed/online precision must be at
87
+ least 99% per surface that uses that claim.
88
+ 5. The lower 95% confidence bound for recall within the declared supported
89
+ catalog must be at least 90% per surface.
90
+ 6. Zero external scan requests, zero sensitive report leaks, and zero registry,
91
+ Passport, Mint, Runtime_C2, or production writes.
92
+ 7. Repeated unchanged-device item sets must be at least 99% stable; time and
93
+ process-instance counts are excluded from this comparison.
94
+ 8. Package install, tests, doctor, and isolated tarball smoke must pass on Node
95
+ 20, 22, and 24 on hosted macOS runners and on real Macs.
96
+
97
+ The tarball smoke is a separate release gate and must run before `npm publish`;
98
+ it is intentionally not nested inside npm's publication lifecycle.
99
+
100
+ These are release gates, not current achievements. No public accuracy claim is
101
+ allowed until an independently reviewed aggregate evaluation satisfies them.
102
+
103
+ ## Accuracy interpretation
104
+
105
+ Different numbers have different meanings; there is no honest single accuracy
106
+ percentage for the whole product.
107
+
108
+ - **Known agents/tools:** the curated process corpus is a conformance test, not
109
+ field prevalence. The release target is a lower 95% precision bound of 99%
110
+ and a lower 95% supported-catalog recall bound of 90% after the field minimum.
111
+ - **Supported runtimes and loaded models:** a successful loopback API response
112
+ is strong current-state evidence. Unsupported/custom runtimes remain outside
113
+ recall and must not be described as absent AI.
114
+ - **Model inventory:** file metadata and runtime records are exact for evidence
115
+ the scanner recognizes, but total recall across every possible model format
116
+ and directory is unknown until representative field labelling.
117
+ - **Model storage:** the byte sum is exact for recognized files whose metadata
118
+ can be read. It is not total AI disk use when a format or location is outside
119
+ the supported catalog.
120
+ - **Agent CPU/memory:** the values are operating-system samples for strongly
121
+ detected processes. They are not exclusive task attribution and receive no
122
+ per-task accuracy percentage in this release.
123
+ - **Verified global installations:** App Attest plus replay/risk controls can
124
+ strongly establish a genuine supported app installation, but this is an
125
+ integrity result rather than detector precision. It cannot prove that every
126
+ local artifact is meaningful or prevent all deliberate local environment
127
+ manipulation.
128
+
129
+ The practical public target is therefore **≥99% precision and ≥90% recall
130
+ within the explicitly supported catalog**, with Wilson lower bounds satisfying
131
+ the release rules above. The current evidence does not yet authorize those
132
+ figures as achieved accuracy.
133
+
134
+ ## Controlled CI is not field evidence
135
+
136
+ The labelled compatibility workflow may run tests and privacy/stability checks
137
+ on GitHub-hosted Apple Silicon and Intel macOS runners. Those machines improve
138
+ OS and architecture compatibility evidence, but they do not contain a human's
139
+ independently established inventory truth and must never be counted toward the
140
+ 100-Mac field minimum.