altium-toolkit 1.0.8 → 1.0.10

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 (102) hide show
  1. package/README.md +18 -6
  2. package/docs/api.md +78 -16
  3. package/docs/model-format.md +229 -8
  4. package/docs/schemas/altium_toolkit/ci_artifact_bundle_a1.schema.json +76 -0
  5. package/docs/schemas/altium_toolkit/draftsman_digest_a1.schema.json +35 -0
  6. package/docs/schemas/altium_toolkit/netlist_a1.schema.json +53 -0
  7. package/docs/schemas/altium_toolkit/normalized_model_a1.schema.json +1826 -110
  8. package/docs/schemas/altium_toolkit/parser_compatibility_fuzz_a1.schema.json +25 -0
  9. package/docs/schemas/altium_toolkit/pcb_svg_semantics_a1.schema.json +86 -0
  10. package/docs/schemas/altium_toolkit/project_bundle_a1.schema.json +63 -0
  11. package/docs/schemas/altium_toolkit/project_document_graph_a1.schema.json +33 -0
  12. package/docs/schemas/altium_toolkit/schematic_svg_semantics_a1.schema.json +50 -0
  13. package/docs/schemas/altium_toolkit/svg_model_cross_link_a1.schema.json +39 -0
  14. package/docs/testing.md +9 -3
  15. package/package.json +1 -1
  16. package/spec/library-scope.md +7 -1
  17. package/src/core/altium/AltiumLayoutParser.mjs +104 -8
  18. package/src/core/altium/AltiumParser.mjs +196 -45
  19. package/src/core/altium/CiArtifactBundleBuilder.mjs +202 -0
  20. package/src/core/altium/DraftsmanDigestParser.mjs +689 -0
  21. package/src/core/altium/EmbeddedFileInventoryBuilder.mjs +255 -0
  22. package/src/core/altium/IntLibModelParser.mjs +240 -0
  23. package/src/core/altium/IntLibStreamExtractor.mjs +366 -0
  24. package/src/core/altium/LibraryRenderManifestBuilder.mjs +417 -0
  25. package/src/core/altium/LibrarySearchIndex.mjs +215 -0
  26. package/src/core/altium/NormalizedModelSchema.mjs +36 -0
  27. package/src/core/altium/ParserCompatibilityFuzzer.mjs +192 -0
  28. package/src/core/altium/PcbCustomPadShapeParser.mjs +244 -0
  29. package/src/core/altium/PcbDefaultsParser.mjs +171 -0
  30. package/src/core/altium/PcbDimensionParser.mjs +229 -0
  31. package/src/core/altium/PcbEmbeddedModelExtractor.mjs +232 -6
  32. package/src/core/altium/PcbExtendedPrimitiveInformationParser.mjs +256 -0
  33. package/src/core/altium/PcbLibModelParser.mjs +235 -14
  34. package/src/core/altium/PcbLibStreamExtractor.mjs +62 -4
  35. package/src/core/altium/PcbMaskPasteResolver.mjs +354 -0
  36. package/src/core/altium/PcbMechanicalLayerPairParser.mjs +204 -0
  37. package/src/core/altium/PcbModelParser.mjs +495 -32
  38. package/src/core/altium/PcbOwnershipGraphBuilder.mjs +245 -0
  39. package/src/core/altium/PcbPadPrimitiveParser.mjs +78 -65
  40. package/src/core/altium/PcbPadStackParser.mjs +229 -2
  41. package/src/core/altium/PcbPickPlacePositionResolver.mjs +224 -0
  42. package/src/core/altium/PcbPrimitiveParameterParser.mjs +3 -2
  43. package/src/core/altium/PcbRawRecordRegistry.mjs +121 -130
  44. package/src/core/altium/PcbRegionPrimitiveParser.mjs +76 -3
  45. package/src/core/altium/PcbRouteAnalysisBuilder.mjs +730 -0
  46. package/src/core/altium/PcbRuleParser.mjs +354 -33
  47. package/src/core/altium/PcbSidecarRecordParser.mjs +177 -0
  48. package/src/core/altium/PcbSpecialStringResolver.mjs +220 -0
  49. package/src/core/altium/PcbStatisticsBuilder.mjs +541 -0
  50. package/src/core/altium/PcbStreamExtractor.mjs +111 -4
  51. package/src/core/altium/PcbTextPrimitiveParser.mjs +60 -0
  52. package/src/core/altium/PcbUnionParser.mjs +307 -0
  53. package/src/core/altium/PcbViaStackParser.mjs +98 -10
  54. package/src/core/altium/PcbViaStructureParser.mjs +335 -0
  55. package/src/core/altium/PrintableTextDecoder.mjs +53 -3
  56. package/src/core/altium/PrjPcbModelParser.mjs +281 -7
  57. package/src/core/altium/ProjectAnnotationParser.mjs +205 -0
  58. package/src/core/altium/ProjectDesignBundleBuilder.mjs +492 -0
  59. package/src/core/altium/ProjectDocumentGraphBuilder.mjs +280 -0
  60. package/src/core/altium/ProjectNetlistExporter.mjs +503 -0
  61. package/src/core/altium/ProjectOutJobDigestBuilder.mjs +109 -0
  62. package/src/core/altium/ProjectVariantViewBuilder.mjs +334 -0
  63. package/src/core/altium/SchematicBindingProvenanceParser.mjs +223 -0
  64. package/src/core/altium/SchematicComponentOwnerTextResolver.mjs +312 -0
  65. package/src/core/altium/SchematicComponentTextResolver.mjs +72 -19
  66. package/src/core/altium/SchematicConnectivityQaBuilder.mjs +271 -0
  67. package/src/core/altium/SchematicCrossSheetConnectorParser.mjs +140 -0
  68. package/src/core/altium/SchematicDirectiveParser.mjs +312 -0
  69. package/src/core/altium/SchematicDisplayModeCatalogParser.mjs +231 -0
  70. package/src/core/altium/SchematicHarnessParser.mjs +302 -0
  71. package/src/core/altium/SchematicImageParser.mjs +474 -3
  72. package/src/core/altium/SchematicImplementationParser.mjs +518 -0
  73. package/src/core/altium/SchematicNetlistBuilder.mjs +15 -2
  74. package/src/core/altium/SchematicOwnershipGraphParser.mjs +195 -0
  75. package/src/core/altium/SchematicPinParser.mjs +84 -1
  76. package/src/core/altium/SchematicPrimitiveParser.mjs +301 -0
  77. package/src/core/altium/SchematicProjectParameterResolver.mjs +361 -0
  78. package/src/core/altium/SchematicQaReportBuilder.mjs +284 -0
  79. package/src/core/altium/SchematicRecordTypeRegistry.mjs +137 -0
  80. package/src/core/altium/SchematicRepeatedChannelParser.mjs +229 -0
  81. package/src/core/altium/SchematicStreamExtractor.mjs +10 -1
  82. package/src/core/altium/SchematicTemplateParser.mjs +256 -0
  83. package/src/core/altium/SchematicTextParser.mjs +123 -0
  84. package/src/core/altium/SvgModelCrossLinkValidator.mjs +402 -0
  85. package/src/core/circuit-json/CircuitJsonModelAdapter.mjs +136 -96
  86. package/src/core/circuit-json/CircuitJsonModelAdapterPcbElements.mjs +244 -0
  87. package/src/core/circuit-json/CircuitJsonModelSchema.mjs +1 -1
  88. package/src/core/ole/OleCompoundDocument.mjs +20 -0
  89. package/src/parser.mjs +35 -0
  90. package/src/styles/altium-renderers.css +19 -0
  91. package/src/ui/PcbBarcodeTextRenderer.mjs +436 -0
  92. package/src/ui/PcbInteractionIndex.mjs +9 -4
  93. package/src/ui/PcbScene3dBuilder.mjs +137 -3
  94. package/src/ui/PcbScene3dModelRegistry.mjs +74 -0
  95. package/src/ui/PcbSvgRenderer.mjs +1252 -34
  96. package/src/ui/PcbTextPrimitiveRenderer.mjs +193 -7
  97. package/src/ui/SchematicNoteRenderer.mjs +9 -2
  98. package/src/ui/SchematicOwnerPinLabelLayout.mjs +206 -0
  99. package/src/ui/SchematicShapeRenderer.mjs +362 -0
  100. package/src/ui/SchematicSvgRenderer.mjs +1442 -92
  101. package/src/ui/SchematicTypography.mjs +48 -5
  102. package/src/ui/TextGeometrySidecarBuilder.mjs +147 -0
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "altium-toolkit.parser-compatibility-fuzz.a1",
4
+ "title": "Altium Toolkit Parser Compatibility Fuzz A1",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": ["schema", "summary", "cases"],
8
+ "properties": {
9
+ "schema": {
10
+ "const": "altium-toolkit.parser-compatibility-fuzz.a1"
11
+ },
12
+ "summary": {
13
+ "type": "object",
14
+ "additionalProperties": true
15
+ },
16
+ "cases": {
17
+ "type": "array",
18
+ "items": {
19
+ "type": "object",
20
+ "additionalProperties": true,
21
+ "required": ["key", "status"]
22
+ }
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,86 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "altium-toolkit.pcb.svg.semantics.a1",
4
+ "title": "Altium Toolkit PCB SVG Semantics A1",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": ["schema", "view", "layers", "elements"],
8
+ "properties": {
9
+ "schema": {
10
+ "const": "altium-toolkit.pcb.svg.semantics.a1"
11
+ },
12
+ "view": {
13
+ "type": "object",
14
+ "additionalProperties": true,
15
+ "properties": {
16
+ "kind": {
17
+ "type": "string"
18
+ },
19
+ "layerSet": {
20
+ "type": "object"
21
+ },
22
+ "board": {
23
+ "type": "object"
24
+ }
25
+ }
26
+ },
27
+ "boardOutline": {
28
+ "type": "object"
29
+ },
30
+ "lookups": {
31
+ "type": "object",
32
+ "additionalProperties": true,
33
+ "properties": {
34
+ "netsByIndex": {
35
+ "type": "object"
36
+ },
37
+ "netIndexByName": {
38
+ "type": "object"
39
+ },
40
+ "netClassesByName": {
41
+ "type": "object"
42
+ },
43
+ "componentsByIndex": {
44
+ "type": "object"
45
+ },
46
+ "componentIndexByDesignator": {
47
+ "type": "object"
48
+ },
49
+ "layersByKey": {
50
+ "type": "object"
51
+ },
52
+ "layerKeyByDisplayName": {
53
+ "type": "object"
54
+ }
55
+ }
56
+ },
57
+ "layers": {
58
+ "type": "array"
59
+ },
60
+ "elements": {
61
+ "type": "array",
62
+ "items": {
63
+ "type": "object",
64
+ "additionalProperties": true,
65
+ "required": ["elementKey", "primitive"],
66
+ "properties": {
67
+ "elementKey": {
68
+ "type": "string"
69
+ },
70
+ "primitive": {
71
+ "type": "string"
72
+ },
73
+ "layerKey": {
74
+ "type": "string"
75
+ },
76
+ "net": {
77
+ "type": "string"
78
+ },
79
+ "component": {
80
+ "type": "string"
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
@@ -0,0 +1,63 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "urn:altium-toolkit:project-bundle:a1",
4
+ "title": "Altium Toolkit Project Bundle A1",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": [
8
+ "schema",
9
+ "kind",
10
+ "project",
11
+ "sheets",
12
+ "components",
13
+ "nets",
14
+ "indexes"
15
+ ],
16
+ "properties": {
17
+ "schema": {
18
+ "const": "urn:altium-toolkit:normalized-model:a1"
19
+ },
20
+ "kind": {
21
+ "const": "design-bundle"
22
+ },
23
+ "project": {
24
+ "type": "object"
25
+ },
26
+ "units": {
27
+ "type": "object",
28
+ "additionalProperties": {
29
+ "type": "string"
30
+ }
31
+ },
32
+ "variants": {
33
+ "type": "array"
34
+ },
35
+ "sheets": {
36
+ "type": "array"
37
+ },
38
+ "components": {
39
+ "type": "array"
40
+ },
41
+ "schematic_hierarchy": {
42
+ "type": "object"
43
+ },
44
+ "pnp": {
45
+ "type": "object"
46
+ },
47
+ "nets": {
48
+ "type": "array"
49
+ },
50
+ "annotations": {
51
+ "type": "object"
52
+ },
53
+ "indexes": {
54
+ "type": "object"
55
+ },
56
+ "bom": {
57
+ "type": "array"
58
+ },
59
+ "effectiveVariant": {
60
+ "type": "object"
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "altium-toolkit.project.document-graph.a1",
4
+ "title": "Altium Toolkit Project Document Graph A1",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": ["schema", "summary", "documents", "groups", "indexes"],
8
+ "properties": {
9
+ "schema": {
10
+ "const": "altium-toolkit.project.document-graph.a1"
11
+ },
12
+ "summary": {
13
+ "type": "object",
14
+ "additionalProperties": true
15
+ },
16
+ "documents": {
17
+ "type": "array",
18
+ "items": {
19
+ "type": "object",
20
+ "additionalProperties": true,
21
+ "required": ["normalizedPath", "kind"]
22
+ }
23
+ },
24
+ "groups": {
25
+ "type": "object",
26
+ "additionalProperties": true
27
+ },
28
+ "indexes": {
29
+ "type": "object",
30
+ "additionalProperties": true
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "altium-toolkit.schematic.svg.semantics.a1",
4
+ "title": "Altium Toolkit Schematic SVG Semantics A1",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": ["schema", "elements"],
8
+ "properties": {
9
+ "schema": {
10
+ "const": "altium-toolkit.schematic.svg.semantics.a1"
11
+ },
12
+ "nets": {
13
+ "type": "array"
14
+ },
15
+ "components": {
16
+ "type": "array"
17
+ },
18
+ "elements": {
19
+ "type": "array",
20
+ "items": {
21
+ "type": "object",
22
+ "additionalProperties": true,
23
+ "required": ["elementKey"],
24
+ "properties": {
25
+ "elementKey": {
26
+ "type": "string"
27
+ },
28
+ "primitive": {
29
+ "type": "string"
30
+ },
31
+ "recordId": {
32
+ "type": "string"
33
+ },
34
+ "component": {
35
+ "type": "string"
36
+ },
37
+ "componentUniqueId": {
38
+ "type": "string"
39
+ },
40
+ "net": {
41
+ "type": "string"
42
+ },
43
+ "pin": {
44
+ "type": "string"
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "altium-toolkit.svg-model-cross-link.a1",
4
+ "title": "Altium Toolkit SVG Model Cross-Link A1",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": [
8
+ "schema",
9
+ "documentKind",
10
+ "summary",
11
+ "missingElements",
12
+ "orphanElements",
13
+ "unresolvedReferences"
14
+ ],
15
+ "properties": {
16
+ "schema": {
17
+ "const": "altium-toolkit.svg-model-cross-link.a1"
18
+ },
19
+ "documentKind": {
20
+ "enum": ["schematic", "pcb", "unknown"]
21
+ },
22
+ "summary": {
23
+ "type": "object",
24
+ "additionalProperties": true
25
+ },
26
+ "missingElements": {
27
+ "type": "array"
28
+ },
29
+ "orphanElements": {
30
+ "type": "array"
31
+ },
32
+ "unresolvedReferences": {
33
+ "type": "array"
34
+ },
35
+ "metadata": {
36
+ "type": "object"
37
+ }
38
+ }
39
+ }
package/docs/testing.md CHANGED
@@ -16,10 +16,11 @@ The tests cover:
16
16
 
17
17
  - Binary and OLE helpers
18
18
  - Printable and binary Altium parser recovery for `.SchDoc`, `.PcbDoc`,
19
- `.PcbLib`, and `.PrjPcb` entrypoints
19
+ `.PcbLib`, `.PrjPcb`, and `.IntLib` entrypoints
20
20
  - PCB primitive stream slicing and focused decoders for tracks, fills, arcs,
21
21
  vias, pads, text, regions, rules, raw records, board regions, ownership
22
- indexes, sidecar PrimitiveParameters/Text tables, and embedded font metadata
22
+ indexes, sidecar PrimitiveParameters/Text tables, extended primitive
23
+ information, custom pad shapes, union metadata, and embedded font metadata
23
24
  - Obfuscated fake schematic and PCB fixture shards
24
25
  - Schematic SVG, side-resolved PCB SVG, BOM HTML, and static 3D summary
25
26
  renderers
@@ -27,4 +28,9 @@ The tests cover:
27
28
 
28
29
  Fixture data must remain repo-owned and obfuscated. Do not add native provided
29
30
  Altium files, real customer identifiers, real vendor identifiers, or
30
- source-descriptive fixture names.
31
+ source-descriptive fixture names. The machine-readable
32
+ `tests/fixtures/fixture-manifest.json` catalog tracks synthetic fixture coverage
33
+ areas and must keep `assetPolicy` set to `repo-owned-synthetic-only`. Each
34
+ fixture entry records `source: inline-synthetic-records` plus expected parser,
35
+ SVG, schema, and diagnostic contracts so tests can catch drift between fake
36
+ fixtures and public read-model coverage.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "altium-toolkit",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "Altium document parsing and non-interactive rendering utilities",
5
5
  "keywords": [
6
6
  "altium",
@@ -11,7 +11,8 @@ rendering primitives.
11
11
 
12
12
  ## In Scope
13
13
 
14
- - `.SchDoc`, `.PcbDoc`, `.PcbLib`, and `.PrjPcb` parsing from `ArrayBuffer`
14
+ - `.SchDoc`, `.PcbDoc`, `.PcbLib`, `.PrjPcb`, and `.IntLib` parsing from
15
+ `ArrayBuffer`
15
16
  - OLE and binary stream helpers needed by parser recovery
16
17
  - Schematic SVG rendering
17
18
  - PCB SVG rendering
@@ -22,6 +23,9 @@ rendering primitives.
22
23
  SVG rendering
23
24
  - Read-only PCB primitive record registry metadata and base64 raw-record
24
25
  preservation for unsupported or partially decoded PcbDoc/PcbLib streams
26
+ - Read-only PCB pad/via detail recovery, including hole tolerances,
27
+ mask/paste semantics, stack metadata, via-protection sidecars, custom pad
28
+ shape links, and PCB union metadata
25
29
  - Static 3D summary HTML
26
30
  - Parser worker entrypoint for host applications
27
31
  - Optional renderer CSS
@@ -37,3 +41,5 @@ rendering primitives.
37
41
  - STEP mesh loading and browser script injection
38
42
  - Model ZIP export UI and download orchestration
39
43
  - Server, deployment, and app metadata endpoints
44
+ - Native document authoring, round-trip writing, GUI automation, and compiled
45
+ multi-sheet project netlist generation
@@ -114,19 +114,115 @@ export class AltiumLayoutParser {
114
114
  if (!match) continue
115
115
 
116
116
  const index = Number.parseInt(match[1], 10)
117
- layers.push({
118
- index,
119
- name: getField(fields, key),
120
- layerId: parseNumericField(
121
- fields,
122
- 'V9_STACK_LAYER' + index + '_LAYERID'
123
- )
124
- })
117
+ layers.push(
118
+ AltiumLayoutParser.#stripUndefined({
119
+ index,
120
+ name: getField(fields, key),
121
+ layerId: parseNumericField(
122
+ fields,
123
+ 'V9_STACK_LAYER' + index + '_LAYERID'
124
+ ),
125
+ kind: AltiumLayoutParser.#firstLayerStackTextField(
126
+ fields,
127
+ index,
128
+ ['KIND', 'TYPE', 'ROLE']
129
+ ),
130
+ material: AltiumLayoutParser.#firstLayerStackTextField(
131
+ fields,
132
+ index,
133
+ ['MATERIAL', 'MATERIALNAME']
134
+ ),
135
+ thicknessMil:
136
+ AltiumLayoutParser.#firstLayerStackNumericField(
137
+ fields,
138
+ index,
139
+ ['THICKNESS', 'DIELECTRICTHICKNESS']
140
+ ),
141
+ copperThicknessMil:
142
+ AltiumLayoutParser.#firstLayerStackNumericField(
143
+ fields,
144
+ index,
145
+ ['COPPERTHICKNESS', 'COPPER_THICKNESS']
146
+ ),
147
+ copperWeight: AltiumLayoutParser.#firstLayerStackTextField(
148
+ fields,
149
+ index,
150
+ ['COPPERWEIGHT', 'COPPER_WEIGHT']
151
+ ),
152
+ dielectricConstant:
153
+ AltiumLayoutParser.#firstLayerStackNumericField(
154
+ fields,
155
+ index,
156
+ ['DK', 'DIELECTRICCONSTANT', 'DIELECTRIC_CONSTANT']
157
+ ),
158
+ dissipationFactor:
159
+ AltiumLayoutParser.#firstLayerStackNumericField(
160
+ fields,
161
+ index,
162
+ ['DF', 'DISSIPATIONFACTOR', 'DISSIPATION_FACTOR']
163
+ )
164
+ })
165
+ )
125
166
  }
126
167
 
127
168
  return layers.sort((left, right) => left.index - right.index)
128
169
  }
129
170
 
171
+ /**
172
+ * Reads the first non-empty text field from a layer-stack entry.
173
+ * @param {Record<string, string | string[]>} fields Source fields.
174
+ * @param {number} index Layer-stack index.
175
+ * @param {string[]} suffixes Candidate suffixes.
176
+ * @returns {string | undefined}
177
+ */
178
+ static #firstLayerStackTextField(fields, index, suffixes) {
179
+ for (const suffix of suffixes) {
180
+ const value = getField(
181
+ fields,
182
+ 'V9_STACK_LAYER' + index + '_' + suffix
183
+ )
184
+ if (value) {
185
+ return value
186
+ }
187
+ }
188
+
189
+ return undefined
190
+ }
191
+
192
+ /**
193
+ * Reads the first finite numeric field from a layer-stack entry.
194
+ * @param {Record<string, string | string[]>} fields Source fields.
195
+ * @param {number} index Layer-stack index.
196
+ * @param {string[]} suffixes Candidate suffixes.
197
+ * @returns {number | undefined}
198
+ */
199
+ static #firstLayerStackNumericField(fields, index, suffixes) {
200
+ for (const suffix of suffixes) {
201
+ const value = parseNumericField(
202
+ fields,
203
+ 'V9_STACK_LAYER' + index + '_' + suffix
204
+ )
205
+ if (value !== null) {
206
+ return value
207
+ }
208
+ }
209
+
210
+ return undefined
211
+ }
212
+
213
+ /**
214
+ * Removes undefined object values for stable parser output.
215
+ * @param {object} value Source object.
216
+ * @returns {object}
217
+ */
218
+ static #stripUndefined(value) {
219
+ return Object.fromEntries(
220
+ Object.entries(value).filter(
221
+ ([, entryValue]) => entryValue !== undefined
222
+ )
223
+ )
224
+ }
225
+
130
226
  /**
131
227
  * Extracts legacy primitive-layer names keyed by the numeric layer IDs used
132
228
  * by decoded binary track and fill streams.