From 62bf4e246ec4acdeab3fcaa14a0433eb4ea5cecf Mon Sep 17 00:00:00 2001 From: vczh Date: Mon, 28 Sep 2026 03:42:39 -0700 Subject: [PATCH] Sync combined coding-agent learnings from Tools --- .github/KnowledgeBase/Learning.md | 49 +++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/.github/KnowledgeBase/Learning.md b/.github/KnowledgeBase/Learning.md index 6e7a6870..4dd2d99c 100644 --- a/.github/KnowledgeBase/Learning.md +++ b/.github/KnowledgeBase/Learning.md @@ -2,15 +2,15 @@ # Orders -- Verify generated artifacts with downstream consumer checks [25] -- Keep design documentation aligned with code after refactoring [23] -- Process staged tasks one by one with verification [22] -- Proactively remove code made redundant by refactoring [21] -- Port fixes from imports to source repositories [18] -- Verify and localize portability on every target OS [17] -- Crash early instead of adding error-tolerance fallbacks [15] -- Extract abstractions only for real shared behavior [14] -- Fix behavior at the owning state instead of patching symptoms [12] +- Verify generated artifacts with downstream consumer checks [29] +- Keep design documentation aligned with code after refactoring [25] +- Proactively remove code made redundant by refactoring [24] +- Process staged tasks one by one with verification [23] +- Port fixes from imports to source repositories [21] +- Verify and localize portability on every target OS [18] +- Crash early instead of adding error-tolerance fallbacks [16] +- Extract abstractions only for real shared behavior [16] +- Fix behavior at the owning state instead of patching symptoms [13] - Validate expectations against implementation and existing tests [12] - Make `Stop()` drain asynchronous work before returning [8] - Do not assume async callback owners are heap allocated [5] @@ -54,6 +54,9 @@ - Preserve ordered HTTP messages at upload and completion boundaries [1] - Preserve an existing `Ptr` counter across asynchronous ownership handoffs [1] - Reuse established MSBuild project configurations [1] +- Use explicit positive compiler and platform guards [1] +- Keep encoding and exception adapters at the C++/JavaScript boundary [1] +- Revalidate mutable external state immediately before mutation [1] # Refinements @@ -125,6 +128,8 @@ For environment or lifecycle invalidation, prefer forwarding one application-lev Keep application-specific choices in the application that owns them. When several entry points share one showcase, expose its selection event and attach one shared handler at each entry point instead of adding a callback plugin, selector API or availability state to a reusable skin. A dependency arrangement should make required behavior available in each consumer without teaching the lower layer the showcase policy. +When macOS or WebAssembly can reuse most of a Linux implementation, keep the shared implementation in the existing `*.Linux.*` file with explicit positive platform guards and small conditional differences. Delete duplicate platform files and their project/filter registrations; retain separate files for genuinely different implementations such as a browser console bridge. + ## Make `Stop()` drain asynchronous work before returning If an API exposes `Stop()`, callers should be able to rely on it as the shutdown boundary: after it returns, no pending action, wait callback, overlapped I/O, or async completion should still touch the object. Do not paper over a broken `Stop()` with sleeps in tests; fix the stop path. @@ -275,6 +280,10 @@ For a released VlppOS namespace change, validate Workflow through the ChatBot SO When relocating manually maintained configuration beside generated types, validate both development architectures and the normal and IncludeOnly release consumers. Generate prerequisite types before packing and verify that each canonical configuration implementation appears exactly once; a successful development build can otherwise conceal stale release dependencies. +When a new platform backend is packed into an existing release pair, compile and run a separate consumer of that generated pair. A passing source-project build cannot prove that release guards expose supported APIs exactly once or that deliberately unavailable services still fail as specified. + +For compiler refactors intended to preserve valid resource behavior, rebuild the deployed release tools, invalidate resource caches that do not track compiler binaries, and inspect each downstream architecture's outputs. A driver that catches errors and continues cannot be validated by its exit alone. Explain the complete generated diff, including unchanged consumers, and avoid inserting runtime checks for constraints that the authoring compiler can validate directly. + ## `vl::regex` separator regex: `L"[\\/\\\\]+"` In `vl::regex::Regex`, both `/` and `\\` are escaping characters, and incorrect escaping inside `[]` can throw errors like `Illegal character set definition.` @@ -321,6 +330,10 @@ For application refactors, remove helper wrappers that only duplicate an already When a shared event-information type can own a newly common field, move the field there and delete modifier-only wrapper types and parallel overload plumbing that no longer represent a distinct concept. +When a documented build invariant guarantees that `CPP_TARGET` and its package outputs are files under `Bin`, removing `Bin` already cleans them. Remove redundant file-by-file cleanup instead of preserving commands for target layouts the build no longer supports. + +Before adding persistent validation state, check whether the existing input contract can provide the complete set of values in one batch. If it can, validate with local state and remove the state map, wrapper type and alternate authoring paths that existed only to support incremental arrival. Preserve ordinary runtime mutation when the restriction belongs specifically to authoring. + ## Keep design documentation aligned with code after refactoring When a refactoring changes architecture or behavior, update the corresponding design documents in the same task rather than deferring it. After a structural change, re-read the related documents and reconcile anything that became misaligned (for example, descriptions of a transport path that no longer exists). Treat documentation drift left by a previous refactoring as part of the current cleanup. @@ -349,6 +362,8 @@ When HTTP long-poll delivery needs a bounded acknowledgement, put the deadline o When a native window-style update changes keyboard focus or responder ownership as a side effect, preserve and restore the previous owner at the style-changing boundary. Restore focus only when the affected view already owned it; do not activate an inactive window or steal focus from another responder. Standalone startup may hide the problem by activating the window afterward, while an already-visible remote renderer receives no later activation to repair the lost state. +When a compiler diagnostic lacks a source location, repair the argument or syntax metadata where the position should be produced. Do not make a downstream loader guess a location that the common compilation pipeline already knows. + ## Treat environment correlation as evidence, not a cause When a bug reproduces on one machine but not another, do not assume hardware speed or timing is causal merely because the machines differ. Reproduce the smallest differing state or response shape deterministically, then identify the missing transition or dependency that the other environment happens to mask. @@ -363,6 +378,8 @@ When asked to prepare Unix `vmake` configuration on Windows without executing it Portability applies to test synchronization APIs too. When a timed thread wait exists only on one platform, use a cross-platform completion primitive such as `EventObject` for the bounded deadlock guard, signal it on every expected completion path, and still join the worker afterward. Do not weaken a bounded test into an unbounded join merely to make it compile elsewhere. +Browser automation can change the environment being tested. Verify effective security preferences and worker-local settings instead of assuming automation defaults or page-context overrides match a normal browser. For example, restore Firefox's normal strict file-origin policy when reproducing local-module failures, and probe the worker's actual timezone before claiming timezone coverage. Serve Wasm module packages over HTTP for their supported run and distinguish that result from opening the HTML through `file://`. + ## Use reentrant POSIX date-time conversions On POSIX platforms, never retain pointers returned by `localtime()` or `gmtime()` across calls or threads because both may share process-wide `tm` storage. Use caller-owned stack values populated by `localtime_r()` and `gmtime_r()` instead, with separate values for simultaneous local and UTC conversions. @@ -408,3 +425,17 @@ When a callback or adapter must retain an object beyond the caller's synchronize ## Reuse established MSBuild project configurations When adding a solution or project, start from a comparable existing `.vcxproj` configuration and adapt its dependencies and source inventory. Reuse established architecture, runtime, compiler and linker settings instead of reconstructing the build configuration from scratch. + +## Use explicit positive compiler and platform guards + +Compiler/platform selection must enumerate supported branches with `#if` and `#elif`; do not assume that everything outside MSVC is native GCC/Clang. Select Emscripten explicitly as `VCZH_WASM`, independently of `VCZH_MSVC` and `VCZH_GCC`, while `VCZH_APPLE` refines the native GCC branch. Correct encountered platform-selection `#ifdef` / `#else` shortcuts, including unrelated ones, without changing ordinary header guards or unrelated feature switches. Unsupported compilers should fail instead of silently entering a fallback. + +## Keep encoding and exception adapters at the C++/JavaScript boundary + +Preserve Emscripten's SDK-compatible 32-bit `wchar_t` and use `WString` throughout C++; do not force `-fshort-wchar`. Convert to temporary `U16String` only at the JavaScript boundary, and convert received strings back immediately. Use `U8String` only when UTF-16 cannot be bound easily and document that limitation. Honor explicit code-unit lengths and copy temporary buffers before the C++ call returns. + +Prefer `EMSCRIPTEN_BINDINGS` for C++ exports and small `EM_JS` calls to named JavaScript helpers for imports. Keep application logic in normal C++ or JavaScript/TypeScript functions; direct JavaScript built-ins are appropriate for general operations. Separate the normal C++ function from its exception-catching `wasm_` export, and translate failures to return values in both directions so exceptions do not cross the boundary. + +## Revalidate mutable external state immediately before mutation + +A UI selection or cached snapshot is not authoritative for external state that can change independently. Re-read the actual state at the operation boundary and reject a mismatch before any mutation. Report the selected and actual state, including special states such as detached HEAD, rather than silently ignoring the command or claiming a merge conflict. Keep a matching-state positive control and verify rejected operations leave all relevant external state unchanged.