agent-workflow-inspector 0.0.0-stage → 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.
Files changed (41) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/CODE_OF_CONDUCT.md +5 -0
  3. package/CONTRIBUTING.md +9 -0
  4. package/LICENSE +21 -0
  5. package/README.md +341 -2
  6. package/SECURITY.md +5 -0
  7. package/awi.config.example.json +39 -0
  8. package/dist/cli/index.d.ts +1 -0
  9. package/dist/cli/index.js +1338 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/index.d.ts +256 -0
  12. package/dist/index.js +1159 -0
  13. package/dist/index.js.map +1 -0
  14. package/docs/architecture.md +21 -0
  15. package/docs/assets/architecture.svg +139 -0
  16. package/docs/assets/banner.svg +105 -0
  17. package/docs/assets/detection-patterns.svg +134 -0
  18. package/docs/assets/terminal-preview.svg +93 -0
  19. package/docs/audit.md +91 -0
  20. package/docs/ci-integration.md +45 -0
  21. package/docs/configuration.md +17 -0
  22. package/docs/detection-rules.md +38 -0
  23. package/docs/getting-started.md +70 -0
  24. package/docs/limitations.md +15 -0
  25. package/docs/releases/v1.0.0.md +32 -0
  26. package/docs/releasing.md +23 -0
  27. package/docs/report-schema.md +29 -0
  28. package/docs/schemas/config.schema.json +183 -0
  29. package/docs/schemas/report.schema.json +158 -0
  30. package/docs/schemas/trace.schema.json +98 -0
  31. package/docs/security.md +34 -0
  32. package/docs/trace-formats.md +41 -0
  33. package/docs/troubleshooting.md +12 -0
  34. package/docs/verification.md +44 -0
  35. package/examples/argument-drift.config.json +9 -0
  36. package/examples/healthy/basic.json +30 -0
  37. package/examples/opentelemetry/tools.json +210 -0
  38. package/examples/suspicious/argument-drift.json +62 -0
  39. package/examples/suspicious/cycle.json +78 -0
  40. package/examples/suspicious/retries.json +116 -0
  41. package/package.json +78 -3
@@ -0,0 +1,23 @@
1
+ # Release procedure
2
+
3
+ ## v1.0.0 status (verified October 20, 2026)
4
+
5
+ - [GitHub release](https://github.com/jigar48/awi/releases/tag/v1.0.0): published October 19, 2026, neither draft nor prerelease. Assets include the package tarball and `release-candidate.json` (an artifact filename, not the current release status).
6
+ - Annotated tag `v1.0.0` resolves to commit `1baca3ebdcc4da792f11487483abf3f60c22d1fb`. The default branch is `main`.
7
+ - [npm registry version](https://registry.npmjs.org/agent-workflow-inspector/1.0.0): HTTP 200, name `agent-workflow-inspector`, version `1.0.0`, published October 19, 2026.
8
+ - Registry tarball integrity: `sha512-lLYHfyeswXS2mF13a0a0YLKkdC6PSSYBnZM74XuYsqfHIiNTkBFQDk6gmhb3fcaAH3Ebf+W+lDo/LxUKv9CAXw==`.
9
+
10
+ These are read-only metadata checks, not a fresh registry installation or byte comparison against GitHub assets. The registry README still contains historical candidate wording; local documentation changes do not modify existing npm metadata or release assets.
11
+
12
+ ## Future releases
13
+
14
+ Publication is a separate maintainer action requiring explicit authorization. Never republish 1.0.0, move its tag, or replace its assets to include these later changes.
15
+
16
+ 1. Choose an unused version and review source, package metadata, changelog and release notes. Confirm current registry ownership and existing tags/releases without exposing credentials.
17
+ 2. Run `pnpm install --frozen-lockfile`, `pnpm check`, `pnpm verify:quickstart`, `pnpm format:check`, `pnpm schemas`, `git diff --exit-code -- docs/schemas`, `pnpm audit --prod`, `pnpm audit`, and `pnpm smoke:package`.
18
+ 3. Require a successful nine-job hosted matrix for the exact approved source commit. Earlier runs do not validate a later commit.
19
+ 4. Pack and inspect the artifact. Record the source SHA and tarball SHA-512 outside the package; validate the isolated installed package, executable, examples and ESM/TypeScript imports.
20
+ 5. Only after approval, use the maintainer's authenticated release process with interactive 2FA or a separately reviewed trusted publisher. Never store credentials in this repository. No publishing workflow is provided here.
21
+ 6. Verify the published tag/source SHA, GitHub assets and registry integrity against the approved artifact. Test a clean registry consumer, then record the date, URLs, CI run and verification limits.
22
+
23
+ See [verification](verification.md) for historical results and the [release notes](releases/v1.0.0.md) for v1.0.0 behavior.
@@ -0,0 +1,29 @@
1
+ # JSON report v2
2
+
3
+ The [machine schema](schemas/report.schema.json) and the exported `Report` type use `version: 2`. The `fingerprintVersion` remains `awi-sha256-v1`. The envelope also includes `complete`, `summaries`, `findings`, and `warnings`. Optional `content` requires explicit opt-in. Reports contain no generation timestamp or absolute input path.
4
+
5
+ Summaries include `traceId`, `operations`, `toolCalls`, `maxDepth`, and, when available, `durationMs` and recorded leaf `usage`. Findings include `ruleId`, `severity`, `confidence`, `title`, `description`, `explanation`, `remediation`, `traceId`, `operationIds`, and structured `evidence`. `evidence.references` repeats the operation aliases and includes the adapter's source format and index when available. A source index describes recorded order in its input, which can repeat across merged files. AWI005 is trace-wide and has empty operation and reference lists.
6
+
7
+ `traceId` uses `trace-N`. `operationIds` and `evidence.references[].operationId` use `op-N`. Join on `traceId` within a report and on the pair `(traceId, operationId)` for operation references. Ordinals start at 1 and follow the lexical order of recorded trace IDs and the recorded operation IDs within each merged trace. They can shift when inputs are added, removed, or renamed. Findings retain descending severity and the existing lexical order of underlying trace IDs, rule IDs, and operation ID lists. Source indices still depend on the order in the original export. Warnings deduplicate and sort.
8
+
9
+ ```json
10
+ {
11
+ "version": 2,
12
+ "fingerprintVersion": "awi-sha256-v1",
13
+ "complete": true,
14
+ "summaries": [
15
+ { "traceId": "trace-1", "operations": 0, "toolCalls": 0, "maxDepth": 0 }
16
+ ],
17
+ "findings": [],
18
+ "warnings": []
19
+ }
20
+ ```
21
+
22
+ `complete: false` indicates truncation and produces a CLI operational failure. Eligibility warnings identify unavailable timing or argument evidence. Consumers should use structured fields for integrations and allow additive evidence fields.
23
+
24
+ ## Migrating from v1
25
+
26
+ - Update consumers to recognize `version: 2`. The v2 validator rejects v1, and v1 validators reject v2. Trace input and configuration versions are independent of the report version.
27
+ - Replace joins to raw input IDs with report-local joins. For private debugging, `--show-content` and `analyze(traces, config, true)` add `content[].recordedTraceId` alongside the report alias `content[].traceId`. The normalized operation at zero-based index `N - 1` in `content[].operations` corresponds to `op-N` and contains the recorded ID, subject to output sanitization. Findings and summaries keep the same aliases. See [privacy limits](security.md).
28
+ - AWI006 `evidence.recordedCosts` groups amounts by `currency-N` in lexical order of recorded currency labels within the finding. These aliases have finding-local scope.
29
+ - AWI007 remains disabled by default. Once enabled, it reports `failedCalls`, `distinctArgumentFingerprints` and `references`, with operation IDs in run order. V2 omits `toolName` and `errorCode` from evidence even when recorded content is enabled.
@@ -0,0 +1,183 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "type": "object",
4
+ "properties": {
5
+ "version": { "default": 1, "type": "number", "const": 1 },
6
+ "rules": {
7
+ "default": {
8
+ "AWI001": { "enabled": true, "threshold": 4 },
9
+ "AWI002": { "enabled": true, "threshold": 3 },
10
+ "AWI003": { "enabled": true, "minRepetitions": 3, "maxCycleLength": 6 },
11
+ "AWI004": { "enabled": true, "threshold": 5, "windowSeconds": 30 },
12
+ "AWI005": { "enabled": true, "maxOperations": 100, "maxDepth": 20 },
13
+ "AWI006": { "enabled": true },
14
+ "AWI007": {
15
+ "enabled": false,
16
+ "threshold": 4,
17
+ "minDistinctArguments": 3
18
+ }
19
+ },
20
+ "type": "object",
21
+ "properties": {
22
+ "AWI001": {
23
+ "default": { "enabled": true, "threshold": 4 },
24
+ "type": "object",
25
+ "properties": {
26
+ "enabled": { "default": true, "type": "boolean" },
27
+ "threshold": {
28
+ "default": 4,
29
+ "type": "integer",
30
+ "minimum": 2,
31
+ "maximum": 100
32
+ }
33
+ },
34
+ "required": ["enabled", "threshold"],
35
+ "additionalProperties": false
36
+ },
37
+ "AWI002": {
38
+ "default": { "enabled": true, "threshold": 3 },
39
+ "type": "object",
40
+ "properties": {
41
+ "enabled": { "default": true, "type": "boolean" },
42
+ "threshold": {
43
+ "default": 3,
44
+ "type": "integer",
45
+ "minimum": 2,
46
+ "maximum": 100
47
+ }
48
+ },
49
+ "required": ["enabled", "threshold"],
50
+ "additionalProperties": false
51
+ },
52
+ "AWI003": {
53
+ "default": {
54
+ "enabled": true,
55
+ "minRepetitions": 3,
56
+ "maxCycleLength": 6
57
+ },
58
+ "type": "object",
59
+ "properties": {
60
+ "enabled": { "default": true, "type": "boolean" },
61
+ "minRepetitions": {
62
+ "default": 3,
63
+ "type": "integer",
64
+ "minimum": 2,
65
+ "maximum": 100
66
+ },
67
+ "maxCycleLength": {
68
+ "default": 6,
69
+ "type": "integer",
70
+ "minimum": 2,
71
+ "maximum": 16
72
+ }
73
+ },
74
+ "required": ["enabled", "minRepetitions", "maxCycleLength"],
75
+ "additionalProperties": false
76
+ },
77
+ "AWI004": {
78
+ "default": { "enabled": true, "threshold": 5, "windowSeconds": 30 },
79
+ "type": "object",
80
+ "properties": {
81
+ "enabled": { "default": true, "type": "boolean" },
82
+ "threshold": {
83
+ "default": 5,
84
+ "type": "integer",
85
+ "minimum": 2,
86
+ "maximum": 100
87
+ },
88
+ "windowSeconds": {
89
+ "default": 30,
90
+ "type": "integer",
91
+ "minimum": 1,
92
+ "maximum": 3600
93
+ }
94
+ },
95
+ "required": ["enabled", "threshold", "windowSeconds"],
96
+ "additionalProperties": false
97
+ },
98
+ "AWI005": {
99
+ "default": { "enabled": true, "maxOperations": 100, "maxDepth": 20 },
100
+ "type": "object",
101
+ "properties": {
102
+ "enabled": { "default": true, "type": "boolean" },
103
+ "maxOperations": {
104
+ "default": 100,
105
+ "type": "integer",
106
+ "minimum": 1,
107
+ "maximum": 50000
108
+ },
109
+ "maxDepth": {
110
+ "default": 20,
111
+ "type": "integer",
112
+ "minimum": 1,
113
+ "maximum": 1000
114
+ }
115
+ },
116
+ "required": ["enabled", "maxOperations", "maxDepth"],
117
+ "additionalProperties": false
118
+ },
119
+ "AWI006": {
120
+ "default": { "enabled": true },
121
+ "type": "object",
122
+ "properties": { "enabled": { "default": true, "type": "boolean" } },
123
+ "required": ["enabled"],
124
+ "additionalProperties": false
125
+ },
126
+ "AWI007": {
127
+ "default": {
128
+ "enabled": false,
129
+ "threshold": 4,
130
+ "minDistinctArguments": 3
131
+ },
132
+ "type": "object",
133
+ "properties": {
134
+ "enabled": { "default": false, "type": "boolean" },
135
+ "threshold": {
136
+ "default": 4,
137
+ "type": "integer",
138
+ "minimum": 4,
139
+ "maximum": 100
140
+ },
141
+ "minDistinctArguments": {
142
+ "default": 3,
143
+ "type": "integer",
144
+ "minimum": 3,
145
+ "maximum": 100
146
+ }
147
+ },
148
+ "required": ["enabled", "threshold", "minDistinctArguments"],
149
+ "additionalProperties": false
150
+ }
151
+ },
152
+ "required": [
153
+ "AWI001",
154
+ "AWI002",
155
+ "AWI003",
156
+ "AWI004",
157
+ "AWI005",
158
+ "AWI006",
159
+ "AWI007"
160
+ ],
161
+ "additionalProperties": false
162
+ },
163
+ "fingerprint": {
164
+ "default": { "ignorePaths": [] },
165
+ "type": "object",
166
+ "properties": {
167
+ "ignorePaths": {
168
+ "default": [],
169
+ "maxItems": 100,
170
+ "type": "array",
171
+ "items": {
172
+ "type": "string",
173
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)*$"
174
+ }
175
+ }
176
+ },
177
+ "required": ["ignorePaths"],
178
+ "additionalProperties": false
179
+ }
180
+ },
181
+ "required": ["version", "rules", "fingerprint"],
182
+ "additionalProperties": false
183
+ }
@@ -0,0 +1,158 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "type": "object",
4
+ "properties": {
5
+ "version": { "type": "number", "const": 2 },
6
+ "fingerprintVersion": { "type": "string", "const": "awi-sha256-v1" },
7
+ "complete": { "type": "boolean" },
8
+ "summaries": {
9
+ "type": "array",
10
+ "items": {
11
+ "type": "object",
12
+ "properties": {
13
+ "traceId": { "type": "string", "pattern": "^trace-[1-9][0-9]*$" },
14
+ "operations": {
15
+ "type": "integer",
16
+ "minimum": 0,
17
+ "maximum": 9007199254740991
18
+ },
19
+ "toolCalls": {
20
+ "type": "integer",
21
+ "minimum": 0,
22
+ "maximum": 9007199254740991
23
+ },
24
+ "maxDepth": {
25
+ "type": "integer",
26
+ "minimum": 0,
27
+ "maximum": 9007199254740991
28
+ },
29
+ "durationMs": { "type": "number", "minimum": 0 },
30
+ "usage": {
31
+ "type": "object",
32
+ "properties": {
33
+ "inputTokens": {
34
+ "type": "integer",
35
+ "minimum": 0,
36
+ "maximum": 9007199254740991
37
+ },
38
+ "outputTokens": {
39
+ "type": "integer",
40
+ "minimum": 0,
41
+ "maximum": 9007199254740991
42
+ },
43
+ "totalTokens": {
44
+ "type": "integer",
45
+ "minimum": 0,
46
+ "maximum": 9007199254740991
47
+ }
48
+ },
49
+ "additionalProperties": false
50
+ }
51
+ },
52
+ "required": ["traceId", "operations", "toolCalls", "maxDepth"],
53
+ "additionalProperties": false
54
+ }
55
+ },
56
+ "findings": {
57
+ "type": "array",
58
+ "items": {
59
+ "type": "object",
60
+ "properties": {
61
+ "ruleId": {
62
+ "type": "string",
63
+ "enum": [
64
+ "AWI001",
65
+ "AWI002",
66
+ "AWI003",
67
+ "AWI004",
68
+ "AWI005",
69
+ "AWI006",
70
+ "AWI007"
71
+ ]
72
+ },
73
+ "severity": { "type": "string", "enum": ["low", "medium", "high"] },
74
+ "confidence": { "type": "string", "enum": ["high", "moderate"] },
75
+ "title": { "type": "string" },
76
+ "description": { "type": "string" },
77
+ "explanation": { "type": "string" },
78
+ "remediation": { "type": "string" },
79
+ "traceId": { "type": "string", "pattern": "^trace-[1-9][0-9]*$" },
80
+ "operationIds": {
81
+ "type": "array",
82
+ "items": { "type": "string", "pattern": "^op-[1-9][0-9]*$" }
83
+ },
84
+ "evidence": {
85
+ "type": "object",
86
+ "properties": {
87
+ "references": {
88
+ "type": "array",
89
+ "items": {
90
+ "type": "object",
91
+ "properties": {
92
+ "operationId": {
93
+ "type": "string",
94
+ "pattern": "^op-[1-9][0-9]*$"
95
+ },
96
+ "source": {
97
+ "type": "object",
98
+ "properties": {
99
+ "format": { "type": "string", "enum": ["awi", "otel"] },
100
+ "index": {
101
+ "type": "integer",
102
+ "minimum": 0,
103
+ "maximum": 9007199254740991
104
+ }
105
+ },
106
+ "required": ["format", "index"],
107
+ "additionalProperties": false
108
+ }
109
+ },
110
+ "required": ["operationId"],
111
+ "additionalProperties": false
112
+ }
113
+ }
114
+ },
115
+ "required": ["references"],
116
+ "additionalProperties": {}
117
+ }
118
+ },
119
+ "required": [
120
+ "ruleId",
121
+ "severity",
122
+ "confidence",
123
+ "title",
124
+ "description",
125
+ "explanation",
126
+ "remediation",
127
+ "traceId",
128
+ "operationIds",
129
+ "evidence"
130
+ ],
131
+ "additionalProperties": false
132
+ }
133
+ },
134
+ "warnings": { "type": "array", "items": { "type": "string" } },
135
+ "content": {
136
+ "type": "array",
137
+ "items": {
138
+ "type": "object",
139
+ "properties": {
140
+ "traceId": { "type": "string", "pattern": "^trace-[1-9][0-9]*$" },
141
+ "recordedTraceId": { "type": "string" },
142
+ "operations": { "type": "array", "items": {} }
143
+ },
144
+ "required": ["traceId", "recordedTraceId", "operations"],
145
+ "additionalProperties": false
146
+ }
147
+ }
148
+ },
149
+ "required": [
150
+ "version",
151
+ "fingerprintVersion",
152
+ "complete",
153
+ "summaries",
154
+ "findings",
155
+ "warnings"
156
+ ],
157
+ "additionalProperties": false
158
+ }
@@ -0,0 +1,98 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "type": "object",
4
+ "properties": {
5
+ "version": { "type": "number", "const": 1 },
6
+ "traceId": { "type": "string", "minLength": 1 },
7
+ "metadata": {
8
+ "type": "object",
9
+ "propertyNames": { "type": "string" },
10
+ "additionalProperties": {}
11
+ },
12
+ "operations": {
13
+ "maxItems": 50000,
14
+ "type": "array",
15
+ "items": {
16
+ "type": "object",
17
+ "properties": {
18
+ "id": { "type": "string", "minLength": 1 },
19
+ "parentId": { "type": "string", "minLength": 1 },
20
+ "type": {
21
+ "type": "string",
22
+ "enum": ["tool", "agent", "model", "workflow", "generic"]
23
+ },
24
+ "name": { "type": "string", "minLength": 1 },
25
+ "toolName": { "type": "string" },
26
+ "startTime": {
27
+ "type": "string",
28
+ "format": "date-time",
29
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
30
+ },
31
+ "endTime": {
32
+ "type": "string",
33
+ "format": "date-time",
34
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
35
+ },
36
+ "status": {
37
+ "default": "unknown",
38
+ "type": "string",
39
+ "enum": ["ok", "error", "unknown"]
40
+ },
41
+ "error": {
42
+ "type": "object",
43
+ "properties": {
44
+ "code": { "type": "string" },
45
+ "message": { "type": "string" }
46
+ },
47
+ "additionalProperties": false
48
+ },
49
+ "arguments": {},
50
+ "resultMetadata": {
51
+ "type": "object",
52
+ "propertyNames": { "type": "string" },
53
+ "additionalProperties": {}
54
+ },
55
+ "usage": {
56
+ "type": "object",
57
+ "properties": {
58
+ "inputTokens": {
59
+ "type": "integer",
60
+ "minimum": 0,
61
+ "maximum": 9007199254740991
62
+ },
63
+ "outputTokens": {
64
+ "type": "integer",
65
+ "minimum": 0,
66
+ "maximum": 9007199254740991
67
+ },
68
+ "totalTokens": {
69
+ "type": "integer",
70
+ "minimum": 0,
71
+ "maximum": 9007199254740991
72
+ }
73
+ },
74
+ "additionalProperties": false
75
+ },
76
+ "cost": {
77
+ "type": "object",
78
+ "properties": {
79
+ "amount": { "type": "number", "minimum": 0 },
80
+ "currency": { "type": "string", "pattern": "^[A-Z]{3}$" }
81
+ },
82
+ "required": ["amount", "currency"],
83
+ "additionalProperties": false
84
+ },
85
+ "metadata": {
86
+ "type": "object",
87
+ "propertyNames": { "type": "string" },
88
+ "additionalProperties": {}
89
+ }
90
+ },
91
+ "required": ["id", "type", "name", "status"],
92
+ "additionalProperties": false
93
+ }
94
+ }
95
+ },
96
+ "required": ["version", "traceId", "operations"],
97
+ "additionalProperties": false
98
+ }
@@ -0,0 +1,34 @@
1
+ # Security and privacy
2
+
3
+ All trace content is inert untrusted JSON. AWI never obeys embedded instructions. Analysis uses no eval, shell execution, URL fetching, telemetry, network, database or intermediate content files. Fixed limits apply to parsing, files, spans, nesting, strings, traversal, cycles, findings and default report amplification. Shared native values count once per occurrence against the processed-content budget.
4
+
5
+ Default JSON and human reports generated by AWI use report-local ordinal references such as `trace-1` and `op-1`. The references encode rank in a deterministic order. They contain no raw identifier bytes or hashes and are scoped to one report (`op-N` is scoped to one trace within that report). AWI007 still compares exact tool names and error codes internally. Its report gives the number of failures, number of distinct argument fingerprints, and operation references. Default reports omit raw names, codes, arguments, results, prompts, metadata, error messages and fingerprint values. AWI006 uses `currency-N` keys in place of recorded currency labels and preserves each currency group's amount.
6
+
7
+ Reports still expose counts, timing, usage, cost amounts, source indices, relative identifier order, and relationships within the workflow. Those details can be sensitive or allow inference when combined with other data. Review them before sharing. These guarantees apply to reports produced by AWI analysis. The public renderers format the report supplied by the caller and can display strings the caller inserts.
8
+
9
+ `--show-content` and the third argument to `analyze(traces, config, true)` add a separate `content` section with the recorded trace ID and normalized operations, including recorded operation and parent IDs, names, tool names, error codes, and arguments. Recursive redaction of operations replaces values under keys matching authorization, password, secret, token, API key, cookie, credential, prompt, message, output or result. Arbitrary strings and keys can still reveal private data. Keep these reports private. AWI never transmits trace content.
10
+
11
+ JSON serialization escapes control and formatting characters where needed. Human output replaces terminal controls, bidirectional formatting and line/paragraph separators. Severity color is limited to supported interactive terminals and honors `NO_COLOR` and `--no-color`.
12
+
13
+ Parsing rejects `__proto__`, `constructor` and `prototype` object keys. No prototype merging occurs. Files are size-checked before parsing, decoded as strict UTF-8 (optional BOM accepted), and read in bounded chunks even if they grow. Aggregate limits count bytes actually read. CLI rejects symlink entries and symlink components of trace/configuration/output paths. Resolve legitimate OS aliases (including macOS /var temporary paths) to real paths first. POSIX opens also use O_NOFOLLOW, and all platforms compare the opened file identity with the checked file. This is not a filesystem sandbox against concurrent replacement of directory components: use trusted directories and OS permissions. Reports use an adjacent temporary file with mode 0600 on POSIX (Windows uses inherited filesystem ACLs), fsync and atomic exclusive hard-link publication. Existing targets are never overwritten. Cleanup is attempted on ordinary failures; OS errors can prevent removal. Filesystems without hard links fail closed. Crashes or cleanup failures may leave .tmp files to inspect/remove locally under the same filesystem permissions.
14
+
15
+ Broken stdout pipes produce a controlled operational failure, without an uncaught stack trace. Errors omit raw parser content, OS filenames and stacks. Schema errors show field paths/codes. See [the security policy](../SECURITY.md) for private disclosure guidance.
16
+
17
+ ## Synthetic before and after
18
+
19
+ Run the same fixture with the AWI007 opt-in configuration on the previous source revision and on the v2 source:
20
+
21
+ ```sh
22
+ node dist/cli/index.js inspect examples/suspicious/argument-drift.json --config examples/argument-drift.config.json --format json
23
+ ```
24
+
25
+ Selected fields from the AWI007 finding:
26
+
27
+ | Field | Previous report v1 | Report v2 |
28
+ | --------------------------------------- | ------------------------------------------ | ------------------------------ |
29
+ | `traceId` | `argument-drift` | `trace-1` |
30
+ | `operationIds` | `drift-0`, `drift-1`, `drift-2`, `drift-3` | `op-1`, `op-2`, `op-3`, `op-4` |
31
+ | `evidence.toolName` | `search` | Omitted |
32
+ | `evidence.errorCode` | `INVALID_QUERY` | Omitted |
33
+ | `evidence.failedCalls` | `4` | `4` |
34
+ | `evidence.distinctArgumentFingerprints` | `4` | `4` |
@@ -0,0 +1,41 @@
1
+ # Trace formats
2
+
3
+ ## AWI JSON v1
4
+
5
+ A trace is `{version:1, traceId:string, metadata?:object, operations:Operation[]}`. A collection is `{version:1, traces:Trace[]}`. Unknown fields fail validation; use metadata for extensions. See the [single-trace schema](schemas/trace.schema.json); ingest validates the collection wrapper separately.
6
+
7
+ Required operation fields: id, type, name. Types: tool, agent, model, workflow, generic. Status: ok, error, unknown (default). Optional fields: parentId, toolName, startTime, endTime, error:{code?,message?}, arguments (any JSON), resultMetadata, usage:{inputTokens?,outputTokens?,totalTokens?}, cost:{amount,currency}, metadata.
8
+
9
+ Times are offset-bearing ISO-8601 strings, optional independently, with at most nine fractional-second digits. Ordering and overlap use exact nanosecond comparisons; summary duration is a floating-point millisecond measurement. Duration is derived only with both endpoints; end-before-start fails. Trace duration is reported only if all operations have both endpoints. Token counts are nonnegative safe integers; cost is a finite nonnegative amount with a three-letter uppercase currency. Missing resources stay absent; recorded zero stays zero. IDs are nonempty and unique per trace. Missing parents warn and yield lower-bound depth; cycles and duplicates fail. Root depth is 1, empty trace depth 0. Generic operations remain in structure/counts.
10
+
11
+ ## OTLP JSON subset
12
+
13
+ Accepts protobuf JSON-shaped resourceSpans[].scopeSpans[].spans[]. Does not accept JSONL, legacy instrumentationLibrarySpans, binary protobuf, collector envelopes or proprietary framework exports. Trace IDs are nonzero 32-digit hex; span/parent IDs are 16-digit hex, lowercased. Empty/all-zero parent means root. Missing trace/span IDs fail. Missing scopeSpans/spans are empty; malformed arrays fail.
14
+
15
+ | Input | Canonical mapping |
16
+ | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
17
+ | traceId, spanId, parentSpanId, name | identity, parent, name |
18
+ | startTimeUnixNano / endTimeUnixNano | ISO times retaining nanosecond precision; decimal strings; numbers must be safe integers |
19
+ | status.code 1 / STATUS_CODE_OK | ok |
20
+ | status.code 2 / STATUS_CODE_ERROR | error |
21
+ | absent, 0, unrecognized status | unknown |
22
+ | gen_ai.tool.name or tool.name | toolName and tool classification |
23
+ | gen_ai.operation.name = execute_tool | tool |
24
+ | invoke_agent | agent |
25
+ | chat, generate_content, text_completion, embeddings | model |
26
+ | workflow | workflow |
27
+ | unrecognized operation | generic |
28
+ | gen_ai.tool.call.arguments | arguments; JSON strings parsed if valid, otherwise string preserved |
29
+ | gen_ai.usage.input_tokens / output_tokens / total_tokens | separately recorded nonnegative safe integer usage |
30
+ | exception event: exception.type / exception.message; error status.message | error code/message; status message is a fallback; exception alone does not promote unknown to failure |
31
+ | resource attributes, scope, attributes, events | preserved metadata |
32
+
33
+ Tool name takes precedence over operation classification. No span-name guessing. No results, costs, or usage are invented. AnyValue supports stringValue, boolValue, intValue, doubleValue, bytesValue, arrayValue.values, kvlistValue.values. Integer AnyValues must be signed 64-bit decimal strings or safe integer JSON numbers. Large values outside the safe numeric range stay strings and cannot become usage. Malformed known AnyValue encodings fail; empty or unknown encodings are omitted rather than turned into tool arguments. Arrays/objects with unknown members are not used as argument identity evidence. No type coercion fabricates usage.
34
+
35
+ These are limited GenAI semantic-convention assumptions, not universal compatibility. Instrumentation can use different attributes or omit arguments; inspect warnings or explicitly convert to AWI JSON. No framework integration has been certified. Positive-duration nanosecond spans retain their precision; truly zero-duration groups are excluded conservatively. Attributes/events remain in memory and are absent from default reports.
36
+
37
+ Auto-detection requires exactly one recognizable AWI/OTLP root. Otherwise specify input-format or fix the export. Malformed required data fails as a unit rather than silently dropping spans.
38
+
39
+ Resource attributes are decoded once per resourceSpans entry. Raw and normalized structures each have a bounded node budget; exports with extreme shared-metadata amplification fail explicitly. Binary AnyValues remain opaque base64 metadata and are not interpreted as tool/operation names, errors or argument identity. Unknown duplicate attributes clear earlier evidence rather than reviving stale values. Timestamp zero means missing; negative/out-of-uint64 timestamps fail. Unknown attributes remain outside classification; this subset does not certify every semantic-convention revision.
40
+
41
+ For missing or empty span names, the display label is unnamed and metadata awi.operation_name_recorded is false. An explicit execute_tool span still counts as a tool, but identity rules exclude it unless an actual tool name or recorded operation name is available. The display placeholder never establishes tool identity.
@@ -0,0 +1,12 @@
1
+ # Troubleshooting
2
+
3
+ - Invalid JSON/schema: use UTF-8 JSON, supported version and fields. JSONL/collector envelopes need conversion.
4
+ - Ambiguous format: remove conflicting roots or explicitly select input-format; schemas still apply.
5
+ - No sequence findings: read warnings. Recorded arguments, positive-duration times, shared parent and non-overlap are required. Patterns may span bounded windows.
6
+ - Duplicate IDs: files sharing traceId merge. Give unrelated executions different identities.
7
+ - Filesystem failure: check permissions, existing output, regular inputs and hard-link support. Use a new report path.
8
+ - Directory rejected: use a dedicated JSON trace directory; empty dirs, symlinks, unrelated files and excessive recursion fail.
9
+ - Exit 2: severity met fail-on (default high). Review evidence or adjust policy.
10
+ - Exit 1/incomplete: fix input or split workloads. Finding overflow is not success.
11
+ - Missing tokens/cost: unknown remains absent; parent totals are not attributed to tools.
12
+ - Install engines failure: use supported Node. Do not bypass engines or delete lockfile to hide incompatibility.
@@ -0,0 +1,44 @@
1
+ # Verification record
2
+
3
+ Audit date: October 19, 2026. Package manager: pnpm 11.25.0. Baseline implementation: 9bc61c1. See the historical [audit findings](audit.md) and current [release procedure](releasing.md).
4
+
5
+ ## Quickstart documentation check — October 20, 2026
6
+
7
+ On Windows, Node 24.19.0 / pnpm 11.25.0: frozen-lockfile installation, `pnpm check` (72 tests: 69 existing plus two README process-exit checks and one documentation encoding check; typecheck, lint and JS/declaration build), `pnpm verify:quickstart`, `pnpm format:check`, schema regeneration with no drift, isolated `pnpm smoke:package`, and `git diff --check` passed. README/getting-started synthetic JSON traces also parsed and analyzed with zero findings.
8
+
9
+ The quickstart verifier checks complete JSON reports, no warnings, healthy exit 0 with no findings, and retry exit 2 with exactly `AWI002`, `AWI004`, `AWI006`. It uses `process.execPath`, script-relative paths and no shell or network operations. The existing nine-job workflow now runs it; this change has not yet run on hosted CI, macOS, Linux or the other supported Node versions. No runtime source, dependencies or lockfile changed. The README gate exits 0 for the healthy fixture and 1 for the retry fixture; the CLI retains its existing exit codes. Registry/GitHub status was checked read-only; see [release status and limits](releasing.md). No push, tag, release, publish or deployment was performed during this check.
10
+
11
+ ## Historical hosted CI and release preparation
12
+
13
+ The [nine-job hosted CI run](https://github.com/jigar48/awi/actions/runs/39208844432) completed successfully for `d2514af3e9d4a7b11a53308a77ab2ca40333d8ce`. Windows, macOS and Ubuntu each passed on Node 22.18.0, 24.11.0 and 26, including all 69 tests, typecheck/lint/build, formatting, schema consistency, production dependency audit, packing and isolated package installation/API checks.
14
+
15
+ The platform table below records the earlier local audit only. The hosted run resolves that audit's platform gate for d2514af. Later local release-preparation changes affect documentation/package metadata, not runtime source or dependencies. They require a fresh nine-job main run before publication; earlier CI does not validate them. At that preparation stage, no tag, GitHub release or npm publication had been performed; publication was subsequently confirmed on October 20, 2026 (see [current release status](releasing.md)).
16
+
17
+ Release-preparation validation on Windows Node 24.19.0: `pnpm install --frozen-lockfile`, `pnpm check` (69 passing tests, typecheck, lint, JS/declaration build), `pnpm format:check`, `pnpm schemas` (before/after schema hashes unchanged), full `pnpm audit` (no known vulnerabilities), `pnpm smoke:package` (clean external consumer, all shipped examples/options, ESM and strict TypeScript imports), and `git diff --check` passed. Runtime source, tests, dependencies, lockfile and CI workflow remain identical to d2514af. Local documentation links and prepared GitHub topic syntax were checked; version-tagged release links intentionally await tag creation. Maintainer GitHub/portfolio/support links responded successfully; LinkedIn rejects HEAD checks, so that supplied URL is retained without claiming live content verification. Candidate artifact byte counts, SHA-256/SHA-512 and source SHA are recorded outside the package in the local release manifest.
18
+
19
+ ## Actual platform checks
20
+
21
+ | Environment | Node | Full tests | Typecheck / lint / full build | Isolated installed-package check |
22
+ | ----------------------------- | ------------------------- | ---------- | ----------------------------- | -------------------------------- |
23
+ | Windows x64 | 24.19.0 | 69 passed | Passed | Passed |
24
+ | Ubuntu 24.04.3 x64 under WSL2 | 24.19.0 | 69 passed | Passed | Passed |
25
+ | Ubuntu 24.04.3 x64 under WSL2 | 22.18.0 | 69 passed | Passed | Passed |
26
+ | Ubuntu 24.04.3 x64 under WSL2 | 26.0.0 | 69 passed | Passed | Passed |
27
+ | macOS | Not available | Not run | Not run | Not run |
28
+ | Hosted GitHub Actions matrix | 9 configured combinations | Not run | Not run | Not run |
29
+
30
+ WSL uses real Linux Node distributions and independent Linux dependencies. Downloaded runtimes were verified against their official SHA-256 manifests. WSL/NTFS and Linux temporary-filesystem checks do not certify macOS or hosted runners. Windows Node 22/26 and the exact Node 24.11.0 floor remain for CI to verify. Future Node majors are not verified by these runs.
31
+
32
+ ## Checks performed
33
+
34
+ - Strict TypeScript, ESLint and full JS/declaration builds.
35
+ - 69 tests: original 37 plus 32 targeted audit regressions, with additional assertions in existing tests. All six rules have positive/negative coverage; tests include exact concurrency/time boundaries, failure interactions, graph errors, OTLP encodings, source validation, deterministic fragments and capped findings, hostile content, terminal/JSON escaping, UTF-8/BOM, symlinks, overwrite/hardlink/long-name handling, resource budgets and operational exit codes.
36
+ - The original 50,000-operation performance assertion remains unchanged. Specific hostile metadata, wide-array and shared-string vectors return controlled errors in a 96 MiB child heap; this is not a universal minimum-memory guarantee for all maximum-size inputs.
37
+ - Network, DNS/fetch and subprocess APIs were blocked while analyzing hostile trace values; no external effects occurred.
38
+ - Frozen-lockfile installation, formatting, whitespace checks and deterministic schema regeneration.
39
+ - Full pnpm audit reported no known dependency vulnerabilities at audit time. This result can change; it does not assess all Node/OS vulnerabilities or prove absence of defects.
40
+ - Actual tarball allowlist, executable mode/shebang, bin/ESM/type export mappings, included maintainer documents, installation outside the repository with scripts disabled, all shipped examples/options and strict consumer TypeScript imports.
41
+
42
+ A cold-filesystem declaration compilation timeout and a multi-process CLI test timeout were diagnosed as test-harness I/O budgets, not waived product assertions. CLI setup compiles runtime JS with a bounded setup timeout; full builds/consumer typechecks still verify declarations. CLI subprocesses and end-to-end I/O cases have explicit budgets; detector performance checks remain unchanged.
43
+
44
+ During the original local audit, no remote mutations occurred. The later authorized feature-branch push produced the successful hosted run above. At that stage, publication required approval, a fresh successful matrix on the final main candidate, and npm authentication/name checks. The current published status is recorded separately. See [release procedure](releasing.md).