Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
622 commits
Select commit Hold shift + click to select a range
8754f5f
fix(data-types): stop a single-file save from half-migrating a projec…
thiagoralves Sep 3, 2026
bdab871
fix(located): refuse multi-dimensional arrays, and hoist the walk's scan
Sep 3, 2026
bb0ec38
refactor(located): walk the linear index, dropping incrementLocationB…
Sep 3, 2026
1a83678
style(save-actions): apply prettier formatting
thiagoralves Sep 3, 2026
500d6fc
fix(data-types): validate legacy type names before they become file p…
thiagoralves Sep 3, 2026
aaec22a
fix(variables): compare variable names case-insensitively everywhere …
JoaoGSP Sep 3, 2026
315c5ef
Merge remote-tracking branch 'origin/development' into bugfix/DOPE-59…
JoaoGSP Sep 3, 2026
1d3a6f1
fix(editor): three small defects from the community forum
thiagoralves Sep 3, 2026
7344cf8
Merge pull request #1074 from Autonomy-Logic/chore/DOPE-601-version-d…
JoaoGSP Sep 3, 2026
7f300fc
Merge branch 'development' into task/DOPE-603-datatypes-dt-standard
thiagoralves Sep 3, 2026
0eec265
Merge pull request #1081 from Autonomy-Logic/task/DOPE-603-datatypes-…
thiagoralves Sep 3, 2026
94a869b
Merge remote-tracking branch 'origin/development' into bugfix/DOPE-60…
thiagoralves Sep 3, 2026
780934c
fix(editor): address review on DOPE-606
thiagoralves Sep 3, 2026
a192153
Merge pull request #1084 from Autonomy-Logic/bugfix/DOPE-606-small-ed…
thiagoralves Sep 3, 2026
8e85a70
feat(bootloader): client, IPC and port for the runtime bootloader
thiagoralves Sep 3, 2026
1130d6d
feat(device): Runtime Status screen with version change
thiagoralves Sep 3, 2026
eed33f1
fix(editor): make execution order legible and drop it from ladder
thiagoralves Sep 3, 2026
9f70f21
Merge branch 'development' into feature/gh-565-located-arrays
thiagoralves Sep 3, 2026
2cfb31c
test(device): cover the Runtime Status screen's decisions
thiagoralves Sep 3, 2026
abafe32
Merge pull request #1080 from Autonomy-Logic/feature/gh-565-located-a…
thiagoralves Sep 3, 2026
ea83f81
fix(editor): make execution order legible, drop it from ladder, stop …
thiagoralves Sep 3, 2026
b0c6871
style(editor): prettier reflow of the DOPE-611 rewire helper
thiagoralves Sep 4, 2026
4db2645
fix(runtime-status): pick a version from the published list, not free…
thiagoralves Sep 4, 2026
22c4fbc
fix(runtime-status): read device facts from the bootloader, and name …
thiagoralves Sep 4, 2026
b21719b
fix(editor): address review — rung chain, self-loops, and the type as…
thiagoralves Sep 4, 2026
9f638ad
fix(runtime-status): stop the version dialog leaking a poll timer per…
thiagoralves Sep 4, 2026
e775635
fix(print): run the PDF preview in-process on Electron, with polyfill…
dcoutinho1328 Sep 4, 2026
8f3d5aa
feat(print): redesign the export-to-PDF preview — bigger viewer, scro…
dcoutinho1328 Sep 4, 2026
dd5a93a
fix(print): keep paginated content from clipping through headers, ele…
dcoutinho1328 Sep 4, 2026
0d0cdd6
chore(release): bring every version field into agreement at 4.3.0
marconetsf Sep 4, 2026
89b527a
Merge branch 'development' into feature/DOPE-442-modbus-server-unific…
marconetsf Sep 4, 2026
64a59a0
Merge pull request #1085 from Autonomy-Logic/bugfix/DOPE-606-executio…
thiagoralves Sep 4, 2026
27bce68
Merge branch 'development' into bugfix/DOPE-599-global-variable-name-…
JoaoGSP Sep 4, 2026
a893436
Merge branch 'development' into bugfix/DOPE-557-library-symbol-collision
JoaoGSP Sep 4, 2026
c055866
Merge pull request #1083 from Autonomy-Logic/bugfix/DOPE-599-global-v…
JoaoGSP Sep 4, 2026
c6da13c
test(store): move the duplicate fixture off a reserved library name (…
JoaoGSP Sep 4, 2026
cce3b31
Merge remote-tracking branch 'origin/development' into bugfix/DOPE-55…
JoaoGSP Sep 4, 2026
8ae4f9e
fix(runtime-status): address the review, and stop the header being blank
thiagoralves Sep 4, 2026
f3d04cd
Merge pull request #1078 from Autonomy-Logic/bugfix/DOPE-557-library-…
JoaoGSP Sep 4, 2026
2885ec7
feat(runtime-status): show the kernel for an orchestrator-managed device
thiagoralves Sep 4, 2026
9a2bfe5
fix(runtime-status): serialize progress polls, and let only the polle…
thiagoralves Sep 4, 2026
a35290e
fix(bootloader-api): refuse an address that is not a bare host
thiagoralves Sep 4, 2026
1c95266
fix(runtime-adapter): cover the bootloader methods, and format three …
thiagoralves Sep 4, 2026
1676a1e
ci(sync): name the differing files when a web PR does not match
thiagoralves Sep 4, 2026
66b09e4
Merge remote-tracking branch 'origin/development' into RTOP-283-runti…
thiagoralves Sep 4, 2026
a04a5ec
style(print): fix pre-existing prettier violations flagged by CI's fo…
dcoutinho1328 Sep 4, 2026
2f3de9c
Merge remote-tracking branch 'origin/development' into task/DOPE-594-…
dcoutinho1328 Sep 4, 2026
079b9b8
fix(runtime-status): treat a blank agent value as not reported
thiagoralves Sep 4, 2026
db395df
fix(store): refuse duplicate variable names coming from the code view…
JoaoGSP Sep 4, 2026
aaf9749
Merge pull request #1086 from Autonomy-Logic/RTOP-283-runtime-status-…
JoaoGSP Sep 4, 2026
c0970cc
Merge branch 'development' into bugfix/DOPE-616-code-view-duplicate-v…
JoaoGSP Sep 4, 2026
76d1aca
fix(store): keep the duplicate-name guard on the text boundary (DOPE-…
JoaoGSP Sep 4, 2026
cfddc50
fix(print): address code review — mirror gate gap, version pin, start…
dcoutinho1328 Sep 4, 2026
404421f
Merge remote-tracking branch 'origin/development' into task/DOPE-594-…
dcoutinho1328 Sep 4, 2026
f0bb418
Merge pull request #1088 from Autonomy-Logic/bugfix/DOPE-616-code-vie…
thiagoralves Sep 4, 2026
1a4e1a7
fix(menu): reach Retrieve Project from PLC on macOS and Linux (DOPE-617)
thiagoralves Sep 4, 2026
ecaa851
fix(breadcrumbs): label screens by editor type, not by name (DOPE-617)
thiagoralves Sep 4, 2026
a47ad75
fix(device): stop drawing a divider over nothing on Configuration (DO…
thiagoralves Sep 4, 2026
28c05c8
fix(persistent-storage): trim the copy on the screen (DOPE-617)
thiagoralves Sep 4, 2026
c64ae10
fix(table): keep a combobox cell the size of the table it sits in (DO…
thiagoralves Sep 4, 2026
7a2b34f
fix(menu): keep the File menu visible where it is the only one (DOPE-…
thiagoralves Sep 4, 2026
7695836
fix(menu): give Retrieve Project its own group (DOPE-617)
thiagoralves Sep 4, 2026
252dd96
fix(snapshot): actually open the project a retrieve fetched (DOPE-617)
thiagoralves Sep 4, 2026
48c8fff
fix(snapshot): resume the retrieve after the unsaved-changes dialog (…
thiagoralves Sep 4, 2026
bcdb502
fix(snapshot): keep retrieved projects out of the recent list (DOPE-617)
thiagoralves Sep 4, 2026
f140467
refactor(snapshot): one shared tail for opening a retrieved project (…
thiagoralves Sep 5, 2026
69f189c
refactor(snapshot): stop offering three ways into a one-way flow (DOP…
thiagoralves Sep 5, 2026
f4e81e7
fix(snapshot): refuse Save File on a project with no location too (DO…
thiagoralves Sep 5, 2026
34c5eac
feat(modbus): give a baremetal board a real server instead of a screen
marconetsf Sep 7, 2026
d60411a
feat(modbus): one screen, one store, and the editor's own port on offer
marconetsf Sep 7, 2026
5df68db
feat(compile): emit the Modbus block from the project, not from the p…
marconetsf Sep 7, 2026
41510c4
fix(firmware): stop TCP from eating a serial frame mid-assembly
marconetsf Sep 7, 2026
55853db
fix(modbus): recognise baremetal by its compiler, not by a screen
marconetsf Sep 7, 2026
355486a
chore(release): bring every version field to 4.4.0
marconetsf Sep 7, 2026
bc63957
Merge remote-tracking branch 'origin/development' into task/DOPE-594-…
dcoutinho1328 Sep 7, 2026
567e15d
feat(modbus): one screen shape on every target, and a switch that is …
marconetsf Sep 7, 2026
7a7bf0f
feat(modbus): stop offering RTU and TCP at the same time
marconetsf Sep 7, 2026
b006bb2
refactor(modbus): put field help behind a hover glyph, and share one …
marconetsf Sep 7, 2026
c08ff96
refactor(modbus): say each field's help in a line, not a paragraph
marconetsf Sep 7, 2026
d34fcd1
Revert "feat(modbus): stop offering RTU and TCP at the same time"
marconetsf Sep 7, 2026
b7f8351
feat(firmware): answer the editor's function codes on their own slave id
marconetsf Sep 7, 2026
4337f6c
feat(modbus): give the slave id back to the user on every port
marconetsf Sep 7, 2026
8c01634
feat(modbus): the server owns the speed of a UART of its own
marconetsf Sep 8, 2026
465ce6b
docs: the server owns a secondary UART's speed, the package the defau…
marconetsf Sep 8, 2026
a119c72
feat(modbus): put the board's pages next to the fields they govern
marconetsf Sep 8, 2026
561c194
fix(modbus): an editor upgrade must not strand a board or hide its se…
marconetsf Sep 8, 2026
628380e
fix(modbus): let an older package's Modbus screen render itself
marconetsf Sep 8, 2026
c93b62e
fix(print): address CodeRabbit review on the export-to-PDF PR
dcoutinho1328 Sep 8, 2026
2a16c87
fix(snapshot): unblock lint, and say when a retrieve stops (DOPE-617)
thiagoralves Sep 8, 2026
c44cc60
fix(menu): wire Save As where it is the only File menu (DOPE-617)
thiagoralves Sep 8, 2026
a172603
fix(project): keep recent-list bookkeeping out of the way (DOPE-617)
thiagoralves Sep 8, 2026
a22da9e
test(breadcrumbs): pin every editor type, and drop what the trail rep…
thiagoralves Sep 8, 2026
71b27a4
fix(snapshot): narrow what crosses the retrieve's two boundaries (DOP…
thiagoralves Sep 8, 2026
2ef8458
fix(modals): check the dialog's payload, and let nothing escape the r…
thiagoralves Sep 8, 2026
63af02d
Merge pull request #1087 from Autonomy-Logic/task/DOPE-594-print-expo…
dcoutinho1328 Sep 8, 2026
d3f2ca7
Merge remote-tracking branch 'origin/development' into bugfix/DOPE-61…
thiagoralves Sep 8, 2026
c34e107
fix(project): require an absolute path, and count the scratch root it…
thiagoralves Sep 8, 2026
17ce6d1
Merge pull request #1089 from Autonomy-Logic/bugfix/DOPE-617-editor-u…
thiagoralves Sep 8, 2026
6998475
feat(logo): Ethernet/Modbus TCP runtime + reboot-to-bootloader for LO…
thiagoralves Sep 8, 2026
52abee4
fix(cli): route `debug open` through the shared baremetal Modbus-TCP …
thiagoralves Sep 8, 2026
7b6cdff
refactor(logo): rename board define BOARD_LOGO8_TM4C1294 -> BOARD_LOGO8
thiagoralves Sep 8, 2026
aa1ead7
fix(lsp): keep the variables code view's tokens and markers in step w…
JoaoGSP Sep 8, 2026
889ab60
fix(logo): force Modbus TCP on for ethernet-upload targets (mandatory…
thiagoralves Sep 8, 2026
b00c901
fix(logo): correct scan-cycle pacing on the LOGO! (timers ran ~60x fast)
thiagoralves Sep 8, 2026
f6cd731
test(lsp): cover the stub:// publish path of the variables-view mirro…
JoaoGSP Sep 8, 2026
9ce6e53
Merge pull request #1092 from Autonomy-Logic/bugfix/DOPE-552-pouvars-…
JoaoGSP Sep 8, 2026
2ccd440
feat(logo): ethernet upload/connect flow + network discovery
thiagoralves Sep 9, 2026
8079d3a
Merge branch 'development' into feature/DOPE-442-modbus-server-unific…
marconetsf Sep 9, 2026
090c81f
fix(lsp): navigate on activation only, never while resolving a defini…
JoaoGSP Sep 9, 2026
c2dce95
refactor(lsp): narrow instead of asserting in the outline patch and t…
JoaoGSP Sep 9, 2026
793e57a
fix(modbus): draw the address map even when the package does not stat…
marconetsf Sep 9, 2026
65c27b0
chore(format): run prettier over the files this branch touched
marconetsf Sep 9, 2026
051fccc
fix(lsp): keep a childless POU out of the body outline, and cover the…
JoaoGSP Sep 9, 2026
82f6154
Merge pull request #1095 from Autonomy-Logic/bugfix/DOPE-551-goto-def…
JoaoGSP Sep 9, 2026
d333962
fix(modbus): carry the RTU wiring across from a pre-4.4.0 project
marconetsf Sep 9, 2026
46f2ef9
Merge remote-tracking branch 'origin/development' into feature/DOPE-4…
marconetsf Sep 9, 2026
582bd5b
fix(modbus): honour a server switched off, and persist the one migrat…
marconetsf Sep 9, 2026
89d3574
fix(store): gate globals, servers and remote devices against every ot…
JoaoGSP Sep 9, 2026
6f6089f
Refuse FC 0x4C when the device is programming-locked, and say so
thiagoralves Sep 10, 2026
eff0ad7
fix(store): close the review round on the element-name gate (DOPE-598…
JoaoGSP Sep 10, 2026
5f526b1
Merge pull request #1097 from Autonomy-Logic/bugfix/DOPE-598-600-name…
JoaoGSP Sep 10, 2026
b822202
Merge remote-tracking branch 'origin/development' into RTOP-285-logo-…
thiagoralves Sep 10, 2026
bd9093a
Undef Arduino's `round` before the std headers in C blocks
thiagoralves Sep 10, 2026
d3efcb0
feat(opcua): capability plumbing, opcua_config.h codegen and the netw…
thiagoralves Sep 10, 2026
48dead3
Undef Energia's `PT` before the generated headers in C blocks
thiagoralves Sep 10, 2026
fafeb7e
Give the OpenPLC Simulator a compile-time identity
thiagoralves Sep 10, 2026
a259382
feat(opcua): arena allocator and the bare-metal platform layer
thiagoralves Sep 10, 2026
6922cb4
feat(opcua): live server on the LOGO! — browse and read verified on h…
thiagoralves Sep 11, 2026
d1d67ac
revert(modbus): take the I/O image sizing out of this demand
marconetsf Sep 11, 2026
9fd64d0
fix(modbus): honour the wiring a pre-4.4.0 project still carries
marconetsf Sep 11, 2026
5eefe1e
test(modbus): pin the claims this demand makes, and fix the CLI load …
marconetsf Sep 11, 2026
755096c
Merge remote-tracking branch 'origin/development' into feature/DOPE-4…
marconetsf Sep 11, 2026
fd637a4
fix(lint): drop the imports the removal left behind
marconetsf Sep 11, 2026
eed3d21
fix(vpp): use a target-safe own-property check in the option path lookup
marconetsf Sep 11, 2026
92505d2
fix(opcua): track connection identity across Arduino client-slot reuse
thiagoralves Sep 11, 2026
f05af53
refactor(opcua): drop the connection-identity workaround, the core ow…
thiagoralves Sep 11, 2026
a6ce593
fix(store): warn before deleting a data type that is still referenced…
JoaoGSP Sep 11, 2026
d0628e0
perf(opcua): admission control on cycle slack, and a non-blocking sen…
thiagoralves Sep 11, 2026
6814cc2
Undef the whole Energia GPIO port-letter family in C blocks
thiagoralves Sep 11, 2026
7f5906a
fix(opcua): guarantee service, don't gate it purely on slack
thiagoralves Sep 11, 2026
ff1fded
feat(opcua): flash-backed nodestore — the address space leaves RAM
thiagoralves Sep 11, 2026
377a3ad
fix(store): drop parked data type confirmations on project teardown (…
JoaoGSP Sep 11, 2026
944a404
feat(opcua): username/password authentication (PBKDF2-HMAC-SHA256)
thiagoralves Sep 12, 2026
9d97c4c
docs(opcua): document the limits the LOGO! actually has
thiagoralves Sep 12, 2026
a6e3e7a
feat(opcua): the BUILD derives the stored credential, not the editor
thiagoralves Sep 12, 2026
82f9e8a
test(opcua): add passwordScheme to the header-generator fixture
thiagoralves Sep 12, 2026
7232122
fix(opcua): stop reaching across the precompile boundary for the debu…
thiagoralves Sep 13, 2026
d1bd572
feat(compile): install third-party Arduino libraries by git URL (DOPE…
thiagoralves Sep 13, 2026
3f50bf3
Merge pull request #1103 from Autonomy-Logic/RTOP-285-third-party-lib…
thiagoralves Sep 13, 2026
2c4ddf7
feat(s7comm): Phase 0 — an S7 server the LOGO! answers on port 102 (D…
thiagoralves Sep 13, 2026
fd5800f
feat(s7comm): Phase 1 — serve live PLC variables over S7 (DOPE-631)
thiagoralves Sep 13, 2026
4c858a0
Merge pull request #1104 from Autonomy-Logic/RTOP-285-s7comm-phase1
thiagoralves Sep 13, 2026
37a4c19
feat(s7comm): Phase 2 — identification and CPU control (DOPE-632)
thiagoralves Sep 13, 2026
f5d8cb7
Merge pull request #1105 from Autonomy-Logic/RTOP-285-s7comm-phase2
thiagoralves Sep 13, 2026
2c104b8
feat(s7comm): Phase 3 — harden, measure and document (DOPE-633)
thiagoralves Sep 13, 2026
8cb4a8d
Merge pull request #1106 from Autonomy-Logic/RTOP-285-s7comm-phase3
thiagoralves Sep 13, 2026
219f25e
fix(capabilities): resolve nested profiles even when a VPP declares none
thiagoralves Sep 13, 2026
6f18310
Merge pull request #1108 from Autonomy-Logic/RTOP-285-s7comm-capabili…
thiagoralves Sep 13, 2026
b215e2f
Merge remote-tracking branch 'refs/remotes/origin/feature/DOPE-442-mo…
thiagoralves Sep 13, 2026
6783084
Merge pull request #1109 from Autonomy-Logic/RTOP-285-merge-dope442
thiagoralves Sep 13, 2026
4456807
fix(ci): make the branch pass the gates CI actually runs
thiagoralves Sep 13, 2026
cdb4c19
Merge pull request #1110 from Autonomy-Logic/RTOP-285-opcua-ci-gates
thiagoralves Sep 13, 2026
636c638
Merge branch 'RTOP-285-opcua-baremetal' into RTOP-285-s7comm-sync-opcua
thiagoralves Sep 13, 2026
2e23d2a
Merge remote-tracking branch 'origin/RTOP-285-logo-openplc-runtime' i…
thiagoralves Sep 13, 2026
283d91c
chore(format): format the C-blocks test the LOGO! branch brought in
thiagoralves Sep 13, 2026
38abe95
Merge pull request #1111 from Autonomy-Logic/RTOP-285-opcua-sync-logo
thiagoralves Sep 13, 2026
bf81543
Merge branch 'RTOP-285-opcua-baremetal' into RTOP-285-s7comm-sync-opcua
thiagoralves Sep 13, 2026
98beb15
Merge pull request #1112 from Autonomy-Logic/RTOP-285-s7comm-sync-opcua
thiagoralves Sep 13, 2026
f842e55
fix(modbus): resolve the slave id in one place, and gate TCP on the s…
marconetsf Sep 14, 2026
d551652
docs(modbus): the emitter's RTU defaults note pointed at a constant t…
marconetsf Sep 14, 2026
e3432f8
refactor(modbus)!: drop every pre-4.4.0 compatibility path
marconetsf Sep 14, 2026
45cc142
fix(modbus): show the buffer sizes the board actually compiles with
marconetsf Sep 14, 2026
c44f61e
Merge pull request #1099 from Autonomy-Logic/bugfix/DOPE-553-datatype…
JoaoGSP Sep 14, 2026
7bac726
refactor(baremetal): DOPE-636 topic 2 — move the OPC-UA platform laye…
thiagoralves Sep 14, 2026
508251e
fix(ci): make the shared-surface check two-way, with the asymmetry de…
thiagoralves Sep 14, 2026
cedd2ba
fix(ci): compare tracked files, and stop allowlisting MatIEC
thiagoralves Sep 14, 2026
357c480
feat(baremetal): DOPE-636 3a — serve namespace zero from the library …
thiagoralves Sep 14, 2026
5368fc1
feat(baremetal): DOPE-636 3b — free the ziptree when namespace zero i…
thiagoralves Sep 15, 2026
2af192d
chore(baremetal): DOPE-636 — default OPCUA_NS0_FROM_FLASH off
thiagoralves Sep 15, 2026
807c5e7
perf(baremetal): DOPE-636 — 1 KB transfer buffer, and name the chunk …
thiagoralves Sep 15, 2026
05ecf5e
fix(baremetal): turn the telnet debug log back off
thiagoralves Sep 15, 2026
eeafa7b
feat(vpp): warn on every build when the board's package has a newer r…
marconetsf Sep 15, 2026
0895b1a
Merge remote-tracking branch 'origin/development' into feature/DOPE-4…
marconetsf Sep 15, 2026
9bd8024
fix(graphical): re-derive placed user-FB signatures on load (DOPE-548)
JoaoGSP Sep 15, 2026
c7abbf8
refactor(store): one expected-type helper for both graphical validato…
JoaoGSP Sep 15, 2026
ec0a287
fix(modbus): a board serves only what it has a carrier for
marconetsf Sep 15, 2026
06fc302
fix(graphical): normalise block names and guard malformed variants (D…
JoaoGSP Sep 15, 2026
1fe10ed
fix(modbus): a disabled server is not served on Runtime v4 either
marconetsf Sep 15, 2026
cfee817
feat(data-type): rename a data type from its .dt code view (DOPE-545)
JoaoGSP Sep 15, 2026
822f546
Merge pull request #1094 from Autonomy-Logic/feature/DOPE-442-modbus-…
thiagoralves Sep 15, 2026
f9cdd9b
Merge pull request #1117 from Autonomy-Logic/feature/DOPE-636-opcua-l…
thiagoralves Sep 15, 2026
49ac5ad
Merge development, and unify every version field on 4.3.0
autonomylogic Sep 15, 2026
a443f5b
docs(logo): strip verbose prose from the LOGO! 8 implementation comments
thiagoralves Sep 15, 2026
81534fe
feat(baremetal): let a project pick its SPI Ethernet driver and chip …
autonomylogic Sep 15, 2026
cb18ae1
fix(data-type): keep CRLF terminators when rewriting a declaration na…
JoaoGSP Sep 15, 2026
da878f9
Merge remote-tracking branch 'origin/development' into task/DOPE-545-…
JoaoGSP Sep 15, 2026
64a14f4
fix(baremetal): split the Ethernet stack off BOARD_*, so a WiFi-shape…
autonomylogic Sep 16, 2026
d9e3173
fix(compile): a default the user can see has to be the default the bu…
autonomylogic Sep 16, 2026
7e49f47
Merge pull request #1116 from Autonomy-Logic/task/DOPE-545-datatype-r…
JoaoGSP Sep 16, 2026
e140145
Merge remote-tracking branch 'origin/development' into bugfix/DOPE-54…
JoaoGSP Sep 16, 2026
159fccd
Merge pull request #1115 from Autonomy-Logic/bugfix/DOPE-548-user-fb-…
JoaoGSP Sep 16, 2026
8c3399f
chore(strucpp): pin the language server to v0.6.7
JoaoGSP Sep 16, 2026
13fee91
Merge pull request #1120 from Autonomy-Logic/chore/strucpp-v0.6.7
JoaoGSP Sep 16, 2026
c2f621e
feat(EDGE-639): name the platform entity Edge Devices in the project …
Thiago-Pio-Autonomy Sep 9, 2026
7f81feb
feat(EDGE-639): speak Edge Device and vPLC on the Edge Devices screen
Thiago-Pio-Autonomy Sep 9, 2026
d7ec0c1
feat(EDGE-639): name the agent Device Agent on the runtime status screen
Thiago-Pio-Autonomy Sep 9, 2026
604eb32
docs(EDGE-639): point two comments at the screen's current name
Thiago-Pio-Autonomy Sep 9, 2026
bf70044
fix(EDGE-639): restore the Device Agent label reverted by the previou…
Thiago-Pio-Autonomy Sep 9, 2026
746ffcb
test(EDGE-639): pin the Edge Devices screen's vocabulary
Thiago-Pio-Autonomy Sep 9, 2026
a2b3d32
fix(frontend): make view toggles keyboard accessible and scope struct…
JoaoGSP Sep 16, 2026
d28f7b6
fix(frontend): make the view toggle's focus ring and group label reac…
JoaoGSP Sep 16, 2026
600742a
Merge branch 'development' into RTOP-285-logo-openplc-runtime
thiagoralves Sep 16, 2026
adb529d
Merge pull request #1121 from Autonomy-Logic/task/DOPE-546-547-dual-m…
JoaoGSP Sep 16, 2026
127b0c7
fix(review): the smaller half of the PR-48 review findings
autonomylogic Sep 16, 2026
6a49a6d
fix(baremetal): the mandate is the network, not Modbus
autonomylogic Sep 16, 2026
f1a1ecd
fix(cli): --host stopped wiping the configuration it was meant to add to
autonomylogic Sep 16, 2026
a5f127a
fix(frontend): re-canonicalise the code buffer after a successful commit
JoaoGSP Sep 16, 2026
0dba541
fix(frontend): handle rejection from the variables view's commit call
JoaoGSP Sep 16, 2026
1a621d7
Merge remote-tracking branch 'refs/remotes/origin/development' into R…
autonomylogic Sep 16, 2026
1312149
docs(debug): strings are readable — correct the comments that said ot…
autonomylogic Sep 16, 2026
82268b0
fix(baremetal): size the Modbus frame to the widest value it must carry
autonomylogic Sep 16, 2026
f874f9d
fix(baremetal): leave the AVR frame alone
autonomylogic Sep 16, 2026
46cbde1
fix(opcua): honour the project's anonymous setting and enforce per-se…
thiagoralves Sep 17, 2026
6ae612c
fix(opcua): warn about leaves left out of the address space, and drop…
thiagoralves Sep 17, 2026
8ba994b
style: prettier formatting for the OPC-UA generator test
thiagoralves Sep 17, 2026
aab47f6
feat(opcua): serve STRING and WSTRING, and read every value in place
thiagoralves Sep 17, 2026
5fb549c
test(build): pin the Ethernet debug link restore across a throwing build
thiagoralves Sep 17, 2026
995da36
fix(opcua): defer to the node's own AccessLevel for nodes we do not own
thiagoralves Sep 17, 2026
cc2a0b3
fix(device): never invent a device IP, and say when a device config i…
thiagoralves Sep 17, 2026
234f5cd
fix(ui): stop offering a developer's own device address as the IP pla…
thiagoralves Sep 17, 2026
3cc1002
fix(compile): refuse a build that turns off an ethernet board's only …
thiagoralves Sep 17, 2026
eda9278
fix(ui): fold the whole Device branch, offer to connect, and stop dou…
thiagoralves Sep 17, 2026
658524f
fix(opcua): derive credentials with WebCrypto so openplc-web boots again
thiagoralves Sep 17, 2026
5c9eaac
fix(debugger): let the Debugger button work on a simulator target
thiagoralves Sep 17, 2026
ff99454
fix(debugger): offer to connect from the Debugger button, and name th…
thiagoralves Sep 17, 2026
aff52e0
fix(opcua): address a VAR_EXTERNAL in the global scope, not the decla…
thiagoralves Sep 17, 2026
8bbda22
fix(ci): satisfy lint, format and the frontend/hooks coverage gate
thiagoralves Sep 17, 2026
db0d249
fix(compile): build the simulator with user logic only, not servers
thiagoralves Sep 18, 2026
9c5bd25
fix(baremetal,opcua): review round 2 — TCP frame guard, S7 run/stop, …
thiagoralves Sep 18, 2026
a526744
Merge pull request #1122 from Autonomy-Logic/task/DOPE-622-code-buffe…
JoaoGSP Sep 18, 2026
0c918a0
chore(frontend): drop rewriteDeclaredTypeName, now unused
JoaoGSP Sep 18, 2026
13f8ba9
fix(review): items 12–21 and nits from the second review
thiagoralves Sep 18, 2026
da1e2bc
Merge pull request #1126 from Autonomy-Logic/chore/drop-unused-rewrit…
JoaoGSP Sep 18, 2026
b17e8df
chore(sync): adopt development's datatypes-series files
thiagoralves Sep 18, 2026
c504ddd
chore(strucpp): bump the pinned strucpp release to v0.6.8
thiagoralves Sep 18, 2026
145b1c4
Merge remote-tracking branch 'origin/development' into RTOP-285-logo-…
thiagoralves Sep 18, 2026
183dac8
Merge branch 'development' into feat/edge-639/rename-device-vplc
thiagoralves Sep 18, 2026
6ac081b
Merge pull request #1096 from Autonomy-Logic/feat/edge-639/rename-dev…
thiagoralves Sep 18, 2026
51382bc
Merge remote-tracking branch 'origin/development' into RTOP-285-logo-…
thiagoralves Sep 18, 2026
bf48d85
Merge pull request #1091 from Autonomy-Logic/RTOP-285-logo-openplc-ru…
thiagoralves Sep 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
18 changes: 16 additions & 2 deletions .github/workflows/ci-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,22 @@ jobs:
echo "::endgroup::"
exit 0
else
DIFF_COUNT=$(echo "$RESULT" | python3 -c "import json,sys; print(json.load(sys.stdin)['total_diffs'])")
echo "Still $DIFF_COUNT difference(s) with PR #$PR_NUMBER"
# Name the files, not just a count.
#
# A bare "Still 8 difference(s)" is undiagnosable: it gives no
# way to tell a genuine divergence from a PR head this run
# fetched before the other repo's push had propagated, which is
# a real race when both PRs are pushed within seconds of each
# other. The target-branch comparison already lists its files;
# this one now does too.
echo "$RESULT" | python3 -c "
import json, sys
data = json.load(sys.stdin)
print(f\"Still {data['total_diffs']} difference(s) with this PR:\")
for surface, info in data['surfaces'].items():
for d in info.get('diffs', []):
print(f\" {d['reason']}: src/{d['file']}\")
"
fi

echo "::endgroup::"
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/ci-unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ name: CI - Unit Tests

on:
workflow_dispatch:
# Called from `ci.yml` on every pull request.
workflow_call:

jobs:
unit-tests:
name: Unit Tests + Coverage
runs-on: ubuntu-latest
# Required check on `development` — a red suite blocks the merge.
steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ jobs:
lint:
uses: ./.github/workflows/ci-lint.yml

unit-tests:
uses: ./.github/workflows/ci-unit-tests.yml

format:
needs: [architecture, build-check, lint]
uses: ./.github/workflows/ci-format.yml
Expand All @@ -27,4 +30,8 @@ jobs:

complete-build:
needs: [sync]
# Full 3-OS packaging is release work: the tag-triggered release
# workflow builds it for real, so PRs into development skip it and
# only the promotion PRs into main still prove the app packages.
if: github.base_ref == 'main'
uses: ./.github/workflows/build.yml
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,30 @@ resources/st-compiler/**.spec
# External tool binaries (downloaded by scripts/download-binaries.ts)
# arduino-cli stays committed since we don't own its releases
resources/strucpp/
resources/bin/**
# Git will not re-include a file whose ancestor directory is excluded, and `bin/**` excludes
# the platform/arch directories too — so the two exceptions below only bite once these are
# re-included. Without them a NEWLY downloaded arduino-cli is invisible to git, and the six
# committed ones survive only because they were already tracked when the rule landed.
!resources/bin/
!resources/bin/*/
!resources/bin/*/*/
!resources/bin/*/*/arduino-cli
!resources/bin/*/*/arduino-cli.exe
# A local build leaves xml2st, iec2c/iec2iec and .binary-metadata.json here, plus
# timestamped .xml2st-backup-* copies. They are downloaded artefacts, not sources —
# 123 MB of them were swept into a PR by a `git add -A` before this rule existed.
resources/sources/MatIEC/

# Playwright
/test-results/
playwright-report
/blob-report/
/playwright/.cache/

# Claude Code session state (a running session's id and pid — never a project artefact)
.claude/scheduled_tasks.lock

# Development build of the headless CLI (see webpack.config.cli.dev.ts)
openplc-cli.dev.js
openplc-cli.dev.js.map
81 changes: 69 additions & 12 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ const createPou = useOpenPLCStore((s) => s.projectActions.createPou)
| `console` | Log output |
| `library` | System + user function block libraries |
| `file` | File save states (dirty tracking) |
| `print` | Print/export-to-PDF selection, render mode, page policy, page setup |
| `ai`, `history`, `modal`, `readme`, `search`, `shared`, `version-control`, `webrtc` | Supporting features |

**Conventions:**
Expand Down Expand Up @@ -217,6 +218,37 @@ Structured Text is generated in-process by the TS transpiler
legacy `xml2st` binary path has been retired. `XmlGenerator` is kept only for
the "Export Project as XML" feature.

**The Modbus block of `defines.h` has two sources**, split along the ownership
boundary (`src/backend/shared/compile/steps/modbus-defines.ts`):

- the project's Modbus `PLCServer` says **what is served** — the transports,
the slave id, the TCP port, and the speed of a UART of its own. On every
target, baremetal included.
- the board's VPP screens say **what it is served over** — the default UART's
speed, the RS-485 pin, the network. `serial` and `network` sections.

The default UART's speed is the one thing on that line the server does not own,
because it is the editor's own link and a UART has one speed. `resolveServerBaud`
in `middleware/shared/utils/modbus-server-profile/baud.ts` decides between the
two, and the SCREEN calls it as well — a hook cannot import `backend/shared`, and
two copies of that chain is how a screen ends up disagreeing with the firmware.

A firmware build serves exactly one slave (`modbus.slaveid` is a single global),
so `selectModbusServer` refuses a build with more than one enabled server and
names them. The editor still allows several, because a project moves between
targets.

The editor's own link is deliberately NOT derived from the server. `DEBUG_BAUD`
comes from `screens.serial.baud_rate` — that UART's speed is the package's to
state — and `DEBUG_SLAVE` is the constant 1, so a project with no Modbus server
still debugs and changing a server's slave id is not an access event.

On the default UART the firmware answers **both** ids and routes by function
code: `0x41`-`0x4B` on the editor's, everything on the server's. So a server
sharing that port keeps whatever id the user picked, and `MBSERIAL_SLAVE` is the
server's on every port. A board flashed before 4.3.0 may answer the editor on
another id; Connect tries 1 first and the project's legacy id after.

Platform-specific binaries in `/resources/bin/[platform]/[arch]/`. Board configs in `src/backend/shared/firmware/hals.json`.

### Debugging
Expand All @@ -231,14 +263,23 @@ Platform-specific binaries in `/resources/bin/[platform]/[arch]/`. Board configs
- **Framework:** Jest + jsdom
- **Test files:** `*.test.ts(x)`, `*.spec.ts(x)`, or `__tests__/` directories
- **E2E:** Playwright (`/e2e`), Chromium only
- **Coverage thresholds** (100% functions/lines/statements required):
- `src/frontend/store/slices/`
- `src/frontend/utils/`
- `src/backend/shared/`
- `src/middleware/adapters/editor/`
- **Coverage thresholds** — per-directory and aggregate, enforced by
`jest.config.json`. Branch coverage is not gated anywhere (`branches: 0`);
read the config for the current numbers rather than trusting this table:

| Directory | statements | lines | functions |
|---|---|---|---|
| `src/frontend/store/slices/` | 97 | 98 | 98 |
| `src/frontend/utils/` | 95 | 95 | 97 |
| `src/backend/shared/` | 75 | 77 | 76 |
| `src/middleware/adapters/editor/` | 85 | 85 | 87 |

They are floors for the directory as a whole, not a per-file rule, so a new
file is not obliged to reach 100% on its own — but it must not drag the
directory below the floor.
- **Mocks:** `configs/mocks/` for file stubs; `identity-obj-proxy` for CSS modules

When adding new code to covered directories, you must add corresponding tests to maintain 100% coverage.
When adding new code to a covered directory, add tests with it: the directory has to stay above its floor, and an untested file is what pushes it under.

## Code Style

Expand Down Expand Up @@ -278,6 +319,7 @@ When adding new code to covered directories, you must add corresponding tests to
- **Socket.io** for real-time communication
- **Winston** for structured logging (main process)
- **serialport** for serial communication
- **pdf-lib** + **@pdf-lib/fontkit** for PDF export (print/export-to-PDF)

## Important Patterns

Expand All @@ -290,11 +332,26 @@ The About modal renders it directly; the web build writes it into `version.json`
**Bump `APP_VERSION` — never `package.json` alone.** Make the identical one-line
edit in BOTH repos, and set `package.json.version` to the same value in both so
they can't drift. Roles: `APP_VERSION` is what the user sees in the About dialog;
`package.json.version` is what electron-builder stamps on the desktop binary and
what the release tag `vX.Y.Z` must match. Bumping only `package.json` leaves the
About dialog stuck on the old version — **this mistake shipped 4.2.7 and 4.2.8
with About still showing 4.2.6.** If the two ever disagree, `APP_VERSION` is
authoritative; fix it to match.
`package.json.version` is what a local build stamps. Bumping only `package.json`
leaves the About dialog stuck on the old version — **this mistake shipped 4.2.7
and 4.2.8 with About still showing 4.2.6.** If those two disagree, `APP_VERSION`
is authoritative; fix `package.json` to match.

**The release tag must equal `APP_VERSION` too.** `release.yml` stamps the binary
from the tag while About renders `APP_VERSION`, so tagging `v4.3.0` while
`APP_VERSION` is 4.2.12 ships an installer named 4.3.0 whose About dialog says
4.2.12 — the same failure in a different disguise. Check before tagging: a pushed
tag cannot be "fixed to match".

In the editor, electron-builder reads **`release/app/package.json`**, not the root
one — `electron-builder.json` sets `directories.app` to `release/app`. The release
workflow runs `npm version <tag>` at the root AND in `release/app`, so a
*tag-triggered* release is always correct. Two cases are not: a LOCAL package
build takes whatever `release/app/package.json` says, and a `workflow_dispatch`
run with an empty `version` input falls back to root `package.json`
(`release.yml`, version resolution). Use `npm version <v> --no-git-tag-version
--allow-same-version` in both places rather than editing by hand: it updates each
lockfile too, which hand edits miss (see DOPE-601).

Release order: bump `APP_VERSION` + `package.json` (both repos, same value) → PR
to `development` → merge → promote `development`→`main` on both → tag `vX.Y.Z` on
Expand All @@ -313,7 +370,7 @@ on its `main` push. (Ideally `package.json.version` should be derived from
1. Create `types.ts`, `slice.ts`, `index.ts` in `src/frontend/store/slices/<name>/`
2. Add the slice type to `RootState` union in `src/frontend/store/index.ts`
3. Spread the slice creator in `createOpenPLCStore()`
4. Add tests to maintain 100% coverage
4. Add tests with it, so the directory stays above its coverage floor

### When adding a new POU language or type:
1. Update project parser (`src/backend/shared/utils/parse-project-files.ts`)
Expand Down
2 changes: 1 addition & 1 deletion binary-versions.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"strucpp": {
"version": "v0.6.2",
"version": "v0.6.8",
"repository": "Autonomy-Logic/STruCpp"
}
}
7 changes: 7 additions & 0 deletions configs/mocks/monaco-editor-mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// monaco-editor ships no CommonJS entry point (package.json has no "main",
// only an ESM "module" field), so plain `require.resolve('monaco-editor')`
// fails under Jest — this mapping gives it a real, resolvable path so
// `jest.mock('monaco-editor', factory)` in individual test files can
// register their own factory instead of hitting a MODULE_NOT_FOUND error.
// Tests that don't provide their own factory get this harmless stub.
export const editor = { tokenize: () => [] }
64 changes: 64 additions & 0 deletions configs/webpack/webpack.config.cli.dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Development build of the headless CLI.
*
* Two things make this a config of its own rather than another entry on the dev
* main build, and both are path resolution rather than bundling:
*
* - `NODE_ENV=development`, because `CompilerModule` chooses between
* `process.cwd()/resources` and `process.resourcesPath` from it, and that
* choice is baked in at build time. A production-built CLI run from a dev
* checkout looks for arduino-cli inside Electron.app and fails with ENOENT.
* - Output at the REPO ROOT, because Electron sets `app.getAppPath()` to the
* directory of the script it is handed, and the compiler resolves the
* STruC++ runtime headers as `getAppPath()/node_modules/strucpp/...`. The
* dev GUI is launched as `electron .` from the root, so the root is what
* the GUI resolves — and matching it is the whole point of the CLI.
*
* The packaged CLI has neither problem: `app.isPackaged` sends every one of
* these lookups to `process.resourcesPath`.
*/

import webpack from 'webpack'
import { merge } from 'webpack-merge'

import devMainConfig from './webpack.config.main.dev'
import webpackPaths from './webpack.paths'

const configuration: webpack.Configuration = {
output: {
path: webpackPaths.rootPath,
filename: '[name].js',
library: { type: 'umd' },
},

// One file, no chunks. Both matter because the output directory is the repo
// ROOT: merging would keep the dev main build's `main`/`preload` entries and
// emit them here too, and code splitting would scatter vendor chunks
// alongside them — which is exactly the litter this replaced.
optimization: { splitChunks: false, runtimeChunk: false },

// `entry.ts` reaches both roles through dynamic imports, which webpack would
// split into sibling chunk files next to this bundle in the repo root. Folded
// back into the one file instead — the point of this config is a single
// artifact you can hand to `electron`.
plugins: [new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 })],
}

const merged = merge(devMainConfig, configuration)

export default {
...merged,
// Assigned after the merge: webpack-merge UNIONS `entry` objects, so the dev
// main build's entries would survive an override expressed inside the merge.
// `entry.ts`, NOT `cli/main.ts` — the same entry the packaged binary runs.
//
// Entering at `cli/main.ts` skipped the argv dispatcher, and with it two
// things that only exist there: the Linux re-exec that supplies the headless
// Chromium switches, and the handler that turns a failure to LOAD the CLI
// into an exit instead of a modal error dialog nobody can click. Both were
// therefore untestable with the bundle used to test everything else — a dev
// build that starts differently from the shipped one is a dev build that can
// pass while the product hangs. Costs `--cli` on every dev invocation, which
// is what the packaged binary needs anyway.
entry: { 'openplc-cli.dev': `${webpackPaths.srcPath}/main/entry.ts` },
}
6 changes: 5 additions & 1 deletion configs/webpack/webpack.config.main.prod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ const configuration: webpack.Configuration = {
target: 'electron-main',

entry: {
main: join(webpackPaths.srcMainPath, 'main.ts'),
// `entry.ts`, not `main.ts`: a packaged Electron app always runs
// `package.json.main`, so the GUI and the headless CLI (DOPE-567) have to
// ship in one binary with argv deciding which starts. It imports the GUI
// only when this is not a `--cli` run.
main: join(webpackPaths.srcMainPath, 'entry.ts'),
preload: join(webpackPaths.srcMainPath, 'modules/preload/preload.ts'),
},

Expand Down
13 changes: 12 additions & 1 deletion configs/webpack/webpack.config.renderer.dev.dll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,18 @@ const configuration: webpack.Configuration = {
// source code only consumes them via subpath imports (e.g.
// `browser-basedpyright` ships only the worker bundle under
// `dist/` and is loaded through `?url`).
renderer: Object.keys(dependencies || {}).filter((name) => name !== 'browser-basedpyright'),
//
// `pdfjs-dist` DOES resolve (it has `main`), but must be excluded for a
// different reason: we `import('pdfjs-dist')` for its main-thread API
// *and* load `pdf.worker.min.mjs` separately via `?url` as an
// independent Worker. Pre-bundling the main API into the DLL creates a
// second, separate module instantiation of pdf.js alongside the one in
// the renderer bundle, which breaks the API/Worker handshake pdf.js
// relies on internally — surfaces as cryptic runtime errors deep in the
// worker (e.g. a hash helper missing a method during fingerprint
// computation), not a load failure. Same class of problem as the
// browser-basedpyright exclusion above, different root cause.
renderer: Object.keys(dependencies || {}).filter((name) => name !== 'browser-basedpyright' && name !== 'pdfjs-dist'),
},

output: {
Expand Down
Loading
Loading