# Task 1 Brief: Build scaffold and public C ABI lifecycle ## Global constraints - Use only original source code; do not link proprietary SDK binaries. - Current workspace is not a git repository; replace commit steps with verification plus updates to progress.md. - Keep public C ABI free of C++ types. - Use C++17. - libusb-1.0 is the only native runtime dependency for the core library. - Firmware update commands are not exposed as an easy accidental CLI action. - IR protocol gaps return MAG160C_ERR_PROTOCOL_UNKNOWN or MAG160C_ERR_UNSUPPORTED. ## Files - Create: CMakeLists.txt - Create: include/mag160c/mag160c.h - Create: src/core/error.hpp - Create: src/core/error.cpp - Create: src/core/context.hpp - Create: src/core/context.cpp - Create: src/c_api.cpp - Create: tests/cpp/test_c_api.cpp - Update: progress.md with the checkpoint at the end. ## Interfaces to produce - mag160c_error_t - opaque mag160c_context_t - opaque mag160c_ir_device_t - opaque mag160c_tcm_device_t - mag160c_error_t mag160c_init(mag160c_context_t** out_ctx) - void mag160c_shutdown(mag160c_context_t* ctx) - const char* mag160c_last_error(void) - const char* mag160c_error_name(mag160c_error_t code) ## Required public error enum ```c typedef enum mag160c_error_t { MAG160C_OK = 0, MAG160C_ERR_INVALID_ARGUMENT = 1, MAG160C_ERR_NO_DEVICE = 2, MAG160C_ERR_PERMISSION = 3, MAG160C_ERR_USB = 4, MAG160C_ERR_TIMEOUT = 5, MAG160C_ERR_CHECKSUM = 6, MAG160C_ERR_PROTOCOL_UNKNOWN = 7, MAG160C_ERR_UNSUPPORTED = 8, MAG160C_ERR_INTERNAL = 9 } mag160c_error_t; ``` ## Required test assertions Create tests/cpp/test_c_api.cpp and include assertions equivalent to: ```cpp assert(std::strcmp(mag160c_error_name(MAG160C_OK), "MAG160C_OK") == 0); assert(std::strcmp(mag160c_error_name(MAG160C_ERR_PROTOCOL_UNKNOWN), "MAG160C_ERR_PROTOCOL_UNKNOWN") == 0); assert(std::strcmp(mag160c_error_name(static_cast(9999)), "MAG160C_ERR_UNKNOWN_CODE") == 0); assert(mag160c_init(nullptr) == MAG160C_ERR_INVALID_ARGUMENT); mag160c_context_t* ctx = nullptr; assert(mag160c_init(&ctx) == MAG160C_OK); assert(ctx != nullptr); mag160c_shutdown(ctx); ``` ## Required CMake behavior - Minimum CMake 3.16. - Project name mag160c, C and CXX languages. - Options: - MAG160C_BUILD_TESTS ON by default. - MAG160C_BUILD_CLI ON by default. - C++ standard 17, required, no compiler extensions. - Use PkgConfig to find libusb-1.0 if available. - Build shared library target mag160c_core from: - src/core/error.cpp - src/core/context.cpp - src/c_api.cpp - Public include directory: include. - Private include directory: src. - If libusb is found, define MAG160C_HAS_LIBUSB=1 and link include/library variables. - If libusb is absent, define MAG160C_HAS_LIBUSB=0 and still build. - When tests are enabled, build test_c_api and register it with CTest. ## Required implementation behavior - last error is thread-local. - mag160c_error_name returns stable string names for every enum value and MAG160C_ERR_UNKNOWN_CODE for unknown values. - Context construction succeeds without hardware. - When libusb is absent at build time, Context records has_libusb as false but still constructs. - mag160c_init rejects a null output pointer, sets last_error mentioning out_ctx, and returns MAG160C_ERR_INVALID_ARGUMENT. - mag160c_init allocates a context on success, clears last_error, and returns MAG160C_OK. - mag160c_shutdown accepts null safely through delete behavior. - mag160c_last_error returns the thread-local message. ## Verification Run: ```powershell cmake -S . -B build -DMAG160C_BUILD_TESTS=ON cmake --build build ctest --test-dir build --output-on-failure ``` Expected: test_c_api passes. ## Progress checkpoint Append this line to progress.md after verification: ```markdown - Implemented Task 1 scaffold: CMake, public C ABI lifecycle, error names, and lifecycle tests. ``` ## Report contract Write a report to .superpowers/sdd/task-1-report.md with: - status: DONE, DONE_WITH_CONCERNS, NEEDS_CONTEXT, or BLOCKED - files created/modified - exact commands run - test results - concerns, if any - self-review notes