rea-agents 1.7.0 → 2.0.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.
- package/README.md +38 -31
- package/dist/application/CapabilityInventory.js +18 -0
- package/dist/application/CrossVersionInvestigation.js +10 -6
- package/dist/application/Doctor.js +56 -6
- package/dist/application/ElectronBoundaryAnalysis.js +96 -0
- package/dist/application/ElectronBoundaryGraph.js +9 -0
- package/dist/application/ElectronBoundaryGraphContext.js +62 -0
- package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
- package/dist/application/ElectronBoundaryGraphNative.js +86 -0
- package/dist/application/ElectronBoundaryGraphWindows.js +199 -0
- package/dist/application/EnhancedTools.js +38 -13
- package/dist/application/InvestigationProviders.js +30 -0
- package/dist/application/JavaScriptApplicationEvidence.js +26 -0
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
- package/dist/application/JavaScriptApplicationService.js +74 -0
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
- package/dist/application/JavaScriptArtifactAnalysis.js +7 -1
- package/dist/application/JavaScriptArtifactGraphBuilder.js +59 -16
- package/dist/application/JavaScriptArtifactGraphEvidence.js +24 -14
- package/dist/application/JavaScriptArtifactReconstruction.js +3 -0
- package/dist/application/JavaScriptArtifactReconstructionInput.js +2 -83
- package/dist/application/JavaScriptReplayPlanning.js +201 -0
- package/dist/application/JavaScriptReplayService.js +266 -0
- package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
- package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
- package/dist/application/ManagedApplicationGraphService.js +55 -0
- package/dist/application/ManagedMemberComparisonService.js +122 -0
- package/dist/application/ManagedNativeVerificationService.js +39 -0
- package/dist/application/ManagedReconstructionService.js +58 -0
- package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
- package/dist/application/PermissionAuthority.js +1 -1
- package/dist/application/ProcessSampling.js +15 -11
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/runtime.js +2 -0
- package/dist/browser/CdpCaptureEvents.js +49 -0
- package/dist/browser/CdpElectronInspection.js +106 -162
- package/dist/browser/CdpElectronProvider.js +5 -1
- package/dist/browser/CdpElectronScriptEvents.js +69 -0
- package/dist/browser/CdpElectronScripts.js +94 -0
- package/dist/browser/CdpElectronWorkers.js +56 -0
- package/dist/browser/CdpPageCapture.js +8 -4
- package/dist/catalogIdentity.js +4 -1
- package/dist/cli.js +388 -0
- package/dist/cliApplicationCommands.js +62 -0
- package/dist/cliCommandNames.js +13 -0
- package/dist/cliElectronCommands.js +103 -1
- package/dist/cliJsonInput.js +54 -0
- package/dist/config.js +83 -0
- package/dist/contracts/applicationToolContracts.js +91 -0
- package/dist/contracts/artifactToolContracts.js +5 -9
- package/dist/contracts/browserToolContracts.js +14 -62
- package/dist/contracts/electronToolContracts.js +45 -19
- package/dist/contracts/errorSchemas.js +1 -0
- package/dist/contracts/investigationExamples.js +0 -6
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
- package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
- package/dist/contracts/managedToolContracts.js +153 -0
- package/dist/contracts/managedWorkflowExamples.js +346 -0
- package/dist/contracts/managedWorkflowToolContracts.js +203 -0
- package/dist/contracts/nativeToolContracts.js +2 -6
- package/dist/contracts/promptContracts.js +18 -2
- package/dist/contracts/toolContractExamples.js +10 -25
- package/dist/contracts/toolContracts.js +47 -45
- package/dist/contracts/toolEffects.js +160 -0
- package/dist/contracts/toolOutputSchemas.js +46 -31
- package/dist/doctorRuntime.js +42 -1
- package/dist/domain/artifactComparison.js +3 -4
- package/dist/domain/browserObservation.js +3 -0
- package/dist/domain/bundleComparison.js +4 -4
- package/dist/domain/electronObservation.js +13 -0
- package/dist/domain/electronStaticAnalysis.js +9 -0
- package/dist/domain/electronStaticAnalysisBrowser.js +194 -0
- package/dist/domain/electronStaticAnalysisIpc.js +171 -0
- package/dist/domain/electronStaticAnalysisNative.js +164 -0
- package/dist/domain/electronStaticAnalysisTypes.js +1 -0
- package/dist/domain/electronStaticAnalysisValues.js +103 -0
- package/dist/domain/errors.js +67 -1
- package/dist/domain/functionComparisonSchemas.js +3 -8
- package/dist/domain/inputIssueProjection.js +52 -0
- package/dist/domain/javascriptApplicationAnalysis.js +155 -0
- package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +18 -0
- package/dist/domain/javascriptApplicationGraph.js +2 -1
- package/dist/domain/javascriptApplicationGraphSchemas.js +7 -0
- package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionItems.js +221 -0
- package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
- package/dist/domain/javascriptFeatureSeed.js +140 -0
- package/dist/domain/javascriptFeatureTrace.js +232 -0
- package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
- package/dist/domain/javascriptFeatureTraversal.js +88 -0
- package/dist/domain/javascriptNativeHandoff.js +85 -0
- package/dist/domain/javascriptReplay.js +361 -0
- package/dist/domain/javascriptRuntimeLoadState.js +106 -0
- package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
- package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
- package/dist/domain/javascriptRuntimeStaticCandidates.js +191 -0
- package/dist/domain/javascriptStaticAnalysis.js +31 -43
- package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
- package/dist/domain/javascriptStaticAnalysisHelpers.js +10 -0
- package/dist/domain/javascriptStaticAnalysisState.js +6 -0
- package/dist/domain/managedApplicationGraph.js +556 -0
- package/dist/domain/managedArtifact.js +444 -0
- package/dist/domain/managedMemberComparison.js +565 -0
- package/dist/domain/managedNativeVerification.js +408 -0
- package/dist/domain/managedReconstruction.js +183 -0
- package/dist/domain/managedRuntimeCorrelation.js +175 -0
- package/dist/domain/reconstructionVerificationSchemas.js +1 -3
- package/dist/dotnet/ManagedArtifactInspector.js +318 -0
- package/dist/dotnet/ManagedMemberInspector.js +887 -0
- package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
- package/dist/dotnet/ManagedMetadataInventory.js +368 -0
- package/dist/dotnet/ManagedMetadataLayout.js +322 -0
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +391 -0
- package/dist/dotnet/ManagedPeReader.js +157 -0
- package/dist/dotnet/ManagedReaderFailure.js +10 -0
- package/dist/dotnet/ManagedStaticProvider.js +203 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraProvider.js +6 -0
- package/dist/main.js +14 -0
- package/dist/replay/JavaScriptReplayWorker.js +286 -0
- package/dist/replay/LinuxJavaScriptReplayRunner.js +434 -0
- package/dist/replay/LinuxRuntimeClosure.js +46 -0
- package/dist/replay/LinuxSeccompPolicy.js +40 -0
- package/dist/replay/ReplayWorkerProtocol.js +55 -0
- package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
- package/dist/server/createServer.js +52 -0
- package/dist/server/registerApplicationTools.js +115 -0
- package/dist/server/registerArtifactComparisonTool.js +16 -9
- package/dist/server/registerBrowserTools.js +33 -8
- package/dist/server/registerBundleComparisonTool.js +17 -20
- package/dist/server/registerElectronTools.js +45 -3
- package/dist/server/registerEnhancedTools.js +58 -13
- package/dist/server/registerEvidenceTools.js +5 -1
- package/dist/server/registerFunctionComparisonTool.js +14 -7
- package/dist/server/registerInvestigationTools.js +21 -17
- package/dist/server/registerManagedTools.js +6 -0
- package/dist/server/registerManagedWorkflowTools.js +277 -0
- package/dist/server/registerOfficialTools.js +8 -8
- package/dist/server/registerProcessComparisonTool.js +25 -47
- package/dist/server/registerSessionStatusTool.js +7 -7
- package/dist/server/registerSessionTools.js +51 -86
- package/dist/server/sessionEvidence.js +14 -19
- package/dist/server/toolInputValidation.js +77 -0
- package/dist/server/toolRegistrationOptions.js +79 -2
- package/dist/server/toolResult.js +25 -17
- package/package.json +12 -4
- package/scripts/rea.mjs +1 -1
- package/skills/rea-analysis/SKILL.md +59 -3
|
@@ -9,43 +9,60 @@ export const toCallToolResult = (result, contract, options = {}) => result.ok
|
|
|
9
9
|
: errorResult(result.error);
|
|
10
10
|
const errorResult = (error) => {
|
|
11
11
|
const projected = projectAnalysisError(error);
|
|
12
|
+
const structuredContent = { error: projected };
|
|
12
13
|
return {
|
|
13
14
|
content: [
|
|
14
15
|
{
|
|
15
16
|
type: "text",
|
|
16
|
-
text:
|
|
17
|
+
text: JSON.stringify(structuredContent),
|
|
17
18
|
},
|
|
18
19
|
],
|
|
19
|
-
structuredContent
|
|
20
|
+
structuredContent,
|
|
20
21
|
isError: true,
|
|
21
22
|
};
|
|
22
23
|
};
|
|
23
24
|
const successResult = (value, contract, options) => {
|
|
24
|
-
const candidate =
|
|
25
|
+
const candidate = compactEvidence(value) ??
|
|
26
|
+
(contract.kind === "session" ? { result: value } : value);
|
|
25
27
|
const parsed = contract.outputSchema.safeParse(candidate);
|
|
26
28
|
if (!parsed.success) {
|
|
29
|
+
const structuredContent = {
|
|
30
|
+
error: projectAnalysisError(new AnalysisOutputError(contract.name, "output does not match the tool contract")),
|
|
31
|
+
};
|
|
27
32
|
return {
|
|
28
33
|
content: [
|
|
29
34
|
{
|
|
30
35
|
type: "text",
|
|
31
|
-
text:
|
|
36
|
+
text: JSON.stringify(structuredContent),
|
|
32
37
|
},
|
|
33
38
|
],
|
|
34
|
-
structuredContent
|
|
35
|
-
error: projectAnalysisError(new AnalysisOutputError(contract.name, "output does not match the tool contract")),
|
|
36
|
-
},
|
|
39
|
+
structuredContent,
|
|
37
40
|
isError: true,
|
|
38
41
|
};
|
|
39
42
|
}
|
|
40
43
|
return {
|
|
41
44
|
content: [
|
|
42
|
-
{ type: "text", text:
|
|
45
|
+
{ type: "text", text: JSON.stringify(parsed.data) },
|
|
43
46
|
...evidenceResourceLinks(value, contract.kind === "session" ||
|
|
44
47
|
options.evidenceResourcesAvailable === true),
|
|
45
48
|
],
|
|
46
49
|
structuredContent: candidate,
|
|
47
50
|
};
|
|
48
51
|
};
|
|
52
|
+
const compactEvidence = (value) => {
|
|
53
|
+
if (typeof value !== "object" ||
|
|
54
|
+
value === null ||
|
|
55
|
+
Array.isArray(value) ||
|
|
56
|
+
typeof value.evidence_id !== "string" ||
|
|
57
|
+
!/^ev_[a-f0-9]{64}$/u.test(value.evidence_id) ||
|
|
58
|
+
!("normalized_result" in value))
|
|
59
|
+
return undefined;
|
|
60
|
+
return {
|
|
61
|
+
result: value.normalized_result,
|
|
62
|
+
evidence_id: value.evidence_id,
|
|
63
|
+
evidence_uri: `rea://evidence/${value.evidence_id}`,
|
|
64
|
+
};
|
|
65
|
+
};
|
|
49
66
|
const evidenceResourceLinks = (value, available) => {
|
|
50
67
|
if (!available ||
|
|
51
68
|
typeof value !== "object" ||
|
|
@@ -64,12 +81,3 @@ const evidenceResourceLinks = (value, available) => {
|
|
|
64
81
|
},
|
|
65
82
|
];
|
|
66
83
|
};
|
|
67
|
-
const formatValue = (value) => {
|
|
68
|
-
if (value === null)
|
|
69
|
-
return "OK";
|
|
70
|
-
if (typeof value === "string")
|
|
71
|
-
return value;
|
|
72
|
-
if (typeof value === "object")
|
|
73
|
-
return JSON.stringify(value, null, 2);
|
|
74
|
-
return String(value);
|
|
75
|
-
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rea-agents",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Reverse engineer anything from your terminal or agent with one CLI and MCP server.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -50,9 +50,11 @@
|
|
|
50
50
|
"LICENSE"
|
|
51
51
|
],
|
|
52
52
|
"scripts": {
|
|
53
|
-
"
|
|
53
|
+
"deps:check": "node scripts/check-dependency-install.mjs",
|
|
54
|
+
"prebuild": "npm run deps:check && node scripts/generate-package-metadata.mjs",
|
|
54
55
|
"build": "tsc -p tsconfig.build.json",
|
|
55
56
|
"postbuild": "node scripts/record-build-cache.mjs",
|
|
57
|
+
"precheck": "npm run deps:check",
|
|
56
58
|
"check": "npm run typecheck && npm run lint && npm run format:check && npm run docs:check && npm test",
|
|
57
59
|
"format": "prettier --write .",
|
|
58
60
|
"format:check": "prettier --check .",
|
|
@@ -74,6 +76,10 @@
|
|
|
74
76
|
"verify:hopper": "npm run build && node scripts/verify-real-hopper.mjs",
|
|
75
77
|
"verify:ghidra": "npm run build && node scripts/verify-real-ghidra.mjs",
|
|
76
78
|
"verify:browser": "npm run build && node scripts/verify-real-browser.mjs",
|
|
79
|
+
"verify:javascript-runtime": "npm run build && node scripts/verify-local-javascript-runtime.mjs",
|
|
80
|
+
"verify:application-workflows": "npm run build && node scripts/verify-local-application-workflows.mjs",
|
|
81
|
+
"verify:managed": "npm run build && node scripts/verify-managed-conformance.mjs",
|
|
82
|
+
"verify:replay": "npm run build && node scripts/verify-real-javascript-replay.mjs",
|
|
77
83
|
"verify:hopper:linux": "npm run build && node scripts/verify-real-hopper-linux.mjs",
|
|
78
84
|
"verify:setup:linux": "npm run build && node scripts/verify-linux-setup-e2e.mjs",
|
|
79
85
|
"build:fixtures": "node scripts/build-conformance-fixtures.mjs",
|
|
@@ -81,9 +87,11 @@
|
|
|
81
87
|
"verify:package": "npm run build && node scripts/verify-package.mjs",
|
|
82
88
|
"verify:published": "node scripts/verify-published-package.mjs",
|
|
83
89
|
"config:print": "node scripts/print-mcp-config.mjs",
|
|
84
|
-
"docs:generate": "npm run build && node scripts/generate-product-catalog.mjs && typedoc && node scripts/generate-error-schema.mjs",
|
|
85
|
-
"docs:check": "node scripts/generate-package-metadata.mjs --check && npm run build && node scripts/generate-product-catalog.mjs --check && node scripts/check-doc-facts.mjs && node scripts/check-typedoc.mjs && node scripts/generate-error-schema.mjs --check",
|
|
90
|
+
"docs:generate": "npm run build && node scripts/generate-skill-metadata.mjs && node scripts/generate-product-catalog.mjs && typedoc && node scripts/generate-error-schema.mjs",
|
|
91
|
+
"docs:check": "node scripts/generate-package-metadata.mjs --check && npm run build && node scripts/generate-skill-metadata.mjs --check && node scripts/generate-product-catalog.mjs --check && node scripts/check-doc-facts.mjs && node scripts/check-typedoc.mjs && node scripts/generate-error-schema.mjs --check",
|
|
86
92
|
"docs:error-schema": "npm run build && node scripts/generate-error-schema.mjs",
|
|
93
|
+
"prepack": "npm run deps:check && node scripts/generate-skill-metadata.mjs --check",
|
|
94
|
+
"prepublishOnly": "npm run deps:check && node scripts/generate-skill-metadata.mjs --check",
|
|
87
95
|
"prepare": "npm run build && husky",
|
|
88
96
|
"rebuild:native": "node scripts/rebuild-native.mjs"
|
|
89
97
|
},
|
package/scripts/rea.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { dirname, resolve } from "node:path";
|
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
|
|
7
7
|
// Route production MCP before importing Incur. Incur owns registration helpers
|
|
8
|
-
// such as `mcp add`, while only dist/main.js may serve the
|
|
8
|
+
// such as `mcp add`, while only dist/main.js may serve the stdio tool catalog.
|
|
9
9
|
const args = process.argv.slice(2);
|
|
10
10
|
const { default: packageJson } = await import("../package.json", {
|
|
11
11
|
with: { type: "json" },
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: rea-analysis
|
|
3
|
-
description: Reverse engineer
|
|
3
|
+
description: Reverse engineer native, Electron/JavaScript, and web applications with REA. Connect static artifacts to passive runtime evidence, explain how features work, and build a version tailored to the user's project.
|
|
4
4
|
metadata:
|
|
5
|
-
version: "
|
|
6
|
-
tool_count:
|
|
5
|
+
version: "20"
|
|
6
|
+
tool_count: 91
|
|
7
|
+
catalog_digest: "bdf382596e1a00ffc9d59de287b2ad647eeebe629c48a8f8cf158b300363ce53"
|
|
7
8
|
---
|
|
8
9
|
|
|
9
10
|
# REA
|
|
@@ -35,6 +36,61 @@ Electron `file://` pages use `list_electron_targets` and
|
|
|
35
36
|
filesystem-root authority. Never claim that Electron inspection invoked IPC,
|
|
36
37
|
evaluated renderer JavaScript, navigated, or escaped an approved root.
|
|
37
38
|
|
|
39
|
+
For an operator-supplied ASAR or extracted JavaScript/Electron application, use
|
|
40
|
+
`analyze_javascript_application` after the operator configures its canonical
|
|
41
|
+
root in `REA_INVESTIGATION_INPUT_ROOTS_JSON`; every call still requires
|
|
42
|
+
`approved: true`. Source-map contents require the independent
|
|
43
|
+
`source_map_read_approved` flag. Treat BrowserWindow preferences, preload and
|
|
44
|
+
contextBridge surfaces, IPC registrations, utility processes, and native
|
|
45
|
+
binding requests as static syntax observations. Treat only a unique exact
|
|
46
|
+
literal IPC channel match as an inferred pairing; keep dynamic and ambiguous
|
|
47
|
+
channels unresolved. A requested `.node` member is not a verified binary export.
|
|
48
|
+
Never claim that this workflow executed application code or observed runtime
|
|
49
|
+
registration, reachability, defaults, or policy enforcement.
|
|
50
|
+
|
|
51
|
+
When static application Evidence and passive `inspect_web_page` or
|
|
52
|
+
`inspect_electron_page` Evidence already exist, use
|
|
53
|
+
`reconcile_javascript_runtime` to map capture-scoped targets, frames, scripts,
|
|
54
|
+
and workers onto the static graph. Supply exactly one `application` layer and
|
|
55
|
+
add separately analyzed `cache` or `assets` layers only when relevant. Use
|
|
56
|
+
explicit file-root or URL-prefix mappings for relocated runtime paths; mappings
|
|
57
|
+
are inference inputs and never broaden CDP or filesystem authority. Prefer
|
|
58
|
+
approved captured-source digest identity, report path/digest disagreement as a
|
|
59
|
+
mismatch, preserve ambiguity, and never call a module executed merely because
|
|
60
|
+
its containing bundle was observed. Keep source-map authority separate. This
|
|
61
|
+
tool maps JavaScript graph entities; `correlate_static_and_runtime` remains the
|
|
62
|
+
separate workflow for explicit cross-version comparison hypotheses.
|
|
63
|
+
|
|
64
|
+
Use `trace_application_feature` on authenticated static or reconciled
|
|
65
|
+
application Evidence to follow one literal node ID, route, string, API, IPC
|
|
66
|
+
channel, module, or native export. Choose an explicit direction and bounds.
|
|
67
|
+
Preserve every graph authority in the returned subgraph. A native handoff means
|
|
68
|
+
only that the exact artifact digest and requested export frontier are known;
|
|
69
|
+
link Ghidra or Hopper Evidence only on exact subject digest, and never claim the
|
|
70
|
+
workflow opened a provider or verified a requested export by itself.
|
|
71
|
+
|
|
72
|
+
Use `compare_application_versions` after analyzing both versions independently.
|
|
73
|
+
Accept only its unique digest, source-map, structural-fingerprint, or non-module
|
|
74
|
+
semantic matches. Never use module ordinals or minified names as persistent
|
|
75
|
+
identity, and never promote an ambiguous candidate to a match. Report added or
|
|
76
|
+
removed only when opposite-side coverage is complete; otherwise report unknown.
|
|
77
|
+
Use `unknown_registry_approved: true` only after approval to retain unresolved
|
|
78
|
+
version matches. For local operator-provided artifacts, the packaged
|
|
79
|
+
`verify:application-workflows` command reports digests and coverage without
|
|
80
|
+
printing source text.
|
|
81
|
+
|
|
82
|
+
Use `run_controlled_replay` only for operator-selected extracted JavaScript
|
|
83
|
+
modules when the separate `javascript_replay` policy is enabled. First call
|
|
84
|
+
`mode: plan`; review the exact module, stub, runtime, sandbox, case, limit, and
|
|
85
|
+
policy commitments. Execute only with `approved: true` and that exact
|
|
86
|
+
`plan_digest`. Prefer explicit cases plus the parser, sanitizer, or clipboard
|
|
87
|
+
boundary generator. A right manifest produces a derived differential result.
|
|
88
|
+
Treat return values, exceptions, denials, limits, and crashes as observations
|
|
89
|
+
of the isolated experiment with `controlled-replay` authority—not facts about
|
|
90
|
+
the real application. Never substitute passive browser/Electron permission,
|
|
91
|
+
Process Capture, or an in-process `vm` run. Reproducer export requires its own
|
|
92
|
+
literal approval and `evidence_write` authority after sandbox cleanup.
|
|
93
|
+
|
|
38
94
|
## Understand the request
|
|
39
95
|
|
|
40
96
|
Identify the app and what the user wants to understand or build. Do not ask for information they already provided.
|