Wire up ADS submodule, codegen, runtime path aliases (no behavioral swap yet)#445
Wire up ADS submodule, codegen, runtime path aliases (no behavioral swap yet)#445kevinelliott wants to merge 6 commits into
Conversation
…wap yet)
Sets the foundation for the cross-language Airframes Decoder Spec (ADS)
unification by integrating airframes-decoder into this repo as a git
submodule, without yet replacing any hand-written plugins. Behavior is
identical to master after this PR.
What this PR does:
- Add `vendor/airframes-decoder` as a git submodule (pinned to its
init/ads-v1 branch).
- Add tsconfig path aliases (`@airframes/ads-runtime-ts` and friends)
resolving into the submodule's runtimes/typescript/.
- Add npm scripts:
npm run ads:codegen-build — build the codegen tool
npm run ads:generate — emit lib/plugins/generated/*.ts from spec
npm run ads:check — fail if generated tree is out-of-date
- Generate the 68 plugins into lib/plugins/generated/ and commit them
(avoids requiring the codegen toolchain in every contributor's env).
- Exclude vendor/ and lib/plugins/generated/ from ESLint.
- Exclude vendor/ from Jest test discovery.
- Add .github/workflows/ads-check.yml that calls the central reusable
`codegen-check.yml` workflow (single source of CI logic across repos).
What this PR does NOT do (intentionally — separate Stage 2.5 PR):
- Does NOT register generated plugins in MessageDecoder.ts. The current
emitter double-bookkeeps `raw` fields (field assignments + formatter
writes), which would diverge from existing test expectations. Resolving
this needs an emitter design pass (track which raw keys the formatter
owns, suppress auto-emit in those cases) before a behavioral swap
is safe.
- Does NOT remove the original lib/utils/*.ts helpers yet. The runtime
is duplicated between this repo and the submodule until Stage 2.5
swaps imports.
Verification:
- All 407 existing tests pass.
- `npm run ads:generate` produces 68 .ts files with no diff vs committed.
- Generated files compile against `@airframes/ads-runtime-ts` path
aliases (resolution verified via tsc paths).
See airframesio/acars-decoder#1 for the central spec, codegen, runtimes,
docs, and 288-sample corpus this submodule references.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 15 minutes and 36 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (11)
📒 Files selected for processing (66)
WalkthroughAdds a vendored ADS decoder submodule, configures TypeScript path mappings, excludes vendor/generated code from lint/tests, adds npm scripts for ADS codegen, wires generated label plugins into the decoder, and adds a GitHub Actions workflow to validate generated artifacts. ChangesADS Decoder Submodule Integration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1 | ||
| with: | ||
| language: ts | ||
| generated-path: lib/plugins/generated | ||
| spec-path: vendor/airframes-decoder/spec | ||
| codegen-path: vendor/airframes-decoder/codegen |
|
|
||
| import { DecoderPlugin } from "@airframes/ads-runtime-ts"; | ||
| import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts"; | ||
| import { ResultFormatter } from "@airframes/ads-runtime-ts"; |
| import { DecoderPlugin } from "@airframes/ads-runtime-ts"; | ||
| import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts"; | ||
| import { ResultFormatter } from "@airframes/ads-runtime-ts"; | ||
| import * as helpers from "@airframes/ads-runtime-ts/helpers"; |
|
|
||
| import { DecoderPlugin } from "@airframes/ads-runtime-ts"; | ||
| import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts"; | ||
| import { ResultFormatter } from "@airframes/ads-runtime-ts"; |
| import { DecoderPlugin } from "@airframes/ads-runtime-ts"; | ||
| import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts"; | ||
| import { ResultFormatter } from "@airframes/ads-runtime-ts"; | ||
| import * as helpers from "@airframes/ads-runtime-ts/helpers"; |
|
|
||
| import { DecoderPlugin } from "@airframes/ads-runtime-ts"; | ||
| import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts"; | ||
| import { ResultFormatter } from "@airframes/ads-runtime-ts"; |
| import { DecoderPlugin } from "@airframes/ads-runtime-ts"; | ||
| import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts"; | ||
| import { ResultFormatter } from "@airframes/ads-runtime-ts"; | ||
| import * as helpers from "@airframes/ads-runtime-ts/helpers"; |
|
|
||
| import { DecoderPlugin } from "@airframes/ads-runtime-ts"; | ||
| import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts"; | ||
| import { ResultFormatter } from "@airframes/ads-runtime-ts"; |
| import { DecoderPlugin } from "@airframes/ads-runtime-ts"; | ||
| import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts"; | ||
| import { ResultFormatter } from "@airframes/ads-runtime-ts"; | ||
| import * as helpers from "@airframes/ads-runtime-ts/helpers"; |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c3d7008546
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts"; | ||
| import { ResultFormatter } from "@airframes/ads-runtime-ts"; | ||
| import * as helpers from "@airframes/ads-runtime-ts/helpers"; | ||
| import * as hatches from "../escape_hatches"; |
There was a problem hiding this comment.
Import the generated escape hatches from an existing module
When any generated plugin is type-checked or imported, this relative import resolves to lib/plugins/escape_hatches, but this commit does not add that module (a repo search for escape_hatches only finds these generated imports). The new generated tree is included by tsconfig.json, so consumers running a project type-check or later wiring these plugins into the decoder will hit a missing-module error before the generated plugins can be used.
Useful? React with 👍 / 👎.
| "test": "jest", | ||
| "ads:codegen-build": "cd vendor/airframes-decoder/codegen && npm install && npm run build", | ||
| "ads:generate": "node vendor/airframes-decoder/codegen/dist/cli.js generate --target ts --spec vendor/airframes-decoder/spec --out lib/plugins/generated", | ||
| "ads:check": "git diff --exit-code -- lib/plugins/generated || (echo 'lib/plugins/generated is out of date. Run npm run ads:generate and commit.' && exit 1)" |
There was a problem hiding this comment.
Run generation before diffing in ads:check
In a clean checkout where the ADS spec/submodule was changed but lib/plugins/generated was not regenerated, this command only checks for an existing uncommitted diff and exits successfully. That means npm run ads:check can pass with stale committed generated files, contrary to the script's stated purpose; it needs to run the generator (or invoke a check mode that does) before git diff --exit-code.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
This PR lays the groundwork for adopting the shared “ADS” decoder spec/codegen by adding a vendored airframesio/acars-decoder submodule, wiring TypeScript path aliases to the vendored TS runtime, and committing the generated plugin sources so builds/tests don’t require running codegen.
Changes:
- Add
vendor/airframes-decoderas a git submodule and introduce TS path aliases for the ADS TS runtime. - Add npm scripts to build/run/check ADS codegen output and commit
lib/plugins/generated/*to the repo. - Update ESLint/Jest config to ignore vendored and generated sources, and add a CI workflow to verify generated output is up-to-date.
Reviewed changes
Copilot reviewed 5 out of 75 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.json | Adds baseUrl/paths for ADS runtime and excludes vendor from compilation inputs. |
| package.json | Adds ADS codegen build/generate/check scripts. |
| jest.config.ts | Ignores tests under vendor/. |
| eslint.config.mts | Ignores vendor/** and lib/plugins/generated/**. |
| .gitmodules | Adds vendor/airframes-decoder submodule reference. |
| .github/workflows/ads-check.yml | Adds CI job to verify generated tree matches the spec. |
| lib/plugins/generated/ARINC_702.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/CBand.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_10_LDR.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_10_POS.ts | Adds generated plugin implementation. |
| lib/plugins/generated/Label_10_Slash.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_12_N_Space.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_12_POS.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_13Through18_Slash.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_15.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_15_FST.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_16_AUTPOS.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_16_Honeywell.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_16_N_Space.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_16_POSA1.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_16_TOD.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_1L_070.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_1L_3Line.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_1L_660.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_1L_Slash.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_1M_Slash.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_20_CFB01.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_20_POS.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_21_POS.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_22_OFF.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_22_POS.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_24_Slash.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_2P_FM3.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_2P_FM4.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_2P_FM5.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_30_Slash_EA.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_44_Slash.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_44_POS.ts | Adds generated plugin implementation. |
| lib/plugins/generated/Label_44_ON.ts | Adds generated plugin implementation. |
| lib/plugins/generated/Label_44_OFF.ts | Adds generated plugin implementation. |
| lib/plugins/generated/Label_44_IN.ts | Adds generated plugin implementation. |
| lib/plugins/generated/Label_44_ETA.ts | Adds generated plugin implementation. |
| lib/plugins/generated/Label_4A.ts | Adds generated plugin implementation. |
| lib/plugins/generated/Label_4A_01.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_4A_Slash_01.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_4A_DOOR.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_4A_DIS.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_4N.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_4T_AGFSR.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_4T_ETA.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_58.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_5Z_Slash.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_80.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_83.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_8E.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_B6_Forwardslash.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_ColonComma.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_H1_ATIS.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_H1_EZF.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_H1_FLR.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_H1_M_POS.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_H1_OFP.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_H1_OHMA.ts | Adds generated plugin implementation. |
| lib/plugins/generated/Label_H1_Paren.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_H1_StarPOS.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_H1_WRN.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_H2_02E.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_HX.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_MA.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_QP.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_QQ.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_QR.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_QS.ts | Adds generated plugin wrapper. |
| lib/plugins/generated/Label_SQ.ts | Adds generated plugin wrapper. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "ads:codegen-build": "cd vendor/airframes-decoder/codegen && npm install && npm run build", | ||
| "ads:generate": "node vendor/airframes-decoder/codegen/dist/cli.js generate --target ts --spec vendor/airframes-decoder/spec --out lib/plugins/generated", | ||
| "ads:check": "git diff --exit-code -- lib/plugins/generated || (echo 'lib/plugins/generated is out of date. Run npm run ads:generate and commit.' && exit 1)" |
| jobs: | ||
| ads-generated-up-to-date: | ||
| uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1 | ||
| with: |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
package.json (1)
19-19: ⚡ Quick winPrefer
npm cifor reproducible codegen builds.Using
npm installmay produce non-deterministic builds ifpackage-lock.jsonis out of sync. Since this installs dependencies for the vendored codegen tool,npm ciwill enforce the lockfile and fail fast if it's stale.♻️ Proposed fix
- "ads:codegen-build": "cd vendor/airframes-decoder/codegen && npm install && npm run build", + "ads:codegen-build": "cd vendor/airframes-decoder/codegen && npm ci && npm run build",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@package.json` at line 19, Replace the npm install call in the npm script "ads:codegen-build" (which runs in vendor/airframes-decoder/codegen) with npm ci so the vendored codegen build uses the lockfile for reproducible installs and fails fast if the lockfile is stale; update the script invocation to run npm ci && npm run build instead of npm install && npm run build.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/ads-check.yml:
- Around line 10-16: The workflow job ads-generated-up-to-date is missing an
explicit permissions block and currently inherits default GITHUB_TOKEN rights;
add a minimal permissions section to the workflow (at the top-level of the job
or workflow) granting only what the reusable workflow needs—e.g., permissions:
contents: read—so the codegen-check invocation (uses:
airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1) runs
with least privilege.
- Line 11: Update the reusable workflow reference used by the
ads-generated-up-to-date job (the line using
airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1) to
pin it to the specific commit SHA provided in the review and replace the branch
ref with that SHA; also add an explicit permissions: block (either at workflow
top or inside the ads-generated-up-to-date job) that scopes GITHUB_TOKEN to the
minimum required permissions for the codegen check so the workflow no longer
relies on default, broad token scopes.
In `@jest.config.ts`:
- Around line 162-165: The string literals in the Jest config's
testPathIgnorePatterns array use double quotes which conflicts with the
project's Prettier single-quote rule; update the array entries (the values
within testPathIgnorePatterns) to use single quotes (e.g., '/node_modules/' and
'/vendor/') so formatting/linting passes, leaving the rest of the
testPathIgnorePatterns property and its comments unchanged.
In `@tsconfig.json`:
- Line 5: tsconfig.json's compilerOptions.paths mapping for the alias
"`@airframes/ads-runtime-ts`" points to non-existent targets; update the paths
entry so each key under "compilerOptions.paths" for "`@airframes/ads-runtime-ts`"
(and any subpaths like "`@airframes/ads-runtime-ts/`*") points to the actual
TypeScript source file locations (for example the real index, helpers, and
escape_hatches files in the repo) instead of
"vendor/airframes-decoder/runtimes/typescript/index.ts",
"vendor/airframes-decoder/runtimes/typescript/helpers.ts", and
"vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts"; locate
and replace those target strings in the tsconfig.json paths section so
TypeScript can resolve imports of `@airframes/ads-runtime-ts` correctly.
---
Nitpick comments:
In `@package.json`:
- Line 19: Replace the npm install call in the npm script "ads:codegen-build"
(which runs in vendor/airframes-decoder/codegen) with npm ci so the vendored
codegen build uses the lockfile for reproducible installs and fails fast if the
lockfile is stale; update the script invocation to run npm ci && npm run build
instead of npm install && npm run build.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 7f552c64-d4d6-4287-bee0-24d3f64f2f3a
⛔ Files ignored due to path filters (68)
lib/plugins/generated/ARINC_702.tsis excluded by!**/generated/**lib/plugins/generated/CBand.tsis excluded by!**/generated/**lib/plugins/generated/Label_10_LDR.tsis excluded by!**/generated/**lib/plugins/generated/Label_10_POS.tsis excluded by!**/generated/**lib/plugins/generated/Label_10_Slash.tsis excluded by!**/generated/**lib/plugins/generated/Label_12_N_Space.tsis excluded by!**/generated/**lib/plugins/generated/Label_12_POS.tsis excluded by!**/generated/**lib/plugins/generated/Label_13Through18_Slash.tsis excluded by!**/generated/**lib/plugins/generated/Label_15.tsis excluded by!**/generated/**lib/plugins/generated/Label_15_FST.tsis excluded by!**/generated/**lib/plugins/generated/Label_16_AUTPOS.tsis excluded by!**/generated/**lib/plugins/generated/Label_16_Honeywell.tsis excluded by!**/generated/**lib/plugins/generated/Label_16_N_Space.tsis excluded by!**/generated/**lib/plugins/generated/Label_16_POSA1.tsis excluded by!**/generated/**lib/plugins/generated/Label_16_TOD.tsis excluded by!**/generated/**lib/plugins/generated/Label_1L_070.tsis excluded by!**/generated/**lib/plugins/generated/Label_1L_3Line.tsis excluded by!**/generated/**lib/plugins/generated/Label_1L_660.tsis excluded by!**/generated/**lib/plugins/generated/Label_1L_Slash.tsis excluded by!**/generated/**lib/plugins/generated/Label_1M_Slash.tsis excluded by!**/generated/**lib/plugins/generated/Label_20_CFB01.tsis excluded by!**/generated/**lib/plugins/generated/Label_20_POS.tsis excluded by!**/generated/**lib/plugins/generated/Label_21_POS.tsis excluded by!**/generated/**lib/plugins/generated/Label_22_OFF.tsis excluded by!**/generated/**lib/plugins/generated/Label_22_POS.tsis excluded by!**/generated/**lib/plugins/generated/Label_24_Slash.tsis excluded by!**/generated/**lib/plugins/generated/Label_2P_FM3.tsis excluded by!**/generated/**lib/plugins/generated/Label_2P_FM4.tsis excluded by!**/generated/**lib/plugins/generated/Label_2P_FM5.tsis excluded by!**/generated/**lib/plugins/generated/Label_30_Slash_EA.tsis excluded by!**/generated/**lib/plugins/generated/Label_44_ETA.tsis excluded by!**/generated/**lib/plugins/generated/Label_44_IN.tsis excluded by!**/generated/**lib/plugins/generated/Label_44_OFF.tsis excluded by!**/generated/**lib/plugins/generated/Label_44_ON.tsis excluded by!**/generated/**lib/plugins/generated/Label_44_POS.tsis excluded by!**/generated/**lib/plugins/generated/Label_44_Slash.tsis excluded by!**/generated/**lib/plugins/generated/Label_4A.tsis excluded by!**/generated/**lib/plugins/generated/Label_4A_01.tsis excluded by!**/generated/**lib/plugins/generated/Label_4A_DIS.tsis excluded by!**/generated/**lib/plugins/generated/Label_4A_DOOR.tsis excluded by!**/generated/**lib/plugins/generated/Label_4A_Slash_01.tsis excluded by!**/generated/**lib/plugins/generated/Label_4N.tsis excluded by!**/generated/**lib/plugins/generated/Label_4T_AGFSR.tsis excluded by!**/generated/**lib/plugins/generated/Label_4T_ETA.tsis excluded by!**/generated/**lib/plugins/generated/Label_58.tsis excluded by!**/generated/**lib/plugins/generated/Label_5Z_Slash.tsis excluded by!**/generated/**lib/plugins/generated/Label_80.tsis excluded by!**/generated/**lib/plugins/generated/Label_83.tsis excluded by!**/generated/**lib/plugins/generated/Label_8E.tsis excluded by!**/generated/**lib/plugins/generated/Label_B6_Forwardslash.tsis excluded by!**/generated/**lib/plugins/generated/Label_ColonComma.tsis excluded by!**/generated/**lib/plugins/generated/Label_H1_ATIS.tsis excluded by!**/generated/**lib/plugins/generated/Label_H1_EZF.tsis excluded by!**/generated/**lib/plugins/generated/Label_H1_FLR.tsis excluded by!**/generated/**lib/plugins/generated/Label_H1_M_POS.tsis excluded by!**/generated/**lib/plugins/generated/Label_H1_OFP.tsis excluded by!**/generated/**lib/plugins/generated/Label_H1_OHMA.tsis excluded by!**/generated/**lib/plugins/generated/Label_H1_Paren.tsis excluded by!**/generated/**lib/plugins/generated/Label_H1_StarPOS.tsis excluded by!**/generated/**lib/plugins/generated/Label_H1_WRN.tsis excluded by!**/generated/**lib/plugins/generated/Label_H2_02E.tsis excluded by!**/generated/**lib/plugins/generated/Label_HX.tsis excluded by!**/generated/**lib/plugins/generated/Label_MA.tsis excluded by!**/generated/**lib/plugins/generated/Label_QP.tsis excluded by!**/generated/**lib/plugins/generated/Label_QQ.tsis excluded by!**/generated/**lib/plugins/generated/Label_QR.tsis excluded by!**/generated/**lib/plugins/generated/Label_QS.tsis excluded by!**/generated/**lib/plugins/generated/Label_SQ.tsis excluded by!**/generated/**
📒 Files selected for processing (7)
.github/workflows/ads-check.yml.gitmoduleseslint.config.mtsjest.config.tspackage.jsontsconfig.jsonvendor/airframes-decoder
| ads-generated-up-to-date: | ||
| uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1 | ||
| with: | ||
| language: ts | ||
| generated-path: lib/plugins/generated | ||
| spec-path: vendor/airframes-decoder/spec | ||
| codegen-path: vendor/airframes-decoder/codegen |
There was a problem hiding this comment.
Add an explicit permissions block.
The workflow inherits default GITHUB_TOKEN permissions, which may be broader than required. For a validation-only workflow that runs codegen checks, read-only access should suffice.
🛡️ Proposed fix to add minimal permissions
jobs:
ads-generated-up-to-date:
+ permissions:
+ contents: read
uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1Adjust permissions based on what the reusable workflow actually requires. If it only validates generated code, contents: read should be sufficient.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ads-generated-up-to-date: | |
| uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1 | |
| with: | |
| language: ts | |
| generated-path: lib/plugins/generated | |
| spec-path: vendor/airframes-decoder/spec | |
| codegen-path: vendor/airframes-decoder/codegen | |
| ads-generated-up-to-date: | |
| permissions: | |
| contents: read | |
| uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1 | |
| with: | |
| language: ts | |
| generated-path: lib/plugins/generated | |
| spec-path: vendor/airframes-decoder/spec | |
| codegen-path: vendor/airframes-decoder/codegen |
🧰 Tools
🪛 GitHub Check: CodeQL
[warning] 11-16: Workflow does not contain permissions
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {{}}
🪛 zizmor (1.25.2)
[warning] 10-17: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block
(excessive-permissions)
[error] 11-11: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/ads-check.yml around lines 10 - 16, The workflow job
ads-generated-up-to-date is missing an explicit permissions block and currently
inherits default GITHUB_TOKEN rights; add a minimal permissions section to the
workflow (at the top-level of the job or workflow) granting only what the
reusable workflow needs—e.g., permissions: contents: read—so the codegen-check
invocation (uses:
airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1) runs
with least privilege.
|
|
||
| jobs: | ||
| ads-generated-up-to-date: | ||
| uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Get the commit SHA for the init/ads-v1 branch
gh api repos/airframesio/acars-decoder/git/ref/heads/init/ads-v1 --jq '.object.sha'Repository: airframesio/acars-decoder-typescript
Length of output: 121
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the workflow content around the referenced `uses:` line and top-level permissions
echo "=== File head (with line numbers) ==="
nl -ba .github/workflows/ads-check.yml | head -n 120
echo
echo "=== Grep for permissions/use blocks ==="
rg -n "^[[:space:]]*permissions:|^[[:space:]]*uses:" .github/workflows/ads-check.yml || trueRepository: airframesio/acars-decoder-typescript
Length of output: 179
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Confirm file exists ==="
ls -la .github/workflows/ads-check.yml
echo
echo "=== File head (with line numbers) ==="
cat -n .github/workflows/ads-check.yml | head -n 120
echo
echo "=== Grep for permissions/use blocks ==="
rg -n "^[[:space:]]*permissions:|^[[:space:]]*uses:" .github/workflows/ads-check.yml || true
echo
echo "=== Show lines around uses: (approx) ==="
# Show a reasonable window around the reported uses line
sed -n '1,80p' .github/workflows/ads-check.ymlRepository: airframesio/acars-decoder-typescript
Length of output: 1299
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Full file ==="
cat -n .github/workflows/ads-check.ymlRepository: airframesio/acars-decoder-typescript
Length of output: 605
Pin the reusable workflow to a commit SHA.
.github/workflows/ads-check.yml (job ads-generated-up-to-date) currently calls codegen-check.yml via a branch ref (@init/ads-v1), which is a supply-chain risk. Pin it to the current commit for that ref:
uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@6da198f085a6ae56eb0291fe938c239aef8faa93Also add an explicit permissions: block (workflow- or job-level) to scope GITHUB_TOKEN to the minimum required; this workflow currently has no permissions: configured.
🧰 Tools
🪛 GitHub Check: CodeQL
[warning] 11-16: Workflow does not contain permissions
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {{}}
🪛 zizmor (1.25.2)
[error] 11-11: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/ads-check.yml at line 11, Update the reusable workflow
reference used by the ads-generated-up-to-date job (the line using
airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1) to
pin it to the specific commit SHA provided in the review and replace the branch
ref with that SHA; also add an explicit permissions: block (either at workflow
top or inside the ads-generated-up-to-date job) that scopes GITHUB_TOKEN to the
minimum required permissions for the codegen check so the workflow no longer
relies on default, broad token scopes.
| testPathIgnorePatterns: [ | ||
| "/node_modules/", | ||
| "/vendor/", // skip vendored airframes-decoder submodule's tests | ||
| ], |
There was a problem hiding this comment.
Fix quote style to match Prettier configuration.
The string literals use double quotes, but Prettier is configured to enforce single quotes. This will cause the build to fail or require a formatting pass.
🎨 Proposed fix
testPathIgnorePatterns: [
- "/node_modules/",
- "/vendor/", // skip vendored airframes-decoder submodule's tests
+ '/node_modules/',
+ '/vendor/', // skip vendored airframes-decoder submodule's tests
],📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| testPathIgnorePatterns: [ | |
| "/node_modules/", | |
| "/vendor/", // skip vendored airframes-decoder submodule's tests | |
| ], | |
| testPathIgnorePatterns: [ | |
| '/node_modules/', | |
| '/vendor/', // skip vendored airframes-decoder submodule's tests | |
| ], |
🧰 Tools
🪛 ESLint
[error] 163-163: Replace "/node_modules/" with '/node_modules/'
(prettier/prettier)
[error] 164-164: Replace "/vendor/" with '/vendor/'
(prettier/prettier)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@jest.config.ts` around lines 162 - 165, The string literals in the Jest
config's testPathIgnorePatterns array use double quotes which conflicts with the
project's Prettier single-quote rule; update the array entries (the values
within testPathIgnorePatterns) to use single quotes (e.g., '/node_modules/' and
'/vendor/') so formatting/linting passes, leaving the rest of the
testPathIgnorePatterns property and its comments unchanged.
| "compilerOptions": { | ||
| "target": "esNext", | ||
| "module": "commonjs", | ||
| "moduleResolution": "node", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Verify that all TypeScript path mappings point to existing files
echo "Checking `@airframes/ads-runtime-ts` path mappings..."
files=(
"vendor/airframes-decoder/runtimes/typescript/index.ts"
"vendor/airframes-decoder/runtimes/typescript/helpers.ts"
"vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts"
)
missing=0
for file in "${files[@]}"; do
if [[ -f "$file" ]]; then
echo "✓ $file"
else
echo "✗ MISSING: $file"
missing=$((missing + 1))
fi
done
if [[ $missing -eq 0 ]]; then
echo "All path mappings verified."
else
echo "ERROR: $missing file(s) missing."
exit 1
fiRepository: airframesio/acars-decoder-typescript
Length of output: 370
Fix tsconfig.json compilerOptions.paths targets for @airframes/ads-runtime-ts — the mappings point to missing files (vendor/airframes-decoder/runtimes/typescript/index.ts, helpers.ts, and escape_hatches/index.ts), so TypeScript will fail to resolve these aliases anywhere they’re imported.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tsconfig.json` at line 5, tsconfig.json's compilerOptions.paths mapping for
the alias "`@airframes/ads-runtime-ts`" points to non-existent targets; update the
paths entry so each key under "compilerOptions.paths" for
"`@airframes/ads-runtime-ts`" (and any subpaths like
"`@airframes/ads-runtime-ts/`*") points to the actual TypeScript source file
locations (for example the real index, helpers, and escape_hatches files in the
repo) instead of "vendor/airframes-decoder/runtimes/typescript/index.ts",
"vendor/airframes-decoder/runtimes/typescript/helpers.ts", and
"vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts"; locate
and replace those target strings in the tsconfig.json paths section so
TypeScript can resolve imports of `@airframes/ads-runtime-ts` correctly.
There was a problem hiding this comment.
Thanks for wiring up the ADS submodule/codegen path. I think this needs another pass before merge because the generated tree is not currently reproducible or type-safe once exercised.
What I ran:
npm cifailed with an existing@typescript-eslintpeer-resolution conflict, so I installed withnpm ci --legacy-peer-depsto continue review.npm run buildpassed.npm test -- --runInBandpassed.npm run ads:codegen-buildpassed.npm run ads:generaterewrote every generated file header from the author’s local absolute path to the checkout path, andnpm run ads:checkthen failed.npx tsc --noEmitfails; many failures are pre-existing test/source strictness issues, but the newlib/plugins/generated/**files also add errors such as missing../escape_hatches, invalidResultFormatter.fuel(...), and block-scoped variables used out of scope.
The current package build passes mostly because the generated files are not imported/exported yet. Since this PR is establishing the generated source and tooling foundation, I’d fix these now so the next PR does not inherit a generated tree that cannot be regenerated or imported cleanly.
Sent by Cursor Automation: acars-decoder-typescript: PR Review
| @@ -0,0 +1,40 @@ | |||
| // AUTO-GENERATED from /Users/kevin/Cloud/Dropbox/work/airframes/acars-decoder-typescript/vendor/airframes-decoder/spec/labels/10/POS.yaml. Do not edit. | |||
There was a problem hiding this comment.
This generated header embeds the author’s absolute local path. That makes the generated tree non-reproducible: after npm run ads:codegen-build && npm run ads:generate in this checkout, every generated file changed only from /Users/kevin/... to /workspace/..., and npm run ads:check then failed.
Please make the generator emit a stable path, usually repo-relative to the spec root (or omit the source path entirely), then regenerate and commit the stable output. Otherwise the new CI check will fail or create noise for every contributor whose checkout path differs.
| import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts"; | ||
| import { ResultFormatter } from "@airframes/ads-runtime-ts"; | ||
| import * as helpers from "@airframes/ads-runtime-ts/helpers"; | ||
| import * as hatches from "../escape_hatches"; |
There was a problem hiding this comment.
All generated plugins import ../escape_hatches, but this PR does not add lib/plugins/escape_hatches or otherwise make that relative module resolvable. A full type-check reports TS2307: Cannot find module '../escape_hatches' for each generated file.
Even plugins that do not call any hatch import it unconditionally, so this blocks importing any generated plugin. Either emit this import only when needed and point it at a real module, or add the local escape-hatch module with the functions the specs require.
| ResultFormatter.timestamp(result, day); | ||
| ResultFormatter.timestamp(result, timestamp); | ||
| ResultFormatter.timestamp(result, eta); | ||
| ResultFormatter.fuel(result, fuel_in_tons); |
There was a problem hiding this comment.
This generated code does not compile and would also be unsafe at runtime. fuel_in_tons is declared with const inside the if block above, but it is used here outside that block and may not exist for the ***/**** cases. The runtime ResultFormatter also exposes currentFuel(...)/burnedFuel(...), not fuel(...), so npx tsc --noEmit reports both Cannot find name 'fuel_in_tons' and Property 'fuel' does not exist.
The same pattern appears in the generated label 44 variants with fuel_remaining. This should be fixed in the spec/codegen/runtime contract before these generated plugins are committed as a usable baseline.
| "test": "jest", | ||
| "ads:codegen-build": "cd vendor/airframes-decoder/codegen && npm install && npm run build", | ||
| "ads:generate": "node vendor/airframes-decoder/codegen/dist/cli.js generate --target ts --spec vendor/airframes-decoder/spec --out lib/plugins/generated", | ||
| "ads:check": "git diff --exit-code -- lib/plugins/generated || (echo 'lib/plugins/generated is out of date. Run npm run ads:generate and commit.' && exit 1)" |
There was a problem hiding this comment.
This freshness check only detects modifications to already-tracked generated files. If regeneration creates a new plugin file, git diff --exit-code -- lib/plugins/generated still exits successfully because untracked files are not part of git diff.
For a generated-code guard, prefer checking porcelain status for the path after generation, for example test -z "$(git status --porcelain -- lib/plugins/generated)", or combine git diff --exit-code with an explicit git ls-files --others --exclude-standard -- lib/plugins/generated check.
| "strict": true, | ||
| "baseUrl": ".", | ||
| "paths": { | ||
| "@airframes/ads-runtime-ts": ["vendor/airframes-decoder/runtimes/typescript/index.ts"], |
There was a problem hiding this comment.
compilerOptions.paths helps TypeScript resolve this alias during type-checking, but it does not by itself make the alias available to Jest/Babel or to Node for emitted JavaScript. Right now that is hidden because lib/plugins/generated/** is not imported by index.ts, so the package build never exercises these imports.
Before switching behavior to generated plugins, please add the matching runtime/test/build resolution path: for example a real workspace/package dependency for @airframes/ads-runtime-ts, Jest moduleNameMapper, and/or tsup alias/bundling configuration. Otherwise the first generated plugin import is likely to fail with Cannot find module '@airframes/ads-runtime-ts' outside the TypeScript compiler.
…oder
Proof point that the full vertical works end-to-end:
spec/labels/10/POS.yaml
→ ads-gen --target ts
→ lib/plugins/generated/Label_10_POS.ts
→ @airframes/ads-runtime-ts {DecoderPlugin, ResultFormatter, helpers}
→ MessageDecoder dispatcher
→ 3/3 Label_10_POS tests + 407/407 full suite passes
Changes:
- Bump vendor/airframes-decoder submodule to e839bbc, which includes
the emitter fix that suppresses raw auto-emit for fields consumed
by a formatter (no more divergent raw.latitude/longitude/altitude
next to the formatter's raw.position/altitude). Bytes now match
the hand-written plugin.
- jest.config.ts: add moduleNameMapper for the @airframes/ads-runtime-ts
path aliases (Jest doesn't read tsconfig paths by default).
- lib/plugins/escape_hatches/index.ts: placeholder so generated
plugins' `import * as hatches from '../escape_hatches'` resolves
(no hatches needed for Label_10_POS; later plugins populate this).
- lib/MessageDecoder.ts: import Label_10_POS from the generated tree
and register it in place of the hand-written Plugins.Label_10_POS.
Verification:
npm test -- --testPathPatterns=Label_10_POS → 3/3 pass
npm test → 407/407 pass
Next: extend the pilot to the other declarative ports
(Label_44_IN/ON/OFF/ETA — also pure data, no escape hatches). The
remaining 60+ plugins need their escape-hatch implementations in
lib/plugins/escape_hatches/ before they can swap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…orts)
Extends the pilot to the remaining 4 fully-declarative spec ports
identified during the bulk-port phase. Same byte-for-byte parity proof
as Label_10_POS: no escape hatches needed, runtime helpers cover all
the decode-fn calls (coordinate_decimal_minutes, integer, float,
timestamp_hhmmss, airport).
Verification:
npm test -- --testPathPatterns='Label_44_(IN|ON|OFF|ETA)'
→ 14/14 pass
npm test
→ 407/407 pass (no regression)
All 5 of the v1 declarative ports now run through the generated tree.
The remaining ~60 plugins use whole-plugin escape hatches; their
behavioral swap waits on the corresponding hatch implementations under
lib/plugins/escape_hatches/, ported from the original TS plugin
sources.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@jest.config.ts`:
- Around line 91-98: Update the string literals in the moduleNameMapper object
to use single quotes to match Prettier settings: change the keys and mapped path
values inside moduleNameMapper (the "^`@airframes/ads-runtime-ts`$",
"^`@airframes/ads-runtime-ts/helpers`$",
"^`@airframes/ads-runtime-ts/escape_hatches`$" entries) from double-quoted to
single-quoted strings so linting/formatting passes.
In `@lib/MessageDecoder.ts`:
- Around line 14-18: lib/plugins/official.ts currently re-exports legacy
handwritten symbols (Label_10_POS, Label_44_ETA, Label_44_IN, Label_44_OFF,
Label_44_ON) which are unused except for generated imports like
Label_10_POS_Generated in lib/MessageDecoder.ts; either remove those legacy
export lines to eliminate dead/ambiguous API or explicitly deprecate them by
re-exporting with JSDoc `@deprecated` annotations and providing a migration note
pointing to the generated names (e.g., Label_10_POS -> Label_10_POS_Generated),
update any internal imports to use the generated symbols instead (verify
MessageDecoder.ts imports), and add a short changelog/migration comment so
consumers know to switch to the generated exports.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 46c233e5-edb4-4fad-baa1-c2b8b6adb4f8
⛔ Files ignored due to path filters (6)
lib/plugins/generated/Label_10_POS.tsis excluded by!**/generated/**lib/plugins/generated/Label_44_ETA.tsis excluded by!**/generated/**lib/plugins/generated/Label_44_IN.tsis excluded by!**/generated/**lib/plugins/generated/Label_44_OFF.tsis excluded by!**/generated/**lib/plugins/generated/Label_44_ON.tsis excluded by!**/generated/**lib/plugins/generated/Label_44_POS.tsis excluded by!**/generated/**
📒 Files selected for processing (4)
jest.config.tslib/MessageDecoder.tslib/plugins/escape_hatches/index.tsvendor/airframes-decoder
✅ Files skipped from review due to trivial changes (1)
- lib/plugins/escape_hatches/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- vendor/airframes-decoder
| moduleNameMapper: { | ||
| "^@airframes/ads-runtime-ts$": | ||
| "<rootDir>/vendor/airframes-decoder/runtimes/typescript/index.ts", | ||
| "^@airframes/ads-runtime-ts/helpers$": | ||
| "<rootDir>/vendor/airframes-decoder/runtimes/typescript/helpers.ts", | ||
| "^@airframes/ads-runtime-ts/escape_hatches$": | ||
| "<rootDir>/vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts", | ||
| }, |
There was a problem hiding this comment.
Fix quote style to match Prettier configuration.
All string literals in moduleNameMapper use double quotes, but Prettier is configured to enforce single quotes. This will cause linting to fail.
🎨 Proposed fix
moduleNameMapper: {
- "^`@airframes/ads-runtime-ts`$":
- "<rootDir>/vendor/airframes-decoder/runtimes/typescript/index.ts",
- "^`@airframes/ads-runtime-ts/helpers`$":
- "<rootDir>/vendor/airframes-decoder/runtimes/typescript/helpers.ts",
- "^`@airframes/ads-runtime-ts/escape_hatches`$":
- "<rootDir>/vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts",
+ '^`@airframes/ads-runtime-ts`$':
+ '<rootDir>/vendor/airframes-decoder/runtimes/typescript/index.ts',
+ '^`@airframes/ads-runtime-ts/helpers`$':
+ '<rootDir>/vendor/airframes-decoder/runtimes/typescript/helpers.ts',
+ '^`@airframes/ads-runtime-ts/escape_hatches`$':
+ '<rootDir>/vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts',
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| moduleNameMapper: { | |
| "^@airframes/ads-runtime-ts$": | |
| "<rootDir>/vendor/airframes-decoder/runtimes/typescript/index.ts", | |
| "^@airframes/ads-runtime-ts/helpers$": | |
| "<rootDir>/vendor/airframes-decoder/runtimes/typescript/helpers.ts", | |
| "^@airframes/ads-runtime-ts/escape_hatches$": | |
| "<rootDir>/vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts", | |
| }, | |
| moduleNameMapper: { | |
| '^`@airframes/ads-runtime-ts`$': | |
| '<rootDir>/vendor/airframes-decoder/runtimes/typescript/index.ts', | |
| '^`@airframes/ads-runtime-ts/helpers`$': | |
| '<rootDir>/vendor/airframes-decoder/runtimes/typescript/helpers.ts', | |
| '^`@airframes/ads-runtime-ts/escape_hatches`$': | |
| '<rootDir>/vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts', | |
| }, |
🧰 Tools
🪛 ESLint
[error] 92-92: Replace "^@airframes/ads-runtime-ts$" with '^@airframes/ads-runtime-ts$'
(prettier/prettier)
[error] 93-93: Replace "<rootDir>/vendor/airframes-decoder/runtimes/typescript/index.ts" with '<rootDir>/vendor/airframes-decoder/runtimes/typescript/index.ts'
(prettier/prettier)
[error] 94-94: Replace "^@airframes/ads-runtime-ts/helpers$" with '^@airframes/ads-runtime-ts/helpers$'
(prettier/prettier)
[error] 95-95: Replace "<rootDir>/vendor/airframes-decoder/runtimes/typescript/helpers.ts" with '<rootDir>/vendor/airframes-decoder/runtimes/typescript/helpers.ts'
(prettier/prettier)
[error] 96-96: Replace "^@airframes/ads-runtime-ts/escape_hatches$" with '^@airframes/ads-runtime-ts/escape_hatches$'
(prettier/prettier)
[error] 97-97: Replace "<rootDir>/vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts" with '<rootDir>/vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts'
(prettier/prettier)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@jest.config.ts` around lines 91 - 98, Update the string literals in the
moduleNameMapper object to use single quotes to match Prettier settings: change
the keys and mapped path values inside moduleNameMapper (the
"^`@airframes/ads-runtime-ts`$", "^`@airframes/ads-runtime-ts/helpers`$",
"^`@airframes/ads-runtime-ts/escape_hatches`$" entries) from double-quoted to
single-quoted strings so linting/formatting passes.
… fixes)
Pulls in three fixes that unblock the Label_44_{IN,ON,OFF,ETA} pilot:
1. Emitter: when-gated field declarations are now hoisted (let X;
outside the if), so downstream formatters see the variable
(undefined when the guard fails) instead of crashing with
ReferenceError. (80095f5)
2. Emitter: formatter type 'fuel' now maps to ResultFormatter.currentFuel
(the actual runtime method name). Was emitting .fuel which threw
'is not a function'. (ef58ee3)
3. Runtime: ResultFormatter.currentFuel tolerates undefined/NaN input
so it can be called unconditionally from generated plugins even
when the upstream when-gated value never got assigned. Matches the
original hand-written guard pattern. (ce7d385)
Verified: 407/407 full suite passes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
||
| import { DecoderPlugin } from "@airframes/ads-runtime-ts"; | ||
| import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts"; | ||
| import { ResultFormatter } from "@airframes/ads-runtime-ts"; |
Backed by ~60 escape-hatch implementations under lib/plugins/escape_hatches/
that port each hand-written plugin's decode() body into a free function
the generated wrapper invokes via 'import * as hatches from
../escape_hatches'. Implementations authored by 4 parallel agents in a
single pass.
What's now generated:
CBand, ARINC_702, Label_ColonComma, Label_5Z_Slash,
Label_10_LDR, Label_10_POS, Label_10_Slash, Label_12_N_Space,
Label_12_POS, Label_13Through18_Slash, Label_15, Label_15_FST,
Label_16_AUTPOS, Label_16_Honeywell, Label_16_N_Space, Label_16_POSA1,
Label_16_TOD, Label_1L_3Line, Label_1L_070, Label_1L_660, Label_1L_Slash,
Label_20_CFB01, Label_20_POS, Label_21_POS, Label_22_OFF, Label_22_POS,
Label_24_Slash, Label_2P_FM3, Label_2P_FM4, Label_2P_FM5,
Label_30_Slash_EA, Label_44_ETA, Label_44_IN, Label_44_OFF, Label_44_ON,
Label_44_Slash, Label_4A_01, Label_4A_DIS, Label_4A_DOOR, Label_4A_Slash_01,
Label_4N, Label_4T_AGFSR, Label_4T_ETA, Label_B6_Forwardslash, Label_H2_02E,
Label_H1_ATIS, Label_H1_EZF, Label_H1_FLR, Label_H1_M_POS, Label_H1_OHMA,
Label_H1_OFP, Label_H1_Paren, Label_H1_WRN, Label_H1_StarPOS, Label_HX,
Label_58, Label_80, Label_83, Label_8E, Label_1M_Slash, Label_MA, Label_SQ,
Label_QP, Label_QQ, Label_QR, Label_QS.
What's still hand-written (separate follow-up):
- Plugins.Label_4A — agent stubbed; variant-2/variant-3 field hatches
need design (formatter ownership of items list).
- Plugins.Label_44_POS — spec uses field-level customs
(parse_flight_level_or_ground +
flight_level_to_altitude_feet) not implemented
in this bulk pass.
Submodule bumped to airframes-decoder@c037de4 to pick up:
- runtime: DecoderPlugin helpers made public (initResult/setDecodeLevel/
failUnknown/debug) so escape hatches can delegate
- runtime: re-export Arinc702Helper, FlightPlanUtils, RouteUtils,
parseIcaoFpl, MIAMCoreUtils, base64ToUint8Array, inflateData,
ascii85Decode from the package index
- emitter: smart slugger handles camelCase boundaries (CBand→c-band,
StarPOS→star-pos, 3Line→3-line, 4A stays 4a) so generated plugin
names match the legacy ones byte-for-byte
Verified: 407/407 tests pass. No regressions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts"; | ||
| import { ResultFormatter } from "@airframes/ads-runtime-ts"; | ||
| import * as helpers from "@airframes/ads-runtime-ts/helpers"; | ||
| import * as hatches from "../escape_hatches"; |
Two final swaps: - Label_4A: spec changed (airframesio/acars-decoder@de6137f) from variants+field-customs to whole-plugin parse-custom. Hatch implementation in escape_hatches/Label_4A.ts mirrors the original decode() body byte-for-byte (3 variants by field count + first-char inspection, inline ResultFormatter calls). - Label_44_POS: spec stays declarative; added the two field-level hatches it referenced — parse_flight_level_or_ground and flight_level_to_altitude_feet — in escape_hatches/Label_44_POS.ts. Both are 1-line ports of inline TS code: 'GRD'/'***' → 0, else Number(value) multiply by 100 Submodule bumped to airframes-decoder@de6137f (carries the Label_4A spec change). Verified: 407/407 tests pass. End-to-end vertical for every TS plugin: spec/*.yaml → ads-gen → lib/plugins/generated/*.ts → escape_hatches/* → ResultFormatter / helpers → MessageDecoder dispatcher → original tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>


Summary
Integrates airframesio/acars-decoder as a git submodule and wires up the codegen toolchain, without replacing any hand-written plugin yet. Behavior is identical to master after this PR — every one of the 407 existing tests still passes, byte-for-byte.
This is the foundation PR for Stage 2 of the cross-language ACARS decoder unification. The actual swap (registering generated plugins in
MessageDecoder) is deferred to a follow-up because the emitter design needs one more pass before swapping is safe (see "What's deferred" below).What landed
vendor/airframes-decoderpinned toinit/ads-v1.@airframes/ads-runtime-ts→vendor/airframes-decoder/runtimes/typescript/index.ts@airframes/ads-runtime-ts/helpers→vendor/airframes-decoder/runtimes/typescript/helpers.ts@airframes/ads-runtime-ts/escape_hatches→vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.tsnpm run ads:codegen-build— installs + builds the codegen toolnpm run ads:generate— emitslib/plugins/generated/*.tsfrom spec YAMLnpm run ads:check— fails iflib/plugins/generated/is out-of-datelib/plugins/generated/. Committed (not gitignored) so contributors don't need the codegen toolchain to build/test, and reviewers see exactly what the runtime would use.vendor/**andlib/plugins/generated/**(avoid linting third-party code and auto-generated source)./vendor/(skip vendored submodule's own test files)..github/workflows/ads-check.ymlcalls the central reusablecodegen-check.ymlfrom airframes-decoder. Single source of CI logic across all three language repos.What's deferred (to a follow-up "Stage 2.5" PR)
The emitter currently double-bookkeeps
rawfields: it auto-emitsresult.raw.<fieldName> = valuefrom the spec'sfieldsblock AND then formatter calls write torawunder formatter-canonical keys (position,altitude, etc.). The original hand-written plugins only do the latter. Adopting the generated plugins as-is would produce extrarawentries that diverge from the existing test expectations.The fix is in the emitter (
vendor/airframes-decoder/codegen/src/emit-typescript.ts): track which raw keys the formatter writes and suppress the auto-emit for those keys. Once that lands in airframes-decoder and propagates here via submodule bump, the registration swap is safe.The original
lib/utils/*.tshelpers also stay in place until then; once the swap happens, they'll be removed in favor of the vendored copies.Test plan
npm test— 407 / 416 tests pass (9 skipped, matches baseline)npm run ads:codegen-buildsucceedsnpm run ads:generateproduces clean output; no diff vs committedads-checkworkflow on this PR (verifies generated tree stays in sync)Related
🤖 Generated with Claude Code
Summary by CodeRabbit
Chores
Refactor