{"baked_at":"2026-08-30T22:15:01.494720+00:00","repos":[{"name":"alchemo-sigilism","head":"da39a3ee5e6b4b0d3255bfef95601890afd80709","language":""},{"name":"azura-land","head":"63e964a8d2519fb5f583f53d7b882e7071afa69c","language":"python"},{"name":"azura-terraforming","head":"145a38e3a2018e772bcaa7a5c7725285e74bb7a6","language":"markdown"},{"name":"azura-website","head":"de7e9abac0d239b641bd6ad9cd2cf17d93bb9f69","language":"markdown"},{"name":"azurak-language","head":"aa7d8e6f95fd9bd13ff91ef97b6f8593cc33792d","language":"markdown"},{"name":"azuran-knowledge-ark","head":"612fa15f3593e979646b4642edcda761854f4c8d","language":"javascript"},{"name":"bioflash","head":"6a019c5b208cb128c302a78136e469069663fe2b","language":"python"},{"name":"cell","head":"d9a282f24a8ade4a232a0315025bae81952df2e7","language":"rust"},{"name":"code-forge","head":"3387fccfd89308eb43f7e9ec0742e97377fb67a4","language":"javascript"},{"name":"composite-organism","head":"78a499df2f0caddbe42731cd0278484fba10e8a0","language":"markdown"},{"name":"deck-of-cards","head":"f6eabe5fd71a473230569e4ca2b84dbf401312e4","language":"javascript"},{"name":"dying-earth","head":"5a672090b456abc5e6d5d98419d2d21dcb82e04d","language":"markdown"},{"name":"dynamic","head":"acf6b2c42a22323d9755ac32842d7a4bd4426e8e","language":"python"},{"name":"elemental","head":"bbcf2f2f74f85ee0ad35aea05a31d4564a2bfb9a","language":"markdown"},{"name":"emoji_wall","head":"b424fa99e0d905fa5736f80dd3d666f6530490df","language":""},{"name":"eureka-co-nevada","head":"4a541e084e8a05e1e1b900e74a8f35f9fd03b598","language":"markdown"},{"name":"external-organelle-project","head":"b713b3535f1c72f7304b631da3ae50117212e30f","language":"python"},{"name":"facedancer","head":"325ab41a33e6e0d3d467a961e431b5b3949b37bf","language":"rust"},{"name":"form-template","head":"ee2dbbedb34a6093d45e9b679a5e01219c171056","language":"html"},{"name":"forms","head":"740fd7ea6aa8138d1380f72909867f170dbd24e7","language":"typescript"},{"name":"gerald-herald","head":"fb0f750679e34837cbb8a620ff7e687e5cfadee0","language":"markdown"},{"name":"glyph3d","head":"0ae663aea14ff1dc91bd1950d91be15f6a2ff80c","language":"markdown"},{"name":"glyphic","head":"7ec1b2d5fa6784946918368aa13d9f07f6cc8031","language":"markdown"},{"name":"goat_management_app","head":"61420c7b5b64134cfb525664d4d8f6645c424f05","language":""},{"name":"good-news","head":"cc9f405bfbf4f2a3ffdfed6cf50747d35213be0b","language":"markdown"},{"name":"groundwork","head":"b5713d479e37100992c764800f7a8ba089b270c6","language":"python"},{"name":"heloo-wald","head":"7a8ae40b4bfd41b13f7143c838d8ff483d153066","language":"markdown"},{"name":"hex-tessellation","head":"3a0710a3e012b1038a958c799b7e9a867aaa3829","language":"python"},{"name":"hexa","head":"84c19386d4b5ce958b8f9000e7734e5b9b9c105a","language":"python"},{"name":"hexquest","head":"da39a3ee5e6b4b0d3255bfef95601890afd80709","language":""},{"name":"holocene","head":"126921edf92d7ad41602cb45a2b6c912033cda69","language":"typescript"},{"name":"infra","head":"d9c33b6802b445b97f67fe87b7122cb6725ed770","language":"shell"},{"name":"iris","head":"0564c198b3e1814c0042c009c918e551ebd909ab","language":"rust"},{"name":"learning-area","head":"9a321eb5c600e00241a3a21901883c9a5ab6bb88","language":"html"},{"name":"major-tims-ground-control","head":"3502091393f783774ceba2ab95258d68542a0df9","language":"javascript"},{"name":"margin","head":"81e8cef0443e9955411ff7be23f1344ec5576423","language":"typescript"},{"name":"mesnada","head":"f71dd1d8f3662427aa02412d207758427d099117","language":"python"},{"name":"meso-cli","head":"2bdb3c2523b6ce5fb067073a0e760a6eb7419dd5","language":"markdown"},{"name":"metabolic","head":"cb872c0a4398751fc3e7ce3dd9dd5c79000819d5","language":"rust"},{"name":"musico","head":"41d127cd625cd82cfa319ae9669f286b6904ef01","language":"rust"},{"name":"mycelial-network","head":"df356a45eac971197b55212b534cb8a227866d31","language":"javascript"},{"name":"new-belen-game","head":"2bc884ec9d4f3903c29ca05d470828b22c452e90","language":"python"},{"name":"new-church-game","head":"4bdc42658f40400fc17f0b0198fb89a5d55282ce","language":"python"},{"name":"operations","head":"a2b20bb9d4d487166d7d9abe36746212105fa26f","language":"markdown"},{"name":"ops26-04p2a","head":"775b01937fc4e84b290239886e3e97109b308d81","language":"markdown"},{"name":"opsin","head":"b90d0b3be48dd8da1401c44944def6735a70b460","language":"kotlin"},{"name":"persian-gulf-theater","head":"64e298c949b14e0acf45af05613ef46c143793ca","language":"markdown"},{"name":"plenum","head":"1c0e2f5b16554d3c2bb08d0d6c8312a07c911147","language":"typescript"},{"name":"program-x19","head":"3d018281d6131e53b976588072a6d4aec48da856","language":"typescript"},{"name":"publications","head":"8af886292f435a03f1afa6afda7ce758dce75bb6","language":"markdown"},{"name":"puppet","head":"bf5e6e5a0db72258d89efdb38fff4a5005ae9a20","language":"typescript"},{"name":"reflex","head":"a1f5a4f15ab8b62ebcfd5494a44d409bab360b6d","language":"kotlin"},{"name":"researcher-graph","head":"71d6c18c42e44c4c56383d030bb8a577ccf0335d","language":"python"},{"name":"robotics","head":"da39a3ee5e6b4b0d3255bfef95601890afd80709","language":""},{"name":"rowbots","head":"326bd43b81350f10a55750263b26c296e5865955","language":"markdown"},{"name":"seandruh","head":"07b195deb61809d2e04ac1b66e58abc5bb85beb7","language":"python"},{"name":"soma","head":"3cfc0bfe0e69684edb3ceafc0b1b638b2ef979f8","language":"markdown"},{"name":"somaphore","head":"566f1c797af02e9c2a46e4be5ae7f46a16a2bd52","language":"rust"},{"name":"symbiont-gis","head":"5d435a152260f7cbd920f6c6511dbec2a64e765a","language":"python"},{"name":"symbiont-systems","head":"b7d25fd21d866a53429a8d781aedc16d84e6e95f","language":"markdown"},{"name":"symbiont.systems","head":"d9b1d9d66acbb3968323d1897eaef91f1e483317","language":"javascript"},{"name":"symbiontic-dialogues","head":"21af48a8e5f40c1ca1ab4437c6bde632ef7ca9f6","language":"markdown"},{"name":"synthpen","head":"b0ad3bf1601a8b35af2ff7b53b47c848e1263343","language":"html"},{"name":"techbiont-framework","head":"b2b810d65a96f89e0c176280a74a6fab47febfba","language":"markdown"},{"name":"the-azuran","head":"c97423106631299e998f2bfab7ef05a9ffa55826","language":"markdown"},{"name":"the-azuran.github.io","head":"7b69ab7f2ab24fbc285d29136103a6fe147c055b","language":"html"},{"name":"trishsays","head":"8ecab93e9b9addb80c0452f9509924957ebb4cc0","language":"html"},{"name":"unified-ai","head":"b9fa3838b194ebf43ef4bde8a0f003a4f4dfac6f","language":"python"},{"name":"web-scrapper","head":"c5b260a156f42762b5cc59e5788d1a1bfbe26bbb","language":""},{"name":"wheel-of-the-heavens","head":"753141bbbbfd4d743bc81f42b65be34db48ab43c","language":"rust"},{"name":"world","head":"62f31663c0e3e0a17d65e3f992a360828db3492e","language":"typescript"}],"commits":[{"repo":"deck-of-cards","hash":"04586d85c6b5c180a11ce77b7655d59983a69a5d","ts":1441209959,"wall":"2015-09-02T19:05","msg":"initial commit","body":"","parents":[],"add":1352,"del":0,"cadd":1221,"cdel":0,"files":23},{"repo":"deck-of-cards","hash":"00a94ddb2a7862155e3d399bc9476d2e122ad667","ts":1441210219,"wall":"2015-09-02T19:10","msg":"initial commit","body":"","parents":["04586d85c6b5c180a11ce77b7655d59983a69a5d"],"add":0,"del":1127,"cadd":0,"cdel":997,"files":22},{"repo":"deck-of-cards","hash":"8673c947b4411418da94fc05db737188958264a5","ts":1441210273,"wall":"2015-09-02T19:11","msg":"added dist","body":"","parents":["00a94ddb2a7862155e3d399bc9476d2e122ad667"],"add":479,"del":0,"cadd":479,"cdel":0,"files":2},{"repo":"deck-of-cards","hash":"8e6c6b43391ba700012a8803d8e6c42124ddc914","ts":1441210339,"wall":"2015-09-02T19:12","msg":"changed deck.min.js url","body":"","parents":["04586d85c6b5c180a11ce77b7655d59983a69a5d"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"7ecf662b92fa58529f2b19af5901304dad5a905b","ts":1441210378,"wall":"2015-09-02T19:12","msg":"small fix..","body":"","parents":["8e6c6b43391ba700012a8803d8e6c42124ddc914"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"3b6b81e986fd5c741eaa0d1038c1d9c4597d43fc","ts":1441210410,"wall":"2015-09-02T19:13","msg":"changed url","body":"","parents":["7ecf662b92fa58529f2b19af5901304dad5a905b"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"acd9284f2381abcb249aefc1b9b82c2a60097ff1","ts":1441210469,"wall":"2015-09-02T19:14","msg":"changed url","body":"","parents":["8673c947b4411418da94fc05db737188958264a5"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"73543d001b55dcf3316d32b6144de7be1f3f2756","ts":1441210732,"wall":"2015-09-02T19:18","msg":"Create README.md","body":"","parents":["3b6b81e986fd5c741eaa0d1038c1d9c4597d43fc"],"add":3,"del":0,"cadd":3,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"7d6860dde62da93d374872cd83dfced1adc6a6c1","ts":1441211980,"wall":"2015-09-02T19:39","msg":"added github fork banner","body":"","parents":["73543d001b55dcf3316d32b6144de7be1f3f2756"],"add":3,"del":1,"cadd":1,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"88182f6f27f536d064432053111f0477dbfa987d","ts":1441212005,"wall":"2015-09-02T19:40","msg":"added github fork banner","body":"","parents":["acd9284f2381abcb249aefc1b9b82c2a60097ff1"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"39c882c4f2bfc780c9b9a915a489a879f86750f9","ts":1441212732,"wall":"2015-09-02T19:52","msg":"small cosmetic changes..","body":"","parents":["7d6860dde62da93d374872cd83dfced1adc6a6c1"],"add":165,"del":61,"cadd":160,"cdel":61,"files":14},{"repo":"deck-of-cards","hash":"78844896d438ff6c91c262a20becf2dea12d6298","ts":1441212833,"wall":"2015-09-02T19:53","msg":"small cosmetic changes..","body":"","parents":["39c882c4f2bfc780c9b9a915a489a879f86750f9"],"add":59,"del":60,"cadd":59,"cdel":60,"files":8},{"repo":"deck-of-cards","hash":"9f19fb7f44630a8e54427c09460cc0350a993aec","ts":1441212902,"wall":"2015-09-02T19:55","msg":"small cosmetic changes..","body":"","parents":["88182f6f27f536d064432053111f0477dbfa987d"],"add":117,"del":68,"cadd":117,"cdel":68,"files":2},{"repo":"deck-of-cards","hash":"72c44bca72632224ef5a77ac112e67a88d16bc9b","ts":1441213060,"wall":"2015-09-02T19:57","msg":"added media query","body":"","parents":["78844896d438ff6c91c262a20becf2dea12d6298"],"add":9,"del":0,"cadd":5,"cdel":0,"files":2},{"repo":"deck-of-cards","hash":"030cc90b7e43ccb9f652748a7c78101da1c6a2cc","ts":1441213109,"wall":"2015-09-02T19:58","msg":"compressed CSS","body":"","parents":["72c44bca72632224ef5a77ac112e67a88d16bc9b"],"add":2,"del":194,"cadd":1,"cdel":193,"files":2},{"repo":"deck-of-cards","hash":"771a677221ebd05298e25e7f505b71fd427c48bd","ts":1441213154,"wall":"2015-09-02T19:59","msg":"added media query + compressed CSS","body":"","parents":["9f19fb7f44630a8e54427c09460cc0350a993aec"],"add":1,"del":188,"cadd":1,"cdel":188,"files":1},{"repo":"deck-of-cards","hash":"4a0cce7fe64913f0c9abe72ee7839d3947a8ca0e","ts":1441213289,"wall":"2015-09-02T20:01","msg":"added another media query","body":"","parents":["030cc90b7e43ccb9f652748a7c78101da1c6a2cc"],"add":5,"del":1,"cadd":1,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"8c39ab672e259df28a303b7bc96b3f2e02b81652","ts":1441213304,"wall":"2015-09-02T20:01","msg":"added another media query","body":"","parents":["771a677221ebd05298e25e7f505b71fd427c48bd"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"3e22196d65f349ef4ede3e98b77e68e922fb8bbe","ts":1441213498,"wall":"2015-09-02T20:04","msg":"Update README.md","body":"","parents":["4a0cce7fe64913f0c9abe72ee7839d3947a8ca0e"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"fc28544f76bdfc74e435fe3a64d8bce0207e71a2","ts":1441214493,"wall":"2015-09-02T20:21","msg":"Update README.md","body":"","parents":["3e22196d65f349ef4ede3e98b77e68e922fb8bbe"],"add":14,"del":0,"cadd":14,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"eb24640144a125ae13ca0b4331890a768907bf3d","ts":1441214525,"wall":"2015-09-02T20:22","msg":"Update README.md","body":"","parents":["fc28544f76bdfc74e435fe3a64d8bce0207e71a2"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"00c42c5618613f9f18da352f553559abbbb1fda9","ts":1441214569,"wall":"2015-09-02T20:22","msg":"Update README.md","body":"","parents":["eb24640144a125ae13ca0b4331890a768907bf3d"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"56f7a99a496379ec6ae593fbf7993484774c0c61","ts":1441214704,"wall":"2015-09-02T20:25","msg":"Update README.md","body":"","parents":["00c42c5618613f9f18da352f553559abbbb1fda9"],"add":10,"del":5,"cadd":10,"cdel":5,"files":1},{"repo":"deck-of-cards","hash":"a573c68f7366b439c45c27a0b4bf2ec108f4c75f","ts":1441215317,"wall":"2015-09-02T20:35","msg":"added commas","body":"","parents":["56f7a99a496379ec6ae593fbf7993484774c0c61"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"fe16b1c7f8c731924325e40db11b561639c7d230","ts":1441217074,"wall":"2015-09-02T21:04","msg":"added Moz -prefix","body":"","parents":["a573c68f7366b439c45c27a0b4bf2ec108f4c75f"],"add":15,"del":1,"cadd":15,"cdel":1,"files":3},{"repo":"deck-of-cards","hash":"97a748cac3e12a3ec67b8ddad3b18a5e2ecb6658","ts":1441217121,"wall":"2015-09-02T21:05","msg":"added Moz -prefix","body":"","parents":["8c39ab672e259df28a303b7bc96b3f2e02b81652"],"add":8,"del":1,"cadd":8,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"d51a87b3badfbedf9531ccca4b0dd054c3be51b4","ts":1441220312,"wall":"2015-09-02T21:58","msg":"fixed prefix issue","body":"","parents":["fe16b1c7f8c731924325e40db11b561639c7d230"],"add":19,"del":17,"cadd":19,"cdel":17,"files":3},{"repo":"deck-of-cards","hash":"fe9fb03c91453d24a5ec73d26779f404ac30b083","ts":1441220352,"wall":"2015-09-02T21:59","msg":"fixed prefix issue","body":"","parents":["97a748cac3e12a3ec67b8ddad3b18a5e2ecb6658"],"add":10,"del":9,"cadd":10,"cdel":9,"files":2},{"repo":"deck-of-cards","hash":"0ef9084f41657fe88dd6bdd633e6f44d5c9a61db","ts":1441220490,"wall":"2015-09-02T22:01","msg":"fixed protocol issue","body":"","parents":["fe9fb03c91453d24a5ec73d26779f404ac30b083"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"caef3ed4518073ea9f4adee283b3bf175c69aae8","ts":1441220502,"wall":"2015-09-02T22:01","msg":"fixed protocol issue","body":"","parents":["d51a87b3badfbedf9531ccca4b0dd054c3be51b4"],"add":2,"del":2,"cadd":1,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"fe59bd36be5f79f05a6dd5b179f16fae6d719c2f","ts":1441229633,"wall":"2015-09-03T00:33","msg":"Update package.json","body":"","parents":["caef3ed4518073ea9f4adee283b3bf175c69aae8"],"add":1,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"6ce6a1b95a139fa3c92d17133bc216eaa06ce8eb","ts":1441229740,"wall":"2015-09-03T00:35","msg":"Update README.md","body":"","parents":["fe59bd36be5f79f05a6dd5b179f16fae6d719c2f"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"4e1c996e75b5faa1900b208375bee3e80a17f23c","ts":1441250133,"wall":"2015-09-03T06:15","msg":"Create LICENSE","body":"","parents":["6ce6a1b95a139fa3c92d17133bc216eaa06ce8eb"],"add":21,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"bcbc3e36d2ecb8cf46677175a3568c90987be7d4","ts":1441250201,"wall":"2015-09-03T06:16","msg":"Create LICENSE","body":"","parents":["0ef9084f41657fe88dd6bdd633e6f44d5c9a61db"],"add":21,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"5a5ca44a1388a44736192282d5b5c081df14afac","ts":1441250750,"wall":"2015-09-03T06:25","msg":"Update README.md","body":"","parents":["4e1c996e75b5faa1900b208375bee3e80a17f23c"],"add":2,"del":0,"cadd":2,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"abe838b0f9cd04174aa7cfc7906c490b9b0e0d78","ts":1441253106,"wall":"2015-09-03T07:05","msg":"Update README.md","body":"","parents":["5a5ca44a1388a44736192282d5b5c081df14afac"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"74f43c305fb1764a5d6058890e39a0e2a1e538fb","ts":1441253132,"wall":"2015-09-03T07:05","msg":"Update README.md","body":"","parents":["abe838b0f9cd04174aa7cfc7906c490b9b0e0d78"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"f71c344dd892d1fec01d0ae5543e20ace968f474","ts":1441256547,"wall":"2015-09-03T08:02","msg":"changed background color to poker table green","body":"","parents":["74f43c305fb1764a5d6058890e39a0e2a1e538fb"],"add":7,"del":5,"cadd":1,"cdel":1,"files":3},{"repo":"deck-of-cards","hash":"d681d0d0c9be2e24146a21194ffd210546b5e6ad","ts":1441256673,"wall":"2015-09-03T08:04","msg":"changed background color to poker table green","body":"","parents":["bcbc3e36d2ecb8cf46677175a3568c90987be7d4"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"2014d7230a8ff4688da4edba209a74e5b2af922b","ts":1441256929,"wall":"2015-09-03T08:08","msg":"changed github fork ribbon color","body":"","parents":["f71c344dd892d1fec01d0ae5543e20ace968f474"],"add":7,"del":4,"cadd":2,"cdel":2,"files":4},{"repo":"deck-of-cards","hash":"88f28ad991d619eaed0fefde77fa038deb2ee588","ts":1441256998,"wall":"2015-09-03T08:09","msg":"changed github ribbon color to white and added media query","body":"","parents":["d681d0d0c9be2e24146a21194ffd210546b5e6ad"],"add":2,"del":2,"cadd":2,"cdel":2,"files":2},{"repo":"deck-of-cards","hash":"d474c9f55667bcd0adf76d4d7e102239403db815","ts":1441257618,"wall":"2015-09-03T08:20","msg":"fixed ribbon link","body":"","parents":["2014d7230a8ff4688da4edba209a74e5b2af922b"],"add":2,"del":2,"cadd":1,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"f08c0b2738624b7ba33d6d415194d067fde7fb53","ts":1441257637,"wall":"2015-09-03T08:20","msg":"fixed ribbon link","body":"","parents":["88f28ad991d619eaed0fefde77fa038deb2ee588"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"ce9012a272825b72fe6faff0f40cd4ed9b58b651","ts":1441258769,"wall":"2015-09-03T08:39","msg":"setTimeout -> transition-delay","body":"","parents":["d474c9f55667bcd0adf76d4d7e102239403db815"],"add":55,"del":34,"cadd":54,"cdel":34,"files":8},{"repo":"deck-of-cards","hash":"59d0b2727720e3db0a43cb3116d6e5f85b4d9ef5","ts":1441258827,"wall":"2015-09-03T08:40","msg":"setTimeout -> transition-delay","body":"","parents":["f08c0b2738624b7ba33d6d415194d067fde7fb53"],"add":24,"del":13,"cadd":24,"cdel":13,"files":2},{"repo":"deck-of-cards","hash":"f51e3bb67753c9aafd7b5d8d19ccee8624212788","ts":1441259072,"wall":"2015-09-03T08:44","msg":"fixed bysuit..","body":"","parents":["59d0b2727720e3db0a43cb3116d6e5f85b4d9ef5"],"add":2,"del":2,"cadd":2,"cdel":2,"files":2},{"repo":"deck-of-cards","hash":"e7f48bebee9c1dc445c18a9d2a57a909d408d618","ts":1441259086,"wall":"2015-09-03T08:44","msg":"fixed bysuit..","body":"","parents":["ce9012a272825b72fe6faff0f40cd4ed9b58b651"],"add":3,"del":3,"cadd":3,"cdel":3,"files":3},{"repo":"deck-of-cards","hash":"d9be0ead2da3974a64a65d45c4f00d7e6402611c","ts":1441259324,"wall":"2015-09-03T08:48","msg":"added CNAME for dns.js.org","body":"","parents":["f51e3bb67753c9aafd7b5d8d19ccee8624212788"],"add":1,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"08e9edb9ad7c48f06dd7fe57e5e4dbe831f5da80","ts":1441259923,"wall":"2015-09-03T08:58","msg":"small fix for firefox","body":"","parents":["e7f48bebee9c1dc445c18a9d2a57a909d408d618"],"add":5,"del":5,"cadd":5,"cdel":5,"files":3},{"repo":"deck-of-cards","hash":"92cc18fad283231c26b8b573c85eee830ad0ee54","ts":1441260023,"wall":"2015-09-03T09:00","msg":"small fix for firefox","body":"","parents":["d9be0ead2da3974a64a65d45c4f00d7e6402611c"],"add":3,"del":3,"cadd":3,"cdel":3,"files":2},{"repo":"deck-of-cards","hash":"49432be30fae486fbeee0699852bd92b3ad1b135","ts":1441276430,"wall":"2015-09-03T13:33","msg":"lighten up a bit..","body":"","parents":["08e9edb9ad7c48f06dd7fe57e5e4dbe831f5da80"],"add":3,"del":3,"cadd":1,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"1d35e492b5ef17c5803a813d8f460f0b7c9fd846","ts":1441276452,"wall":"2015-09-03T13:34","msg":"lighten up a bit..","body":"","parents":["92cc18fad283231c26b8b573c85eee830ad0ee54"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"3b8ee6d5d4c020fdc41a2b84b6350cc2de971529","ts":1441277459,"wall":"2015-09-03T13:50","msg":"simplified prefix.js","body":"","parents":["49432be30fae486fbeee0699852bd92b3ad1b135"],"add":21,"del":73,"cadd":21,"cdel":73,"files":3},{"repo":"deck-of-cards","hash":"ced4634661ae1aa3513840c2c926b86bbaf2e568","ts":1441277517,"wall":"2015-09-03T13:51","msg":"simplified prefix helper","body":"","parents":["1d35e492b5ef17c5803a813d8f460f0b7c9fd846"],"add":11,"del":37,"cadd":11,"cdel":37,"files":2},{"repo":"deck-of-cards","hash":"3a28687fdc0912b97a2a92b9815c466227957de6","ts":1441290484,"wall":"2015-09-03T08:28","msg":"Update index.styl","body":"Reduced shadow depth and spread. Added border.","parents":["3b8ee6d5d4c020fdc41a2b84b6350cc2de971529"],"add":2,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"4eb4a10b31f8eec43a410a2c1ca9516ddf61915e","ts":1441293354,"wall":"2015-09-03T18:15","msg":"Update README.md","body":"","parents":["3b8ee6d5d4c020fdc41a2b84b6350cc2de971529"],"add":8,"del":0,"cadd":8,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"521dfdaa1980d83cd181d91600d50b05f2366668","ts":1441303720,"wall":"2015-09-03T21:08","msg":"Update README.md","body":"","parents":["4eb4a10b31f8eec43a410a2c1ca9516ddf61915e"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"62610c2968106e5c69af353a827bb2060cc5d7a8","ts":1441303753,"wall":"2015-09-03T21:09","msg":"Update README.md","body":"","parents":["521dfdaa1980d83cd181d91600d50b05f2366668"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"249ff4968b400270d74cdcd556a67b80faaf92d3","ts":1441319865,"wall":"2015-09-04T00:37","msg":"Make example refer to JS in repo, not github","body":"","parents":["62610c2968106e5c69af353a827bb2060cc5d7a8"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"c87f5820d1d3539b34265a3461eb20414d49eb27","ts":1441319899,"wall":"2015-09-04T00:38","msg":"Add touchmove/end listeners if touch detected, not remove","body":"","parents":["249ff4968b400270d74cdcd556a67b80faaf92d3"],"add":5,"del":5,"cadd":5,"cdel":5,"files":3},{"repo":"deck-of-cards","hash":"4a03451731802917661bb0a1a4feb4b5fd8c4428","ts":1441359700,"wall":"2015-09-04T12:41","msg":"Merge pull request #5 from joequery/bugfix_touch_listener","body":"Bugfix touch listener","parents":["62610c2968106e5c69af353a827bb2060cc5d7a8","c87f5820d1d3539b34265a3461eb20414d49eb27"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"60cf467087a333b0ed241caacec8df1ef90eeca8","ts":1441360094,"wall":"2015-09-04T12:48","msg":"#5","body":"","parents":["ced4634661ae1aa3513840c2c926b86bbaf2e568"],"add":4,"del":4,"cadd":4,"cdel":4,"files":3},{"repo":"deck-of-cards","hash":"b21786a6641388bda17f9d04ff91655a126511c5","ts":1441360908,"wall":"2015-09-04T13:01","msg":"#5","body":"","parents":["4a03451731802917661bb0a1a4feb4b5fd8c4428"],"add":2,"del":3,"cadd":1,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"c1d8a6d1d02a92a2ff3b929d9181c73e586d2d6b","ts":1441362133,"wall":"2015-09-04T13:22","msg":"made intro shorter and added \"poker\"","body":"","parents":["b21786a6641388bda17f9d04ff91655a126511c5"],"add":89,"del":5,"cadd":89,"cdel":5,"files":7},{"repo":"deck-of-cards","hash":"fb295ec0b8d8ea57aed4bb9b116f73cd1ccd3c79","ts":1441362176,"wall":"2015-09-04T13:22","msg":"made intro shorter and added \"poker\"","body":"","parents":["60cf467087a333b0ed241caacec8df1ef90eeca8"],"add":40,"del":3,"cadd":40,"cdel":3,"files":2},{"repo":"deck-of-cards","hash":"2f4a0baa0508d1a13f23d8fbbe7829b91e89326d","ts":1441362304,"wall":"2015-09-04T13:25","msg":"Made intro shorter and added 'poker'","body":"","parents":["cd1b96bfbed65229833194974fc134bd9b23bd87"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"cd1b96bfbed65229833194974fc134bd9b23bd87","ts":1441362481,"wall":"2015-09-04T13:28","msg":"Update README.md","body":"","parents":["c1d8a6d1d02a92a2ff3b929d9181c73e586d2d6b"],"add":8,"del":3,"cadd":8,"cdel":3,"files":1},{"repo":"deck-of-cards","hash":"917d30279ff522761250b4d51c298fab77162094","ts":1441362541,"wall":"2015-09-04T13:29","msg":"0.0.2","body":"","parents":["fb295ec0b8d8ea57aed4bb9b116f73cd1ccd3c79"],"add":13,"del":8,"cadd":13,"cdel":8,"files":1},{"repo":"deck-of-cards","hash":"0c34f5773c5cbe58a8ad19f65a7a2d16c16425cb","ts":1441362772,"wall":"2015-09-04T13:32","msg":"added fb share image","body":"","parents":["917d30279ff522761250b4d51c298fab77162094"],"add":0,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"e2d83803375aa8f05ac556fa84a7e167f719742a","ts":1441363086,"wall":"2015-09-04T13:38","msg":"added some meta","body":"","parents":["0c34f5773c5cbe58a8ad19f65a7a2d16c16425cb"],"add":23,"del":1,"cadd":23,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"7eadc04766f667117fb5af9e6cfd65a589712b4a","ts":1441363169,"wall":"2015-09-04T13:39","msg":"added some more meta..","body":"","parents":["e2d83803375aa8f05ac556fa84a7e167f719742a"],"add":2,"del":0,"cadd":2,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"3d068a180955da07fb51e510cd0560f3bec44ba7","ts":1441363292,"wall":"2015-09-04T13:41","msg":"added github ribbon","body":"","parents":["7eadc04766f667117fb5af9e6cfd65a589712b4a"],"add":0,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"819de5e26be77801b61ce8e6748e074bceec3982","ts":1441363411,"wall":"2015-09-04T13:43","msg":"removed og:url & http -> https","body":"","parents":["3d068a180955da07fb51e510cd0560f3bec44ba7"],"add":1,"del":2,"cadd":1,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"08300bc2688165ed6dc27ba51e346d57696dee2a","ts":1441364086,"wall":"2015-09-04T13:54","msg":"added ga","body":"","parents":["819de5e26be77801b61ce8e6748e074bceec3982"],"add":10,"del":0,"cadd":10,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"5ed11f516d993509f5ed957250126cb8ae45bac9","ts":1441369982,"wall":"2015-09-04T15:33","msg":"fixed poker","body":"","parents":["2f4a0baa0508d1a13f23d8fbbe7829b91e89326d"],"add":13,"del":13,"cadd":13,"cdel":13,"files":5},{"repo":"deck-of-cards","hash":"cadb376ee9d02f9f71a05e8baf468abe6f2e3728","ts":1441370029,"wall":"2015-09-04T15:33","msg":"fixed poker and made shuffle faster..","body":"","parents":["08300bc2688165ed6dc27ba51e346d57696dee2a"],"add":7,"del":7,"cadd":7,"cdel":7,"files":2},{"repo":"deck-of-cards","hash":"2dfe71a336e4f5c96d97024b3f16bd15a75f2e97","ts":1441373671,"wall":"2015-09-04T16:34","msg":"translate -> translate3d where available, fixes #4","body":"","parents":["5ed11f516d993509f5ed957250126cb8ae45bac9"],"add":114,"del":48,"cadd":113,"cdel":47,"files":12},{"repo":"deck-of-cards","hash":"a1a30e022001b4660ffb3975581cdd0766916ff2","ts":1441373735,"wall":"2015-09-04T16:35","msg":"translate -> translate3d where available, fixes #4","body":"","parents":["cadb376ee9d02f9f71a05e8baf468abe6f2e3728"],"add":52,"del":23,"cadd":52,"cdel":23,"files":2},{"repo":"deck-of-cards","hash":"820b3ad88cf79a2f73ef9156aa1826efa5e0bb08","ts":1441373969,"wall":"2015-09-04T16:39","msg":"fixed an issue with safari #4","body":"","parents":["a1a30e022001b4660ffb3975581cdd0766916ff2"],"add":2,"del":2,"cadd":2,"cdel":2,"files":2},{"repo":"deck-of-cards","hash":"110f02709deb8f9674a1de2ae9cfabdfb289cac8","ts":1441373989,"wall":"2015-09-04T16:39","msg":"fixed an issue with safari #4","body":"","parents":["2dfe71a336e4f5c96d97024b3f16bd15a75f2e97"],"add":3,"del":3,"cadd":3,"cdel":3,"files":3},{"repo":"deck-of-cards","hash":"60e328e3bbe19a442d539fb3bca4987eb4dcca6e","ts":1441375645,"wall":"2015-09-04T17:07","msg":"fixed translate.js","body":"","parents":["110f02709deb8f9674a1de2ae9cfabdfb289cac8"],"add":5,"del":9,"cadd":5,"cdel":9,"files":3},{"repo":"deck-of-cards","hash":"2fc4a0bd9153cf395fadf8836f3cb092fbd3979b","ts":1441375697,"wall":"2015-09-04T17:08","msg":"fixed translate3d","body":"","parents":["820b3ad88cf79a2f73ef9156aa1826efa5e0bb08"],"add":3,"del":5,"cadd":3,"cdel":5,"files":2},{"repo":"deck-of-cards","hash":"b538772e20be9fc2ec4462f372c55cd054ae2f10","ts":1441376597,"wall":"2015-09-04T17:23","msg":"fixed dragging..","body":"","parents":["2fc4a0bd9153cf395fadf8836f3cb092fbd3979b"],"add":3,"del":1,"cadd":3,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"d877b880ca9a9dc1edfe868c9a1871d72e716b34","ts":1441376609,"wall":"2015-09-04T17:23","msg":"fixed dragging..","body":"","parents":["60e328e3bbe19a442d539fb3bca4987eb4dcca6e"],"add":5,"del":1,"cadd":5,"cdel":1,"files":3},{"repo":"deck-of-cards","hash":"70cff4e0e759c39bfb5fc8eb6cfb42c090764745","ts":1441381268,"wall":"2015-09-04T18:41","msg":"added adsense","body":"","parents":["b538772e20be9fc2ec4462f372c55cd054ae2f10"],"add":19,"del":1,"cadd":19,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"f473464c4d02673a2592aff28313b1d6b4ac698a","ts":1441381562,"wall":"2015-09-04T18:46","msg":"changed ad format to horizontal","body":"","parents":["70cff4e0e759c39bfb5fc8eb6cfb42c090764745"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"d8bf7af352dac48de175e90c8735d21cff971b5b","ts":1441381610,"wall":"2015-09-04T18:46","msg":"removed comment line","body":"","parents":["f473464c4d02673a2592aff28313b1d6b4ac698a"],"add":0,"del":1,"cadd":0,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"3c8ebcb29a1091f4f998e34245e92bfbf4de411e","ts":1441381721,"wall":"2015-09-04T18:48","msg":"moved adsense to the back of the cards for dragging to work correctly..","body":"","parents":["d8bf7af352dac48de175e90c8735d21cff971b5b"],"add":10,"del":10,"cadd":10,"cdel":10,"files":1},{"repo":"deck-of-cards","hash":"b4f7ffea2de06dc7196c9cfba39df5b3919f0f2e","ts":1441381782,"wall":"2015-09-04T18:49","msg":"moved adsense script line..","body":"","parents":["3c8ebcb29a1091f4f998e34245e92bfbf4de411e"],"add":3,"del":3,"cadd":3,"cdel":3,"files":1},{"repo":"deck-of-cards","hash":"d299ec6cb828785700f8cd2593a392ac788aedc0","ts":1441381851,"wall":"2015-09-04T18:50","msg":"changed back..","body":"","parents":["b4f7ffea2de06dc7196c9cfba39df5b3919f0f2e"],"add":9,"del":9,"cadd":9,"cdel":9,"files":1},{"repo":"deck-of-cards","hash":"aec7438a953d4dbfffacc9efcac9c8d07a370637","ts":1441381964,"wall":"2015-09-04T18:52","msg":"switching back and forth because of the cache.. :(","body":"","parents":["d299ec6cb828785700f8cd2593a392ac788aedc0"],"add":1,"del":3,"cadd":1,"cdel":3,"files":1},{"repo":"deck-of-cards","hash":"a63368b2867ad33718848f40297a6d0e497c4ca8","ts":1441382382,"wall":"2015-09-04T18:59","msg":"added some dividers..","body":"","parents":["aec7438a953d4dbfffacc9efcac9c8d07a370637"],"add":5,"del":0,"cadd":5,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"58b91ac70a3938cfcc69144b77665ad98f8bc096","ts":1441384375,"wall":"2015-09-04T19:32","msg":"added fastclick & removed some protocols..","body":"","parents":["a63368b2867ad33718848f40297a6d0e497c4ca8"],"add":7,"del":3,"cadd":7,"cdel":3,"files":1},{"repo":"deck-of-cards","hash":"25af3a0d55c3ce6b52339ce71801723bc811d5fd","ts":1441385068,"wall":"2015-09-04T19:44","msg":"moved GA inside <head>","body":"","parents":["58b91ac70a3938cfcc69144b77665ad98f8bc096"],"add":9,"del":9,"cadd":9,"cdel":9,"files":1},{"repo":"deck-of-cards","hash":"924f46c68cb56d786c495a3fe27f5971b131805b","ts":1441385081,"wall":"2015-09-04T19:44","msg":"added npm-debug.log","body":"","parents":["25af3a0d55c3ce6b52339ce71801723bc811d5fd"],"add":1,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"9074350e490988994c2c34e5ed8e5843030c2e45","ts":1441386617,"wall":"2015-09-04T20:10","msg":"Update README.md","body":"","parents":["d877b880ca9a9dc1edfe868c9a1871d72e716b34"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"9e0d97ac19c030c104dbc1323fce34be53801cee","ts":1441387667,"wall":"2015-09-04T20:27","msg":"added npm-debug.log","body":"","parents":["9074350e490988994c2c34e5ed8e5843030c2e45"],"add":1,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"f3677d40aed256606068c71bffc9bbbebf359bd1","ts":1441394754,"wall":"2015-09-04T22:25","msg":"Update index.styl #6","body":"","parents":["9e0d97ac19c030c104dbc1323fce34be53801cee"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"e4b520a665e6212b9e6d000fc88c40cde17426ef","ts":1441394848,"wall":"2015-09-04T22:27","msg":"Update index.styl","body":"","parents":["f3677d40aed256606068c71bffc9bbbebf359bd1"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"eed4444dd0103f5536475ddc3d799cd1e9557f96","ts":1441394941,"wall":"2015-09-04T22:29","msg":"Revert \"Update index.styl\"","body":"This reverts commit e4b520a665e6212b9e6d000fc88c40cde17426ef.","parents":["e4b520a665e6212b9e6d000fc88c40cde17426ef"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"c983dd9aca30fced7b18b82a08c6b7bc68726170","ts":1441395610,"wall":"2015-09-04T22:40","msg":"Merge branch 'master' into pr/6","body":"Conflicts:\n\tcss/index.styl","parents":["3a28687fdc0912b97a2a92b9815c466227957de6","eed4444dd0103f5536475ddc3d799cd1e9557f96"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"57846c46c50c8e0a3e31fe7c1692017d790f1158","ts":1441395673,"wall":"2015-09-04T22:41","msg":"Merge pull request #7 from pakastin/pr/6","body":"Pr/6","parents":["eed4444dd0103f5536475ddc3d799cd1e9557f96","c983dd9aca30fced7b18b82a08c6b7bc68726170"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"0a3d2baaf6b483abb2a59ba11fac6048db814ca4","ts":1441398844,"wall":"2015-09-04T23:34","msg":"#6","body":"","parents":["57846c46c50c8e0a3e31fe7c1692017d790f1158"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"7640b2b6a255aeab333e13e6676fc1a149160cb0","ts":1441398899,"wall":"2015-09-04T23:34","msg":"#6","body":"","parents":["924f46c68cb56d786c495a3fe27f5971b131805b"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"710724f1737748f56ed3b0323ee4ff081339ae3d","ts":1441399428,"wall":"2015-09-04T23:43","msg":"maybe should try the default setting first..","body":"","parents":["7640b2b6a255aeab333e13e6676fc1a149160cb0"],"add":0,"del":1,"cadd":0,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"481ab9577a10b3cb097dac9b7b326f41236d8e62","ts":1441406522,"wall":"2015-09-05T01:42","msg":"big refactoring – code is now easier to follow and in smaller pieces..","body":"","parents":["0a3d2baaf6b483abb2a59ba11fac6048db814ca4"],"add":256,"del":177,"cadd":256,"cdel":177,"files":12},{"repo":"deck-of-cards","hash":"335e0a604e46f248311335b6aa682461d4b108ad","ts":1441406676,"wall":"2015-09-05T01:44","msg":"Big refactoring","body":"","parents":["481ab9577a10b3cb097dac9b7b326f41236d8e62"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"926f003ed84bb5bab008efe208317db5075b045a","ts":1441406742,"wall":"2015-09-05T01:45","msg":"Update README.md","body":"","parents":["335e0a604e46f248311335b6aa682461d4b108ad"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"d9658b354d6fb7624952f3df0e09eff1fb11406e","ts":1441406946,"wall":"2015-09-05T01:49","msg":"big refactoring","body":"","parents":["710724f1737748f56ed3b0323ee4ff081339ae3d"],"add":126,"del":88,"cadd":126,"cdel":88,"files":3},{"repo":"deck-of-cards","hash":"25f84f026bf1c46c8ebc3866438b0ac68d8161b2","ts":1441407240,"wall":"2015-09-05T01:54","msg":"fixed error in queue..","body":"","parents":["926f003ed84bb5bab008efe208317db5075b045a"],"add":7,"del":3,"cadd":7,"cdel":3,"files":3},{"repo":"deck-of-cards","hash":"5d7d8ab3ddcf0110d0567a4eb817948374d332de","ts":1441407491,"wall":"2015-09-05T01:58","msg":"Update README.md","body":"","parents":["25f84f026bf1c46c8ebc3866438b0ac68d8161b2"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"b73b0ab72e01d0b4ad8d8c1e1f1251c58450b285","ts":1441407763,"wall":"2015-09-05T02:02","msg":"fixed issue with queue","body":"","parents":["d9658b354d6fb7624952f3df0e09eff1fb11406e"],"add":4,"del":2,"cadd":4,"cdel":2,"files":2},{"repo":"deck-of-cards","hash":"b3f75e5d2f5eebef6d8432ca001d2feba55ec61f","ts":1441408218,"wall":"2015-09-05T02:10","msg":".5px not working in Safari..","body":"","parents":["5d7d8ab3ddcf0110d0567a4eb817948374d332de"],"add":2,"del":2,"cadd":1,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"182abbea3b0abbd5b830d259bf277fe77f770dbc","ts":1441408250,"wall":"2015-09-05T02:10","msg":".5px not working in Safari..","body":"","parents":["b73b0ab72e01d0b4ad8d8c1e1f1251c58450b285"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"36c3c0b8d5235238dd2548b34107cc955b005b50","ts":1441408667,"wall":"2015-09-05T02:17","msg":"refactor CSS files","body":"","parents":["b3f75e5d2f5eebef6d8432ca001d2feba55ec61f"],"add":40,"del":39,"cadd":1,"cdel":1,"files":3},{"repo":"deck-of-cards","hash":"4d1e49854f72120f257153d36d6111780d89bbdd","ts":1441408694,"wall":"2015-09-05T02:18","msg":"refactor CSS files","body":"","parents":["182abbea3b0abbd5b830d259bf277fe77f770dbc"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"f4051c58de6a7f70b902064516fce83d82d061da","ts":1441409326,"wall":"2015-09-05T02:28","msg":"fixed stacking error..","body":"","parents":["36c3c0b8d5235238dd2548b34107cc955b005b50"],"add":5,"del":3,"cadd":5,"cdel":3,"files":3},{"repo":"deck-of-cards","hash":"4b7d739444bcaf87cd7d48566bfea6da24764f8d","ts":1441409379,"wall":"2015-09-05T02:29","msg":"fixed stacking error..","body":"","parents":["4d1e49854f72120f257153d36d6111780d89bbdd"],"add":3,"del":2,"cadd":3,"cdel":2,"files":2},{"repo":"deck-of-cards","hash":"68356a695828e38f4f268dbec489cab15a8d6830","ts":1441414202,"wall":"2015-09-05T03:50","msg":"Update README.md","body":"","parents":["f4051c58de6a7f70b902064516fce83d82d061da"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"845303550450b9bbf784494442defaf76645b585","ts":1441414252,"wall":"2015-09-05T03:50","msg":"Update README.md","body":"","parents":["68356a695828e38f4f268dbec489cab15a8d6830"],"add":1,"del":3,"cadd":1,"cdel":3,"files":1},{"repo":"deck-of-cards","hash":"bc38c1d2b59cf2f30116adfa4851a98da479568d","ts":1441417273,"wall":"2015-09-05T04:41","msg":"Update README.md","body":"","parents":["845303550450b9bbf784494442defaf76645b585"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"dc9cbc8e0b0831ec768afdfa3725182ab387448e","ts":1441417305,"wall":"2015-09-05T04:41","msg":"Update README.md","body":"","parents":["bc38c1d2b59cf2f30116adfa4851a98da479568d"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"24cb92826357916544a5d319ee92239e35d480be","ts":1441419114,"wall":"2015-09-05T05:11","msg":"Update README.md","body":"","parents":["dc9cbc8e0b0831ec768afdfa3725182ab387448e"],"add":3,"del":0,"cadd":3,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"8ee69edec765d720f04e598a35d8fb1c43e5d8f6","ts":1441419158,"wall":"2015-09-05T05:12","msg":"Update README.md","body":"","parents":["24cb92826357916544a5d319ee92239e35d480be"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"90d562bbf6351d907a732fb44ea29ca28fcbe8aa","ts":1441419249,"wall":"2015-09-05T05:14","msg":"Update README.md","body":"","parents":["8ee69edec765d720f04e598a35d8fb1c43e5d8f6"],"add":8,"del":3,"cadd":8,"cdel":3,"files":1},{"repo":"deck-of-cards","hash":"21838fc56249be080bf86900f1b6db0ab9cc308e","ts":1441444532,"wall":"2015-09-05T12:15","msg":"removed adsense","body":"","parents":["4b7d739444bcaf87cd7d48566bfea6da24764f8d"],"add":1,"del":19,"cadd":1,"cdel":19,"files":1},{"repo":"deck-of-cards","hash":"9fac78b576ca6423bfb2e206885cb93f855f1d37","ts":1441445920,"wall":"2015-09-05T12:38","msg":"simplified shuffling","body":"","parents":["90d562bbf6351d907a732fb44ea29ca28fcbe8aa"],"add":12,"del":38,"cadd":12,"cdel":38,"files":5},{"repo":"deck-of-cards","hash":"305c1a6b8f92d9135b2eed87566f9776c80ab09c","ts":1441446011,"wall":"2015-09-05T12:40","msg":"simplified shuffling","body":"","parents":["21838fc56249be080bf86900f1b6db0ab9cc308e"],"add":8,"del":19,"cadd":8,"cdel":19,"files":3},{"repo":"deck-of-cards","hash":"abebd218ae6cbfa2adb5300a871b7160981036eb","ts":1441457902,"wall":"2015-09-05T15:58","msg":"added secret \"winning\" -mode..don't tell anyone....","body":"","parents":["9fac78b576ca6423bfb2e206885cb93f855f1d37"],"add":116,"del":11,"cadd":115,"cdel":11,"files":8},{"repo":"deck-of-cards","hash":"95adcaf2065053ebcf08eab812ed64bb91e8ec12","ts":1441458017,"wall":"2015-09-05T16:00","msg":"added secret \"winning\" mode..don't tell anyone... :)","body":"","parents":["305c1a6b8f92d9135b2eed87566f9776c80ab09c"],"add":95,"del":6,"cadd":95,"cdel":6,"files":3},{"repo":"deck-of-cards","hash":"b8bb2ac0322046263def5d8e3f2beebc919e42b6","ts":1441458373,"wall":"2015-09-05T16:06","msg":"fixed \"winning\" mode","body":"","parents":["abebd218ae6cbfa2adb5300a871b7160981036eb"],"add":5,"del":2,"cadd":5,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"adf844104eb47c447cea1f16b4d9441ac212360a","ts":1441458388,"wall":"2015-09-05T16:06","msg":"fixed \"winning\" mode","body":"","parents":["95adcaf2065053ebcf08eab812ed64bb91e8ec12"],"add":5,"del":2,"cadd":5,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"2a99b7318077d8ae5377d8ebda2d24ea4f0d387e","ts":1441462164,"wall":"2015-09-05T17:09","msg":"Update README.md","body":"","parents":["b8bb2ac0322046263def5d8e3f2beebc919e42b6"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"b16f9d5e3ab85563df31c2ae6f7bf4f82502d73e","ts":1441462925,"wall":"2015-09-05T17:22","msg":"added some secret instructions....","body":"","parents":["2a99b7318077d8ae5377d8ebda2d24ea4f0d387e"],"add":45,"del":1,"cadd":36,"cdel":1,"files":3},{"repo":"deck-of-cards","hash":"24b57633b908aa23132bd4f109951c6c417d439b","ts":1441462979,"wall":"2015-09-05T17:22","msg":"added some secret instructions....","body":"","parents":["adf844104eb47c447cea1f16b4d9441ac212360a"],"add":36,"del":1,"cadd":36,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"2b48c0031794fd8cf16e830b1137723f4ea6d9a3","ts":1441463526,"wall":"2015-09-05T17:32","msg":"added add2home","body":"","parents":["24b57633b908aa23132bd4f109951c6c417d439b"],"add":260,"del":0,"cadd":260,"cdel":0,"files":3},{"repo":"deck-of-cards","hash":"38a67f3e7f132be00b04f610a9795b38395935aa","ts":1441494815,"wall":"2015-09-06T02:13","msg":"remove add2home","body":"","parents":["2b48c0031794fd8cf16e830b1137723f4ea6d9a3"],"add":0,"del":2,"cadd":0,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"4ef2b1cfc58867fcd145dcdd56599c39db97b906","ts":1441494833,"wall":"2015-09-06T02:13","msg":"Delete add2home.js","body":"","parents":["38a67f3e7f132be00b04f610a9795b38395935aa"],"add":0,"del":2,"cadd":0,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"46013cc078678b3182ccb003b26d9f9ea5fec772","ts":1441494852,"wall":"2015-09-06T02:14","msg":"Delete add2home.css","body":"","parents":["4ef2b1cfc58867fcd145dcdd56599c39db97b906"],"add":0,"del":255,"cadd":0,"cdel":255,"files":1},{"repo":"deck-of-cards","hash":"81bc09517f81909f3c3075200eb5081faab46b83","ts":1441494897,"wall":"2015-09-06T02:14","msg":"remove add2home","body":"","parents":["46013cc078678b3182ccb003b26d9f9ea5fec772"],"add":0,"del":1,"cadd":0,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"12ad58e211308314ef8991662ab64c898224af30","ts":1441546213,"wall":"2015-09-06T16:30","msg":"0.0.4","body":"","parents":["b16f9d5e3ab85563df31c2ae6f7bf4f82502d73e"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"45d5e020a67109a34f2bfd653adb9a958baa2aef","ts":1441546321,"wall":"2015-09-06T16:32","msg":"Update README.md","body":"","parents":["12ad58e211308314ef8991662ab64c898224af30"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"8efec6ae83ad53d956d0314ea0b3ed2423d2e4ad","ts":1441546443,"wall":"2015-09-06T16:34","msg":"MIT -> GPL","body":"","parents":["45d5e020a67109a34f2bfd653adb9a958baa2aef"],"add":339,"del":21,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"e04e51f1eb0b1818f7b5336e910ea45334d4c808","ts":1441546476,"wall":"2015-09-06T16:34","msg":"Update README.md","body":"","parents":["8efec6ae83ad53d956d0314ea0b3ed2423d2e4ad"],"add":5,"del":0,"cadd":5,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"00e6754e31f8c8b9a68794928560790dd7443e53","ts":1441546493,"wall":"2015-09-06T16:34","msg":"Update README.md","body":"","parents":["e04e51f1eb0b1818f7b5336e910ea45334d4c808"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"659b0920ac41461c13344e50a7a2c19eb673d6e7","ts":1441547326,"wall":"2015-09-06T16:48","msg":"Realistic face graphics, fixes #8","body":"","parents":["12ad58e211308314ef8991662ab64c898224af30"],"add":1356,"del":59,"cadd":55,"cdel":45,"files":66},{"repo":"deck-of-cards","hash":"8d51f2c45b6fdb91ed258a3387b2f168ef4ada55","ts":1441547423,"wall":"2015-09-06T16:50","msg":"Merge remote-tracking branch 'origin/master'","body":"Conflicts:\n\tREADME.md","parents":["659b0920ac41461c13344e50a7a2c19eb673d6e7","00e6754e31f8c8b9a68794928560790dd7443e53"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"2e0d161170ad2980da2644981a3f32bf2d578bdb","ts":1441547602,"wall":"2015-09-06T16:53","msg":"Realistic face graphics, fixes #8","body":"","parents":["81bc09517f81909f3c3075200eb5081faab46b83"],"add":1145,"del":22,"cadd":23,"cdel":22,"files":58},{"repo":"deck-of-cards","hash":"fa43415aac32dc2f2c9be487a043b73cada459a1","ts":1441547658,"wall":"2015-09-06T16:54","msg":"forgot font..","body":"","parents":["2e0d161170ad2980da2644981a3f32bf2d578bdb"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"821beeba2bf28f369a5b716ad456ac72866d4341","ts":1441547931,"wall":"2015-09-06T16:58","msg":"fixed dragging..","body":"","parents":["fa43415aac32dc2f2c9be487a043b73cada459a1"],"add":3,"del":3,"cadd":3,"cdel":3,"files":2},{"repo":"deck-of-cards","hash":"b19b7a79e495503a2b340ca7c1f8cf279920c84d","ts":1441549182,"wall":"2015-09-06T17:19","msg":"Update README.md","body":"","parents":["8d51f2c45b6fdb91ed258a3387b2f168ef4ada55"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"906d75d7f5c8b27e47e070d9619460724bc5674b","ts":1441549206,"wall":"2015-09-06T17:20","msg":"Update README.md","body":"","parents":["b19b7a79e495503a2b340ca7c1f8cf279920c84d"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"eac28bbb4cbd46d35b94ab86a3a531fc9d36fdfc","ts":1441549348,"wall":"2015-09-06T17:22","msg":"Update README.md","body":"","parents":["906d75d7f5c8b27e47e070d9619460724bc5674b"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"57c6b52de86781edd22c1ab2048802ba2c1d25fb","ts":1441553711,"wall":"2015-09-06T18:35","msg":"fixed dragging, added slight delay to intro..","body":"","parents":["eac28bbb4cbd46d35b94ab86a3a531fc9d36fdfc"],"add":6,"del":6,"cadd":6,"cdel":6,"files":4},{"repo":"deck-of-cards","hash":"a5fdccfce888101f24d77e73bd3c8ceb10b4f1b2","ts":1441553862,"wall":"2015-09-06T18:37","msg":"added small delay to intro..","body":"","parents":["821beeba2bf28f369a5b716ad456ac72866d4341"],"add":2,"del":2,"cadd":2,"cdel":2,"files":2},{"repo":"deck-of-cards","hash":"2af25910fd8ce5c85e00a8f5e818dddf1cdad871","ts":1441554733,"wall":"2015-09-06T18:52","msg":"added fisher-yates shuffle – fixes #9","body":"","parents":["57c6b52de86781edd22c1ab2048802ba2c1d25fb"],"add":33,"del":10,"cadd":33,"cdel":10,"files":4},{"repo":"deck-of-cards","hash":"065b2a5f58d45c46569de5f197b6745636af89a0","ts":1441554819,"wall":"2015-09-06T18:53","msg":"added fisher-yates shuffle – fixes #9","body":"","parents":["a5fdccfce888101f24d77e73bd3c8ceb10b4f1b2"],"add":17,"del":6,"cadd":17,"cdel":6,"files":2},{"repo":"deck-of-cards","hash":"e229594c68eff4d1a60ed328c83c324c233969c2","ts":1441569435,"wall":"2015-09-06T22:57","msg":"added another secret mode.... ;)","body":"","parents":["2af25910fd8ce5c85e00a8f5e818dddf1cdad871"],"add":136,"del":54,"cadd":114,"cdel":48,"files":16},{"repo":"deck-of-cards","hash":"b1658cf151a5603e2381e162bb3607a2b19e8e92","ts":1441569555,"wall":"2015-09-06T22:59","msg":"added another secret mode.... ;)","body":"","parents":["065b2a5f58d45c46569de5f197b6745636af89a0"],"add":73,"del":27,"cadd":73,"cdel":27,"files":3},{"repo":"deck-of-cards","hash":"7a43e1fa082053f7c21378786d69a6fecfc9b05d","ts":1441569671,"wall":"2015-09-06T23:01","msg":"added another secret mode.... ;)","body":"","parents":["b1658cf151a5603e2381e162bb3607a2b19e8e92"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"2e777c880273d845aa42ad3f9bfc291fae0765e2","ts":1441571100,"wall":"2015-09-06T23:25","msg":"Update README.md","body":"","parents":["e229594c68eff4d1a60ed328c83c324c233969c2"],"add":2,"del":0,"cadd":2,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"47d7093e5f8ddfe08376ef92d664d91c82e7bc55","ts":1441639604,"wall":"2015-09-07T18:26","msg":"made deck bit larger on smaller screens..","body":"","parents":["2e777c880273d845aa42ad3f9bfc291fae0765e2"],"add":2,"del":2,"cadd":1,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"a6cec60b65f4c2b9569c23a225d26f3dbe8198d5","ts":1441639625,"wall":"2015-09-07T18:27","msg":"made deck a bit larger on smaller screens..","body":"","parents":["7a43e1fa082053f7c21378786d69a6fecfc9b05d"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"2b28ef625d9d0290f8d471b54c9cd1b58f49f031","ts":1441640066,"wall":"2015-09-07T18:34","msg":"GPL -> LGPL, fixes #13","body":"","parents":["47d7093e5f8ddfe08376ef92d664d91c82e7bc55"],"add":161,"del":335,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"d931b25192ee08f07e116e1bfe8beddd3dbecd6e","ts":1441640086,"wall":"2015-09-07T18:34","msg":"Update README.md","body":"","parents":["2b28ef625d9d0290f8d471b54c9cd1b58f49f031"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"8053e11eaeb3040cc456ee1d32e02b1261f2fb88","ts":1441640232,"wall":"2015-09-07T18:37","msg":"Update README.md","body":"","parents":["d931b25192ee08f07e116e1bfe8beddd3dbecd6e"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"1c6da426b0d0522805d73ed58edd58777f67c2bd","ts":1441660460,"wall":"2015-09-08T00:14","msg":"Update README.md","body":"","parents":["8053e11eaeb3040cc456ee1d32e02b1261f2fb88"],"add":8,"del":0,"cadd":8,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"8eb146eed66a6880ac4a5939a560e2750fb163e5","ts":1441660578,"wall":"2015-09-08T00:16","msg":"Update README.md","body":"","parents":["1c6da426b0d0522805d73ed58edd58777f67c2bd"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"d1e1e29a633bac33e8b1698ac8bcc6fdfc9fd690","ts":1441661222,"wall":"2015-09-08T00:27","msg":"Update README.md","body":"","parents":["8eb146eed66a6880ac4a5939a560e2750fb163e5"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"e784260f0088718ab3daf95f350dc1b20e2d5c10","ts":1441661408,"wall":"2015-09-08T00:30","msg":"Update README.md","body":"","parents":["d1e1e29a633bac33e8b1698ac8bcc6fdfc9fd690"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"c476f646aa1c20fc5422572933548651d6ffcbb4","ts":1441661500,"wall":"2015-09-08T00:31","msg":"Update README.md","body":"","parents":["e784260f0088718ab3daf95f350dc1b20e2d5c10"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"7b7225268f01fd01b83e61a7bf0dd1914522657f","ts":1441661599,"wall":"2015-09-08T00:33","msg":"Update README.md","body":"","parents":["c476f646aa1c20fc5422572933548651d6ffcbb4"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"52dfe23d70b2b972f1905cecfd9da3428a4bb8c4","ts":1441661655,"wall":"2015-09-08T00:34","msg":"Update README.md","body":"","parents":["7b7225268f01fd01b83e61a7bf0dd1914522657f"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"ff2761526f21a7137b18c4a2d7b5b0ae465d7229","ts":1441662400,"wall":"2015-09-08T00:46","msg":"Update README.md","body":"","parents":["52dfe23d70b2b972f1905cecfd9da3428a4bb8c4"],"add":2,"del":0,"cadd":2,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"b8d12014a0f9507f5d89382c0940a3d25086c624","ts":1441672338,"wall":"2015-09-08T03:32","msg":"Update example.js","body":"","parents":["ff2761526f21a7137b18c4a2d7b5b0ae465d7229"],"add":14,"del":2,"cadd":14,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"a13582f8b224c3371040d726cf6f111b896f0e13","ts":1441680125,"wall":"2015-09-08T04:42","msg":"Combine Google font requests","body":"","parents":["b8d12014a0f9507f5d89382c0940a3d25086c624"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"68e8bb374cfa7d9e4d0fedadbe2d02422f598797","ts":1441698379,"wall":"2015-09-08T10:46","msg":"Merge pull request #14 from hubdotcom/patch-1","body":"Combine Google font requests","parents":["b8d12014a0f9507f5d89382c0940a3d25086c624","a13582f8b224c3371040d726cf6f111b896f0e13"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"1dae07a3d1b48ecb74a237f9b7c5a4ee8c9ff86d","ts":1441698526,"wall":"2015-09-08T10:48","msg":"combined google font requests, related to #14","body":"","parents":["68e8bb374cfa7d9e4d0fedadbe2d02422f598797"],"add":2,"del":3,"cadd":1,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"04431cb668a558298f2fb67c3e4ae7e64ad36396","ts":1441698584,"wall":"2015-09-08T10:49","msg":"Combined Google Font requests, related to #14","body":"","parents":["a6cec60b65f4c2b9569c23a225d26f3dbe8198d5"],"add":1,"del":2,"cadd":1,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"61bd3ac45df7fda6b46e07036e7a77165f73ee9a","ts":1441700130,"wall":"2015-09-08T11:15","msg":"Update README.md","body":"","parents":["1dae07a3d1b48ecb74a237f9b7c5a4ee8c9ff86d"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"2fb79df3f362f24b30acf4857f21c82f67c98479","ts":1441700455,"wall":"2015-09-08T11:20","msg":"Update README.md","body":"","parents":["61bd3ac45df7fda6b46e07036e7a77165f73ee9a"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"f2ad7cb36e4fed779d9c554e0fac05090d6b6a3f","ts":1441700714,"wall":"2015-09-08T11:25","msg":"fixed an issue when adding jokers multiple times..","body":"","parents":["2fb79df3f362f24b30acf4857f21c82f67c98479"],"add":3,"del":1,"cadd":3,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"3367c722b8c3fc49126ea3969ed4fe4046dc5d9a","ts":1441700738,"wall":"2015-09-08T11:25","msg":"fixed an issue when adding jokers multiple times..","body":"","parents":["04431cb668a558298f2fb67c3e4ae7e64ad36396"],"add":17,"del":3,"cadd":17,"cdel":3,"files":1},{"repo":"deck-of-cards","hash":"be6443e821233ebdcd42820180bbba2d1e502b0d","ts":1441702407,"wall":"2015-09-08T11:53","msg":"Update README.md","body":"","parents":["f2ad7cb36e4fed779d9c554e0fac05090d6b6a3f"],"add":8,"del":8,"cadd":8,"cdel":8,"files":1},{"repo":"deck-of-cards","hash":"e8c1770447550ef803c5655b91f977ce8e184812","ts":1441702626,"wall":"2015-09-08T11:57","msg":"Update README.md","body":"","parents":["be6443e821233ebdcd42820180bbba2d1e502b0d"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"6aece1b8979ed132aa2a03bb5ab2f9e00b187807","ts":1441702664,"wall":"2015-09-08T11:57","msg":"Update README.md","body":"","parents":["e8c1770447550ef803c5655b91f977ce8e184812"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"08e61db345961b7232b8649330bc8dd1b7c6ebf8","ts":1441702757,"wall":"2015-09-08T11:59","msg":"Update README.md","body":"","parents":["6aece1b8979ed132aa2a03bb5ab2f9e00b187807"],"add":3,"del":0,"cadd":3,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"460a5564ac91b25f6a703f5244cb689a1e8c2d3c","ts":1441703241,"wall":"2015-09-08T12:07","msg":"Update README.md","body":"","parents":["08e61db345961b7232b8649330bc8dd1b7c6ebf8"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"dac0983bfa7a61d9612056f78eb3395f8ece52c7","ts":1441703737,"wall":"2015-09-08T12:15","msg":"point to deck-of-cards.github.io","body":"","parents":["3367c722b8c3fc49126ea3969ed4fe4046dc5d9a"],"add":5,"del":3,"cadd":5,"cdel":3,"files":1},{"repo":"deck-of-cards","hash":"312d40ec4860b6d84e5887bc72b22a743e515cbb","ts":1441703937,"wall":"2015-09-08T12:18","msg":"Update README.md","body":"","parents":["460a5564ac91b25f6a703f5244cb689a1e8c2d3c"],"add":4,"del":4,"cadd":4,"cdel":4,"files":1},{"repo":"deck-of-cards","hash":"4e6732f79c440898aaa929e8e3b4a6d3c550eae6","ts":1441707107,"wall":"2015-09-08T13:11","msg":"Update README.md","body":"","parents":["312d40ec4860b6d84e5887bc72b22a743e515cbb"],"add":9,"del":12,"cadd":9,"cdel":12,"files":1},{"repo":"deck-of-cards","hash":"ad4d23047c3ca8e0bade1ae6f3a9592ab2128050","ts":1441707202,"wall":"2015-09-08T13:13","msg":"call back!","body":"","parents":["dac0983bfa7a61d9612056f78eb3395f8ece52c7"],"add":3,"del":4,"cadd":3,"cdel":4,"files":1},{"repo":"deck-of-cards","hash":"638019336b0ab2a9345bf4641c30cf8f22189042","ts":1441707323,"wall":"2015-09-08T13:15","msg":"call back!","body":"","parents":["ad4d23047c3ca8e0bade1ae6f3a9592ab2128050"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"580d7c23861d046b4e30003aae2130890793cea9","ts":1441717462,"wall":"2015-09-08T16:04","msg":"added carbon ads","body":"","parents":["638019336b0ab2a9345bf4641c30cf8f22189042"],"add":373,"del":5,"cadd":373,"cdel":5,"files":3},{"repo":"deck-of-cards","hash":"002d4cf5ae9dfa174ccfff958792e7861d990b7e","ts":1441717690,"wall":"2015-09-08T16:08","msg":"fixed text padding..","body":"","parents":["580d7c23861d046b4e30003aae2130890793cea9"],"add":2,"del":1,"cadd":2,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"6f599f7cf0275d4bfd1bcfd7d55a2c854dab184f","ts":1441718107,"wall":"2015-09-08T16:15","msg":"made horizontal","body":"","parents":["002d4cf5ae9dfa174ccfff958792e7861d990b7e"],"add":8,"del":5,"cadd":8,"cdel":5,"files":1},{"repo":"deck-of-cards","hash":"cf376e07a13c21a91a4aa82c67da089de41168e6","ts":1441718267,"wall":"2015-09-08T16:17","msg":"Update README.md","body":"","parents":["4e6732f79c440898aaa929e8e3b4a6d3c550eae6"],"add":4,"del":4,"cadd":4,"cdel":4,"files":1},{"repo":"deck-of-cards","hash":"f1a3cf55261434625fd387aba3c022a2fb24ac71","ts":1441718663,"wall":"2015-09-08T16:24","msg":"modules are now better organized","body":"","parents":["6f599f7cf0275d4bfd1bcfd7d55a2c854dab184f"],"add":303,"del":276,"cadd":303,"cdel":276,"files":2},{"repo":"deck-of-cards","hash":"11c6212b07feeffca09a9d1189957a86f9818950","ts":1441718762,"wall":"2015-09-08T16:26","msg":"modules now better organized","body":"","parents":["cf376e07a13c21a91a4aa82c67da089de41168e6"],"add":983,"del":620,"cadd":980,"cdel":616,"files":25},{"repo":"deck-of-cards","hash":"72a2e81404366332ae893b0e56d36ccf40795c0a","ts":1441719167,"wall":"2015-09-08T16:32","msg":"relocated message","body":"","parents":["11c6212b07feeffca09a9d1189957a86f9818950"],"add":2,"del":2,"cadd":1,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"f44bff5ffbe22ef69b71878ae6c1c2dee25a9289","ts":1441719194,"wall":"2015-09-08T16:33","msg":"relocated message","body":"","parents":["f1a3cf55261434625fd387aba3c022a2fb24ac71"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"7f876a3a3c74221ef853aa0887f4d611e3f4a453","ts":1441719443,"wall":"2015-09-08T16:37","msg":"added redirect","body":"","parents":["f44bff5ffbe22ef69b71878ae6c1c2dee25a9289"],"add":3,"del":0,"cadd":3,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"34ce0543c6bdf1940f5f187e9ae32d82e32199e5","ts":1441719625,"wall":"2015-09-08T16:40","msg":"Update README.md","body":"","parents":["72a2e81404366332ae893b0e56d36ccf40795c0a"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"17559c4d6144fcff03058f122248635393c8fb3f","ts":1441731079,"wall":"2015-09-08T19:51","msg":"added Chrome app source","body":"","parents":["34ce0543c6bdf1940f5f187e9ae32d82e32199e5"],"add":48,"del":0,"cadd":24,"cdel":0,"files":6},{"repo":"deck-of-cards","hash":"4419a63db7c8a7efd011d70d36c58bdf6fa0ad42","ts":1441731117,"wall":"2015-09-08T19:51","msg":"Update README.md","body":"","parents":["17559c4d6144fcff03058f122248635393c8fb3f"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"4d45ff37ca268db9612c4aed788bd0a85d3bf968","ts":1441731237,"wall":"2015-09-08T19:53","msg":"Update README.md","body":"","parents":["4419a63db7c8a7efd011d70d36c58bdf6fa0ad42"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"6c4bc3616af03da498bc2d0437be1803bb892220","ts":1441731966,"wall":"2015-09-08T20:06","msg":"Update README.md","body":"","parents":["4d45ff37ca268db9612c4aed788bd0a85d3bf968"],"add":3,"del":1,"cadd":3,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"1c6f271c552310c23f351bbc59f4fb6fb6bb581a","ts":1441751679,"wall":"2015-09-09T01:34","msg":"Update README.md","body":"","parents":["6c4bc3616af03da498bc2d0437be1803bb892220"],"add":4,"del":0,"cadd":4,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"f3558bee4eab00c2eda3b14a3320255f25026244","ts":1441751705,"wall":"2015-09-09T01:35","msg":"Update README.md","body":"","parents":["1c6f271c552310c23f351bbc59f4fb6fb6bb581a"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"e8cd409d7d42f310d09b9c4bc37f275dfaba534d","ts":1441802417,"wall":"2015-09-09T15:40","msg":"prettyfied Jade, fixed font issue","body":"","parents":["f3558bee4eab00c2eda3b14a3320255f25026244"],"add":18,"del":3,"cadd":16,"cdel":1,"files":3},{"repo":"deck-of-cards","hash":"9e7a6c110a492887f2851596e028801aa48de5d0","ts":1441804998,"wall":"2015-09-09T16:23","msg":"Update README.md","body":"","parents":["e8cd409d7d42f310d09b9c4bc37f275dfaba534d"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"e46ec1211e44236f5d3357ed51e9cbc1d227b107","ts":1441831797,"wall":"2015-09-09T23:49","msg":"Update README.md","body":"","parents":["9e7a6c110a492887f2851596e028801aa48de5d0"],"add":1,"del":4,"cadd":1,"cdel":4,"files":1},{"repo":"deck-of-cards","hash":"1c8e75ecf2fc24f1f7c6b7a6cce474e20936b976","ts":1442140703,"wall":"2015-09-13T13:38","msg":"fixed dragging","body":"","parents":["e46ec1211e44236f5d3357ed51e9cbc1d227b107"],"add":154,"del":55,"cadd":154,"cdel":55,"files":10},{"repo":"deck-of-cards","hash":"12140cf3378d3148487b4a00904e26a8453d797e","ts":1442140767,"wall":"2015-09-13T13:39","msg":"fixed dragging","body":"","parents":["7f876a3a3c74221ef853aa0887f4d611e3f4a453"],"add":76,"del":28,"cadd":76,"cdel":28,"files":2},{"repo":"deck-of-cards","hash":"37cec38a52a23521eb75876fe48ecb15d6ab2442","ts":1442142392,"wall":"2015-09-13T14:06","msg":"fixed dragging on touch screen","body":"","parents":["1c8e75ecf2fc24f1f7c6b7a6cce474e20936b976"],"add":7,"del":13,"cadd":7,"cdel":13,"files":3},{"repo":"deck-of-cards","hash":"c199d2341aea36b50db19aa2352b0bfdf228b136","ts":1442142439,"wall":"2015-09-13T14:07","msg":"fixed dragging on touch screen","body":"","parents":["12140cf3378d3148487b4a00904e26a8453d797e"],"add":4,"del":7,"cadd":4,"cdel":7,"files":2},{"repo":"deck-of-cards","hash":"ec91d1276fbd425c89badb26c48bdd937117ad3e","ts":1442143246,"wall":"2015-09-13T14:20","msg":"fixed another issue with dragging on touch screen","body":"","parents":["c199d2341aea36b50db19aa2352b0bfdf228b136"],"add":8,"del":8,"cadd":8,"cdel":8,"files":2},{"repo":"deck-of-cards","hash":"1bd6eeb4cadad656cc435d12f27fe666ba6db004","ts":1442143264,"wall":"2015-09-13T14:21","msg":"fixed an issue with dragging","body":"","parents":["37cec38a52a23521eb75876fe48ecb15d6ab2442"],"add":15,"del":15,"cadd":15,"cdel":15,"files":3},{"repo":"deck-of-cards","hash":"19b119fe2497a9c8a1416a787535003ec3740c27","ts":1442165591,"wall":"2015-09-13T20:33","msg":"added preliminary flip support","body":"","parents":["1bd6eeb4cadad656cc435d12f27fe666ba6db004"],"add":287,"del":44,"cadd":240,"cdel":42,"files":12},{"repo":"deck-of-cards","hash":"0ca38c3557972eb4cc4b0be45e198ffcc5706b1a","ts":1442165657,"wall":"2015-09-13T20:34","msg":"added preliminary flip support..","body":"","parents":["ec91d1276fbd425c89badb26c48bdd937117ad3e"],"add":111,"del":29,"cadd":111,"cdel":29,"files":2},{"repo":"deck-of-cards","hash":"59730590ea57824f628093fb0b1911bfb1d270f3","ts":1442165826,"wall":"2015-09-13T20:37","msg":"added back graphics","body":"","parents":["0ca38c3557972eb4cc4b0be45e198ffcc5706b1a"],"add":31,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"56b7bd9aedb512d23e211a2f8e55343732dccc93","ts":1442165905,"wall":"2015-09-13T20:38","msg":"Update README.md","body":"","parents":["19b119fe2497a9c8a1416a787535003ec3740c27"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"5ed1dca49a20fe9f4b15177b7df56296e7f82bcf","ts":1442165915,"wall":"2015-09-13T20:38","msg":"Update README.md","body":"","parents":["56b7bd9aedb512d23e211a2f8e55343732dccc93"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"f06685870b8301c50b2056fcd69189511e9ce869","ts":1442165922,"wall":"2015-09-13T20:38","msg":"Update README.md","body":"","parents":["5ed1dca49a20fe9f4b15177b7df56296e7f82bcf"],"add":3,"del":1,"cadd":3,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"2fcf3e104579989ca179b76b63e37725387e7af1","ts":1442166044,"wall":"2015-09-13T20:40","msg":"backside added","body":"","parents":["59730590ea57824f628093fb0b1911bfb1d270f3"],"add":36,"del":3,"cadd":36,"cdel":3,"files":2},{"repo":"deck-of-cards","hash":"2157712f2aaffc2dc2d7b16246efc4f90e9df7e4","ts":1442166211,"wall":"2015-09-13T20:43","msg":"less border-radius","body":"","parents":["2fcf3e104579989ca179b76b63e37725387e7af1"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"c50078e2eda15645ecb4d61e0d674df8e6ea0a6c","ts":1442167878,"wall":"2015-09-13T21:11","msg":"less border-radius","body":"","parents":["f06685870b8301c50b2056fcd69189511e9ce869"],"add":3,"del":3,"cadd":2,"cdel":2,"files":2},{"repo":"deck-of-cards","hash":"c5ef2b8c2529f9a7c2cfb129c6cd294489a5185b","ts":1442170318,"wall":"2015-09-13T21:51","msg":"added setRankSuit + rounded poker & bySuit coordinates..","body":"","parents":["c50078e2eda15645ecb4d61e0d674df8e6ea0a6c"],"add":39,"del":47,"cadd":39,"cdel":47,"files":5},{"repo":"deck-of-cards","hash":"b2d5dae364dbfe6ab6b05da03b10e878d8550bdb","ts":1442170387,"wall":"2015-09-13T21:53","msg":"added setRankSuit + rounded bySuit & poker coordinates","body":"","parents":["2157712f2aaffc2dc2d7b16246efc4f90e9df7e4"],"add":20,"del":24,"cadd":20,"cdel":24,"files":2},{"repo":"deck-of-cards","hash":"115f59f05e1607c7764a3c1be83d9286c0bfc013","ts":1442171498,"wall":"2015-09-13T22:11","msg":"fixed small issue..","body":"","parents":["c5ef2b8c2529f9a7c2cfb129c6cd294489a5185b"],"add":7,"del":1,"cadd":7,"cdel":1,"files":3},{"repo":"deck-of-cards","hash":"5d28828e1bf0ac79d3920205cbd78751b47600be","ts":1442171550,"wall":"2015-09-13T22:12","msg":"small fix..","body":"","parents":["b2d5dae364dbfe6ab6b05da03b10e878d8550bdb"],"add":4,"del":1,"cadd":4,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"66b3f64c3723b37ab8777696dba58b9dd1126777","ts":1442171909,"wall":"2015-09-13T22:18","msg":"0.1.1","body":"","parents":["115f59f05e1607c7764a3c1be83d9286c0bfc013"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"982b50de979977978e0bc3d89bbd8770ded715ac","ts":1442171982,"wall":"2015-09-13T22:19","msg":"0.1.2","body":"","parents":["66b3f64c3723b37ab8777696dba58b9dd1126777"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"1f28268f41b1ab005c121ba3498fabfc0f27e36a","ts":1442179546,"wall":"2015-09-14T00:25","msg":"rank killed the bySuit star..","body":"","parents":["982b50de979977978e0bc3d89bbd8770ded715ac"],"add":5,"del":5,"cadd":5,"cdel":5,"files":3},{"repo":"deck-of-cards","hash":"2d6660dabbbdeba24fc89b5a4f924bade1058718","ts":1442179599,"wall":"2015-09-14T00:26","msg":"rank killed the bySuit star..","body":"","parents":["5d28828e1bf0ac79d3920205cbd78751b47600be"],"add":3,"del":3,"cadd":3,"cdel":3,"files":2},{"repo":"deck-of-cards","hash":"d61884b47b8cdb7a235ef3076f6cb608c1b0aa7f","ts":1442180067,"wall":"2015-09-14T00:34","msg":"changed order and flipped jokers when introduced..","body":"","parents":["1f28268f41b1ab005c121ba3498fabfc0f27e36a"],"add":3,"del":2,"cadd":3,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"6bc9c921fff4ddca96d6661dd77538fbcf2f6396","ts":1442180414,"wall":"2015-09-14T00:40","msg":"changed the order of buttons & fixed jokers introduction","body":"","parents":["2d6660dabbbdeba24fc89b5a4f924bade1058718"],"add":4,"del":3,"cadd":4,"cdel":3,"files":2},{"repo":"deck-of-cards","hash":"cd87aa84edef558143e63867b24e50923ca5bd64","ts":1442180477,"wall":"2015-09-14T00:41","msg":"changed something..?","body":"","parents":["6bc9c921fff4ddca96d6661dd77538fbcf2f6396"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"5697c26dbe253d59afd11146475509e2d8dca89e","ts":1442180585,"wall":"2015-09-14T00:43","msg":"added lang","body":"","parents":["cd87aa84edef558143e63867b24e50923ca5bd64"],"add":2,"del":2,"cadd":2,"cdel":2,"files":2},{"repo":"deck-of-cards","hash":"c705bb15a57f767680db53a6e966021ece90034c","ts":1442181290,"wall":"2015-09-14T00:54","msg":"bit greener..","body":"","parents":["d61884b47b8cdb7a235ef3076f6cb608c1b0aa7f"],"add":2,"del":2,"cadd":1,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"c50bb16b44890266088c9c1cccca74437cbab3f6","ts":1442181310,"wall":"2015-09-14T00:55","msg":"bit greener..","body":"","parents":["5697c26dbe253d59afd11146475509e2d8dca89e"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"927755e85f97b4c617931ca9c0f7b0f6d804bd18","ts":1442186420,"wall":"2015-09-13T20:20","msg":"Fix issue when loading the library before DOM is ready.","body":"","parents":["c705bb15a57f767680db53a6e966021ece90034c"],"add":21,"del":17,"cadd":21,"cdel":17,"files":3},{"repo":"deck-of-cards","hash":"4104b1b144a14f5aac112af4386357eb09781384","ts":1442207434,"wall":"2015-09-14T08:10","msg":"small change to make more cross browser..","body":"","parents":["927755e85f97b4c617931ca9c0f7b0f6d804bd18"],"add":28,"del":21,"cadd":28,"cdel":21,"files":4},{"repo":"deck-of-cards","hash":"0cc77107a609a5704010686c006a476d3b49389d","ts":1442208151,"wall":"2015-09-14T08:22","msg":"Merge pull request #16 from pakastin/pr/15","body":"Pr/15","parents":["c705bb15a57f767680db53a6e966021ece90034c","4104b1b144a14f5aac112af4386357eb09781384"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"66019f7ebbf1d77141cd45c24c64ae1c4224b648","ts":1442208761,"wall":"2015-09-14T08:32","msg":"#16","body":"","parents":["c50bb16b44890266088c9c1cccca74437cbab3f6"],"add":18,"del":13,"cadd":18,"cdel":13,"files":2},{"repo":"deck-of-cards","hash":"ea9742dec47e602de970f49a36f518135d797d98","ts":1442209243,"wall":"2015-09-14T08:40","msg":"fix jokers' flipping","body":"","parents":["0cc77107a609a5704010686c006a476d3b49389d"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"6e48fefeb56d2265ff169b50ad7f5e2c0de0effd","ts":1442209254,"wall":"2015-09-14T08:40","msg":"fix jokers' flipping","body":"","parents":["66019f7ebbf1d77141cd45c24c64ae1c4224b648"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"32df55bdf093d61e0f3670c02f158f8bd9730830","ts":1442216219,"wall":"2015-09-14T10:36","msg":"Update README.md","body":"","parents":["ea9742dec47e602de970f49a36f518135d797d98"],"add":2,"del":0,"cadd":2,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"1f75aef7e4121c2e7a60b2a41e33a9a06038b32b","ts":1442234680,"wall":"2015-09-14T15:44","msg":"Update README.md","body":"","parents":["32df55bdf093d61e0f3670c02f158f8bd9730830"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"fd2449a2c6139dec94c6df83f9951e5ce7760c8b","ts":1442337486,"wall":"2015-09-15T14:18","msg":"Add `jsnext:main` for better ES6 module packaging.","body":"The [rollup wiki](https://github.com/rollup/rollup/wiki/jsnext:main) has\ngood arguments in favor of using `jsnext:main`.  This fits perfectly\nwith this library's usage of ES6.","parents":["1f75aef7e4121c2e7a60b2a41e33a9a06038b32b"],"add":1,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"4dab72f52aef7d25b21b20236ab8afd123abe790","ts":1442338403,"wall":"2015-09-15T20:33","msg":"Merge pull request #17 from jansegre/master","body":"Add `jsnext:main` for better ES6 module packaging.","parents":["1f75aef7e4121c2e7a60b2a41e33a9a06038b32b","fd2449a2c6139dec94c6df83f9951e5ce7760c8b"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"aa2b545f24f6ef7abb1f9b47cf26933b32757b71","ts":1442415169,"wall":"2015-09-16T17:52","msg":"css transition -> JS animation","body":"","parents":["4dab72f52aef7d25b21b20236ab8afd123abe790"],"add":670,"del":284,"cadd":663,"cdel":279,"files":17},{"repo":"deck-of-cards","hash":"8fc5c16d0225b4fc5b5d32eb861d878c1269b03d","ts":1442415481,"wall":"2015-09-16T17:58","msg":"CSS transition -> JS animation","body":"","parents":["6e48fefeb56d2265ff169b50ad7f5e2c0de0effd"],"add":322,"del":149,"cadd":322,"cdel":149,"files":5},{"repo":"deck-of-cards","hash":"d29ab8ac2aa4ed38dbdec4723752c3094290c010","ts":1442415954,"wall":"2015-09-16T18:05","msg":"removed one shuffle","body":"","parents":["aa2b545f24f6ef7abb1f9b47cf26933b32757b71"],"add":19,"del":1,"cadd":19,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"784cd2b391dc9224a86d6ead092801758f28ca23","ts":1442415974,"wall":"2015-09-16T18:06","msg":"removed return","body":"","parents":["8fc5c16d0225b4fc5b5d32eb861d878c1269b03d"],"add":0,"del":1,"cadd":0,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"f72fcf0817bf9776cc334647ea692edb7dabe504","ts":1442416027,"wall":"2015-09-16T18:07","msg":"Delete test.js","body":"","parents":["d29ab8ac2aa4ed38dbdec4723752c3094290c010"],"add":0,"del":19,"cadd":0,"cdel":19,"files":1},{"repo":"deck-of-cards","hash":"91bee01a150021d080bdd5439b5d834e650591c8","ts":1442416135,"wall":"2015-09-16T18:08","msg":"Update README.md","body":"","parents":["f72fcf0817bf9776cc334647ea692edb7dabe504"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"44ef7a46bec945ceb82321ea5e79473a8aa97966","ts":1442416993,"wall":"2015-09-16T18:23","msg":"added comments + fixed one bug","body":"","parents":["91bee01a150021d080bdd5439b5d834e650591c8"],"add":133,"del":43,"cadd":133,"cdel":43,"files":8},{"repo":"deck-of-cards","hash":"6ad20a5a32cf9ffe8e8253739309702f0d316885","ts":1442417081,"wall":"2015-09-16T18:24","msg":"added comments + fixed one bug","body":"","parents":["784cd2b391dc9224a86d6ead092801758f28ca23"],"add":65,"del":18,"cadd":65,"cdel":18,"files":2},{"repo":"deck-of-cards","hash":"1a90c436809fadacc028e042005307bd1c50f731","ts":1442417151,"wall":"2015-09-16T18:25","msg":"enableMoving -> enableDragging","body":"","parents":["6ad20a5a32cf9ffe8e8253739309702f0d316885"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"4ce5c2fe7045a28a4b3a41ad27f64472771411b1","ts":1442417543,"wall":"2015-09-16T18:32","msg":"added twitter card meta","body":"","parents":["1a90c436809fadacc028e042005307bd1c50f731"],"add":6,"del":0,"cadd":6,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"2f7ab4a3cb047fbf88deee2fb5cb95fc88e1d667","ts":1442417629,"wall":"2015-09-16T18:33","msg":"changed facebook share/image url","body":"","parents":["4ce5c2fe7045a28a4b3a41ad27f64472771411b1"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"39091d4ce22e5eed9762befcca03ef3f94691b84","ts":1442417784,"wall":"2015-09-16T18:36","msg":"summary_large_image -> summary","body":"","parents":["2f7ab4a3cb047fbf88deee2fb5cb95fc88e1d667"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"20c1f9311cde1ca63edc6a4eb7a5f39e991d7587","ts":1442423538,"wall":"2015-09-16T14:12","msg":"Correct red tone on card ranks.","body":"","parents":["44ef7a46bec945ceb82321ea5e79473a8aa97966"],"add":3,"del":3,"cadd":1,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"c1a50c03f0150187e56d236dd1b82a43e4e2b31b","ts":1442424114,"wall":"2015-09-16T14:21","msg":"Fix: easing was removed, some references were not.","body":"","parents":["20c1f9311cde1ca63edc6a4eb7a5f39e991d7587"],"add":1,"del":10,"cadd":1,"cdel":10,"files":3},{"repo":"deck-of-cards","hash":"a6c45483408c27f5e1240f6e79f90446f1aa8145","ts":1442424382,"wall":"2015-09-16T14:26","msg":"Use css for card labels for better theming support.","body":"","parents":["c1a50c03f0150187e56d236dd1b82a43e4e2b31b"],"add":379,"del":292,"cadd":144,"cdel":108,"files":5},{"repo":"deck-of-cards","hash":"f18b6a95e10f3f4122759acb0f405a7fb96f856b","ts":1442430398,"wall":"2015-09-16T22:06","msg":"Merge pull request #18 from jansegre/master","body":"Correct red tone on card ranks.","parents":["44ef7a46bec945ceb82321ea5e79473a8aa97966","c1a50c03f0150187e56d236dd1b82a43e4e2b31b"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"94a910e72ece7f11ba74ea22bae2077804141eec","ts":1442430509,"wall":"2015-09-16T22:08","msg":"changed backside graphics","body":"","parents":["f18b6a95e10f3f4122759acb0f405a7fb96f856b"],"add":1344,"del":45,"cadd":8,"cdel":13,"files":3},{"repo":"deck-of-cards","hash":"e43269bfa0d1c4ada67d136d323aea405f58665f","ts":1442430644,"wall":"2015-09-16T22:10","msg":"Merge branch 'master' into pr/19","body":"Conflicts:\n\tcss/card.styl","parents":["a6c45483408c27f5e1240f6e79f90446f1aa8145","94a910e72ece7f11ba74ea22bae2077804141eec"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"bae1033e31097903ef240b6ceb704562e53874a1","ts":1442430766,"wall":"2015-09-16T22:12","msg":"Merge pull request #20 from pakastin/pr/19","body":"Pr/19","parents":["94a910e72ece7f11ba74ea22bae2077804141eec","e43269bfa0d1c4ada67d136d323aea405f58665f"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"c56570c74cb2bae99ce088d41c99bb006a00335a","ts":1442430942,"wall":"2015-09-16T22:15","msg":"new backside graphics + better theming","body":"","parents":["39091d4ce22e5eed9762befcca03ef3f94691b84"],"add":1482,"del":140,"cadd":152,"cdel":117,"files":4},{"repo":"deck-of-cards","hash":"08e971a096f24e9fb3f9f6c16c41adae99a07774","ts":1442432462,"wall":"2015-09-16T22:41","msg":"temporary fix for backside graphics (PNG)","body":"","parents":["c56570c74cb2bae99ce088d41c99bb006a00335a"],"add":1,"del":1,"cadd":1,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"761eed89f99efe073b0b77453dcd960dae7a5804","ts":1442441071,"wall":"2015-09-17T01:04","msg":"fixed winning mode!","body":"","parents":["bae1033e31097903ef240b6ceb704562e53874a1"],"add":159,"del":141,"cadd":159,"cdel":141,"files":4},{"repo":"deck-of-cards","hash":"d20c55a28f982d888fd34f5e7f5ac9cf3fbc71c0","ts":1442441140,"wall":"2015-09-17T01:05","msg":"fixed winning mode!","body":"","parents":["08e971a096f24e9fb3f9f6c16c41adae99a07774"],"add":155,"del":141,"cadd":155,"cdel":141,"files":3},{"repo":"deck-of-cards","hash":"d9ff5d15dfa7e6ad59f37967cb53da5864b40cfb","ts":1442443134,"wall":"2015-09-17T01:38","msg":"updated back graphic","body":"","parents":["d20c55a28f982d888fd34f5e7f5ac9cf3fbc71c0"],"add":0,"del":1338,"cadd":0,"cdel":0,"files":2},{"repo":"deck-of-cards","hash":"36304acc3b4362eccf843a8bc4dcedab1e6b414b","ts":1442443184,"wall":"2015-09-17T01:39","msg":"updated backside graphic","body":"","parents":["761eed89f99efe073b0b77453dcd960dae7a5804"],"add":0,"del":1338,"cadd":0,"cdel":0,"files":2},{"repo":"deck-of-cards","hash":"f35d35d50ef5b0a7e7655950eae012388468083a","ts":1442538271,"wall":"2015-09-18T04:04","msg":"fixed secret message + svg->png","body":"","parents":["36304acc3b4362eccf843a8bc4dcedab1e6b414b"],"add":22,"del":13,"cadd":21,"cdel":12,"files":3},{"repo":"deck-of-cards","hash":"c8422d0c2c98e21d8a9e918682d61752821e824c","ts":1442538324,"wall":"2015-09-18T04:05","msg":"fixed secret message","body":"","parents":["d9ff5d15dfa7e6ad59f37967cb53da5864b40cfb"],"add":20,"del":11,"cadd":20,"cdel":11,"files":1},{"repo":"deck-of-cards","hash":"2ef931af70a50b75b8fd20a5441388394e7a24c3","ts":1442694077,"wall":"2015-09-19T23:21","msg":"translate3d only on mobile (performance is worse on desktop)","body":"","parents":["f35d35d50ef5b0a7e7655950eae012388468083a"],"add":17,"del":1,"cadd":17,"cdel":1,"files":3},{"repo":"deck-of-cards","hash":"a555049fcb4513d1a56b4fee00d5b77750195186","ts":1442694127,"wall":"2015-09-19T23:22","msg":"translate3d only on mobile (performance is worse on desktop)","body":"","parents":["c8422d0c2c98e21d8a9e918682d61752821e824c"],"add":9,"del":1,"cadd":9,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"ec5542a812ae7feda8fd69fe8132311fc3dd0464","ts":1443048664,"wall":"2015-09-24T01:51","msg":"added card.animateTo() -method!","body":"","parents":["2ef931af70a50b75b8fd20a5441388394e7a24c3"],"add":717,"del":766,"cadd":716,"cdel":765,"files":12},{"repo":"deck-of-cards","hash":"ad6e56108c0081a7d706753eac96d227b4b9adcc","ts":1443048673,"wall":"2015-09-24T01:51","msg":"0.1.3","body":"","parents":["ec5542a812ae7feda8fd69fe8132311fc3dd0464"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"e0672b9e924cb1b2c0f824fcef267cd2d86583bd","ts":1443048868,"wall":"2015-09-24T01:54","msg":"0.1.4","body":"","parents":["40b359c37a3ef5eb47b02a476fe588030236771c"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"e89e1ec3e8b6fa8d547145e733f0fd183e507d32","ts":1443048924,"wall":"2015-09-24T01:55","msg":"Update README.md","body":"","parents":["ad6e56108c0081a7d706753eac96d227b4b9adcc"],"add":25,"del":23,"cadd":25,"cdel":23,"files":1},{"repo":"deck-of-cards","hash":"2130d45061770b4999fe4c78833fc3412956c9d9","ts":1443048945,"wall":"2015-09-24T01:55","msg":"Update README.md","body":"","parents":["e89e1ec3e8b6fa8d547145e733f0fd183e507d32"],"add":1,"del":3,"cadd":1,"cdel":3,"files":1},{"repo":"deck-of-cards","hash":"512b4dd81a44b1ab2274bb2f3aad624fed5b579b","ts":1443048961,"wall":"2015-09-24T01:56","msg":"Update README.md","body":"","parents":["2130d45061770b4999fe4c78833fc3412956c9d9"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"e5e94e1b805642a261bdc930d931c3705146f979","ts":1443048982,"wall":"2015-09-24T01:56","msg":"Update README.md","body":"","parents":["512b4dd81a44b1ab2274bb2f3aad624fed5b579b"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"40b359c37a3ef5eb47b02a476fe588030236771c","ts":1443049007,"wall":"2015-09-24T01:56","msg":"Update README.md","body":"","parents":["e5e94e1b805642a261bdc930d931c3705146f979"],"add":0,"del":1,"cadd":0,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"c828bbde3996f73bc004919fc12630107355c47c","ts":1443049204,"wall":"2015-09-24T02:00","msg":"added card.animateTo() -method -> simplier modules","body":"","parents":["a555049fcb4513d1a56b4fee00d5b77750195186"],"add":581,"del":537,"cadd":581,"cdel":537,"files":3},{"repo":"deck-of-cards","hash":"5dde7b1d49d47f9d7203c1599baec82f8ae88145","ts":1443050791,"wall":"2015-09-24T02:26","msg":"Update README.md","body":"","parents":["e0672b9e924cb1b2c0f824fcef267cd2d86583bd"],"add":5,"del":6,"cadd":5,"cdel":6,"files":1},{"repo":"deck-of-cards","hash":"9e806c267425c415c1cc3eff1832a8a2de92bad4","ts":1443050841,"wall":"2015-09-24T02:27","msg":"Update README.md","body":"","parents":["5dde7b1d49d47f9d7203c1599baec82f8ae88145"],"add":7,"del":10,"cadd":7,"cdel":10,"files":1},{"repo":"deck-of-cards","hash":"982e17bc9521ae853db4330acfb38fb9b47851b7","ts":1443087334,"wall":"2015-09-24T12:35","msg":"Update README.md","body":"","parents":["9e806c267425c415c1cc3eff1832a8a2de92bad4"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"29190e13e7ed7df6f7ba9f5950e9cffcae470a7f","ts":1443131429,"wall":"2015-09-25T00:50","msg":"addthis added","body":"","parents":["c828bbde3996f73bc004919fc12630107355c47c"],"add":17,"del":1,"cadd":17,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"4d3089e5b0be1599e210de3d7b24d9d0db95c045","ts":1443132217,"wall":"2015-09-25T01:03","msg":"small fix","body":"","parents":["29190e13e7ed7df6f7ba9f5950e9cffcae470a7f"],"add":11,"del":1,"cadd":11,"cdel":1,"files":2},{"repo":"deck-of-cards","hash":"751ae695e3191bbb9ddaf65ff82ca33b5b24821f","ts":1443132548,"wall":"2015-09-25T01:09","msg":"needsclick","body":"","parents":["4d3089e5b0be1599e210de3d7b24d9d0db95c045"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"fadeaa289956057533a5968cbbc9abc7454a2063","ts":1443133105,"wall":"2015-09-25T01:18","msg":"removed needsclick","body":"","parents":["751ae695e3191bbb9ddaf65ff82ca33b5b24821f"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"c12acfdc1701e93193a594cbb76caec4f368dc05","ts":1443187667,"wall":"2015-09-25T16:27","msg":"Update README.md","body":"","parents":["982e17bc9521ae853db4330acfb38fb9b47851b7"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"b3374fe055329e84c8e87009bdfe0946c63e7105","ts":1443187703,"wall":"2015-09-25T16:28","msg":"Update README.md","body":"","parents":["c12acfdc1701e93193a594cbb76caec4f368dc05"],"add":0,"del":1,"cadd":0,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"9d5ee8edf895c6f160cad079832505ad35c4e312","ts":1443789580,"wall":"2015-10-02T08:39","msg":"Restore original z-indices when performing Deck.fan()","body":"","parents":["b3374fe055329e84c8e87009bdfe0946c63e7105"],"add":13,"del":1,"cadd":13,"cdel":1,"files":3},{"repo":"deck-of-cards","hash":"7a492154cea535c838de20877e4e1e0d89f8feb1","ts":1443792165,"wall":"2015-10-02T16:22","msg":"Merge pull request #22 from ceautery/fan_zIndex","body":"Restore original z-indices when performing Deck.fan()","parents":["b3374fe055329e84c8e87009bdfe0946c63e7105","9d5ee8edf895c6f160cad079832505ad35c4e312"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"d533ad92303c238f927f0d3479e4012e42b2af0f","ts":1443800413,"wall":"2015-10-02T11:40","msg":"Fixed animationFrames case ambiguity","body":"","parents":["7a492154cea535c838de20877e4e1e0d89f8feb1"],"add":6,"del":96,"cadd":6,"cdel":96,"files":5},{"repo":"deck-of-cards","hash":"69db502e0b42fcc345aaf3f170207fd4ead2a06e","ts":1443885593,"wall":"2015-10-03T18:19","msg":"#23 + other camelCasing fixes..","body":"","parents":["d533ad92303c238f927f0d3479e4012e42b2af0f"],"add":7,"del":7,"cadd":7,"cdel":7,"files":9},{"repo":"deck-of-cards","hash":"d3ae6fd0a2b0d22b80dfb0ada31c910e6bb86e07","ts":1443885692,"wall":"2015-10-03T18:21","msg":"Merge pull request #24 from pakastin/pr/23","body":"Pr/23","parents":["7a492154cea535c838de20877e4e1e0d89f8feb1","69db502e0b42fcc345aaf3f170207fd4ead2a06e"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"7da9ddeb2f0f9e1a4de781a577727f21783885b4","ts":1443885833,"wall":"2015-10-03T18:23","msg":"#22 + #23","body":"","parents":["fadeaa289956057533a5968cbbc9abc7454a2063"],"add":10,"del":94,"cadd":10,"cdel":94,"files":2},{"repo":"deck-of-cards","hash":"a5b3b99535082008940fcc5a40ba3dea6369fd08","ts":1444142066,"wall":"2015-10-06T17:34","msg":"Update README.md","body":"","parents":["d3ae6fd0a2b0d22b80dfb0ada31c910e6bb86e07"],"add":2,"del":0,"cadd":2,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"3d6572297498799bcdcd6dfa6fc402d9d8d7e774","ts":1445803964,"wall":"2015-10-25T22:12","msg":"Update README.md","body":"","parents":["a5b3b99535082008940fcc5a40ba3dea6369fd08"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"a09734051f5d43dca9c47dca989574b1a529aa57","ts":1445929633,"wall":"2015-10-27T09:07","msg":"do not limit raf fps","body":"","parents":["3d6572297498799bcdcd6dfa6fc402d9d8d7e774"],"add":1,"del":19,"cadd":1,"cdel":19,"files":3},{"repo":"deck-of-cards","hash":"c8cea2bb8a34e38ed255783bcea55bc2dbef214d","ts":1445929705,"wall":"2015-10-27T09:08","msg":"do not limit raf fps","body":"","parents":["7da9ddeb2f0f9e1a4de781a577727f21783885b4"],"add":1,"del":10,"cadd":1,"cdel":10,"files":2},{"repo":"deck-of-cards","hash":"2e3297613647ca5c3142d979fa9d54a880d9ea8e","ts":1445929748,"wall":"2015-10-27T09:09","msg":"0.1.5","body":"","parents":["a09734051f5d43dca9c47dca989574b1a529aa57"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"2a537663770a5c4ca32b8cc28eac9a99e8dc9c80","ts":1447240623,"wall":"2015-11-11T13:17","msg":"Update README.md","body":"","parents":["2e3297613647ca5c3142d979fa9d54a880d9ea8e"],"add":1,"del":2,"cadd":1,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"cc5826aaa78d05d1fc52f0e174f85322b735ce8c","ts":1447240829,"wall":"2015-11-11T13:20","msg":"Update LICENSE","body":"","parents":["2a537663770a5c4ca32b8cc28eac9a99e8dc9c80"],"add":31,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"47edf5727903ffc46aa60c0618c90cd7d0f69ad9","ts":1447240847,"wall":"2015-11-11T13:20","msg":"Update LICENSE","body":"","parents":["cc5826aaa78d05d1fc52f0e174f85322b735ce8c"],"add":2,"del":2,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"91412dd6e5859d174b6dd59ecb557f567f42fbe7","ts":1448922310,"wall":"2015-11-30T17:25","msg":"Meteor packaging","body":"","parents":["47edf5727903ffc46aa60c0618c90cd7d0f69ad9"],"add":45,"del":0,"cadd":44,"cdel":0,"files":2},{"repo":"deck-of-cards","hash":"d64c42a5e7b799c604c8c960e94939b3daddb8c0","ts":1452957246,"wall":"2016-01-16T17:14","msg":"Merge pull request #26 from mizzao/master","body":"Packaging for Meteor","parents":["47edf5727903ffc46aa60c0618c90cd7d0f69ad9","91412dd6e5859d174b6dd59ecb557f567f42fbe7"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"76c4b8b89c92124454556594ab2f821e11fbe995","ts":1453503775,"wall":"2016-01-23T10:02","msg":"Allow a side to be specified when flipping deck","body":"","parents":["d64c42a5e7b799c604c8c960e94939b3daddb8c0"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"deck-of-cards","hash":"37f2a68aeb380d1dec5b3fbedaa25a45cbf18596","ts":1453505937,"wall":"2016-01-23T10:38","msg":"Update dist files appropriately","body":"","parents":["76c4b8b89c92124454556594ab2f821e11fbe995"],"add":3,"del":3,"cadd":3,"cdel":3,"files":2},{"repo":"deck-of-cards","hash":"88c106fef0d616f75dd8e6bf1cb73d6708f1f82d","ts":1453544372,"wall":"2016-01-23T12:19","msg":"Merge pull request #32 from vinceau/master","body":"Allow a side to be specified when flipping deck","parents":["d64c42a5e7b799c604c8c960e94939b3daddb8c0","37f2a68aeb380d1dec5b3fbedaa25a45cbf18596"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"3e64104233abb3521f1659d0c1f9ba30df912732","ts":1453544453,"wall":"2016-01-23T12:20","msg":"0.1.6","body":"","parents":["88c106fef0d616f75dd8e6bf1cb73d6708f1f82d"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"c8766afd021f9f9172742fc0c935b0179fd78a50","ts":1453544486,"wall":"2016-01-23T12:21","msg":"0.1.6","body":"","parents":["c8cea2bb8a34e38ed255783bcea55bc2dbef214d"],"add":3,"del":3,"cadd":3,"cdel":3,"files":2},{"repo":"learning-area","hash":"ec54b504f5a03ddffa9ce0549771ed5eedc08040","ts":1457445769,"wall":"2016-03-08T14:02","msg":"initial repo population","body":"","parents":[],"add":2574,"del":0,"cadd":2416,"cdel":0,"files":83},{"repo":"learning-area","hash":"c8da0a28bfa4e964e7c037444dee0114c2f284dd","ts":1457445873,"wall":"2016-03-08T14:04","msg":"adding image example","body":"","parents":["ec54b504f5a03ddffa9ce0549771ed5eedc08040"],"add":12,"del":0,"cadd":12,"cdel":0,"files":1},{"repo":"learning-area","hash":"b9b2236284c404eb2ace962bcd1acf75d2203521","ts":1457545279,"wall":"2016-03-09T18:41","msg":"adding small dino picture","body":"","parents":["c8da0a28bfa4e964e7c037444dee0114c2f284dd"],"add":5,"del":1,"cadd":5,"cdel":1,"files":2},{"repo":"learning-area","hash":"7d049d2cc310b81ec812630a02a20a0a020c0a53","ts":1458051564,"wall":"2016-03-15T14:19","msg":"adding audio and video examples","body":"","parents":["b9b2236284c404eb2ace962bcd1acf75d2203521"],"add":69,"del":0,"cadd":69,"cdel":0,"files":9},{"repo":"learning-area","hash":"a223839276702117c4bca68cbb7063985e5fd2ef","ts":1458052779,"wall":"2016-03-15T14:39","msg":"adding audio and video examples","body":"","parents":["7d049d2cc310b81ec812630a02a20a0a020c0a53"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"9e5c45c9977428204bcef49af5ce618269bd45e5","ts":1458129744,"wall":"2016-03-16T12:02","msg":"adding iframe demos","body":"","parents":["a223839276702117c4bca68cbb7063985e5fd2ef"],"add":26,"del":0,"cadd":26,"cdel":0,"files":2},{"repo":"learning-area","hash":"f7d2947445f995a3b87e8fb6d6622df8f196efc9","ts":1458155153,"wall":"2016-03-16T19:05","msg":"adding embed and object examples","body":"","parents":["9e5c45c9977428204bcef49af5ce618269bd45e5"],"add":386,"del":0,"cadd":386,"cdel":0,"files":9},{"repo":"learning-area","hash":"6103f0a7290afaa579248d3d3c5594d4ee60a392","ts":1458578892,"wall":"2016-03-21T16:48","msg":"adding vector graphc example","body":"","parents":["f7d2947445f995a3b87e8fb6d6622df8f196efc9"],"add":110,"del":0,"cadd":13,"cdel":0,"files":3},{"repo":"learning-area","hash":"8b5789e30c2a88a9515329d3901ddbff52acba22","ts":1458741228,"wall":"2016-03-23T13:53","msg":"adding responsive images examples","body":"","parents":["6103f0a7290afaa579248d3d3c5594d4ee60a392"],"add":126,"del":0,"cadd":126,"cdel":0,"files":9},{"repo":"learning-area","hash":"c8172e907594d1f6310e2b303e952ba687443da8","ts":1458742880,"wall":"2016-03-23T14:21","msg":"adding responsive images examples","body":"","parents":["8b5789e30c2a88a9515329d3901ddbff52acba22"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"learning-area","hash":"62ab8146b87e370889afbcc19e52bb539c058139","ts":1458745785,"wall":"2016-03-23T15:09","msg":"adding responsive image example","body":"","parents":["c8172e907594d1f6310e2b303e952ba687443da8"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"70281725012ab6c33a211f835ed59070540c8f8b","ts":1458747806,"wall":"2016-03-23T15:43","msg":"adding responsive image examples","body":"","parents":["62ab8146b87e370889afbcc19e52bb539c058139"],"add":26,"del":1,"cadd":26,"cdel":1,"files":3},{"repo":"learning-area","hash":"2ab8928318602b7ebbcd52d5d66b135b712ae408","ts":1458756484,"wall":"2016-03-23T18:08","msg":"adding picture element example","body":"","parents":["70281725012ab6c33a211f835ed59070540c8f8b"],"add":6,"del":2,"cadd":6,"cdel":2,"files":2},{"repo":"learning-area","hash":"f74f379a1f079b5a1df6afd1e6405e3ba6f03500","ts":1458756714,"wall":"2016-03-23T18:11","msg":"fixing <picture> element example src should be srcset","body":"","parents":["2ab8928318602b7ebbcd52d5d66b135b712ae408"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"9105644497ae7e7be80d892217c3a48c917bc24c","ts":1458821380,"wall":"2016-03-24T12:09","msg":"adding finished assessment example","body":"","parents":["f74f379a1f079b5a1df6afd1e6405e3ba6f03500"],"add":504,"del":0,"cadd":154,"cdel":0,"files":16},{"repo":"learning-area","hash":"bac2f8c510c78f0a4998f6e63a2963da58649193","ts":1458822142,"wall":"2016-03-24T12:22","msg":"adding finished assessment example","body":"","parents":["9105644497ae7e7be80d892217c3a48c917bc24c"],"add":2,"del":0,"cadd":2,"cdel":0,"files":1},{"repo":"learning-area","hash":"8288ae4500faccf1bfd163e5624dc0b441380f56","ts":1458828383,"wall":"2016-03-24T14:06","msg":"adding starting content for assessment","body":"","parents":["bac2f8c510c78f0a4998f6e63a2963da58649193"],"add":144,"del":0,"cadd":144,"cdel":0,"files":2},{"repo":"learning-area","hash":"4f82e6b3214f625862c5aca9673b0d931c19a9c0","ts":1458828991,"wall":"2016-03-24T14:16","msg":"adding starting content for assessment","body":"","parents":["8288ae4500faccf1bfd163e5624dc0b441380f56"],"add":2,"del":3,"cadd":2,"cdel":3,"files":1},{"repo":"learning-area","hash":"2038e300bdad00fc763df92f374b147a7ff5d102","ts":1458856973,"wall":"2016-03-24T22:02","msg":"adding extras","body":"","parents":["4f82e6b3214f625862c5aca9673b0d931c19a9c0"],"add":74,"del":0,"cadd":74,"cdel":0,"files":1},{"repo":"learning-area","hash":"23bbd92fc27d773f8d933b236703b09a49a7e225","ts":1458857122,"wall":"2016-03-24T22:05","msg":"adding extras","body":"","parents":["2038e300bdad00fc763df92f374b147a7ff5d102"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"44f6e56838814e92b264be631ebb43653af7afa3","ts":1459432538,"wall":"2016-03-31T14:55","msg":"adding font styling examples","body":"","parents":["23bbd92fc27d773f8d933b236703b09a49a7e225"],"add":47,"del":0,"cadd":47,"cdel":0,"files":1},{"repo":"learning-area","hash":"2ae4fb5db54293a754517b980cba3f6986c9a24d","ts":1459445819,"wall":"2016-03-31T18:36","msg":"adding styling list examples","body":"","parents":["44f6e56838814e92b264be631ebb43653af7afa3"],"add":234,"del":0,"cadd":137,"cdel":0,"files":3},{"repo":"learning-area","hash":"639d3abe6d219c600e33a344db39a52809337ba9","ts":1459795853,"wall":"2016-04-04T19:50","msg":"adding list styling examples","body":"","parents":["2ae4fb5db54293a754517b980cba3f6986c9a24d"],"add":29,"del":14,"cadd":29,"cdel":14,"files":2},{"repo":"learning-area","hash":"a4576d0aa5a7030c4a476b499e2df4b5d85580a1","ts":1460650247,"wall":"2016-04-14T17:10","msg":"adding web fonts examples","body":"","parents":["639d3abe6d219c600e33a344db39a52809337ba9"],"add":2983,"del":2,"cadd":2141,"cdel":2,"files":32},{"repo":"learning-area","hash":"1fb6a31cc9cdeaca2245911fe57d7fbd20d4e450","ts":1461096072,"wall":"2016-04-19T21:01","msg":"adding css styling text assessment examples","body":"","parents":["a4576d0aa5a7030c4a476b499e2df4b5d85580a1"],"add":4178,"del":0,"cadd":2711,"cdel":0,"files":49},{"repo":"learning-area","hash":"cddccbd465827e95933b6bb2f9516ba5520a78a5","ts":1461101664,"wall":"2016-04-19T22:34","msg":"adding css styling text assessment examples","body":"","parents":["1fb6a31cc9cdeaca2245911fe57d7fbd20d4e450"],"add":99,"del":2,"cadd":99,"cdel":2,"files":4},{"repo":"learning-area","hash":"631baa1553390e93ee47ffcdc347e1712d9436cd","ts":1461249976,"wall":"2016-04-21T15:46","msg":"adding box model recap examples","body":"","parents":["cddccbd465827e95933b6bb2f9516ba5520a78a5"],"add":137,"del":0,"cadd":137,"cdel":0,"files":7},{"repo":"learning-area","hash":"554c78e554675dc1d846bc2dc05c2e5332fa1c87","ts":1461429607,"wall":"2016-04-23T17:40","msg":"adding css tables and flexbox examples","body":"","parents":["631baa1553390e93ee47ffcdc347e1712d9436cd"],"add":134,"del":1,"cadd":134,"cdel":1,"files":3},{"repo":"learning-area","hash":"78766d9fc48b8f483a33a386299ad8d52263dbf5","ts":1461677517,"wall":"2016-04-26T14:31","msg":"adding backgrounds examples","body":"","parents":["554c78e554675dc1d846bc2dc05c2e5332fa1c87"],"add":153,"del":0,"cadd":153,"cdel":0,"files":7},{"repo":"learning-area","hash":"2ae5213736b76b4f1e7c573c06c3ac05238ce5ee","ts":1461756117,"wall":"2016-04-27T12:21","msg":"adding border examples","body":"","parents":["78766d9fc48b8f483a33a386299ad8d52263dbf5"],"add":135,"del":0,"cadd":135,"cdel":0,"files":5},{"repo":"learning-area","hash":"093011a76dcd9d9687e9c80987e4135ceda73620","ts":1461839820,"wall":"2016-04-28T11:37","msg":"adding table styling examples","body":"","parents":["2ae5213736b76b4f1e7c573c06c3ac05238ce5ee"],"add":450,"del":0,"cadd":450,"cdel":0,"files":10},{"repo":"learning-area","hash":"1d69e0a81a4b33fff14b4ca0a39240386aa0b545","ts":1461839864,"wall":"2016-04-28T11:37","msg":"adding table styling examples","body":"","parents":["093011a76dcd9d9687e9c80987e4135ceda73620"],"add":0,"del":201,"cadd":0,"cdel":201,"files":5},{"repo":"learning-area","hash":"04bc9a86f3c440f110b4b1fd48bd9f657eabcea1","ts":1461931926,"wall":"2016-04-29T13:12","msg":"adding advanced box effects examples","body":"","parents":["1d69e0a81a4b33fff14b4ca0a39240386aa0b545"],"add":512,"del":0,"cadd":512,"cdel":0,"files":5},{"repo":"learning-area","hash":"bf9576311e51df9d41a9fe996423f43a0bf0d5a6","ts":1462391497,"wall":"2016-05-04T20:51","msg":"adding assessment files","body":"","parents":["04bc9a86f3c440f110b4b1fd48bd9f657eabcea1"],"add":197,"del":0,"cadd":197,"cdel":0,"files":14},{"repo":"learning-area","hash":"eb7c3d58b14b44e016d163292ac00dc39854f3dd","ts":1462442455,"wall":"2016-05-05T11:00","msg":"adding assessment marking guides","body":"","parents":["bf9576311e51df9d41a9fe996423f43a0bf0d5a6"],"add":105,"del":2,"cadd":105,"cdel":2,"files":5},{"repo":"learning-area","hash":"c68f82b8d3a3ea91a5f937cccf0571e6dfb40304","ts":1462965245,"wall":"2016-05-11T12:14","msg":"remove license","body":"","parents":["eb7c3d58b14b44e016d163292ac00dc39854f3dd"],"add":0,"del":24,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"f001bd27ce4ac39f6b743db0fffb3305e3207300","ts":1462965266,"wall":"2016-05-11T12:14","msg":"Create LICENSE","body":"","parents":["c68f82b8d3a3ea91a5f937cccf0571e6dfb40304"],"add":116,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"851aadc27133a75f87e495f73d6d226a4e43c72d","ts":1462965330,"wall":"2016-05-11T12:15","msg":"updating license to cc-0","body":"","parents":["eb7c3d58b14b44e016d163292ac00dc39854f3dd"],"add":116,"del":24,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"707a4e6012d55f0244cabd4a817e2e005b606cd6","ts":1463588916,"wall":"2016-05-18T17:28","msg":"adding floats and clearing examples","body":"","parents":["851aadc27133a75f87e495f73d6d226a4e43c72d"],"add":543,"del":0,"cadd":543,"cdel":0,"files":11},{"repo":"learning-area","hash":"fe5651f715629015dff6351ce3fb532d92616784","ts":1463589424,"wall":"2016-05-18T17:37","msg":"adding float examples","body":"","parents":["f001bd27ce4ac39f6b743db0fffb3305e3207300"],"add":543,"del":0,"cadd":543,"cdel":0,"files":11},{"repo":"learning-area","hash":"76419e9b8ddf11bd4367451a8ba4dffb75261f67","ts":1463589571,"wall":"2016-05-18T17:39","msg":"Merge branch 'gh-pages' of https://github.com/chrisdavidmills/learning-area into gh-pages","body":"","parents":["fe5651f715629015dff6351ce3fb532d92616784","707a4e6012d55f0244cabd4a817e2e005b606cd6"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"ec0108dd2a362b82a6cc5c3e2495edb3183991ec","ts":1463590487,"wall":"2016-05-18T17:54","msg":"adding clear example","body":"","parents":["fe5651f715629015dff6351ce3fb532d92616784"],"add":57,"del":0,"cadd":57,"cdel":0,"files":1},{"repo":"learning-area","hash":"ae600c0b40984a4b099c9a0a626bda27ad93a0bd","ts":1463590567,"wall":"2016-05-18T17:56","msg":"Merge branch 'gh-pages' of https://github.com/chrisdavidmills/learning-area into gh-pages","body":"","parents":["ec0108dd2a362b82a6cc5c3e2495edb3183991ec","76419e9b8ddf11bd4367451a8ba4dffb75261f67"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"59d215b03942f1f4e58b30e1bbe0d1570376c509","ts":1463684151,"wall":"2016-05-19T19:55","msg":"adding basic positioning examples","body":"","parents":["ec0108dd2a362b82a6cc5c3e2495edb3183991ec"],"add":330,"del":0,"cadd":330,"cdel":0,"files":8},{"repo":"learning-area","hash":"6911673860ed257a6fdcb2eb5f0728f0eab01672","ts":1463684207,"wall":"2016-05-19T19:56","msg":"Merge branch 'gh-pages' of https://github.com/chrisdavidmills/learning-area into gh-pages","body":"","parents":["59d215b03942f1f4e58b30e1bbe0d1570376c509","ae600c0b40984a4b099c9a0a626bda27ad93a0bd"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"6ba4d48235094fc9b33a53ebfd0a24e0de17f850","ts":1463684450,"wall":"2016-05-19T20:00","msg":"adding basic positioning examples","body":"","parents":["59d215b03942f1f4e58b30e1bbe0d1570376c509"],"add":6,"del":6,"cadd":6,"cdel":6,"files":3},{"repo":"learning-area","hash":"18d2b36b89e5bbc1d7d31c362a2c54b6b01568b3","ts":1463684478,"wall":"2016-05-19T20:01","msg":"Merge branch 'gh-pages' of https://github.com/chrisdavidmills/learning-area into gh-pages","body":"","parents":["6ba4d48235094fc9b33a53ebfd0a24e0de17f850","6911673860ed257a6fdcb2eb5f0728f0eab01672"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"19d76ffe6d00b5ceff24a8f83abb8863112adafa","ts":1464039685,"wall":"2016-05-23T22:41","msg":"adding practical positioning examples","body":"","parents":["6ba4d48235094fc9b33a53ebfd0a24e0de17f850"],"add":482,"del":0,"cadd":482,"cdel":0,"files":5},{"repo":"learning-area","hash":"dda872bc497a1dab0d0eef2e294f952d27c9b34a","ts":1464039734,"wall":"2016-05-23T22:42","msg":"Merge branch 'gh-pages' of https://github.com/chrisdavidmills/learning-area into gh-pages","body":"","parents":["19d76ffe6d00b5ceff24a8f83abb8863112adafa","18d2b36b89e5bbc1d7d31c362a2c54b6b01568b3"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"be003507668af08b469e64985dcfa0329399fd26","ts":1466500586,"wall":"2016-06-21T10:16","msg":"adding flexbox demos","body":"","parents":["19d76ffe6d00b5ceff24a8f83abb8863112adafa"],"add":831,"del":1,"cadd":831,"cdel":1,"files":11},{"repo":"learning-area","hash":"7291a71445f7edbf0c4abeec1deb9f28e81ae984","ts":1466500761,"wall":"2016-06-21T10:19","msg":"Merge branch 'gh-pages' of https://github.com/chrisdavidmills/learning-area into gh-pages","body":"","parents":["be003507668af08b469e64985dcfa0329399fd26","dda872bc497a1dab0d0eef2e294f952d27c9b34a"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"de91ea36f3b329ee8a64a98f963ce41ccfa380fa","ts":1466510281,"wall":"2016-06-21T12:58","msg":"adding javascript console example","body":"","parents":["be003507668af08b469e64985dcfa0329399fd26"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"1cfdce6e44a2bd7887a22067a65c284b668711dd","ts":1466510352,"wall":"2016-06-21T12:59","msg":"Merge branch 'gh-pages' of https://github.com/chrisdavidmills/learning-area into gh-pages","body":"","parents":["de91ea36f3b329ee8a64a98f963ce41ccfa380fa","7291a71445f7edbf0c4abeec1deb9f28e81ae984"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"806c65af9e0f377afeef3ddba3ff17255cabbea8","ts":1466761662,"wall":"2016-06-24T10:47","msg":"adding what is javascript demo files","body":"","parents":["1cfdce6e44a2bd7887a22067a65c284b668711dd"],"add":86,"del":0,"cadd":86,"cdel":0,"files":6},{"repo":"learning-area","hash":"2f0ee789c3be94e6d9e9812ce7eb10f1eab3030e","ts":1467208954,"wall":"2016-06-29T15:02","msg":"adding javascript number guessing game","body":"","parents":["806c65af9e0f377afeef3ddba3ff17255cabbea8"],"add":192,"del":2,"cadd":192,"cdel":2,"files":4},{"repo":"learning-area","hash":"322a00365a28ec3ef7e22d8c5dfa9686a9d404ad","ts":1467877211,"wall":"2016-07-07T08:40","msg":"fixing error in fundamental comprehansion marking guide","body":"","parents":["2f0ee789c3be94e6d9e9812ce7eb10f1eab3030e"],"add":4,"del":4,"cadd":4,"cdel":4,"files":1},{"repo":"learning-area","hash":"9bc2f9b6215a6cf46e15db3ea3ce9e62bc0ecc8d","ts":1468325361,"wall":"2016-07-12T13:09","msg":"adding broken javascript example for troubleshooting article","body":"","parents":["322a00365a28ec3ef7e22d8c5dfa9686a9d404ad"],"add":286,"del":0,"cadd":286,"cdel":0,"files":4},{"repo":"learning-area","hash":"b7be8307a16400c2decae6c87d89d4fa9520df8d","ts":1468408545,"wall":"2016-07-13T12:15","msg":"normalizing all quotes in JS code to single quotes","body":"","parents":["9bc2f9b6215a6cf46e15db3ea3ce9e62bc0ecc8d"],"add":12,"del":12,"cadd":12,"cdel":12,"files":2},{"repo":"learning-area","hash":"bd1ad8c80822a7e5906cc34d104ae91d1725be2f","ts":1469526473,"wall":"2016-07-26T10:47","msg":"updating loops to use var for best practice","body":"","parents":["b7be8307a16400c2decae6c87d89d4fa9520df8d"],"add":6,"del":6,"cadd":6,"cdel":6,"files":5},{"repo":"learning-area","hash":"8c8f0695bda13460ea401c0d0fc7860a8bd531ed","ts":1470237409,"wall":"2016-08-03T16:16","msg":"adding assessment for javascript first steps module","body":"","parents":["bd1ad8c80822a7e5906cc34d104ae91d1725be2f"],"add":201,"del":0,"cadd":155,"cdel":0,"files":4},{"repo":"learning-area","hash":"caad5a2e533b4de8a80ed3a9deb93c6947c26108","ts":1470241153,"wall":"2016-08-03T17:19","msg":"adding marking guide for first steps assessment","body":"","parents":["8c8f0695bda13460ea401c0d0fc7860a8bd531ed"],"add":60,"del":8,"cadd":59,"cdel":7,"files":3},{"repo":"learning-area","hash":"dfb654b5918d4406982c1be9bb1ccad4ef5626b8","ts":1470241372,"wall":"2016-08-03T17:22","msg":"adding marking guide for first steps assessment","body":"","parents":["caad5a2e533b4de8a80ed3a9deb93c6947c26108"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"883a20de055de4a9f646f3c8bdebd8dea1d9a54e","ts":1470738124,"wall":"2016-08-09T11:22","msg":"adding conditionals examples","body":"","parents":["dfb654b5918d4406982c1be9bb1ccad4ef5626b8"],"add":290,"del":0,"cadd":290,"cdel":0,"files":6},{"repo":"learning-area","hash":"2dd8ed8bbbcdc3aba7380afbf3031b43450190b1","ts":1471364828,"wall":"2016-08-16T17:27","msg":"adding loops and functions examples","body":"","parents":["883a20de055de4a9f646f3c8bdebd8dea1d9a54e"],"add":722,"del":0,"cadd":722,"cdel":0,"files":18},{"repo":"learning-area","hash":"fd4c4551cf31c6885a5b57586e7cdd42bc7f7c1b","ts":1471436514,"wall":"2016-08-17T13:21","msg":"naming conflict example","body":"","parents":["2dd8ed8bbbcdc3aba7380afbf3031b43450190b1"],"add":29,"del":2,"cadd":29,"cdel":2,"files":4},{"repo":"learning-area","hash":"388882381e1453f689a74d8af1837a4f02b4899b","ts":1471441764,"wall":"2016-08-17T14:49","msg":"fixing styling on return values example","body":"","parents":["fd4c4551cf31c6885a5b57586e7cdd42bc7f7c1b"],"add":9,"del":21,"cadd":9,"cdel":21,"files":2},{"repo":"learning-area","hash":"b9dd2f0158254a59a667980d8410a12530558638","ts":1471612447,"wall":"2016-08-19T14:14","msg":"adding events examples","body":"","parents":["388882381e1453f689a74d8af1837a4f02b4899b"],"add":329,"del":0,"cadd":329,"cdel":0,"files":10},{"repo":"learning-area","hash":"54ee616ed8c4e58db640da6dc07d95cf92e41957","ts":1471879677,"wall":"2016-08-22T16:27","msg":"adding building blocks assessment","body":"","parents":["b9dd2f0158254a59a667980d8410a12530558638"],"add":106,"del":0,"cadd":106,"cdel":0,"files":9},{"repo":"learning-area","hash":"2afa79900e995bcc83cd904f319fcbeba2d7ba2a","ts":1471884460,"wall":"2016-08-22T17:47","msg":"more assessment details","body":"","parents":["54ee616ed8c4e58db640da6dc07d95cf92e41957"],"add":162,"del":0,"cadd":162,"cdel":0,"files":9},{"repo":"learning-area","hash":"e5cd424f2f98f2553182257553f2f84dbee5b1ab","ts":1471884504,"wall":"2016-08-22T17:48","msg":"removing unneeded directory","body":"","parents":["2afa79900e995bcc83cd904f319fcbeba2d7ba2a"],"add":0,"del":84,"cadd":0,"cdel":84,"files":8},{"repo":"learning-area","hash":"904f84d7ab6b1e6003371828a3823933fedda58f","ts":1471884641,"wall":"2016-08-22T17:50","msg":"fixing title on markgin guide","body":"","parents":["e5cd424f2f98f2553182257553f2f84dbee5b1ab"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"c55430a2b39ad138052430387bce00a016cda8ea","ts":1472720129,"wall":"2016-09-01T09:55","msg":"adding basic OOJs examples","body":"","parents":["904f84d7ab6b1e6003371828a3823933fedda58f"],"add":208,"del":0,"cadd":208,"cdel":0,"files":4},{"repo":"learning-area","hash":"f8a626345d2b0ceb2be6040a9dc620bca3dc0fd4","ts":1473256131,"wall":"2016-09-07T14:48","msg":"adding inheritance examples","body":"","parents":["c55430a2b39ad138052430387bce00a016cda8ea"],"add":438,"del":0,"cadd":438,"cdel":0,"files":4},{"repo":"learning-area","hash":"6f38210038dff7d9e8862f464e014f33be545127","ts":1473280492,"wall":"2016-09-07T21:34","msg":"adding JSON examples","body":"","parents":["f8a626345d2b0ceb2be6040a9dc620bca3dc0fd4"],"add":121,"del":0,"cadd":80,"cdel":0,"files":3},{"repo":"learning-area","hash":"8600507c3207870a7e5936f2e627c43e3a002d55","ts":1473347501,"wall":"2016-09-08T16:11","msg":"finishing JSON examples","body":"","parents":["6f38210038dff7d9e8862f464e014f33be545127"],"add":230,"del":9,"cadd":230,"cdel":9,"files":4},{"repo":"learning-area","hash":"867cfbba1088c4383e015eb90a778aedc72b5339","ts":1473670699,"wall":"2016-09-12T09:58","msg":"adding bouncy ball demo files","body":"","parents":["8600507c3207870a7e5936f2e627c43e3a002d55"],"add":170,"del":0,"cadd":170,"cdel":0,"files":5},{"repo":"learning-area","hash":"e70f76d32c691af3c00160f4b129a8ab9ad251eb","ts":1473780057,"wall":"2016-09-13T16:20","msg":"adding OO assessment","body":"","parents":["867cfbba1088c4383e015eb90a778aedc72b5339"],"add":263,"del":0,"cadd":263,"cdel":0,"files":3},{"repo":"learning-area","hash":"adae814d12d68ba9509b7017c2dbf23a3361e4c2","ts":1473857598,"wall":"2016-09-14T13:53","msg":"adding marking guide","body":"","parents":["e70f76d32c691af3c00160f4b129a8ab9ad251eb"],"add":119,"del":0,"cadd":119,"cdel":0,"files":1},{"repo":"learning-area","hash":"89be2174506dc5b42099ee5da8542d04c70d1089","ts":1474323348,"wall":"2016-09-19T15:15","msg":"Update calendar-finished.html","body":"add space in code for consistency","parents":["adae814d12d68ba9509b7017c2dbf23a3361e4c2"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"7ed039d17e820c93cafaff541aa65d874dde8323","ts":1474539921,"wall":"2016-09-22T11:25","msg":"adding grid design examples","body":"","parents":["adae814d12d68ba9509b7017c2dbf23a3361e4c2"],"add":1367,"del":0,"cadd":1367,"cdel":0,"files":12},{"repo":"learning-area","hash":"1bcaccbc51186e62ae875402c8dfb4bad092d4bb","ts":1474574746,"wall":"2016-09-22T21:05","msg":"adding grid design examples","body":"","parents":["7ed039d17e820c93cafaff541aa65d874dde8323"],"add":0,"del":5,"cadd":0,"cdel":5,"files":1},{"repo":"learning-area","hash":"26a5bb2b5e8a231f17f103045925d060ecb130d1","ts":1474906946,"wall":"2016-09-26T17:22","msg":"fixing error in assessment","body":"","parents":["1bcaccbc51186e62ae875402c8dfb4bad092d4bb"],"add":3,"del":1,"cadd":3,"cdel":1,"files":1},{"repo":"learning-area","hash":"2c9073e7ee8d65c377f9ac636f97b9c002c3c3db","ts":1474947254,"wall":"2016-09-27T04:34","msg":"Merge pull request #1 from Cameron-Riecan/patch-1","body":"Update calendar-finished.html","parents":["26a5bb2b5e8a231f17f103045925d060ecb130d1","89be2174506dc5b42099ee5da8542d04c70d1089"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"3e86fe25dbc96686d3b9c49be1ae559f9271cf31","ts":1475831568,"wall":"2016-10-07T10:12","msg":"adding additional css tables example","body":"","parents":["26a5bb2b5e8a231f17f103045925d060ecb130d1"],"add":56,"del":0,"cadd":56,"cdel":0,"files":1},{"repo":"learning-area","hash":"9e1a05646b8dd257c244207e3fd6f48088c1dcd6","ts":1475831596,"wall":"2016-10-07T10:13","msg":"Merge branch 'master' of https://github.com/chrisdavidmills/learning-area","body":"","parents":["3e86fe25dbc96686d3b9c49be1ae559f9271cf31","2c9073e7ee8d65c377f9ac636f97b9c002c3c3db"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"5ade9b705f748724e74c9d60198972c80c63faaa","ts":1475831696,"wall":"2016-10-07T10:14","msg":"another update","body":"","parents":["9e1a05646b8dd257c244207e3fd6f48088c1dcd6"],"add":2,"del":3,"cadd":2,"cdel":3,"files":1},{"repo":"learning-area","hash":"c4cb79e1ab6ebc95827e7a96542e51727089a534","ts":1475847864,"wall":"2016-10-07T14:44","msg":"small fix on grid example","body":"","parents":["5ade9b705f748724e74c9d60198972c80c63faaa"],"add":1,"del":2,"cadd":1,"cdel":2,"files":1},{"repo":"learning-area","hash":"1574795b462f489321e32e47f8c6e0ba3c287acc","ts":1476133535,"wall":"2016-10-10T22:05","msg":"adding simple example for cross browser testing","body":"","parents":["c4cb79e1ab6ebc95827e7a96542e51727089a534"],"add":76,"del":0,"cadd":76,"cdel":0,"files":1},{"repo":"learning-area","hash":"e340f65c4a0d4543094db646be7995f53c0a9103","ts":1476208221,"wall":"2016-10-11T18:50","msg":"adding css and html debugging examples","body":"","parents":["1574795b462f489321e32e47f8c6e0ba3c287acc"],"add":6532,"del":5,"cadd":6507,"cdel":5,"files":9},{"repo":"learning-area","hash":"4a1ac4a6a21da8e2be1a16b4fd39bbcf26a886cb","ts":1476311622,"wall":"2016-10-12T23:33","msg":"adding more HTML and CSS cross browser examples","body":"","parents":["e340f65c4a0d4543094db646be7995f53c0a9103"],"add":29,"del":3,"cadd":29,"cdel":3,"files":3},{"repo":"learning-area","hash":"8d6197a5da40fb84f69c2a9936ecc43ff1c1a10e","ts":1476451630,"wall":"2016-10-14T14:27","msg":"adding more js testing files","body":"","parents":["4a1ac4a6a21da8e2be1a16b4fd39bbcf26a886cb"],"add":3606,"del":4,"cadd":3606,"cdel":4,"files":17},{"repo":"learning-area","hash":"a8dfa62704a5de3a475625cb97b7b06522fea996","ts":1476804016,"wall":"2016-10-18T16:20","msg":"adding accessibility testing examples","body":"","parents":["8d6197a5da40fb84f69c2a9936ecc43ff1c1a10e"],"add":279,"del":0,"cadd":279,"cdel":0,"files":9},{"repo":"learning-area","hash":"5d62765897d0510f958dc206a9d613926b539248","ts":1476972332,"wall":"2016-10-20T15:05","msg":"adding automated testing samples","body":"","parents":["a8dfa62704a5de3a475625cb97b7b06522fea996"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"93db14f3694da7e530852b545c1d7dc28c4edab6","ts":1476972612,"wall":"2016-10-20T15:10","msg":"adding automated testing samples","body":"","parents":["5d62765897d0510f958dc206a9d613926b539248"],"add":29,"del":0,"cadd":29,"cdel":0,"files":3},{"repo":"learning-area","hash":"3e919caefb81746b9429ddee80291b9d65a29027","ts":1477346783,"wall":"2016-10-24T23:06","msg":"adding selenium test files to repo","body":"","parents":["93db14f3694da7e530852b545c1d7dc28c4edab6"],"add":196,"del":0,"cadd":196,"cdel":0,"files":6},{"repo":"learning-area","hash":"0d7a754afa703ed691e6800ec5c498788beca642","ts":1477433328,"wall":"2016-10-25T23:08","msg":"adding feature detection examples","body":"","parents":["3e919caefb81746b9429ddee80291b9d65a29027"],"add":479,"del":1,"cadd":479,"cdel":1,"files":14},{"repo":"learning-area","hash":"509139b54f9a3af8ded6ab8fb7f7cbd30c7f27a0","ts":1478201118,"wall":"2016-11-03T19:25","msg":"adding API examples","body":"","parents":["0d7a754afa703ed691e6800ec5c498788beca642"],"add":319,"del":0,"cadd":319,"cdel":0,"files":6},{"repo":"learning-area","hash":"a08792e6797a4692fed9a3be11c032ac3602df2d","ts":1478780606,"wall":"2016-11-10T12:23","msg":"adding accessible html examples","body":"","parents":["509139b54f9a3af8ded6ab8fb7f7cbd30c7f27a0"],"add":359,"del":5,"cadd":359,"cdel":5,"files":14},{"repo":"learning-area","hash":"5e200d5628122c81925cb6e66aa7d6b2017e6840","ts":1479206797,"wall":"2016-11-15T10:46","msg":"adding CSS and JS accessibility examples","body":"","parents":["a08792e6797a4692fed9a3be11c032ac3602df2d"],"add":250,"del":0,"cadd":250,"cdel":0,"files":4},{"repo":"learning-area","hash":"3d666728f5d53f0e3ff1360fc87e37964deca74d","ts":1479207766,"wall":"2016-11-15T11:02","msg":"adding CSS and JS accessibility examples","body":"","parents":["5e200d5628122c81925cb6e66aa7d6b2017e6840"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"f0c401a28acab2934ba0ce4cdb847590aa64703d","ts":1479396069,"wall":"2016-11-17T15:21","msg":"mouse and keyboard events demo","body":"","parents":["3d666728f5d53f0e3ff1360fc87e37964deca74d"],"add":49,"del":0,"cadd":49,"cdel":0,"files":2},{"repo":"learning-area","hash":"5d502f53d743e12628da4758d20935e6eb23e452","ts":1479485380,"wall":"2016-11-18T20:09","msg":"add closing body tag","body":"","parents":["f0c401a28acab2934ba0ce4cdb847590aa64703d"],"add":2,"del":1,"cadd":2,"cdel":1,"files":1},{"repo":"learning-area","hash":"4ad399b06154f00be41e42ec2dd622f917bd5e22","ts":1479675153,"wall":"2016-11-20T20:52","msg":"Merge pull request #3 from badersur/patch-1","body":"add closing body tag","parents":["f0c401a28acab2934ba0ce4cdb847590aa64703d","5d502f53d743e12628da4758d20935e6eb23e452"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"dc55cdbad8e2fef921de11c2a07d7675ef7b57a4","ts":1479906071,"wall":"2016-11-23T13:01","msg":"adding ARIA roles examples","body":"","parents":["f0c401a28acab2934ba0ce4cdb847590aa64703d"],"add":442,"del":0,"cadd":442,"cdel":0,"files":4},{"repo":"learning-area","hash":"c6593ef729574c6fa3b7ab6b8c5ce2eb91638937","ts":1479906082,"wall":"2016-11-23T13:01","msg":"erge branch 'master' of https://github.com/chrisdavidmills/learning-area","body":"","parents":["dc55cdbad8e2fef921de11c2a07d7675ef7b57a4","4ad399b06154f00be41e42ec2dd622f917bd5e22"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"e46f3d1548270b1674c1fead8e0281d4a2f3eb04","ts":1479928481,"wall":"2016-11-23T19:14","msg":"adding live-region example","body":"","parents":["c6593ef729574c6fa3b7ab6b8c5ce2eb91638937"],"add":176,"del":0,"cadd":74,"cdel":0,"files":2},{"repo":"learning-area","hash":"9c7d13af5551f65bd45b0e978c3e96fc45621f83","ts":1479928669,"wall":"2016-11-23T19:17","msg":"adding live-region example","body":"","parents":["e46f3d1548270b1674c1fead8e0281d4a2f3eb04"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"d282ee9f190585f06c0bc9459ed7e5523615f100","ts":1480004173,"wall":"2016-11-24T16:16","msg":"adding wai-aria examples","body":"","parents":["9c7d13af5551f65bd45b0e978c3e96fc45621f83"],"add":610,"del":19,"cadd":610,"cdel":19,"files":10},{"repo":"learning-area","hash":"dbf8689a21c52051ca87a99ef35e1f045594aac6","ts":1480325752,"wall":"2016-11-28T09:35","msg":"adding fixes to the first HTML assessment","body":"","parents":["d282ee9f190585f06c0bc9459ed7e5523615f100"],"add":17,"del":17,"cadd":15,"cdel":15,"files":3},{"repo":"learning-area","hash":"aba3bd461ac05364d22c19fdd6c1057a1c5c0b12","ts":1480502747,"wall":"2016-11-30T10:45","msg":"fixing wai-aria tabs example","body":"","parents":["dbf8689a21c52051ca87a99ef35e1f045594aac6"],"add":8,"del":13,"cadd":8,"cdel":13,"files":1},{"repo":"learning-area","hash":"223ce83e9293f6c6e5974342dacbd3ca26d7022a","ts":1480796368,"wall":"2016-12-03T12:19","msg":"adding multimedia accessibility examples","body":"","parents":["aba3bd461ac05364d22c19fdd6c1057a1c5c0b12"],"add":498,"del":0,"cadd":498,"cdel":0,"files":13},{"repo":"learning-area","hash":"62851485b318a0938c41beec11e731a38f9b7695","ts":1480796368,"wall":"2016-12-03T12:19","msg":"adding multimedia accessibility examples","body":"","parents":["7f3aad68b391997d67966f6764c613a7e6d30608"],"add":498,"del":0,"cadd":498,"cdel":0,"files":13},{"repo":"learning-area","hash":"7f3aad68b391997d67966f6764c613a7e6d30608","ts":1480796877,"wall":"2016-12-03T12:27","msg":"adding multimedia accessibility examples","body":"","parents":["aba3bd461ac05364d22c19fdd6c1057a1c5c0b12"],"add":4,"del":0,"cadd":4,"cdel":0,"files":1},{"repo":"learning-area","hash":"b0d7d11215eab30d04f7fb51915706575b0d50a4","ts":1480796908,"wall":"2016-12-03T12:28","msg":"Merge branch 'gh-pages' of https://github.com/chrisdavidmills/learning-area into gh-pages","body":"","parents":["62851485b318a0938c41beec11e731a38f9b7695","223ce83e9293f6c6e5974342dacbd3ca26d7022a"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"68ff69d539edb5656805b7a87cd6e6a44d5ff2b2","ts":1480799773,"wall":"2016-12-03T13:16","msg":"minor native controls update","body":"","parents":["b0d7d11215eab30d04f7fb51915706575b0d50a4"],"add":4,"del":2,"cadd":4,"cdel":2,"files":1},{"repo":"learning-area","hash":"817f4c99ce830ad486052b4e7384d4e1d2a7dfa7","ts":1481646536,"wall":"2016-12-13T16:28","msg":"adding mobile accessibility examples","body":"","parents":["68ff69d539edb5656805b7a87cd6e6a44d5ff2b2"],"add":322,"del":0,"cadd":322,"cdel":0,"files":5},{"repo":"learning-area","hash":"ff6b4b027b8fb893dcdbe8c1c540494998929722","ts":1481649270,"wall":"2016-12-13T17:14","msg":"adding mobile accessibility examples","body":"","parents":["817f4c99ce830ad486052b4e7384d4e1d2a7dfa7"],"add":34,"del":17,"cadd":34,"cdel":17,"files":1},{"repo":"learning-area","hash":"63eacb9b37c353aff8f1c70282917f8ad3fe3600","ts":1481650187,"wall":"2016-12-13T17:29","msg":"adding mobile accessibility examples","body":"","parents":["ff6b4b027b8fb893dcdbe8c1c540494998929722"],"add":4,"del":1,"cadd":4,"cdel":1,"files":1},{"repo":"learning-area","hash":"41341249e7b61fdfebede901e767eefa1a8d1c12","ts":1481650797,"wall":"2016-12-13T17:39","msg":"adding mobile accessibility examples","body":"","parents":["63eacb9b37c353aff8f1c70282917f8ad3fe3600"],"add":5,"del":6,"cadd":5,"cdel":6,"files":1},{"repo":"learning-area","hash":"a2649eba183fe5114da73e1e8addaf091fab688f","ts":1481651207,"wall":"2016-12-13T17:46","msg":"adding mobile accessibility examples","body":"","parents":["41341249e7b61fdfebede901e767eefa1a8d1c12"],"add":1,"del":3,"cadd":1,"cdel":3,"files":1},{"repo":"learning-area","hash":"cc473b743e66bd4d397a8bf049c80fdf61166126","ts":1481704265,"wall":"2016-12-14T08:31","msg":"adding mobile accessibility examples","body":"","parents":["a2649eba183fe5114da73e1e8addaf091fab688f"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"learning-area","hash":"cacedb16009ee026acf875ed0720bd8074f3d36a","ts":1481704584,"wall":"2016-12-14T08:36","msg":"adding mobile accessibility examples","body":"","parents":["cc473b743e66bd4d397a8bf049c80fdf61166126"],"add":2,"del":1,"cadd":2,"cdel":1,"files":1},{"repo":"learning-area","hash":"534faa1a2008702798f3970ff3346fb892123ab2","ts":1481709304,"wall":"2016-12-14T09:55","msg":"adding mobile accessibility examples","body":"","parents":["cacedb16009ee026acf875ed0720bd8074f3d36a"],"add":0,"del":5,"cadd":0,"cdel":5,"files":1},{"repo":"learning-area","hash":"1add82d0d88805af0b5e19c8de9f18156abe28da","ts":1481711065,"wall":"2016-12-14T10:24","msg":"adding mobile accessibility examples","body":"","parents":["534faa1a2008702798f3970ff3346fb892123ab2"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"c60399f383222c4ff8045b1a43685560d7a13e79","ts":1483797829,"wall":"2017-01-07T14:03","msg":"adding a11y assessment materials, and fixing a marking guide","body":"","parents":["1add82d0d88805af0b5e19c8de9f18156abe28da"],"add":958,"del":4,"cadd":958,"cdel":4,"files":16},{"repo":"learning-area","hash":"b02d4d8625a7715c8359250fa89b6edf661ffa53","ts":1483896934,"wall":"2017-01-08T17:35","msg":"adding finished accessibility material","body":"","parents":["c60399f383222c4ff8045b1a43685560d7a13e79"],"add":116,"del":18,"cadd":116,"cdel":18,"files":3},{"repo":"learning-area","hash":"0cf537514a746293e6a8c870586e3c9890c37d86","ts":1483897089,"wall":"2017-01-08T17:38","msg":"adding finished accessibility material","body":"","parents":["b02d4d8625a7715c8359250fa89b6edf661ffa53"],"add":0,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"079401ec98402d2cd69992d011c92e664ba114c3","ts":1483897622,"wall":"2017-01-08T17:47","msg":"adding finished accessibility material","body":"","parents":["0cf537514a746293e6a8c870586e3c9890c37d86"],"add":5,"del":5,"cadd":5,"cdel":5,"files":1},{"repo":"learning-area","hash":"56fe0cb982314bbf8c74d100529d7869d2a9036c","ts":1483897739,"wall":"2017-01-08T17:48","msg":"adding finished accessibility material","body":"","parents":["079401ec98402d2cd69992d011c92e664ba114c3"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"8fcd8ce70e13d23553f7e86434745b0fb188b215","ts":1483897779,"wall":"2017-01-08T17:49","msg":"adding finished accessibility material","body":"","parents":["56fe0cb982314bbf8c74d100529d7869d2a9036c"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"6dae4407fabcff3570eb439dd6c73b374355c634","ts":1483897938,"wall":"2017-01-08T17:52","msg":"fix a11y examples","body":"","parents":["8fcd8ce70e13d23553f7e86434745b0fb188b215"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"cc6aacdf7cc4ca50dc5ba4a4a3cd731b369187ba","ts":1483898089,"wall":"2017-01-08T17:54","msg":"fix a11y examples","body":"","parents":["6dae4407fabcff3570eb439dd6c73b374355c634"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"85839d432b64447714ab62c4b86e9e335de6d337","ts":1483898272,"wall":"2017-01-08T17:57","msg":"a11y examples","body":"","parents":["cc6aacdf7cc4ca50dc5ba4a4a3cd731b369187ba"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"3b63adf3759d09b3be5b77994560bf24e595f025","ts":1484256510,"wall":"2017-01-12T21:28","msg":"adding dom manipulation examples to apis module","body":"","parents":["85839d432b64447714ab62c4b86e9e335de6d337"],"add":227,"del":0,"cadd":227,"cdel":0,"files":8},{"repo":"learning-area","hash":"d8568d833b8904e9f7ebdfd2de03b57aa3238911","ts":1484907748,"wall":"2017-01-20T10:22","msg":"fixing <nav> accessibility issue - putting it outside the <header>","body":"","parents":["3b63adf3759d09b3be5b77994560bf24e595f025"],"add":52,"del":61,"cadd":52,"cdel":61,"files":8},{"repo":"learning-area","hash":"3971b29d7e2cdf389c68f20cbe8e757cf8f787be","ts":1485299642,"wall":"2017-01-24T23:14","msg":"adding html table examples","body":"","parents":["d8568d833b8904e9f7ebdfd2de03b57aa3238911"],"add":567,"del":0,"cadd":567,"cdel":0,"files":11},{"repo":"learning-area","hash":"51f303a9b31871a3006ada4913318866131abbe2","ts":1485867025,"wall":"2017-01-31T12:50","msg":"adding advanced html table examples","body":"","parents":["3971b29d7e2cdf389c68f20cbe8e757cf8f787be"],"add":547,"del":4,"cadd":547,"cdel":4,"files":9},{"repo":"learning-area","hash":"9f029dd09b7c9d3b50aeed05e23454085548aa0e","ts":1486034536,"wall":"2017-02-02T11:22","msg":"small fixes to grid layout examples","body":"","parents":["51f303a9b31871a3006ada4913318866131abbe2"],"add":68,"del":53,"cadd":68,"cdel":53,"files":5},{"repo":"learning-area","hash":"e2a8524c0a7888522d5bfcd840dc28053aaa0670","ts":1486493557,"wall":"2017-02-07T18:52","msg":"adding html table assessment","body":"","parents":["9f029dd09b7c9d3b50aeed05e23454085548aa0e"],"add":278,"del":0,"cadd":234,"cdel":0,"files":5},{"repo":"learning-area","hash":"b338a3f67356df90005f1a67307c5a92bb9b79cf","ts":1486552511,"wall":"2017-02-08T11:15","msg":"adding table marking guide and making fixes","body":"","parents":["e2a8524c0a7888522d5bfcd840dc28053aaa0670"],"add":57,"del":5,"cadd":56,"cdel":2,"files":3},{"repo":"learning-area","hash":"94ce02f845d03a0b0795c32b4dfa5e02c76596ad","ts":1486552540,"wall":"2017-02-08T11:15","msg":"adding table marking guide and making fixes","body":"","parents":["b338a3f67356df90005f1a67307c5a92bb9b79cf"],"add":0,"del":2,"cadd":0,"cdel":2,"files":1},{"repo":"learning-area","hash":"fa3e2e7f6f57b40ec31f15055871c26ffa40edf3","ts":1486552805,"wall":"2017-02-08T11:20","msg":"Update marking-guide.md","body":"","parents":["94ce02f845d03a0b0795c32b4dfa5e02c76596ad"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"a6e4c9aa32762429b5ebfeced4ff2d4d78db3053","ts":1486993747,"wall":"2017-02-13T13:49","msg":"adding basic html forms examples","body":"","parents":["fa3e2e7f6f57b40ec31f15055871c26ffa40edf3"],"add":106,"del":0,"cadd":106,"cdel":0,"files":2},{"repo":"learning-area","hash":"3c9b133c64404dd109dbffd72bf47cfe5d6b07b9","ts":1487070708,"wall":"2017-02-14T11:11","msg":"updating payment form example","body":"","parents":["a6e4c9aa32762429b5ebfeced4ff2d4d78db3053"],"add":231,"del":0,"cadd":231,"cdel":0,"files":5},{"repo":"learning-area","hash":"dd707b25a104e922402387a47e1c2bb6b67a930d","ts":1487192862,"wall":"2017-02-15T21:07","msg":"adding form eidget examples","body":"","parents":["3c9b133c64404dd109dbffd72bf47cfe5d6b07b9"],"add":327,"del":0,"cadd":327,"cdel":0,"files":8},{"repo":"learning-area","hash":"2f9e2eab00496bebbd8b2efc034d9be2e91c608c","ts":1487594370,"wall":"2017-02-20T12:39","msg":"fixing specificity terminology","body":"","parents":["dd707b25a104e922402387a47e1c2bb6b67a930d"],"add":12,"del":16,"cadd":12,"cdel":12,"files":3},{"repo":"learning-area","hash":"a45b4fe511712f9f730d0421fc50362d8c7f6bf6","ts":1487694726,"wall":"2017-02-21T16:32","msg":"adding form submission examples","body":"","parents":["2f9e2eab00496bebbd8b2efc034d9be2e91c608c"],"add":134,"del":0,"cadd":126,"cdel":0,"files":6},{"repo":"learning-area","hash":"eed42ee777ee05656aa5d1b28f09e56109dbaf07","ts":1487768845,"wall":"2017-02-22T13:07","msg":"updating python example to something that works","body":"","parents":["a45b4fe511712f9f730d0421fc50362d8c7f6bf6"],"add":65,"del":0,"cadd":65,"cdel":0,"files":5},{"repo":"learning-area","hash":"9b66ef72e91bae6b2a304b78b5c44799b82575a0","ts":1488533812,"wall":"2017-03-03T09:36","msg":"simplifying collision detection code","body":"","parents":["eed42ee777ee05656aa5d1b28f09e56109dbaf07"],"add":5,"del":5,"cadd":5,"cdel":5,"files":2},{"repo":"learning-area","hash":"c2f97874aee424f5446c67eb11c5e7f8121a7c39","ts":1489422423,"wall":"2017-03-13T16:27","msg":"adding more complex example to fetching data article of APIs module","body":"","parents":["9b66ef72e91bae6b2a304b78b5c44799b82575a0"],"add":1308,"del":8,"cadd":1120,"cdel":8,"files":49},{"repo":"learning-area","hash":"95bf6682f7d5711dd0cbbef25cfbea5ebe5f5397","ts":1489491382,"wall":"2017-03-14T11:36","msg":"updating google maps example to use https - ooops","body":"","parents":["c2f97874aee424f5446c67eb11c5e7f8121a7c39"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"857bfb21fe414993751c1e3dc7fc2cc016782a03","ts":1489565910,"wall":"2017-03-15T08:18","msg":"adding password field example","body":"","parents":["95bf6682f7d5711dd0cbbef25cfbea5ebe5f5397"],"add":8,"del":1,"cadd":8,"cdel":1,"files":1},{"repo":"learning-area","hash":"24b46344bf9126d196bab94af9b77effc37e4155","ts":1490023591,"wall":"2017-03-20T11:26","msg":"fixing errors in the HTML assessment on marking up a letter","body":"","parents":["857bfb21fe414993751c1e3dc7fc2cc016782a03"],"add":4,"del":4,"cadd":2,"cdel":2,"files":3},{"repo":"learning-area","hash":"6528e95be902a66b2f43331f00cae34b986dda0b","ts":1490033494,"wall":"2017-03-20T14:11","msg":"adding editable canvas demo from Math article to github","body":"","parents":["24b46344bf9126d196bab94af9b77effc37e4155"],"add":75,"del":0,"cadd":75,"cdel":0,"files":1},{"repo":"learning-area","hash":"3c5e4955d6ceb885aab87a9d475f7e9a4a78fe15","ts":1490107419,"wall":"2017-03-21T10:43","msg":"adding editable form input example","body":"","parents":["6528e95be902a66b2f43331f00cae34b986dda0b"],"add":76,"del":0,"cadd":76,"cdel":0,"files":1},{"repo":"learning-area","hash":"8dd83e055307aab26b04c672733684a7953791b9","ts":1490110966,"wall":"2017-03-21T11:42","msg":"adding combinators example, and forms and api examples","body":"","parents":["3c5e4955d6ceb885aab87a9d475f7e9a4a78fe15"],"add":271,"del":0,"cadd":271,"cdel":0,"files":7},{"repo":"learning-area","hash":"d8d018e01b320ded828563fda533f13654d227f2","ts":1490191393,"wall":"2017-03-22T10:03","msg":"improving layout of editable form","body":"","parents":["8dd83e055307aab26b04c672733684a7953791b9"],"add":3,"del":3,"cadd":3,"cdel":3,"files":1},{"repo":"learning-area","hash":"4fc9bb690ac7612629c5481f349259c1cc3fd18f","ts":1490208722,"wall":"2017-03-22T14:52","msg":"nytimes examples, plus updating marking guide","body":"","parents":["d8d018e01b320ded828563fda533f13654d227f2"],"add":218,"del":35,"cadd":218,"cdel":35,"files":3},{"repo":"learning-area","hash":"9ac36ee1cbfc407f031691215b2a9f653354e9ce","ts":1490366603,"wall":"2017-03-24T10:43","msg":"adding youtube api example, and fixing another marking guide","body":"","parents":["4fc9bb690ac7612629c5481f349259c1cc3fd18f"],"add":232,"del":4,"cadd":232,"cdel":4,"files":4},{"repo":"learning-area","hash":"4838e60e7278b06e7e0ee3f5032eaa62d305c3e8","ts":1490401756,"wall":"2017-03-24T20:29","msg":"finalizing the API examples","body":"","parents":["9ac36ee1cbfc407f031691215b2a9f653354e9ce"],"add":96,"del":4,"cadd":96,"cdel":4,"files":3},{"repo":"learning-area","hash":"9d14f0624130132981479103ffdb098477872231","ts":1490647850,"wall":"2017-03-27T21:50","msg":"updating iframe sizes to make them fit better in the pages","body":"","parents":["4838e60e7278b06e7e0ee3f5032eaa62d305c3e8"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"ebd0e5e292d7459221f351c7a537e9592dac6b18","ts":1490774888,"wall":"2017-03-29T09:08","msg":"updating hummus spelling in text examples","body":"","parents":["9d14f0624130132981479103ffdb098477872231"],"add":18,"del":18,"cadd":18,"cdel":18,"files":2},{"repo":"deck-of-cards","hash":"8aa9ccfbe1a847f84d972550e568200892b84e54","ts":1490778573,"wall":"2017-03-29T12:09","msg":"fixes #36","body":"","parents":["3e64104233abb3521f1659d0c1f9ba30df912732"],"add":3,"del":1,"cadd":3,"cdel":1,"files":3},{"repo":"deck-of-cards","hash":"f4c0393ed9e852f92713f32e9e87deafbd4e6541","ts":1490778580,"wall":"2017-03-29T12:09","msg":"0.1.7","body":"","parents":["8aa9ccfbe1a847f84d972550e568200892b84e54"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"57fc3f5270fff072554a5a441c9c33db49920ed4","ts":1490778734,"wall":"2017-03-29T12:12","msg":"added postversion script","body":"","parents":["f4c0393ed9e852f92713f32e9e87deafbd4e6541"],"add":2,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"b4b9aa556abd7995b905333eefc3c76b70ed3931","ts":1490778812,"wall":"2017-03-29T12:13","msg":"updated version","body":"","parents":["c8766afd021f9f9172742fc0c935b0179fd78a50"],"add":2,"del":1,"cadd":2,"cdel":1,"files":2},{"repo":"learning-area","hash":"63b75c2a1bd5516df2bfe416d1bb0a587f16c438","ts":1491288225,"wall":"2017-04-04T07:43","msg":"fixing busienss card formatting","body":"","parents":["ebd0e5e292d7459221f351c7a537e9592dac6b18"],"add":6,"del":6,"cadd":6,"cdel":6,"files":1},{"repo":"learning-area","hash":"06950fe220f5e97227773f419ef571edde01e97a","ts":1491295408,"wall":"2017-04-04T09:43","msg":"updating blend-mode article","body":"","parents":["63b75c2a1bd5516df2bfe416d1bb0a587f16c438"],"add":15,"del":15,"cadd":15,"cdel":15,"files":1},{"repo":"learning-area","hash":"b0259e5153219f4766a94da44c4cb837e0ec06d9","ts":1491296526,"wall":"2017-04-04T10:02","msg":"fixing silly story generator marking guide formatting","body":"","parents":["06950fe220f5e97227773f419ef571edde01e97a"],"add":7,"del":7,"cadd":7,"cdel":7,"files":1},{"repo":"learning-area","hash":"0e8939256724d76f3bc2ef9a0da0d02be5374333","ts":1491297706,"wall":"2017-04-04T10:21","msg":"more improvements to blend mode example","body":"","parents":["b0259e5153219f4766a94da44c4cb837e0ec06d9"],"add":2,"del":3,"cadd":2,"cdel":3,"files":1},{"repo":"learning-area","hash":"02befd8f35bb931578e25bc823e7cab01fbf9682","ts":1491312425,"wall":"2017-04-04T14:27","msg":"adding WebGL example to graphics folder","body":"","parents":["0e8939256724d76f3bc2ef9a0da0d02be5374333"],"add":1,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"a1158932a198ffdd95b60433a85d6771f5bdfd4b","ts":1491312763,"wall":"2017-04-04T14:32","msg":"removing bad folder","body":"","parents":["0e8939256724d76f3bc2ef9a0da0d02be5374333"],"add":1,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"3026fe2c613b5bb25121f38cb5c9ddd3bef33fc7","ts":1491312788,"wall":"2017-04-04T14:33","msg":"Merge branch 'master' of https://github.com/chrisdavidmills/learning-area","body":"","parents":["a1158932a198ffdd95b60433a85d6771f5bdfd4b","02befd8f35bb931578e25bc823e7cab01fbf9682"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"264aefa7c81c736279262f1a761fc977b3efaab9","ts":1491312828,"wall":"2017-04-04T14:33","msg":"remove bad folder","body":"","parents":["3026fe2c613b5bb25121f38cb5c9ddd3bef33fc7"],"add":0,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"3215cc626de10adb5a726146b8d036a9b045ed5f","ts":1491312958,"wall":"2017-04-04T14:35","msg":"add WebGL example to draging-graphics","body":"","parents":["264aefa7c81c736279262f1a761fc977b3efaab9"],"add":993,"del":0,"cadd":993,"cdel":0,"files":6},{"repo":"learning-area","hash":"f45637c0b229afd9a1857ecfe4cae733e101db17","ts":1491313355,"wall":"2017-04-04T14:42","msg":"adding standard cube example to drawing-graphics","body":"","parents":["3215cc626de10adb5a726146b8d036a9b045ed5f"],"add":959,"del":0,"cadd":959,"cdel":0,"files":6},{"repo":"learning-area","hash":"d89ee976428c14dbfd20f65b3a1bb11abaa0cf7b","ts":1491314100,"wall":"2017-04-04T14:55","msg":"adding standard cube example to drawing-graphics","body":"","parents":["f45637c0b229afd9a1857ecfe4cae733e101db17"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"76635bdf3bd8c560e1d58524410b2c968c05f53e","ts":1491420145,"wall":"2017-04-05T20:22","msg":"adding simple canvas examples","body":"","parents":["d89ee976428c14dbfd20f65b3a1bb11abaa0cf7b"],"add":214,"del":0,"cadd":214,"cdel":0,"files":7},{"repo":"deck-of-cards","hash":"d85cf760ca08027416a95483d3e7e2d345ec119c","ts":1491422807,"wall":"2017-04-05T23:06","msg":"Update README.md","body":"","parents":["57fc3f5270fff072554a5a441c9c33db49920ed4"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"eb29470f971fc5b8fd8d484ffc4f62324a0d04f1","ts":1491422819,"wall":"2017-04-05T23:06","msg":"Update README.md","body":"","parents":["d85cf760ca08027416a95483d3e7e2d345ec119c"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"abb91ff8826193b817c13981601b807188f88935","ts":1491487367,"wall":"2017-04-06T15:02","msg":"animation examples","body":"","parents":["76635bdf3bd8c560e1d58524410b2c968c05f53e"],"add":120,"del":0,"cadd":120,"cdel":0,"files":3},{"repo":"learning-area","hash":"e475e7b07928df8f686f39c5f6f662b92528557c","ts":1491497567,"wall":"2017-04-06T17:52","msg":"animation examples","body":"","parents":["abb91ff8826193b817c13981601b807188f88935"],"add":112,"del":0,"cadd":112,"cdel":0,"files":1},{"repo":"learning-area","hash":"af874dffcc206515745b2acdaf9cccf677309a86","ts":1491518847,"wall":"2017-04-06T23:47","msg":"updating Three demos","body":"","parents":["e475e7b07928df8f686f39c5f6f662b92528557c"],"add":920,"del":953,"cadd":920,"cdel":953,"files":11},{"repo":"learning-area","hash":"04eff0045691e666c05315f9c532ac2b6a292196","ts":1491836643,"wall":"2017-04-10T16:04","msg":"fixing bouncing balls guide formatting","body":"","parents":["af874dffcc206515745b2acdaf9cccf677309a86"],"add":7,"del":6,"cadd":7,"cdel":6,"files":1},{"repo":"learning-area","hash":"14b999d201468d2625c0a2c8226bc1f415c9e503","ts":1491862968,"wall":"2017-04-10T23:22","msg":"adding indeterminate example","body":"","parents":["04eff0045691e666c05315f9c532ac2b6a292196"],"add":68,"del":0,"cadd":68,"cdel":0,"files":1},{"repo":"learning-area","hash":"fbe6e9e363d49a2c4cfdd75b2b4fcc95136940b4","ts":1492030775,"wall":"2017-04-12T21:59","msg":"adding input type date example with fallback for non-supporting browsers","body":"","parents":["14b999d201468d2625c0a2c8226bc1f415c9e503"],"add":192,"del":0,"cadd":192,"cdel":0,"files":1},{"repo":"learning-area","hash":"5d0c5a6ec00110335c5e67f5fd9059070c01b09b","ts":1492030991,"wall":"2017-04-12T22:03","msg":"adding input type date example with fallback for non-supporting browsers","body":"","parents":["fbe6e9e363d49a2c4cfdd75b2b4fcc95136940b4"],"add":1,"del":3,"cadd":1,"cdel":3,"files":1},{"repo":"learning-area","hash":"64641abda2edaebaa46acc7ddda379b3ca4cb1ca","ts":1492031074,"wall":"2017-04-12T22:04","msg":"fixing mistake","body":"","parents":["fbe6e9e363d49a2c4cfdd75b2b4fcc95136940b4"],"add":1,"del":3,"cadd":1,"cdel":3,"files":1},{"repo":"learning-area","hash":"08d4915bfed37490febda192dee26c62574f20e9","ts":1492073134,"wall":"2017-04-13T09:45","msg":"minor modification to NYTimes API example - changing the API key to an obvious dummy key","body":"","parents":["5d0c5a6ec00110335c5e67f5fd9059070c01b09b"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"8f5f602a758bcdf6c9fcbac0d058bdc9e4704d15","ts":1492073266,"wall":"2017-04-13T09:47","msg":"Merge branch 'master' of https://github.com/chrisdavidmills/learning-area","body":"","parents":["08d4915bfed37490febda192dee26c62574f20e9","64641abda2edaebaa46acc7ddda379b3ca4cb1ca"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"311c88ea0d65fcee63a196cc2e577678d016b47f","ts":1492079555,"wall":"2017-04-13T11:32","msg":"fixing a few for loops that dont have var keywords","body":"","parents":["8f5f602a758bcdf6c9fcbac0d058bdc9e4704d15"],"add":5,"del":5,"cadd":5,"cdel":5,"files":2},{"repo":"learning-area","hash":"f8177739803b59098f1ff490d62cf42c40944bfa","ts":1492433777,"wall":"2017-04-17T13:56","msg":"adding new google maps starting file with dummy api key in it","body":"","parents":["311c88ea0d65fcee63a196cc2e577678d016b47f"],"add":41,"del":0,"cadd":41,"cdel":0,"files":1},{"repo":"learning-area","hash":"5354a5327a93901c284e0a26897314bb322ec49b","ts":1492451760,"wall":"2017-04-17T11:56","msg":"Update number-guessing-game-start.html","body":"","parents":["f8177739803b59098f1ff490d62cf42c40944bfa"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"87f00e28bed21a66fc2519c818978221f1b17e01","ts":1492706438,"wall":"2017-04-20T17:40","msg":"small correction to letter assessment","body":"","parents":["f8177739803b59098f1ff490d62cf42c40944bfa"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"4b38d336a9f20fabe598591eb510242a4c0362c8","ts":1492716218,"wall":"2017-04-20T20:23","msg":"adding input type hidden example","body":"","parents":["87f00e28bed21a66fc2519c818978221f1b17e01"],"add":48,"del":0,"cadd":48,"cdel":0,"files":1},{"repo":"learning-area","hash":"5401b463dd9b0bfabdce5c5440ec2a62dd737414","ts":1492716798,"wall":"2017-04-20T20:33","msg":"adding input type hidden example","body":"","parents":["4b38d336a9f20fabe598591eb510242a4c0362c8"],"add":9,"del":0,"cadd":9,"cdel":0,"files":1},{"repo":"learning-area","hash":"99cccd0c08262b32b2a70934e77d0684b30a87dc","ts":1493019610,"wall":"2017-04-24T08:40","msg":"adding datetime-local example","body":"","parents":["5401b463dd9b0bfabdce5c5440ec2a62dd737414"],"add":17,"del":0,"cadd":17,"cdel":0,"files":1},{"repo":"learning-area","hash":"d352b668a55fb632183acf8aee34c76cdf9e1441","ts":1493026280,"wall":"2017-04-24T10:31","msg":"updating datetime-local example so I can test min and max datetimes","body":"","parents":["99cccd0c08262b32b2a70934e77d0684b30a87dc"],"add":4,"del":4,"cadd":4,"cdel":4,"files":1},{"repo":"deck-of-cards","hash":"ba0facb444ec0924932c008cc7ebf249ae1575df","ts":1493029281,"wall":"2017-04-24T13:21","msg":"Update package.json","body":"","parents":["eb29470f971fc5b8fd8d484ffc4f62324a0d04f1"],"add":1,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"1207c0a6fdfae77645e891553025316d0222103d","ts":1493029425,"wall":"2017-04-24T13:23","msg":"0.1.8","body":"","parents":["ba0facb444ec0924932c008cc7ebf249ae1575df"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"1103fe7a239a176cea08ddcbe4d0ce727187789f","ts":1493047073,"wall":"2017-04-24T16:17","msg":"fixing datetime-local examples, adding a number example","body":"","parents":["d352b668a55fb632183acf8aee34c76cdf9e1441"],"add":299,"del":29,"cadd":299,"cdel":29,"files":4},{"repo":"learning-area","hash":"a011ad83cd47b1649ded6085d41531444e8087a9","ts":1493130382,"wall":"2017-04-25T15:26","msg":"updating input type=\"number\" example","body":"","parents":["1103fe7a239a176cea08ddcbe4d0ce727187789f"],"add":65,"del":11,"cadd":65,"cdel":11,"files":2},{"repo":"learning-area","hash":"089c45a3e0d7c00b4b4027736509033e13bcb966","ts":1493205171,"wall":"2017-04-26T12:12","msg":"adding input type image example","body":"","parents":["a011ad83cd47b1649ded6085d41531444e8087a9"],"add":37,"del":0,"cadd":37,"cdel":0,"files":3},{"repo":"learning-area","hash":"e3ef02d893b9c82c7400a093b08cd01ad8be18a8","ts":1493211708,"wall":"2017-04-26T14:01","msg":"adding color chooser example","body":"","parents":["089c45a3e0d7c00b4b4027736509033e13bcb966"],"add":29,"del":0,"cadd":29,"cdel":0,"files":3},{"repo":"learning-area","hash":"a0c7e3b56d0d0c3c07b7ea3c9d9c2c6437ee99aa","ts":1493703600,"wall":"2017-05-02T06:40","msg":"fixing minor typo in example","body":"","parents":["e3ef02d893b9c82c7400a093b08cd01ad8be18a8"],"add":398,"del":1,"cadd":398,"cdel":1,"files":17},{"repo":"learning-area","hash":"e6a82fc22675457f3281c4b6da6fe8470046e1e8","ts":1493705379,"wall":"2017-05-02T07:09","msg":"fixing a few small errors, adding copyright notice in for the video","body":"","parents":["a0c7e3b56d0d0c3c07b7ea3c9d9c2c6437ee99aa"],"add":90,"del":62,"cadd":90,"cdel":62,"files":6},{"repo":"learning-area","hash":"bf2e805ae59d0e3fff3f885c30e0efc3a7d5e1b4","ts":1493721556,"wall":"2017-05-02T11:39","msg":"adding minor fix for problem with embedded layout in MDN article","body":"","parents":["e6a82fc22675457f3281c4b6da6fe8470046e1e8"],"add":14,"del":13,"cadd":14,"cdel":13,"files":2},{"repo":"learning-area","hash":"f63a58a7d6ab764894aaa301392b68c5cc8e7345","ts":1493721754,"wall":"2017-05-02T11:42","msg":"adding minor fix for problem with embedded layout in MDN article","body":"","parents":["bf2e805ae59d0e3fff3f885c30e0efc3a7d5e1b4"],"add":9,"del":0,"cadd":9,"cdel":0,"files":2},{"repo":"learning-area","hash":"cf679d8f300cd8946120aef140c77cd53338eff3","ts":1493721905,"wall":"2017-05-02T11:45","msg":"adding minor fix for problem with embedded layout in MDN article","body":"","parents":["f63a58a7d6ab764894aaa301392b68c5cc8e7345"],"add":0,"del":2,"cadd":0,"cdel":2,"files":2},{"repo":"learning-area","hash":"446dbc0278eb121776f01144bde42efa75a59990","ts":1493808208,"wall":"2017-05-03T11:43","msg":"Merge pull request #6 from Knock7/patch-1","body":"Update number-guessing-game-start.html","parents":["cf679d8f300cd8946120aef140c77cd53338eff3","5354a5327a93901c284e0a26897314bb322ec49b"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"347c35f5ce6d0f3ec539727be9c7d30b38fe973c","ts":1493817773,"wall":"2017-05-03T14:22","msg":"improving shopping list example","body":"","parents":["446dbc0278eb121776f01144bde42efa75a59990"],"add":5,"del":5,"cadd":5,"cdel":5,"files":2},{"repo":"learning-area","hash":"2e818b4a533805fae9081facce6d0c6c1334af6e","ts":1493841810,"wall":"2017-05-03T21:03","msg":"fixing assessment markdown","body":"","parents":["347c35f5ce6d0f3ec539727be9c7d30b38fe973c"],"add":14,"del":15,"cadd":14,"cdel":15,"files":3},{"repo":"learning-area","hash":"7ed646d6d6ecafcaae5114d78f4f5296fe92f61e","ts":1493919065,"wall":"2017-05-04T18:31","msg":"fixing issue with call() usage in oojs examples","body":"","parents":["2e818b4a533805fae9081facce6d0c6c1334af6e"],"add":16,"del":16,"cadd":16,"cdel":16,"files":4},{"repo":"learning-area","hash":"122ba2dc4c329c7257fe2a0830d05163b55dd94e","ts":1493927559,"wall":"2017-05-04T20:52","msg":"fixing issue with call() usage in oojs examples","body":"","parents":["7ed646d6d6ecafcaae5114d78f4f5296fe92f61e"],"add":45,"del":30,"cadd":45,"cdel":30,"files":3},{"repo":"learning-area","hash":"b157ad8612b5c1d99d4e246c59ce9c94212e23a7","ts":1495446309,"wall":"2017-05-22T15:15","msg":"Improved Code Readability","body":"Hey, I wish to contribute to the guide. Please take a look at my changes and let me know your feedback. I'm also learning. I learn't JavaScript and I want to master CSS. Thank you.","parents":["122ba2dc4c329c7257fe2a0830d05163b55dd94e"],"add":5,"del":9,"cadd":5,"cdel":9,"files":1},{"repo":"learning-area","hash":"61344ec74824bf05f2dfc34da3cdcfb84dcdb5a2","ts":1495446492,"wall":"2017-05-22T15:18","msg":"Improved Code Readability","body":"Hey there, I'm going through the MDN Guide. Thanks. I wish to contribute, so please take a look and provide me with feedback. Thank you.","parents":["b157ad8612b5c1d99d4e246c59ce9c94212e23a7"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"64253d81f46d2a3601df65e0f11e2528ef71ab9f","ts":1495448997,"wall":"2017-05-22T11:29","msg":"Merge pull request #8 from clintonyeb/master","body":"Improved Code Readability","parents":["122ba2dc4c329c7257fe2a0830d05163b55dd94e","61344ec74824bf05f2dfc34da3cdcfb84dcdb5a2"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"e981fb54fc265e38d2f7c388428cbc225bdcb20a","ts":1495449159,"wall":"2017-05-22T11:32","msg":"updating original info box example to use the new code too.","body":"","parents":["64253d81f46d2a3601df65e0f11e2528ef71ab9f"],"add":7,"del":11,"cadd":7,"cdel":11,"files":1},{"repo":"learning-area","hash":"052eeb5290113f84111c733801a2e9c689489fec","ts":1495461696,"wall":"2017-05-22T15:01","msg":"fixing markdown formatting on a couple of assessments","body":"","parents":["e981fb54fc265e38d2f7c388428cbc225bdcb20a"],"add":9,"del":10,"cadd":9,"cdel":10,"files":2},{"repo":"learning-area","hash":"ecf742752d51454d923b1df6f29475f8077138e7","ts":1496121355,"wall":"2017-05-30T01:15","msg":"Fix minor HTML issues","body":"","parents":["052eeb5290113f84111c733801a2e9c689489fec"],"add":8,"del":8,"cadd":8,"cdel":8,"files":4},{"repo":"learning-area","hash":"d832828948c7148f3355dbee17bf71e185de48f0","ts":1496126616,"wall":"2017-05-30T07:43","msg":"Merge pull request #9 from daywaves/html-fixes","body":"Fix minor HTML issues","parents":["052eeb5290113f84111c733801a2e9c689489fec","ecf742752d51454d923b1df6f29475f8077138e7"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"619bf3fc83d3c5088ed4c951ff702a3df3165238","ts":1496214737,"wall":"2017-05-31T08:12","msg":"updating function examples to use panel.parentNode.removeChild(panel);","body":"","parents":["d832828948c7148f3355dbee17bf71e185de48f0"],"add":6,"del":6,"cadd":6,"cdel":6,"files":2},{"repo":"learning-area","hash":"ad13d15dde66572a9f04182256544f02a87ea37b","ts":1496961847,"wall":"2017-06-08T15:44","msg":"Update marking-guide.md","body":"","parents":["619bf3fc83d3c5088ed4c951ff702a3df3165238"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"31c4420d4b5f94e108aae86882cb45014e73f8de","ts":1496999832,"wall":"2017-06-09T10:17","msg":"Merge pull request #10 from mdn/wbamberg-patch-1","body":"Fix a typo - thanks Will!","parents":["619bf3fc83d3c5088ed4c951ff702a3df3165238","ad13d15dde66572a9f04182256544f02a87ea37b"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"e48b73b8edfebc0e53a977de645df5bf92ee754e","ts":1497000051,"wall":"2017-06-09T14:50","msg":"misplaced semi-colon ( ; )","body":"button { margin: 10px } ;  changed into button { margin: 10px ; }","parents":["31c4420d4b5f94e108aae86882cb45014e73f8de"],"add":3,"del":3,"cadd":3,"cdel":3,"files":1},{"repo":"learning-area","hash":"8d212cd9caa7079989ff6e0104f5b80cd7870108","ts":1497196069,"wall":"2017-06-11T16:47","msg":"Merge pull request #11 from GowthamPrakaash/patch-2","body":"misplaced semi-colon ( ; )","parents":["31c4420d4b5f94e108aae86882cb45014e73f8de","e48b73b8edfebc0e53a977de645df5bf92ee754e"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"91918d4e8a1dab067f4e228bd1e734d7afebeee4","ts":1497372573,"wall":"2017-06-13T17:49","msg":"moving script elements inside the body","body":"","parents":["8d212cd9caa7079989ff6e0104f5b80cd7870108"],"add":17,"del":15,"cadd":17,"cdel":15,"files":2},{"repo":"learning-area","hash":"56ee4d8da1ca813f36a022523401702b325ee119","ts":1497474891,"wall":"2017-06-14T16:14","msg":"Moved script tag into body","body":"","parents":["91918d4e8a1dab067f4e228bd1e734d7afebeee4"],"add":1,"del":2,"cadd":1,"cdel":2,"files":1},{"repo":"learning-area","hash":"ba71a2265aecc9a2ade7dc422087fc8914052182","ts":1497513219,"wall":"2017-06-15T08:53","msg":"Merge pull request #12 from hadleyel/patch-1","body":"Moved <script> element into <body> element","parents":["91918d4e8a1dab067f4e228bd1e734d7afebeee4","56ee4d8da1ca813f36a022523401702b325ee119"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"842feb1253b83457e8abfd1c7a1e0a3d7ae11acd","ts":1497555418,"wall":"2017-06-15T14:36","msg":"Moved <script> into <body>, removed .focus()","body":"Moved <script> element into <body> element following W3C recommendations; removed inputForm.focus(), which caused the page at https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps/Math to jump past the first few paragraphs of content to the console whenever newly accessed.","parents":["ba71a2265aecc9a2ade7dc422087fc8914052182"],"add":3,"del":6,"cadd":3,"cdel":6,"files":1},{"repo":"learning-area","hash":"8a7b16bf87c76666b44be28a90a749e7b7b040b9","ts":1497760572,"wall":"2017-06-17T21:36","msg":"Fix the [for] attribute of the password label","body":"","parents":["ba71a2265aecc9a2ade7dc422087fc8914052182"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"f9c1e949c306ea92547f25cf68024236fef138e0","ts":1497860580,"wall":"2017-06-19T09:23","msg":"Merge pull request #15 from vhalbwachs/patch-1","body":"Fix the [for] attribute of the password label","parents":["ba71a2265aecc9a2ade7dc422087fc8914052182","8a7b16bf87c76666b44be28a90a749e7b7b040b9"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"4b024b66831c2e94740f0b5a15ed43e9bf71b00e","ts":1497874160,"wall":"2017-06-19T13:09","msg":"Merge pull request #13 from hadleyel/patch-1","body":"Moved <script> into <body>, removed .focus()","parents":["f9c1e949c306ea92547f25cf68024236fef138e0","842feb1253b83457e8abfd1c7a1e0a3d7ae11acd"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"298328441f500fd9e21b825cc1306ecc021bb897","ts":1497875375,"wall":"2017-06-19T13:29","msg":"added check so that the inputs are automatically focused only when the created input is not the first on the page - fixes the problem of the page jumping to the example when embedded, when it first loads","body":"","parents":["4b024b66831c2e94740f0b5a15ed43e9bf71b00e"],"add":6,"del":4,"cadd":6,"cdel":4,"files":1},{"repo":"deck-of-cards","hash":"ec6a864c67681792101e67107fe93b9ede4dbd1c","ts":1497898014,"wall":"2017-06-19T21:46","msg":"Add will-change","body":"","parents":["1207c0a6fdfae77645e891553025316d0222103d"],"add":407,"del":0,"cadd":406,"cdel":0,"files":4},{"repo":"deck-of-cards","hash":"a7d5ebf74aca234d6a7b1e43ba65f2101898399d","ts":1497898019,"wall":"2017-06-19T21:46","msg":"0.1.9","body":"","parents":["ec6a864c67681792101e67107fe93b9ede4dbd1c"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"6667c33e9b744f688f3a7947a2661238b2b8790b","ts":1497898077,"wall":"2017-06-19T21:47","msg":"Add will-change","body":"","parents":["b4b9aa556abd7995b905333eefc3c76b70ed3931"],"add":411,"del":46,"cadd":411,"cdel":46,"files":4},{"repo":"deck-of-cards","hash":"2569f00e2e4ad18c6c34e04d51d33b4066643624","ts":1497898606,"wall":"2017-06-19T21:56","msg":"Rollback","body":"","parents":["6667c33e9b744f688f3a7947a2661238b2b8790b"],"add":91,"del":9,"cadd":91,"cdel":9,"files":2},{"repo":"deck-of-cards","hash":"5b3c55ba585c3ef6afb2fa13724a2ab0b32b04d5","ts":1497899056,"wall":"2017-06-19T22:04","msg":"Fix Twitter image","body":"","parents":["2569f00e2e4ad18c6c34e04d51d33b4066643624"],"add":2,"del":2,"cadd":2,"cdel":2,"files":2},{"repo":"learning-area","hash":"b273659b6216983efc645575d3ebab271f68b1ec","ts":1498372951,"wall":"2017-06-25T01:42","msg":"changed btn.onmouseout to btn.onclick","body":"The article specifies to change btn.onclick to different values, but there is no btn.onclick. I believe it was meant to have btn.onmouseout be as btn.onclick. The user is supposed to change it to btn.onmouseout later in the experiment.","parents":["298328441f500fd9e21b825cc1306ecc021bb897"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"25c55a439c834a75fde44598df630a8c0f97bf36","ts":1498579848,"wall":"2017-06-27T09:10","msg":"Merge pull request #20 from qdirks/qdirks-patch-1","body":"changed btn.onmouseout to btn.onclick","parents":["298328441f500fd9e21b825cc1306ecc021bb897","b273659b6216983efc645575d3ebab271f68b1ec"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"6c4954ed8da562134408d6adb14079b489961795","ts":1498694428,"wall":"2017-06-28T17:00","msg":"spelling correction","body":"","parents":["25c55a439c834a75fde44598df630a8c0f97bf36"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"14ca31539c088dcff046fc29d86082ca7c46c89a","ts":1498744443,"wall":"2017-06-29T06:54","msg":"Merge pull request #21 from jrpool/patch-1","body":"spelling correction","parents":["25c55a439c834a75fde44598df630a8c0f97bf36","6c4954ed8da562134408d6adb14079b489961795"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"7d6a8d0e4836dd00392dc02f7de5d28b5d7278f6","ts":1498865879,"wall":"2017-06-30T16:37","msg":"adding input type file examples","body":"","parents":["14ca31539c088dcff046fc29d86082ca7c46c89a"],"add":189,"del":3,"cadd":189,"cdel":3,"files":4},{"repo":"learning-area","hash":"a1b307d632549f7f014639d05bcf5929bbcdab90","ts":1499440322,"wall":"2017-07-07T16:12","msg":"fixing up JSON examples to use best practice for loops","body":"","parents":["7d6a8d0e4836dd00392dc02f7de5d28b5d7278f6"],"add":23,"del":15,"cadd":23,"cdel":15,"files":3},{"repo":"learning-area","hash":"f9e9eac4979bf9183686ffb0c250a22e22536bf6","ts":1499663032,"wall":"2017-07-10T06:03","msg":"removing summary from starting state of a11y assessment","body":"","parents":["a1b307d632549f7f014639d05bcf5929bbcdab90"],"add":10,"del":10,"cadd":10,"cdel":10,"files":3},{"repo":"learning-area","hash":"684e45d6182ae44ede7adf90b36c26322df73a0e","ts":1500221844,"wall":"2017-07-17T00:17","msg":"Fixed typo of file-example.html","body":"","parents":["f9e9eac4979bf9183686ffb0c250a22e22536bf6"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"37222b877d5dedcc8db1e17da9638506500129f4","ts":1500284470,"wall":"2017-07-17T10:41","msg":"fixing marking guide formatting","body":"","parents":["f9e9eac4979bf9183686ffb0c250a22e22536bf6"],"add":6,"del":7,"cadd":6,"cdel":7,"files":1},{"repo":"learning-area","hash":"b39c8899411367c2b21dae7ae65a7881321d48eb","ts":1500287215,"wall":"2017-07-17T18:26","msg":"Remove the unnecessary line.","body":"","parents":["684e45d6182ae44ede7adf90b36c26322df73a0e"],"add":0,"del":1,"cadd":0,"cdel":1,"files":1},{"repo":"learning-area","hash":"4b0cce1487c409dec3e7bcdb7db062a9648dd80a","ts":1500289358,"wall":"2017-07-17T12:02","msg":"Merge pull request #26 from pezy/patch-1","body":"Fixed typo of file-example.html","parents":["37222b877d5dedcc8db1e17da9638506500129f4","b39c8899411367c2b21dae7ae65a7881321d48eb"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"fbce78ca8c777098401392e3cfc27cdd8fadcc93","ts":1500367979,"wall":"2017-07-18T09:52","msg":"fixing some minor code lint warnings","body":"","parents":["4b0cce1487c409dec3e7bcdb7db062a9648dd80a"],"add":11,"del":11,"cadd":11,"cdel":11,"files":1},{"repo":"learning-area","hash":"86161e8d468d40119f779876e9adf3da17e23096","ts":1500375398,"wall":"2017-07-18T11:56","msg":"making list-style-type usage more consistent","body":"","parents":["fbce78ca8c777098401392e3cfc27cdd8fadcc93"],"add":6,"del":6,"cadd":6,"cdel":6,"files":1},{"repo":"learning-area","hash":"347487fabace51fc3d2ed778e0bd098bc761d55f","ts":1500397151,"wall":"2017-07-18T19:59","msg":"Move <script> tags before the closing </body>","body":"","parents":["86161e8d468d40119f779876e9adf3da17e23096"],"add":171,"del":173,"cadd":171,"cdel":173,"files":11},{"repo":"learning-area","hash":"bad55aa05f89669086965877adb562e6d0ccb002","ts":1500398935,"wall":"2017-07-18T18:28","msg":"Merge pull request #25 from psylone/master","body":"Move <script> tag before the closing </body>.","parents":["86161e8d468d40119f779876e9adf3da17e23096","347487fabace51fc3d2ed778e0bd098bc761d55f"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"cb6cd8381cfa2d8f92b1dc0922f6c9b78be6ac1d","ts":1500454932,"wall":"2017-07-19T10:02","msg":"fixing title of finished CSS comprehension page","body":"","parents":["bad55aa05f89669086965877adb562e6d0ccb002"],"add":5,"del":5,"cadd":5,"cdel":5,"files":3},{"repo":"learning-area","hash":"895c33db460cebc0587c5c0038eefe338952ff93","ts":1500469903,"wall":"2017-07-19T14:11","msg":"adding stacking and float example","body":"","parents":["cb6cd8381cfa2d8f92b1dc0922f6c9b78be6ac1d"],"add":102,"del":0,"cadd":102,"cdel":0,"files":1},{"repo":"learning-area","hash":"a1430f8916513cb5dfa339ce65abe747b68d0193","ts":1500540314,"wall":"2017-07-20T16:45","msg":"Update style.css","body":"","parents":["895c33db460cebc0587c5c0038eefe338952ff93"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"1b215bf0b702d6dc6712c95652d68290fce94e21","ts":1500549844,"wall":"2017-07-20T12:24","msg":"Merge pull request #27 from sunboy-y8/patch-1","body":"Update style.css","parents":["895c33db460cebc0587c5c0038eefe338952ff93","a1430f8916513cb5dfa339ce65abe747b68d0193"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"92e4f1a83e3049fc407100e22b08245d7bc904bd","ts":1500965369,"wall":"2017-07-25T07:49","msg":"removing unneccessary classnames","body":"","parents":["895c33db460cebc0587c5c0038eefe338952ff93"],"add":19,"del":19,"cadd":19,"cdel":19,"files":2},{"repo":"learning-area","hash":"5b439c050ac2ebbdaac02f34e62eb0774c223879","ts":1500965384,"wall":"2017-07-25T07:49","msg":"Merge branch 'master' of https://github.com/chrisdavidmills/learning-area","body":"","parents":["92e4f1a83e3049fc407100e22b08245d7bc904bd","1b215bf0b702d6dc6712c95652d68290fce94e21"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"2a458754b6cadde829de8f9dd6f8825277c9ed23","ts":1501509904,"wall":"2017-07-31T15:05","msg":"removing opacity from stacking/float example so it behaves as expected","body":"","parents":["5b439c050ac2ebbdaac02f34e62eb0774c223879"],"add":0,"del":5,"cadd":0,"cdel":5,"files":1},{"repo":"deck-of-cards","hash":"f468de9f5c1830b2d78d6f73e0c41f0a590426db","ts":1501604926,"wall":"2017-08-01T18:28","msg":"add doc about handle deck and card in javascript","body":"","parents":["a7d5ebf74aca234d6a7b1e43ba65f2101898399d"],"add":149,"del":0,"cadd":149,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"ca7351bb9fa53b6e3dd375134ab7b8631c360298","ts":1501605113,"wall":"2017-08-01T18:31","msg":"add doc about handle deck and card in javascript","body":"","parents":["f468de9f5c1830b2d78d6f73e0c41f0a590426db"],"add":4,"del":4,"cadd":4,"cdel":4,"files":1},{"repo":"deck-of-cards","hash":"f3c57b168eaf241ea170fc0572dcd3f3bda9d4bc","ts":1501672099,"wall":"2017-08-02T14:08","msg":"Merge pull request #39 from alcalyn/feature/doc-api","body":"Api documentation","parents":["a7d5ebf74aca234d6a7b1e43ba65f2101898399d","ca7351bb9fa53b6e3dd375134ab7b8631c360298"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"98e0d8b18502c6a3e39f5155308a6f4b0c746502","ts":1501672166,"wall":"2017-08-02T14:09","msg":"Update README.md","body":"","parents":["f3c57b168eaf241ea170fc0572dcd3f3bda9d4bc"],"add":3,"del":0,"cadd":3,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"7afec8d2585b683445f03aa9a8655283be4b87e5","ts":1501672230,"wall":"2017-08-02T14:10","msg":"Update README.md","body":"","parents":["98e0d8b18502c6a3e39f5155308a6f4b0c746502"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"cb692e866f55b6881ac39efb6329f5e49101a92e","ts":1502219284,"wall":"2017-08-08T22:08","msg":"Responsive ads","body":"","parents":["5b3c55ba585c3ef6afb2fa13724a2ab0b32b04d5"],"add":20,"del":8,"cadd":20,"cdel":8,"files":2},{"repo":"learning-area","hash":"a8cfe1857b38b861e9ff788d1e8f5d9d8749f59f","ts":1503292143,"wall":"2017-08-21T13:09","msg":"Update index.html","body":"The DOM input event is fired synchronously when the value of an <input>, <select>, or <textarea> element is changed. (For input elements with type=checkbox or type=radio, the input event does not fire when a user clicks the control, because the value attribute does not change.)","parents":["2a458754b6cadde829de8f9dd6f8825277c9ed23"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"b456d4e7532777e0e89543637ab0e0b8cc79382a","ts":1503484695,"wall":"2017-08-23T11:38","msg":"Merge pull request #31 from fh408931/patch-4","body":"Update index.html","parents":["2a458754b6cadde829de8f9dd6f8825277c9ed23","a8cfe1857b38b861e9ff788d1e8f5d9d8749f59f"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"a857aad04bcdb45606a6e1c457ef8539a8c672ac","ts":1504006460,"wall":"2017-08-29T19:34","msg":"Update style.css","body":"Class and pseudo-class of the specificity of 10,\nElements and pseudo-elements of the specificity of 1","parents":["2a458754b6cadde829de8f9dd6f8825277c9ed23"],"add":3,"del":3,"cadd":3,"cdel":3,"files":1},{"repo":"learning-area","hash":"a93d92b6bc77f0ce53956ce5e03ed9e6556dd29a","ts":1504007857,"wall":"2017-08-29T12:57","msg":"Merge pull request #35 from fh408931/master","body":"Update style.css","parents":["b456d4e7532777e0e89543637ab0e0b8cc79382a","a857aad04bcdb45606a6e1c457ef8539a8c672ac"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"856ec92136af266b5f132619129d891b9be09900","ts":1504203208,"wall":"2017-08-31T19:13","msg":"adding/fixing selenium examples, and removing unnecessary declaration in HTML multimedia example","body":"","parents":["a93d92b6bc77f0ce53956ce5e03ed9e6556dd29a"],"add":86,"del":20,"cadd":86,"cdel":20,"files":7},{"repo":"learning-area","hash":"5b1ff5626149246c4d5d8468307611d89367f876","ts":1504541659,"wall":"2017-09-04T17:14","msg":"adding month type example","body":"","parents":["856ec92136af266b5f132619129d891b9be09900"],"add":46,"del":0,"cadd":46,"cdel":0,"files":1},{"repo":"learning-area","hash":"459f7655d75c3d7adf3ab423fe338dcd65106be9","ts":1504603187,"wall":"2017-09-05T10:19","msg":"adding input time example","body":"","parents":["5b1ff5626149246c4d5d8468307611d89367f876"],"add":46,"del":0,"cadd":46,"cdel":0,"files":1},{"repo":"learning-area","hash":"f5762681ab1a463a92471c42144b7e2c7d1bce75","ts":1504615662,"wall":"2017-09-05T13:47","msg":"adding week example","body":"","parents":["459f7655d75c3d7adf3ab423fe338dcd65106be9"],"add":48,"del":0,"cadd":48,"cdel":0,"files":1},{"repo":"learning-area","hash":"67dbe527b7f3b37a38429d5ff100a880b8fc376e","ts":1505833390,"wall":"2017-09-19T16:03","msg":"adding input type tel example","body":"","parents":["f5762681ab1a463a92471c42144b7e2c7d1bce75"],"add":48,"del":1,"cadd":48,"cdel":1,"files":2},{"repo":"learning-area","hash":"4c2058e7357117be973f7ee948262c79704a1e4c","ts":1505833626,"wall":"2017-09-19T16:07","msg":"adding input type tel example","body":"","parents":["67dbe527b7f3b37a38429d5ff100a880b8fc376e"],"add":0,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"be69b2494bb5e187dc9d1153d7c882e5a46dd47c","ts":1505912979,"wall":"2017-09-20T14:09","msg":"adding better input tel example","body":"","parents":["4c2058e7357117be973f7ee948262c79704a1e4c"],"add":72,"del":4,"cadd":72,"cdel":4,"files":1},{"repo":"learning-area","hash":"7d8bd4beae12ad725fe71d938127ea249e153b2a","ts":1505924563,"wall":"2017-09-20T17:22","msg":"adding url input type example","body":"","parents":["be69b2494bb5e187dc9d1153d7c882e5a46dd47c"],"add":47,"del":0,"cadd":47,"cdel":0,"files":1},{"repo":"learning-area","hash":"95d974714dbde1fd75bdaff7c0342572a5fc6b1d","ts":1505934094,"wall":"2017-09-20T20:01","msg":"improving URL example","body":"","parents":["7d8bd4beae12ad725fe71d938127ea249e153b2a"],"add":10,"del":2,"cadd":10,"cdel":2,"files":1},{"repo":"learning-area","hash":"0951d11af74324370ba13fd224f9c19610870b6a","ts":1506498004,"wall":"2017-09-27T13:10","msg":"Update: 'type' attribute removed","body":"","parents":["95d974714dbde1fd75bdaff7c0342572a5fc6b1d"],"add":3,"del":2,"cadd":3,"cdel":2,"files":1},{"repo":"learning-area","hash":"e270858e7c65cbeefd264607f3923728f60bd951","ts":1506499911,"wall":"2017-09-27T13:41","msg":"<header> element to be used instead of <heading>","body":"","parents":["95d974714dbde1fd75bdaff7c0342572a5fc6b1d"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"73ec3ad2388bdb5f33ca53acd11ddd1ed92f5381","ts":1506506402,"wall":"2017-09-27T11:00","msg":"Merge pull request #43 from vkWeb/patch-2","body":"<header> element to be used instead of <heading>","parents":["95d974714dbde1fd75bdaff7c0342572a5fc6b1d","e270858e7c65cbeefd264607f3923728f60bd951"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"a9a983f84bbe3133d2e99ee1f23222d10e9db578","ts":1506508639,"wall":"2017-09-27T11:37","msg":"addig new form examples","body":"","parents":["73ec3ad2388bdb5f33ca53acd11ddd1ed92f5381"],"add":1932,"del":0,"cadd":1927,"cdel":0,"files":18},{"repo":"learning-area","hash":"1de3385d8c1f1838ee30edd9cc7915ec3127326b","ts":1506508673,"wall":"2017-09-27T11:37","msg":"adding new form examples","body":"","parents":["a9a983f84bbe3133d2e99ee1f23222d10e9db578"],"add":0,"del":1658,"cadd":0,"cdel":1653,"files":9},{"repo":"learning-area","hash":"5c0cdb7b528cd4ce6b09adef619e07bc3bb31293","ts":1506524816,"wall":"2017-09-27T16:06","msg":"Merge pull request #42 from vkWeb/patch-1","body":"Update: 'type' attribute removed","parents":["1de3385d8c1f1838ee30edd9cc7915ec3127326b","0951d11af74324370ba13fd224f9c19610870b6a"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"4d25e4d4d6ff8712d13a0db8aa341fe94a2c4dce","ts":1506525016,"wall":"2017-09-27T16:10","msg":"updating google fonts line in finished example directory, and in the assets.zip file","body":"","parents":["5c0cdb7b528cd4ce6b09adef619e07bc3bb31293"],"add":5,"del":12,"cadd":5,"cdel":12,"files":6},{"repo":"learning-area","hash":"79b1eecd95d9246c362f6f56425939243434b87e","ts":1506930291,"wall":"2017-10-02T08:44","msg":"add automation examples, ad update README","body":"","parents":["4d25e4d4d6ff8712d13a0db8aa341fe94a2c4dce"],"add":59,"del":1,"cadd":59,"cdel":1,"files":3},{"repo":"learning-area","hash":"aac7025dd582f047d3e6f5b6349f5058f4b6ebf9","ts":1507102149,"wall":"2017-10-04T08:29","msg":"fixing formatting on typesetting assessment","body":"","parents":["79b1eecd95d9246c362f6f56425939243434b87e"],"add":8,"del":7,"cadd":8,"cdel":7,"files":1},{"repo":"learning-area","hash":"a5fce60fb492ed1cd3162145abe775887d571a26","ts":1508317080,"wall":"2017-10-18T16:58","msg":"Update can-script.js","body":"The first time after all the search is not satisfied, querySelector ('p') to find the element is the footer under the p element, added to the main element below, the second time after all search, p element has been removed , The page does not have a p element, and document.querySelector ('p') returns null","parents":["aac7025dd582f047d3e6f5b6349f5058f4b6ebf9"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"a342628a9d2bb5534ec9ce467385fcdcad922032","ts":1508321528,"wall":"2017-10-18T12:12","msg":"Merge pull request #46 from fh408931/master","body":"Update can-script.js","parents":["aac7025dd582f047d3e6f5b6349f5058f4b6ebf9","a5fce60fb492ed1cd3162145abe775887d571a26"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"cfeaa25eab51bc4a97bf601c31822dbcd782c7f3","ts":1508321779,"wall":"2017-10-18T11:16","msg":"updating xhr can script and fetch version can-store zip file","body":"","parents":["a342628a9d2bb5534ec9ce467385fcdcad922032"],"add":1,"del":1,"cadd":1,"cdel":1,"files":2},{"repo":"learning-area","hash":"d56b7f461eda28e1dae39a1c04ba46ea95e57141","ts":1510994315,"wall":"2017-11-18T16:38","msg":"Fix a minor bug.","body":"A closing parenthesis has lost.","parents":["cfeaa25eab51bc4a97bf601c31822dbcd782c7f3"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"37d7ed3e12657dd3745ab8bd7a0786af56737d26","ts":1511158083,"wall":"2017-11-20T06:08","msg":"Merge pull request #47 from vilscrolls/patch-1","body":"Fix a minor bug.","parents":["cfeaa25eab51bc4a97bf601c31822dbcd782c7f3","d56b7f461eda28e1dae39a1c04ba46ea95e57141"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"3f8d1498ba89f9da114ae1876196dc18ce868bc4","ts":1512045037,"wall":"2017-11-30T12:30","msg":"various small fixes","body":"","parents":["37d7ed3e12657dd3745ab8bd7a0786af56737d26"],"add":8,"del":8,"cadd":8,"cdel":8,"files":4},{"repo":"deck-of-cards","hash":"26eb94bac32fb32b03f9412e5db01ff6ff08ecc6","ts":1513092724,"wall":"2017-12-12T17:32","msg":"Hide ads with shortcut","body":"","parents":["cb692e866f55b6881ac39efb6329f5e49101a92e"],"add":11,"del":0,"cadd":11,"cdel":0,"files":1},{"repo":"learning-area","hash":"cb9e63f676b8c29b055cb3fe132ae265cc417851","ts":1513877023,"wall":"2017-12-21T12:23","msg":"Update other-examples.html","body":"","parents":["3f8d1498ba89f9da114ae1876196dc18ce868bc4"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"55cb35a5f62019f71256c841248067b2168edd8c","ts":1513947642,"wall":"2017-12-22T13:00","msg":"Merge pull request #49 from jenniferlrx/patch-1","body":"Update other-examples.html","parents":["3f8d1498ba89f9da114ae1876196dc18ce868bc4","cb9e63f676b8c29b055cb3fe132ae265cc417851"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"369c45623c6b7c1def757640a4509a9d69dfe046","ts":1514152175,"wall":"2017-12-25T08:49","msg":"Update style.css","body":"Strictly speaking if the html had an h2 + p unbound by a section it would still be indented. This is more to adjust for the spec.","parents":["55cb35a5f62019f71256c841248067b2168edd8c"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"3d9f757970dbfc4bf358a6760495ebd93424bb83","ts":1514902197,"wall":"2018-01-02T14:09","msg":"Merge pull request #50 from DarkPurple141/patch-1","body":"Update style.css","parents":["55cb35a5f62019f71256c841248067b2168edd8c","369c45623c6b7c1def757640a4509a9d69dfe046"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"c1989e710a74e65a6dde330d9267de17df78474b","ts":1515447087,"wall":"2018-01-08T21:31","msg":"adding web storage demos for client-side storage APIs tutorial","body":"","parents":["3d9f757970dbfc4bf358a6760495ebd93424bb83"],"add":140,"del":0,"cadd":140,"cdel":0,"files":3},{"repo":"learning-area","hash":"182136dc099bd9c94325e63b2adfb12575be9b7c","ts":1515447835,"wall":"2018-01-08T21:43","msg":"adding web storage demos for client-side storage APIs tutorial","body":"","parents":["c1989e710a74e65a6dde330d9267de17df78474b"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"learning-area","hash":"f30b62ea89c8edc4d4823501dddd1d6c0256b840","ts":1515690836,"wall":"2018-01-11T17:13","msg":"adding indexeddb example","body":"","parents":["182136dc099bd9c94325e63b2adfb12575be9b7c"],"add":260,"del":0,"cadd":260,"cdel":0,"files":4},{"repo":"learning-area","hash":"392ad8929e314b6ff947c05a8c4c163c6a8a040e","ts":1516021772,"wall":"2018-01-15T13:09","msg":"adding initial attempt at video storage IDB example","body":"","parents":["f30b62ea89c8edc4d4823501dddd1d6c0256b840"],"add":212,"del":0,"cadd":212,"cdel":0,"files":15},{"repo":"learning-area","hash":"ba66db0c4676df24fc1fc31809ce479558e47c23","ts":1516022442,"wall":"2018-01-15T13:20","msg":"simplifying code, trying to make the database writes work","body":"","parents":["392ad8929e314b6ff947c05a8c4c163c6a8a040e"],"add":18,"del":43,"cadd":18,"cdel":43,"files":1},{"repo":"learning-area","hash":"b7471a3538c73a0c7dcb9fde393f7b2f0e937fed","ts":1516022941,"wall":"2018-01-15T13:29","msg":"simplifying code, trying to make the database writes work","body":"","parents":["ba66db0c4676df24fc1fc31809ce479558e47c23"],"add":20,"del":17,"cadd":20,"cdel":17,"files":1},{"repo":"learning-area","hash":"384cd14ee6f90ab861f1c85f85bc2e460f0017cc","ts":1516023082,"wall":"2018-01-15T13:31","msg":"simplifying code, trying to make the database writes work","body":"","parents":["b7471a3538c73a0c7dcb9fde393f7b2f0e937fed"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"40a526923e898228d0263fe6c0ec0dbb0be22d65","ts":1516023229,"wall":"2018-01-15T13:33","msg":"simplifying code, trying to make the database writes work","body":"","parents":["384cd14ee6f90ab861f1c85f85bc2e460f0017cc"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"1c31f030fb4ce20e8b7ba0b45c363a298b0f9e31","ts":1516024081,"wall":"2018-01-15T13:48","msg":"adding final fix to idb videos example - making sure object urls are being proper constructed","body":"","parents":["40a526923e898228d0263fe6c0ec0dbb0be22d65"],"add":9,"del":7,"cadd":9,"cdel":7,"files":1},{"repo":"learning-area","hash":"54d8eef17c0622a440e9bad0042a8f8601f1707f","ts":1516024455,"wall":"2018-01-15T13:54","msg":"make sure the code is prperly commented","body":"","parents":["1c31f030fb4ce20e8b7ba0b45c363a298b0f9e31"],"add":14,"del":4,"cadd":14,"cdel":4,"files":1},{"repo":"learning-area","hash":"ba404e5a22a908ff94738c6d7a31cb14d02b1408","ts":1516047444,"wall":"2018-01-15T20:17","msg":"adding cache and service worker example","body":"","parents":["54d8eef17c0622a440e9bad0042a8f8601f1707f"],"add":463,"del":37,"cadd":463,"cdel":37,"files":20},{"repo":"learning-area","hash":"112c6da6cd9629328cbf1e32c956148251f6093b","ts":1516047652,"wall":"2018-01-15T20:20","msg":"adding cache and service worker example","body":"","parents":["ba404e5a22a908ff94738c6d7a31cb14d02b1408"],"add":8,"del":9,"cadd":8,"cdel":9,"files":2},{"repo":"learning-area","hash":"2fd6590f49c01067240609718dc37cb2f3042718","ts":1516048944,"wall":"2018-01-15T20:42","msg":"adding cache and service worker example","body":"","parents":["112c6da6cd9629328cbf1e32c956148251f6093b"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"e76c923e425c8e67facefbefd69234f02a4b5432","ts":1516049122,"wall":"2018-01-15T20:45","msg":"adding cache and service worker example","body":"","parents":["2fd6590f49c01067240609718dc37cb2f3042718"],"add":1,"del":1,"cadd":1,"cdel":1,"files":2},{"repo":"learning-area","hash":"c235d8198ff6874f6271739611a0f32743512a87","ts":1516049815,"wall":"2018-01-15T20:56","msg":"fixing up snafu - editing wrong version of code! Old code now deleted, and new code editing correctly","body":"","parents":["e76c923e425c8e67facefbefd69234f02a4b5432"],"add":1,"del":195,"cadd":1,"cdel":195,"files":5},{"repo":"learning-area","hash":"b592f9276dd9085bcf1c8911d15dea0a5ad6e17d","ts":1516049936,"wall":"2018-01-15T20:58","msg":"fixing incorrect sw register path","body":"","parents":["c235d8198ff6874f6271739611a0f32743512a87"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"fe6129f8c2278320a650314f6f7636e94e0cc541","ts":1516050193,"wall":"2018-01-15T21:03","msg":"trying to get rid of waitUntil \"bad status 404 error\"","body":"","parents":["b592f9276dd9085bcf1c8911d15dea0a5ad6e17d"],"add":0,"del":1,"cadd":0,"cdel":1,"files":1},{"repo":"learning-area","hash":"080709742a7445baf88f7330ab9281aa48c1570c","ts":1516050296,"wall":"2018-01-15T21:04","msg":"trying paths relative to site root, to see if this fixes the problem","body":"","parents":["fe6129f8c2278320a650314f6f7636e94e0cc541"],"add":4,"del":3,"cadd":4,"cdel":3,"files":1},{"repo":"learning-area","hash":"21f8d6076bd44ffb8d0a3f7191f31499439ded15","ts":1517358502,"wall":"2018-01-30T18:28","msg":"Updated Article titles","body":"","parents":["080709742a7445baf88f7330ab9281aa48c1570c"],"add":10,"del":10,"cadd":10,"cdel":10,"files":1},{"repo":"learning-area","hash":"b981d6a2ae112c69a3f4f83d2e095cb573f1c529","ts":1517387177,"wall":"2018-01-31T08:26","msg":"Merge pull request #52 from ColemanTO/patch-1","body":"Updated Article titles","parents":["080709742a7445baf88f7330ab9281aa48c1570c","21f8d6076bd44ffb8d0a3f7191f31499439ded15"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"fb60ed9da24544cf481ed5d5b055dd682afb440e","ts":1517474579,"wall":"2018-02-01T08:42","msg":"updating OOJS examples to make them less confusing, and making small update to flexbox wrap example","body":"","parents":["b981d6a2ae112c69a3f4f83d2e095cb573f1c529"],"add":22,"del":80,"cadd":22,"cdel":80,"files":5},{"repo":"learning-area","hash":"acb7ad1787bf03de66865ae21454a7eb4fc9c307","ts":1517993736,"wall":"2018-02-07T08:55","msg":"updating positioning sliding panel example so it makes more sense - thanks jruota!","body":"","parents":["fb60ed9da24544cf481ed5d5b055dd682afb440e"],"add":5,"del":5,"cadd":5,"cdel":5,"files":1},{"repo":"learning-area","hash":"cb1146858df4ee937a261f3cf331ec9a9fcd0feb","ts":1518008215,"wall":"2018-02-07T12:56","msg":"updating editable canvas active learning editable sample to behave the same as the other new ones","body":"","parents":["acb7ad1787bf03de66865ae21454a7eb4fc9c307"],"add":53,"del":1,"cadd":53,"cdel":1,"files":1},{"repo":"learning-area","hash":"cfc3b99bdf092491efe8bf59769247672a819806","ts":1518686962,"wall":"2018-02-15T14:59","msg":"correct the spelling","body":"","parents":["cb1146858df4ee937a261f3cf331ec9a9fcd0feb"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"92a78963cd4a0a2efca52ee27ee3ab7e699302bb","ts":1518687411,"wall":"2018-02-15T09:36","msg":"Merge pull request #54 from bshankar/patch-1","body":"correct the spelling of temperatures","parents":["cb1146858df4ee937a261f3cf331ec9a9fcd0feb","cfc3b99bdf092491efe8bf59769247672a819806"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"0677af5ecd0b0124769af8ce81183f6386caebad","ts":1518687634,"wall":"2018-02-15T09:40","msg":"fixing spelling mistake","body":"","parents":["92a78963cd4a0a2efca52ee27ee3ab7e699302bb"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"729346956340bbd38a063544ba6c18d60b2e307f","ts":1519025406,"wall":"2018-02-19T07:30","msg":"updating marking up a letter assessment - making improvements suggested by bripmccann","body":"","parents":["0677af5ecd0b0124769af8ce81183f6386caebad"],"add":10,"del":10,"cadd":8,"cdel":8,"files":4},{"repo":"learning-area","hash":"91510abfbad9177217af238ffd0fd5d32b58ed52","ts":1519099704,"wall":"2018-02-19T23:08","msg":"Fixing number-guessing-game-start.html indentation","body":"","parents":["729346956340bbd38a063544ba6c18d60b2e307f"],"add":15,"del":15,"cadd":15,"cdel":15,"files":1},{"repo":"learning-area","hash":"6236dc8de10e30ca9857b99f4488247fc3d1db43","ts":1519100098,"wall":"2018-02-19T23:14","msg":"Formatting number-guessing-game.html","body":"Fixing indentation and placing <script> inside <body>, matching number-guessing-game-start.html.","parents":["91510abfbad9177217af238ffd0fd5d32b58ed52"],"add":87,"del":90,"cadd":87,"cdel":90,"files":1},{"repo":"learning-area","hash":"0893ab33fb0ec6c2636d71d2899b9fac1c57f4ca","ts":1519113067,"wall":"2018-02-20T07:51","msg":"Merge pull request #57 from bripmccann/bripmccann-number-guessing-game","body":"number-guessing-game formatting","parents":["729346956340bbd38a063544ba6c18d60b2e307f","6236dc8de10e30ca9857b99f4488247fc3d1db43"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"95d411e13fd46f52cc53ea1815b8abd94707f825","ts":1519163563,"wall":"2018-02-20T16:52","msg":"Updating apply-javascript-external.html","body":"HTML5 doctype, lang=\"en-US\", charset=\"utf-8\"","parents":["729346956340bbd38a063544ba6c18d60b2e307f"],"add":10,"del":9,"cadd":10,"cdel":9,"files":1},{"repo":"learning-area","hash":"bbf01afc655508eb1ce2ce8412e7f1ea2cc2a299","ts":1519163925,"wall":"2018-02-20T16:58","msg":"Update apply-javascript-internal.html","body":"HTML5 doctype, lang=\"en-US\", charset=\"utf-8\"","parents":["95d411e13fd46f52cc53ea1815b8abd94707f825"],"add":20,"del":19,"cadd":20,"cdel":19,"files":1},{"repo":"learning-area","hash":"9dcb05f1f3b1fc603a5480a8cb1da891d7ec3e12","ts":1519163937,"wall":"2018-02-20T16:58","msg":"Update apply-javascript.html","body":"HTML5 doctype, lang=\"en-US\", charset=\"utf-8\"","parents":["bbf01afc655508eb1ce2ce8412e7f1ea2cc2a299"],"add":10,"del":9,"cadd":10,"cdel":9,"files":1},{"repo":"learning-area","hash":"7155927eb40d1f390d1d8a6b3bc6a4abc8085374","ts":1519163963,"wall":"2018-02-20T16:59","msg":"Update javascript-label.html","body":"HTML5 doctype, lang=\"en-US\", charset=\"utf-8\"","parents":["9dcb05f1f3b1fc603a5480a8cb1da891d7ec3e12"],"add":4,"del":3,"cadd":4,"cdel":3,"files":1},{"repo":"learning-area","hash":"ce8f5f3907796e5c4d17c92e30f31fc5998958c9","ts":1519203575,"wall":"2018-02-21T08:59","msg":"Merge pull request #58 from bripmccann/bripmccann-what-is-js","body":"what-is-js html updates","parents":["0893ab33fb0ec6c2636d71d2899b9fac1c57f4ca","7155927eb40d1f390d1d8a6b3bc6a4abc8085374"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"a32b0e1f8c66d8ee9e433d51b4b005163eb7e184","ts":1519253892,"wall":"2018-02-21T16:58","msg":"Remove redundant code","body":"","parents":["ce8f5f3907796e5c4d17c92e30f31fc5998958c9"],"add":2,"del":4,"cadd":2,"cdel":4,"files":2},{"repo":"learning-area","hash":"601f0b5e0c3b59616b315711bdcb7f71c1f2ac3e","ts":1519288231,"wall":"2018-02-22T08:30","msg":"Merge pull request #59 from reddraggone9/client-side-storage-changes","body":"Remove redundant code from client-side storage examples","parents":["ce8f5f3907796e5c4d17c92e30f31fc5998958c9","a32b0e1f8c66d8ee9e433d51b4b005163eb7e184"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"126f91338460201c22af1e561b0ace8002faabad","ts":1519756599,"wall":"2018-02-27T18:36","msg":"Update oojs-finished.html","body":"","parents":["601f0b5e0c3b59616b315711bdcb7f71c1f2ac3e"],"add":14,"del":14,"cadd":14,"cdel":14,"files":1},{"repo":"learning-area","hash":"9daa4bb27f7c00850674a5daa2c1a428da9699d7","ts":1521682689,"wall":"2018-03-21T21:38","msg":"Update main.js","body":"Just a tiny change so that if the value for the customName field is female, there won't be a pronoun issue.","parents":["601f0b5e0c3b59616b315711bdcb7f71c1f2ac3e"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"9c185911b248009c5e6c6749dc224a8560c80840","ts":1521818805,"wall":"2018-03-23T15:26","msg":"Merge pull request #62 from redrambles/redrambles-patch-1","body":"Update main.js","parents":["601f0b5e0c3b59616b315711bdcb7f71c1f2ac3e","9daa4bb27f7c00850674a5daa2c1a428da9699d7"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"f5772d5f95109e149fc736501c6583d0b074811c","ts":1521818978,"wall":"2018-03-23T15:29","msg":"updating start text to avoid pronoun issue too","body":"","parents":["9c185911b248009c5e6c6749dc224a8560c80840"],"add":5,"del":5,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"59c6b8098dee16323739645d5c16a32284d19173","ts":1521927235,"wall":"2018-03-24T15:33","msg":"replace bgtile.png","body":"Original bgtile has an extra 1px border that makes the background not uniform, so I removed it. From 615x615 to 613x613 pixels.","parents":["f5772d5f95109e149fc736501c6583d0b074811c"],"add":0,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"d2bce124d7eaf9384cda6296720b908501efd942","ts":1522038348,"wall":"2018-03-25T22:25","msg":"Fixes a bug that appears after page reloads","body":"","parents":["f5772d5f95109e149fc736501c6583d0b074811c"],"add":2,"del":1,"cadd":2,"cdel":1,"files":1},{"repo":"learning-area","hash":"8ee92bd03205102165234d57c78bb7501f8ee6a8","ts":1522038932,"wall":"2018-03-25T22:35","msg":"Removes trailing/leading whitespaces from the search query","body":"","parents":["d2bce124d7eaf9384cda6296720b908501efd942"],"add":4,"del":4,"cadd":4,"cdel":4,"files":1},{"repo":"learning-area","hash":"22b9be277b39c86db53127c9d421be16b775ab0d","ts":1522042069,"wall":"2018-03-26T06:27","msg":"Merge pull request #65 from 2alin/can-store-patches","body":"can-store patches","parents":["f5772d5f95109e149fc736501c6583d0b074811c","8ee92bd03205102165234d57c78bb7501f8ee6a8"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"73b6dd8db319978b36c9daed7c5b09c8377ecc9e","ts":1522042901,"wall":"2018-03-26T06:41","msg":"updating can-store zip file and XHR version with the same changes made by 2alin","body":"","parents":["22b9be277b39c86db53127c9d421be16b775ab0d"],"add":6,"del":5,"cadd":6,"cdel":5,"files":2},{"repo":"learning-area","hash":"f22c279762a719e18555c130c061c1dd9bc34a7f","ts":1522044031,"wall":"2018-03-26T07:00","msg":"Merge pull request #63 from 2alin/2alin-patch-1","body":"replace bgtile.png","parents":["73b6dd8db319978b36c9daed7c5b09c8377ecc9e","59c6b8098dee16323739645d5c16a32284d19173"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"021c9632e92df0f53a595f181fe647159a229dcf","ts":1522044278,"wall":"2018-03-26T07:04","msg":"removing min-width from splash page example","body":"","parents":["f22c279762a719e18555c130c061c1dd9bc34a7f"],"add":0,"del":2,"cadd":0,"cdel":2,"files":2},{"repo":"learning-area","hash":"a64af9589f8af85800bd14b26feef9540a417464","ts":1522123542,"wall":"2018-03-26T22:05","msg":"Replace current.lead_paragraph with current.snippet","body":"","parents":["021c9632e92df0f53a595f181fe647159a229dcf"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"fa91a2148cc5caa1d73a3959893c4a69bfb68ff9","ts":1522123985,"wall":"2018-03-26T22:13","msg":"Restrict search to document_type:'article'","body":"","parents":["a64af9589f8af85800bd14b26feef9540a417464"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"0a9ca270e7ec9c5b560cbf09aa1b72710235f9a0","ts":1522124301,"wall":"2018-03-26T22:18","msg":"Reset pageNumber every time a new search is made","body":"","parents":["fa91a2148cc5caa1d73a3959893c4a69bfb68ff9"],"add":6,"del":2,"cadd":6,"cdel":2,"files":1},{"repo":"learning-area","hash":"69a00e758f9c04ba6e009b98d11b55c98318b066","ts":1522124426,"wall":"2018-03-26T22:20","msg":"Fix code typo","body":"","parents":["0a9ca270e7ec9c5b560cbf09aa1b72710235f9a0"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"c1a69870b5813193a9a1b654e78e52b8cabda7ca","ts":1522128449,"wall":"2018-03-27T06:27","msg":"Merge pull request #66 from 2alin/nytimes-patches","body":"nytimes patches","parents":["021c9632e92df0f53a595f181fe647159a229dcf","69a00e758f9c04ba6e009b98d11b55c98318b066"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"acfd5807cacaf4a8bb37372125ddaa35ff075b0f","ts":1522741937,"wall":"2018-04-03T08:52","msg":"adding notes to the OOJS examples to make it more obvious what you need to do","body":"","parents":["c1a69870b5813193a9a1b654e78e52b8cabda7ca"],"add":5,"del":1,"cadd":5,"cdel":1,"files":4},{"repo":"learning-area","hash":"389a8241091ede9003bd4978252b42c08a7ccd17","ts":1523365172,"wall":"2018-04-10T08:59","msg":"Update text-start.html (typo - capitalization)","body":"","parents":["acfd5807cacaf4a8bb37372125ddaa35ff075b0f"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"2c59aced8fe0b9d4c1384159e0618825755d04a9","ts":1523365264,"wall":"2018-04-10T09:01","msg":"Update text-start.html","body":"","parents":["389a8241091ede9003bd4978252b42c08a7ccd17"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"ed125811a06ccd02f7805dc9d189aba8a81e0827","ts":1523371921,"wall":"2018-04-10T15:52","msg":"Merge pull request #68 from mbuc/patch-1","body":"Update text-start.html (typo - capitalization)","parents":["acfd5807cacaf4a8bb37372125ddaa35ff075b0f","2c59aced8fe0b9d4c1384159e0618825755d04a9"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"694dbe74b7d4b5706ba95d7098f6b84f8613ded9","ts":1525266142,"wall":"2018-05-02T14:02","msg":"updating OOJS bouncing balls example","body":"","parents":["acfd5807cacaf4a8bb37372125ddaa35ff075b0f"],"add":2,"del":4,"cadd":2,"cdel":4,"files":2},{"repo":"learning-area","hash":"dc06ee8c854fec63e5a8b6b97d84c3c68ac4ce8c","ts":1525266154,"wall":"2018-05-02T14:02","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["694dbe74b7d4b5706ba95d7098f6b84f8613ded9","ed125811a06ccd02f7805dc9d189aba8a81e0827"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"0aa8c8cda2d656a2d7220cfd9f7106fed7cb8ee7","ts":1526152820,"wall":"2018-05-12T13:20","msg":"Fixed spelling error in comments","body":"","parents":["dc06ee8c854fec63e5a8b6b97d84c3c68ac4ce8c"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"a4cb183a6d72c06b13e062d26fd3f82e75f005c9","ts":1526253922,"wall":"2018-05-13T16:25","msg":"Merge pull request #71 from SteviBee/patch-1","body":"Fixed spelling error in comments","parents":["dc06ee8c854fec63e5a8b6b97d84c3c68ac4ce8c","0aa8c8cda2d656a2d7220cfd9f7106fed7cb8ee7"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"5e00e1cb3579e392814ac3f44c5f28f13c431c0d","ts":1526456789,"wall":"2018-05-16T08:46","msg":"correcting mistake in the HTML tables assessment marking guide","body":"","parents":["a4cb183a6d72c06b13e062d26fd3f82e75f005c9"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"7e95fe8c272ec3ab3b6df5d51f6b7cbf83f3c151","ts":1526563438,"wall":"2018-05-17T14:23","msg":"updating ball drawing code  to avoid collisions with edge of canvas","body":"","parents":["5e00e1cb3579e392814ac3f44c5f28f13c431c0d"],"add":12,"del":6,"cadd":12,"cdel":6,"files":2},{"repo":"learning-area","hash":"f4e2d8bce023b261a5714581d81b8ed1e19764ba","ts":1526980169,"wall":"2018-05-22T10:09","msg":"adding small improvement to collision detection function","body":"","parents":["7e95fe8c272ec3ab3b6df5d51f6b7cbf83f3c151"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"6653b5009a58dcca10912dc151512cd94ef62ea5","ts":1527021007,"wall":"2018-05-22T23:30","msg":"Update carbonads script","body":"","parents":["26eb94bac32fb32b03f9412e5db01ff6ff08ecc6"],"add":1,"del":2,"cadd":1,"cdel":2,"files":1},{"repo":"learning-area","hash":"8c139fb104abac9060fc4b580ae841d2b6da96f9","ts":1528775082,"wall":"2018-06-12T09:14","msg":"Fixed spelling error","body":"","parents":["f4e2d8bce023b261a5714581d81b8ed1e19764ba"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"a22a3c66419c3dc39996034aa94813986f81039d","ts":1528800433,"wall":"2018-06-12T11:47","msg":"new files for the learning area CSS. Floats, Grid, Multicol","body":"","parents":["f4e2d8bce023b261a5714581d81b8ed1e19764ba"],"add":1161,"del":0,"cadd":1160,"cdel":0,"files":25},{"repo":"learning-area","hash":"8bbc2ddf49e9075a59f5e81a1ca39ce640a26b9f","ts":1529030155,"wall":"2018-06-14T21:35","msg":"Missing parenthesis at the end of sentence","body":"","parents":["a22a3c66419c3dc39996034aa94813986f81039d"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"05afe81e9771db47c2d0b843610ee8c4f68cc3b1","ts":1529080631,"wall":"2018-06-15T09:37","msg":"Merge pull request #75 from jzunigacoayla/master","body":"Missing parenthesis at the end of sentence","parents":["a22a3c66419c3dc39996034aa94813986f81039d","8bbc2ddf49e9075a59f5e81a1ca39ce640a26b9f"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"627374ffa40bfb20f0be502842ce241c56fa9463","ts":1529480609,"wall":"2018-06-20T08:43","msg":"updating examples to use modern loading strategies","body":"","parents":["05afe81e9771db47c2d0b843610ee8c4f68cc3b1"],"add":15,"del":15,"cadd":15,"cdel":15,"files":2},{"repo":"learning-area","hash":"24488283a48447cef0ad622e4ff1566d8aedc6aa","ts":1530019168,"wall":"2018-06-26T14:19","msg":"adding complex select example","body":"","parents":["627374ffa40bfb20f0be502842ce241c56fa9463"],"add":27,"del":0,"cadd":27,"cdel":0,"files":1},{"repo":"learning-area","hash":"f4599ab604ddac8cfcd8b1922e52925d126f4f19","ts":1530345542,"wall":"2018-06-30T08:59","msg":"sticky example","body":"","parents":["24488283a48447cef0ad622e4ff1566d8aedc6aa"],"add":164,"del":73,"cadd":164,"cdel":73,"files":4},{"repo":"learning-area","hash":"980d44b45706c28801d334359aba93d511794aba","ts":1530497694,"wall":"2018-07-02T12:14","msg":"layout task","body":"","parents":["f4599ab604ddac8cfcd8b1922e52925d126f4f19"],"add":142,"del":0,"cadd":142,"cdel":0,"files":8},{"repo":"learning-area","hash":"968b8696251eafe8e7b26eba92f11d988bfc8d28","ts":1530552079,"wall":"2018-07-02T12:21","msg":"Stray end tag for div element","body":"","parents":["980d44b45706c28801d334359aba93d511794aba"],"add":7,"del":14,"cadd":7,"cdel":14,"files":7},{"repo":"learning-area","hash":"aa63a81d3b6af299c5d752ada2dcc310654809df","ts":1530562551,"wall":"2018-07-03T06:15","msg":"Merge pull request #78 from jzunigacoayla/master","body":"Stray end tag for div element","parents":["980d44b45706c28801d334359aba93d511794aba","968b8696251eafe8e7b26eba92f11d988bfc8d28"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"d535ebf50a41542f2ec8389fe34d47114620aa70","ts":1530949609,"wall":"2018-07-07T17:46","msg":"marking guide for layout task","body":"","parents":["aa63a81d3b6af299c5d752ada2dcc310654809df"],"add":182,"del":1,"cadd":182,"cdel":1,"files":10},{"repo":"learning-area","hash":"c9d4e978f7194e86e635ee97f43434c174ff64a9","ts":1530949900,"wall":"2018-07-07T17:51","msg":"fixing some markdown","body":"","parents":["d535ebf50a41542f2ec8389fe34d47114620aa70"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"6c629ce42e612bc80f96a4d1a18e6e9e767682dd","ts":1531997988,"wall":"2018-07-19T11:59","msg":"adding new ES2015 inheritiance examples to repo","body":"","parents":["c9d4e978f7194e86e635ee97f43434c174ff64a9"],"add":135,"del":0,"cadd":135,"cdel":0,"files":2},{"repo":"learning-area","hash":"0168d9dc0ce3e004d3c62889a2f55c71e10878ec","ts":1532499943,"wall":"2018-07-25T11:55","msg":"Reference correct video source video file","body":"","parents":["6c629ce42e612bc80f96a4d1a18e6e9e767682dd"],"add":2,"del":2,"cadd":2,"cdel":2,"files":2},{"repo":"learning-area","hash":"de9797d0981860615c9a07450e14e14081680aac","ts":1532507049,"wall":"2018-07-25T09:24","msg":"Merge pull request #84 from rohit/master","body":"Reference correct video source video file","parents":["6c629ce42e612bc80f96a4d1a18e6e9e767682dd","0168d9dc0ce3e004d3c62889a2f55c71e10878ec"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"c01aa1c7dca2e680bf4291d2605827133af88563","ts":1532516628,"wall":"2018-07-25T12:03","msg":"adding sample version of finished guilpfile.js","body":"","parents":["de9797d0981860615c9a07450e14e14081680aac"],"add":35,"del":0,"cadd":35,"cdel":0,"files":1},{"repo":"learning-area","hash":"4beb064eb83162e06d8051a005b8208a1f56b245","ts":1532637994,"wall":"2018-07-26T23:46","msg":"fixed \"farenheit\" typo","body":"","parents":["c01aa1c7dca2e680bf4291d2605827133af88563"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"8190666697a7aabf8f0635df8fe8919ed8caacfe","ts":1532681092,"wall":"2018-07-27T09:44","msg":"Merge pull request #85 from arda152/patch-1","body":"fixed \"farenheit\" typo","parents":["c01aa1c7dca2e680bf4291d2605827133af88563","4beb064eb83162e06d8051a005b8208a1f56b245"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"d402d868f6b4391e74b6193c06c5fd6caa77da17","ts":1532813854,"wall":"2018-07-28T22:37","msg":"fixing comparison operator in 3. EVENT LISTENER...","body":"replacing != with the correct !== comparison operator inside if statement in\n3. EVENT LISTENER AND PARTIAL FUNCTION DEFINITION","parents":["8190666697a7aabf8f0635df8fe8919ed8caacfe"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"2e847e45428d3fad8c8ba18465ab63d28204936a","ts":1533048236,"wall":"2018-07-31T07:43","msg":"tweaking and fixing getters setters example","body":"","parents":["8190666697a7aabf8f0635df8fe8919ed8caacfe"],"add":3,"del":3,"cadd":3,"cdel":3,"files":1},{"repo":"learning-area","hash":"fe8c6aee87f3ea06955e33017ee68461401c92d4","ts":1533050333,"wall":"2018-07-31T16:18","msg":"Merge pull request #86 from aka-yuki/patch-1","body":"fixing comparison operator in 3. EVENT LISTENER...","parents":["2e847e45428d3fad8c8ba18465ab63d28204936a","d402d868f6b4391e74b6193c06c5fd6caa77da17"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"4c86baed175434b2bdad153bacee137c5f799bb4","ts":1533793980,"wall":"2018-08-09T06:53","msg":"Merge pull request #74 from utkarshnag/patch-1","body":"Fixed spelling error","parents":["fe8c6aee87f3ea06955e33017ee68461401c92d4","8c139fb104abac9060fc4b580ae841d2b6da96f9"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"778ee12a51335794df96f73c1e0a6c4f764a1ba9","ts":1535208649,"wall":"2018-08-25T22:50","msg":"My question","body":"I am confused, please compare the contents of these two URLs.\n10 lines ：It was 94 fahrenheit \nhttps://github.com/mdn/learning-area/edit/master/javascript/introduction-to-js-1/assessment-start/raw-text.txt\n13 lines：It was 94 farenheit\nThese two are different,I am using the Chinese tutorial at MDN\n将 '94 farenheit' 置换成为变量 temperature 的值\nAccording to the prompt I copied '94 farenheit',then an error occurred, I spent an hour finding out the problem.\nThis may cause problems for other learners.","parents":["4c86baed175434b2bdad153bacee137c5f799bb4"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"11e52b4381a002564670c98c3987e049df3a9559","ts":1535283774,"wall":"2018-08-26T12:42","msg":"Merge pull request #91 from LittleMang/patch-1","body":"My question","parents":["4c86baed175434b2bdad153bacee137c5f799bb4","778ee12a51335794df96f73c1e0a6c4f764a1ba9"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"7def729f409718c81ea30d5c5cb944051c52dce0","ts":1536645675,"wall":"2018-09-11T08:01","msg":"typo: fallback content wrong filename","body":"","parents":["f8177739803b59098f1ff490d62cf42c40944bfa"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"38178b71364cd1d89517b4989ae333036618c18c","ts":1536658806,"wall":"2018-09-11T10:40","msg":"Merge pull request #94 from torzsmokus/patch-1","body":"typo: fallback content wrong filename","parents":["f8177739803b59098f1ff490d62cf42c40944bfa","7def729f409718c81ea30d5c5cb944051c52dce0"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"873722dbb9022838843dd7199313aa91a108cd2b","ts":1537116747,"wall":"2018-09-17T00:52","msg":"Remove unused variable","body":"","parents":["11e52b4381a002564670c98c3987e049df3a9559"],"add":1,"del":2,"cadd":1,"cdel":2,"files":1},{"repo":"learning-area","hash":"1a2b9eb2eb84dd9a25435981392a5c9872976eff","ts":1537259499,"wall":"2018-09-18T09:31","msg":"Merge pull request #95 from xuchunyang/patch-1","body":"Remove unused variable","parents":["11e52b4381a002564670c98c3987e049df3a9559","873722dbb9022838843dd7199313aa91a108cd2b"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"80a775db207e58e51122d344910515f9b797c96c","ts":1537295207,"wall":"2018-09-19T02:26","msg":"Fix undefined variable","body":"","parents":["1a2b9eb2eb84dd9a25435981392a5c9872976eff"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"e977f44b9209d6860ab32f87705eafbff6b2d69c","ts":1537345612,"wall":"2018-09-19T09:26","msg":"Merge pull request #96 from xuchunyang/patch-1","body":"Fix undefined variable","parents":["1a2b9eb2eb84dd9a25435981392a5c9872976eff","80a775db207e58e51122d344910515f9b797c96c"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"da4f13e1da76a52025599ccb38773fa8bf65221a","ts":1537346019,"wall":"2018-09-19T09:33","msg":"fixing undefined variables and adding ES class version of OOJS assessment","body":"","parents":["e977f44b9209d6860ab32f87705eafbff6b2d69c"],"add":251,"del":1,"cadd":251,"cdel":1,"files":5},{"repo":"learning-area","hash":"e57a7fef386c07ad1428cb8a04ce3b40f6b9c509","ts":1537347537,"wall":"2018-09-19T09:58","msg":"fix error in silly story generator finished version","body":"","parents":["da4f13e1da76a52025599ccb38773fa8bf65221a"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"5bc75c7f4f6221db6cf7b389da17663d83372e6c","ts":1537477988,"wall":"2018-09-20T22:13","msg":"ranaming incorrectly named zip file","body":"","parents":["e57a7fef386c07ad1428cb8a04ce3b40f6b9c509"],"add":0,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"776deace7ee2aaef264e50989594c3cd892eb49c","ts":1537967995,"wall":"2018-09-26T14:19","msg":"updating link to html5shiv with up to date one that does not 404","body":"","parents":["5bc75c7f4f6221db6cf7b389da17663d83372e6c"],"add":52,"del":44,"cadd":52,"cdel":44,"files":21},{"repo":"learning-area","hash":"969306f85b1ac87e983ae364bde7d1d657911519","ts":1538143086,"wall":"2018-09-28T09:58","msg":"Changed reference to female chickens from cock to hen.","body":"","parents":["776deace7ee2aaef264e50989594c3cd892eb49c"],"add":2,"del":2,"cadd":2,"cdel":2,"files":2},{"repo":"learning-area","hash":"9ae4a15b97f9723ea3238e09b6b92f7ab3675b40","ts":1538143602,"wall":"2018-09-28T15:06","msg":"Merge pull request #99 from irenesmith/fixAnimals","body":"Changed reference to female chickens from cock to hen.","parents":["776deace7ee2aaef264e50989594c3cd892eb49c","969306f85b1ac87e983ae364bde7d1d657911519"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"d7624452ec00d9c33daa6593d3ee4864892e85b3","ts":1538474592,"wall":"2018-10-02T11:03","msg":"removing entity reference parts from first html assessment, as they are not really need any more","body":"","parents":["776deace7ee2aaef264e50989594c3cd892eb49c"],"add":8,"del":15,"cadd":2,"cdel":10,"files":3},{"repo":"learning-area","hash":"be5d6a3b3b72b0c679eb1e78d89a6d51c3504392","ts":1538474607,"wall":"2018-10-02T11:03","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["d7624452ec00d9c33daa6593d3ee4864892e85b3","9ae4a15b97f9723ea3238e09b6b92f7ab3675b40"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"836e613270b556baeebd58c7d3afd4823b59c5ed","ts":1538686098,"wall":"2018-10-04T16:48","msg":"Update 'var' to 'let'","body":"","parents":["be5d6a3b3b72b0c679eb1e78d89a6d51c3504392"],"add":5,"del":5,"cadd":5,"cdel":5,"files":1},{"repo":"learning-area","hash":"6481cd77b17bb4d1aade8b210888d89d2ae625b9","ts":1538686321,"wall":"2018-10-04T16:52","msg":"Update 'var' to 'let'","body":"","parents":["be5d6a3b3b72b0c679eb1e78d89a6d51c3504392"],"add":4,"del":4,"cadd":4,"cdel":4,"files":1},{"repo":"learning-area","hash":"54b744f6daadf8bb3e90cec7c570a34320fbd705","ts":1538735696,"wall":"2018-10-05T11:34","msg":"updating structuring assessment to work equally well for use of both section and article element","body":"","parents":["be5d6a3b3b72b0c679eb1e78d89a6d51c3504392"],"add":2,"del":2,"cadd":2,"cdel":2,"files":3},{"repo":"learning-area","hash":"70af19c20fee21e0f515caddaa27758f8978f6d1","ts":1538990520,"wall":"2018-10-08T10:22","msg":"changing console example to use let not var","body":"","parents":["54b744f6daadf8bb3e90cec7c570a34320fbd705"],"add":9,"del":8,"cadd":9,"cdel":8,"files":1},{"repo":"learning-area","hash":"bac2be25cafb82197432a153f8900556fac581a0","ts":1538991053,"wall":"2018-10-08T10:30","msg":"Merge pull request #106 from li3097/patch-6","body":"Update 'var' to 'let'","parents":["70af19c20fee21e0f515caddaa27758f8978f6d1","6481cd77b17bb4d1aade8b210888d89d2ae625b9"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"09c06f65d388dc7e1d98d3ff36673950d46b68a9","ts":1538992532,"wall":"2018-10-08T10:55","msg":"updated loops article to use let and const","body":"","parents":["bac2be25cafb82197432a153f8900556fac581a0"],"add":84,"del":84,"cadd":84,"cdel":84,"files":9},{"repo":"learning-area","hash":"9c066e94c08dfb9cd040553c3838794e87bb0a41","ts":1540197089,"wall":"2018-10-22T09:31","msg":"changing what is JS article examples to use let and const","body":"","parents":["09c06f65d388dc7e1d98d3ff36673950d46b68a9"],"add":9,"del":9,"cadd":9,"cdel":9,"files":3},{"repo":"learning-area","hash":"08cd1206eb972b95f44d808d93603c8bcb0e99c4","ts":1540911669,"wall":"2018-10-30T15:01","msg":"updating a JS article touse let and const, and adding some missing source data to the HTML tables assessment","body":"","parents":["9c066e94c08dfb9cd040553c3838794e87bb0a41"],"add":17,"del":28,"cadd":16,"cdel":27,"files":2},{"repo":"learning-area","hash":"93ee25b727a0875d69725f47751062327230e5bc","ts":1540992844,"wall":"2018-10-31T13:34","msg":"adding Name column to the planets assessment starting text","body":"","parents":["08cd1206eb972b95f44d808d93603c8bcb0e99c4"],"add":1,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"02da53d8a11a58a19781efc6b578b7250c5206ff","ts":1541197696,"wall":"2018-11-02T18:28","msg":"Update complex-flexbox.html","body":"Wrapping behavior of the buttons will now visually match the photograph finished example. \n\nChanged line 58 button's flex value to 1 auto. Equivalent to flex: auto but continues above explicit usage of flex-grow/flex-shrink.","parents":["93ee25b727a0875d69725f47751062327230e5bc"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"a31974ef027ff955bdbdfc0160c46c064cdd04d8","ts":1541429379,"wall":"2018-11-05T14:49","msg":"Merge pull request #108 from stefsulzer/patch-1","body":"Update complex-flexbox.html","parents":["93ee25b727a0875d69725f47751062327230e5bc","02da53d8a11a58a19781efc6b578b7250c5206ff"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"4e35b52ce4f52af52c4cbeaaa5e334a3d5ed2700","ts":1542974208,"wall":"2018-11-23T11:56","msg":"correcting the input types of the example payment form","body":"","parents":["a31974ef027ff955bdbdfc0160c46c064cdd04d8"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"9a1d59132d4e646f2c5eadb0d98cb3b1ec321a88","ts":1543342507,"wall":"2018-11-27T18:15","msg":"adding first set of async examples; impving promise code in client-side apis section","body":"","parents":["4e35b52ce4f52af52c4cbeaaa5e334a3d5ed2700"],"add":201,"del":19,"cadd":201,"cdel":19,"files":9},{"repo":"learning-area","hash":"b7d0b6bc2c88ce14975e9fbbefe330575c1a13ea","ts":1543343242,"wall":"2018-11-27T18:27","msg":"last minute fix","body":"","parents":["9a1d59132d4e646f2c5eadb0d98cb3b1ec321a88"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"97542e85209bc197b457712fc98d7fc224f63c18","ts":1543776412,"wall":"2018-12-03T00:46","msg":"Add html 'lang' attribute","body":"","parents":["b7d0b6bc2c88ce14975e9fbbefe330575c1a13ea"],"add":36,"del":36,"cadd":36,"cdel":36,"files":36},{"repo":"learning-area","hash":"766b12c7ca2010149ac960c6b7edd889cc2e0f0f","ts":1544049470,"wall":"2018-12-05T17:37","msg":"adding loops and intervals examples to learning area repo","body":"","parents":["b7d0b6bc2c88ce14975e9fbbefe330575c1a13ea"],"add":692,"del":0,"cadd":692,"cdel":0,"files":10},{"repo":"learning-area","hash":"4ee2557f2750f8349752e7e5938ccfb941c4a787","ts":1544104222,"wall":"2018-12-06T08:50","msg":"adding lang attributes","body":"","parents":["766b12c7ca2010149ac960c6b7edd889cc2e0f0f"],"add":13,"del":13,"cadd":13,"cdel":13,"files":9},{"repo":"learning-area","hash":"5acc6979875d1ca621772505f046468f368841de","ts":1544104825,"wall":"2018-12-06T20:00","msg":"Change 'en' to 'en-US'","body":"","parents":["97542e85209bc197b457712fc98d7fc224f63c18"],"add":32,"del":32,"cadd":32,"cdel":32,"files":32},{"repo":"learning-area","hash":"52a89b84275a6c6c6b3cf2f94e05c0daaf85167a","ts":1544106043,"wall":"2018-12-06T09:20","msg":"Merge pull request #113 from alexphilin/add-lang-attribute","body":"<html> element must have a lang attribute","parents":["4ee2557f2750f8349752e7e5938ccfb941c4a787","5acc6979875d1ca621772505f046468f368841de"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"9ca5f0d39f397e6acb553cbb6b5c0f5818fa52d4","ts":1544704829,"wall":"2018-12-13T12:40","msg":"adding promises examples for async module","body":"","parents":["4ee2557f2750f8349752e7e5938ccfb941c4a787"],"add":201,"del":3,"cadd":200,"cdel":3,"files":10},{"repo":"learning-area","hash":"71131f14477ca84a072de5fce8c68afbde19b3b1","ts":1544704848,"wall":"2018-12-13T12:40","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["9ca5f0d39f397e6acb553cbb6b5c0f5818fa52d4","52a89b84275a6c6c6b3cf2f94e05c0daaf85167a"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"cd3e3d697391f3ad94dd437bd4b1eb0776e6a459","ts":1545302871,"wall":"2018-12-20T18:47","msg":"<input> element miss a id attribute","body":"","parents":["71131f14477ca84a072de5fce8c68afbde19b3b1"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"833cf3fc034bfbdb1d9b441721a4fe1f8b9f2b37","ts":1545307834,"wall":"2018-12-20T12:10","msg":"Merge pull request #114 from lfzyx/patch-1","body":"<input> element miss a id attribute","parents":["71131f14477ca84a072de5fce8c68afbde19b3b1","cd3e3d697391f3ad94dd437bd4b1eb0776e6a459"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"bacebd174cb0e805d310fdde3c60f9e2781e8dca","ts":1545833639,"wall":"2018-12-26T22:13","msg":"Duplicate file in \"introduction-to-js-1/what-is-js\" folder","body":"","parents":["833cf3fc034bfbdb1d9b441721a4fe1f8b9f2b37"],"add":0,"del":11,"cadd":0,"cdel":11,"files":1},{"repo":"learning-area","hash":"895ffc3e3bdaba53791e378bf08ad82ffa42023f","ts":1546885414,"wall":"2019-01-07T18:23","msg":"Merge pull request #115 from lfzyx/patch-1","body":"Duplicate file in \"introduction-to-js-1/what-is-js\" folder","parents":["833cf3fc034bfbdb1d9b441721a4fe1f8b9f2b37","bacebd174cb0e805d310fdde3c60f9e2781e8dca"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"68ab603e57b0ccdb05f3cd75fbd5e9717f039a48","ts":1547462271,"wall":"2019-01-14T10:37","msg":"getting rid of problematic geolocation example, and changing basic intro example to use web audio api instead","body":"","parents":["895ffc3e3bdaba53791e378bf08ad82ffa42023f"],"add":74,"del":46,"cadd":74,"cdel":46,"files":3},{"repo":"learning-area","hash":"ca35b0c98b5e253701db9b78a2f03400b0f6a514","ts":1547462398,"wall":"2019-01-14T10:39","msg":"changing default volume to 1","body":"","parents":["68ab603e57b0ccdb05f3cd75fbd5e9717f039a48"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"176dce93cfa2ca52d65805dfca4e2d0a55508867","ts":1547465845,"wall":"2019-01-14T11:37","msg":"making a few other small fixes","body":"","parents":["ca35b0c98b5e253701db9b78a2f03400b0f6a514"],"add":14,"del":13,"cadd":14,"cdel":13,"files":1},{"repo":"learning-area","hash":"8358d8c53988eedc6cae80b93895a72bdfbd6138","ts":1547466498,"wall":"2019-01-14T11:48","msg":"add simple working google maps api example","body":"","parents":["176dce93cfa2ca52d65805dfca4e2d0a55508867"],"add":31,"del":0,"cadd":31,"cdel":0,"files":1},{"repo":"learning-area","hash":"ff45ef6a70c83fea323d6cc255b9b54bde70a05d","ts":1547468371,"wall":"2019-01-14T12:19","msg":"small changes","body":"","parents":["8358d8c53988eedc6cae80b93895a72bdfbd6138"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"3c1e44f4b14d926923f23c20c765299597113301","ts":1547468438,"wall":"2019-01-14T12:20","msg":"small changes","body":"","parents":["ff45ef6a70c83fea323d6cc255b9b54bde70a05d"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"db0db30dca2ea3392b6efe6ebc0d220ad6f5e495","ts":1547471341,"wall":"2019-01-14T13:09","msg":"adding updated finished maps example","body":"","parents":["3c1e44f4b14d926923f23c20c765299597113301"],"add":57,"del":112,"cadd":57,"cdel":112,"files":3},{"repo":"learning-area","hash":"6b740cd308cc104a638ffc27976ccfb57d661659","ts":1547472432,"wall":"2019-01-14T13:27","msg":"small adjustments","body":"","parents":["db0db30dca2ea3392b6efe6ebc0d220ad6f5e495"],"add":3,"del":3,"cadd":3,"cdel":3,"files":2},{"repo":"learning-area","hash":"cb67adfe02608a5ccd3b8e67109942e632bbb283","ts":1548040526,"wall":"2019-01-21T11:15","msg":"Update basic-for-improved.html","body":"","parents":["6b740cd308cc104a638ffc27976ccfb57d661659"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"dbf5e23d772d8b104c9a30b746427c59fede5464","ts":1548066635,"wall":"2019-01-21T05:30","msg":"Merge pull request #117 from mdn/gh-pages","body":"2","parents":["6b740cd308cc104a638ffc27976ccfb57d661659","38178b71364cd1d89517b4989ae333036618c18c"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"7c00b3853425aca853f13692701284883455478c","ts":1548066652,"wall":"2019-01-21T05:30","msg":"Merge pull request #116 from hahawillhahawill/patch-1","body":"Update basic-for-improved.html","parents":["dbf5e23d772d8b104c9a30b746427c59fede5464","cb67adfe02608a5ccd3b8e67109942e632bbb283"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"06fefa820b7c35bc5d485fa191ffa1c65898c427","ts":1548099170,"wall":"2019-01-21T19:32","msg":"adding simple mapquest example","body":"","parents":["7c00b3853425aca853f13692701284883455478c"],"add":30,"del":0,"cadd":30,"cdel":0,"files":1},{"repo":"learning-area","hash":"edeb9bc9d4570ad34033c2566a0c9193eccaba70","ts":1548101016,"wall":"2019-01-21T20:03","msg":"adding simple mapquest example","body":"","parents":["06fefa820b7c35bc5d485fa191ffa1c65898c427"],"add":15,"del":11,"cadd":15,"cdel":11,"files":1},{"repo":"learning-area","hash":"1ef220f64f4aad54c010c63a461f7bfe95a4a260","ts":1548145617,"wall":"2019-01-22T08:26","msg":"adding simple mapquest example","body":"","parents":["edeb9bc9d4570ad34033c2566a0c9193eccaba70"],"add":20,"del":2,"cadd":20,"cdel":2,"files":1},{"repo":"learning-area","hash":"20eccc47fe06ba8dadef8194e6da07b4ddcf913e","ts":1548147460,"wall":"2019-01-22T08:57","msg":"adding simple mapquest example","body":"","parents":["1ef220f64f4aad54c010c63a461f7bfe95a4a260"],"add":53,"del":18,"cadd":53,"cdel":18,"files":2},{"repo":"learning-area","hash":"73bf289203be5a3ebbfb4763ff557d1cc0773b4e","ts":1548153033,"wall":"2019-01-22T10:30","msg":"adding simple mapquest example","body":"","parents":["20eccc47fe06ba8dadef8194e6da07b4ddcf913e"],"add":4,"del":5,"cadd":4,"cdel":5,"files":1},{"repo":"learning-area","hash":"3c0e38b2952e48595aa25ee459afb80573f3f3ee","ts":1548155460,"wall":"2019-01-22T11:11","msg":"further small change to mapquest exaple, and testing nyt exaple with actual api key","body":"","parents":["73bf289203be5a3ebbfb4763ff557d1cc0773b4e"],"add":3,"del":3,"cadd":3,"cdel":3,"files":2},{"repo":"learning-area","hash":"e6107134490a188c4709f16bafdb11b95bd9b41d","ts":1548232134,"wall":"2019-01-23T08:28","msg":"adding starter file for mapquest example","body":"","parents":["3c0e38b2952e48595aa25ee459afb80573f3f3ee"],"add":35,"del":0,"cadd":35,"cdel":0,"files":1},{"repo":"learning-area","hash":"12d9c473ca715ceff67cd057ff4104d90043a92a","ts":1550762692,"wall":"2019-02-21T15:24","msg":"adding async await examples to learning area","body":"","parents":["e6107134490a188c4709f16bafdb11b95bd9b41d"],"add":398,"del":50,"cadd":395,"cdel":48,"files":20},{"repo":"learning-area","hash":"e8b297e4dd6e954b1f1566c1ab2fd2a02996041b","ts":1550766697,"wall":"2019-02-21T16:31","msg":"adding async await examples to learning area","body":"","parents":["12d9c473ca715ceff67cd057ff4104d90043a92a"],"add":31,"del":15,"cadd":31,"cdel":15,"files":2},{"repo":"learning-area","hash":"8ea7256f8126ddd9c247d91780369162a3753f18","ts":1550766726,"wall":"2019-02-21T16:32","msg":"adding async await examples to learning area","body":"","parents":["e8b297e4dd6e954b1f1566c1ab2fd2a02996041b"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"040de1d3d0c696824ff910ca1a92774b6ddce01b","ts":1550770486,"wall":"2019-02-21T17:34","msg":"adding async await examples to learning area","body":"","parents":["8ea7256f8126ddd9c247d91780369162a3753f18"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"9f9cf606ec813c9f507fa6f9687fdf52b46336bc","ts":1550771963,"wall":"2019-02-21T17:59","msg":"adding async await examples to learning area","body":"","parents":["040de1d3d0c696824ff910ca1a92774b6ddce01b"],"add":21,"del":21,"cadd":21,"cdel":21,"files":2},{"repo":"learning-area","hash":"1b03c2266fbd5fbb0799c31ce2ce2cb7be8f3539","ts":1552303939,"wall":"2019-03-11T11:32","msg":"fixing cite element example to be more accurate wirth semantics expected","body":"","parents":["9f9cf606ec813c9f507fa6f9687fdf52b46336bc"],"add":3,"del":3,"cadd":2,"cdel":2,"files":3},{"repo":"learning-area","hash":"d9f581f98548ba6d9e3fae82afa61509161da65d","ts":1553249623,"wall":"2019-03-22T06:13","msg":"Hide File Input Using Opacity","body":"Updates the sample code to match the approach recommended in https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file","parents":["1b03c2266fbd5fbb0799c31ce2ce2cb7be8f3539"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"e66485e16264ed1c164ed038530cf48f37ced4cd","ts":1553274793,"wall":"2019-03-22T17:13","msg":"Merge pull request #123 from swseverance/patch-1","body":"Hide File Input Using Opacity","parents":["1b03c2266fbd5fbb0799c31ce2ce2cb7be8f3539","d9f581f98548ba6d9e3fae82afa61509161da65d"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"2802615c1d183e51ac95b26e01fe0ad62f8830ad","ts":1553525469,"wall":"2019-03-25T14:51","msg":"updating IndexedDB example DB and OS names, as per Kayce Basques comments","body":"","parents":["e66485e16264ed1c164ed038530cf48f37ced4cd"],"add":12,"del":12,"cadd":12,"cdel":12,"files":2},{"repo":"learning-area","hash":"3ef9dfd2e1807f63c8592494dad2537b021b5fa8","ts":1553952537,"wall":"2019-03-30T06:28","msg":"Add Mozilla Code of Conduct file","body":"Fixes #125.\n\n_(Message COC002)_","parents":["2802615c1d183e51ac95b26e01fe0ad62f8830ad"],"add":15,"del":0,"cadd":15,"cdel":0,"files":1},{"repo":"learning-area","hash":"5172fd3f3446ceb8e1ccee255fef233e068f390a","ts":1554054538,"wall":"2019-03-31T18:48","msg":"Merge pull request #126 from Mozilla-GitHub-Standards/master","body":"Add Mozilla Code of Conduct","parents":["2802615c1d183e51ac95b26e01fe0ad62f8830ad","3ef9dfd2e1807f63c8592494dad2537b021b5fa8"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"3eed65fedda567ada5c6dab838a95d1219e122e1","ts":1554232355,"wall":"2019-04-02T22:12","msg":"Typo in Caffiene","body":"","parents":["5172fd3f3446ceb8e1ccee255fef233e068f390a"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"4b3dced4d438bcb877ae064ee2ecb36d37dfd544","ts":1554268771,"wall":"2019-04-03T06:19","msg":"Merge pull request #127 from fazl/patch-1","body":"Typo in Caffiene","parents":["5172fd3f3446ceb8e1ccee255fef233e068f390a","3eed65fedda567ada5c6dab838a95d1219e122e1"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"660f31865bd70eb53079b3af8b8f0b0d39c05774","ts":1554747638,"wall":"2019-04-08T19:20","msg":"adding more async js examples","body":"","parents":["2802615c1d183e51ac95b26e01fe0ad62f8830ad"],"add":57,"del":16,"cadd":43,"cdel":2,"files":5},{"repo":"learning-area","hash":"2ef9f6ec70ddcc7b875b5a04b50ccd4dd090190e","ts":1554747650,"wall":"2019-04-08T19:20","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["660f31865bd70eb53079b3af8b8f0b0d39c05774","4b3dced4d438bcb877ae064ee2ecb36d37dfd544"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"ef95deb4584699975fb3a8ad1f9de7429980a73c","ts":1554811459,"wall":"2019-04-09T13:04","msg":"adding async-await example","body":"","parents":["2ef9f6ec70ddcc7b875b5a04b50ccd4dd090190e"],"add":22,"del":0,"cadd":22,"cdel":0,"files":1},{"repo":"learning-area","hash":"1119d07a6bb51d7d4a3b7e8cc8d3003ae1883247","ts":1555242698,"wall":"2019-04-14T08:51","msg":"Populate balls array outside the animation loop","body":"","parents":["ef95deb4584699975fb3a8ad1f9de7429980a73c"],"add":16,"del":16,"cadd":16,"cdel":16,"files":1},{"repo":"learning-area","hash":"c46ba9916af7cf48171ae008fdb826d79233fdaa","ts":1555320409,"wall":"2019-04-15T10:26","msg":"Merge pull request #128 from campos20/populate-outside","body":"Populate balls array outside the animation loop","parents":["ef95deb4584699975fb3a8ad1f9de7429980a73c","1119d07a6bb51d7d4a3b7e8cc8d3003ae1883247"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"97e996dac5393e983a19f4f32578dd05fca67f2a","ts":1555331057,"wall":"2019-04-15T13:24","msg":"updating bouncing ball examples to move the ball array population code outside the main rendering loop","body":"","parents":["c46ba9916af7cf48171ae008fdb826d79233fdaa"],"add":39,"del":37,"cadd":39,"cdel":37,"files":2},{"repo":"learning-area","hash":"68ed6daf75eb46504ca4295ffa7490084fce952e","ts":1555349835,"wall":"2019-04-15T14:37","msg":"Minor typo (Terrestial)","body":"","parents":["97e996dac5393e983a19f4f32578dd05fca67f2a"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"085024c937e52ea356fb523bf64910a160bf92a9","ts":1555405715,"wall":"2019-04-16T10:08","msg":"Merge pull request #129 from EricCBL/patch-1","body":"Minor typo (Terrestial)","parents":["97e996dac5393e983a19f4f32578dd05fca67f2a","68ed6daf75eb46504ca4295ffa7490084fce952e"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"e918199300b6df6e57fb1c90f78c3fcc70c342ba","ts":1555579877,"wall":"2019-04-18T11:31","msg":"add es6 version of main-finished.js","body":"alter main-finished in such a way that it uses ES6 classes.","parents":["085024c937e52ea356fb523bf64910a160bf92a9"],"add":109,"del":0,"cadd":109,"cdel":0,"files":1},{"repo":"learning-area","hash":"9f7b07548144f4ad87fa6efb6b4799c61882f78b","ts":1555580813,"wall":"2019-04-18T10:46","msg":"Merge pull request #130 from tamasmucs/patch-1","body":"add es6 version of main-finished.js","parents":["085024c937e52ea356fb523bf64910a160bf92a9","e918199300b6df6e57fb1c90f78c3fcc70c342ba"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"67320f9c2a3965b63acb9e90710f8bd5a42a7f07","ts":1555582413,"wall":"2019-04-18T12:13","msg":"use Object.defineProperty as in tutorial docs","body":"In tutorial docs:\nhttps://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance#Setting_Teacher()'s_prototype_and_constructor_reference\n\nHere you redefine Teacher.prototype.constructor with Object.defineProperty, but in  in this code you use the simply use the equals operator. I propose to update this file or the tutorial guidelines.","parents":["9f7b07548144f4ad87fa6efb6b4799c61882f78b"],"add":5,"del":1,"cadd":5,"cdel":1,"files":1},{"repo":"learning-area","hash":"58309aa02df5fc3feab9ecc085286ebd541d4421","ts":1556021345,"wall":"2019-04-23T13:09","msg":"updating rotateCount functions as per sheppy comment","body":"","parents":["9f7b07548144f4ad87fa6efb6b4799c61882f78b"],"add":4,"del":4,"cadd":4,"cdel":4,"files":4},{"repo":"deck-of-cards","hash":"53e6922633af0db0b404332f18a0fc9c86a935b9","ts":1556333365,"wall":"2019-04-26T22:49","msg":"Fixed typo","body":"","parents":["7afec8d2585b683445f03aa9a8655283be4b87e5"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"4b1a567e4acac23adcb30ee023c5f389c8a022c6","ts":1556337103,"wall":"2019-04-27T06:51","msg":"Merge pull request #53 from GregFrench/patch-1","body":"Fixed typo","parents":["7afec8d2585b683445f03aa9a8655283be4b87e5","53e6922633af0db0b404332f18a0fc9c86a935b9"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"afca30bd1c0fa4ffef12294d159002940419e6d9","ts":1556727898,"wall":"2019-05-02T00:24","msg":"Update index.html to clean JavaScript code","body":"I tested and think this approach could be clearer and easier to understand.","parents":["58309aa02df5fc3feab9ecc085286ebd541d4421"],"add":6,"del":6,"cadd":6,"cdel":6,"files":1},{"repo":"learning-area","hash":"e35fe9a9f29d83e475cefa231511746b3312e171","ts":1556788434,"wall":"2019-05-02T10:13","msg":"Update basic-for-improved.html","body":"I think there should be  if(i === cats.length -1 ) - otherwise it will never run this code?","parents":["58309aa02df5fc3feab9ecc085286ebd541d4421"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"f765b53348db046f9567df13288b63386f6f578c","ts":1556800967,"wall":"2019-05-02T13:42","msg":"Update basic-for-improved.html","body":"","parents":["e35fe9a9f29d83e475cefa231511746b3312e171"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"3f28254e2177c724e0cb82ca0d6af868711694bd","ts":1556801628,"wall":"2019-05-02T13:53","msg":"Merge pull request #134 from escape0707/patch-1","body":"Update index.html to clean JavaScript code","parents":["58309aa02df5fc3feab9ecc085286ebd541d4421","afca30bd1c0fa4ffef12294d159002940419e6d9"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"f22bad01fe47b028a3292a46a8af9b7f0a1f87dd","ts":1556804430,"wall":"2019-05-02T14:40","msg":"Update javascript/building-blocks/loops/basic-for-improved.html","body":"Fix spacing\n\nCo-Authored-By: mgo7 <44372913+mgo7@users.noreply.github.com>","parents":["f765b53348db046f9567df13288b63386f6f578c"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"55dbd9f661b44023e1b1d2cd9502d6d24f4134d5","ts":1556804783,"wall":"2019-05-02T14:46","msg":"Merge pull request #135 from mgo7/patch-1","body":"Update basic-for-improved.html","parents":["3f28254e2177c724e0cb82ca0d6af868711694bd","f22bad01fe47b028a3292a46a8af9b7f0a1f87dd"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"900168149345ac386d9fceec0ee427391d68f513","ts":1557742499,"wall":"2019-05-13T11:14","msg":"fixing variable declaration error in image gallery code","body":"","parents":["3f28254e2177c724e0cb82ca0d6af868711694bd"],"add":3,"del":3,"cadd":3,"cdel":3,"files":2},{"repo":"learning-area","hash":"76a041e0226568a61a865dafcdb4a4aed6d53d21","ts":1557742517,"wall":"2019-05-13T11:15","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["900168149345ac386d9fceec0ee427391d68f513","55dbd9f661b44023e1b1d2cd9502d6d24f4134d5"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"3996f8c7ecf50a92f454fa5b6766221093b93a49","ts":1558640797,"wall":"2019-05-23T22:46","msg":"Redirect to new domain","body":"","parents":["6653b5009a58dcca10912dc151512cd94ef62ea5"],"add":6,"del":5,"cadd":6,"cdel":5,"files":1},{"repo":"learning-area","hash":"0a266eebc25606548808445ec41a50ad202b7bd1","ts":1558697748,"wall":"2019-05-24T12:35","msg":"Input Box Case sentivity","body":"","parents":["76a041e0226568a61a865dafcdb4a4aed6d53d21"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"9cb8222609188be82b394cfab68dd08e61d6db32","ts":1559134651,"wall":"2019-05-29T13:57","msg":"Merge pull request #139 from mayunited12/master","body":"Input Box Case sentivity","parents":["76a041e0226568a61a865dafcdb4a4aed6d53d21","0a266eebc25606548808445ec41a50ad202b7bd1"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"b15c1c3465ba550b3752191fc8763e7ccd175abd","ts":1559214167,"wall":"2019-05-30T13:02","msg":"updating date picker examples to use better methof of calculating leap years","body":"","parents":["76a041e0226568a61a865dafcdb4a4aed6d53d21"],"add":6,"del":4,"cadd":6,"cdel":4,"files":3},{"repo":"learning-area","hash":"a6fcd749959693c6cec1cf6d472d7ba1ccb33fc0","ts":1559214191,"wall":"2019-05-30T13:03","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["b15c1c3465ba550b3752191fc8763e7ccd175abd","9cb8222609188be82b394cfab68dd08e61d6db32"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"a9d8fdd8c0182fe9547e9a10f75182a584f17e5c","ts":1559305441,"wall":"2019-05-31T15:24","msg":"Update README.md","body":"","parents":["4b1a567e4acac23adcb30ee023c5f389c8a022c6"],"add":7,"del":1,"cadd":7,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"843ff48e926845b162cf8f67b3625b997d563eef","ts":1559305465,"wall":"2019-05-31T15:24","msg":"Update README.md","body":"","parents":["a9d8fdd8c0182fe9547e9a10f75182a584f17e5c"],"add":0,"del":3,"cadd":0,"cdel":3,"files":1},{"repo":"deck-of-cards","hash":"91d3f417b1e58ee955a3283f5d97f848c9f6182e","ts":1559305533,"wall":"2019-05-31T15:25","msg":"Update README.md","body":"","parents":["843ff48e926845b162cf8f67b3625b997d563eef"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"06ad501317728711cea1756e7c36fbee6d7ad0b3","ts":1559305550,"wall":"2019-05-31T15:25","msg":"Update README.md","body":"","parents":["91d3f417b1e58ee955a3283f5d97f848c9f6182e"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"80d398fce3baa42b9ef584f0c4a80a0820f14669","ts":1559307160,"wall":"2019-05-31T15:52","msg":"Fix shuffle","body":"","parents":["06ad501317728711cea1756e7c36fbee6d7ad0b3"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"83b4df1e06790881ea6dd807834b1ae6028afdb5","ts":1559500459,"wall":"2019-06-02T21:34","msg":"Create FUNDING.yml","body":"","parents":["80d398fce3baa42b9ef584f0c4a80a0820f14669"],"add":9,"del":0,"cadd":9,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"48105ba8eb461406d7489e55c15dfc1f62bd3dfc","ts":1559506040,"wall":"2019-06-02T23:07","msg":"Update FUNDING.yml","body":"","parents":["83b4df1e06790881ea6dd807834b1ae6028afdb5"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"9393af4690d72a14025d856f347dc35910ed388c","ts":1559668547,"wall":"2019-06-04T20:15","msg":"Total rewrite!","body":"","parents":["48105ba8eb461406d7489e55c15dfc1f62bd3dfc"],"add":0,"del":5106,"cadd":0,"cdel":3359,"files":97},{"repo":"deck-of-cards","hash":"e25328c44d04278f7c1eb067872bbed957f5a26b","ts":1559668599,"wall":"2019-06-04T20:16","msg":"Create package.json","body":"","parents":["9393af4690d72a14025d856f347dc35910ed388c"],"add":18,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"8a0add06830683c999af501318024034bd7af814","ts":1559668627,"wall":"2019-06-04T20:17","msg":"Create LICENSE","body":"","parents":["e25328c44d04278f7c1eb067872bbed957f5a26b"],"add":21,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"c48171adb4c0cbc6801804d0eab11ff513070c50","ts":1559724511,"wall":"2019-06-05T14:18","msg":"Multiple times  clicking of start button is bug.","body":"After clicking start button once it has to be disabled. Enable it again after clicking of stop button.","parents":["a6fcd749959693c6cec1cf6d472d7ba1ccb33fc0"],"add":2,"del":0,"cadd":2,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"10b0c45fe0f3f6a1e8c1723e1362f87d4af33c3b","ts":1559730394,"wall":"2019-06-05T13:26","msg":"Update FUNDING.yml","body":"","parents":["8a0add06830683c999af501318024034bd7af814"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"56454058035165dfc56741e691eb91fffc7e0908","ts":1559730450,"wall":"2019-06-05T13:27","msg":"Update FUNDING.yml","body":"","parents":["48105ba8eb461406d7489e55c15dfc1f62bd3dfc"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"aeed8a42674b5243d585769568be3da786d25d51","ts":1559752536,"wall":"2019-06-05T22:05","msg":"changes made added space for better visibility.","body":"","parents":["c48171adb4c0cbc6801804d0eab11ff513070c50"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"8c085daef10b08a7503ad8204096bce9464e7dac","ts":1559904746,"wall":"2019-06-07T11:52","msg":"Merge pull request #140 from monil25/patch-1","body":"Multiple times  clicking of start button is bug.","parents":["a6fcd749959693c6cec1cf6d472d7ba1ccb33fc0","aeed8a42674b5243d585769568be3da786d25d51"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"9a7b5f541cdb325b325cd163e5817a9d2cc7b829","ts":1561043245,"wall":"2019-06-20T18:07","msg":"declare once, keeping it value in range [0;360]","body":"","parents":["8c085daef10b08a7503ad8204096bce9464e7dac"],"add":7,"del":6,"cadd":7,"cdel":6,"files":1},{"repo":"learning-area","hash":"5a07e52de587b173ec05cf9dd3f741ecea86e52a","ts":1562063777,"wall":"2019-07-02T11:36","msg":"removing broken console example","body":"","parents":["8c085daef10b08a7503ad8204096bce9464e7dac"],"add":0,"del":103,"cadd":0,"cdel":103,"files":1},{"repo":"learning-area","hash":"8da8afd1683a7717bb224fb71755edfdd4e07e8d","ts":1562579632,"wall":"2019-07-08T10:53","msg":"Merge pull request #103 from li3097/patch-3","body":"Update 'var' to 'let'","parents":["5a07e52de587b173ec05cf9dd3f741ecea86e52a","836e613270b556baeebd58c7d3afd4823b59c5ed"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"a7cebeb75bd525cd61cc068d2dcb9f9c67417bee","ts":1562579865,"wall":"2019-07-08T10:57","msg":"Merge pull request #60 from MarckK/patch-1","body":"Update oojs-finished.html","parents":["8da8afd1683a7717bb224fb71755edfdd4e07e8d","126f91338460201c22af1e561b0ace8002faabad"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"3ef464f05530a5a53e74725e9fb43e4ed172b2f9","ts":1562580090,"wall":"2019-07-08T11:01","msg":"Merge pull request #142 from enejko/patch-1","body":"declare once, keeping it value in range [0;360)","parents":["a7cebeb75bd525cd61cc068d2dcb9f9c67417bee","9a7b5f541cdb325b325cd163e5817a9d2cc7b829"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"45ee546a91f5775995ed945e643580b893759819","ts":1563198861,"wall":"2019-07-15T06:54","msg":"Added financial contributors to the README","body":"","parents":["56454058035165dfc56741e691eb91fffc7e0908"],"add":31,"del":1,"cadd":31,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"9064c038071763283cb8e6c1a49aa0ee5753ba2e","ts":1563198861,"wall":"2019-07-15T06:54","msg":"Added call to donate after npm install (optional)","body":"","parents":["45ee546a91f5775995ed945e643580b893759819"],"add":10,"del":2,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"97652099151eb94c8d0dca0d0885d0d3049ee948","ts":1563200652,"wall":"2019-07-15T17:24","msg":"Merge pull request #56 from opencollective/opencollective","body":"Activating Open Collective","parents":["56454058035165dfc56741e691eb91fffc7e0908","9064c038071763283cb8e6c1a49aa0ee5753ba2e"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"597ed5f306de51e7faaa9d59cc40e7797677cab1","ts":1565349771,"wall":"2019-08-09T16:52","msg":"Changed Var to Let and Const","body":"","parents":["3ef464f05530a5a53e74725e9fb43e4ed172b2f9"],"add":14,"del":17,"cadd":14,"cdel":17,"files":1},{"repo":"learning-area","hash":"1a9e8fa686ce3f145c05f742c16a38c1565a81f8","ts":1566476479,"wall":"2019-08-22T13:21","msg":"Merge pull request #149 from edisonaugusthy/master","body":"Changed Var to Let and Const","parents":["3ef464f05530a5a53e74725e9fb43e4ed172b2f9","597ed5f306de51e7faaa9d59cc40e7797677cab1"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"c67dec25a06b715dc8ac39b5052412e8a0277581","ts":1567087522,"wall":"2019-08-29T15:05","msg":"Dealing with reset button's issue.","body":"Letting users to use the reset button straight after they press the start button without the clock having wrong behavior. Originally, if a user starts the clock and doesn't press the stop button before pressing the reset button, the clock will reset to 00:00:00 and then start running again automatically.","parents":["1a9e8fa686ce3f145c05f742c16a38c1565a81f8"],"add":2,"del":0,"cadd":2,"cdel":0,"files":1},{"repo":"learning-area","hash":"072849adf6fb6496c33baae9c9501a066ce38bf0","ts":1567093320,"wall":"2019-08-29T16:42","msg":"Merge pull request #151 from jasontwuk/patch-1","body":"Dealing with reset button's issue.","parents":["1a9e8fa686ce3f145c05f742c16a38c1565a81f8","c67dec25a06b715dc8ac39b5052412e8a0277581"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"b66dd15918ce802b0ed163d270d4b7c9f0deb9f3","ts":1567182595,"wall":"2019-08-30T19:29","msg":"fixed indentation for two paragraphs","body":"","parents":["072849adf6fb6496c33baae9c9501a066ce38bf0"],"add":13,"del":13,"cadd":13,"cdel":13,"files":1},{"repo":"learning-area","hash":"c0abf810d2ea69bf74e5ae16abf7d3a765dd849c","ts":1567183005,"wall":"2019-08-30T17:36","msg":"Update start-and-stop-spinner.html","body":"Matching the code with the previous example's (simple-raf-spinner.html).","parents":["072849adf6fb6496c33baae9c9501a066ce38bf0"],"add":6,"del":5,"cadd":6,"cdel":5,"files":1},{"repo":"learning-area","hash":"887b77be36ff3c79d934fa021153bdbcbec5e0d0","ts":1567196338,"wall":"2019-08-30T21:18","msg":"Update reaction-game.html","body":"(1) Match up the code with the previous example's (simple-raf-spinner.html). \n(2) Remove a let declaration, because it is repeated. \n(3) The contents in this MDN web docs webpage (https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals#requestAnimationFrame()) might need an update as well. The location is \"Active learning: a reaction game - 4\" in that webpage.","parents":["072849adf6fb6496c33baae9c9501a066ce38bf0"],"add":6,"del":5,"cadd":6,"cdel":5,"files":1},{"repo":"learning-area","hash":"e8d2304a8ffe17a2c990a0a21db5adaa6b9e783e","ts":1567423852,"wall":"2019-09-02T12:30","msg":"Merge pull request #152 from Haggr/master","body":"fixed indentation for two paragraphs","parents":["072849adf6fb6496c33baae9c9501a066ce38bf0","b66dd15918ce802b0ed163d270d4b7c9f0deb9f3"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"224e58788b55fd0a5a3d4df89df1e96c72611d54","ts":1567502042,"wall":"2019-09-03T10:14","msg":"updating latter assessment ot use address element","body":"","parents":["e8d2304a8ffe17a2c990a0a21db5adaa6b9e783e"],"add":6,"del":6,"cadd":6,"cdel":6,"files":2},{"repo":"learning-area","hash":"f8a750ef1064f72f0be27bbbe8d4997865b80c18","ts":1567503988,"wall":"2019-09-03T10:46","msg":"Merge pull request #153 from jasontwuk/patch-1","body":"Update start-and-stop-spinner.html","parents":["224e58788b55fd0a5a3d4df89df1e96c72611d54","c0abf810d2ea69bf74e5ae16abf7d3a765dd849c"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"4edc3e1b13f468f24de105c429ba91fdf1e300d1","ts":1567504438,"wall":"2019-09-03T10:53","msg":"Merge pull request #154 from jasontwuk/patch-2","body":"Update reaction-game.html","parents":["f8a750ef1064f72f0be27bbbe8d4997865b80c18","887b77be36ff3c79d934fa021153bdbcbec5e0d0"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"4fe2fab39580be3b8042ee92b45eb1db25cc52b2","ts":1569582911,"wall":"2019-09-27T12:15","msg":"fixing typo in HTML tables example","body":"","parents":["4edc3e1b13f468f24de105c429ba91fdf1e300d1"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"da9eff0e320299663ec9741c418b67fe849d9e3d","ts":1570926406,"wall":"2019-10-13T02:26","msg":"Use ES6 variable keywords","body":"Window's height and width have to be stored in as a \"let\" to be able to change their values on resize. Otherwise the program throws an error.","parents":["4fe2fab39580be3b8042ee92b45eb1db25cc52b2"],"add":9,"del":9,"cadd":9,"cdel":9,"files":1},{"repo":"learning-area","hash":"52dd942eab33353cc896fd5223fa6f7ecde24b6f","ts":1571223540,"wall":"2019-10-16T11:59","msg":"Merge pull request #159 from hararca/patch-1","body":"Use ES6 variable keywords","parents":["4fe2fab39580be3b8042ee92b45eb1db25cc52b2","da9eff0e320299663ec9741c418b67fe849d9e3d"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"359cbefb76d5e30cd40fd6f3d07b936d03eda5be","ts":1572635895,"wall":"2019-11-01T15:18","msg":"Using srcObject instead of object URL","body":"createObjectURL no longer accepts MediaStreams, so the previous version threw a TypeError.","parents":["52dd942eab33353cc896fd5223fa6f7ecde24b6f"],"add":1,"del":2,"cadd":1,"cdel":2,"files":1},{"repo":"learning-area","hash":"83c73b7f393bbc0991ad70925958286c8b4c5ea1","ts":1572892330,"wall":"2019-11-04T18:32","msg":"Merge pull request #163 from wwags33/patch-1","body":"Using srcObject instead of createObjectURL","parents":["52dd942eab33353cc896fd5223fa6f7ecde24b6f","359cbefb76d5e30cd40fd6f3d07b936d03eda5be"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"4728a9d7d52654e08769cc3f4dd5bac9ad632b98","ts":1572893096,"wall":"2019-11-04T18:44","msg":"updating Three.js examples to use modern ES features and up-to-date APIs","body":"","parents":["83c73b7f393bbc0991ad70925958286c8b4c5ea1"],"add":37,"del":50,"cadd":37,"cdel":50,"files":2},{"repo":"learning-area","hash":"ef0392556bb16c548286059aaa10a49d14a94375","ts":1573695699,"wall":"2019-11-14T10:41","msg":"Update the info box color and margins to match the capture.","body":"","parents":["4728a9d7d52654e08769cc3f4dd5bac9ad632b98"],"add":15,"del":11,"cadd":15,"cdel":11,"files":1},{"repo":"learning-area","hash":"44ad8911e661f007d26c6254de96310a067c7cc5","ts":1573720264,"wall":"2019-11-14T08:31","msg":"Merge pull request #166 from snakada/update-info-box","body":"Update the info box color and margins to match the capture.","parents":["4728a9d7d52654e08769cc3f4dd5bac9ad632b98","ef0392556bb16c548286059aaa10a49d14a94375"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"9f2e652723a66d469797a38317679a1f96838c56","ts":1573720699,"wall":"2019-11-14T08:38","msg":"updating fixed info box styling to be consistent with updated basic info box example","body":"","parents":["44ad8911e661f007d26c6254de96310a067c7cc5"],"add":18,"del":13,"cadd":18,"cdel":13,"files":1},{"repo":"learning-area","hash":"fca08f2c072c6364744a7f2972dc076a0107da0b","ts":1573731271,"wall":"2019-11-14T11:34","msg":"updating video post image to something that wont offend anyone","body":"","parents":["9f2e652723a66d469797a38317679a1f96838c56"],"add":0,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"a8fb469fafbd32ebe24e912177e1a056c5b6103f","ts":1574365111,"wall":"2019-11-21T19:38","msg":"updating all examples in JS first steps to use const and var","body":"","parents":["fca08f2c072c6364744a7f2972dc076a0107da0b"],"add":66,"del":67,"cadd":60,"cdel":61,"files":7},{"repo":"learning-area","hash":"9dd9614a557a56f5231a3f0e75d2d3b86a4bee23","ts":1574426856,"wall":"2019-11-22T12:47","msg":"fixing broken datetime-local input test","body":"","parents":["a8fb469fafbd32ebe24e912177e1a056c5b6103f"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"f04584a7fa563981864ae502d827fdfecb88fd22","ts":1574427603,"wall":"2019-11-22T13:00","msg":"fixing broken datetime-local input test","body":"","parents":["9dd9614a557a56f5231a3f0e75d2d3b86a4bee23"],"add":7,"del":1,"cadd":7,"cdel":1,"files":1},{"repo":"learning-area","hash":"f6d9af7d88ea30936a6e40ed48910f84c05fc861","ts":1574445430,"wall":"2019-11-22T17:57","msg":"updating OOJS articles to use const and let","body":"","parents":["f04584a7fa563981864ae502d827fdfecb88fd22"],"add":274,"del":290,"cadd":274,"cdel":290,"files":44},{"repo":"learning-area","hash":"6c3bc59548de858264612e4f9d0576003ab37192","ts":1574452863,"wall":"2019-11-22T20:01","msg":"updating the API examples to use const and let","body":"","parents":["f6d9af7d88ea30936a6e40ed48910f84c05fc861"],"add":77,"del":78,"cadd":77,"cdel":78,"files":14},{"repo":"learning-area","hash":"76596d17e86a672385b5472e969da00e4a6ad05d","ts":1574457802,"wall":"2019-11-22T21:23","msg":"updating a11y files to use let and const","body":"","parents":["6c3bc59548de858264612e4f9d0576003ab37192"],"add":621,"del":150,"cadd":621,"cdel":150,"files":26},{"repo":"learning-area","hash":"7c60d316c0c60bcdf1cf0c8d2109e8311e9ac702","ts":1574509696,"wall":"2019-11-23T11:48","msg":"updating tools articles to use const/let","body":"","parents":["76596d17e86a672385b5472e969da00e4a6ad05d"],"add":108,"del":109,"cadd":108,"cdel":109,"files":25},{"repo":"learning-area","hash":"ae28fcea511cd6da1105c04d9f64e8c1782ec7d7","ts":1575371643,"wall":"2019-12-03T11:14","msg":"fixing detection code on data picker example","body":"","parents":["7c60d316c0c60bcdf1cf0c8d2109e8311e9ac702"],"add":7,"del":1,"cadd":7,"cdel":1,"files":1},{"repo":"learning-area","hash":"34d380994d8fc2df135e0b1ef57bdfeb0f31486f","ts":1575907541,"wall":"2019-12-09T16:05","msg":"fixing consts that should be let","body":"","parents":["ae28fcea511cd6da1105c04d9f64e8c1782ec7d7"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"42789cda2bf968a467123eae2a37217b427d3e5b","ts":1575908978,"wall":"2019-12-09T08:29","msg":"gender neutral / tel for credit card","body":"Removed Miss and Mister and made it ace, king, queen to make it less gendered.\nChanged credit card to tel instead of number, since a spinner is not correct for a cc#","parents":["34d380994d8fc2df135e0b1ef57bdfeb0f31486f"],"add":11,"del":5,"cadd":11,"cdel":5,"files":1},{"repo":"learning-area","hash":"dbb22c38d376649dc1974bffec646355a175605e","ts":1575990230,"wall":"2019-12-10T15:03","msg":"Merge pull request #170 from estelle/patch-1","body":"gender neutral / tel for credit card","parents":["34d380994d8fc2df135e0b1ef57bdfeb0f31486f","42789cda2bf968a467123eae2a37217b427d3e5b"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"7c90fa276dad68ee58dd8caccb1d44dd7f7c7b6d","ts":1576166320,"wall":"2019-12-12T15:58","msg":"adding skill tests for HTML text fundamentals","body":"","parents":["34d380994d8fc2df135e0b1ef57bdfeb0f31486f"],"add":538,"del":0,"cadd":538,"cdel":0,"files":9},{"repo":"learning-area","hash":"de06a8814e356b01c1a48b82d79467a46fae0445","ts":1576166334,"wall":"2019-12-12T15:58","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["7c90fa276dad68ee58dd8caccb1d44dd7f7c7b6d","dbb22c38d376649dc1974bffec646355a175605e"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"311038cdf268f6949e06d9ce346112b91b43aa06","ts":1576167165,"wall":"2019-12-12T16:12","msg":"changing folder name so it is more accurate","body":"","parents":["de06a8814e356b01c1a48b82d79467a46fae0445"],"add":0,"del":0,"cadd":0,"cdel":0,"files":7},{"repo":"learning-area","hash":"f54e4bef228116b5ebe1fdceb785fb54acb88a2d","ts":1576175968,"wall":"2019-12-12T18:39","msg":"adding links test your skills examples","body":"","parents":["311038cdf268f6949e06d9ce346112b91b43aa06"],"add":450,"del":0,"cadd":450,"cdel":0,"files":12},{"repo":"learning-area","hash":"076be8e859e882fa572de7e138b1f5d5f736ea7d","ts":1576248733,"wall":"2019-12-13T14:52","msg":"adding advanced test you skills tasks","body":"","parents":["f54e4bef228116b5ebe1fdceb785fb54acb88a2d"],"add":297,"del":0,"cadd":297,"cdel":0,"files":5},{"repo":"learning-area","hash":"8fc207ef72f195a167bc7a6499acfebdc3a18510","ts":1576264621,"wall":"2019-12-13T14:17","msg":"Update raw-text.txt","body":"the MDN exercise file is missing \"random\" variable","parents":["076be8e859e882fa572de7e138b1f5d5f736ea7d"],"add":2,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"083ac9e3a928392c678223158b0a0385c7d15c17","ts":1576491233,"wall":"2019-12-16T10:13","msg":"Merge pull request #172 from Coach-G/patch-1","body":"Update raw-text.txt","parents":["076be8e859e882fa572de7e138b1f5d5f736ea7d","8fc207ef72f195a167bc7a6499acfebdc3a18510"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"325227633eca17ae73c1bd98b02ee5a8cb776a96","ts":1576673921,"wall":"2019-12-18T12:58","msg":"trying to make the srcset example work better","body":"","parents":["083ac9e3a928392c678223158b0a0385c7d15c17"],"add":7,"del":9,"cadd":7,"cdel":9,"files":1},{"repo":"learning-area","hash":"9ef9b7f0d7fffce4b15747c39fa652a54bd77561","ts":1576674076,"wall":"2019-12-18T13:01","msg":"trying to make the srcset example work better","body":"","parents":["325227633eca17ae73c1bd98b02ee5a8cb776a96"],"add":0,"del":1,"cadd":0,"cdel":1,"files":1},{"repo":"learning-area","hash":"f865c8a1cbbb77f8486b1ddb0fadfae6f2b8f705","ts":1576674349,"wall":"2019-12-18T13:05","msg":"trying to make the srcset example work better","body":"","parents":["9ef9b7f0d7fffce4b15747c39fa652a54bd77561"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"1c1e65eeff1bb80494fd6e3e9616842cbd1170dd","ts":1576678262,"wall":"2019-12-18T14:11","msg":"updating srcset in assessment","body":"","parents":["f865c8a1cbbb77f8486b1ddb0fadfae6f2b8f705"],"add":9,"del":9,"cadd":9,"cdel":9,"files":1},{"repo":"learning-area","hash":"222f4393bb618b7f21f1609a945f5dfc59419b4f","ts":1576678832,"wall":"2019-12-18T14:20","msg":"updating srcset in assessment","body":"","parents":["1c1e65eeff1bb80494fd6e3e9616842cbd1170dd"],"add":3,"del":3,"cadd":3,"cdel":3,"files":1},{"repo":"learning-area","hash":"45a82aa9b8908c3ed98b2b9b49b702cc6708aa53","ts":1576679200,"wall":"2019-12-18T14:26","msg":"updating srcset in assessment","body":"","parents":["222f4393bb618b7f21f1609a945f5dfc59419b4f"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"91d08b737a9bbaa592d992bc5ed6e2aed5ad981e","ts":1576754269,"wall":"2019-12-19T11:17","msg":"improving styling text and third party apis examples","body":"","parents":["45a82aa9b8908c3ed98b2b9b49b702cc6708aa53"],"add":12,"del":12,"cadd":12,"cdel":12,"files":3},{"repo":"learning-area","hash":"d154533462a3be37b6b69a0b4693839b04d82c37","ts":1576821732,"wall":"2019-12-20T15:02","msg":"updating your-first-HTML-form to be more accurate","body":"","parents":["91d08b737a9bbaa592d992bc5ed6e2aed5ad981e"],"add":104,"del":90,"cadd":104,"cdel":90,"files":2},{"repo":"learning-area","hash":"060dee862c59b01b62ab6cd7047b9a8804a80d17","ts":1576829394,"wall":"2019-12-20T08:09","msg":"Merge pull request #173 from kyonlee/master","body":"updating your-first-HTML-form to be more accurate","parents":["91d08b737a9bbaa592d992bc5ed6e2aed5ad981e","d154533462a3be37b6b69a0b4693839b04d82c37"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"837c35a221dd26a8af5e1b734b047cc7d588b530","ts":1577167025,"wall":"2019-12-23T21:57","msg":"changed from absolutes positioning to grid","body":"We should not be suggesting absolute positioning as a potential solution, so switched it to grid.","parents":["060dee862c59b01b62ab6cd7047b9a8804a80d17"],"add":112,"del":130,"cadd":112,"cdel":130,"files":1},{"repo":"learning-area","hash":"0665da155841eb9c9e61d9228267058ba9a97182","ts":1577174565,"wall":"2019-12-24T08:02","msg":"Merge pull request #174 from estelle/patch-2","body":"changed from absolutes positioning to grid","parents":["060dee862c59b01b62ab6cd7047b9a8804a80d17","837c35a221dd26a8af5e1b734b047cc7d588b530"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"9e7dd2c10084986a38122c5c6e137eed0c68935f","ts":1577549009,"wall":"2019-12-28T08:03","msg":"Uppercase \"squadName\"","body":"Looks better.","parents":["0665da155841eb9c9e61d9228267058ba9a97182"],"add":2,"del":2,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"b5a047cae13eef69df958d02f9a405e67e6b0b25","ts":1577698821,"wall":"2019-12-30T09:40","msg":"Merge pull request #176 from ckashby/patch-1","body":"Uppercase \"squadName\"","parents":["0665da155841eb9c9e61d9228267058ba9a97182","9e7dd2c10084986a38122c5c6e137eed0c68935f"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"1b876f01decca19887d4dc2cc456e128e6f905ac","ts":1577705504,"wall":"2019-12-30T11:31","msg":"simplifying the image gallery assessment","body":"","parents":["0665da155841eb9c9e61d9228267058ba9a97182"],"add":4,"del":20,"cadd":4,"cdel":20,"files":2},{"repo":"learning-area","hash":"771d9372ef09da5ce1f4a245825abe7060f8d09f","ts":1577705521,"wall":"2019-12-30T11:32","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["1b876f01decca19887d4dc2cc456e128e6f905ac","b5a047cae13eef69df958d02f9a405e67e6b0b25"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"71ed5ea2d383eac7fa901039b24c6b3961524caf","ts":1577729564,"wall":"2019-12-30T18:12","msg":"adding images/multimedia test your skills examples","body":"","parents":["771d9372ef09da5ce1f4a245825abe7060f8d09f"],"add":709,"del":2,"cadd":696,"cdel":2,"files":26},{"repo":"learning-area","hash":"87333612ba451343eed8bc08ad84ad4cc6343cd1","ts":1577976930,"wall":"2020-01-02T18:55","msg":"for consistency with the MDN web docs","body":"https://developer.mozilla.org/en-US/docs/Learn/Forms/How_to_structure_an_HTML_form#Labels_are_clickable_too!","parents":["71ed5ea2d383eac7fa901039b24c6b3961524caf"],"add":8,"del":8,"cadd":8,"cdel":8,"files":1},{"repo":"learning-area","hash":"f92ff894bd69885ff99385b69bf8c767ecec4599","ts":1578056149,"wall":"2020-01-03T12:55","msg":"updating can store example to use const/let","body":"","parents":["71ed5ea2d383eac7fa901039b24c6b3961524caf"],"add":22,"del":22,"cadd":22,"cdel":22,"files":2},{"repo":"learning-area","hash":"4566c1b97ec433c16cef89ee57b176467185fa31","ts":1578152820,"wall":"2020-01-04T15:47","msg":"adding a toggle switch example","body":"","parents":["f92ff894bd69885ff99385b69bf8c767ecec4599"],"add":117,"del":0,"cadd":117,"cdel":0,"files":1},{"repo":"learning-area","hash":"577365b4d2bb4f09fecce428b9d6cfcf9546424a","ts":1578303662,"wall":"2020-01-06T09:41","msg":"adding basic input types example","body":"","parents":["4566c1b97ec433c16cef89ee57b176467185fa31"],"add":86,"del":1,"cadd":86,"cdel":1,"files":2},{"repo":"learning-area","hash":"e2009908ee037889d08bc77b5beb06519daeec12","ts":1578306327,"wall":"2020-01-06T10:25","msg":"adding basic input types example","body":"","parents":["577365b4d2bb4f09fecce428b9d6cfcf9546424a"],"add":4,"del":0,"cadd":4,"cdel":0,"files":1},{"repo":"learning-area","hash":"75be5a18d800cce381a24d9126aa738a64bc57c5","ts":1578310295,"wall":"2020-01-06T11:31","msg":"adding simple range example","body":"","parents":["e2009908ee037889d08bc77b5beb06519daeec12"],"add":75,"del":0,"cadd":75,"cdel":0,"files":1},{"repo":"learning-area","hash":"3a0c5b6a93e439cc5aca067295333ee3298572e6","ts":1578313566,"wall":"2020-01-06T12:26","msg":"adding color control example","body":"","parents":["75be5a18d800cce381a24d9126aa738a64bc57c5"],"add":65,"del":0,"cadd":65,"cdel":0,"files":1},{"repo":"learning-area","hash":"2de0ac5c5c86ab100bafa13ad2f318fa1259bcef","ts":1578326941,"wall":"2020-01-06T16:09","msg":"correcting usage of output element","body":"","parents":["3a0c5b6a93e439cc5aca067295333ee3298572e6"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"18c39fd80ab3d0166036b906bc5af59d0362aa5f","ts":1578661556,"wall":"2020-01-10T13:05","msg":"add more form examples","body":"","parents":["2de0ac5c5c86ab100bafa13ad2f318fa1259bcef"],"add":90,"del":2,"cadd":90,"cdel":2,"files":3},{"repo":"learning-area","hash":"1e1d62c252bf4160b613a30d59c57c12f8026d15","ts":1578665965,"wall":"2020-01-10T14:19","msg":"fixing up postcard example","body":"","parents":["18c39fd80ab3d0166036b906bc5af59d0362aa5f"],"add":15,"del":21,"cadd":15,"cdel":21,"files":2},{"repo":"learning-area","hash":"c4ecd96f43a21238863416d9d4321973e753c664","ts":1578682162,"wall":"2020-01-10T18:49","msg":"adding appearence example","body":"","parents":["1e1d62c252bf4160b613a30d59c57c12f8026d15"],"add":83,"del":0,"cadd":83,"cdel":0,"files":1},{"repo":"learning-area","hash":"2f7c6a984ba5177cb4acb26decbeed71e475de72","ts":1578682276,"wall":"2020-01-10T18:51","msg":"adding appearence example","body":"","parents":["c4ecd96f43a21238863416d9d4321973e753c664"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"f53f5494b0468dbde7b70490503c35fba3c62831","ts":1578689008,"wall":"2020-01-10T20:43","msg":"adding new appearence examples","body":"","parents":["2f7c6a984ba5177cb4acb26decbeed71e475de72"],"add":198,"del":20,"cadd":198,"cdel":20,"files":4},{"repo":"learning-area","hash":"8761713a36fca2b9fd111b37d1f277dad5f9efb3","ts":1578694187,"wall":"2020-01-10T22:09","msg":"adding radio button","body":"","parents":["f53f5494b0468dbde7b70490503c35fba3c62831"],"add":73,"del":5,"cadd":73,"cdel":5,"files":2},{"repo":"learning-area","hash":"9f8ceb179b2a605d74e32f68833e20b451dfb9e6","ts":1578745217,"wall":"2020-01-11T12:20","msg":"update radio example to include cubic-bezier animation","body":"","parents":["8761713a36fca2b9fd111b37d1f277dad5f9efb3"],"add":2,"del":1,"cadd":2,"cdel":1,"files":1},{"repo":"learning-area","hash":"1c0f95bee15d7a74a1fe5107b833021388f6ccff","ts":1578829433,"wall":"2020-01-12T11:43","msg":"add ugly controls example","body":"","parents":["9f8ceb179b2a605d74e32f68833e20b451dfb9e6"],"add":137,"del":0,"cadd":137,"cdel":0,"files":1},{"repo":"learning-area","hash":"809752a82c3143ce2ed1b3cbc4e183a9e4b3fae4","ts":1578830188,"wall":"2020-01-12T11:56","msg":"add ugly controls example","body":"","parents":["1c0f95bee15d7a74a1fe5107b833021388f6ccff"],"add":8,"del":0,"cadd":8,"cdel":0,"files":1},{"repo":"learning-area","hash":"2bc9894f5d4e4025d83e8bb0fc65d22ebdbc4d2e","ts":1578917412,"wall":"2020-01-13T12:10","msg":"making select look more similar cross browser","body":"","parents":["809752a82c3143ce2ed1b3cbc4e183a9e4b3fae4"],"add":16,"del":6,"cadd":16,"cdel":6,"files":1},{"repo":"learning-area","hash":"2500a5397e7d7a3e310260efd69e34f2611ec7c6","ts":1578919716,"wall":"2020-01-13T12:48","msg":"making select look more similar cross browser","body":"","parents":["2bc9894f5d4e4025d83e8bb0fc65d22ebdbc4d2e"],"add":0,"del":1,"cadd":0,"cdel":1,"files":1},{"repo":"learning-area","hash":"d3ea99af6e4bc62ee199026c1954f6b0826a9f93","ts":1578919884,"wall":"2020-01-13T12:51","msg":"making select look more similar cross browser","body":"","parents":["2500a5397e7d7a3e310260efd69e34f2611ec7c6"],"add":2,"del":3,"cadd":2,"cdel":3,"files":1},{"repo":"learning-area","hash":"f04d3b87d7e3d77552c8e87cddb0e7bdee2002bc","ts":1578921469,"wall":"2020-01-13T13:17","msg":"making select look more similar cross browser","body":"","parents":["d3ea99af6e4bc62ee199026c1954f6b0826a9f93"],"add":12,"del":13,"cadd":12,"cdel":13,"files":1},{"repo":"learning-area","hash":"522e56ecf675eb7c714b69c88b6d98458015e939","ts":1578939892,"wall":"2020-01-13T18:24","msg":"adding styled file picker","body":"","parents":["f04d3b87d7e3d77552c8e87cddb0e7bdee2002bc"],"add":107,"del":0,"cadd":107,"cdel":0,"files":1},{"repo":"learning-area","hash":"8b17c587ad4c5cba0398d862dfa0659bc9609a63","ts":1579008968,"wall":"2020-01-14T13:36","msg":"adding required and optional example","body":"","parents":["522e56ecf675eb7c714b69c88b6d98458015e939"],"add":85,"del":0,"cadd":85,"cdel":0,"files":1},{"repo":"learning-area","hash":"c8f626f1b52e6f7f44d89343cd7c8b507fb71bfa","ts":1579012763,"wall":"2020-01-14T14:39","msg":"adding required example with pseudo-classes","body":"","parents":["8b17c587ad4c5cba0398d862dfa0659bc9609a63"],"add":101,"del":0,"cadd":101,"cdel":0,"files":1},{"repo":"learning-area","hash":"0847d99657814ffdff65264a7e226823143f577e","ts":1579013437,"wall":"2020-01-14T14:50","msg":"adding required example with generated content","body":"","parents":["c8f626f1b52e6f7f44d89343cd7c8b507fb71bfa"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"cc694010c12c0be20843bbd65ea1ac6fd76b5e89","ts":1579018994,"wall":"2020-01-14T16:23","msg":"adding enabled/disabled example","body":"","parents":["0847d99657814ffdff65264a7e226823143f577e"],"add":135,"del":2,"cadd":135,"cdel":2,"files":2},{"repo":"learning-area","hash":"1d4c721ff473c1d8ec26ef4bbcd7393f9d8036fe","ts":1579025289,"wall":"2020-01-14T18:08","msg":"add :read-only example","body":"","parents":["cc694010c12c0be20843bbd65ea1ac6fd76b5e89"],"add":142,"del":22,"cadd":142,"cdel":22,"files":2},{"repo":"learning-area","hash":"1f6d137a7cc806fab9a512894a9d861b4e418e34","ts":1579088087,"wall":"2020-01-15T11:34","msg":"adding valid/invalid example","body":"","parents":["1d4c721ff473c1d8ec26ef4bbcd7393f9d8036fe"],"add":108,"del":0,"cadd":108,"cdel":0,"files":1},{"repo":"learning-area","hash":"3276b570dd13461dfd87efc060eeb2aab2f76cff","ts":1579090212,"wall":"2020-01-15T12:10","msg":"adding valid/invalid example","body":"","parents":["1f6d137a7cc806fab9a512894a9d861b4e418e34"],"add":17,"del":6,"cadd":17,"cdel":6,"files":1},{"repo":"learning-area","hash":"c69bb41ad619961fb1ae04d1aea7e19584a96bee","ts":1579092795,"wall":"2020-01-15T12:53","msg":"adding out-of-range example","body":"","parents":["3276b570dd13461dfd87efc060eeb2aab2f76cff"],"add":130,"del":0,"cadd":130,"cdel":0,"files":1},{"repo":"learning-area","hash":"79220dd6b7b2f89bd85e0cdedfd327104ee63034","ts":1579092969,"wall":"2020-01-15T12:56","msg":"adding out-of-range example","body":"","parents":["c69bb41ad619961fb1ae04d1aea7e19584a96bee"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"8c911a087027318c6dfd3505838818c2f723825f","ts":1579112185,"wall":"2020-01-15T18:16","msg":"adding :checked and :indeterminate examples","body":"","parents":["79220dd6b7b2f89bd85e0cdedfd327104ee63034"],"add":172,"del":0,"cadd":172,"cdel":0,"files":2},{"repo":"learning-area","hash":"0e56cb864c75e29f31031f029b8c113368c7241b","ts":1579182535,"wall":"2020-01-16T13:48","msg":"making updates to validation examples","body":"","parents":["8c911a087027318c6dfd3505838818c2f723825f"],"add":92,"del":6,"cadd":92,"cdel":6,"files":3},{"repo":"learning-area","hash":"9c74bef04c6345d72392b20963ff298f5883afa1","ts":1579187893,"wall":"2020-01-16T15:18","msg":"adding custom error message example","body":"","parents":["0e56cb864c75e29f31031f029b8c113368c7241b"],"add":38,"del":0,"cadd":38,"cdel":0,"files":1},{"repo":"learning-area","hash":"141bd011d2e380b215f6a987e63b5caacd1b8518","ts":1579200488,"wall":"2020-01-16T18:48","msg":"adding more complex custom validation example","body":"","parents":["9c74bef04c6345d72392b20963ff298f5883afa1"],"add":125,"del":0,"cadd":125,"cdel":0,"files":1},{"repo":"learning-area","hash":"6c9cd039b38d6912c1ee622ff2d0767bd503d64d","ts":1579201548,"wall":"2020-01-16T19:05","msg":"adding more complex custom validation example","body":"","parents":["141bd011d2e380b215f6a987e63b5caacd1b8518"],"add":26,"del":22,"cadd":26,"cdel":22,"files":1},{"repo":"learning-area","hash":"19f96a29b5a4debda617729b9e693190deb1a668","ts":1579201931,"wall":"2020-01-16T19:12","msg":"adding more complex custom validation example","body":"","parents":["6c9cd039b38d6912c1ee622ff2d0767bd503d64d"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"52d0d71acf1ef04e6d413bd4e637e8aa4d875b9b","ts":1579277743,"wall":"2020-01-17T16:15","msg":"updating styling on basic required example","body":"","parents":["19f96a29b5a4debda617729b9e693190deb1a668"],"add":4,"del":0,"cadd":4,"cdel":0,"files":1},{"repo":"learning-area","hash":"5791f9bf9ea5d5d719fa26c85058444a2a261a8f","ts":1579627335,"wall":"2020-01-21T17:22","msg":"adding javascript first steps examples","body":"","parents":["52d0d71acf1ef04e6d413bd4e637e8aa4d875b9b"],"add":1539,"del":0,"cadd":1539,"cdel":0,"files":30},{"repo":"learning-area","hash":"656e8413ea3e94b54ccad2d8267c22f218d3b2b5","ts":1579629587,"wall":"2020-01-21T17:59","msg":"small fix","body":"","parents":["5791f9bf9ea5d5d719fa26c85058444a2a261a8f"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"360088986aba92c278facb6a8e12a751020a5635","ts":1579884600,"wall":"2020-01-24T16:50","msg":"adding JS building blocks test your skills examples","body":"","parents":["656e8413ea3e94b54ccad2d8267c22f218d3b2b5"],"add":1664,"del":7,"cadd":1664,"cdel":7,"files":33},{"repo":"learning-area","hash":"5f3f516f0cf6d27c53e390159bed03523f565c6a","ts":1579905251,"wall":"2020-01-24T23:34","msg":"removing global variable products","body":"removing global variable in favour of passing variables between functions","parents":["8b17c587ad4c5cba0398d862dfa0659bc9609a63"],"add":4,"del":6,"cadd":4,"cdel":6,"files":1},{"repo":"learning-area","hash":"a1cfc8dd0bb0d77c140a8f3105212335e40e8dde","ts":1579906387,"wall":"2020-01-25T02:53","msg":"Merge pull request #1 from ughurh/ughurh-patch-1","body":"for consistency with the MDN web docs","parents":["71ed5ea2d383eac7fa901039b24c6b3961524caf","87333612ba451343eed8bc08ad84ad4cc6343cd1"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"1d18f72277547f4fa91dc9b21baaeab512931155","ts":1579953064,"wall":"2020-01-25T11:51","msg":"Merge pull request #182 from ughurh/master","body":"Swapped input and label order","parents":["360088986aba92c278facb6a8e12a751020a5635","a1cfc8dd0bb0d77c140a8f3105212335e40e8dde"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"7d07d89a99028199aadb71be3f482ceb722e861b","ts":1580031067,"wall":"2020-01-26T10:31","msg":"Fix duplicate id attribute in form input/label fields","body":"","parents":["1d18f72277547f4fa91dc9b21baaeab512931155"],"add":6,"del":6,"cadd":6,"cdel":6,"files":1},{"repo":"learning-area","hash":"9927f80202c0a15347a334a94022e3442a5a3010","ts":1580041540,"wall":"2020-01-26T12:25","msg":"Merge pull request #183 from 83C10/master","body":"Fix duplicate id attribute in form input/label fields","parents":["1d18f72277547f4fa91dc9b21baaeab512931155","7d07d89a99028199aadb71be3f482ceb722e861b"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"9db124c8277b0f9ad23b721b017537949f684977","ts":1580225620,"wall":"2020-01-28T16:33","msg":"fixing a few errors in the sample code","body":"","parents":["360088986aba92c278facb6a8e12a751020a5635"],"add":7,"del":6,"cadd":7,"cdel":6,"files":4},{"repo":"learning-area","hash":"1466fc0d13ff2c3b37e454560ceedd913d4e73bc","ts":1580225633,"wall":"2020-01-28T16:33","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["9db124c8277b0f9ad23b721b017537949f684977","9927f80202c0a15347a334a94022e3442a5a3010"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"83ffb71b6536f874c9eced99bd1309ba70b00aa4","ts":1580747574,"wall":"2020-02-03T16:32","msg":"fixing mistake in regex","body":"","parents":["1466fc0d13ff2c3b37e454560ceedd913d4e73bc"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"4522ea51466798b317d40840167274bee8b964d3","ts":1580813138,"wall":"2020-02-04T10:45","msg":"Merge pull request #181 from gitmrwick/179-productsvariable","body":"removing global variable products","parents":["83ffb71b6536f874c9eced99bd1309ba70b00aa4","5f3f516f0cf6d27c53e390159bed03523f565c6a"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"d492aedb2c4a52263eedb398e47feafecc69212f","ts":1580813870,"wall":"2020-02-04T10:57","msg":"fixing the xhr version of the can store demo","body":"","parents":["4522ea51466798b317d40840167274bee8b964d3"],"add":30,"del":32,"cadd":30,"cdel":32,"files":2},{"repo":"learning-area","hash":"7a44290ef8d7761ae461ed95ed7e56c3826f7349","ts":1581111235,"wall":"2020-02-07T16:33","msg":"Use same text as in marking-up-a-letter-start","body":"accomodate > accommodate\nlivestock or be \"fruitful\" > livestock to be fruitful\nimperceptably > imperceptibly\nexcellent > awesome","parents":["d492aedb2c4a52263eedb398e47feafecc69212f"],"add":4,"del":4,"cadd":4,"cdel":4,"files":1},{"repo":"learning-area","hash":"efbafa465d9fdf32e1c057f4c011bc047549bf4b","ts":1581311332,"wall":"2020-02-10T14:08","msg":"modernize file input example","body":"","parents":["d492aedb2c4a52263eedb398e47feafecc69212f"],"add":129,"del":134,"cadd":129,"cdel":134,"files":1},{"repo":"learning-area","hash":"6f081503c6f5b9b52eb23e74a39fcb90733220a5","ts":1581325141,"wall":"2020-02-10T08:59","msg":"Merge pull request #187 from alattalatta/master","body":"modernize file input example","parents":["d492aedb2c4a52263eedb398e47feafecc69212f","efbafa465d9fdf32e1c057f4c011bc047549bf4b"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"97a73fb399b4fcb5881dfce92c84829093c8270c","ts":1581333847,"wall":"2020-02-10T11:24","msg":"Merge pull request #186 from jrsnzc/master","body":"Use same text as in marking-up-a-letter-start file","parents":["6f081503c6f5b9b52eb23e74a39fcb90733220a5","7a44290ef8d7761ae461ed95ed7e56c3826f7349"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"3eba88109d882eb18cdf0b5436799e0edd7dae17","ts":1581518684,"wall":"2020-02-12T14:44","msg":"fixing position of add your code here line in MAth 1 skilltest","body":"","parents":["d492aedb2c4a52263eedb398e47feafecc69212f"],"add":8,"del":4,"cadd":8,"cdel":4,"files":2},{"repo":"learning-area","hash":"2e4719215fedfe170cf1f64307b33bbcb422736d","ts":1581525264,"wall":"2020-02-12T16:34","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["3eba88109d882eb18cdf0b5436799e0edd7dae17","97a73fb399b4fcb5881dfce92c84829093c8270c"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"918f815dc948ca265d2f4ab6c9de363c687e0edc","ts":1581525331,"wall":"2020-02-12T16:35","msg":"adding template literal skilltest to the strings tasks","body":"","parents":["2e4719215fedfe170cf1f64307b33bbcb422736d"],"add":119,"del":2,"cadd":119,"cdel":2,"files":3},{"repo":"learning-area","hash":"f1583cb31fd61384804226c95bec7d8e4a7ecd18","ts":1582119412,"wall":"2020-02-19T13:36","msg":"minor fix to accessibility assessment","body":"","parents":["918f815dc948ca265d2f4ab6c9de363c687e0edc"],"add":0,"del":1,"cadd":0,"cdel":1,"files":1},{"repo":"learning-area","hash":"e2f73fd9a0ed7747d9b8842bbb2de05c0fa79c6e","ts":1582301708,"wall":"2020-02-21T16:15","msg":"adding OOJS assessments","body":"","parents":["f1583cb31fd61384804226c95bec7d8e4a7ecd18"],"add":1056,"del":0,"cadd":1001,"cdel":0,"files":20},{"repo":"learning-area","hash":"5c53f6972bcdd27a44d2d32c6e1bb174e6e295e5","ts":1582308461,"wall":"2020-02-21T18:07","msg":"further fixes to oojs marking guide","body":"","parents":["e2f73fd9a0ed7747d9b8842bbb2de05c0fa79c6e"],"add":17,"del":17,"cadd":17,"cdel":17,"files":1},{"repo":"learning-area","hash":"907018148d22175bac7f2f1a333e4fabb6861715","ts":1582540225,"wall":"2020-02-24T10:30","msg":"small marking guide fixes","body":"","parents":["5c53f6972bcdd27a44d2d32c6e1bb174e6e295e5"],"add":4,"del":4,"cadd":4,"cdel":4,"files":2},{"repo":"learning-area","hash":"7a7fe1cc572dc3e56987d74cf248a1631f580a56","ts":1582894336,"wall":"2020-02-28T12:52","msg":"adding missing basic sync function example","body":"","parents":["907018148d22175bac7f2f1a333e4fabb6861715"],"add":20,"del":0,"cadd":20,"cdel":0,"files":1},{"repo":"learning-area","hash":"00f676da6c8680efa1247d95576b7174c7ad32b9","ts":1583814130,"wall":"2020-03-10T12:22","msg":"Correct function's name","body":"","parents":["7a7fe1cc572dc3e56987d74cf248a1631f580a56"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"6044bb4bc4ab28ed6df330e069ae2399115c5029","ts":1583828166,"wall":"2020-03-10T08:16","msg":"Merge pull request #190 from reuixiy/patch-1","body":"Correct function's name in comments","parents":["7a7fe1cc572dc3e56987d74cf248a1631f580a56","00f676da6c8680efa1247d95576b7174c7ad32b9"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"4b340bde7930e38ef56714dc9d835f082778fb5c","ts":1583950540,"wall":"2020-03-11T18:15","msg":"making some adjustments according to fscholz feedback. Thank you Florian!","body":"","parents":["7a7fe1cc572dc3e56987d74cf248a1631f580a56"],"add":10,"del":6,"cadd":10,"cdel":6,"files":4},{"repo":"learning-area","hash":"bd6e8083ff2aeb8d0a9da8054c186d932e3d08db","ts":1583950553,"wall":"2020-03-11T18:15","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["4b340bde7930e38ef56714dc9d835f082778fb5c","6044bb4bc4ab28ed6df330e069ae2399115c5029"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"350298afe21c5c007b04eb1776b9701b1b2d13f1","ts":1584013256,"wall":"2020-03-12T11:40","msg":"further improvements to ES Class inheritance example","body":"","parents":["bd6e8083ff2aeb8d0a9da8054c186d932e3d08db"],"add":4,"del":5,"cadd":4,"cdel":5,"files":1},{"repo":"learning-area","hash":"1983d8cee2df648d9833e1aeccc3b0625070830a","ts":1584357692,"wall":"2020-03-16T11:21","msg":"fixing conditionals assessment answer","body":"","parents":["350298afe21c5c007b04eb1776b9701b1b2d13f1"],"add":2,"del":6,"cadd":2,"cdel":6,"files":1},{"repo":"learning-area","hash":"f850fb9fffaa6d59b748aa6ada2f323dae98bfbc","ts":1584357810,"wall":"2020-03-16T11:23","msg":"fixing conditionals assessment answer","body":"","parents":["1983d8cee2df648d9833e1aeccc3b0625070830a"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"91e30b3e7b62f559aa657f38e5a21db7f1166186","ts":1584368382,"wall":"2020-03-16T08:19","msg":"Change var to const and let","body":"","parents":["1983d8cee2df648d9833e1aeccc3b0625070830a"],"add":60,"del":152,"cadd":60,"cdel":152,"files":3},{"repo":"learning-area","hash":"16bf84a86806407e0d76c33be8bc14ab9828598c","ts":1584383461,"wall":"2020-03-16T22:01","msg":"change the date format","body":"","parents":["f850fb9fffaa6d59b748aa6ada2f323dae98bfbc"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"916ee93ec850bc08a138231cb8c1e96d3bc0849c","ts":1584415963,"wall":"2020-03-17T11:32","msg":"Fix typo","body":"","parents":["7a7fe1cc572dc3e56987d74cf248a1631f580a56"],"add":3,"del":3,"cadd":3,"cdel":3,"files":1},{"repo":"learning-area","hash":"a90b844c89f3ae429634e9c9ba69b3cadb942aa8","ts":1584416181,"wall":"2020-03-17T11:36","msg":"Fix typo","body":"","parents":["916ee93ec850bc08a138231cb8c1e96d3bc0849c"],"add":3,"del":3,"cadd":3,"cdel":3,"files":1},{"repo":"learning-area","hash":"99b26d84c049cf3f4eab5379ec8dc357972867bc","ts":1584434401,"wall":"2020-03-17T08:40","msg":"Merge pull request #196 from reuixiy/master","body":"Fix typos","parents":["f850fb9fffaa6d59b748aa6ada2f323dae98bfbc","a90b844c89f3ae429634e9c9ba69b3cadb942aa8"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"6f5e6c7ff7216c69a92f9a8362a10533df80bca0","ts":1584437446,"wall":"2020-03-17T09:30","msg":"Merge pull request #195 from A-Faturechi/patch-1","body":"change the date format","parents":["99b26d84c049cf3f4eab5379ec8dc357972867bc","16bf84a86806407e0d76c33be8bc14ab9828598c"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"a0e5e40230ff672e19a59e83c870af898e16c5cc","ts":1584734408,"wall":"2020-03-20T14:00","msg":"did indenting","body":"","parents":["91e30b3e7b62f559aa657f38e5a21db7f1166186"],"add":244,"del":141,"cadd":244,"cdel":141,"files":2},{"repo":"learning-area","hash":"38886df580f1dbd368cbf0c6bac720cfb3e5aa46","ts":1584797764,"wall":"2020-03-21T07:36","msg":"removed line with json","body":"","parents":["a0e5e40230ff672e19a59e83c870af898e16c5cc"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"41314bf6f4fca35302b6bfbd8f487cd802582784","ts":1584964207,"wall":"2020-03-23T11:50","msg":"fixing result of math assessment","body":"","parents":["f850fb9fffaa6d59b748aa6ada2f323dae98bfbc"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"8206415ab7fa9467cd45b6e525c0f8716c012df0","ts":1584964217,"wall":"2020-03-23T11:50","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["41314bf6f4fca35302b6bfbd8f487cd802582784","6f5e6c7ff7216c69a92f9a8362a10533df80bca0"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"31b3ff0a62eb38659ef8eed6e1c9e9d69cb7ea2d","ts":1584964520,"wall":"2020-03-23T11:55","msg":"Merge pull request #194 from garcai/nytimes-example","body":"Change var to const and let","parents":["8206415ab7fa9467cd45b6e525c0f8716c012df0","38886df580f1dbd368cbf0c6bac720cfb3e5aa46"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"8d3be56c56950afe787b6217bc3993ebeab62e9c","ts":1585218279,"wall":"2020-03-26T12:24","msg":"Fix fisher-yates 🙈","body":"","parents":["97652099151eb94c8d0dca0d0885d0d3049ee948"],"add":6,"del":6,"cadd":6,"cdel":6,"files":1},{"repo":"deck-of-cards","hash":"a0800be41548636015556205813d56ff5aa0a0e9","ts":1585665473,"wall":"2020-03-31T17:37","msg":"Initial commit","body":"","parents":["10b0c45fe0f3f6a1e8c1723e1362f87d4af33c3b"],"add":1463,"del":1,"cadd":80,"cdel":0,"files":14},{"repo":"deck-of-cards","hash":"f129e7a2d655ac1d993781773d30b91fff57e90c","ts":1585676821,"wall":"2020-03-31T20:47","msg":"Add bg","body":"","parents":["a0800be41548636015556205813d56ff5aa0a0e9"],"add":0,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"76e2a40b6b435e667424074405938eb1b2bf8408","ts":1585676843,"wall":"2020-03-31T20:47","msg":"Start adding some CSS","body":"","parents":["f129e7a2d655ac1d993781773d30b91fff57e90c"],"add":37,"del":0,"cadd":37,"cdel":0,"files":4},{"repo":"deck-of-cards","hash":"8de4de7532c616331a5dd9f9f570bbd86d9b8603","ts":1585676856,"wall":"2020-03-31T20:47","msg":"pileCards method","body":"","parents":["76e2a40b6b435e667424074405938eb1b2bf8408"],"add":15,"del":0,"cadd":15,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"a61b38d80db71cd673fb6046e22fc6d283b48915","ts":1585676872,"wall":"2020-03-31T20:47","msg":"Start fiddling around with cards","body":"","parents":["8de4de7532c616331a5dd9f9f570bbd86d9b8603"],"add":20,"del":1,"cadd":20,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"8a95cbf72a95bf204485553cfda4c28808ca1ddd","ts":1585676876,"wall":"2020-03-31T20:47","msg":"Build","body":"","parents":["a61b38d80db71cd673fb6046e22fc6d283b48915"],"add":35,"del":2,"cadd":35,"cdel":2,"files":2},{"repo":"learning-area","hash":"e8a9fbe15a9a98002dc855c54ddfbfc3ae35f848","ts":1585833218,"wall":"2020-04-02T15:13","msg":"Async JS - catch() fix with Error()","body":"Fix to call catch() method when a HTTP error occurs. For example when the URL trying to be fetched is not valid.","parents":["31b3ff0a62eb38659ef8eed6e1c9e9d69cb7ea2d"],"add":10,"del":1,"cadd":10,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"98bd98180751fcf0e65ac9b095d226ed173b4b98","ts":1585916378,"wall":"2020-04-03T15:19","msg":"Add and use generated standard deck cards","body":"","parents":["8a95cbf72a95bf204485553cfda4c28808ca1ddd"],"add":48,"del":2,"cadd":47,"cdel":2,"files":61},{"repo":"deck-of-cards","hash":"aa2ed4dfe7a18c099660d589532d902f967339b5","ts":1585917012,"wall":"2020-04-03T15:30","msg":"Round to nearest pixel","body":"","parents":["98bd98180751fcf0e65ac9b095d226ed173b4b98"],"add":3,"del":3,"cadd":3,"cdel":3,"files":3},{"repo":"deck-of-cards","hash":"b4e9d9110fa9fa5dc83ab152dc7a000a17115d0a","ts":1585941549,"wall":"2020-04-03T22:19","msg":"Add viewport","body":"","parents":["aa2ed4dfe7a18c099660d589532d902f967339b5"],"add":2,"del":0,"cadd":2,"cdel":0,"files":1},{"repo":"deck-of-cards","hash":"5a113c64f976c07f27dbeb7168a16294acfde790","ts":1585944373,"wall":"2020-04-03T23:06","msg":"Create README.md","body":"","parents":["b4e9d9110fa9fa5dc83ab152dc7a000a17115d0a"],"add":11,"del":0,"cadd":11,"cdel":0,"files":1},{"repo":"learning-area","hash":"bfdb9d039d7140af22218faf1fd8d2a4ed4904af","ts":1585958706,"wall":"2020-04-03T20:05","msg":"Expand list of valid image types","body":"","parents":["31b3ff0a62eb38659ef8eed6e1c9e9d69cb7ea2d"],"add":11,"del":3,"cadd":11,"cdel":3,"files":1},{"repo":"learning-area","hash":"221e2375b90084b2bba4a50fda46e8e17cb60177","ts":1585993059,"wall":"2020-04-04T10:37","msg":"Merge pull request #203 from apoorva-sriv/patch-2","body":"Expand list of valid image types","parents":["31b3ff0a62eb38659ef8eed6e1c9e9d69cb7ea2d","bfdb9d039d7140af22218faf1fd8d2a4ed4904af"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"bd0b95969deb6c53d95171c5843e15a94c344508","ts":1586162247,"wall":"2020-04-06T09:37","msg":"Merge pull request #201 from VincentDaviet/learning-area-vda-pr","body":"Make catch() called if URL is misspelled, as mentionned in tutorial","parents":["221e2375b90084b2bba4a50fda46e8e17cb60177","e8a9fbe15a9a98002dc855c54ddfbfc3ae35f848"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"f20d8f795c92669dc64a6c59bb8884113c393c12","ts":1586319560,"wall":"2020-04-08T07:19","msg":"Refactor & stuff..","body":"","parents":["5a113c64f976c07f27dbeb7168a16294acfde790"],"add":198,"del":155,"cadd":198,"cdel":155,"files":72},{"repo":"deck-of-cards","hash":"7d289466d21212637e910d62ac651ab6bdd14529","ts":1586342849,"wall":"2020-04-08T13:47","msg":"Better stacking, include graphics","body":"","parents":["f20d8f795c92669dc64a6c59bb8884113c393c12"],"add":361,"del":44,"cadd":361,"cdel":44,"files":69},{"repo":"deck-of-cards","hash":"9a0a1be27092f28959aa6cfef6922e1f9f324150","ts":1586347652,"wall":"2020-04-08T15:07","msg":"Add touch support","body":"","parents":["7d289466d21212637e910d62ac651ab6bdd14529"],"add":32,"del":13,"cadd":32,"cdel":13,"files":5},{"repo":"deck-of-cards","hash":"0bce955f434d09b44ff0900c59ef3312b2be7e62","ts":1586378249,"wall":"2020-04-08T23:37","msg":"Fiddle with piles, add animations, make renderer use no CSS","body":"","parents":["9a0a1be27092f28959aa6cfef6922e1f9f324150"],"add":108,"del":66,"cadd":108,"cdel":66,"files":16},{"repo":"deck-of-cards","hash":"4f03f400a9491add47bd4d57c55666abe10632a1","ts":1586379884,"wall":"2020-04-09T00:04","msg":"Fix deck push","body":"","parents":["0bce955f434d09b44ff0900c59ef3312b2be7e62"],"add":12,"del":3,"cadd":12,"cdel":3,"files":2},{"repo":"deck-of-cards","hash":"f75168425e5b79bde56e4da48ed252b0537c1184","ts":1586411876,"wall":"2020-04-09T08:57","msg":"Pile vertically","body":"","parents":["4f03f400a9491add47bd4d57c55666abe10632a1"],"add":14,"del":7,"cadd":14,"cdel":7,"files":3},{"repo":"deck-of-cards","hash":"7bd025793a0fb015a921372e5bdc3176dfc20753","ts":1586422807,"wall":"2020-04-09T12:00","msg":"user-select none","body":"","parents":["f75168425e5b79bde56e4da48ed252b0537c1184"],"add":2,"del":0,"cadd":2,"cdel":0,"files":2},{"repo":"deck-of-cards","hash":"6e2889220a897e3c4649c76e00addd793d1d1654","ts":1586423295,"wall":"2020-04-09T12:08","msg":"Update dependencies","body":"","parents":["7bd025793a0fb015a921372e5bdc3176dfc20753"],"add":4,"del":4,"cadd":0,"cdel":0,"files":2},{"repo":"deck-of-cards","hash":"889ea54a750120fc8cf95914c10a3f7ac58a77d8","ts":1586450036,"wall":"2020-04-09T19:33","msg":"Don't use z for depth","body":"","parents":["6e2889220a897e3c4649c76e00addd793d1d1654"],"add":49,"del":52,"cadd":48,"cdel":51,"files":65},{"repo":"deck-of-cards","hash":"d8338cf8dbf741dd6b3bea73499ffb08e334e278","ts":1586454534,"wall":"2020-04-09T20:48","msg":"Use events, refactor","body":"","parents":["889ea54a750120fc8cf95914c10a3f7ac58a77d8"],"add":251,"del":214,"cadd":240,"cdel":208,"files":11},{"repo":"deck-of-cards","hash":"1125f611bf00a08108e316d65de07e81182d5fd0","ts":1586457499,"wall":"2020-04-09T21:38","msg":"Refactor rendering","body":"","parents":["d8338cf8dbf741dd6b3bea73499ffb08e334e278"],"add":60,"del":75,"cadd":60,"cdel":75,"files":5},{"repo":"deck-of-cards","hash":"a34b62d8cfcc602f525034f5731514b19b73e83e","ts":1586459579,"wall":"2020-04-09T22:12","msg":"Fix issue with addPile","body":"","parents":["1125f611bf00a08108e316d65de07e81182d5fd0"],"add":692,"del":19,"cadd":692,"cdel":19,"files":7},{"repo":"learning-area","hash":"4ec917e6cb3c9a90e5e99b10e8c49235a1bfc7ea","ts":1586519500,"wall":"2020-04-10T12:51","msg":"Correct Chemical Formula for Water","body":"Water has two hydrogen atoms and one oxygen atom, not 20 hydrogen atoms!","parents":["bd0b95969deb6c53d95171c5843e15a94c344508"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"3feb0689b66285fdf45db570113ee07499e011b5","ts":1586550136,"wall":"2020-04-10T21:22","msg":"Merge pull request #207 from JTansey93/patch-1","body":"Correct Chemical Formula for Water","parents":["bd0b95969deb6c53d95171c5843e15a94c344508","4ec917e6cb3c9a90e5e99b10e8c49235a1bfc7ea"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"cb54c28f675b6648f7e6bdec5291dea8309a23db","ts":1586720380,"wall":"2020-04-12T22:39","msg":"Refactor","body":"","parents":["a34b62d8cfcc602f525034f5731514b19b73e83e"],"add":206,"del":196,"cadd":206,"cdel":196,"files":6},{"repo":"deck-of-cards","hash":"585141b7f5072463f816b2a73b24ce754c1a2d36","ts":1586944128,"wall":"2020-04-15T12:48","msg":"Refactor","body":"","parents":["cb54c28f675b6648f7e6bdec5291dea8309a23db"],"add":686,"del":1071,"cadd":686,"cdel":1071,"files":132},{"repo":"deck-of-cards","hash":"3e69d3780fa7663d58de2cae0b4037340b88faf9","ts":1586947903,"wall":"2020-04-15T13:51","msg":"Add interaction","body":"","parents":["585141b7f5072463f816b2a73b24ce754c1a2d36"],"add":205,"del":85,"cadd":205,"cdel":85,"files":10},{"repo":"deck-of-cards","hash":"f82844008da0ac3b0288655cb4111de91df0ec24","ts":1586949712,"wall":"2020-04-15T14:21","msg":"Enhance performance","body":"","parents":["3e69d3780fa7663d58de2cae0b4037340b88faf9"],"add":4,"del":0,"cadd":4,"cdel":0,"files":3},{"repo":"deck-of-cards","hash":"02acb3246cae8f7e527862c2612e4cd062bc452d","ts":1586974288,"wall":"2020-04-15T21:11","msg":"Add piles etc","body":"","parents":["f82844008da0ac3b0288655cb4111de91df0ec24"],"add":590,"del":66,"cadd":590,"cdel":66,"files":17},{"repo":"learning-area","hash":"10137f33f2c3a8e56ff9b3a93e4b9f355e7b88c1","ts":1587121489,"wall":"2020-04-17T12:04","msg":"making number type test more foolproof","body":"","parents":["31b3ff0a62eb38659ef8eed6e1c9e9d69cb7ea2d"],"add":2,"del":2,"cadd":2,"cdel":2,"files":2},{"repo":"learning-area","hash":"1a20b80f35691afa4b53c8115de82f97e2ca815b","ts":1587121499,"wall":"2020-04-17T12:04","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["10137f33f2c3a8e56ff9b3a93e4b9f355e7b88c1","3feb0689b66285fdf45db570113ee07499e011b5"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"945988ea4d7f823a7efb15a2db9fa847dc7d11e1","ts":1587133729,"wall":"2020-04-17T17:28","msg":"Refactor","body":"","parents":["02acb3246cae8f7e527862c2612e4cd062bc452d"],"add":713,"del":1265,"cadd":713,"cdel":1265,"files":22},{"repo":"deck-of-cards","hash":"7a886c4506d3b04430648296491cc2b8077d64cc","ts":1587133979,"wall":"2020-04-17T17:32","msg":"Align cards and stage","body":"","parents":["945988ea4d7f823a7efb15a2db9fa847dc7d11e1"],"add":16,"del":4,"cadd":16,"cdel":4,"files":5},{"repo":"deck-of-cards","hash":"a92fd9399cbd1a71d736a54c4f55a6e85bf82623","ts":1587134341,"wall":"2020-04-17T17:39","msg":"Move card back to deck with animation","body":"","parents":["7a886c4506d3b04430648296491cc2b8077d64cc"],"add":82,"del":0,"cadd":82,"cdel":0,"files":4},{"repo":"learning-area","hash":"2969ee77497563454d4fffe6c6247051bf9d41c2","ts":1587135044,"wall":"2020-04-17T16:50","msg":"Refactor IF","body":"","parents":["1a20b80f35691afa4b53c8115de82f97e2ca815b"],"add":1,"del":3,"cadd":1,"cdel":3,"files":1},{"repo":"deck-of-cards","hash":"dacc824038741329db4a1071423a431e5bba06d1","ts":1587144796,"wall":"2020-04-17T20:33","msg":"Add piles","body":"","parents":["a92fd9399cbd1a71d736a54c4f55a6e85bf82623"],"add":190,"del":37,"cadd":190,"cdel":37,"files":7},{"repo":"deck-of-cards","hash":"b4c7aafe0a08c365c19711f04dec19f5c681a8b9","ts":1587146676,"wall":"2020-04-17T21:04","msg":"Fix piles","body":"","parents":["dacc824038741329db4a1071423a431e5bba06d1"],"add":25,"del":18,"cadd":25,"cdel":18,"files":3},{"repo":"deck-of-cards","hash":"b4d34272ffaa385512430089f557cbcb00e715e8","ts":1587204051,"wall":"2020-04-18T13:00","msg":"Refactor","body":"","parents":["b4c7aafe0a08c365c19711f04dec19f5c681a8b9"],"add":466,"del":184,"cadd":465,"cdel":183,"files":11},{"repo":"deck-of-cards","hash":"d3304066acd5a2b6d56125b5d46b1d0fc507f042","ts":1587323565,"wall":"2020-04-19T22:12","msg":"Refactor, fix shuffle","body":"","parents":["b4d34272ffaa385512430089f557cbcb00e715e8"],"add":169,"del":884,"cadd":166,"cdel":882,"files":14},{"repo":"deck-of-cards","hash":"6e78a9b2f880d94873a88d882d6c214637634aba","ts":1587323578,"wall":"2020-04-19T22:12","msg":"Remove console.log","body":"","parents":["d3304066acd5a2b6d56125b5d46b1d0fc507f042"],"add":1,"del":2,"cadd":1,"cdel":2,"files":2},{"repo":"deck-of-cards","hash":"0bc70b5300aa1b71f33b5419d5a84abc2d260599","ts":1587362072,"wall":"2020-04-20T08:54","msg":"Refactor mouse/touch event register","body":"","parents":["6e78a9b2f880d94873a88d882d6c214637634aba"],"add":6,"del":0,"cadd":6,"cdel":0,"files":2},{"repo":"deck-of-cards","hash":"1f49570ed0bc02df1073f1e7034ee45c1890be53","ts":1587366587,"wall":"2020-04-20T10:09","msg":"Fix touch events","body":"","parents":["0bc70b5300aa1b71f33b5419d5a84abc2d260599"],"add":61,"del":31,"cadd":61,"cdel":31,"files":6},{"repo":"deck-of-cards","hash":"dbf3d7e3833d3341d03aaa9fbef6317c275c2a38","ts":1587376074,"wall":"2020-04-20T12:47","msg":"Small refactor","body":"","parents":["1f49570ed0bc02df1073f1e7034ee45c1890be53"],"add":96,"del":96,"cadd":96,"cdel":96,"files":6},{"repo":"learning-area","hash":"0fe19ebacb42dea7f0f86cc635c4229d1c9936bd","ts":1587381508,"wall":"2020-04-20T12:18","msg":"Merge pull request #209 from VincentDaviet/pr-nyt-if-condition","body":"Refactor IF condition to make it more simple","parents":["1a20b80f35691afa4b53c8115de82f97e2ca815b","2969ee77497563454d4fffe6c6247051bf9d41c2"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"d272ecad2afdc8f7edfad3902007f0a94d549625","ts":1587381711,"wall":"2020-04-20T12:21","msg":"Revert \"Refactor IF condition to make it more simple\"","body":"","parents":["0fe19ebacb42dea7f0f86cc635c4229d1c9936bd"],"add":3,"del":1,"cadd":3,"cdel":1,"files":1},{"repo":"deck-of-cards","hash":"f04b38a0bae7f1a9904680efe712dcd61e34c6d0","ts":1588074995,"wall":"2020-04-28T14:56","msg":"Fix issue","body":"","parents":["dbf3d7e3833d3341d03aaa9fbef6317c275c2a38"],"add":17,"del":11,"cadd":16,"cdel":11,"files":5},{"repo":"learning-area","hash":"ee1e09d17f9d9301d44ddfa689bf922df9987e08","ts":1588336345,"wall":"2020-05-01T13:32","msg":"removing solution line from strings 1 download that is not supposed to be there ;-)","body":"","parents":["1a20b80f35691afa4b53c8115de82f97e2ca815b"],"add":0,"del":3,"cadd":0,"cdel":3,"files":1},{"repo":"learning-area","hash":"45e028417f828d95f16bbfffd2802191e38c7306","ts":1588336357,"wall":"2020-05-01T13:32","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["ee1e09d17f9d9301d44ddfa689bf922df9987e08","0fe19ebacb42dea7f0f86cc635c4229d1c9936bd"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"c48b3394c8cdb5f49243a86d5efc506c384e34ac","ts":1588527432,"wall":"2020-05-03T20:37","msg":"Corrected minor typo in planets data file","body":"","parents":["45e028417f828d95f16bbfffd2802191e38c7306"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"82eafa91d27b71783f0e01610938eb5b76ccaccd","ts":1588591087,"wall":"2020-05-04T12:18","msg":"Merge pull request #215 from dariusdv/master","body":"Corrected minor typo in planets data file","parents":["45e028417f828d95f16bbfffd2802191e38c7306","c48b3394c8cdb5f49243a86d5efc506c384e34ac"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"deck-of-cards","hash":"4be0f35a86af4ab9365be374a4ca242610d83a83","ts":1588618813,"wall":"2020-05-04T22:00","msg":"Let pile piles, update dependencies","body":"","parents":["f04b38a0bae7f1a9904680efe712dcd61e34c6d0"],"add":176,"del":246,"cadd":75,"cdel":42,"files":9},{"repo":"deck-of-cards","hash":"8e5c4ad3a615d875fcd894e37a89d1ea3ac110c9","ts":1588803113,"wall":"2020-05-07T01:11","msg":"Refactor","body":"","parents":["4be0f35a86af4ab9365be374a4ca242610d83a83"],"add":343,"del":202,"cadd":303,"cdel":107,"files":29},{"repo":"learning-area","hash":"e526e072aacb3ce12ebc377516b5266303db628d","ts":1588837862,"wall":"2020-05-07T09:51","msg":"Bring bouncing balls JS in line with tutorial text","body":"On https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_building_practice, the random function generates a number in [min, max], whereas in the provided main.js file it is [min, max).","parents":["82eafa91d27b71783f0e01610938eb5b76ccaccd"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"aa65af8e09e5fa8b1f8efd44ba852836ce96efb8","ts":1588838093,"wall":"2020-05-07T08:54","msg":"Merge pull request #217 from nfelger/master","body":"Bring bouncing balls JS in line with tutorial text","parents":["82eafa91d27b71783f0e01610938eb5b76ccaccd","e526e072aacb3ce12ebc377516b5266303db628d"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"d4f1c19d1519ebeeae29f2c1eb1b9fe1301d4828","ts":1588844091,"wall":"2020-05-07T11:34","msg":"Copy update from main.js to other main-*.js files","body":"","parents":["e526e072aacb3ce12ebc377516b5266303db628d"],"add":5,"del":5,"cadd":5,"cdel":5,"files":2},{"repo":"learning-area","hash":"72d7a7ec82942a0daed186c3b1dabff4a020d349","ts":1588845333,"wall":"2020-05-07T10:55","msg":"Merge pull request #218 from nfelger/master","body":"Copy update from main.js to other main-*.js files","parents":["aa65af8e09e5fa8b1f8efd44ba852836ce96efb8","d4f1c19d1519ebeeae29f2c1eb1b9fe1301d4828"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"a22f7f6d65e5f78999aca09f163edc89e6326513","ts":1589749226,"wall":"2020-05-17T22:00","msg":"fixing syntax error in marking guide","body":"","parents":["45e028417f828d95f16bbfffd2802191e38c7306"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"1ab6c99a3897d2a80b396beb3d4e11a95e2ac48c","ts":1589749236,"wall":"2020-05-17T22:00","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["a22f7f6d65e5f78999aca09f163edc89e6326513","72d7a7ec82942a0daed186c3b1dabff4a020d349"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"f02051166d254917c53a420b520126eacf50d85a","ts":1589903743,"wall":"2020-05-19T16:55","msg":"fixing promise examples to reject 404 errors correctly","body":"","parents":["1ab6c99a3897d2a80b396beb3d4e11a95e2ac48c"],"add":27,"del":10,"cadd":27,"cdel":10,"files":4},{"repo":"learning-area","hash":"a499489bb4532152e5b0a985c85459a477a7ff52","ts":1589907346,"wall":"2020-05-19T17:55","msg":"fixing async/await examples to reject 404 errors correctly","body":"","parents":["f02051166d254917c53a420b520126eacf50d85a"],"add":57,"del":26,"cadd":57,"cdel":26,"files":6},{"repo":"learning-area","hash":"3f303379a8fd2da19ee6a37904a4a16e98d51d40","ts":1589995489,"wall":"2020-05-20T18:24","msg":"addinf form structure test your skills files","body":"","parents":["a499489bb4532152e5b0a985c85459a477a7ff52"],"add":231,"del":0,"cadd":231,"cdel":0,"files":5},{"repo":"learning-area","hash":"bb313f7ba04cf66f3db3c7aca11639aa56bc8902","ts":1590029290,"wall":"2020-05-21T09:48","msg":"Update 6_fixed-positioning.html","body":"centering an element using margin: 0 auto; doesn't work without the explicit left: 0 and right: 0 combination (in case we want to center the element within the full viewport width)","parents":["3f303379a8fd2da19ee6a37904a4a16e98d51d40"],"add":0,"del":1,"cadd":0,"cdel":1,"files":1},{"repo":"learning-area","hash":"63a280c4ddb880672c457e400cfc852f500d3b8d","ts":1590047623,"wall":"2020-05-21T14:53","msg":"Update 6_fixed-positioning.html","body":"","parents":["bb313f7ba04cf66f3db3c7aca11639aa56bc8902"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"8032912ad8a9d5742e4521a9a7091999e21ff0fc","ts":1590047815,"wall":"2020-05-21T14:56","msg":"Update 6_fixed-positioning.html","body":"","parents":["63a280c4ddb880672c457e400cfc852f500d3b8d"],"add":2,"del":1,"cadd":2,"cdel":1,"files":1},{"repo":"learning-area","hash":"f3fa5bb1cb4b6b928594d2552827b68c64811906","ts":1590047889,"wall":"2020-05-21T14:58","msg":"Update 6_fixed-positioning.html","body":"","parents":["8032912ad8a9d5742e4521a9a7091999e21ff0fc"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"2149dbb29f083aaa06607b1622c13b37c13d52f8","ts":1590050539,"wall":"2020-05-21T09:42","msg":"Merge pull request #221 from haond10adp/patch-1","body":"Update 6_fixed-positioning.html","parents":["3f303379a8fd2da19ee6a37904a4a16e98d51d40","f3fa5bb1cb4b6b928594d2552827b68c64811906"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"4ab18b124ca94db57b5a42afc87322b0e4dcb050","ts":1590056760,"wall":"2020-05-21T11:26","msg":"forms assessments work, plus fixing a JS assessment","body":"","parents":["3f303379a8fd2da19ee6a37904a4a16e98d51d40"],"add":494,"del":64,"cadd":494,"cdel":64,"files":12},{"repo":"learning-area","hash":"b16f0aee43db9d4801c59aa526fe6208cbf8da1f","ts":1590056802,"wall":"2020-05-21T11:26","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["4ab18b124ca94db57b5a42afc87322b0e4dcb050","2149dbb29f083aaa06607b1622c13b37c13d52f8"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"6edb605c648249dd3aad4cde18e5894cbc78b689","ts":1590062654,"wall":"2020-05-21T13:04","msg":"adding html5 control assessments","body":"","parents":["b16f0aee43db9d4801c59aa526fe6208cbf8da1f"],"add":304,"del":0,"cadd":304,"cdel":0,"files":5},{"repo":"learning-area","hash":"d0e8d557d5a18313e20d00d77b873b41d3982c7e","ts":1590067738,"wall":"2020-05-21T14:28","msg":"adding other form control assessment examples","body":"","parents":["6edb605c648249dd3aad4cde18e5894cbc78b689"],"add":430,"del":0,"cadd":430,"cdel":0,"files":7},{"repo":"learning-area","hash":"5866cfd4f0373ed5f12d018ed5826fcc9dd9ffcf","ts":1590091121,"wall":"2020-05-21T20:58","msg":"adding form styling assessment","body":"","parents":["d0e8d557d5a18313e20d00d77b873b41d3982c7e"],"add":137,"del":3,"cadd":137,"cdel":3,"files":3},{"repo":"learning-area","hash":"3a19f150be275cd37b89cbf62d13db1e5fa6fbf6","ts":1590091684,"wall":"2020-05-21T21:08","msg":"small update","body":"","parents":["5866cfd4f0373ed5f12d018ed5826fcc9dd9ffcf"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"8c9e5cd02bda4c109082332eb6885fd4e3755de2","ts":1590167988,"wall":"2020-05-22T18:19","msg":"adding advanced form styling assessments","body":"","parents":["3a19f150be275cd37b89cbf62d13db1e5fa6fbf6"],"add":567,"del":0,"cadd":567,"cdel":0,"files":7},{"repo":"learning-area","hash":"4a329c54fff9dc77cd5881b31be4eb3731e6bd93","ts":1590168943,"wall":"2020-05-22T18:35","msg":"couple of typo fixes","body":"","parents":["8c9e5cd02bda4c109082332eb6885fd4e3755de2"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"9316c6f7ce2d1d25f512dd70e517526f9671d178","ts":1590246677,"wall":"2020-05-23T16:11","msg":"adding form validation assessments","body":"","parents":["4a329c54fff9dc77cd5881b31be4eb3731e6bd93"],"add":252,"del":0,"cadd":252,"cdel":0,"files":4},{"repo":"learning-area","hash":"92d54772b314836bcbd1b01bdef849d0ec509457","ts":1590248515,"wall":"2020-05-23T16:41","msg":"typo and grammar fixes","body":"","parents":["9316c6f7ce2d1d25f512dd70e517526f9671d178"],"add":5,"del":7,"cadd":5,"cdel":7,"files":1},{"repo":"learning-area","hash":"2149db4bb944437a866e5651452b6bca290891b6","ts":1590344222,"wall":"2020-05-24T19:17","msg":"Merge pull request #210 from mdn/revert-209-pr-nyt-if-condition","body":"Revert \"Refactor IF condition to make it more simple\"","parents":["92d54772b314836bcbd1b01bdef849d0ec509457","d272ecad2afdc8f7edfad3902007f0a94d549625"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"dd20fb8127447f85be49ae5a233c364dac04dd62","ts":1590763989,"wall":"2020-05-29T08:53","msg":"Without tabIndex the canvas can't get focus","body":"Without tabIndex the canvas can't get focus and the exercise won't work (without changing the code above `// add your code here`","parents":["2149db4bb944437a866e5651452b6bca290891b6"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"9624224ceb55e6aa4c02d1f9ebda629bf032159c","ts":1591166809,"wall":"2020-06-03T12:16","msg":"Put script inside head and use defer attribute","body":"The tutorial recommends this as the best way - hence, the code should use that method rather than using <script> before the closing body tag.","parents":["2149db4bb944437a866e5651452b6bca290891b6"],"add":3,"del":2,"cadd":3,"cdel":2,"files":1},{"repo":"learning-area","hash":"b3a76f80d04b381717efdd985323ed1d26f5b241","ts":1591169488,"wall":"2020-06-03T08:31","msg":"Merge pull request #223 from siraj-samsudeen/patch-1","body":"Put script inside head and use defer attribute","parents":["2149db4bb944437a866e5651452b6bca290891b6","9624224ceb55e6aa4c02d1f9ebda629bf032159c"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"ce12528e1d5b2603076eca13046b785df9cd894c","ts":1591219621,"wall":"2020-06-03T15:27","msg":"added tabindes to the normal example","body":"","parents":["dd20fb8127447f85be49ae5a233c364dac04dd62"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"cbedbac72184268d36bc4eb9c506ca9a87e411fe","ts":1591251757,"wall":"2020-06-04T07:22","msg":"Merge pull request #222 from KjellKod/patch-1","body":"events2 exercise: Without tabIndex the canvas can't get focus","parents":["b3a76f80d04b381717efdd985323ed1d26f5b241","ce12528e1d5b2603076eca13046b785df9cd894c"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"fa34a676dca089c3cfb860ced3ea3edcd6f47982","ts":1591278664,"wall":"2020-06-04T14:51","msg":"add promise any() example, update read-only and read-write pseudo example","body":"","parents":["92d54772b314836bcbd1b01bdef849d0ec509457"],"add":45,"del":11,"cadd":45,"cdel":11,"files":2},{"repo":"learning-area","hash":"1aff9a2f7f35f7e6c1180837969a062ab3941819","ts":1591278677,"wall":"2020-06-04T14:51","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["fa34a676dca089c3cfb860ced3ea3edcd6f47982","cbedbac72184268d36bc4eb9c506ca9a87e411fe"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"d0d1e2f8beee81818d0905c9e86c1d0f59ee2e31","ts":1591281051,"wall":"2020-06-04T17:30","msg":"Use const instead of var as according to best practices","body":"","parents":["1aff9a2f7f35f7e6c1180837969a062ab3941819"],"add":6,"del":6,"cadd":6,"cdel":6,"files":1},{"repo":"learning-area","hash":"3ae3a0e207a81d764fa8f9b2735f9a73ae2fd560","ts":1591356975,"wall":"2020-06-05T12:36","msg":"Merge pull request #226 from avivmu/master","body":"Use const instead of var as according to best practices","parents":["1aff9a2f7f35f7e6c1180837969a062ab3941819","d0d1e2f8beee81818d0905c9e86c1d0f59ee2e31"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"fbf4fc4140e25234c4be010d49c168bacdfc85de","ts":1591631761,"wall":"2020-06-08T18:56","msg":"Add language to html tag and encode \"|\" in the URL\"","body":"","parents":["3ae3a0e207a81d764fa8f9b2735f9a73ae2fd560"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"f133d6ee179950658797e6f4b09b1dec90eb7752","ts":1591645321,"wall":"2020-06-08T20:42","msg":"Merge pull request #229 from avivmu/master","body":"Add language to html tag and encode \"|\" in the URL\"","parents":["3ae3a0e207a81d764fa8f9b2735f9a73ae2fd560","fbf4fc4140e25234c4be010d49c168bacdfc85de"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"51fca7ece64f9406e8e418002112a45d9f993985","ts":1591877462,"wall":"2020-06-11T13:11","msg":"fixing broken json example","body":"","parents":["1aff9a2f7f35f7e6c1180837969a062ab3941819"],"add":13,"del":7,"cadd":13,"cdel":7,"files":4},{"repo":"learning-area","hash":"599fa97c232efb49c2568fc146cc80da92a9a6b6","ts":1591877473,"wall":"2020-06-11T13:11","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["51fca7ece64f9406e8e418002112a45d9f993985","f133d6ee179950658797e6f4b09b1dec90eb7752"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"06bc02e718378debdd1421e334757ad52320a199","ts":1592179200,"wall":"2020-06-14T17:00","msg":"Corrected capitalization on Sham69 track name","body":"Updated the capitalization Sham 69's \"If The Kids Are United\" track on\nmatch conventional capitalization and, more importantly, match the\ntrack name in the punk-bands-completed.html file that tutorial users\nwill be comparing against.\n\nAlso added the \"lang\" attribute to the html tags on both files to\nappease the Nu Html Checker.","parents":["599fa97c232efb49c2568fc146cc80da92a9a6b6"],"add":3,"del":3,"cadd":3,"cdel":3,"files":2},{"repo":"learning-area","hash":"95fd349d2c32070a2f488182c1348c1c4ed1997b","ts":1592179200,"wall":"2020-06-14T17:00","msg":"Update punk-bands-unstyled.html","body":"Updated track title on \"If The Kids Are United\" to match the conventional capitalization, which is used in the punk-bands-complete.html file.","parents":["599fa97c232efb49c2568fc146cc80da92a9a6b6"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"ee2c5e8d69277abf8b48dad92e511bc185371b9f","ts":1592245655,"wall":"2020-06-15T11:27","msg":"Update punk-bands-unstyled.html","body":"Added lang to html tag to pass Nu Html Checker.","parents":["95fd349d2c32070a2f488182c1348c1c4ed1997b"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"c31f7877572615bba395ca645630990c085ad054","ts":1592245658,"wall":"2020-06-15T11:27","msg":"Update punk-bands-complete.html","body":"Added lang to html tag to pass Nu Html Checker.","parents":["ee2c5e8d69277abf8b48dad92e511bc185371b9f"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"62dd85f2ac69225eb4427483821f4c72ccfa94c6","ts":1592255760,"wall":"2020-06-15T14:16","msg":"Merge branch 'patch-2' of https://github.com/vgiffin/learning-area into patch-2","body":"","parents":["06bc02e718378debdd1421e334757ad52320a199","c31f7877572615bba395ca645630990c085ad054"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"01ca14104b503e005250d28bbca694bb10f2a403","ts":1592289202,"wall":"2020-06-16T07:33","msg":"Merge pull request #230 from vgiffin/patch-2","body":"Update punk-bands-unstyled.html","parents":["599fa97c232efb49c2568fc146cc80da92a9a6b6","62dd85f2ac69225eb4427483821f4c72ccfa94c6"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"3bb50636b201f9b2a136bf10dad96e72abdac18e","ts":1592557511,"wall":"2020-06-19T13:35","msg":"End the game on \"a\" or \"l\" only","body":"Based on the description on MDN, pressing a wrong key shouldn't end the game, right?\n\n> Regardless of which one of the player control keys was pressed, remove the `keydown` event listener using `removeEventListener()` so that once the winning press has happened, no more keyboard input is possible to mess up the final game result.","parents":["01ca14104b503e005250d28bbca694bb10f2a403"],"add":10,"del":4,"cadd":10,"cdel":4,"files":1},{"repo":"learning-area","hash":"efb6d977386b21991f09b413de28c64deda698d4","ts":1592816378,"wall":"2020-06-22T09:59","msg":"Merge pull request #231 from mrmowji/patch-1","body":"End the game on \"a\" or \"l\" only","parents":["01ca14104b503e005250d28bbca694bb10f2a403","3bb50636b201f9b2a136bf10dad96e72abdac18e"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"7b388a83d64aaf792980d1ec8ac5ae372fe4fb4b","ts":1592818881,"wall":"2020-06-22T10:41","msg":"various fixes","body":"","parents":["efb6d977386b21991f09b413de28c64deda698d4"],"add":27,"del":7,"cadd":27,"cdel":7,"files":5},{"repo":"learning-area","hash":"7255678614b4aaabf4d9d58bb4ca1a62434a3ab8","ts":1593157575,"wall":"2020-06-26T08:46","msg":"using better answer","body":"","parents":["7b388a83d64aaf792980d1ec8ac5ae372fe4fb4b"],"add":5,"del":11,"cadd":5,"cdel":11,"files":1},{"repo":"learning-area","hash":"0380200b9553cb3c14ed364632986d1ae04d8ea8","ts":1593176394,"wall":"2020-06-26T08:59","msg":"create ajax-finish.html","body":"To accompany the ajax-start.html file as a reference for completion.","parents":["7255678614b4aaabf4d9d58bb4ca1a62434a3ab8"],"add":94,"del":0,"cadd":94,"cdel":0,"files":1},{"repo":"learning-area","hash":"295f4373de339103d00bef550f302e518f72097d","ts":1593177765,"wall":"2020-06-26T14:22","msg":"Merge pull request #233 from lacunablue/patch-1","body":"create ajax-finish.html","parents":["7255678614b4aaabf4d9d58bb4ca1a62434a3ab8","0380200b9553cb3c14ed364632986d1ae04d8ea8"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"2ff48a37b8b9bc630f3be6de648dfab4dd4575b8","ts":1593508298,"wall":"2020-06-30T10:11","msg":"fixing error with resetting button on track end","body":"","parents":["7255678614b4aaabf4d9d58bb4ca1a62434a3ab8"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"613f9a87bd100a92434b9b9d605878642766bc5d","ts":1593508313,"wall":"2020-06-30T10:11","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["2ff48a37b8b9bc630f3be6de648dfab4dd4575b8","295f4373de339103d00bef550f302e518f72097d"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"20450ea6447cacde6f7f1c08a4f32aa214a05efa","ts":1593703686,"wall":"2020-07-02T10:28","msg":"fix a link error","body":"changes hpt to http","parents":["613f9a87bd100a92434b9b9d605878642766bc5d"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"2d227a9972f8b7dc0a90160671ad84693938aa01","ts":1593704062,"wall":"2020-07-02T16:34","msg":"Merge pull request #236 from qiaoxt/patch-2","body":"fix a link error","parents":["613f9a87bd100a92434b9b9d605878642766bc5d","20450ea6447cacde6f7f1c08a4f32aa214a05efa"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"361c2866dbdbb35e30ae1ae304cb8e4ea28d5a16","ts":1593705637,"wall":"2020-07-02T11:00","msg":"fix a link error","body":"changes htp to http","parents":["2d227a9972f8b7dc0a90160671ad84693938aa01"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"62e693b7be2462e800e8051d681273fb13c67ec3","ts":1593776313,"wall":"2020-07-03T12:38","msg":"Merge pull request #237 from qiaoxt/patch-3","body":"fix a link error","parents":["2d227a9972f8b7dc0a90160671ad84693938aa01","361c2866dbdbb35e30ae1ae304cb8e4ea28d5a16"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"6842ea3b0e029a626ad382fa3685ecec2720d6d4","ts":1593961050,"wall":"2020-07-05T15:57","msg":"Merge pull request #131 from hu-tmx/patch-2","body":"use Object.defineProperty as in tutorial docs","parents":["62e693b7be2462e800e8051d681273fb13c67ec3","67320f9c2a3965b63acb9e90710f8bd5a42a7f07"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"b9c031b0f861a1a73d5f5ce9304a9019e79a3205","ts":1594313935,"wall":"2020-07-09T17:58","msg":"adding a11y assessment tasks structure and html a11t tasks","body":"","parents":["6842ea3b0e029a626ad382fa3685ecec2720d6d4"],"add":2389,"del":0,"cadd":2389,"cdel":0,"files":43},{"repo":"learning-area","hash":"ee8a5bd23f73c3d985161b6501eb44996eca0dff","ts":1594314107,"wall":"2020-07-09T18:01","msg":"removing unneeded files","body":"","parents":["b9c031b0f861a1a73d5f5ce9304a9019e79a3205"],"add":0,"del":1325,"cadd":0,"cdel":1325,"files":27},{"repo":"learning-area","hash":"5e3f6a4ecb07a63d36888658b9652588c24bcd50","ts":1594646469,"wall":"2020-07-13T14:21","msg":"adding CSS and JS a11y tests","body":"","parents":["ee8a5bd23f73c3d985161b6501eb44996eca0dff"],"add":406,"del":186,"cadd":406,"cdel":186,"files":13},{"repo":"learning-area","hash":"8cdd087710d8f3901eb3f6489973ffb3ccd0197f","ts":1594659690,"wall":"2020-07-13T18:01","msg":"adding wai-aria skill tests","body":"","parents":["5e3f6a4ecb07a63d36888658b9652588c24bcd50"],"add":341,"del":1,"cadd":341,"cdel":1,"files":7},{"repo":"learning-area","hash":"f9872766417486a55518b2100b1b4a8aceabce1e","ts":1595068313,"wall":"2020-07-18T13:31","msg":"removing redundant lines","body":"removed task1 lines from task2 file to avoid confusion","parents":["8cdd087710d8f3901eb3f6489973ffb3ccd0197f"],"add":0,"del":5,"cadd":0,"cdel":5,"files":1},{"repo":"learning-area","hash":"4f8f09c852b2d98c86c759c25228f7df6c480e74","ts":1595084142,"wall":"2020-07-18T17:55","msg":"Added a missing element name","body":"","parents":["8cdd087710d8f3901eb3f6489973ffb3ccd0197f"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"547c3bd60fc38ee83924fa2b2b2fd908395f300d","ts":1595227683,"wall":"2020-07-20T12:18","msg":"Vocabulary error ","body":"Changes Applying Javascript example to External Javascript Example","parents":["8cdd087710d8f3901eb3f6489973ffb3ccd0197f"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"4fc3bf786a41e12c388fbde864356b7c1b4ad741","ts":1595231996,"wall":"2020-07-20T08:59","msg":"Merge pull request #244 from avivmu/master","body":"Added a missing element name","parents":["8cdd087710d8f3901eb3f6489973ffb3ccd0197f","4f8f09c852b2d98c86c759c25228f7df6c480e74"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"c19ccd6715227bfc4ec1c12c888707cb3ed5f8b3","ts":1595232918,"wall":"2020-07-20T09:15","msg":"Merge pull request #243 from Sonntag09/patch-1","body":"removing redundant lines","parents":["4fc3bf786a41e12c388fbde864356b7c1b4ad741","f9872766417486a55518b2100b1b4a8aceabce1e"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"ac89e4b73a6b6bdeeb7f83d94c6a92dc7523bec6","ts":1595233656,"wall":"2020-07-20T13:57","msg":"Updated Apply Javascript Example to Internal JavaScript Example","body":"","parents":["c19ccd6715227bfc4ec1c12c888707cb3ed5f8b3"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"6e0ceb4e5284be74878ffc8d0efc5293b61cf761","ts":1595233754,"wall":"2020-07-20T09:29","msg":"Merge pull request #249 from himanshujaidka/patch-3","body":"Updated title","parents":["c19ccd6715227bfc4ec1c12c888707cb3ed5f8b3","ac89e4b73a6b6bdeeb7f83d94c6a92dc7523bec6"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"812560fdc468555a3b1b12ddf2923cda73074021","ts":1595233788,"wall":"2020-07-20T09:29","msg":"Merge pull request #248 from himanshujaidka/patch-2","body":"Vocabulary error","parents":["6e0ceb4e5284be74878ffc8d0efc5293b61cf761","547c3bd60fc38ee83924fa2b2b2fd908395f300d"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"16111951dff8874ee2f6e6c7f30cb019e64d9e4a","ts":1595237933,"wall":"2020-07-20T10:38","msg":"removing line that isnt supposed to be there in the starter file","body":"","parents":["812560fdc468555a3b1b12ddf2923cda73074021"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"d738c2f38b40bdb110da011b9dd53528a15e81e3","ts":1595493699,"wall":"2020-07-23T11:41","msg":"Add a missing word to a paragraph text","body":"","parents":["16111951dff8874ee2f6e6c7f30cb019e64d9e4a"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"1e7dda862a83398ede8a7188bff1f49f2dd45176","ts":1595498941,"wall":"2020-07-23T11:09","msg":"Merge pull request #251 from avivmu/master","body":"Add a missing word to a paragraph text","parents":["16111951dff8874ee2f6e6c7f30cb019e64d9e4a","d738c2f38b40bdb110da011b9dd53528a15e81e3"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"cddf821db23a869b9fd4ab704c0f1466a327d048","ts":1595709530,"wall":"2020-07-25T16:38","msg":"Insert empty line","body":"Insert empty line before </script> for repo continuity","parents":["1e7dda862a83398ede8a7188bff1f49f2dd45176"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"learning-area","hash":"1ba9a43aa39d06a95b5ff45e3506dca61a0b828f","ts":1595709595,"wall":"2020-07-25T16:39","msg":"Insert empty line","body":"Insert empty line before </script> for continuity","parents":["1e7dda862a83398ede8a7188bff1f49f2dd45176"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"learning-area","hash":"1bd26006ebe5e1dd02dfc93ca829678a038fc999","ts":1595709758,"wall":"2020-07-25T16:42","msg":"Insert empty line","body":"Insert empty line before </script> for repo continuity","parents":["1e7dda862a83398ede8a7188bff1f49f2dd45176"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"learning-area","hash":"94ec70fc1af694496ef3f652797fb5e5cd6f6d27","ts":1595710834,"wall":"2020-07-25T17:00","msg":"update white space","body":"Update white space for continuity. Code tested, working","parents":["1e7dda862a83398ede8a7188bff1f49f2dd45176"],"add":4,"del":6,"cadd":4,"cdel":6,"files":1},{"repo":"learning-area","hash":"2938420493ea044cd8034a9d1d9e59c092b39b4f","ts":1595711094,"wall":"2020-07-25T17:04","msg":"update whitespace","body":"update whitespace for continuity","parents":["1e7dda862a83398ede8a7188bff1f49f2dd45176"],"add":4,"del":5,"cadd":4,"cdel":5,"files":1},{"repo":"learning-area","hash":"93b7ece243621d522000c58306ae814ce4a1cf24","ts":1595760837,"wall":"2020-07-26T11:53","msg":"Merge pull request #253 from tim-andes/patch-2","body":"Insert empty line","parents":["1e7dda862a83398ede8a7188bff1f49f2dd45176","cddf821db23a869b9fd4ab704c0f1466a327d048"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"d64a895b46eeb42e6cd5e7eb6d1bd541efc1c3ef","ts":1595760895,"wall":"2020-07-26T11:54","msg":"Merge pull request #257 from tim-andes/patch-6","body":"update whitespace","parents":["93b7ece243621d522000c58306ae814ce4a1cf24","2938420493ea044cd8034a9d1d9e59c092b39b4f"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"f8503e5a8c9eed955ffe9c5b125d0a8e711d0e62","ts":1595760915,"wall":"2020-07-26T11:55","msg":"Merge pull request #256 from tim-andes/patch-5","body":"update white space","parents":["d64a895b46eeb42e6cd5e7eb6d1bd541efc1c3ef","94ec70fc1af694496ef3f652797fb5e5cd6f6d27"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"0bb0643b85cc1d5cf517bba930f078ee194fc34f","ts":1595760946,"wall":"2020-07-26T11:55","msg":"Merge pull request #255 from tim-andes/patch-4","body":"Insert empty line","parents":["f8503e5a8c9eed955ffe9c5b125d0a8e711d0e62","1bd26006ebe5e1dd02dfc93ca829678a038fc999"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"4121209d219cfeb3f4b10800188890e611ddd2ed","ts":1595760983,"wall":"2020-07-26T11:56","msg":"Merge pull request #254 from tim-andes/patch-3","body":"Insert empty line","parents":["0bb0643b85cc1d5cf517bba930f078ee194fc34f","1ba9a43aa39d06a95b5ff45e3506dca61a0b828f"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"92a9e0e61c0a0122053f298b5a0a6401fbe44c40","ts":1597899063,"wall":"2020-08-20T07:51","msg":"Update marking.md","body":"fix task 2 username regular expression\n. match any character and not the dot character\nwe should use \\.","parents":["4121209d219cfeb3f4b10800188890e611ddd2ed"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"6215b074ae3f109f6b5c5f864f1637ee04d0f4f7","ts":1597900032,"wall":"2020-08-20T08:07","msg":"Update marking.md","body":"fix the email validation regex\nA-z is not correct because it will catch also these characters: [,\\,],^,_` (ascii 91-96)\nand . should be replaced by \\\\.","parents":["4121209d219cfeb3f4b10800188890e611ddd2ed"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"50a5b552c63fa8e3330c85b2ea597c85d83bc2e7","ts":1597994141,"wall":"2020-08-21T08:15","msg":"Merge pull request #276 from RafaelGreen1/patch-2","body":"Update marking.md","parents":["4121209d219cfeb3f4b10800188890e611ddd2ed","6215b074ae3f109f6b5c5f864f1637ee04d0f4f7"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"e1b14a6e51f891e483d8d37e97be29e55385845a","ts":1597994284,"wall":"2020-08-21T08:18","msg":"Merge branch 'master' into patch-1","body":"","parents":["92a9e0e61c0a0122053f298b5a0a6401fbe44c40","50a5b552c63fa8e3330c85b2ea597c85d83bc2e7"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"5a2bc0cfe1a4690da5baca2b5e931bce6b2fc861","ts":1597994307,"wall":"2020-08-21T08:18","msg":"Merge pull request #275 from RafaelGreen1/patch-1","body":"Update marking.md","parents":["50a5b552c63fa8e3330c85b2ea597c85d83bc2e7","e1b14a6e51f891e483d8d37e97be29e55385845a"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"f28bb31268c0fa50295f13e05acc858b48ea385e","ts":1598314226,"wall":"2020-08-25T03:10","msg":"Update website-no-roles index.html - fix typo","body":"commmong --> common","parents":["5a2bc0cfe1a4690da5baca2b5e931bce6b2fc861"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"c227f8e867a9525000599ce3d1ef6b41124189cb","ts":1598318971,"wall":"2020-08-25T04:29","msg":"update website-aria-roles index.html - fix typo","body":"commmong --> common","parents":["5a2bc0cfe1a4690da5baca2b5e931bce6b2fc861"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"79bb3e3d245947feb6b2a03e48e7918e9794035b","ts":1598335251,"wall":"2020-08-25T09:00","msg":"validation-checkbox-disabled.js - remove unnecessary line","body":"remove unnecessary line of code\ninstruItem.input.removeAttribute('aria-label');\nthere is no attribute aria-label to remove","parents":["5a2bc0cfe1a4690da5baca2b5e931bce6b2fc861"],"add":0,"del":1,"cadd":0,"cdel":1,"files":1},{"repo":"learning-area","hash":"7f3e7134c1fa92bfda5eaae0ddc19388981b814d","ts":1598336541,"wall":"2020-08-25T09:22","msg":"Update 7_canvas_walking_animation.html - remove unnecessary calculation","body":"if we take any whole number and add 2 to it in each iteration it will eventually be a multiple of 13\nthis sentence from the documentation: “This has to be a multiple of 13 because otherwise the previous code block won’t work, since posX would never equal a multiple of 13!”\nis not correct","parents":["5a2bc0cfe1a4690da5baca2b5e931bce6b2fc861"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"3f1b84f99e2730b85476bb4a32ec0fb9e88d960b","ts":1598340254,"wall":"2020-08-25T08:24","msg":"Merge pull request #281 from RafaelGreen1/patch-5","body":"Update website-no-roles index.html - fix typo","parents":["5a2bc0cfe1a4690da5baca2b5e931bce6b2fc861","f28bb31268c0fa50295f13e05acc858b48ea385e"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"55dbba7d2d497aa71317dc7cb5170a2f32d99bb4","ts":1598340285,"wall":"2020-08-25T08:24","msg":"Merge pull request #282 from RafaelGreen1/patch-6","body":"update website-aria-roles index.html - fix typo","parents":["3f1b84f99e2730b85476bb4a32ec0fb9e88d960b","c227f8e867a9525000599ce3d1ef6b41124189cb"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"e44606c2228043b7c40fe354d65dd139e05c4ae3","ts":1598340646,"wall":"2020-08-25T08:30","msg":"Merge pull request #283 from RafaelGreen1/patch-7","body":"validation-checkbox-disabled.js - remove unnecessary line","parents":["55dbba7d2d497aa71317dc7cb5170a2f32d99bb4","79bb3e3d245947feb6b2a03e48e7918e9794035b"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"960d2fd5de89bbf08c8c6e2e94ac42be09cdcc9e","ts":1598341975,"wall":"2020-08-25T08:52","msg":"Merge pull request #284 from RafaelGreen1/patch-8","body":"Update 7_canvas_walking_animation.html - remove unnecessary calculation","parents":["e44606c2228043b7c40fe354d65dd139e05c4ae3","7f3e7134c1fa92bfda5eaae0ddc19388981b814d"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"5c31b923a8df187c4981b86164d1b2125d81ee59","ts":1598391603,"wall":"2020-08-26T00:40","msg":"Update aria-tabbed-info-box.html - remove unnecessary argument","body":"the function setTabHandler has only one parameter, but called with two","parents":["960d2fd5de89bbf08c8c6e2e94ac42be09cdcc9e"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"089966a1da88b7d020418276700cff6ee6a6f140","ts":1598416577,"wall":"2020-08-26T05:36","msg":"Merge pull request #285 from RafaelGreen1/patch-9","body":"Update aria-tabbed-info-box.html - remove unnecessary argument","parents":["960d2fd5de89bbf08c8c6e2e94ac42be09cdcc9e","5c31b923a8df187c4981b86164d1b2125d81ee59"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"7513e2c8dbd908157a51fdd015df0593c693a170","ts":1598581121,"wall":"2020-08-28T05:18","msg":"Update accessibility assessment-finished marking-guide.md considerations","body":"add consideration - add aria-live to the comments area","parents":["089966a1da88b7d020418276700cff6ee6a6f140"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"learning-area","hash":"e12f434ec247d2c1902ca056ec65bee5ab2b0077","ts":1598609602,"wall":"2020-08-28T13:13","msg":"Update accessibility assessment - change aria-live to role=\"alert\"","body":"change aria-live to role=\"alert\"","parents":["7513e2c8dbd908157a51fdd015df0593c693a170"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"35f2f0f806f26f25f6889ea1d5c158159af97d01","ts":1598610448,"wall":"2020-08-28T13:27","msg":"Update accessibility assessment-finished marking-guide.md considerations","body":"change \"visible\" to \"displayed\"","parents":["e12f434ec247d2c1902ca056ec65bee5ab2b0077"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"72f15b9859e920f6b519f5f85177da7204b29350","ts":1598660332,"wall":"2020-08-29T03:18","msg":"Update accessibility assessment - add consideration - show alert when the show comments button is clicked","body":"add suggestion to put the role attribute with \"alert\" value on the <h2> element, and update its text like so:\n<h2 role=\"alert\">Comments (1 available)</h2>","parents":["35f2f0f806f26f25f6889ea1d5c158159af97d01"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"188383b0667dc0586e4319cc90deba9812202193","ts":1598660546,"wall":"2020-08-29T03:22","msg":"Update accessibility assessment - add <code> tags","body":"","parents":["72f15b9859e920f6b519f5f85177da7204b29350"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"c84c19a80de1cc8a117f00e327afe6e09f442e94","ts":1598693840,"wall":"2020-08-29T10:37","msg":"Merge pull request #286 from RafaelGreen1/patch-10","body":"Update accessibility assessment-finished marking-guide.md considerations","parents":["089966a1da88b7d020418276700cff6ee6a6f140","188383b0667dc0586e4319cc90deba9812202193"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"cd49f6dcf03df7e726267961bbafd03b66e3728d","ts":1598694237,"wall":"2020-08-29T12:43","msg":"update marking-guide.md - fix typo","body":"then --> when","parents":["c84c19a80de1cc8a117f00e327afe6e09f442e94"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"a8e426ddfaca4cfdb2c50c3a3492ceecbbd968a7","ts":1598696449,"wall":"2020-08-29T11:20","msg":"Merge pull request #287 from RafaelGreen1/patch-11","body":"update marking-guide.md - fix typo","parents":["c84c19a80de1cc8a117f00e327afe6e09f442e94","cd49f6dcf03df7e726267961bbafd03b66e3728d"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"ab26fe10a1898930d13ddd5e593eca6a4dc464eb","ts":1599401701,"wall":"2020-09-06T17:15","msg":"Update number-guessing-game-start.html - newline","body":"Add new line to make a bit more readable","parents":["a8e426ddfaca4cfdb2c50c3a3492ceecbbd968a7"],"add":2,"del":1,"cadd":2,"cdel":1,"files":1},{"repo":"learning-area","hash":"3bed153e4c8f6947f3ca355515a84cbdfacc8e58","ts":1599467771,"wall":"2020-09-07T09:36","msg":"Merge pull request #290 from dedeogluhu/new-line","body":"Update number-guessing-game-start.html - newline","parents":["a8e426ddfaca4cfdb2c50c3a3492ceecbbd968a7","ab26fe10a1898930d13ddd5e593eca6a4dc464eb"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"1d935804999146341b122a79073191152d883159","ts":1600414750,"wall":"2020-09-18T08:39","msg":"removing redeclared line from events skill test","body":"","parents":["3bed153e4c8f6947f3ca355515a84cbdfacc8e58"],"add":0,"del":1,"cadd":0,"cdel":1,"files":1},{"repo":"learning-area","hash":"37b8ad62342db42effa85bdb577b64980259bfa3","ts":1600610570,"wall":"2020-09-20T17:02","msg":"removing redeclared line from events skill test","body":"","parents":["1d935804999146341b122a79073191152d883159"],"add":0,"del":2,"cadd":0,"cdel":2,"files":2},{"repo":"learning-area","hash":"8e51b4c8f673a2a59eb02601b04295b4b6a05314","ts":1600611599,"wall":"2020-09-20T15:19","msg":"Merge pull request #293 from RafaelGreen1/patch-12","body":"removing redeclared line from events skill test","parents":["1d935804999146341b122a79073191152d883159","37b8ad62342db42effa85bdb577b64980259bfa3"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"be38aa59879aa3f3072fe2c4c1697da5096783f1","ts":1600823941,"wall":"2020-09-22T21:19","msg":"Fixed a really small typo","body":"Hi, in the comment on line 31 I changed \"commmon\" to \"common\". I'm loving the front end developer path so far. I hope it will lead to a career change down the road so thank you for putting this stuff together.","parents":["8e51b4c8f673a2a59eb02601b04295b4b6a05314"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"7e216e95e807a81ec5d67873d5327180e6f61309","ts":1600841401,"wall":"2020-09-23T07:10","msg":"Merge pull request #294 from silvercub/patch-1","body":"Fixed a really small typo","parents":["8e51b4c8f673a2a59eb02601b04295b4b6a05314","be38aa59879aa3f3072fe2c4c1697da5096783f1"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"5ab67e68550d91ae9814792d74d9049992364644","ts":1600931851,"wall":"2020-09-24T10:17","msg":"add empty <p> element to automation/index.html","body":"In the Automated_testing article it's written:\n\"In the input version of the file, you may have noticed that we put an empty <p> element; htmltidy has removed this by the time the output file has been created.\"\nbut there is no <p> element here\n\nhttps://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Automated_testing","parents":["7e216e95e807a81ec5d67873d5327180e6f61309"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"learning-area","hash":"0352d356a51852f5c32c876961513b430d96b74c","ts":1600938616,"wall":"2020-09-24T12:10","msg":"Update gulpfile.js","body":"this didn't work for me, so I'm changing it to a working version\nalso, by gulp's docs, the task API isn't the recommended pattern anymore\nhttps://gulpjs.com/docs/en/api/task/","parents":["7e216e95e807a81ec5d67873d5327180e6f61309"],"add":16,"del":10,"cadd":16,"cdel":10,"files":1},{"repo":"learning-area","hash":"d2e525bb5ceda99cb8378615f1705d72b97b1222","ts":1600938715,"wall":"2020-09-24T10:11","msg":"Merge pull request #296 from RafaelGreen1/patch-14","body":"Update gulpfile.js","parents":["7e216e95e807a81ec5d67873d5327180e6f61309","0352d356a51852f5c32c876961513b430d96b74c"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"4a9a98bb9aff07c4f287f56af9362105c8efb88c","ts":1602327828,"wall":"2020-10-10T12:03","msg":"adding meta viewport to layout assessment examples","body":"","parents":["d2e525bb5ceda99cb8378615f1705d72b97b1222"],"add":4,"del":2,"cadd":4,"cdel":2,"files":2},{"repo":"learning-area","hash":"e939f9ec47fffd56da7b055ea274d1b9c80cde78","ts":1602420480,"wall":"2020-10-11T15:48","msg":"add comment to explain empty paragraph","body":"","parents":["5ab67e68550d91ae9814792d74d9049992364644"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"learning-area","hash":"073b799cc2385fe23d557baa5181cb0969c2426f","ts":1602499263,"wall":"2020-10-12T11:41","msg":"Merge pull request #295 from RafaelGreen1/patch-13","body":"add empty <p> element to automation/index.html","parents":["4a9a98bb9aff07c4f287f56af9362105c8efb88c","e939f9ec47fffd56da7b055ea274d1b9c80cde78"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"1ee344091afcf6d565f1f78632bbdb5b0518f27b","ts":1603273852,"wall":"2020-10-21T10:50","msg":"changing polyfill eample back to use var, to see if it will work","body":"","parents":["4a9a98bb9aff07c4f287f56af9362105c8efb88c"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"0ab12b142263522447990d88a5966a66af1d519e","ts":1603273863,"wall":"2020-10-21T10:51","msg":"Merge branch 'master' of github.com:mdn/learning-area","body":"","parents":["1ee344091afcf6d565f1f78632bbdb5b0518f27b","073b799cc2385fe23d557baa5181cb0969c2426f"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"e2fa574d2b6f3126e9d2599cb808a19589847019","ts":1603277070,"wall":"2020-10-21T11:44","msg":"changing polyfill eample back to use var, to see if it will work","body":"","parents":["0ab12b142263522447990d88a5966a66af1d519e"],"add":3,"del":1,"cadd":3,"cdel":1,"files":1},{"repo":"learning-area","hash":"5b7cdd64d0b9330c4f4f0d1749888a81efeb26e1","ts":1604137957,"wall":"2020-10-31T09:52","msg":"adding missing semi-colos","body":"","parents":["e2fa574d2b6f3126e9d2599cb808a19589847019"],"add":2,"del":2,"cadd":2,"cdel":2,"files":2},{"repo":"learning-area","hash":"c71f5064b584e7214fe42a8e4809ab01a298fe57","ts":1604158557,"wall":"2020-10-31T10:35","msg":"Update heroes-finished.html","body":"This corresponds to the edit I made to the Learning JSON file. https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON","parents":["5b7cdd64d0b9330c4f4f0d1749888a81efeb26e1"],"add":5,"del":5,"cadd":5,"cdel":5,"files":1},{"repo":"learning-area","hash":"265f8c67151591c2c1a7d6615f23e8a3b385b48d","ts":1604315547,"wall":"2020-11-02T11:12","msg":"Merge pull request #304 from randycasburn/patch-1","body":"Update heroes-finished.html","parents":["5b7cdd64d0b9330c4f4f0d1749888a81efeb26e1","c71f5064b584e7214fe42a8e4809ab01a298fe57"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"10575b4117029ed09f3567fd8cce99b505355e0e","ts":1604586194,"wall":"2020-11-05T14:23","msg":"updating starting assets zip file","body":"","parents":["265f8c67151591c2c1a7d6615f23e8a3b385b48d"],"add":0,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"learning-area","hash":"2eb52751a595de478911e5be4c8e7b059ee0793c","ts":1605123874,"wall":"2020-11-12T00:44","msg":"Changed to the starting file state","body":"This one looked like finished one.","parents":["10575b4117029ed09f3567fd8cce99b505355e0e"],"add":1,"del":5,"cadd":1,"cdel":5,"files":1},{"repo":"learning-area","hash":"216861ba094dc6878a7a4623299677e3f37a05b2","ts":1605177753,"wall":"2020-11-12T10:42","msg":"Merge pull request #309 from BassOfBass/patch-1","body":"Changed to the starting file state","parents":["10575b4117029ed09f3567fd8cce99b505355e0e","2eb52751a595de478911e5be4c8e7b059ee0793c"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"eb5eae47a695267bd7f7d890e0db61097ab24c0f","ts":1605303319,"wall":"2020-11-14T02:35","msg":"Turned into the starting state","body":"As per [example in the task brief](https://developer.mozilla.org/en-US/docs/Learn/Accessibility/WAI-ARIA_basics/Test_your_skills:_WAI-ARIA#WAI-ARIA_2).","parents":["216861ba094dc6878a7a4623299677e3f37a05b2"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"e322d9559c2c184c99b86152974e49fe38986ad0","ts":1605360305,"wall":"2020-11-14T13:25","msg":"keypress event changed to keydown","body":"Since the *keypress* event has been deprecated I think it's better to use *keydown* event.\n\n(I'm not sure if I'm totally right, I just stumbled upon that while learning. It's also my first pull request and couldn't find the rules I should follow, sorry.)","parents":["216861ba094dc6878a7a4623299677e3f37a05b2"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"1c63a2ab9f17ff28ed0467aa6d7d381944c66fd5","ts":1605516903,"wall":"2020-11-16T08:55","msg":"Merge pull request #310 from BassOfBass/patch-2","body":"Turned into the starting state","parents":["216861ba094dc6878a7a4623299677e3f37a05b2","eb5eae47a695267bd7f7d890e0db61097ab24c0f"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"40ef2e2db930a98638e63fc87502b87c5bbd4d0d","ts":1606105563,"wall":"2020-11-23T15:26","msg":"bad-for-loop: revert to var","body":"","parents":["1c63a2ab9f17ff28ed0467aa6d7d381944c66fd5"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"cebba94cda768cd95714ea9d2c662daf48db8900","ts":1606105898,"wall":"2020-11-22T20:31","msg":"Merge pull request #313 from mdn/hamishwillee-patch-1","body":"bad-for-loop: revert to var","parents":["1c63a2ab9f17ff28ed0467aa6d7d381944c66fd5","40ef2e2db930a98638e63fc87502b87c5bbd4d0d"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"8ac2f3d32be4115ca4d9a6642b486303a17bf173","ts":1608059587,"wall":"2020-12-15T21:13","msg":"Update xhr-basic.html","body":"Change 'var' to 'const, let', so it relate to ajax-finish.html","parents":["cebba94cda768cd95714ea9d2c662daf48db8900"],"add":5,"del":6,"cadd":5,"cdel":6,"files":1},{"repo":"learning-area","hash":"0480cb7f675ea6dec09b112631b654211ef574ee","ts":1608081184,"wall":"2020-12-16T03:13","msg":"Added meta viewport tag","body":"","parents":["cebba94cda768cd95714ea9d2c662daf48db8900"],"add":25,"del":0,"cadd":25,"cdel":0,"files":2},{"repo":"learning-area","hash":"a4d9b762593953138659a80fded389870a8ffa42","ts":1608149651,"wall":"2020-12-16T22:14","msg":"Added tablet media query, adjusted body margin\"","body":"","parents":["0480cb7f675ea6dec09b112631b654211ef574ee"],"add":10,"del":2,"cadd":10,"cdel":2,"files":1},{"repo":"learning-area","hash":"3a900290f2a01916a24f87e7a46f5c40a0387704","ts":1608320372,"wall":"2020-12-18T21:39","msg":"Update xhr-basic.html","body":"","parents":["8ac2f3d32be4115ca4d9a6642b486303a17bf173"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"aadc63c8f307fbb2c96aa38f7a25edecdc38cd0d","ts":1608332716,"wall":"2020-12-18T23:05","msg":"Merge pull request #320 from webdev4422/patch-1","body":"Update xhr-basic.html","parents":["cebba94cda768cd95714ea9d2c662daf48db8900","3a900290f2a01916a24f87e7a46f5c40a0387704"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"87922a6e1aa46831cff65788a8f73942dc334fee","ts":1608373693,"wall":"2020-12-19T12:28","msg":"Added Mobile body size margin","body":"","parents":["a4d9b762593953138659a80fded389870a8ffa42"],"add":37,"del":19,"cadd":37,"cdel":19,"files":1},{"repo":"learning-area","hash":"c1872e784b05c1f36d8eeab1f8872488c884d073","ts":1608381268,"wall":"2020-12-19T14:34","msg":"Added viewport meta tag","body":"","parents":["87922a6e1aa46831cff65788a8f73942dc334fee"],"add":43,"del":60,"cadd":43,"cdel":60,"files":40},{"repo":"learning-area","hash":"0957b1bf6bedfcb68046507264c3e5fc4177e3b1","ts":1608538271,"wall":"2020-12-21T08:11","msg":"Merge pull request #323 from fikstoday/viewport","body":"Viewport","parents":["aadc63c8f307fbb2c96aa38f7a25edecdc38cd0d","c1872e784b05c1f36d8eeab1f8872488c884d073"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"4101c2779be05f036e0b41b017903937505f29c8","ts":1610290088,"wall":"2021-01-10T16:48","msg":"Update advanced-text2.html","body":"change H20 to H2O","parents":["0957b1bf6bedfcb68046507264c3e5fc4177e3b1"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"3db6721f073b73f7d1136126048736905cbe26d1","ts":1610364797,"wall":"2021-01-11T11:33","msg":"Merge pull request #326 from RafaelGreen1/patch-15","body":"Update advanced-text2.html - fix typo","parents":["0957b1bf6bedfcb68046507264c3e5fc4177e3b1","4101c2779be05f036e0b41b017903937505f29c8"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"0a461d9bf11b72f3009752980b40d467ae01ae73","ts":1610386091,"wall":"2021-01-11T19:28","msg":"Update advanced-text2-download.html - fix type","body":"H20 -> H2O","parents":["3db6721f073b73f7d1136126048736905cbe26d1"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"1a63d60a2cd841c4fead346e9dd5ea1ed2aa5428","ts":1610388733,"wall":"2021-01-11T18:12","msg":"Merge pull request #327 from RafaelGreen1/patch-16","body":"Update advanced-text2-download.html - fix typo","parents":["3db6721f073b73f7d1136126048736905cbe26d1","0a461d9bf11b72f3009752980b40d467ae01ae73"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"83c9d7ffcc0b1088d30c17ac946ad3bce720b6ed","ts":1610477170,"wall":"2021-01-12T20:46","msg":"Added max-width","body":"","parents":["c1872e784b05c1f36d8eeab1f8872488c884d073"],"add":27,"del":0,"cadd":27,"cdel":0,"files":1},{"repo":"learning-area","hash":"14c384b9b5a7d7100508fd13e5c7e0f436afe737","ts":1610490031,"wall":"2021-01-13T00:20","msg":"Fixed aside element border","body":"","parents":["83c9d7ffcc0b1088d30c17ac946ad3bce720b6ed"],"add":22,"del":0,"cadd":22,"cdel":0,"files":1},{"repo":"learning-area","hash":"4c85721bad406fc0a73bca38bbdaf139d60ec46a","ts":1610532520,"wall":"2021-01-13T10:08","msg":"Update can-style.css","body":"","parents":["14c384b9b5a7d7100508fd13e5c7e0f436afe737"],"add":6,"del":18,"cadd":6,"cdel":18,"files":1},{"repo":"learning-area","hash":"b0e7678b5d54998826ce4881042fa327e375f9df","ts":1610532613,"wall":"2021-01-13T10:10","msg":"Merge pull request #330 from fikstoday/correct-aside-border","body":"Correct aside border","parents":["1a63d60a2cd841c4fead346e9dd5ea1ed2aa5428","4c85721bad406fc0a73bca38bbdaf139d60ec46a"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"fd18c66cfad3120c5a52aa1778df86e4e37bade6","ts":1610723441,"wall":"2021-01-15T15:10","msg":"Update math3-download.html","body":"fixed the weights >> weighs typo","parents":["b0e7678b5d54998826ce4881042fa327e375f9df"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"d7b7769cc3a9bc13158deb4cc24e179f535c007d","ts":1610723794,"wall":"2021-01-15T15:16","msg":"Merge pull request #331 from DoodleDeBug/patch-1","body":"Update math3-download.html","parents":["b0e7678b5d54998826ce4881042fa327e375f9df","fd18c66cfad3120c5a52aa1778df86e4e37bade6"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"da001f8ef40942bdbe260552165604a94eb89df9","ts":1612172050,"wall":"2021-02-01T15:04","msg":"Update contact-search.html","body":"Changed the else statement to an else if statement that instead of being\nexecuted for every array element that isn't a match, is executed only upon\nnot finding a matching entry in the entire contacts array","parents":["b0e7678b5d54998826ce4881042fa327e375f9df"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"511eb74a23f057121b4a762ee4b105d1eb706297","ts":1612174972,"wall":"2021-02-01T10:22","msg":"Merge pull request #332 from tankris/patch-1","body":"Update contact-search.html","parents":["d7b7769cc3a9bc13158deb4cc24e179f535c007d","da001f8ef40942bdbe260552165604a94eb89df9"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"a94e7ef94fc73ef4950248bf0d7311ab7b492f87","ts":1612218650,"wall":"2021-02-02T04:00","msg":"in line 40 the code is not require","body":"//const greetBtn = document.querySelector('.greet');","parents":["511eb74a23f057121b4a762ee4b105d1eb706297"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"5f0bbf82e29cbe4863ec11569e57c9ca072d5314","ts":1612287093,"wall":"2021-02-02T17:31","msg":"Merge pull request #333 from adii-the-billionaire/patch-1","body":"in line 40 the code is not require","parents":["511eb74a23f057121b4a762ee4b105d1eb706297","a94e7ef94fc73ef4950248bf0d7311ab7b492f87"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"499d45d22a8523e94951de8eab4a05cdabb3efb2","ts":1612618408,"wall":"2021-02-06T13:33","msg":"Merge pull request #311 from ruippeixe/patch-1","body":"keypress event changed to keydown","parents":["5f0bbf82e29cbe4863ec11569e57c9ca072d5314","e322d9559c2c184c99b86152974e49fe38986ad0"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"e73a308d8c103d6ea3d8800662ac285c61829b58","ts":1613512347,"wall":"2021-02-17T00:52","msg":"Update planets-data.html","body":"Scope tag for \"Dwarf Planets\" should be \"rowgroup\" instead of \"row\" as \"Dwarf planets\" is a group name for all \"dwarf\" ones, not only for\"Pluto\".","parents":["499d45d22a8523e94951de8eab4a05cdabb3efb2"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"59bfd052a8d3d8a06d0af552e3f79e03603bf03d","ts":1613555961,"wall":"2021-02-17T09:59","msg":"Merge pull request #339 from atakndogn/patch-1","body":"Update planets-data.html","parents":["499d45d22a8523e94951de8eab4a05cdabb3efb2","e73a308d8c103d6ea3d8800662ac285c61829b58"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"c9dec74615b8f293bbe84e8565c3b497e422445d","ts":1616095218,"wall":"2021-03-18T13:20","msg":"remove ttf, svg and eot files","body":"","parents":["59bfd052a8d3d8a06d0af552e3f79e03603bf03d"],"add":0,"del":793,"cadd":0,"cdel":0,"files":6},{"repo":"learning-area","hash":"524a9399cf8fceb845b12104ee9187e262515a73","ts":1616172640,"wall":"2021-03-19T11:50","msg":"Give each checkbox the same 'name'","body":"Because they're all related","parents":["59bfd052a8d3d8a06d0af552e3f79e03603bf03d"],"add":9,"del":10,"cadd":9,"cdel":10,"files":2},{"repo":"learning-area","hash":"329728cecd492497afd5f208a6d45e49fc2d4443","ts":1616177224,"wall":"2021-03-19T18:07","msg":"Merge pull request #350 from jrsnzc/hotfix","body":"Give each checkbox the same 'name'","parents":["59bfd052a8d3d8a06d0af552e3f79e03603bf03d","524a9399cf8fceb845b12104ee9187e262515a73"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"e6785c69d25359fe688be2a8ddd8d71169fde798","ts":1616429726,"wall":"2021-03-22T11:15","msg":"Add fix and talk about multiple checkboxes","body":"","parents":["329728cecd492497afd5f208a6d45e49fc2d4443"],"add":2,"del":2,"cadd":2,"cdel":2,"files":2},{"repo":"learning-area","hash":"1095b669de187fc58681bb15cee1902fa24f4385","ts":1616515290,"wall":"2021-03-23T16:01","msg":"Merge pull request #352 from jrsnzc/hotfix","body":"Add fix and talk about multiple related checkboxes","parents":["329728cecd492497afd5f208a6d45e49fc2d4443","e6785c69d25359fe688be2a8ddd8d71169fde798"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"19e646ba51d39c8d49aef4f1f1858b2fa5cef915","ts":1617118883,"wall":"2021-03-30T09:41","msg":"update font-face usage in css/styling-text/web-fonts","body":"","parents":["c9dec74615b8f293bbe84e8565c3b497e422445d"],"add":7,"del":15,"cadd":7,"cdel":15,"files":1},{"repo":"learning-area","hash":"80357576eca41feaa685b83b9d5ddbf3e678d711","ts":1617121520,"wall":"2021-03-30T17:25","msg":"Merge pull request #355 from mainsail-org/mir/css-webfonts","body":"Fix outdated use of @font-face in css/styling-text/web-fonts","parents":["1095b669de187fc58681bb15cee1902fa24f4385","19e646ba51d39c8d49aef4f1f1858b2fa5cef915"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"100d95e42769c0f9eaea9d0c18f0cc54cd7c88ea","ts":1618820270,"wall":"2021-04-19T09:17","msg":"adding user-valid and user-invalid example","body":"","parents":["80357576eca41feaa685b83b9d5ddbf3e678d711"],"add":119,"del":0,"cadd":119,"cdel":0,"files":1},{"repo":"learning-area","hash":"442c07afb8fb3f0759fd4ed9db58971cba8f60d2","ts":1618820727,"wall":"2021-04-19T09:25","msg":"fix page title","body":"","parents":["100d95e42769c0f9eaea9d0c18f0cc54cd7c88ea"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"831fc1f7d07dd53579e22d6685f5a7520b1eb65e","ts":1621676811,"wall":"2021-05-22T15:16","msg":"Fixed  bug in example","body":"","parents":["442c07afb8fb3f0759fd4ed9db58971cba8f60d2"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"ce63adeaaa67514291e9da11671d735f99195b2a","ts":1621844414,"wall":"2021-05-24T09:20","msg":"Merge pull request #365 from NegiAkash890/patch-1","body":"Updated Example","parents":["442c07afb8fb3f0759fd4ed9db58971cba8f60d2","831fc1f7d07dd53579e22d6685f5a7520b1eb65e"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"0cf7e3654ddb240eb3fe64a39a7f3e92160ae5d6","ts":1626060445,"wall":"2021-07-12T08:57","msg":"Information text corrected to match html.onclick()","body":"Please consider the following small improvement made in information text to make it more clear since clicking inside the empty list will also add the 1st item.\n\nInformation text \"Click anywhere outside list\" changed to \"Click anywhere on the page\". \n\nHope this description will more accurately indicate the functionality of html.onclick()","parents":["ce63adeaaa67514291e9da11671d735f99195b2a"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"learning-area","hash":"6d44eed60268d938101e06e91dbcd54a41c0fa9f","ts":1626084638,"wall":"2021-07-12T11:10","msg":"Merge pull request #381 from johnjinto/patch-1","body":"Information text corrected to match html.onclick()","parents":["ce63adeaaa67514291e9da11671d735f99195b2a","0cf7e3654ddb240eb3fe64a39a7f3e92160ae5d6"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"991fbce0466c9be8ba917d6b842117c87f8ef0d5","ts":1627290638,"wall":"2021-07-26T14:40","msg":"Update marking.md","body":"fixing a typo in task 2. Replacing <textarea> with <select>.The task was about select and not textarea so changing id of <select>.","parents":["6d44eed60268d938101e06e91dbcd54a41c0fa9f"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"learning-area","hash":"5967796f72a86e0041fb2148f46f499929e12060","ts":1627335005,"wall":"2021-07-27T07:30","msg":"Merge pull request #386 from MadhavKwatra/patch-1","body":"Update marking.md","parents":["6d44eed60268d938101e06e91dbcd54a41c0fa9f","991fbce0466c9be8ba917d6b842117c87f8ef0d5"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"31042f95b6edf4be9f2c9dc52ec32e89bc7e2ae2","ts":1627613233,"wall":"2021-07-30T08:17","msg":"Fixed Grammer","body":"","parents":["5967796f72a86e0041fb2148f46f499929e12060"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"heloo-wald","hash":"846d58c49b0e815c9c942c45ad8b9bdda68e1305","ts":1630512059,"wall":"2021-09-01T12:00","msg":"Initial commit","body":"","parents":[],"add":2,"del":0,"cadd":2,"cdel":0,"files":1},{"repo":"heloo-wald","hash":"ac0936570ec006396eccc1ea2b1c6cf640c63311","ts":1630512723,"wall":"2021-09-01T12:12","msg":"Update README.md","body":"\"My name is Richard, my health is starting to fail; I'm a continual failure on losing weight... my youtube channel went from 8mil views to under 800 thousand. I live off the charity of others. I haven't seen my penis in probably 8 years. I'm bigger now than I've ever been. I have trouble sleeping, I'm not taking care of myself the way I should and I have to basically play games that I hate, for a living. Welcome to BanWorld.\"","parents":["846d58c49b0e815c9c942c45ad8b9bdda68e1305"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"heloo-wald","hash":"4b4ee48edeedb9e1976c6b0a72d208e2a90a868d","ts":1630513013,"wall":"2021-09-01T12:16","msg":"Update README.md","body":"","parents":["ac0936570ec006396eccc1ea2b1c6cf640c63311"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"heloo-wald","hash":"82b28b28d7f0ebe7b794ac0353775d50ab60cd07","ts":1630513118,"wall":"2021-09-01T12:18","msg":"Merge pull request #1 from The-Azuran/readme-edits","body":"Readme edits","parents":["846d58c49b0e815c9c942c45ad8b9bdda68e1305","4b4ee48edeedb9e1976c6b0a72d208e2a90a868d"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"86116893ba9928e19e1a70368673d9388ccf1357","ts":1631110720,"wall":"2021-09-08T19:48","msg":"applied changes as requested","body":"","parents":["5967796f72a86e0041fb2148f46f499929e12060"],"add":2,"del":3,"cadd":2,"cdel":3,"files":1},{"repo":"learning-area","hash":"6a704bd55855f594ac73dbc059502542eeeec28d","ts":1631139206,"wall":"2021-09-09T08:13","msg":"Merge pull request #400 from Biki-das/mywork","body":"applied changes as requested","parents":["5967796f72a86e0041fb2148f46f499929e12060","86116893ba9928e19e1a70368673d9388ccf1357"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"learning-area","hash":"d2c9c81f9d97dbfd7f1414f0d76b6a5630928481","ts":1631701524,"wall":"2021-09-15T11:25","msg":"Merge pull request #387 from NegiAkash890/master","body":"Fixed Grammar","parents":["6a704bd55855f594ac73dbc059502542eeeec28d","31042f95b6edf4be9f2c9dc52ec32e89bc7e2ae2"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"the-azuran","hash":"765f3ee7d768e939f34c7177bccfe75d76c5b58f","ts":1633448235,"wall":"2021-10-05T11:37","msg":"Create README.md","body":"","parents":[],"add":10,"del":0,"cadd":10,"cdel":0,"files":1},{"repo":"the-azuran.github.io","hash":"d12187b70ac525b7bc73f88617988769019cbc14","ts":1633552573,"wall":"2021-10-06T16:36","msg":"Initial commit","body":"","parents":[],"add":2,"del":0,"cadd":2,"cdel":0,"files":1},{"repo":"the-azuran.github.io","hash":"a200b1b43fbe4773f071f8b819b9ff907c88492e","ts":1633552662,"wall":"2021-10-06T16:37","msg":"Update and rename README.md to index.html","body":"","parents":["d12187b70ac525b7bc73f88617988769019cbc14"],"add":47,"del":2,"cadd":47,"cdel":2,"files":2},{"repo":"the-azuran.github.io","hash":"cc282e75fe70de12a426bd6b3ed764c23c376955","ts":1633552903,"wall":"2021-10-06T16:41","msg":"Add files via upload","body":"","parents":["a200b1b43fbe4773f071f8b819b9ff907c88492e"],"add":204,"del":0,"cadd":204,"cdel":0,"files":7},{"repo":"the-azuran.github.io","hash":"adf435402193cf5e873950048a99ccf7768058c1","ts":1633557904,"wall":"2021-10-06T18:05","msg":"Update index.html","body":"","parents":["cc282e75fe70de12a426bd6b3ed764c23c376955"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"the-azuran.github.io","hash":"7b7bcbd7aee45788319a45c31cad54decd54dd0c","ts":1633558223,"wall":"2021-10-06T18:10","msg":"Update what-i-do.html","body":"","parents":["adf435402193cf5e873950048a99ccf7768058c1"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"the-azuran.github.io","hash":"9881e20463def0f54e913bfe14c1233dff38afa5","ts":1633558277,"wall":"2021-10-06T18:11","msg":"Update what-i-do.html","body":"","parents":["7b7bcbd7aee45788319a45c31cad54decd54dd0c"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"form-template","hash":"8ef38ee8269ed1e64e8def5b46ee4791f65b5f20","ts":1633614575,"wall":"2021-10-07T09:49","msg":"Add files via upload","body":"","parents":[],"add":169,"del":0,"cadd":169,"cdel":0,"files":5},{"repo":"the-azuran.github.io","hash":"38d57f85009bc4e74901255f8c1a46a8c2aea8fa","ts":1633652548,"wall":"2021-10-07T20:22","msg":"Add files via upload","body":"","parents":["adf435402193cf5e873950048a99ccf7768058c1"],"add":128,"del":0,"cadd":128,"cdel":0,"files":1},{"repo":"the-azuran.github.io","hash":"c09bc51e1719d2cf6a74a397a88a35afc864a3a4","ts":1633652739,"wall":"2021-10-07T20:25","msg":"Update number-guessing-game-start.html","body":"","parents":["38d57f85009bc4e74901255f8c1a46a8c2aea8fa"],"add":3,"del":0,"cadd":3,"cdel":0,"files":1},{"repo":"the-azuran.github.io","hash":"f7d7ec2fd0acb44d8ea8ca4629a2f845bd5a35d1","ts":1633652957,"wall":"2021-10-07T20:29","msg":"Update index.html","body":"","parents":["c09bc51e1719d2cf6a74a397a88a35afc864a3a4"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"the-azuran.github.io","hash":"a0ef7e3ec74875b7848c4ec65615d14ebdc993d6","ts":1633653050,"wall":"2021-10-07T20:30","msg":"Update index.html","body":"","parents":["f7d7ec2fd0acb44d8ea8ca4629a2f845bd5a35d1"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"the-azuran.github.io","hash":"598b51cf15835abffa8fc9f234a9379c30346db8","ts":1633993356,"wall":"2021-10-11T19:02","msg":"Merge pull request #1 from The-Azuran/branch-1","body":"Branch 1","parents":["a0ef7e3ec74875b7848c4ec65615d14ebdc993d6","9881e20463def0f54e913bfe14c1233dff38afa5"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"web-scrapper","hash":"aca4e3a2877522c64fc0983b55ee44397cef6a71","ts":1636751457,"wall":"2021-11-12T16:10","msg":"Initial commit","body":"","parents":[],"add":2,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"emoji_wall","hash":"6b0e4d9b8586d39041131d17e11334c4a788fcf6","ts":1690551854,"wall":"2023-07-28T09:44","msg":"Initial commit","body":"","parents":[],"add":674,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"goat_management_app","hash":"b704ec720ad6a7e2dc38e8e900653c67963a12a6","ts":1690639791,"wall":"2023-07-29T10:09","msg":"Initial commit","body":"","parents":[],"add":1,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"good-news","hash":"9981f58a6d79c37d4e92d44dbd632966b0175a81","ts":1691076515,"wall":"2023-08-03T11:28","msg":"Initial commit","body":"","parents":[],"add":8677,"del":0,"cadd":7500,"cdel":0,"files":20},{"repo":"good-news","hash":"63e4fc8f7cf20b2b569af1f3efbd4d1c1bf03cb0","ts":1691076782,"wall":"2023-08-03T11:33","msg":"Create README.md","body":"","parents":["9981f58a6d79c37d4e92d44dbd632966b0175a81"],"add":3,"del":0,"cadd":3,"cdel":0,"files":1},{"repo":"new-belen-game","hash":"eea3999d23731191fab48f3cadb5a295d6aa8745","ts":1691103515,"wall":"2023-08-03T18:58","msg":"Initial commit","body":"","parents":[],"add":8902,"del":0,"cadd":7591,"cdel":0,"files":22},{"repo":"new-belen-game","hash":"120f6089442f35144348571bca7ab486eeac5be8","ts":1691103950,"wall":"2023-08-03T19:05","msg":"Create README.md","body":"","parents":["eea3999d23731191fab48f3cadb5a295d6aa8745"],"add":17,"del":0,"cadd":17,"cdel":0,"files":1},{"repo":"new-belen-game","hash":"d80a664d9fec9b4bb300cc3bbc4749418dee29fe","ts":1691104073,"wall":"2023-08-03T19:07","msg":"Update README.md","body":"","parents":["120f6089442f35144348571bca7ab486eeac5be8"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"new-belen-game","hash":"6cc56c0ffdbb152700ef299b0c72f980136a7228","ts":1691116766,"wall":"2023-08-03T22:39","msg":"Updated game with resistance mechanic","body":"","parents":["eea3999d23731191fab48f3cadb5a295d6aa8745"],"add":9,"del":10,"cadd":9,"cdel":10,"files":1},{"repo":"new-belen-game","hash":"312cddacce9396e463164866e493955572cdbf3b","ts":1691116910,"wall":"2023-08-03T22:41","msg":"Merge branch 'main' of https://github.com/The-Azuran/New-Belen-game","body":"","parents":["6cc56c0ffdbb152700ef299b0c72f980136a7228","d80a664d9fec9b4bb300cc3bbc4749418dee29fe"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"new-church-game","hash":"d69d113a36768e5dbb786df140621cce2c0e289f","ts":1691191388,"wall":"2023-08-04T19:23","msg":"Initial commit","body":"","parents":[],"add":8962,"del":0,"cadd":7761,"cdel":0,"files":20},{"repo":"seandruh","hash":"1ea2a374bd5f52c5d39d96f8a6d0174fa8c593ac","ts":1691969807,"wall":"2023-08-13T19:36","msg":"Initial commit","body":"","parents":[],"add":23709,"del":0,"cadd":7634,"cdel":0,"files":23},{"repo":"synthpen","hash":"4b725aac85229f4cb94dfd26e9561de6e66e12c7","ts":1692136453,"wall":"2023-08-15T17:54","msg":"Initial commit","body":"","parents":[],"add":315,"del":0,"cadd":188,"cdel":0,"files":4},{"repo":"bioflash","hash":"84f7ff9efa851b9e4f969915a7a7dc69c6bd1798","ts":1692241447,"wall":"2023-08-16T23:04","msg":"Initial commit","body":"","parents":[],"add":176,"del":0,"cadd":173,"cdel":0,"files":4},{"repo":"new-church-game","hash":"dc682a628ce961e3021c8e5849b8333ba390013c","ts":1763680066,"wall":"2025-11-20T23:07","msg":"Fix critical bugs and improve code quality","body":"Critical Bug Fixes:\n- Fix nested loop bug in door_to_door method causing infinite iteration\n- Fix exponential conversion rate growth by using temporary calculations\n- Enable church creation by calling check_church_status() after conversions\n- Improve resistance system to reduce conversion chance instead of blocking\n\nCode Quality Improvements:\n- Implement strategy system: Preach Intensely (+50% conversion, +50% hunger) vs Preach Softly (baseline)\n- Extract 14 magic numbers to named constants for better maintainability\n- Fix daily score tracking to include all conversions (including Satanic)\n\nFeature Enhancements:\n- Add detailed NPC information display showing religion, belief level, attitude, resistance status, and failed attempts\n- Add church creation notifications\n- Improve game balance and player decision-making\n\nAll changes tested and syntax validated.","parents":["d69d113a36768e5dbb786df140621cce2c0e289f"],"add":123,"del":81,"cadd":123,"cdel":81,"files":1},{"repo":"new-church-game","hash":"74deab9fe99e29d26efdc6a18ee7887c564b972b","ts":1763680133,"wall":"2025-11-20T23:08","msg":"Add .gitignore for Python project","body":"","parents":["dc682a628ce961e3021c8e5849b8333ba390013c"],"add":29,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"new-belen-game","hash":"533f011b25a44815e2f86dffebdde45ad9bb7e6c","ts":1768506294,"wall":"2026-01-15T14:44","msg":"Add files via upload","body":"","parents":["312cddacce9396e463164866e493955572cdbf3b"],"add":287,"del":153,"cadd":211,"cdel":153,"files":3},{"repo":"new-belen-game","hash":"b6d4defbd575b377458a5ca5d85c6cf15d62ef9d","ts":1768532584,"wall":"2026-01-15T22:03","msg":"0v1.0.0 - Initial public release","body":"O","parents":["533f011b25a44815e2f86dffebdde45ad9bb7e6c"],"add":4158,"del":8970,"cadd":4083,"cdel":7661,"files":43},{"repo":"new-belen-game","hash":"1d5a11469e7fb5ac7deafa85f97a81de69da3415","ts":1768532950,"wall":"2026-01-15T22:09","msg":"Fix release workflow - rename files to avoid collision","body":"","parents":["b6d4defbd575b377458a5ca5d85c6cf15d62ef9d"],"add":7,"del":4,"cadd":7,"cdel":4,"files":1},{"repo":"new-belen-game","hash":"78365f99ed9b1ba0a86f4c223a6533f44c1bf88f","ts":1768601963,"wall":"2026-01-16T17:19","msg":"Add world hierarchy, inventory system, and navigation improvements","body":"- Add full world hierarchy: County → Town → Neighborhood → Street → Location\n- Add inventory system: buy food/pamphlets and use them later (press 'i')\n- Add zoom-out navigation: press 0 to go back at any level\n- Add Street, Town, County data classes and name generators\n- Update UI to show location hierarchy in status/dashboard\n- Remove obsolete Preaching2.spec\n- Add game assets (icon, desktop file)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["1d5a11469e7fb5ac7deafa85f97a81de69da3415"],"add":521,"del":123,"cadd":503,"cdel":84,"files":11},{"repo":"new-belen-game","hash":"fc8046db6be15cfef6cf3a7a8b7e615ec11c907a","ts":1768604818,"wall":"2026-01-16T18:06","msg":"Add character selection, Titi Olga, and web support","body":"- Add preacher selection system with 7 characters + custom option\n- Each preacher has unique bonuses/penalties\n- Add Titi Olga character (the subtly manipulative one)\n- Update Belen Torres backstory (Dominican ex-witch)\n- Add dedication to Monica Huertas\n- Clean up screen clutter with strategic clears\n- Add Replit config for web deployment\n- Fix various bugs (reputation manager, hunger rate)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["78365f99ed9b1ba0a86f4c223a6533f44c1bf88f"],"add":265,"del":9,"cadd":250,"cdel":8,"files":9},{"repo":"the-azuran","hash":"908c5cdfd8ea9e4f1005b4cdb3f660a4b286f3f8","ts":1768611500,"wall":"2026-01-16T19:58","msg":"Update README.md","body":"","parents":["765f3ee7d768e939f34c7177bccfe75d76c5b58f"],"add":8,"del":6,"cadd":8,"cdel":6,"files":1},{"repo":"the-azuran","hash":"a246bb0c1cd4800d8f7bd4132afcc93b216b6295","ts":1768612024,"wall":"2026-01-16T20:07","msg":"Update README.md","body":"","parents":["908c5cdfd8ea9e4f1005b4cdb3f660a4b286f3f8"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"the-azuran","hash":"526b641fe2547535ac26402707044a2ece6e1231","ts":1768612463,"wall":"2026-01-16T20:14","msg":"Update README.md","body":"","parents":["a246bb0c1cd4800d8f7bd4132afcc93b216b6295"],"add":2,"del":1,"cadd":2,"cdel":1,"files":1},{"repo":"the-azuran","hash":"d7feb7212ff698fafa7fec58da82490b59901d3f","ts":1768613914,"wall":"2026-01-16T20:38","msg":"Update README.md","body":"","parents":["526b641fe2547535ac26402707044a2ece6e1231"],"add":13,"del":13,"cadd":13,"cdel":13,"files":1},{"repo":"new-belen-game","hash":"45f21372c72400bd8683807ab8e0d495d02b2332","ts":1768616101,"wall":"2026-01-16T21:15","msg":"Add web version (HTML/CSS/JS) and author credits","body":"- Pure frontend game, no server needed\n- Playable on any device with a browser\n- Same gameplay: preachers, conversations, world navigation\n- Mobile-friendly responsive design\n- Added author credits to both Python and web versions\n\nCo-Authored-By: Claude <noreply@anthropic.com>","parents":["fc8046db6be15cfef6cf3a7a8b7e615ec11c907a"],"add":1125,"del":0,"cadd":1125,"cdel":0,"files":4},{"repo":"new-belen-game","hash":"2d97a6a8f4aab3822de7a4541f7a131c94f06c5e","ts":1768616449,"wall":"2026-01-16T21:20","msg":"Rename web/ to docs/ for GitHub Pages","body":"","parents":["45f21372c72400bd8683807ab8e0d495d02b2332"],"add":0,"del":0,"cadd":0,"cdel":0,"files":3},{"repo":"new-belen-game","hash":"b1f4c207e2d872ea3eef4ceeae8ad2bb21225a41","ts":1768618189,"wall":"2026-01-16T21:49","msg":"Rewrite web dialogue system with sophisticated conversation engine","body":"- Add ConversationEngine class with weighted objection selection\n- Filter openers/responses based on NPC personality and mood\n- Prioritize counter-responses to match NPC objections\n- Track used responses to prevent repetition\n- Add personality hints to help player strategize\n- Refactor to modern ES6+ with Game, UI, WorldGenerator classes\n- Add CONFIG object for game constants\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["2d97a6a8f4aab3822de7a4541f7a131c94f06c5e"],"add":931,"del":619,"cadd":931,"cdel":619,"files":1},{"repo":"new-belen-game","hash":"91ecc99a18eba00627a1d2c8a46cac647f71c167","ts":1768618794,"wall":"2026-01-16T21:59","msg":"Fix conversation flow and randomize town count","body":"- Return to location after conversation to talk to other NPCs\n- Randomize number of towns in county (2-4)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["b1f4c207e2d872ea3eef4ceeae8ad2bb21225a41"],"add":3,"del":2,"cadd":3,"cdel":2,"files":1},{"repo":"new-belen-game","hash":"b102c5e4be2f3ad829c82e7260799d91fb8004df","ts":1768619020,"wall":"2026-01-16T22:03","msg":"Make all world generation fully random and procedural","body":"- NPCs per house: 1-5, store: 1-3, church: 1-4\n- Locations per street: 2-6\n- Streets per neighborhood: 2-5\n- Neighborhoods per town: 2-4\n- Towns per county: 2-5\n- Resistance chance: 20-40% per NPC\n- Added more name variety for stores, churches, neighborhoods\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["91ecc99a18eba00627a1d2c8a46cac647f71c167"],"add":19,"del":11,"cadd":19,"cdel":11,"files":1},{"repo":"margin","hash":"7a592cee331952b951ec84265fcb58de40f77c1e","ts":1769102663,"wall":"2026-01-22T12:24","msg":"Initial commit: Margin decentralized annotation platform","body":"Monorepo setup with three packages:\n- @margin/core: GUN database integration, SEA authentication, comment CRUD, user profiles, URL normalization\n- @margin/relay: Express + GUN relay server\n- @margin/web: React + Tailwind web application\n\nFeatures:\n- Decentralized P2P data sync via GUN\n- Cryptographic identity with SEA\n- Real-time comment subscriptions\n- Comment creation, editing, deletion with signature verification\n- User profiles\n- Environment variable support for relay URL\n\nCode audit completed:\n- Removed debug console.log statements\n- Fixed editComment GUN metadata bug (was spreading _ property)\n- Removed unused hooks and props\n- Added proper TypeScript declarations\n\nAuthor: The Azuran <The-Azuran@users.noreply.github.com>\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":[],"add":7639,"del":0,"cadd":3053,"cdel":0,"files":39},{"repo":"the-azuran","hash":"38fbc13e0a7cc4cfbad5bea1991afb996ce69d39","ts":1769104773,"wall":"2026-01-22T12:59","msg":"Update README.md","body":"","parents":["d7feb7212ff698fafa7fec58da82490b59901d3f"],"add":0,"del":0,"cadd":0,"cdel":0,"files":0},{"repo":"margin","hash":"ad7c32cf4c2c310d60f95b134a2ec78aac48782a","ts":1769130300,"wall":"2026-01-22T20:05","msg":"Add infinite comment nesting, cascade delete, and session persistence","body":"Features:\n- Infinite Reddit-style comment nesting (replies can have replies forever)\n- Visual depth indicators with reduced indentation after 8 levels\n- Cascade delete: deleting a comment removes all its replies recursively\n\nFixes:\n- Session persistence: users stay logged in across navigation and refresh\n- Added recallSession() to restore GUN sessions from localStorage on startup\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["7a592cee331952b951ec84265fcb58de40f77c1e"],"add":160,"del":41,"cadd":160,"cdel":41,"files":6},{"repo":"margin","hash":"768e19282627afc0b5485e41f03dbe910afe6669","ts":1769233429,"wall":"2026-01-24T00:43","msg":"Add Knowledge Vault, Theme Builder, and Margin Public Benefit License","body":"","parents":["ad7c32cf4c2c310d60f95b134a2ec78aac48782a"],"add":12221,"del":295,"cadd":12020,"cdel":294,"files":67},{"repo":"margin","hash":"5db8c6927a61cfe62a4f008116d81669d24ce39d","ts":1769292027,"wall":"2026-01-24T17:00","msg":"Add Typography System, Public Pages, and Theme Enhancements","body":"Typography & Content Styles:\n- Google Fonts integration with 120+ curated fonts\n- Font picker with search, categories, and live preview\n- Full typography controls (body, headings, code, links)\n- Layout controls (content width, code blocks, quotes, lists, images, dividers)\n- 6 preset content styles (Clean Minimal, Classic Serif, Modern Sans, etc.)\n- Per-page style support with global defaults\n\nPublic Pages:\n- Create and publish pages with margin:// URLs\n- TipTap rich text editor with full formatting\n- Publish vault notes as public pages\n- View/edit pages at /p/:username/:slug\n\nTheme System Improvements:\n- Numeric sliders for all style controls (border radius, shadows, etc.)\n- Advanced color picker with HSL/HSV/RGB modes and hue wheel\n- Real-time preview for all changes\n- Custom range slider styling\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["768e19282627afc0b5485e41f03dbe910afe6669"],"add":7680,"del":323,"cadd":7680,"cdel":323,"files":27},{"repo":"margin","hash":"8837d9ab675f9353e482355c8d6d230e0eb25d94","ts":1769338753,"wall":"2026-01-25T05:59","msg":"Add Unified Posts, Follows, @Mentions, and Username System Overhaul","body":"Features:\n- Unified Posts: Merge VaultNote and MarginPage into single MarginPost entity\n  - Publishing is now a visibility toggle (private → public)\n  - All content starts as draft, \"publish\" makes it public\n  - Dual storage: encrypted private copy + signed public projection\n- Social Follows: Follow/unfollow users with follower counts on profiles\n- @Mentions: Parse @username in comments and send notifications\n- Username System: Single source of truth architecture\n  - Registry (usernames.{alias}) is authoritative\n  - Reverse pointer (users.{pub}.username) for efficient lookups\n  - Removed legacy user-aliases fallback code\n  - Added nukeAccount() for cleaning up test accounts\n  - Auto-repair consistency on login\n\nNew files:\n- packages/core/src/posts.ts - Unified content module\n- packages/core/src/follows.ts - Social graph module\n- packages/core/src/ipfs.ts - IPFS image uploads via Helia\n- packages/web/src/context/PostsContext.tsx - React context for posts\n- packages/web/src/components/FollowButton.tsx - Follow/unfollow button\n- packages/web/src/components/vault/Post*.tsx - New post UI components\n- scripts/nuke-accounts.cjs - Utility to clean up test accounts\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["5db8c6927a61cfe62a4f008116d81669d24ce39d"],"add":5154,"del":1145,"cadd":4991,"cdel":1050,"files":34},{"repo":"margin","hash":"be9ef2f8641a4f6d75038d07628601f5dd46779f","ts":1769371934,"wall":"2026-01-25T15:12","msg":"Remove deprecated pages.ts and migrate to unified posts system","body":"- Delete pages.ts (842 lines) - all functionality now in posts.ts\n- Migrate PageViewer, PageEditor, UserPagesList to use posts.ts\n- Remove unused verify functions (verifyComment, verifyUsernameOwnership)\n- Add getPostBySlug helper for editing published posts\n\nThe keypair-based auth in GUN already proves authorship, making\nsignature verification redundant.\n\nHuman-AI collaboration: github.com/anthropics/claude-code","parents":["8837d9ab675f9353e482355c8d6d230e0eb25d94"],"add":196,"del":1165,"cadd":196,"cdel":1165,"files":8},{"repo":"margin","hash":"eb906a6b5d1adbc7d8f3ee6f1363f92bd3d361a1","ts":1769390561,"wall":"2026-01-25T20:22","msg":"Add Margin URL Protocol System (margin://) with unified navigation","body":"Implements a complete URL addressing system for all Margin content:\n- margin://username → User profiles\n- margin://username/slug → Public pages\n- margin://video/hash → P2P video streams\n- margin://vault/id → Private vault notes\n- margin://url/encoded → External URL comments\n\nCore Features:\n- Full parser/resolver/generator in @margin/core\n- Unified Omnibox component (accepts margin://, https://, @user, magnet:, ipfs://)\n- Quick navigation modal (Ctrl+K / Cmd+K)\n- Smart MarginLink component with auto-conversion\n- React hooks: useMarginUrl, useMarginNavigation, useProtocolHandler\n\nNew Routes:\n- /@:username → Profile lookup by username\n- /video/:infoHash → P2P video player page\n- /margin/* → Deep link handler for web sharing\n\nDesktop Protocol Handler:\n- Native margin:// protocol registration (macOS, Windows, Linux)\n- Single-instance lock with URL forwarding\n- Electron-builder protocol configuration\n\nWeb Protocol Fallback:\n- web+margin:// registration via navigator.registerProtocolHandler\n- /margin/* routes as universal web fallback\n\nThis enables sharing Margin content via clean URLs that work everywhere:\n- Native: margin://valis/hello-world\n- Web: https://margin.app/margin/valis/hello-world\n\nAuthor: Valis <valis@symbiont.systems>\nBuilt with AI assistance (Claude by Anthropic)","parents":["be9ef2f8641a4f6d75038d07628601f5dd46779f"],"add":4409,"del":55,"cadd":4333,"cdel":55,"files":18},{"repo":"margin","hash":"61c910c5764d55ec45bcd14e1fcc34d0d22040b7","ts":1769400672,"wall":"2026-01-25T23:11","msg":"Add Vault Power-Ups and Notion-Style Views with Custom Columns","body":"Session 17 - Vault Power-Ups (PKM Features):\n- Full-text search with Fuse.js (weighted: title 3x, content 1x, tags 2x)\n- Wiki links [[note title]] with autocomplete and navigation\n- Backlinks panel showing \"Notes that link to this one\"\n- Quick capture (Cmd+N) for rapid note creation\n- Tag cloud with multi-select filtering\n- Slash commands (/) for headings, lists, blocks, formatting\n- Knowledge graph view with force-directed visualization\n\nSession 18 - Notion-Style Views & Custom Columns:\n- 6 view modes: List, Gallery, Table, Board, Calendar, Graph\n- Gallery view: Responsive card grid with previews\n- Table view: Sortable columns with inline editing\n- Board view: Kanban (Pinned/Drafts/Published)\n- Calendar view: Monthly grid with post indicators\n- Custom columns system with 18 column types:\n  - Basic: text, checkbox, number, date, select, multiselect\n  - Easy: url, email, phone, rating, progress, currency, color, emoji\n  - Medium: person, relation, duration, location\n- Column definitions stored in localStorage\n- Type-safe value validation and formatting\n\nFiles created:\n- packages/core/src/custom-columns.ts\n- packages/web/src/components/{Gallery,Table,Board,Calendar,Graph}View.tsx\n- packages/web/src/components/{BacklinksPanel,QuickCapture,TagCloud}.tsx\n- packages/web/src/components/editor/{WikiLink,SlashCommand}*.ts(x)\n- packages/web/src/hooks/useVaultSearch.ts\n- packages/web/src/utils/tiptap.ts\n\nAuthor: Valis (@The-Azuran)\nBuilt with assistance from Claude (Anthropic) as a development tool.","parents":["eb906a6b5d1adbc7d8f3ee6f1363f92bd3d361a1"],"add":21667,"del":2199,"cadd":5458,"cdel":160,"files":31},{"repo":"margin","hash":"774b028a877e0ff0e7089fe77a1132193171da3d","ts":1769400827,"wall":"2026-01-25T23:13","msg":"Add WebTorrent P2P Video, Desktop Preload, Admin Panel, and Component Enhancements","body":"WebTorrent Video System:\n- packages/core/src/webtorrent.ts - P2P video sharing via WebTorrent\n- packages/core/src/video-compress.ts - FFmpeg video compression (desktop)\n- packages/relay/src/seeding.ts - Relay server torrent seeding\n- packages/web/src/components/VideoPlayer.tsx - Streaming video player\n- packages/web/src/components/editor/VideoExtension.ts - TipTap video node\n- packages/web/src/components/editor/VideoNodeView.tsx - Video embed renderer\n- packages/web/src/context/WebTorrentContext.tsx - WebTorrent provider\n\nDesktop App:\n- packages/desktop/src/preload.ts - Electron preload script\n- packages/desktop/tsconfig.json - Desktop TypeScript config\n- packages/web/src/types/desktop.d.ts - Desktop API type definitions\n\nAdmin Panel:\n- packages/web/src/pages/Admin.tsx - Admin dashboard\n- packages/web/src/components/admin/AccountsPanel.tsx - User management\n- packages/web/src/components/admin/ModerationPanel.tsx - Content moderation\n- packages/web/src/components/admin/SystemPanel.tsx - System stats\n- packages/web/src/components/admin/TokenPanel.tsx - Token economy\n\nComponent Improvements:\n- ImageUploader.tsx - IPFS image upload component\n- IPFSImage.tsx - IPFS image display with gateway fallback\n- Enhanced EmojiPicker, ProfileCard, AuthForm, NetworkStatus\n- Vite config updates for desktop/web builds\n\nAuthor: Valis (@The-Azuran)\nBuilt with assistance from Claude (Anthropic) as a development tool.","parents":["61c910c5764d55ec45bcd14e1fcc34d0d22040b7"],"add":5067,"del":583,"cadd":5034,"cdel":581,"files":40},{"repo":"margin","hash":"68f2d5012f9532d825c430c34b085de9e068afb2","ts":1769426239,"wall":"2026-01-26T06:17","msg":"Add @margin/db local-first database layer and testing infrastructure","body":"## New Package: @margin/db\nComplete CRDT-based database layer as GUN replacement (47 TypeScript files):\n- Identity: Ed25519 keypairs, signing, XChaCha20-Poly1305 encryption\n- Storage: cr-sqlite wrapper with CRDT sync support\n- Sync: RelaySyncAdapter with changeset protocol\n- Query: Fluent query builder with subscriptions\n- Collections: Full CRUD API with automatic signing\n- Users: Username registry, profiles, follows\n- URLs: Normalization, margin:// protocol support\n- Mentions: @mention parsing and resolution\n- Notifications: Local notification system\n- Discovery: Trending, social discovery, search\n- Media: IPFS/WebTorrent integration points\n- Migration: GUN compatibility adapter layer\n\n## Core Utilities\n- errors.ts: Typed error classes (MarginError, AuthError, etc.)\n- logger.ts: Configurable logging with log levels\n- constants.ts: Centralized timeouts, limits, storage keys\n\n## Testing Infrastructure\n- Vitest configuration for all packages\n- Test suites for @margin/db modules\n- Mock utilities for GUN testing\n\n## Component Improvements\n- Extracted TableView into modular components\n- Split TipTapEditor toolbar into separate files\n- Added custom column editors (Duration, Location, Person, Relation)\n\n## Note\n@margin/db integration with main app is blocked by cr-sqlite WASM loading\nissues in Vite. The code is complete and ready for integration once the\nbundler configuration is resolved. App continues to run on GUN backend.\n\nCo-Authored-By: Claude <noreply@anthropic.com>","parents":["774b028a877e0ff0e7089fe77a1132193171da3d"],"add":19513,"del":1923,"cadd":17203,"cdel":1825,"files":86},{"repo":"margin","hash":"ccdbe8d646063f8fd7d180073abf25caabfc188c","ts":1769534398,"wall":"2026-01-27T12:19","msg":"Add relay file upload and local image storage for profile pictures","body":"- Add POST /upload endpoint to relay server for image uploads\n- Store uploaded files with SHA-256 hash names (content-addressed)\n- Serve files statically at /files/* with CORS/COEP headers for Electron\n- Add local-images.ts module for IndexedDB blob storage\n- Simplify ImageUploader to use relay instead of IPFS gateways\n- Update ProfileCard to use direct URLs for avatars\n- Clean up debug logging in IPFSImage component\n- Add rate limiting (50 uploads/hour) and file validation\n\nProfile images now work reliably without depending on IPFS gateway\navailability. Content-addressed storage enables future IPFS migration.","parents":["68f2d5012f9532d825c430c34b085de9e068afb2"],"add":1257,"del":269,"cadd":1250,"cdel":268,"files":8},{"repo":"margin","hash":"df4cd4467912d4d29f3e424a8fd5538f5991975f","ts":1769543070,"wall":"2026-01-27T14:44","msg":"Complete GUN→SQLite migration, UI component library, and visual polish","body":"Major architectural change:\n- Remove GUN.js entirely from codebase\n- Migrate all data operations to @margin/db (SQLite + cr-sqlite CRDTs)\n- All modules now use local-first Ed25519-signed data layer\n- Delete gun.ts, gun.d.ts, and all GUN-related tests\n\nUI Component Library:\n- EmptyState: Consistent empty states with icons\n- Skeleton: Loading placeholders (post, profile, text, grid)\n- LoadingSpinner: Configurable spinner with sizes\n- Avatar: User avatars with status indicators and stacking\n- Form: Input, Select, TextArea, Checkbox, Button variants\n- Navigation: Tabs, Breadcrumbs, Pagination\n- Icon: Unified icon component with 40+ icons\n- DataDisplay: Badge, Tag, Stat, Progress components\n- Transition: FadeIn, SlideIn, StaggeredList animations\n\nVisual Polish:\n- Typography system with prose classes\n- Card variants (default, ghost, interactive, accent)\n- Layout utilities (stack, cluster, grid, sidebar)\n- Form styling with validation states\n- Animation utilities (fade, slide, scale, pulse, shimmer)\n- Enhanced Tailwind config with custom spacing/animations\n\nComponent Integration:\n- Apply new components to PostList, CommentList, Profile\n- Consistent loading states and empty states across app\n- Staggered list animations for content feeds\n\nCleanup:\n- Delete outdated test files (auth-flow, migration)\n- Delete gift-tokens.ts (used old API)\n- Align vitest to v4.0.18 across packages\n- Fix TypeScript errors in test files\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["ccdbe8d646063f8fd7d180073abf25caabfc188c"],"add":18612,"del":10615,"cadd":18452,"cdel":9774,"files":138},{"repo":"margin","hash":"436d1a9ff5777d6a27484bb70666bd8b4c444f10","ts":1769543343,"wall":"2026-01-27T14:49","msg":"Fix author attribution in desktop package","body":"Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["df4cd4467912d4d29f3e424a8fd5538f5991975f"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"margin","hash":"1bc6ee92de93c2455b181a4918c4d01447414731","ts":1769543981,"wall":"2026-01-27T14:59","msg":"Add protected admin route at /~ with env-based access control","body":"- Route changed from /admin to /~ (obscure path)\n- Access controlled via VITE_ADMIN_PUBLIC_KEY env variable\n- Non-admins silently redirected to home (no 403, no hint route exists)\n- Merged Debug page into Admin as a tab\n- Removed [DBG] link from header\n- Added .env.example with config instructions\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["436d1a9ff5777d6a27484bb70666bd8b4c444f10"],"add":53,"del":37,"cadd":44,"cdel":26,"files":5},{"repo":"margin","hash":"a073d18d3793eb6b1e87caf02278968a57b768bd","ts":1769617316,"wall":"2026-01-28T11:21","msg":"WIP: Final v1 state before simplification","body":"This commit preserves the complete CRDT-based architecture including:\n- cr-sqlite database layer with sync\n- Relay server with federation\n- Desktop Electron app\n- Token economy system\n- Full social features (comments, reactions, follows)\n\nArchiving to branch archive/v1-crdt for reference.","parents":["1bc6ee92de93c2455b181a4918c4d01447414731"],"add":18030,"del":365,"cadd":17691,"cdel":363,"files":107},{"repo":"margin","hash":"57218874ed75b260f78a6ad1049c5805c96a9139","ts":1769617609,"wall":"2026-01-28T11:26","msg":"chore: Clear for v2 rebuild","body":"- Removed all v1 packages (preserved in archive/v1-crdt branch)\n- Updated README for v2 direction\n- Updated .gitignore for new monorepo structure\n- Added V2_BUILD_PLAN.md with detailed roadmap\n- Added ARCHIVE_INDEX.md documenting reusable v1 code","parents":["a073d18d3793eb6b1e87caf02278968a57b768bd"],"add":193,"del":101480,"cadd":177,"cdel":80555,"files":333},{"repo":"margin","hash":"db8019d6ecb5fb2d11b75310379d3d2561183a67","ts":1769618443,"wall":"2026-01-28T11:40","msg":"docs: Add After Action Records (AAR) for workflow documentation","body":"- Captures lessons learned from Phase 0\n- Defines workflow patterns (Archive-First, Phased Execution)\n- Documents anti-patterns to avoid\n- Includes templates for future entries\n- Tracks metrics and decisions","parents":["57218874ed75b260f78a6ad1049c5805c96a9139"],"add":415,"del":0,"cadd":415,"cdel":0,"files":1},{"repo":"margin","hash":"4c74f962b374b52267ea9f629beb77f36689ed72","ts":1769619072,"wall":"2026-01-28T11:51","msg":"feat: Phase 1 - Monorepo scaffold complete","body":"Subphases completed:\n- 1.1: Initialize workspace (pnpm workspaces, .npmrc)\n- 1.2: TypeScript configuration (base config, project references)\n- 1.3: Create package directories (core, storage, features, ui, web, extension)\n- 1.4: Development tooling (Vitest, Prettier, VS Code settings)\n- 1.5: Git configuration (updated .gitignore)\n\nPackages created:\n- @margin/core: Types, utilities, crypto (placeholder)\n- @margin/storage: Database abstraction (placeholder)\n- @margin/features: Business logic modules (placeholder)\n- @margin/ui: React components (placeholder)\n- @margin/web: Main PWA with Vite + Tailwind\n\nBuild verified: pnpm build succeeds for all packages","parents":["db8019d6ecb5fb2d11b75310379d3d2561183a67"],"add":5844,"del":1,"cadd":5413,"cdel":0,"files":36},{"repo":"margin","hash":"a6f23fd9cdda14ccd8e3305b08f9969ac02a1a73","ts":1769619392,"wall":"2026-01-28T11:56","msg":"docs: Update AAR with Phase 1 lessons learned","body":"Added:\n- 5 new lesson entries for Phase 1\n- Decisions D-003, D-004, D-005\n- Phase 1 metrics\n- Updated cumulative metrics table","parents":["4c74f962b374b52267ea9f629beb77f36689ed72"],"add":140,"del":2,"cadd":140,"cdel":2,"files":1},{"repo":"margin","hash":"7c47030c9bf9f2bde6de023a30b84261283ca528","ts":1769620124,"wall":"2026-01-28T12:08","msg":"docs: Add industry research validation to AAR","body":"Added based on 2025-2026 best practices research:\n\nResearch Validation Section:\n- Monorepo architecture validated (pnpm + TS refs)\n- Local-first architecture validated (IndexedDB + Dexie)\n- Documentation practices exceed standards\n- AI-assisted workflow matches expert recommendations\n- Identified gaps: CI/CD, live types, test coverage\n\nNew Workflow Patterns:\n- AI Context Packing (from Addy Osmani)\n- Test-With-Feature Development\n- Local-First Data Flow\n\nNew Anti-Patterns:\n- AI Autopilot\n- Network-First Thinking\n- CRDT Complexity Trap\n- Tests-After Development\n\nAdded Reference Sources section with 15+ citations","parents":["a6f23fd9cdda14ccd8e3305b08f9969ac02a1a73"],"add":366,"del":0,"cadd":366,"cdel":0,"files":1},{"repo":"margin","hash":"5efccfe677199dbf31754855075012cf73415f60","ts":1769622019,"wall":"2026-01-28T12:40","msg":"feat: Phase 2 & 3 - Core types, utils, crypto, and storage layer","body":"Phase 2 (@margin/core):\n- Domain types: Bookmark, Note, Feed, FeedItem, Tag, Settings\n- Utility functions: url, id, date, text helpers\n- Cryptography: AES-GCM encryption, ECDSA signing, key derivation\n- 98 tests passing\n\nPhase 3 (@margin/storage):\n- Storage adapter interface with Dexie and Memory implementations\n- Repositories: bookmarks, notes, feeds, settings, tags\n- Factory pattern for unified storage access\n- 73 tests passing (171 total)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["7c47030c9bf9f2bde6de023a30b84261283ca528"],"add":6105,"del":27,"cadd":6098,"cdel":24,"files":42},{"repo":"margin","hash":"8d83ab4d0384e45147f3b727d71b7f026b54eb7b","ts":1769742065,"wall":"2026-01-29T22:01","msg":"feat: Phase 4+ PWA, API, features, UI components, and expansion plans","body":"PWA (apps/web):\n- Full page structure (Home, Bookmarks, Notes, Feeds, Settings)\n- TipTap rich text editor with extensions (Link, Color, Highlight, etc.)\n- Ticker tape component for RSS headlines\n- App shell with navigation, offline indicator\n- React Query integration with service layer\n- Integration tests for all entity flows\n\nAPI Server (apps/api):\n- Express server with feed proxy for CORS bypass\n- 5-minute caching for RSS feeds\n\nFeatures Package:\n- Bookmarks, Notes, Feeds, Search, Tags services\n- Factory pattern for service instantiation\n\nUI Package:\n- Editor components (toolbar, bubble menu, link/color popovers)\n- Ticker tape with settings\n- Layout primitives (sidebar, header)\n- Entity-specific components (bookmark cards, note cards, feed list)\n\nPlanning Documents:\n- PLAN_DISSENTER.md: Web-wide commenting system\n- PLAN_PUBLISHING.md: Notes as public blogs\n- PLAN_MONETIZATION.md: Creator economy, ads, paywalls\n- PLAN_FEED_DIRECTORY.md: RSS feed discovery approaches\n- PLAN_SOCIAL.md: Non-predatory social features\n- PLAN_DECENTRALIZED_STACK.md: IPFS + Arweave + RSS architecture\n\nAAR updated with research on decentralized storage, competitive analysis,\nand planning methodology documentation.","parents":["5efccfe677199dbf31754855075012cf73415f60"],"add":37978,"del":534,"cadd":37853,"cdel":529,"files":177},{"repo":"margin","hash":"4f07174248dad4f24035b5e82037a49f428e5771","ts":1769744687,"wall":"2026-01-29T22:44","msg":"docs: Add government data and multi-ticker architecture plans","body":"PLAN_GOVERNMENT_DATA.md:\n- Research on NOAA, USGS, NASA, FDA, SEC, EPA APIs\n- All free, high-value data sources\n- Monetization through curation, presentation, alerts\n- Integration with ticker system\n\nPLAN_TICKER_ARCHITECTURE.md:\n- Multi-channel ticker system design\n- Modes: unified, split, stacked, focus\n- User presets: Simple, News Junkie, Investor, Health Conscious\n- Data flow from sources through channels to display\n\nAAR.md:\n- Session summary: strategic planning & architecture\n- MVP definition and value proposition\n- Design philosophy: invisible decentralization\n- Updated active plan documents table","parents":["8d83ab4d0384e45147f3b727d71b7f026b54eb7b"],"add":769,"del":0,"cadd":769,"cdel":0,"files":3},{"repo":"margin","hash":"7b8d4868e7ae5680055f352f7219ab3cf7bbad0e","ts":1769745014,"wall":"2026-01-29T22:50","msg":"docs: Add theming and customization plan","body":"PLAN_THEMING.md:\n- Preset themes: Clean, Cyberpunk, Synthwave, Hacker, Paper, Midnight\n- Custom theme builder with full color/font/effects control\n- Customizable logo (Minimal, Neon, Chrome, ASCII, Glitch, Custom SVG)\n- Theme export/import for sharing\n- CSS variable system with Tailwind integration","parents":["4f07174248dad4f24035b5e82037a49f428e5771"],"add":502,"del":0,"cadd":502,"cdel":0,"files":2},{"repo":"margin","hash":"12ac5fefe7dd52d256f34c2220fa31de013ad137","ts":1769842163,"wall":"2026-01-31T01:49","msg":"feat: NoteViewer component with View/Edit toggle and typography-first design","body":"- Add NoteViewer component with read-only note display\n- Add ReadingProgressBar for scroll progress indication\n- Add utility functions (reading time, word count, relative time)\n- Create NoteViewerPage with actions (pin, archive, delete)\n- Update router: /notes/:id → Viewer, /notes/:id/edit → Editor\n- Update NoteEditorPage with \"Done\" button and back-to-viewer flow\n- Fix slash commands with tippy.js CSS import\n- Add ImageUploadPopover for image insertion UI\n- Add 32 new tests (utils + NoteViewer)\n- Document storage research in PLAN_STORAGE_OPTIONS.md\n- Update AAR with lessons learned from debugging session\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["7b8d4868e7ae5680055f352f7219ab3cf7bbad0e"],"add":2349,"del":19,"cadd":2346,"cdel":18,"files":21},{"repo":"margin","hash":"0cd7b66cd09e707b74b3deee854ce6ff0289ae4c","ts":1769920932,"wall":"2026-01-31T23:42","msg":"feat: Browser extension MVP with comprehensive metadata extraction","body":"Chrome extension (Manifest V3) for capturing bookmarks:\n- Popup UI with tag input and quick save\n- Content script with metadata extraction\n- Service worker for capture queue management\n- Alt+Shift+S keyboard shortcut\n- Selection popup for text highlights\n\nMetadata extraction (~700 lines):\n- Open Graph (title, description, image, video, audio)\n- Twitter Cards (card type, site, creator, player)\n- JSON-LD structured data (Article, NewsArticle, etc.)\n- RSS/Atom/JSON feed discovery via <link> tags\n- YouTube-specific extraction (video title, channel, thumbnail)\n- Reading time estimation and word count\n\nExtension ↔ PWA communication:\n- Uses chrome.storage.local + externally_connectable\n- Auto-detection via postMessage (no manual ID config)\n- Feed discovery triggers \"Subscribe\" toast in PWA\n\nAlso includes:\n- Updated documentation structure (docs/status, docs/future)\n- CLAUDE.md with AI assistant guidelines\n- CONTRIBUTING.md\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["12ac5fefe7dd52d256f34c2220fa31de013ad137"],"add":10814,"del":60,"cadd":10702,"cdel":60,"files":76},{"repo":"margin","hash":"2ae3b7c1c35ec0dd22906faa06cd014a97be7d9b","ts":1769921004,"wall":"2026-01-31T23:43","msg":"feat: Enhanced capture, highlights, ticker, and editor improvements","body":"Capture System:\n- GlobalCapture modal (Cmd+K) with URL/feed detection\n- CapturePage for direct capture\n- useGlobalShortcuts hook for keyboard bindings\n\nHighlights:\n- Highlight entity on bookmarks with color labels\n- AddHighlightModal, HighlightCard, HighlightList components\n- Highlight CRUD hooks in useBookmarks\n\nTicker System:\n- TickerContainer with channel-based display\n- ChannelSelector, ChannelTicker components\n- TickerStack, TickerSplit, TickerFocus layouts\n- useTickerSystem hook with templates\n- ticker-config types\n\nEditor Extensions:\n- BookmarkCard TipTap extension with NodeView\n- FeedItemCard TipTap extension with NodeView\n- ReferenceSelectorMenu for @ mentions\n- BookmarkPopover for link insertion\n\nNotes:\n- Export to markdown (export.ts, markdown.ts)\n- BulkExportDialog, ExportMenu components\n- Enhanced links extraction\n\nCore:\n- URL validation (block dangerous protocols)\n- Ticker types and config types\n- Enhanced bookmark/feed/note types\n\nSettings:\n- Expanded SettingsPage with ticker config\n- Theme and display options\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["0cd7b66cd09e707b74b3deee854ce6ff0289ae4c"],"add":11538,"del":472,"cadd":11527,"cdel":469,"files":87},{"repo":"margin","hash":"04c3b0ff99dd61864c9a10e1661d73f3a271c448","ts":1769925760,"wall":"2026-02-01T01:02","msg":"feat: Puma logo and feed discovery on bookmarks","body":"Logo:\n- Replace \"M\" logo with puma icon throughout\n- Add puma.png to web app public folder\n- Update extension icons (16/48/128px)\n- Update favicon for browser tab\n- Crop image tighter for better small-size display\n\nFeed Discovery:\n- Add DiscoveredFeed type to bookmark\n- Store discovered feeds when capturing bookmarks\n- Display \"Feeds Found\" section on BookmarkDetailPage\n- Subscribe button for each discovered feed\n- Fix data flow: extension sends feeds at root level, PWA now checks both locations\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["2ae3b7c1c35ec0dd22906faa06cd014a97be7d9b"],"add":106,"del":21,"cadd":106,"cdel":21,"files":18},{"repo":"margin","hash":"8e07204f72593c05d5b60636c1820372054e907f","ts":1769928286,"wall":"2026-02-01T01:44","msg":"docs: Add UI customization research and brainstorming","body":"- Research on PKM app patterns (Obsidian, Notion, Logseq)\n- Drag-and-drop best practices and libraries\n- Tiered customization ideas (quick wins to major features)\n- Current architecture analysis and flexibility assessment\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["04c3b0ff99dd61864c9a10e1661d73f3a271c448"],"add":248,"del":0,"cadd":248,"cdel":0,"files":2},{"repo":"groundwork","hash":"918fac1a408710dcebfbfdb7ce4c1b49b0e71985","ts":1769974680,"wall":"2026-02-01T14:38","msg":"Initial commit: Eureka site analysis pipeline","body":"Complete GIS analysis workflow for 40-acre Eureka, NV property:\n\nScripts:\n- 01_download_data.py: Data acquisition from federal sources\n- 02_acquire_supplemental.py: Supplemental data documentation\n- 03_hydrology.py: Flow analysis, water harvesting identification\n- 04_soils.py: SSURGO soil analysis and interpretations\n- 05_context_layers.py: Land cover, climate, geology processing\n- 06_suitability.py: Multi-criteria suitability models\n\nAnalysis outputs:\n- Terrain: slope, aspect, hillshade, contours\n- Hydrology: flow direction/accumulation, streams, subbasins\n- Water harvesting: 2.74 acres pond-suitable, 38 acres overall suitable\n- Suitability zones: water storage, structures, cultivation\n\nDocumentation:\n- SYMBIONT-SYSTEMS.md: Organizational strategy\n- eureka-site-report.md: Full technical report\n- QGIS setup guide\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":[],"add":4995,"del":0,"cadd":3878,"cdel":0,"files":28},{"repo":"groundwork","hash":"47d047eb158959b4cb3aed5a34f3f954d033177f","ts":1769975449,"wall":"2026-02-01T14:50","msg":"Add manual data download guide","body":"Step-by-step instructions for downloading:\n- Soil polygons from Web Soil Survey\n- NLCD land cover from MRLC\n- PRISM climate data\n- Geology from USGS (optional)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["918fac1a408710dcebfbfdb7ce4c1b49b0e71985"],"add":225,"del":0,"cadd":225,"cdel":0,"files":1},{"repo":"groundwork","hash":"5e38b5b66af4707bf1cdf18a00dfc31950126ab5","ts":1769975866,"wall":"2026-02-01T14:57","msg":"Add programmatically acquired supplemental data","body":"Data downloaded via APIs (no manual downloads needed):\n- SSURGO soil polygons via Soil Data Access REST API\n- NLCD 2021 land cover via PyGeoHydro\n- Climate normals via Open-Meteo (30-year 1991-2020)\n\nProcessing outputs:\n- soils_clipped.gpkg: Soil polygons clipped to parcel\n- landcover_summary.json: NLCD class statistics\n- climate_summary.json: Temperature and precipitation normals\n\nUpdated 04_soils.py to find GeoJSON polygon files.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["47d047eb158959b4cb3aed5a34f3f954d033177f"],"add":116,"del":29,"cadd":4,"cdel":2,"files":7},{"repo":"groundwork","hash":"3176badb40ff8d739234987e761cb0b2fb97b8e2","ts":1769975977,"wall":"2026-02-01T14:59","msg":"Add data API reference documentation","body":"Documents working methods for programmatic GIS data acquisition:\n- SSURGO: SDA REST API with SQL queries (pysda broken with Shapely 2.x)\n- NLCD: PyGeoHydro package (must pass GeoDataFrame, not bbox tuple)\n- Climate: Open-Meteo Archive API (free, no auth)\n- DEM: TNM API or py3dep\n- Geology: Manual download from USGS\n\nIncludes code examples, gotchas, and what doesn't work.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["5e38b5b66af4707bf1cdf18a00dfc31950126ab5"],"add":327,"del":0,"cadd":327,"cdel":0,"files":1},{"repo":"groundwork","hash":"f4960ae21c8bce7d2043dd98e733cd2ad74bfced","ts":1769984698,"wall":"2026-02-01T17:24","msg":"Add comprehensive site analysis, flood zones, and silvopasture research","body":"Data additions:\n- FEMA flood zone layer (Zone A covers 100% of property)\n- NBMG 500K geology (Quaternary alluvium/playa deposits)\n- Clipped geology and flood zone layers\n\nDocumentation:\n- Silvopasture research plan with species selection, dryland approaches\n- Capillary nodes design for groundwater access/water harvesting\n- Geodesic dome analysis for flood zone-compliant structures\n- Integrated site analysis combining all findings\n- Complete PDF report for quick reference\n- Corrected aspect analysis (not meaningful on flat terrain)\n\nOutputs:\n- QGIS project with all layers styled and organized\n- PDF maps (base, terrain, hydrology, soils, suitability)\n- PyQGIS script for headless map generation\n\nKey findings:\n- 100% Zone A flood zone = opportunity for Ak-Chin flood farming\n- 93% flat terrain ideal for swales and earthworks\n- 11.3\" rainfall requires water harvesting as primary strategy\n- 5-10 acres intensive silvopasture achievable with 15-20 sheep/goats\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["3176badb40ff8d739234987e761cb0b2fb97b8e2"],"add":139256,"del":52,"cadd":2446,"cdel":37,"files":34},{"repo":"groundwork","hash":"e7e4640189919858acfbb2e14355ea59b32ba075","ts":1769994456,"wall":"2026-02-01T20:07","msg":"groundwork: add project configuration module","body":"Step 1 of Groundwork build - LandProject class for managing:\n- Project metadata and directory structure\n- Automatic UTM zone detection from coordinates\n- Bounds from coordinates or explicit bounding box\n- Config save/load for project persistence\n\nTested: Creates project for Eureka coords, correctly identifies UTM 11N\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["f4960ae21c8bce7d2043dd98e733cd2ad74bfced"],"add":245,"del":0,"cadd":245,"cdel":0,"files":2},{"repo":"groundwork","hash":"bb33aa325a9318e9c3697e2261d11db0972fce24","ts":1769994605,"wall":"2026-02-01T20:10","msg":"groundwork: add elevation acquisition","body":"Step 2 - Fetch DEM from USGS 3DEP using py3dep:\n- Supports 10m and 30m resolution\n- Saves GeoTIFF + JSON summary with elevation stats\n- Handles both tuple and GeoDataFrame bounds\n\nTested: Fetches DEM for Eureka coords, elevation 4712-4751 ft\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["e7e4640189919858acfbb2e14355ea59b32ba075"],"add":128,"del":0,"cadd":128,"cdel":0,"files":2},{"repo":"groundwork","hash":"78733cbdadc2be98dbca90c2ef9b7456ffde957f","ts":1769994802,"wall":"2026-02-01T20:13","msg":"groundwork: add terrain analysis","body":"Step 3 - Calculate slope, aspect, hillshade from DEM:\n- Reprojects DEM to project UTM zone\n- Calculates slope in degrees and percent\n- Calculates aspect with flat-area detection\n- Generates hillshade for visualization\n\nTested: Eureka terrain shows 0.42° mean slope (flat terrain)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["bb33aa325a9318e9c3697e2261d11db0972fce24"],"add":281,"del":0,"cadd":281,"cdel":0,"files":2},{"repo":"groundwork","hash":"cb3996d4b186c3c9dca9d3756985418f2c2c9e98","ts":1769994987,"wall":"2026-02-01T20:16","msg":"groundwork: add hydrology analysis","body":"Step 4 - WhiteboxTools-based hydrology workflow:\n- Depression filling (breach algorithm)\n- D8 flow direction and accumulation\n- Stream network extraction\n- Water harvesting site identification (swale/pond candidates)\n\nTested: Eureka project shows flow patterns and harvest sites\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["78733cbdadc2be98dbca90c2ef9b7456ffde957f"],"add":245,"del":0,"cadd":245,"cdel":0,"files":1},{"repo":"groundwork","hash":"7d58fc310708d3fda6c0062fe5711fa21e544da0","ts":1769995325,"wall":"2026-02-01T20:22","msg":"groundwork: add soils acquisition","body":"Step 5 - NRCS SSURGO via SDA REST API:\n- Fetches soil map unit polygons for project bounds\n- Fetches component data (hydgrp, drainage, taxonomy)\n- Calculates area statistics per map unit\n\nNote: Polygons may extend beyond project bounds; clip if needed\n\nTested: Fetches Batan-Ocala association for Eureka area","parents":["cb3996d4b186c3c9dca9d3756985418f2c2c9e98"],"add":214,"del":0,"cadd":214,"cdel":0,"files":1},{"repo":"groundwork","hash":"88c126a5254c2209cad7d1cd24de22e82872e64e","ts":1769995466,"wall":"2026-02-01T20:24","msg":"docs: add authorship policy to standing orders","body":"All code authored by Rowan Valle. AI assistant (Claude Code) is a tool\nfor centaur pair coding, not a co-author.","parents":["7d58fc310708d3fda6c0062fe5711fa21e544da0"],"add":15,"del":1,"cadd":15,"cdel":1,"files":1},{"repo":"groundwork","hash":"7b0858619ef54124b4cc8937e4c78276edd26e71","ts":1769995520,"wall":"2026-02-01T20:25","msg":"groundwork: add climate acquisition","body":"Step 6 - Open-Meteo Archive API for 30-year climate normals:\n- Temperature stats (mean, extremes)\n- Precipitation (annual, monthly)\n- Growing season estimate\n\nTested: Eureka shows 11.3in precip, 50.8F mean - matches prior research","parents":["88c126a5254c2209cad7d1cd24de22e82872e64e"],"add":151,"del":0,"cadd":151,"cdel":0,"files":1},{"repo":"groundwork","hash":"8226aba3df23d2f035cd28573c5300a3e02a3e36","ts":1769995603,"wall":"2026-02-01T20:26","msg":"groundwork: add flood zone acquisition","body":"Step 7 - FEMA NFHL REST API:\n- Fetches flood hazard zones for project bounds\n- Identifies Special Flood Hazard Areas (Zone A, AE, V, etc.)\n- Calculates area by zone\n\nTested: Eureka shows Zone A coverage (100-year floodplain)","parents":["7b0858619ef54124b4cc8937e4c78276edd26e71"],"add":134,"del":0,"cadd":134,"cdel":0,"files":1},{"repo":"groundwork","hash":"68f2bc72ac4d2c58e8e2b97d8218f14aa2cfccc5","ts":1769995745,"wall":"2026-02-01T20:29","msg":"groundwork: add suitability analysis","body":"Step 8 - Multi-criteria suitability modeling:\n- Water storage suitability (flat + high flow + low elevation)\n- Structure suitability (flat + low flow + high elevation)\n- Cultivation suitability (optimal slope/flow/elevation)\n- Generates vector zones for recommended uses\n\nTested: Eureka shows 15% water storage, 87% structure high suitability","parents":["8226aba3df23d2f035cd28573c5300a3e02a3e36"],"add":292,"del":0,"cadd":292,"cdel":0,"files":1},{"repo":"groundwork","hash":"5d2daf5bb3da2f2611007c9ccd8a7e0a54f1e4e3","ts":1769995819,"wall":"2026-02-01T20:30","msg":"groundwork: add report generation","body":"Step 9 - HTML report from analysis summaries:\n- Collects all JSON summaries from project directories\n- Generates styled HTML report with metrics and tables\n- Includes location, elevation, terrain, climate, soils, flood, suitability\n\nTested: Generates 5KB report for Eureka project","parents":["68f2bc72ac4d2c58e8e2b97d8218f14aa2cfccc5"],"add":275,"del":0,"cadd":275,"cdel":0,"files":2},{"repo":"groundwork","hash":"e5a2c4849388788ce7ecffd51fec187225c7a92d","ts":1769995902,"wall":"2026-02-01T20:31","msg":"groundwork: add web map generation","body":"Step 10 - PMTiles + MapLibre GL JS viewer:\n- Collects GeoJSON layers (streams, suitability, water harvest)\n- Generates PMTiles via tippecanoe\n- Creates interactive HTML viewer with layer toggles\n\nTested: Creates 326KB PMTiles + viewer for Eureka project","parents":["5d2daf5bb3da2f2611007c9ccd8a7e0a54f1e4e3"],"add":221,"del":0,"cadd":221,"cdel":0,"files":1},{"repo":"groundwork","hash":"12057b3ebcf3bee8389c05c916ff77508a70350a","ts":1770056959,"wall":"2026-02-02T13:29","msg":"Complete Phase 4: Server-ready features for Groundwork","body":"This commit implements all Phase 4 features making Groundwork production-ready:\n\nPhase 4.0 - Technical Debt Cleanup:\n- Add missing dependencies (fastapi, pydantic, httpx, aiosqlite)\n- Fix silent error returns in acquire modules (now raise exceptions)\n- Fix slope percent calculation in terrain.py\n- Add unit tests (65 tests total)\n\nPhase 4.1-4.3 - Server Infrastructure:\n- FastAPI server with /api/v1/analyze endpoint\n- Batch processing with CSV input and parallel workers\n- Job queue with SQLite backend and webhook callbacks\n\nPhase 4.4 - Custom AOI Upload:\n- Geometry parser supporting GeoJSON, WKT, KML\n- LandProject.from_geometry() factory method\n- CLI --aoi flag and API geometry field\n\nPhase 4.5 - PDF Report Generation:\n- WeasyPrint-based PDF output with print-optimized CSS\n- CLI --pdf flag and API generate_pdf option\n\nPhase 4.6 - Cloud Storage Integration:\n- Storage abstraction with local and S3 backends\n- Automatic upload of outputs to configured storage\n- Signed URL generation for private S3 buckets\n\nAlso includes:\n- Plugin architecture with protocols and registry\n- 7 new data providers (wildfire, OSM, landcover, solar, ownership, hydrography, groundwater)\n- TUI wizard interface\n- Structured logging with --debug flag","parents":["e5a2c4849388788ce7ecffd51fec187225c7a92d"],"add":11978,"del":155,"cadd":11978,"cdel":155,"files":78},{"repo":"groundwork","hash":"73d856658bf889c70bc3c21c0d8f6f61535e31d1","ts":1770057238,"wall":"2026-02-02T13:33","msg":"docs: update technical roadmap with Groundwork Phase 4 completion","body":"- Update SYMBIONT-SYSTEMS.md technical roadmap to reflect actual\n  Groundwork progress through Phase 4\n- Add comprehensive README.md to groundwork/ package with full\n  documentation of features, installation, usage, and API examples\n- Mark all Phase 4 features as complete: custom AOI, PDF reports,\n  cloud storage, test suite","parents":["12057b3ebcf3bee8389c05c916ff77508a70350a"],"add":320,"del":21,"cadd":320,"cdel":21,"files":2},{"repo":"groundwork","hash":"9932ed83acfecbf06cbaace0ecdfd6e05d0f7078","ts":1770058796,"wall":"2026-02-02T13:59","msg":"security: fix path traversal and webhook SSRF vulnerabilities","body":"Phase 4.7 Security Hardening:\n\nPath Traversal Prevention:\n- Add _validate_path() to LocalStorage using pathlib resolve()+relative_to()\n- Apply validation to all storage methods (upload, delete, exists, get_url)\n- Add _validate_key() to S3Storage for consistency\n- Block '..' sequences in project name validation\n\nWebhook SSRF Prevention:\n- Create groundwork/server/security/ module\n- Implement validate_webhook_url() that resolves DNS and checks IP ranges\n- Block loopback, private networks, link-local, cloud metadata IPs\n- Add @field_validator to SubmitJobRequest for webhook_url\n\nTests: 99 total (34 new security tests)","parents":["73d856658bf889c70bc3c21c0d8f6f61535e31d1"],"add":578,"del":12,"cadd":578,"cdel":12,"files":9},{"repo":"new-belen-game","hash":"dcd98d4114803871c549438cf4341f3191a575a6","ts":1770071272,"wall":"2026-02-02T17:27","msg":"Add internal documentation and AI assistant context","body":"","parents":["b102c5e4be2f3ad829c82e7260799d91fb8004df"],"add":2739,"del":0,"cadd":2739,"cdel":0,"files":14},{"repo":"new-belen-game","hash":"5893d72b6a3edda06c101723878b31f228889952","ts":1770075121,"wall":"2026-02-02T18:32","msg":"Add seeded generation, save/load, new content and preachers","body":"","parents":["dcd98d4114803871c549438cf4341f3191a575a6"],"add":868,"del":7,"cadd":868,"cdel":7,"files":7},{"repo":"new-belen-game","hash":"c9f8e0bb8e32b2ae4df7ff74b03ce2e3870a9c09","ts":1770075488,"wall":"2026-02-02T18:38","msg":"Add world fleshing research to expansion ideas","body":"","parents":["5893d72b6a3edda06c101723878b31f228889952"],"add":99,"del":0,"cadd":99,"cdel":0,"files":1},{"repo":"new-belen-game","hash":"e7bd6ca57260a37f63410e5840eb72d8628c4e7e","ts":1770077717,"wall":"2026-02-02T19:15","msg":"Improve resistant NPC gameplay and add save validation","body":"- Change resistant NPCs from impossible (0%) to very hard (15% of normal rate)\n- Hook on_aggressive_failure() so hellfire/pushy tactics hurt reputation more\n- Add save version validation to prevent silent corruption\n- Add input validation for personality/mood in deserialization\n- Fix import pattern in reputation.py (move random to module level)\n- Add subtle documentation hints for hidden mechanics","parents":["c9f8e0bb8e32b2ae4df7ff74b03ce2e3870a9c09"],"add":41,"del":17,"cadd":41,"cdel":17,"files":7},{"repo":"new-belen-game","hash":"10d45dad84855805af00fdd0f804d6beee18efe4","ts":1770079311,"wall":"2026-02-02T19:41","msg":"Expand dialogue content with ~100 new entries","body":"Add 17 new objections covering intellectual, emotional, practical,\nand hostile categories. Add 20 new responses including probing,\nbridge-building, and tactful retreat options. Add 26 new reaction\nlines and 36 new opening responses (3 per personality type).","parents":["e7bd6ca57260a37f63410e5840eb72d8628c4e7e"],"add":305,"del":0,"cadd":305,"cdel":0,"files":1},{"repo":"new-belen-game","hash":"cd489c431904768e9fa97bc2f980bcca609642be","ts":1770079608,"wall":"2026-02-02T19:46","msg":"Add visible modifiers to show what affects conversion chances","body":"Track and display breakdown of interest changes during conversations.\nPlayers now see what tags worked (effective), backfired, or matched\nobjections. Only shows for significant changes (|change| > 3).","parents":["10d45dad84855805af00fdd0f804d6beee18efe4"],"add":82,"del":13,"cadd":82,"cdel":13,"files":3},{"repo":"new-belen-game","hash":"2d726642af7229a72390f26b38a833712a707f38","ts":1770079861,"wall":"2026-02-02T19:51","msg":"Add preacher internal voice system for character-specific insights","body":"Each preacher now has unique observations during conversations based\non their personality affinities. 53 insights across 11 preachers,\ninspired by Disco Elysium's \"skills as voices\" pattern.","parents":["cd489c431904768e9fa97bc2f980bcca609642be"],"add":245,"del":0,"cadd":245,"cdel":0,"files":4},{"repo":"new-belen-game","hash":"f11e7cc470ebefdbf7704c473aad3ae0e22e65ac","ts":1770080150,"wall":"2026-02-02T19:55","msg":"Add layered objections with press mechanic","body":"Players can now \"Press\" to probe deeper into certain objections,\ndiscovering underlying causes (grief, trauma, betrayal, etc.) that\nunlock new response options. Press costs 1 patience (risk/reward).\n14 causes across 6 objections, inspired by Socrates Jones.","parents":["2d726642af7229a72390f26b38a833712a707f38"],"add":276,"del":2,"cadd":276,"cdel":2,"files":4},{"repo":"the-azuran","hash":"e105b52f75efa0c50abe2ae60729c72f69feb01f","ts":1770080716,"wall":"2026-02-02T20:05","msg":"Update README.md","body":"","parents":["38fbc13e0a7cc4cfbad5bea1991afb996ce69d39"],"add":1,"del":13,"cadd":1,"cdel":13,"files":1},{"repo":"new-belen-game","hash":"6e2c4a0f285ba9b96888944aac695080f797f50d","ts":1770081134,"wall":"2026-02-02T20:12","msg":"Add relationship depth system for NPC memory across days","body":"NPCs now remember previous encounters:\n- Visit count affects conversion threshold (repeat visits = easier)\n- Polite exits build warmth bonus (+3/exit, max +15)\n- Resistant NPCs require 2+ visits before conversion possible\n- Narrative generates relationship-aware thoughts","parents":["f11e7cc470ebefdbf7704c473aad3ae0e22e65ac"],"add":84,"del":8,"cadd":84,"cdel":8,"files":3},{"repo":"techbiont-framework","hash":"fb9026a2272213f0809567cd7e9178a09c7dad94","ts":1770083726,"wall":"2026-02-02T20:55","msg":"feat: initial techbiont framework","body":"Universal standing orders and methodologies for human-AI collaborative\ndevelopment. Includes research-informed practices from Anthropic, Simon\nWillison, Addy Osmani, and academic sources.\n\nKey components:\n- Techbiont philosophy and operating principles\n- 9 standing orders for AI-assisted development\n- Context engineering strategies\n- Auditing protocols with empirical backing\n- Prompt engineering patterns\n- Templates and quick reference\n\nBuilt with Claude Code.","parents":[],"add":872,"del":0,"cadd":851,"cdel":0,"files":3},{"repo":"techbiont-framework","hash":"ce5b06e52725f6200513ebddc41f79fe3cba3857","ts":1770084377,"wall":"2026-02-02T21:06","msg":"feat: add session continuity, metrics, and domain adaptations","body":"New sections based on research:\n\nPart VII: Session Continuity\n- Handoff protocol for multi-session work\n- Memory file hierarchy documentation\n- Context compaction warnings and mitigations\n\nPart VIII: Metrics & Measurement\n- METR study findings (19% slower on familiar codebases)\n- AI productivity paradox (helps review, not generation)\n- SPACE framework adaptation for techbiont work\n- What to track vs avoid (vanity metrics)\n\nPart IX: Domain-Specific Adaptations\n- GIS: L1 autonomy default, CRS verification, GDAL gotchas\n- Web dev: framework docs in context, React Query patterns\n- Game dev: balance preservation, no external deps\n\nAlso includes:\n- Session handoff template\n- 20+ new research sources\n- Updated lessons learned\n\nBuilt with Claude Code.","parents":["fb9026a2272213f0809567cd7e9178a09c7dad94"],"add":288,"del":5,"cadd":288,"cdel":5,"files":1},{"repo":"operations","hash":"e0792fe4ccab0476d3aabd4f3e9cdd5a08932c05","ts":1770087945,"wall":"2026-02-02T22:05","msg":"Initial commit: Symbiont Systems LLC business records","body":"Includes:\n- Formation documents\n- Business master doc\n- Compliance deadlines\n- Operating agreement\n- BOIR transcript (filed 2026-02-02)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":[],"add":690,"del":0,"cadd":675,"cdel":0,"files":12},{"repo":"operations","hash":"092fafdd534deb71e789030638ea9aa8d980de15","ts":1770089947,"wall":"2026-02-02T22:39","msg":"Session 2: BOIR filed, bank research, documentation updates","body":"- BOIR filed successfully (FinCEN ID: 2000-0737-0472)\n- Added IDENTIFIERS.md with all business IDs\n- Added SESSION-LOG.md for session history\n- Updated BUSINESS.md with bank status\n- Bank research: Bluevine denied, Chase deferred, using Citizens\n- Docs prepared for Citizens Bank account opening\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["e0792fe4ccab0476d3aabd4f3e9cdd5a08932c05"],"add":67,"del":1,"cadd":67,"cdel":1,"files":2},{"repo":"operations","hash":"3661e24306af38f24ffe825f14f867b5c24621c3","ts":1770096454,"wall":"2026-02-03T00:27","msg":"Session 3: SDVOSB compliance, capability statement, market research","body":"- Updated operating agreement for SDVOSB certification (13 CFR Part 128)\n- Added veteran status, unconditional ownership, control provisions\n- Officer title: Primus, President, and Principal\n- Drafted federal capability statement (markdown + styled PDF)\n- Drafted website copy for Carrd rebuild\n- Conducted Groundwork competitive analysis (no direct open-source competitor)\n- Identified federal market opportunity (NGA, USDA, DoD SBIR)\n- Updated all business docs with NAICS codes, target agencies, dependency chain","parents":["092fafdd534deb71e789030638ea9aa8d980de15"],"add":652,"del":40,"cadd":652,"cdel":40,"files":10},{"repo":"operations","hash":"ddc7e5fa4d3cfcaf59398424202757f800fce536","ts":1770099921,"wall":"2026-02-03T01:25","msg":"docs: Azura portfolio generation, webmap upgrade research","body":"- Ran Groundwork on Azura (Nevada 40 acres): terrain, hydrology, suitability\n- Named Nevada property \"Azura\" in business docs\n- Comprehensive webmap research: MapLibre GL JS migration, free basemaps,\n  3D terrain, data-driven styling, single-file architecture\n- Research doc at docs/webmap-research.md","parents":["3661e24306af38f24ffe825f14f867b5c24621c3"],"add":479,"del":1,"cadd":479,"cdel":1,"files":3},{"repo":"techbiont-framework","hash":"4b9c274362f17e4d528d23716208d2e14df15812","ts":1770164770,"wall":"2026-02-03T19:26","msg":"feat: MESO colony architecture with install script","body":"Restructured from monolithic standing orders into the siphonophore\ncolonial organism model. Added 10 universal zooids, stolon/pneumatophore\ntemplates, install script with symlink-based auto-updating, and switched\nlicense from MIT to PolyForm Noncommercial 1.0.0.\n\nBy Symbiont Systems LLC. Built with Claude Code.","parents":["ce5b06e52725f6200513ebddc41f79fe3cba3857"],"add":917,"del":55,"cadd":742,"cdel":34,"files":16},{"repo":"techbiont-framework","hash":"30e25437e6a6cdc2a094a9ae31df2b9343ea864f","ts":1770167724,"wall":"2026-02-03T20:15","msg":"feat: introduce operons — trigger-activated knowledge modules","body":"Evolve colony architecture from zooids-only to zooids + operons.\nZooids (rules/) remain always-loaded for core behavior. Operons\n(skills/) activate on demand when context matches their trigger\ndescription, like gene clusters responding to environmental signals.\n\nFive zooids promoted to operons: orchestration, recovery, evolution,\nauditing, context-engineering. Saves ~1.5k tokens/turn while\npreserving the full knowledge base.\n\nInstall script updated to handle both unit types and clean up\nold zooid symlinks on upgrade.\n\nBy Symbiont Systems LLC. Built with Claude Code.","parents":["4b9c274362f17e4d528d23716208d2e14df15812"],"add":322,"del":13,"cadd":322,"cdel":13,"files":7},{"repo":"techbiont-framework","hash":"013780a24bc9c793e2b5c5dbc6c519e17fa02e84","ts":1770170455,"wall":"2026-02-03T21:00","msg":"feat: add scratchpad operon (Cystozooid — Storage & Buoyancy)","body":"Persistent staging area that prevents loss of work-in-progress across\nsessions. Agent output staging, manifest tracking, snapshot recovery,\nlifecycle enforcement, and cross-operon integration.\n\nBuilt with Claude Code","parents":["30e25437e6a6cdc2a094a9ae31df2b9343ea864f"],"add":177,"del":3,"cadd":177,"cdel":3,"files":2},{"repo":"operations","hash":"3d68c87871d756c00b577fd7d39afdff4387cc6f","ts":1770170544,"wall":"2026-02-03T21:02","msg":"feat: MESO integration, website rebuild, scratchpad operon","body":"- Add project CLAUDE.md and .claude/rules (brand voice, business,\n  website, domain rules for GIS/web/gamedev)\n- Add scratchpad manifest and .gitignore rules (Cystozooid operon)\n- Add hexagon animation prototype (Tier 1-2, Canvas 2D)\n- Add website project structure and initial index.html\n- Add skills marketplace notebooks and research docs\n- Update business docs, deadlines, and session log\n- Add session handoff notes\n\nBuilt with Claude Code","parents":["ddc7e5fa4d3cfcaf59398424202757f800fce536"],"add":6963,"del":8,"cadd":4104,"cdel":8,"files":28},{"repo":"operations","hash":"5a5c3657de59c12d3d74ccbe5e1272852b6b79a9","ts":1770176870,"wall":"2026-02-03T22:47","msg":"feat(website): visual overhaul — seamless hex field, glyph shuffle, art deco typography","body":"Kill bloom pass and opacity breathing for seamless opaque hex tiling.\nExpand eukaryotic palettes to 20 dark-weighted colors per kingdom.\nAdd glyph shuffle effect on wordmark (13 display fonts, eclectic\ncolor palette, glow + jitter). Hero h1 in Orbitron Black with gold\nmetallic color and radiating black halo. Cartouche pill on tagline\nand footer. Black halo text-shadow on all unbacked copy for contrast.\nUpdate portfolio cards (Groundwork, Research Stations). Comment out\nSDVOSB designation pending certification.\n\nBuilt with Claude Code","parents":["3d68c87871d756c00b577fd7d39afdff4387cc6f"],"add":574,"del":158,"cadd":574,"cdel":158,"files":1},{"repo":"operations","hash":"c674855424d267e1019f0927f8e1d4a9d6ef414d","ts":1770243876,"wall":"2026-02-04T17:24","msg":"Pre-migration checkpoint","body":"Session state, meso-cli architecture, laptop migration docs.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["5a5c3657de59c12d3d74ccbe5e1272852b6b79a9"],"add":2469,"del":18,"cadd":2448,"cdel":18,"files":9},{"repo":"techbiont-framework","hash":"7391519e8df1264112c77f6f133ad76cbb730c55","ts":1770243877,"wall":"2026-02-04T17:24","msg":"Pre-migration checkpoint","body":"Zooid and operon updates, knowledge operon, docs.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["013780a24bc9c793e2b5c5dbc6c519e17fa02e84"],"add":954,"del":53,"cadd":954,"cdel":53,"files":16},{"repo":"groundwork","hash":"054f017bf5c086c97b6923f4cd4c1255427a5e69","ts":1770243879,"wall":"2026-02-04T17:24","msg":"Pre-migration checkpoint","body":"TUI rebuild, batch processing, webmap, cost estimation docs.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["9932ed83acfecbf06cbaace0ecdfd6e05d0f7078"],"add":3859045,"del":143,"cadd":11918,"cdel":143,"files":259},{"repo":"margin","hash":"c13d5c0325b473abb267bd1ad3b4ef6b7940bc27","ts":1770243881,"wall":"2026-02-04T17:24","msg":"Pre-migration checkpoint","body":"CLAUDE.md updates, audit files.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["8e07204f72593c05d5b60636c1820372054e907f"],"add":160,"del":65,"cadd":160,"cdel":65,"files":4},{"repo":"new-belen-game","hash":"af6d9e3576086d44020a13ef4856b539e2a36448","ts":1770243882,"wall":"2026-02-04T17:24","msg":"Pre-migration checkpoint","body":"CLAUDE.md updates.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["6e2c4a0f285ba9b96888944aac695080f797f50d"],"add":6,"del":69,"cadd":6,"cdel":69,"files":1},{"repo":"unified-ai","hash":"dc0f4b109700cab7295239b1c04c36d6cf5d0933","ts":1770243928,"wall":"2026-02-04T17:25","msg":"Initial commit: unified-ai project","body":"Local-first RAG system with Ollama LLM abstraction.\nPhase 1 complete (core, embeddings, LLM interface).\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":[],"add":5213,"del":0,"cadd":4280,"cdel":0,"files":40},{"repo":"meso-cli","hash":"43a0422edf8601e3bf1d5814741d7e4659b542c6","ts":1770243951,"wall":"2026-02-04T17:25","msg":"Initial commit: meso-cli architecture","body":"Architecture doc, project CLAUDE.md, research docs.\nNo code yet — planning phase.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":[],"add":1161,"del":0,"cadd":1161,"cdel":0,"files":5},{"repo":"operations","hash":"51e202ccb07bf627668901f67c0d901251c95a91","ts":1770244122,"wall":"2026-02-04T17:28","msg":"Extract meso-cli to separate repository","body":"Moved projects/meso-cli/ to ~/code/github.com/the-azuran/meso-cli\nas an independent project.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["c674855424d267e1019f0927f8e1d4a9d6ef414d"],"add":0,"del":1161,"cadd":0,"cdel":1161,"files":5},{"repo":"symbiont.systems","hash":"7c703a440bfa98dee55939b850f3a6163e9d9320","ts":1770244673,"wall":"2026-02-04T17:37","msg":"Initial commit: symbiont.systems website","body":"Extracted from symbiont-systems/projects/website.\nVisual overhaul complete, deployment pending.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":[],"add":1978,"del":0,"cadd":1978,"cdel":0,"files":4},{"repo":"operations","hash":"18cd6a36396e42caa2d807eca6d158c2f183c790","ts":1770244734,"wall":"2026-02-04T17:38","msg":"Extract website to separate repository","body":"Moved projects/website/ to symbiont.systems repo.\nReorganized docs:\n- Technical research → ~/docs/\n- Website docs → symbiont.systems/docs/\n- Groundwork market research → groundwork/docs/\n- Kept: formation/, skills-research.md, projects/ (notebooks)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["51e202ccb07bf627668901f67c0d901251c95a91"],"add":0,"del":4483,"cadd":0,"cdel":4483,"files":10},{"repo":"symbiont.systems","hash":"86cce94fd126a6898df406a2d843bf49876fb1ef","ts":1770244737,"wall":"2026-02-04T17:38","msg":"Add website research docs","body":"Imported from symbiont-systems/docs/.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["7c703a440bfa98dee55939b850f3a6163e9d9320"],"add":617,"del":0,"cadd":617,"cdel":0,"files":2},{"repo":"groundwork","hash":"0959e1aebeb4691b9125dfb486584db8bc3ada7b","ts":1770244738,"wall":"2026-02-04T17:38","msg":"Add Groundwork market research","body":"Competitive landscape and market analysis for automated land assessment platform.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","parents":["054f017bf5c086c97b6923f4cd4c1255427a5e69"],"add":190,"del":0,"cadd":190,"cdel":0,"files":1},{"repo":"operations","hash":"ff378c1a2c748966298d6a701ccd21316f4ce439","ts":1770244769,"wall":"2026-02-04T17:39","msg":"Update CLAUDE.md to reflect repository split","body":"","parents":["18cd6a36396e42caa2d807eca6d158c2f183c790"],"add":9,"del":5,"cadd":9,"cdel":5,"files":1},{"repo":"meso-cli","hash":"84da7d4be220eb298f0a26dc24b7516ea25873eb","ts":1770319888,"wall":"2026-02-05T14:31","msg":"Evolve MESO architecture: neurozooids and autonomic-somatic model","body":"Major architectural evolution from \"model routing tool\" to \"agentic colonial organism\":\n\n- Add neurozooid concept: specialized LLM agents with jurisdictional access\n- Introduce autonomic-somatic nervous system architecture\n  - Autonomic pathway: local/reflexive operations (pattern matching + local LLM)\n  - Somatic pathway: orchestrated operations (Task/Meta orchestrators + specialists)\n- Two-tier orchestration: Task Orchestrator (Sonnet) + Meta-Orchestrator (Opus)\n- Jurisdictional security: positive-control model enforced by Dactylozooid\n- Smart escalation: autonomic handler knows its limits, escalates when needed\n\nKey insight: 80%+ of operations should be autonomic (local, free, instant).\nOnly complex tasks require cloud orchestration.\n\nDocumentation:\n- docs/neurozooid-architecture.md: detailed neurozooid specification\n- docs/autonomic-somatic-model.md: nervous system architecture\n- docs/architecture-evolution-2026-02-05.md: design session summary\n- ARCHITECTURE.md: updated with new concepts\n\nStatus: Architectural specification (not yet implemented).\nWaiting for usage data before implementation.\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>","parents":["43a0422edf8601e3bf1d5814741d7e4659b542c6"],"add":1189,"del":57,"cadd":1189,"cdel":57,"files":4},{"repo":"meso-cli","hash":"60274498c80cfdfefd902a18a3f229eb55a5af14","ts":1770320474,"wall":"2026-02-05T14:41","msg":"Document MESO philosophical positioning and session handoff","body":"Add philosophical framing document:\n- Distinguishes tool vs appliance vs exocortex models\n- Positions MESO as exocortex (symbiotic cognitive extension)\n- Analyzes appliance-like qualities and their implications\n- Establishes design principles to maintain operator sovereignty\n- Documents trade-offs and mitigations\n\nSession handoff captures:\n- Architectural evolution completed this session\n- Critical decisions made (autonomic-somatic split, two-tier orchestration)\n- Key insights (orchestrator bottleneck, context flow, transparency)\n- Open questions and pending design decisions\n- Implementation status (waiting for usage data)\n- Recommended next actions\n\nStatus: Architectural specification complete. No implementation yet.\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>","parents":["84da7d4be220eb298f0a26dc24b7516ea25873eb"],"add":673,"del":0,"cadd":673,"cdel":0,"files":2},{"repo":"techbiont-framework","hash":"08a64e49f556dba1eeb458795aeda23aa30c4608","ts":1770354732,"wall":"2026-02-06T00:12","msg":"feat: implement unified workspace architecture with lifecycle management","body":"Implements the complete workspace operon (Cystozooid Evolved) extending\nthe scratchpad with persistent artifact storage, session archival, and\nfull-text search capabilities.\n\nArchitecture:\n- Three-tier lifecycle: Scratchpad (ephemeral) → Archive (30d TTL) → Artifacts (permanent)\n- SQLite FTS5 full-text search index across artifacts and archives\n- Git-backed version control for global workspace artifacts\n- Configurable retention policies with automatic cleanup\n- Cross-project artifact sharing via symlinks\n\nComponents:\n- operons/workspace/SKILL.md — comprehensive lifecycle guidance (840 lines)\n- templates/workspace.conf.template — retention policy configuration\n- templates/workspace-schema.sql — SQLite database schema\n- templates/workspace-artifact.template.md — artifact frontmatter template\n- docs/workspace-migration.md — migration guide for existing users\n\nIntegration:\n- install.sh — workspace directory setup, git init, SQLite index creation\n- operons/scratchpad/SKILL.md — workspace integration section\n- operons/auditing/SKILL.md — workspace checks in session audit\n- operons/evolution/SKILL.md — workspace search in pattern extraction\n- README.md — workspace architecture section\n- docs/knowledge/INDEX.md — documentation tracking\n\nFeatures:\n- Automatic session archiving with configurable triggers\n- Manual and automatic promotion workflows (3+ reference threshold)\n- Full-text search with type/domain/tag filtering\n- Symlink tracking and validation\n- Retention enforcement (archive TTL, artifact staleness warnings)\n- Git commit automation for promoted artifacts\n- Graceful degradation (works without SQLite or git)\n\nNon-breaking:\n- Scratchpad operon unchanged, workspace is opt-in extension\n- Auto-archiving disabled by default\n- Existing scratchpad files unaffected\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>","parents":["7391519e8df1264112c77f6f133ad76cbb730c55"],"add":1403,"del":6,"cadd":1364,"cdel":6,"files":11},{"repo":"groundwork","hash":"220821303fe5463d7a59666ed1e427740517fc8b","ts":1770369171,"wall":"2026-02-06T04:12","msg":"Add agricultural suitability report template (Phase 1)","body":"Groundwork now generates NRCS-compliant agricultural land evaluation\nreports for farm/ranch assessment. This implements the first of four\nplanned professional templates for commercial environmental consulting.\n\nModified:\n- groundwork/acquire/soils.py\n  * Query hydric classification, land capability class, farmland designation\n  * Add _fetch_farmland_class() for muaggatt prime farmland data\n\n- groundwork/output/report.py\n  * Add template parameter to generate() (comprehensive|agricultural)\n  * Add _prepare_agricultural_data() with capability/farmland calculations\n  * Add crop recommendation logic based on climate/soil/terrain\n\n- groundwork/cli.py\n  * Add --template flag to analyze command\n  * Update examples showing agricultural template usage\n\n- groundwork/README.md\n  * Document agricultural template in features and quick start\n\nCreated:\n- groundwork/output/templates/__init__.py\n- groundwork/output/templates/agricultural.py (NRCS-compliant HTML template)\n- docs/assessment-standards/agricultural-evaluation-format.md (6.5KB standards doc)\n\nReport Structure:\n1. Executive Summary (prime farmland %, dominant capability class, recommended use)\n2. Site Overview (coordinates, area, bounds)\n3. Land Capability Classification (NRCS Classes I-VIII with area distribution)\n4. Prime Farmland Designation (7 CFR Part 657 criteria compliance)\n5. Soil Properties (dominant series, hydrologic groups, hydric classification)\n6. Terrain & Climate (slope, elevation, growing season, precipitation)\n7. Recommendations (crop suitability, conservation practices, management notes)\n8. Data Sources & Methods (SSURGO, USGS 3DEP, Open-Meteo)\n9. Limitations & Assumptions (desktop assessment caveats, next steps)\n\nCommercial Applications:\n- Farm/ranch purchase assessments ($1,500-$3,000 per report)\n- Conservation easement documentation\n- Estate planning and land valuation\n- USDA program eligibility screening\n\nMarket Position:\n- Automates 60-70% of agricultural land evaluation (desktop component)\n- Reduces 8-12 hours manual work to 15-30 minutes automated\n- 10-20x efficiency enables competitive pricing with 60-70% margins\n\nBy Symbiont Systems LLC\nBuilt with Claude Code","parents":["0959e1aebeb4691b9125dfb486584db8bc3ada7b"],"add":1108,"del":10,"cadd":1108,"cdel":10,"files":7},{"repo":"groundwork","hash":"25dde0a2d647ae483b192967c1ef0fe92b102cd1","ts":1770392265,"wall":"2026-02-06T10:37","msg":"Add wetland preliminary assessment template (Phase 2)","body":"Groundwork now generates USACE 1987 Manual-aligned wetland preliminary\nassessment reports for desktop screening. Automates hydric soils analysis,\ntopographic wetness index calculation, depression mapping, and NWI comparison\nto focus field delineation efforts.\n\nModified:\n- groundwork/analyze/hydrology.py\n  * Add _calculate_twi() - Topographic Wetness Index calculation\n  * Add _identify_depressions() - depression mapping from filled vs original DEM\n  * Integrate TWI and depressions into hydrology analysis pipeline\n\n- groundwork/output/report.py\n  * Add wetland template import and routing\n  * Add _prepare_wetland_data() for wetland report data preparation\n  * Combine hydric soils, TWI, depressions, NWI, probability zones\n\n- groundwork/cli.py\n  * Add \"wetland\" to --template choices\n  * Add wetland-specific analysis phase (NWI fetch, probability calculation)\n  * Enable soils enrichment for hydric classification\n\n- groundwork/README.md\n  * Document wetland template in features and quick start\n\nCreated:\n- groundwork/acquire/wetlands.py (NWI data acquisition from USFWS)\n- groundwork/analyze/wetland_probability.py (weighted probability scoring)\n- groundwork/output/templates/wetland_preliminary.py (USACE-aligned HTML template)\n- docs/assessment-standards/wetland-delineation-format.md (10.5KB standards doc)\n\nWetland Analysis Components:\n1. Hydric Soils (SSURGO hydric classification) - 40% weight\n2. Topographic Wetness Index (TWI = ln(area/tan(slope))) - 30% weight\n3. Topographic Depressions (ponding areas) - 20% weight\n4. Flow Convergence (drainage convergence zones) - 10% weight\n5. NWI Comparison (existing mapped wetlands)\n\nReport Structure (USACE 1987 Manual-aligned):\n1. Introduction (three-parameter approach, desktop vs field)\n2. Methods (desktop analysis components, probability scoring)\n3. Desktop Analysis Results (hydric soils, TWI, depressions, NWI, probability zones)\n4. Field Investigation Plan (priority areas, recommended methods, timing)\n5. Conclusions (wetland likelihood, jurisdictional context, recommendations)\n6. Data Sources (SSURGO, 3DEP, NWI)\n7. Limitations (CRITICAL disclaimers - desktop only, field required)\n\nCommercial Applications:\n- Pre-purchase wetland screening ($1,500-$4,000 per report)\n- Focuses field investigation (60% site area reduction)\n- Section 404 permit planning\n- Conservation/restoration site selection\n\nMarket Position:\n- Automates desktop component (8-12 hours manual → 30 minutes automated)\n- Eliminates 60% of site from field investigation\n- USACE 1987 Manual-aligned methodology\n- Clear disclaimers (desktop ≠ jurisdictional determination)\n\nTechnical Implementation:\n- TWI calculation handles edge cases (zero slope, invalid values)\n- Depression mapping with area, depth, volume calculations\n- NWI REST API integration with Cowardin classification parsing\n- Weighted probability scoring with rasterization and vectorization\n- Graceful handling of missing data (NWI unavailable, SSURGO errors)\n\nRegulatory Compliance:\n- Aligned with USACE 1987 Wetland Delineation Manual\n- References Regional Supplements (2024-2025)\n- Sackett v. EPA (2023) jurisdictional context\n- Strong disclaimers: desktop only, field required, not jurisdictional determination\n\nNext: Phase 3 Phase I ESA desktop component\n\nBy Symbiont Systems LLC\nBuilt with Claude Code","parents":["220821303fe5463d7a59666ed1e427740517fc8b"],"add":1676,"del":7,"cadd":1676,"cdel":7,"files":8},{"repo":"techbiont-framework","hash":"36a8ed4390c6a708654cf831a8b700ab32d2c5cf","ts":1770465276,"wall":"2026-02-07T06:54","msg":"feat(security): implement comprehensive OWASP/MITRE-sourced deny-list","body":"Phase 1: Immediate Security Enhancements\n- Expand deny-list from 28 to 84 patterns (+56 additions)\n- Add Script Download Security section to security zooid\n- Implement defense-in-depth with multi-layer gating\n- Document all patterns with authoritative source citations\n\nDeny-List Enhancements (84 patterns total):\n1. Destructive operations (9): dd, mkfs, shred, truncate, crontab -r\n2. Version control (9): git push -f, clean -fd, clean -fdx\n3. Privilege escalation (7): sudo, chmod +s, setfacl\n4. Command injection (6): eval, exec, source\n5. Insecure protocols (7): wget http://, curl -k variants\n6. Network/exfiltration (5): nc, ncat, socat, telnet\n7. Container escapes (7): docker, podman, systemctl, mount, unshare\n8. Credential access (28): .ssh/*, .aws/*, /etc/shadow, recursive .env\n\nSources (Gold Standard):\n- OWASP OS Command Injection Defense Cheat Sheet\n- OWASP Top 10:2025 (A05 Injection)\n- MITRE CWE-78 (OS Command Injection)\n- CISA Secure Design Alert\n- GTFOBins (privilege escalation database)\n- Kubernetes Pod Security Standards\n- Docker Seccomp profiles\n- GitHub Copilot security filters\n\nKnowledge Capture:\n- 3 research proposals (curl security, trust domains, retention)\n- 1 comprehensive maintenance guide (security-deny-list-sources.md)\n- 1 AAR (curl security research)\n- 1 strategic applications document (curl usage across MESO)\n\nMaintenance Strategy:\n- Quarterly reviews (March/June/September/December)\n- Monitor OWASP Top 10, GTFOBins, CVE databases\n- Testing checklist included\n- Next review: 2026-05-07\n\nSecurity Properties:\n- Blocks MITM attacks (certificate bypass prevention)\n- Blocks supply chain attacks (script piping prevention)\n- Blocks privilege escalation (sudo, SUID, container escapes)\n- Blocks credential exposure (SSH keys, AWS creds, secrets)\n- L1 escalation enforced for all script downloads\n\nNo workflow disruption:\n- API testing allowed (HTTPS with safety flags)\n- File downloads allowed (just not direct piping)\n- Legitimate operations unaffected\n\nBy Symbiont Systems LLC\nBuilt with Claude Code","parents":["08a64e49f556dba1eeb458795aeda23aa30c4608"],"add":2668,"del":8,"cadd":2668,"cdel":8,"files":8},{"repo":"unified-ai","hash":"40f8c9a8ea9c1f547ee42eee2631f74dc66d5de3","ts":1770467586,"wall":"2026-02-07T07:33","msg":"feat: implement complete RAG pipeline with hybrid search","body":"Phase 1: RAG infrastructure\n- Document ingestion (markdown, PDF, docx)\n- Recursive chunking with metadata preservation\n- Ollama embeddings (nomic-embed-text, 768-dim)\n- Qdrant vector store (local persistent)\n- Semantic search with metadata filtering\n\nPhase 2: MESO integration\n- Knowledge base indexing scripts\n- Workspace artifacts indexing\n- Integration tests (20 passing)\n- Benchmark framework (70% hit rate baseline)\n\nPhase 3: Hybrid search\n- SQLite FTS5 keyword search with BM25 ranking\n- Reciprocal Rank Fusion (RRF) merging algorithm\n- CLI search interface with full filter support\n- Error handling and validation\n- Re-indexed with 135 chunks (semantic + keyword)\n\nFeatures:\n- Type filtering (aar, decision, research, pattern)\n- Domain/tag filtering (comma-separated lists)\n- Date range filtering (--after, --before)\n- Collection selection (knowledge_base, workspace_artifacts)\n- Top-k result limiting\n- Formatted output (file paths, scores, metadata, previews)\n\nPerformance:\n- Semantic search: ~300ms per query\n- Hybrid search: ~350ms per query (semantic + keyword + RRF)\n- Index size: 135 chunks from 14 documents\n\nBuilt with Claude Code\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>","parents":["dc0f4b109700cab7295239b1c04c36d6cf5d0933"],"add":3888,"del":7,"cadd":3884,"cdel":6,"files":17},{"repo":"techbiont-framework","hash":"0ef637b73617b098ced6a820322e6bd1297a1f81","ts":1770467632,"wall":"2026-02-07T07:33","msg":"feat(retrieval): add RAG semantic search capability to MESO","body":"Add Neurozooid retrieval operon with hybrid search (semantic + keyword).\n\nNew operon:\n- retrieval (Neurozooid) — semantic search and knowledge retrieval\n- Trigger: searching knowledge base, finding past decisions, retrieving\n  relevant context, querying workspace artifacts\n- Implementation: Ollama embeddings + Qdrant vector store + SQLite FTS5\n- Hybrid search with Reciprocal Rank Fusion (RRF) merging\n\nIntegration:\n- Knowledge operon: document RAG indexing trigger after filing\n- Workspace operon: document retrieval for workspace artifacts\n- Auditing operon: reference RAG verification in checklists\n- Handoff: complete implementation summary with usage examples\n\nKnowledge capture:\n- AAR: RAG capability analysis (2026-02-06)\n- Guide: RAG implementation guide 2026\n\nSystem capabilities:\n- Semantic search across knowledge base (135 chunks indexed)\n- Keyword search with BM25 ranking (SQLite FTS5)\n- Metadata filtering (type, domain, tags, severity, dates)\n- Collection selection (knowledge_base, workspace_artifacts)\n- CLI interface via unified-ai/scripts/search.py\n- ~350ms query latency (semantic + keyword + RRF merge)\n\nUsage via MESO:\n  /retrieval search \"query\" [--filters]\n\nBuilt with Claude Code\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>","parents":["36a8ed4390c6a708654cf831a8b700ab32d2c5cf"],"add":1440,"del":60,"cadd":1440,"cdel":60,"files":7},{"repo":"techbiont-framework","hash":"689703580ad89cfc4b4ea3a25d531e866d2285b9","ts":1770475080,"wall":"2026-02-07T09:38","msg":"feat(calendar): add calendar operon infrastructure (Temporozooid)","body":"Implements three-tier calendar system for MESO:\n- Phase 1: Internal SQLite calendar with event tracking\n- Phase 2: Radicale CalDAV server (self-hosted, encrypted)\n- Phase 3: Cal.com integration (external scheduling)\n\nTemplates added:\n- calendar-schema.sql: SQLite database schema (events, reminders, sync_log)\n- calendar.conf.template: TOML configuration with keyring password storage\n- calendar-docker-compose.yml: Radicale CalDAV server setup\n\nFeatures:\n- Review date scanning from knowledge base frontmatter/text\n- Session-start reminders with urgency indicators (🔴 ≤1d, 🟡 ≤3d, 🟢 >3d)\n- Bidirectional knowledge linking (event ↔ document)\n- Security compliant: filesystem encryption, keyring passwords, parameterized queries\n- Auditing integration: calendar checks added to session audit checklist\n\nPhase 1 operational with 7 review dates imported from decision docs.\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>","parents":["0ef637b73617b098ced6a820322e6bd1297a1f81"],"add":203,"del":0,"cadd":150,"cdel":0,"files":3},{"repo":"techbiont-framework","hash":"190df816dd8359e3af8f9fde12f03c696df5e470","ts":1770477418,"wall":"2026-02-07T10:16","msg":"feat(knowledge): add code clarity research and boring code philosophy","body":"Research documents:\n- boring-code-philosophy.md: Industry/academic validation of \"boring code over clever code\"\n  * $3T annual GDP cost of technical debt (Stripe research)\n  * 2-5x maintenance cost difference\n  * 70% of dev time spent reading code\n  * Evidence from Google, Microsoft, academia\n\n- code-clarity-research.md: Cognitive science foundations\n  * Working memory limits (4 chunks, not 7±2)\n  * Extract Method: 70-78% faster, 20-34% higher accuracy\n  * Eye-tracking validation of readability impact\n  * 70+ academic and industry sources\n\nPhase 4 calendar integration:\n- calendar-integration-guide.md: Usage and troubleshooting\n- hookify.calendar-reminders.local.md: Session-start automation\n- phase4-summary.md: Implementation details and testing\n\nStanding orders updated:\n- Order #3: Added \"write boring code\" principle\n- Order #10: \"Follow Documentation\" (new)\n\nNew zooid created:\n- 11-coding-style.md: Detailed boring code guidelines\n\nPhase 4 complete: Session-start reminders operational.\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>","parents":["689703580ad89cfc4b4ea3a25d531e866d2285b9"],"add":1711,"del":0,"cadd":1711,"cdel":0,"files":5},{"repo":"techbiont-framework","hash":"7410377a5536bbabd73820d7e991cbb5164272d8","ts":1770477527,"wall":"2026-02-07T10:18","msg":"docs: add architecture research and session handoff notes","body":"Knowledge base additions:\n- edge-computing-architecture.md: Distributed AI via MCP protocol\n  * Central orchestrator (Claude/DeepSeek) + edge LLMs\n  * Privacy-preserving local processing\n  * Raspberry Pi, Jetson, mobile deployment patterns\n\n- mesocomplete-productization-architecture.md: Keyboard-driven AI IDE\n  * Full-spec keyboard controller with AI integration\n  * Revenue model and market positioning\n\n- pi-minimalist-agent-architecture.md: Lightweight agent deployment\n  * Resource-constrained edge computing\n  * Minimal dependencies for embedded systems\n\nSession handoff:\n- curl-security-handoff.md: Phase 1 curl security completion\n  * 84-pattern deny-list (OWASP, MITRE, CISA sourced)\n  * Safe download protocol documented\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>","parents":["190df816dd8359e3af8f9fde12f03c696df5e470"],"add":2058,"del":0,"cadd":2058,"cdel":0,"files":4},{"repo":"techbiont-framework","hash":"714c00fa4068f6b2589aae4b185f7e3bb6b0847d","ts":1770478141,"wall":"2026-02-07T10:29","msg":"feat(knowledge): add educational reference materials for RAG","body":"Add two comprehensive reference documents to knowledge base:\n- Open-source science textbook equivalents (9 subjects mapped to OER)\n- Programming languages taxonomy (70+ languages categorized by paradigm)\n\nBoth documents include YAML frontmatter, RAG integration notes, and\nmaintenance schedules for future RAG semantic search capabilities.\n\nBuilt with Claude Code","parents":["7410377a5536bbabd73820d7e991cbb5164272d8"],"add":691,"del":0,"cadd":691,"cdel":0,"files":3},{"repo":"unified-ai","hash":"dc779ba4835fcbcbcc6124c89a47c0bea5237845","ts":1770479137,"wall":"2026-02-07T10:45","msg":"fix(rag): resolve concurrent access and query sanitization issues","body":"Fix Qdrant concurrent access for multi-collection search:\n- Add close() method to QdrantStore to release client resources\n- Update search.py to close stores in finally block between searches\n- Enables searching both knowledge_base and workspace_artifacts without errors\n\nFix FTS5 query sanitization:\n- Add '?' to special character list for FTS5 queries\n- Prevents syntax errors when queries contain question marks\n- Fixes benchmark failure with \"Why did we choose...\" type queries\n\nAdd comprehensive unit tests (12 passing):\n- RRF merging: overlap scenarios, empty inputs, score normalization\n- Keyword search: filter extraction, result conversion\n- Edge cases: hybrid disabled, empty queries, score ranges\n\nPhase 3 benchmark results: 80% hit rate (was 70%), 54ms latency (184 chunks)\n\nBuilt with Claude Code","parents":["40f8c9a8ea9c1f547ee42eee2631f74dc66d5de3"],"add":359,"del":2,"cadd":359,"cdel":2,"files":4},{"repo":"techbiont-framework","hash":"ccd2560b6cba322d1d0935d57737818adaa56b3c","ts":1770479499,"wall":"2026-02-07T10:51","msg":"docs: update session handoff for knowledge expansion and RAG improvements","body":"Completed this session:\n- Added 2 reference documents (textbooks + programming languages)\n- Re-indexed RAG system (135→184 chunks)\n- Fixed Qdrant concurrent access bug\n- Ran Phase 3 benchmark (80% hit rate, 54ms latency)\n- Added 12 unit tests for hybrid retriever\n\nRAG system now production-ready with full test coverage.\n\nBuilt with Claude Code","parents":["714c00fa4068f6b2589aae4b185f7e3bb6b0847d"],"add":132,"del":144,"cadd":132,"cdel":144,"files":1},{"repo":"techbiont-framework","hash":"2ced1edb8fad78dca6eb02e1823758a8dd036d65","ts":1770479618,"wall":"2026-02-07T10:53","msg":"docs: capture command center with government APIs concept","body":"Initial idea for centralized government API command center.\nIncludes potential data sources, use cases, and technical considerations.\n\nBuilt with Claude Code","parents":["ccd2560b6cba322d1d0935d57737818adaa56b3c"],"add":55,"del":0,"cadd":55,"cdel":0,"files":1},{"repo":"techbiont-framework","hash":"c5f1032da3a4ef52da32d148ac34aa8afb5d1fdf","ts":1770489692,"wall":"2026-02-07T13:41","msg":"docs: add project idea and context status to handoff","body":"Captured government APIs command center concept in project-ideas.md.\nContext usage: 58% (116k/200k), healthy headroom remaining.\n\nBuilt with Claude Code","parents":["2ced1edb8fad78dca6eb02e1823758a8dd036d65"],"add":23,"del":0,"cadd":23,"cdel":0,"files":1},{"repo":"techbiont-framework","hash":"a289f888c68226d70065b8ca64ad6d6a3891ea88","ts":1770490290,"wall":"2026-02-07T13:51","msg":"docs: document multi-instance Claude coordination methods","body":"Add comprehensive research on six methods for running multiple Claude\ninstances simultaneously: agent teams (native), subagents, git worktrees,\nterminal panes, containers, and desktop apps. Agent teams architecture\ndirectly mirrors MESO's colonial organism model with shared task lists\nand inter-agent messaging.\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>","parents":["c5f1032da3a4ef52da32d148ac34aa8afb5d1fdf"],"add":211,"del":0,"cadd":211,"cdel":0,"files":2},{"repo":"techbiont-framework","hash":"74ff542ca05d070cf0b68bd68953998045bbe67c","ts":1770497435,"wall":"2026-02-07T15:50","msg":"docs: add session handoff for multi-agent development","body":"Comprehensive handoff documenting 3 parallel agent deliverables:\n- Ticker performance investigation (fixes ready)\n- Editor polish implementation (code complete)\n- Collections Phase C foundation (architecture complete)\n\nSession completed with all agents delivering actionable implementations.\nNext session will implement all three with proper permissions.\n\nBuilt with Claude Code","parents":["a289f888c68226d70065b8ca64ad6d6a3891ea88"],"add":229,"del":140,"cadd":229,"cdel":140,"files":1},{"repo":"margin","hash":"a023134da9f96c0dcd55e5c0ee471a719abbb90a","ts":1770497505,"wall":"2026-02-07T15:51","msg":"feat: add export/import, extension fixes, and session handoff","body":"## Extension Fixes\n- Fix popup refresh bug (visibility detection)\n- Add highlight functionality debug logging\n- Both features tested and working\n\n## Export/Import System\n- Full JSON export/import (44 tests passing)\n- HTML bookmarks (Netscape format, browser-compatible)\n- OPML feeds (RSS reader compatible)\n- Complete documentation in docs/EXPORT-IMPORT.md\n\n## Featured Feeds\n- Curated 27 feeds in 4 categories\n- Two-tier discovery (Featured + Browse)\n- Instant load from bundled JSON\n\n## Session Handoff\n- Comprehensive documentation for next session\n- Agent deliverables documented (ticker, editor, collections)\n- Implementation priorities and testing checklists\n\nAuthored by Valis, executed by Claude Code","parents":["c13d5c0325b473abb267bd1ad3b4ef6b7940bc27"],"add":3690,"del":1,"cadd":3467,"cdel":1,"files":19},{"repo":"groundwork","hash":"89801a3578e2f06df6d31f2a5ab411c5219862f8","ts":1770518164,"wall":"2026-02-07T21:36","msg":"Add collapsible legend groups to webmaps (Phase 1.1)","body":"Organize layers into logical groups (Hydrology, Terrain, Soils, Hazards,\nInfrastructure) with expand/collapse functionality. Reduces visual clutter\nand improves navigation for feature-rich webmaps.\n\nFeatures:\n- LayerGroup dataclass defines group metadata\n- CSS-only chevron animation (no images)\n- localStorage persistence for expanded/collapsed state\n- Works in both PMTiles and GeoJSON modes\n\nModified:\n- groundwork/output/layer_config.py: Add LayerGroup dataclass and LAYER_GROUPS dict\n- groundwork/output/webmap.py: Update legend HTML generation and add group toggle JS\n\nPart of Groundwork UI Enhancement Plan - Phase 1, Feature 1.\nBy Rowan Valle | Built with Claude Code","parents":["25dde0a2d647ae483b192967c1ef0fe92b102cd1"],"add":534,"del":162,"cadd":534,"cdel":162,"files":2},{"repo":"groundwork","hash":"74c5242813ea25ddab7d8785ee8ea3d6c3db793d","ts":1770520961,"wall":"2026-02-07T22:22","msg":"Add mobile responsive design and dark mode (Phase 1.4-5)","body":"Implement responsive CSS and theme system for mobile devices and user\npreferences. Both features work independently and complement each other.\n\nMobile Responsive (Phase 1, Feature 4):\n- Bottom sheet legend on tablets/phones (<768px)\n- Touch-friendly buttons (44x44px minimum)\n- Responsive breakpoints: 768px (tablet), 480px (phone)\n- Stack controls vertically on small screens\n- Hide coordinate display on mobile to save space\n- Larger font sizes for readability on small screens\n\nDark Mode (Phase 1, Feature 5):\n- CSS custom properties for theme system\n- Toggle button (🌙/☀️) switches between light/dark\n- localStorage persistence remembers preference\n- Theme variables: backgrounds, text, borders, buttons\n- Works across all UI elements (legend, overlays, controls)\n\nImplementation:\n- No external dependencies (pure CSS + vanilla JS)\n- Theme toggle uses data-theme attribute on :root\n- Mobile uses CSS media queries only\n- Both work in PMTiles and GeoJSON modes\n\nPart of Groundwork UI Enhancement Plan - Quick Wins.\nBy Rowan Valle | Built with Claude Code","parents":["89801a3578e2f06df6d31f2a5ab411c5219862f8"],"add":137,"del":0,"cadd":137,"cdel":0,"files":1},{"repo":"groundwork","hash":"84f17c3b6c87ccc0b3f5cad6cd8aa66cf7f94a85","ts":1770521120,"wall":"2026-02-07T22:25","msg":"Add map export to PNG image (Phase 4.8)","body":"Implement client-side map export using MapLibre's canvas rendering.\nExports current map view as high-quality PNG with overlays included.\n\nFeatures:\n- Export button (📸) in measurement controls\n- Captures full map canvas at current zoom/pan\n- Includes title overlay with project name\n- Automatic download with descriptive filename\n- No server required - pure client-side\n\nImplementation:\n- Uses MapLibre canvas.toBlob() for image generation\n- Waits for map.once('idle') to ensure complete render\n- Draws map + title overlay on combined canvas\n- Filename format: ProjectName-map.png\n\nQuality:\n- Full resolution (matches screen DPI)\n- PNG format for lossless quality\n- Includes visible layers and satellite imagery\n- Suitable for client reports and presentations\n\nCritical client deliverable requirement from plan.\nWorks in both PMTiles and GeoJSON modes.\n\nPart of Groundwork UI Enhancement Plan - Phase 4, Feature 8.\nBy Rowan Valle | Built with Claude Code","parents":["74c5242813ea25ddab7d8785ee8ea3d6c3db793d"],"add":61,"del":0,"cadd":61,"cdel":0,"files":1},{"repo":"groundwork","hash":"81feb5e240fff3df0f856d48550ad06fdff91cbe","ts":1770521275,"wall":"2026-02-07T22:27","msg":"Replace popups with slide-in info panel (Phase 2.5)","body":"Replace basic MapLibre popups with professional slide-in side panel\nfor feature information. Better presentation and more space for data.\n\nFeatures:\n- Slide-in panel from right side (350px width)\n- Smooth CSS transition (0.3s ease)\n- Card-based property display\n- Formatted values (2 decimal places for floats)\n- Close button (×) to dismiss\n- Mobile responsive (full-width on phones)\n\nUI Improvements over popups:\n- More space for properties\n- Better readability with cards\n- Consistent styling with theme system\n- No map obstruction (slides over)\n- Professional appearance\n\nImplementation:\n- Replaces maplibregl.Popup() with custom panel\n- Auto-capitalizes layer names for title\n- Formats property keys (replaces underscores)\n- Theme-aware colors via CSS variables\n- Works in both PMTiles and GeoJSON modes\n\nPart of Groundwork UI Enhancement Plan - Phase 2, Feature 5.\nBy Rowan Valle | Built with Claude Code","parents":["84f17c3b6c87ccc0b3f5cad6cd8aa66cf7f94a85"],"add":59,"del":8,"cadd":59,"cdel":8,"files":1},{"repo":"groundwork","hash":"acb214bf6af86f4f330b3076a7fe8d63bf7bf9e3","ts":1770521759,"wall":"2026-02-07T22:35","msg":"Fix soils layer for Unknown hydgrp values","body":"Change gray fallback color to tan/brown (#d4a574) which is more\nappropriate for soil visualization. Add 'Unknown' to legend so users\nunderstand what they're seeing when NRCS component data is unavailable.\n\nIssue: NRCS SDA API calls for component data (hydgrp, drainage) often\nfail or timeout, leaving soils data with 'Unknown' values. The gray\ncolor was confusing and looked like missing data.\n\nSolution:\n- Use tan/brown for Unknown (looks like soil)\n- Add Unknown to legend for transparency\n- Support mixed drainage classes (A/D, B/D, C/D)\n\nThis is a visualization fix for a data acquisition issue. The real fix\nwould be to retry failed NRCS API calls or implement fallback data sources.\n\nBy Rowan Valle | Built with Claude Code","parents":["81feb5e240fff3df0f856d48550ad06fdff91cbe"],"add":6,"del":1,"cadd":6,"cdel":1,"files":1},{"repo":"groundwork","hash":"5d730b73f994e41467920170da8156dd58719273","ts":1770521837,"wall":"2026-02-07T22:37","msg":"Enable all available data layers on webmaps","body":"Add collection paths for 7 additional layer types that already have\nLayerConfig definitions but weren't being included in maps.\n\nNew layers (if data exists):\n- flowlines (NHD streams with flow type)\n- waterbodies (NHD lakes/ponds/reservoirs)\n- wells (groundwater monitoring wells)\n- roads (OSM road network by type)\n- buildings (OSM building footprints)\n- ownership (federal/state/private land ownership)\n- wildfire (historical fire perimeters)\n\nThis demonstrates the modular design - adding new layers only requires:\n1. LayerConfig in layer_config.py (already exists)\n2. Layer path in _collect_layers() (added here)\n3. Data acquisition module (already exists for these)\n\nMaps now auto-include any layer with available data.\n\nBy Rowan Valle | Built with Claude Code","parents":["acb214bf6af86f4f330b3076a7fe8d63bf7bf9e3"],"add":7,"del":0,"cadd":7,"cdel":0,"files":1},{"repo":"groundwork","hash":"cf055d26450aed0f4a0d6a3de25e0484cbb22f82","ts":1770522542,"wall":"2026-02-07T22:49","msg":"Expand data pipeline and add smooth rendering","body":"**Data Acquisition (10 sources now)**:\n- Added 6 new data sources to Phase 1 pipeline\n- Hydrography: NHD flowlines + waterbodies\n- Groundwater: USGS monitoring wells\n- Land ownership: BLM federal/state/private\n- Wildfire: NIFC historical fire perimeters\n- Wetlands: NWI wetlands (now for all projects, not just wetland template)\n- OpenStreetMap: Roads + buildings\n\n**Smooth Rendering**:\n- MapLibre antialias: true for both viewers\n- Line smoothing: line-round-limit 1.05, line-miter-limit 2\n- Prevents blocky/jagged appearance on streams, roads, contours\n- Applies to all line layers (streams, flowlines, roads, contours, parcel)\n\n**Layer Config**:\n- Added wetlands layer (NWI classification with 6 wetland types)\n- Added to Hydrology group in legend\n- All new layers auto-included when data exists\n\n**Bug fixes**:\n- Fixed regex escape sequences (\\b\\w for JavaScript in Python strings)\n\nModular design means adding new data just requires:\n1. Import module in cli.py\n2. Call fetch() in Phase 1\n3. Add path to _collect_layers()\n4. LayerConfig + LayerGroup already exist\n\nBy Rowan Valle | Built with Claude Code","parents":["5d730b73f994e41467920170da8156dd58719273"],"add":120,"del":12,"cadd":120,"cdel":12,"files":3},{"repo":"mycelial-network","hash":"5f06f9762f383d2547e4f356b83914cc5c17a152","ts":1770527660,"wall":"2026-02-08T00:14","msg":"Initial implementation: Mycelial Network Phase 1","body":"Distributed task management system for Symbiont Systems.\nReplaces scattered JSON files with unified SQLite database.\n\nFeatures:\n- REST API (Hono + Node.js)\n- SQLite with CRDT support (vector clocks)\n- Task CRUD operations with UUIDv7\n- Migration script (69 JSON files successfully imported)\n- Health check and status endpoints\n\nTech stack: Node.js, Hono, better-sqlite3\nNext: Two-station sync (Syncthing + WireGuard)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":1639,"del":0,"cadd":1085,"cdel":0,"files":9},{"repo":"groundwork","hash":"22887c5382776080cfc0ab984bbd7bd44c547e7f","ts":1770612023,"wall":"2026-02-08T23:40","msg":"Fix critical bugs, complete pipeline, harden for production","body":"Phase 1 - Critical bugs:\n- Fix farmland distribution: replace empty pass loop with real\n  mukey-to-area GeoJSON lookup, remove slope-based heuristic\n- Fix wetland water regime parser: replace naive substring match\n  with positional Cowardin code parsing\n- Migrate groundwater from deprecated USGS gwlevels to new\n  api.waterdata.usgs.gov OGC API\n\nPhase 2 - Pipeline gaps:\n- Wire solar and landcover modules into acquisition pipeline,\n  update step counters [1/10] -> [1/12]\n- Implement resume command: extract _run_pipeline(), both analyze\n  and resume call it\n\nPhase 3 - Reliability:\n- Add fetch_with_retry() with exponential backoff, apply to all\n  14 acquire modules (22 API call sites)\n- Replace ~144 print() with logger across acquire/, analyze/,\n  and output/ modules\n- Add GeoJSON size check in webmap: externalize large files\n\nPhase 4 - Polish:\n- Add ReportBranding dataclass with --branding CLI option\n- Add 71 new tests (wetlands, report, CLI, HTTP retry)\n\n170 tests pass (1 skipped).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["cf055d26450aed0f4a0d6a3de25e0484cbb22f82"],"add":1671,"del":394,"cadd":1671,"cdel":394,"files":32},{"repo":"groundwork","hash":"aa129d0c8850c462128f457a9d8e957c651c8f0b","ts":1770612148,"wall":"2026-02-08T23:42","msg":"Add session handoff, knowledge docs, and test project outputs","body":"- .claude/handoff.md: session state from UI enhancement work\n- docs/knowledge/: webmap research notes and index\n- projects/: 12 test project outputs (pipeline validation data)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["22887c5382776080cfc0ab984bbd7bd44c547e7f"],"add":3770906,"del":0,"cadd":2602846,"cdel":0,"files":454},{"repo":"groundwork","hash":"9c815dc3839a95a26ed9a92388951562600df12e","ts":1770612363,"wall":"2026-02-08T23:46","msg":"Update session handoff for fix & polish work","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["aa129d0c8850c462128f457a9d8e957c651c8f0b"],"add":89,"del":84,"cadd":89,"cdel":84,"files":1},{"repo":"groundwork","hash":"d32e4eedb1b9894898df402d8c9d4a806ff43742","ts":1770620668,"wall":"2026-02-09T02:04","msg":"Add boundaries, environmental modules; fix soils SQL bugs; remove broken endpoints","body":"New acquire modules:\n- boundaries.py: Census TIGERweb layer registry (states, counties, places, school districts, congressional)\n- environmental.py: EPA superfund/brownfields + USFWS critical habitat with concern flag\n- broadband.py: FCC Broadband Data Collection (written, not wired — needs API credentials)\n\nSoils fixes:\n- component query: hydclprs does not exist, correct column is hydricrating\n- farmland query: farmlndcl lives in mapunit table, not muaggatt\n\nRemoved from pipeline (broken upstream endpoints):\n- Groundwater (USGS NWIS 404)\n- Ownership (BLM ArcGIS 500)\n- Wetlands (NWI endpoint 404, URL moved)\n\nPipeline: 12 steps. 184 tests passing.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["9c815dc3839a95a26ed9a92388951562600df12e"],"add":1242,"del":115,"cadd":1242,"cdel":115,"files":9},{"repo":"new-belen-game","hash":"772735b99aeaf52b9855910d36f45407ad869bc5","ts":1770677837,"wall":"2026-02-09T17:57","msg":"Add spiritual warfare combat system with faith mechanics","body":"Introduces turn-based combat encounters with demonic NPCs featuring:\n- Spiritual combat (prayer, scripture, rebuke) vs spiritual health\n- Physical combat (dodge, push, restrain) vs physical health\n- Boss battles for possession demons\n- Holy items: holy water, silver cross, anointing oil\n- Faith resource system (0-100) for combat actions\n- Demon types: temptation, deception, oppression, possession\n- Preacher-specific combat bonuses (Belen +25% vs temptation)\n- Combat integration into main game loop and narrative system\n- Aggressive mood added for hostile/demonic NPCs\n\nCombat engine extends existing conversation system to maintain\nconsistent UI patterns (4-action limit, modifier display).\n\nTested: All combat mechanics, faith management, holy items, victory/defeat conditions.\n\nAuthored by Rowan Valle; Executed by Claude Code\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>","parents":["af6d9e3576086d44020a13ef4856b539e2a36448"],"add":1078,"del":5,"cadd":1078,"cdel":5,"files":11},{"repo":"techbiont-framework","hash":"bb34bf88cbccce891a467964711184b2fbc3af50","ts":1770694641,"wall":"2026-02-09T22:37","msg":"docs: add RAG-based session continuity protocol","body":"Transition from manual handoff.md files to RAG semantic search for session continuity. Phase 2 (RAG MCP) is validated and operational. New protocol documents how to use RAG collections (knowledge_base, aar_archive, decisions) for persistent session memory.\n\nKey changes:\n- Created RAG-HANDOFF-PROTOCOL.md with complete protocol\n- Documents session start/end procedures using RAG\n- Clarifies MESO v2 phase structure (1, 2, 4 - no Phase 3)\n- Provides examples and best practices for indexing\n\nPhase 2 validated 2026-02-09 with 35+ chunks indexed across collections.\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>","parents":["74ff542ca05d070cf0b68bd68953998045bbe67c"],"add":279,"del":0,"cadd":279,"cdel":0,"files":1},{"repo":"techbiont-framework","hash":"1a2853875eb59873895b1482ee0c466b1ab43112","ts":1770696571,"wall":"2026-02-09T23:09","msg":"Update Standing Order #8 to verification-led development","body":"Refactor SO#8 from \"Continuous Auditing\" to \"Verification-Led Development\"\nto incorporate Boris's (Claude Code creator) key insight: state verification\nmethod upfront before starting any task.\n\nChanges:\n- Require stating verification method before work begins (6-point checklist)\n- Add domain-specific verification examples (code, UI, config, docs, shell)\n- Make verification a feedback loop (verify immediately, fix if fails, re-verify)\n- Align with industry best practices from Claude Code expert workflow\n\nThis implements Phase 1 of the MESO simplification plan: Boris-aligned\narchitecture for verification-led development.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["bb34bf88cbccce891a467964711184b2fbc3af50"],"add":16,"del":7,"cadd":16,"cdel":7,"files":1},{"repo":"techbiont-framework","hash":"6606df7fde518c81cce94db092523aa58f844055","ts":1770699944,"wall":"2026-02-10T00:05","msg":"Document MCP server integrations in STANDING-ORDERS","body":"Add comprehensive MCP (Model Context Protocol) documentation to Part VII:\n- Configuration locations and structure\n- Available servers: filesystem, memory, rag\n- Tool comparison: when to use MCP vs built-in tools\n- Backend service requirements (Qdrant, Ollama)\n- Access control and security integration\n- Troubleshooting guidance\n\nResolves MESO audit Priority 2: document MCP server configuration.\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>","parents":["1a2853875eb59873895b1482ee0c466b1ab43112"],"add":69,"del":0,"cadd":69,"cdel":0,"files":1},{"repo":"groundwork","hash":"a10f690ddfac3a3c146a46ca88876bcf9f1c48a6","ts":1770743632,"wall":"2026-02-10T12:13","msg":"Harden inputs: SQL injection, command injection, path traversal fixes","body":"- Validate mukeys are alphanumeric before SQL interpolation in SDA queries\n- Replace shell=True subprocess call with os.startfile() on Windows\n- Block absolute paths in API schema name validation\n- Add 11 security regression tests\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d32e4eedb1b9894898df402d8c9d4a806ff43742"],"add":83,"del":2,"cadd":83,"cdel":2,"files":5},{"repo":"groundwork","hash":"eb084ec545493eee5fea23016de77193110139c2","ts":1770752413,"wall":"2026-02-10T14:40","msg":"Fix NWI wetlands endpoint URL (USFWS domain migration)","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["a10f690ddfac3a3c146a46ca88876bcf9f1c48a6"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"groundwork","hash":"ae6d7cd27bf276b7104007111af81805c38baec6","ts":1770752436,"wall":"2026-02-10T14:40","msg":"Disable broadband module: FCC API deprecated (HTTP 405)","body":"fetch() now raises DataAcquisitionError with clear message pointing to\nbulk CSV downloads as replacement. Module preserved for reimplementation.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["eb084ec545493eee5fea23016de77193110139c2"],"add":15,"del":208,"cadd":15,"cdel":208,"files":2},{"repo":"groundwork","hash":"844074a471b12f6f3173e1e9c123e0b7216369e5","ts":1770752480,"wall":"2026-02-10T14:41","msg":"Resolve absolute paths for WhiteboxTools compatibility","body":".resolve() on all interim/processed paths so WhiteboxTools gets absolute\npaths regardless of working directory.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ae6d7cd27bf276b7104007111af81805c38baec6"],"add":14,"del":11,"cadd":14,"cdel":11,"files":1},{"repo":"groundwork","hash":"e3bf83ff04d17466332e0e8d6147e265be1014ac","ts":1770752488,"wall":"2026-02-10T14:41","msg":"Wire boundaries, environmental, groundwater, ownership into API + TUI","body":"These modules worked but were only reachable via CLI. Now all three\npipelines (CLI, API, TUI) call them with try/except on failure.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["844074a471b12f6f3173e1e9c123e0b7216369e5"],"add":82,"del":1,"cadd":82,"cdel":1,"files":4},{"repo":"groundwork","hash":"e4b392bc0040f6c780e7ef7166aa71814d6e3de3","ts":1770752495,"wall":"2026-02-10T14:41","msg":"Update session handoff for broken modules fix","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["e3bf83ff04d17466332e0e8d6147e265be1014ac"],"add":26,"del":115,"cadd":26,"cdel":115,"files":1},{"repo":"groundwork","hash":"f21f27521a1d6238d1315205d589b8f22d0734f2","ts":1770785718,"wall":"2026-02-10T23:55","msg":"Fix TUI screens rendering blank after navigation","body":"Changed fixed width CSS (width: 80) to flexible width (width: auto with max-width: 100)\non wizard-container and progress/results boxes. The fixed width combined with Center\ncontainer centering was causing screens to render off-screen or blank.\n\nFiles modified:\n- groundwork/tui/screens/wizard_base.py (LocationScreen, ProjectScreen, SourcesScreen, OutputsScreen)\n- groundwork/tui/screens/progress.py (ProgressScreen)\n- groundwork/tui/screens/results.py (ResultsScreen)\n\nThis should fix the issue where pressing \"Start Analysis\" caused a blank screen.\n\nCo-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>","parents":["e4b392bc0040f6c780e7ef7166aa71814d6e3de3"],"add":1977962,"del":7499,"cadd":508924,"cdel":7499,"files":247},{"repo":"techbiont-framework","hash":"ef7d306b0de888c4e2f110ce4232caebd455362e","ts":1770834480,"wall":"2026-02-11T13:28","msg":"MESO checkpoint: Phase 3 research, patterns, and infrastructure consolidation","body":"## Changes\n\n### Knowledge Base\n- Consolidated 8 new research documents into docs/knowledge/\n- Added decision record: AECO classification framework (2026-02-09)\n- Added guides: telegram bot implementation, news ticker patterns, supply chain resilience\n- Added analysis: local organelle fine-tuning, interactive feed design patterns\n- Organized research: US manufacturing networks, contractor network resilience\n\n### Infrastructure & Templates\n- Added form generation framework with 3 themes (artdeco, biopunk, terminal)\n- Added form templates: AAR, architecture, surveys, bipolar scales, demo examples\n- Added handoff parser tool (Python)\n- Enhanced knowledge document index\n\n### Updates\n- Updated handoff.md with current session state\n- Updated STANDING-ORDERS.md with evolved patterns\n- Updated form schemas and validation logic\n\n## State\nAll research, AARs, decision records, and supporting materials now consolidated in:\n- docs/knowledge/ - research, decisions, patterns\n- docs/knowledge/aars/ - session AARs\n- templates/knowledge/ - document templates\n- templates/forms/ - interactive form system\n- tools/ - automation utilities\n\nReady for fresh start and new phase.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["6606df7fde518c81cce94db092523aa58f844055"],"add":12867,"del":8,"cadd":12824,"cdel":8,"files":30},{"repo":"margin","hash":"e507e2cb680fea2273d3bba84c25a10ac5089bfa","ts":1770845352,"wall":"2026-02-11T16:29","msg":"feat: Complete Phase 5 unblocking - infrastructure, tooling, and test setup","body":"This commit addresses all Phase 5 blockers identified in the comprehensive audit,\nestablishing a solid foundation for ticker evolution implementation.\n\n## Verification Gates - All Passing ✅\n- TypeCheck: 6/6 packages compile without errors\n- Lint: 0 errors (28 pre-existing warnings in warn mode)\n- Build: ✓ Successful in 17.97s\n- Tests: 46 test files, 336+ tests passing\n\n## Infrastructure & Tooling (Primary Blockers)\n\n### ESLint Setup\n- Added .eslintrc.json with TypeScript support\n- Installed eslint, @typescript-eslint/parser, @typescript-eslint/eslint-plugin\n- Configured warn-mode for pre-existing issues (technical debt tracked separately)\n- Establishes code quality baseline for Phase 5 development\n\n### TypeScript Fixes\n- Fixed 3 unused parameter warnings in apps/extension (service-worker.ts)\n- Removed unused imports: DEFAULT_APP_SETTINGS, beforeEach\n- Fixed no-case-declarations lint errors in packages/features/ticker/router.ts\n  and apps/web/pages/search/SearchPage.tsx (wrapped in braces)\n\n### Test Infrastructure\n- Created packages/features/vitest.config.ts (fixes test discovery)\n- Created packages/ui/vitest.config.ts (fixes test discovery)\n- Root vitest.setup.ts is now properly referenced by package-level configs\n- Resolves \"No test files found\" errors preventing test execution\n\n### Dependency Security Updates\n- Updated vitest to latest (2.1.9)\n  - Brings esbuild from 0.21.5 to 0.27.3 (removes vulnerability)\n  - Dependency tree cleaned up, pnpm-lock.yaml regenerated\n\n## Phase 5 Foundation Work\n\n### Ticker Components & Tests\n- Enhanced ticker adapter tests (packages/features/src/ticker/adapter.test.ts)\n- Ticker routing logic verified and lint-fixed (packages/features/src/ticker/router.ts)\n- Component test baseline for TickerItem, TickerTape, TickerToggle passing\n\n### Feed Discovery\n- Feed discovery implementation (packages/features/src/feeds/discovery.ts)\n- UI component updates (packages/ui/src/feeds/FeedDiscovery.tsx)\n- Integration with feed feature exports\n\n### Documentation & Cleanup\n- Archived obsolete roadmap and handoff files\n- Created AUDIT-2026-02-11.md with detailed audit findings (grade: A-, 97/100)\n- Updated MASTER-PLAN.md with current Phase 5 status\n- Ticker architecture decisions documented\n\n## Technical Debt Tracked\n- Pre-existing console statements (28 warnings) - acceptable for now\n- Unused imports in test files - non-critical\n- Note: These are configured to warn, not error, supporting continuous improvement\n  without blocking feature development\n\n## Ready for Phase 5 Implementation\nAll verification gates established and passing. Infrastructure supports:\n- Continuous type checking\n- Automated code quality checks\n- Comprehensive test coverage\n- Dependency security monitoring\n\nThis foundation enables rapid, high-quality development of ticker evolution features.\n\nAuthored by Rowan Valle; Executed by Claude Code\nCo-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>","parents":["a023134da9f96c0dcd55e5c0ee471a719abbb90a"],"add":8851,"del":724,"cadd":8801,"cdel":722,"files":49},{"repo":"margin","hash":"66947ab4c5e3269b6d26dc0a103f75cb3467ac64","ts":1770847851,"wall":"2026-02-11T17:10","msg":"feat: Add workspace entity and repository","body":"Implement Phase 5 Checkpoint 1: Workspace Entity & Storage\n\nNew features:\n- Workspace type definition with tags, isActive, isArchived, tickerConfigs\n- Dexie schema v2 → v3 migration with workspaces table\n- WorkspaceRepository with full CRUD operations\n- Filtering by isActive, isArchived, search by name/description\n- 19 comprehensive tests covering CRUD, queries, filtering, edge cases\n\nFiles added (3):\n- packages/core/src/types/workspace.ts\n- packages/storage/src/repositories/workspaces.ts\n- packages/storage/src/repositories/workspaces.test.ts\n\nFiles modified (5):\n- packages/core/src/types/index.ts - export Workspace types\n- packages/storage/src/adapters/types.ts - add WORKSPACES to STORES\n- packages/storage/src/adapters/dexie.ts - v3 schema, workspaces table\n- packages/storage/src/adapters/memory.ts - add WORKSPACES boolean fields\n- packages/storage/src/repositories/index.ts - export WorkspaceRepository\n\nVerification:\n✅ 929 tests passing (+19 workspace tests)\n✅ TypeCheck passing\n✅ Build passing\n✅ Lint passing (no new errors)\n\nWorkspaces are organizational containers for ticker configurations,\nenabling users to manage multiple ticker setups (max 6 per workspace).\n\nCo-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>","parents":["e507e2cb680fea2273d3bba84c25a10ac5089bfa"],"add":498,"del":2,"cadd":498,"cdel":2,"files":8},{"repo":"groundwork","hash":"99aaf0035e859227686f1b926099dc526f1cd227","ts":1770903842,"wall":"2026-02-12T08:44","msg":"Add PropertyFormat, BasemapConfig, and TERRAIN_CONFIG to layer config","body":"Introduce structured property formatting for the info panel: each\ninteractive layer now carries PropertyFormat entries with human-readable\nlabels, units, precision, and value maps. Add BasemapConfig dataclass\nand TERRAIN_CONFIG dict for basemap switching and 3D terrain toggle.","parents":["f21f27521a1d6238d1315205d589b8f22d0734f2"],"add":151,"del":0,"cadd":151,"cdel":0,"files":1},{"repo":"groundwork","hash":"64673d664e67f6aa738a32acb780bbaf3ca4c15f","ts":1770903864,"wall":"2026-02-12T08:44","msg":"Extract CSS and JS into shared template modules","body":"Move all map viewer styles into map_styles.py and reusable JS\ncomponents (theme toggle, coordinates, measurement, export, loading\nspinner) into map_scripts.py. Eliminates duplication between PMTiles\nand GeoJSON viewer modes.","parents":["99aaf0035e859227686f1b926099dc526f1cd227"],"add":429,"del":0,"cadd":429,"cdel":0,"files":2},{"repo":"groundwork","hash":"553c2f299d48aa87f75bc15f12cfe35cd36e2c9d","ts":1770903885,"wall":"2026-02-12T08:44","msg":"Unify PMTiles and GeoJSON viewers with new map features","body":"Merge _create_geojson_viewer and _create_viewer into a single\n_create_viewer(mode=) function. Both modes now share identical UI:\ndark-default theme with backdrop blur, SVG toolbar icons, loading\nspinner, basemap switcher (satellite/street/topo), 3D terrain toggle,\ngeocoding search bar, coordinate display, and info panel with\nformatted property cards.","parents":["64673d664e67f6aa738a32acb780bbaf3ca4c15f"],"add":472,"del":686,"cadd":472,"cdel":686,"files":1},{"repo":"groundwork","hash":"9dccfd5f9e94e12d01e3c69cc042189e2fa0ae1c","ts":1770903908,"wall":"2026-02-12T08:45","msg":"Add webmap test suite covering templates, viewers, and layer config","body":"41 tests across 9 test classes: CSS template content, JS component\nbehavior, basemap/terrain config, layer definitions for both modes,\nlegend HTML generation, interaction JS, unified viewer output, the\ngenerate() entry point, and layer config completeness validation.","parents":["553c2f299d48aa87f75bc15f12cfe35cd36e2c9d"],"add":396,"del":0,"cadd":396,"cdel":0,"files":1},{"repo":"groundwork","hash":"1de72b9a6f7c3bb1715529dfbb44cb481630ee81","ts":1770904026,"wall":"2026-02-12T08:47","msg":"Add Charlton County land analysis and enterprise webmap research docs","body":"Charlton County (6,583 ac) land use and revenue analysis for SE Georgia.\nEnterprise webmap research covering MapLibre, PMTiles, PostGIS, tile\nserving, styling, performance, and deployment patterns.","parents":["9dccfd5f9e94e12d01e3c69cc042189e2fa0ae1c"],"add":2279,"del":0,"cadd":2279,"cdel":0,"files":2},{"repo":"groundwork","hash":"15575c5a110ddbaa5077898eb6c29e0ae9e5aba3","ts":1770904033,"wall":"2026-02-12T08:47","msg":"Update session handoff for webmap viewer overhaul","body":"","parents":["1de72b9a6f7c3bb1715529dfbb44cb481630ee81"],"add":29,"del":24,"cadd":29,"cdel":24,"files":1},{"repo":"new-belen-game","hash":"42b341fd4447532ec11dbbc14ad9a2edd05dd30b","ts":1770910075,"wall":"2026-02-12T10:27","msg":"Wire up incomplete mechanics: park walk-away, moral alignment clamping, and tests","body":"- Add _handle_park() with PARK_WALK_AWAY_CHANCE roll before conversation\n- Add _handle_diner() with coffee purchase mechanic\n- Add _handle_community_center() with affiliation check\n- Add clamp_moral_alignment() to GameState, called after all alignment changes\n- Wire new location types (park, diner, laundromat, community center) into\n  _main_loop, models, and world generation\n- Add world_sim overnight events, demon ally system, descriptions module\n- Add 14 tests covering descriptions, locations, world sim, demon allies,\n  and moral alignment clamping (21 total tests pass)","parents":["772735b99aeaf52b9855910d36f45407ad869bc5"],"add":1757,"del":18,"cadd":1757,"cdel":18,"files":12},{"repo":"margin","hash":"3e87badd3c4f9df8f3688022003323297d605f0f","ts":1770910761,"wall":"2026-02-12T10:39","msg":"refactor: Centralize ticker settings, add error handling, tests, and buffer limits","body":"- Create TickerProvider context replacing 7 fragmented localStorage keys\n  and CustomEvent sync with single source of truth\n- Add toast notifications for localStorage failures (save errors, corrupt data)\n- Add useTickerSystem hook tests (11 cases covering init, persistence, routing)\n- Add globalMaxItems (default 500) with oldest-first eviction across buffers\n- Extract TickerToggle to own file, deprecate legacy TickerTape\n- Replace TickerTape tests with ChannelTicker equivalents\n- Add 3 router tests for global buffer limit enforcement\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["66947ab4c5e3269b6d26dc0a103f75cb3467ac64"],"add":948,"del":251,"cadd":948,"cdel":251,"files":14},{"repo":"new-belen-game","hash":"88a3c44dcb546f45c267552f0945adf87c2064c9","ts":1770911367,"wall":"2026-02-12T10:49","msg":"Add location-aware conversation text for non-house locations","body":"Thread location_type through conversation flow so rejection, empty,\nand no-answer text adapts to context (park, diner, laundromat, etc.)\ninstead of always showing house-specific \"door\" language.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["42b341fd4447532ec11dbbc14ad9a2edd05dd30b"],"add":195,"del":32,"cadd":195,"cdel":32,"files":5},{"repo":"margin","hash":"7b2ec1c7db74f483e1e31bbeb30ab4dc2235f245","ts":1770911678,"wall":"2026-02-12T10:54","msg":"fix: Replace CSS animation with requestAnimationFrame for smooth ticker scrolling","body":"CSS animation restarted from position 0 on every React re-render (items/speed\nchanges), causing visible snap. rAF loop survives re-renders and applies speed\nchanges instantly without interrupting scroll position.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["3e87badd3c4f9df8f3688022003323297d605f0f"],"add":44,"del":29,"cadd":44,"cdel":29,"files":2},{"repo":"margin","hash":"070bca9835e43c073a8b0f73ace1240c2921e351","ts":1770914379,"wall":"2026-02-12T11:39","msg":"feat: Add workspaceId to all entities and vault fields to workspaces (Phase 1)","body":"Schema migration for workspace isolation. Dexie v4 adds workspaceId index to\nbookmarks, notes, feeds, feedItems. Migration creates Default workspace and\nassigns all existing records to it. Vault fields (isVault, encryptionSalt,\nencryptionVerifier) added to Workspace type. All create factories and service\nmethods pass workspaceId through. Includes session handoff documentation.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["7b2ec1c7db74f483e1e31bbeb30ab4dc2235f245"],"add":370,"del":15,"cadd":370,"cdel":15,"files":17},{"repo":"margin","hash":"d323a2995107ab3f19aa0cc540941adf645dfc19","ts":1770915094,"wall":"2026-02-12T11:51","msg":"feat: Add WorkspaceService, ActiveWorkspace context, and workspace-scoped queries (Phase 2)","body":"Wire up workspace business logic layer and React context so all content\nqueries automatically scope to the active workspace. WorkspaceService\nhandles CRUD, activation (deactivate previous/activate new), and prevents\ndeleting the default workspace. Content hooks (bookmarks, notes, feeds)\ninject workspaceId from ActiveWorkspaceContext into filters and mutations.","parents":["070bca9835e43c073a8b0f73ace1240c2921e351"],"add":653,"del":22,"cadd":653,"cdel":22,"files":15},{"repo":"margin","hash":"638aaf4328be562d447a20c2ca72826d75528641","ts":1770916295,"wall":"2026-02-12T12:11","msg":"feat: Add workspace UI with switcher, pages, and create modal (Phase 3)","body":"Adds sidebar workspace switcher dropdown, WorkspacesPage grid, WorkspaceSettingsPage\nwith edit/archive/delete actions, CreateWorkspaceModal, and lazy-loaded routes.","parents":["d323a2995107ab3f19aa0cc540941adf645dfc19"],"add":628,"del":1,"cadd":628,"cdel":1,"files":5},{"repo":"margin","hash":"a35fb94f85378ab8db64eb3d2edc322ae67462ef","ts":1770919243,"wall":"2026-02-12T13:00","msg":"feat: Add full vault encryption and fix workspace switcher (Phase 4)","body":"Implement password-based vault encryption with three levels:\nL1 (notes/highlights), L2 (+descriptions/summaries), L3 (+URLs/titles).\nVaultService handles setup, unlock, password change, and removal.\nVaultContext holds CryptoKey in memory only. VaultUnlockGate blocks\ncontent when locked. Fix DropdownItem onSelect not firing, which\nbroke workspace switcher, create modal, and manage link.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["638aaf4328be562d447a20c2ca72826d75528641"],"add":1556,"del":12,"cadd":1556,"cdel":12,"files":30},{"repo":"margin","hash":"a74a479097878c0799144ac7bc08d592dfda7f41","ts":1770920151,"wall":"2026-02-12T13:15","msg":"fix: Add ActiveWorkspaceProvider to test wrappers","body":"Hooks now require workspace context after Phase 2-4 workspace\nintegration. Updated all 7 affected test files to include the provider.\n\n977/977 tests passing.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["a35fb94f85378ab8db64eb3d2edc322ae67462ef"],"add":74,"del":30,"cadd":74,"cdel":30,"files":7},{"repo":"margin","hash":"cd1e5c2f36cc070b49ebc4965f12449381370cd7","ts":1770921073,"wall":"2026-02-12T13:31","msg":"feat: Add table support to TipTap editor","body":"Add @tiptap/extension-table with resizable columns, header rows,\ntoolbar button, /table slash command, and prose styles.\nEnabled in 'full' preset via tables feature flag.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["a74a479097878c0799144ac7bc08d592dfda7f41"],"add":91,"del":1,"cadd":90,"cdel":1,"files":8},{"repo":"margin","hash":"42cb2904d218468c40eca8406c13bbc41bf13bf9","ts":1770921244,"wall":"2026-02-12T13:34","msg":"feat: Add image file upload, drag-drop, and paste support","body":"- Image popover now has URL/Upload tabs with file picker\n- Images compressed to 1200px max width, 0.8 JPEG quality\n- Drag-drop and paste via ImageDropExtension (ProseMirror plugin)\n- All images stored as base64 for local-first compatibility\n- Size warning shown for images >2MB\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["cd1e5c2f36cc070b49ebc4965f12449381370cd7"],"add":357,"del":42,"cadd":357,"cdel":42,"files":5},{"repo":"margin","hash":"10b5bed4a9a4c81174a846dcc069524e1f3e8236","ts":1770921986,"wall":"2026-02-12T13:46","msg":"feat: Add backlink index for O(1) backlink lookups","body":"Replace O(N) note scan with dedicated Dexie backlinkIndex table.\nIndex maintained on write in NoteService create/update/delete.\nSchema v6 migration builds index from existing linkedNotes arrays.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["42cb2904d218468c40eca8406c13bbc41bf13bf9"],"add":257,"del":187,"cadd":257,"cdel":187,"files":11},{"repo":"margin","hash":"330dc623a2eb4ae0b9d77dded2364c7327d60dcb","ts":1770926420,"wall":"2026-02-12T15:00","msg":"feat: Add property system and decouple tags from entities (Phase 2.1a)","body":"Remove tags: string[] from all entity types (Bookmark, Note, Feed,\nWorkspace). Tag assignments now stored as PropertyValue entries in a\nseparate propertyValues table. Tag definitions remain in their own\ntags table for simple CRUD. Adds PropertyDefinition and PropertyValue\ntypes for the general-purpose property system that will power\ncollections and custom properties.\n\nDexie v7 migration moves tag assignments from entities to\npropertyValues while preserving the tags table. UI components now\naccept tags as props instead of reading from entities.","parents":["10b5bed4a9a4c81174a846dcc069524e1f3e8236"],"add":852,"del":612,"cadd":852,"cdel":612,"files":51},{"repo":"margin","hash":"fa8a2c2c5b95f13d6f931f8a563e16458eeed60f","ts":1770929849,"wall":"2026-02-12T15:57","msg":"feat: Wire tag hooks to property system (Phase 2.1b)","body":"Connect UI components to the new PropertyValue-based tag storage.\nNew useEntityTags hooks provide read/write access to tags via the\nproperty system, replacing direct entity field access.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["330dc623a2eb4ae0b9d77dded2364c7327d60dcb"],"add":352,"del":106,"cadd":352,"cdel":106,"files":13},{"repo":"margin","hash":"3282c0bdd6d3f398ebafce8f8f88fb9fce4e8106","ts":1770931928,"wall":"2026-02-12T16:32","msg":"feat: Add Collection entity, repository, service, and hooks (Phase 2.2)","body":"Introduces the Collection data model — structured containers with multiple\nview types for organizing entities. Manual collections first; smart filter\nresolution deferred to Phase 2.6.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["fa8a2c2c5b95f13d6f931f8a563e16458eeed60f"],"add":639,"del":0,"cadd":639,"cdel":0,"files":17},{"repo":"margin","hash":"48a730fce3f9bf79f98c2ad3ac81bdd9e6f50077","ts":1770931956,"wall":"2026-02-12T16:32","msg":"feat: Add Collection list view UI, routing, and navigation (Phase 2.3)","body":"CollectionCard, CollectionList, CollectionForm components following existing\nbookmark patterns. CollectionsPage with search/layout toggle/CRUD,\nCollectionDetailPage with edit modal. Sidebar nav item with FolderKanban icon.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["3282c0bdd6d3f398ebafce8f8f88fb9fce4e8106"],"add":869,"del":0,"cadd":869,"cdel":0,"files":10},{"repo":"margin","hash":"9655063416df8d9074a0eac454c566510359f441","ts":1770937625,"wall":"2026-02-12T18:07","msg":"feat: Add Collection table view with schema-driven columns (Phase 2.4)","body":"TanStack React Table powered table view with type-aware cell renderers\nfor all property types, sorting support, and List/Table view toggle.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["48a730fce3f9bf79f98c2ad3ac81bdd9e6f50077"],"add":537,"del":133,"cadd":536,"cdel":133,"files":10},{"repo":"margin","hash":"afab0056c38c343be9a1e92f1d43bcf9501664cc","ts":1770938873,"wall":"2026-02-12T18:27","msg":"feat: Add Collection board view with drag-and-drop (Phase 2.5)","body":"Kanban-style board grouped by select properties via @dnd-kit. Dragging\ncards between columns updates property values. Extracted shared\nrenderPropertyValue utility from table view for reuse.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["9655063416df8d9074a0eac454c566510359f441"],"add":762,"del":141,"cadd":759,"cdel":141,"files":13},{"repo":"margin","hash":"c728a556d245156b0482b157a2bc0d27d9ec09e4","ts":1770939092,"wall":"2026-02-12T18:31","msg":"docs: Update MASTER-PLAN and CHANGELOG for Phase 2.1a–2.5","body":"Mark completed sub-phases in MASTER-PLAN with commit hashes.\nAdd Phase 2 section to CHANGELOG.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["afab0056c38c343be9a1e92f1d43bcf9501664cc"],"add":19,"del":3,"cadd":19,"cdel":3,"files":2},{"repo":"margin","hash":"c32fae7422562f1f43bbf01e06665b4bd4771393","ts":1770948486,"wall":"2026-02-12T21:08","msg":"refactor: Replace PropertyValue tag system with indexed tagAssignments table","body":"Tags were stored as JSON string[] inside PropertyValue records, forcing\nfull table scans for every tag query. Dead counting code (recalculateCounts,\ncountTagUsage) was never called. Three services orphaned PropertyValues on\nentity delete.\n\nNew tagAssignments table (following BacklinkIndex pattern) stores one row\nper entity-tag pair with indexed lookups. Dexie V9 migration flattens\nexisting PropertyValue tag data into the new table. All 13 tag mutation\npoints rewired. Three orphan bugs fixed (BookmarkService.delete,\nFeedService.unsubscribe, WorkspaceService.delete).\n\n983 tests passing, 10 new tests for TagAssignmentRepository.","parents":["c728a556d245156b0482b157a2bc0d27d9ec09e4"],"add":550,"del":384,"cadd":550,"cdel":384,"files":21},{"repo":"margin","hash":"c2371a26fb16d4ae2e34b7f34fd74da06646f273","ts":1770949037,"wall":"2026-02-12T21:17","msg":"docs: Add comprehensive technical debt registry (24 items)","body":"Full audit of storage, service, UI, and build layers. Key findings:\n- DexieAdapter multi-field where clause bug (silent perf regression)\n- MemoryAdapter boolean field divergence (test/prod mismatch)\n- 16 missing test files across repos, services, and components\n- Export/import missing 6 entity types\n- Collection deletion orphan bug\n- Multiple N+1 query patterns (vault, tags, search)\n- No input validation at service boundaries\n- SettingsPage 913 lines, FeedsPage 714 lines need decomposition","parents":["c32fae7422562f1f43bbf01e06665b4bd4771393"],"add":314,"del":0,"cadd":314,"cdel":0,"files":1},{"repo":"margin","hash":"26898182e5f972d5ff11ba2b12ed83aa80936b43","ts":1770949083,"wall":"2026-02-12T21:18","msg":"docs: Add build/config/DX debt findings (TD-25 through TD-34)","body":"Build/config agent found: 1.2MB main chunk from barrel imports pulling\nin TipTap, vitest version mismatch in features package, stale dist\nartifacts risk, missing sideEffects fields, no CI/CD workflow.\n\nTotal debt registry now 34 items (9 high, 17 medium, 7 low).","parents":["c2371a26fb16d4ae2e34b7f34fd74da06646f273"],"add":114,"del":4,"cadd":114,"cdel":4,"files":1},{"repo":"margin","hash":"b6f6e38c9deb0314f20df15820044b07b40e6257","ts":1770950302,"wall":"2026-02-12T21:38","msg":"fix: Pay down 10 tech debt items (TD-02, TD-09, TD-22, TD-23, TD-26 + 5 more)","body":"Freebies: Fix vitest version mismatch, sync MemoryAdapter boolean fields,\ninject version from package.json via Vite define.\n\nQuick wins: Add board drag duplicate guard, persist collection view toggle\nto localStorage.\n\nPerformance: Index PropertyValueRepository.getByEntity(), batch N×M property\nqueries in useCollectionItemProperties, split TipTap into vendor chunk\n(main bundle 1196KB → 708KB).\n\nTesting/DX: Add 14 backlink index tests, fix prepare script to rebuild dist.\n\n997 tests passing.","parents":["26898182e5f972d5ff11ba2b12ed83aa80936b43"],"add":283,"del":139,"cadd":281,"cdel":137,"files":13},{"repo":"margin","hash":"f071043bf1ff21d6f58c827baaced67b650a41b8","ts":1770950610,"wall":"2026-02-12T21:43","msg":"docs: Add tech debt paydown plan for remaining 23 items","body":"8 sessions across 35-45 hours, prioritized by ROI. Covers database\nperformance, bundle size, input validation, UI refactoring, CI/CD,\nand test coverage. Each session independently committable.","parents":["b6f6e38c9deb0314f20df15820044b07b40e6257"],"add":273,"del":0,"cadd":273,"cdel":0,"files":1},{"repo":"margin","hash":"0c13579d5d73b15a0673e3e519b9ccc812c17f10","ts":1770951534,"wall":"2026-02-12T21:58","msg":"fix: Pay down 9 tech debt quick fixes (Session 2)","body":"TD-07: Fix collection deletion orphan bug (clean up tagAssignments/propertyValues)\nTD-14: Replace 4 silent catch blocks with console.warn\nTD-20: Remove 23 production console.log statements from web app and extension\nTD-24: Make extension popup URL configurable via VITE_MARGIN_URL\nTD-28: Remove duplicate TypeScript version from apps/api\nTD-30: Add sideEffects: false to all 4 package.json files\nTD-31: Remove dist/ from Tailwind content scan\nTD-33: Add .editorconfig\nTD-34: Add rollup-plugin-visualizer behind ANALYZE env flag","parents":["f071043bf1ff21d6f58c827baaced67b650a41b8"],"add":149,"del":788,"cadd":129,"cdel":784,"files":21},{"repo":"margin","hash":"4c477876b0af51a96a5d52a08aaadd33d0fd3596","ts":1770952076,"wall":"2026-02-12T22:07","msg":"perf: Fix multi-field WHERE, add compound indexes, fix tag N+1 (Session 3)","body":"TD-01: Rewrite DexieAdapter.query() and count() to chain .and() filters\nfor all equality fields instead of only using the first field.\nTD-08: Add V10 schema with compound indexes for common multi-field queries\n(workspaceId+isFavorite, feedId+isRead, tagName+entityType, etc.).\nTD-12: Replace N+1 getAllWithCounts loop with bulk getAllCountsByTag() that\nfetches all tag assignment counts in a single pass.","parents":["0c13579d5d73b15a0673e3e519b9ccc812c17f10"],"add":102,"del":20,"cadd":102,"cdel":20,"files":3},{"repo":"margin","hash":"6371a4b0d3acaf0db7c96ff6e8f858f25431f637","ts":1770953291,"wall":"2026-02-12T22:28","msg":"feat: Add custom error types and input validation (TD-15, TD-13)","body":"Introduce MarginError hierarchy (NotFoundError, ValidationError,\nDuplicateError, NetworkError) and input validation utilities\n(validateUrlOrThrow, validateNonEmpty, validateStringLength, validateTags).\nAll feature services updated to use typed errors instead of generic Error.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["4c477876b0af51a96a5d52a08aaadd33d0fd3596"],"add":199,"del":74,"cadd":199,"cdel":74,"files":11},{"repo":"margin","hash":"fc21e86e7961502f60f9a8c4870d6db7eea820ac","ts":1770955219,"wall":"2026-02-12T23:00","msg":"perf: Fix VaultService N+1 saves and SearchService full scan (TD-10, TD-11)","body":"Add saveMany() to BookmarkRepository and NoteRepository using adapter.putMany().\nVaultService encrypt/decrypt now batches all saves instead of sequential puts.\nAdd searchItems() to FeedRepository; SearchService uses it instead of\nfetching 1000 items and filtering in memory.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["6371a4b0d3acaf0db7c96ff6e8f858f25431f637"],"add":64,"del":64,"cadd":64,"cdel":64,"files":5},{"repo":"margin","hash":"43ed77aed008e731af224e55c139ddafee6e097d","ts":1770955965,"wall":"2026-02-12T23:12","msg":"fix: Enable noUnusedLocals/noUnusedParameters, add error boundaries + a11y (TD-29, TD-18, TD-19)","body":"Enable noUnusedLocals and noUnusedParameters in tsconfig.base.json.\nFix ~40 unused imports/variables across all packages.\nAdd CollectionErrorBoundary component for Board/Table/Form views.\nAdd aria-label to CollectionCard, aria-sort to CollectionTable headers.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["fc21e86e7961502f60f9a8c4870d6db7eea820ac"],"add":98,"del":74,"cadd":96,"cdel":74,"files":31},{"repo":"margin","hash":"db8e3eeeafda320ad31230fa5616ef01204de1b7","ts":1770956012,"wall":"2026-02-12T23:13","msg":"docs: Update handoff note for session 4","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["43ed77aed008e731af224e55c139ddafee6e097d"],"add":27,"del":47,"cadd":27,"cdel":47,"files":1},{"repo":"margin","hash":"7391011859ff1e487848ea8f703827214d5be285","ts":1770957838,"wall":"2026-02-12T23:43","msg":"refactor: Complete tech debt paydown — all 34 items cleared (Session 5)","body":"TD-32: CI/CD workflow, TD-21: circular dep fix, TD-25: barrel file\nbreakup (708→301KB main chunk), TD-16: SettingsPage decomp (913→43\nlines), TD-17: FeedsPage decomp (708→434 lines), TD-06: export/import\ncompleteness (+5 entity types), TD-03: repository tests (69 new),\nTD-04: service tests (87 new), TD-05: component tests (60 new).\n\nTest suite: 1213 tests across 71 files.","parents":["db8e3eeeafda320ad31230fa5616ef01204de1b7"],"add":4231,"del":1622,"cadd":4211,"cdel":1622,"files":62},{"repo":"margin","hash":"8d4003ff286286f8e046b1e3e16582b1d92a08b3","ts":1770958007,"wall":"2026-02-12T23:46","msg":"docs: Update changelog and handoff for session 5 completion","body":"Tech debt 34/34 cleared. Updated cumulative stats (1213 tests, 301KB\nbundle). Handoff points to Phase 3 as next priority.","parents":["7391011859ff1e487848ea8f703827214d5be285"],"add":51,"del":46,"cadd":51,"cdel":46,"files":2},{"repo":"margin","hash":"c57401d60557aedbd178e74c48103f44f910909c","ts":1771024162,"wall":"2026-02-13T18:09","msg":"chore: Housekeeping — de-brand docs, update contact info, gitignore additions","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["8d4003ff286286f8e046b1e3e16582b1d92a08b3"],"add":55,"del":21,"cadd":16,"cdel":19,"files":15},{"repo":"margin","hash":"04c91a72433f6c9335506b73a591f96061ddea4c","ts":1771024202,"wall":"2026-02-13T18:10","msg":"fix: Resolve all audit findings — P1/P2/P3 code quality fixes (Session 6)","body":"P1: Feed parser type safety (any→typed guard), fetcher error context,\nreference search error state. P2: Tag N+1 eliminated via ensureMany(),\nunused vars cleaned up, Toast altText wired to aria-label. P3: Test\nmock type safety, unused import removed. Integration test timeouts\nfixed. MASTER-PLAN updated to reflect actual state.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c57401d60557aedbd178e74c48103f44f910909c"],"add":132,"del":74,"cadd":132,"cdel":74,"files":16},{"repo":"margin","hash":"3e1ab040b60763d1b98dba04025d082256aff2c0","ts":1771024278,"wall":"2026-02-13T18:11","msg":"docs: Update handoff for session 6 (audit + fixes)","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["04c91a72433f6c9335506b73a591f96061ddea4c"],"add":40,"del":25,"cadd":40,"cdel":25,"files":1},{"repo":"margin","hash":"454a637bc91cdfd43fc32475f6c6755f6f06db34","ts":1771025828,"wall":"2026-02-13T18:37","msg":"feat: Add items to collections UI — modals, entity resolution, remove button","body":"Add mutation hooks (useAddItemToCollection, useRemoveItemFromCollection),\nentity resolver hook (useResolvedCollectionItems), and two modal components\n(AddItemsModal from collection page, AddToCollectionModal from bookmark/note\npages) to make collections fully usable from the UI.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["3e1ab040b60763d1b98dba04025d082256aff2c0"],"add":854,"del":5,"cadd":854,"cdel":5,"files":12},{"repo":"margin","hash":"548c329c2a2d8ffc03bcd56067f217b74c0ceca4","ts":1771029654,"wall":"2026-02-13T19:40","msg":"feat: Resolved display in table/board views + batch addItems service method","body":"- Table and board views now show resolved titles, favicons, and type badges\n  instead of raw entity IDs\n- Added addItems() batch method to CollectionService (deduplicates, single save)\n- Added useAddItemsToCollection hook; AddItemsModal uses it instead of looping\n- Moved ResolvedItem type out of @margin/core into UI package (display concern)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["454a637bc91cdfd43fc32475f6c6755f6f06db34"],"add":270,"del":57,"cadd":270,"cdel":57,"files":13},{"repo":"margin","hash":"5765bea6dca3a2e599a98d7fc16c2e47993ae1b5","ts":1771030127,"wall":"2026-02-13T19:48","msg":"docs: Update handoff for session 7 (Phase 2.6a complete)","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["548c329c2a2d8ffc03bcd56067f217b74c0ceca4"],"add":44,"del":36,"cadd":44,"cdel":36,"files":1},{"repo":"margin","hash":"c69997bb63795bcfd2af6e0fef0b32d860fbcc2e","ts":1771032379,"wall":"2026-02-13T20:26","msg":"fix: Scope feed queries to active workspace + add background feed sync","body":"Feed item hooks (useUnreadItems, useAllFeedItems, useStarredItems, etc.)\nwere missing workspace filtering, causing feeds to bleed across workspaces.\nApplied useWorkspaceFilter() consistently across all 7 feed hooks, matching\nthe pattern already used by bookmarks and notes. Widened repository and\nservice signatures to accept FeedItemFilter with workspaceId throughout.\n\nAdded 15-minute background feed sync in AppShell to fetch fresh RSS content\nfrom the network. Reduced useUnreadItems polling from 60s to 30s so the\nticker picks up new items faster.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5765bea6dca3a2e599a98d7fc16c2e47993ae1b5"],"add":94,"del":66,"cadd":94,"cdel":66,"files":8},{"repo":"margin","hash":"d1285541044a959ab31077cd26b91547c605ed5f","ts":1771034161,"wall":"2026-02-13T20:56","msg":"feat: Collection filter engine — types, evaluation, sort, group (Phase 2.6b-1)","body":"Extended FilterOperator from 9 to 25 operators covering text, number, date\n(including relative dates like past_week/this_month), select, multi-select,\nand checkbox. Added FilterGroup with AND/OR combinators and 2-level nesting,\nSortRule for multi-field cascading sort, and ViewConfig for per-view\npersistence of filter/sort/group settings.\n\nPure filter engine with zero React/storage deps: evaluateRule,\nevaluateFilterGroup (recursive AND/OR), applyFilters, applySorts,\ngroupItems. 67 tests covering every operator × property type, nested\nboolean logic, edge cases, and immutability.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c69997bb63795bcfd2af6e0fef0b32d860fbcc2e"],"add":1745,"del":10,"cadd":1745,"cdel":10,"files":6},{"repo":"mesnada","hash":"9e2575257b6c41365aa36ed12f978428db3742b0","ts":1771039342,"wall":"2026-02-13T22:22","msg":"Initial backend: hex grid, units, terrain, combat, game state, REST API","body":"Mesnada — a hex-based strategy game with probabilistic combat, 3 eras\n(Stone/Bronze/Iron), 12 unit types, terrain generation, XP/promotion,\nbankable action points, and a FastAPI game server. 44 tests passing.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":1811,"del":0,"cadd":1795,"cdel":0,"files":16},{"repo":"mesnada","hash":"dcf3c100e021834fcb50af4002937245f4cdac02","ts":1771041962,"wall":"2026-02-13T23:06","msg":"Remove era system, new unit roster, XP→AP feedback, perception stat","body":"Eras (Stone/Bronze/Iron) removed entirely — all 11 units available\nfrom turn 1, gated only by AP spawn cost. New roster: Raider,\nSlinger, Tracker, Prowler, Wyrd, Sagittary, Crossbowman, Psionic,\nEngineer, Arbalest, Cataphract. XP gained in combat now awards half\nas bonus AP to the owning player. Perception stat added to UnitType\nfor future stealth/detection mechanics. Terrain generation simplified\nto flat weights (no era-based variation).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["9e2575257b6c41365aa36ed12f978428db3742b0"],"add":167,"del":225,"cadd":167,"cdel":225,"files":9},{"repo":"mesnada","hash":"255ae1e2b93f10effeeed45ec594c65cd1a8b5bf","ts":1771042563,"wall":"2026-02-13T23:16","msg":"Add status effect system: confuse, DOT, effect processing","body":"StatusType enum (CONFUSED, CURSED) and StatusEffect dataclass added\nto Unit. Psionic can now confuse enemy units (skips their actions).\nEffects processed at end of turn: DOT damage applied, durations\nticked, expired effects removed. Confused units blocked from move,\nattack, heal, and confuse actions. DOT can kill units and trigger\nwin condition. Status effects serialized in API responses.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["dcf3c100e021834fcb50af4002937245f4cdac02"],"add":358,"del":4,"cadd":358,"cdel":4,"files":5},{"repo":"mesnada","hash":"5946e79e75cdca18e22060ba76a29f5aae510265","ts":1771043650,"wall":"2026-02-13T23:34","msg":"Add fortification system and stealth/ambush mechanics","body":"Fortifications: Engineer builds forts (+30% DEF), saps enemy forts,\nbridges impassable terrain. Arbalest siege destroys enemy forts on attack.\n\nStealth: Prowler spawns hidden, revealed on move/attack/adjacent contact.\nStealth crit: +75% vs low perception, +25% vs high perception.\nCombat now passes fortification and stealth params through to resolution.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["255ae1e2b93f10effeeed45ec594c65cd1a8b5bf"],"add":667,"del":16,"cadd":667,"cdel":16,"files":7},{"repo":"margin","hash":"e733fbfda6640d7fc2e1db67574b103dd66c389f","ts":1771075558,"wall":"2026-02-14T08:25","msg":"fix: Add missing @margin/features dep, remove orphaned eslint-disable, clean lint warnings","body":"- Add @margin/features as dependency of @margin/ui (phantom dep)\n- Remove eslint-disable for non-existent react-hooks/exhaustive-deps plugin\n- Remove unused imports/vars across 11 files (0 errors, 1 warning remaining)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d1285541044a959ab31077cd26b91547c605ed5f"],"add":25,"del":43,"cadd":24,"cdel":43,"files":14},{"repo":"margin","hash":"8436aa7f1c0f3b8b098ac3fa975dbbf0f5271da1","ts":1771075569,"wall":"2026-02-14T08:26","msg":"docs: Update CLAUDE.md and MASTER-PLAN.md to reflect current state","body":"- Replace stale packages/services references with packages/features\n- Update current state: collections add-items UI and filter engine shipped\n- Mark Phase 2.6a as Done, split 2.6b into 2.6b-1 (Done) and 2.6b-2 (Planned)\n- Update test count to 1,300 tests across 75 files\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["e733fbfda6640d7fc2e1db67574b103dd66c389f"],"add":23,"del":17,"cadd":23,"cdel":17,"files":2},{"repo":"margin","hash":"aad97f99e63ed2f550f00808c61d5a44c39e041e","ts":1771075579,"wall":"2026-02-14T08:26","msg":"fix: Patch qs vulnerability via pnpm override (>=6.14.2)","body":"Express 4.22.1 bundles qs@6.14.1 which has a DoS via arrayLimit bypass.\nOverride forces qs>=6.14.2 until Express ships a patched release.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["8436aa7f1c0f3b8b098ac3fa975dbbf0f5271da1"],"add":5,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"margin","hash":"506ad3836618335a1b9fc237b4f70bc1580a45b8","ts":1771075964,"wall":"2026-02-14T08:32","msg":"docs: Update handoff for session 8 (audit remediation complete)","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["aad97f99e63ed2f550f00808c61d5a44c39e041e"],"add":44,"del":32,"cadd":44,"cdel":32,"files":1},{"repo":"mesnada","hash":"f9648474350d513b17a61ef31150ba7f4b8b6f8b","ts":1771076330,"wall":"2026-02-14T08:38","msg":"Add React + PixiJS frontend: full playable client","body":"Three-phase implementation delivering complete hotseat MVP:\n- Hex board with PixiJS (pointy-top, terrain colors, emoji placeholders)\n- Movement, combat with preview modal, dice rolling, turn flow\n- Unit spawning panel, hex placement with ghost previews\n- All special abilities: heal, confuse, fortify, sap, bridge\n- Status effect icons, floating damage numbers, event animations\n- Scrollable event log, game over overlay\n- Vite dev server with API proxy to FastAPI backend\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5946e79e75cdca18e22060ba76a29f5aae510265"],"add":1794,"del":0,"cadd":1754,"cdel":0,"files":19},{"repo":"margin","hash":"febc076228cfceb7e7b4080292ee705fee4b932d","ts":1771076382,"wall":"2026-02-14T08:39","msg":"docs: Update MASTER-PLAN and CLAUDE.md to reflect Phase 2.6b-1 completion","body":"Phase 2 is now nearly done — only filter UI integration (2.6b-2) remains.\nUpdated shipped list to include add-items UI, filter engine, audit\nremediation, and qs vulnerability patch.","parents":["506ad3836618335a1b9fc237b4f70bc1580a45b8"],"add":6,"del":5,"cadd":6,"cdel":5,"files":2},{"repo":"mesnada","hash":"4f0ee1d6895a1fcb1edefe513a134aff818962af","ts":1771077607,"wall":"2026-02-14T09:00","msg":"Add package-lock.json for reproducible builds","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["f9648474350d513b17a61ef31150ba7f4b8b6f8b"],"add":1823,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"margin","hash":"6a6a20cb3358d9a7a8ec358bba35a9c54ef0638d","ts":1771078115,"wall":"2026-02-14T09:08","msg":"feat: Wire filter/sort/group pipeline into collection views (Phase 2.6b-2)","body":"Add useViewConfig hook with debounced persistence and legacy migration,\nGroupedListView and GroupedTableView components with collapsible sections,\nhideEmptyGroups support for board view, and filter→sort→group pipeline\nin CollectionDetailPage. 18 new tests across 3 test files.","parents":["febc076228cfceb7e7b4080292ee705fee4b932d"],"add":873,"del":16,"cadd":873,"cdel":16,"files":11},{"repo":"margin","hash":"4f5238c628ed77e048b860e7251546597030fc7f","ts":1771079556,"wall":"2026-02-14T09:32","msg":"feat: Filter bar UI — pills, popovers, sort editor, group selector (Phase 2.6b-3)","body":"FilterBar with active filter/sort pills, FilterRuleEditor popover with\ndynamic value inputs per property type, SortEditor popover with multi-field\nsupport, and group-by dropdown. Wired into CollectionDetailPage via\nuseViewConfig. 19 new tests across 3 test files.","parents":["6a6a20cb3358d9a7a8ec358bba35a9c54ef0638d"],"add":870,"del":3,"cadd":870,"cdel":3,"files":9},{"repo":"margin","hash":"156aa17e36a97b7c80a4ac1d6780d89af874b770","ts":1771080321,"wall":"2026-02-14T09:45","msg":"feat(wip): FilterGroupEditor — nested AND/OR filter groups (Phase 2.6b-4 partial)","body":"Recursive group editor with combinator toggle, inline rule editing,\nsub-group support (max 2 levels), and empty-rule cleanup. Still needs:\nFilterBar integration, keyboard shortcut, empty state, count badge,\nhide-empty-groups toggle, accessibility, and tests.","parents":["4f5238c628ed77e048b860e7251546597030fc7f"],"add":291,"del":0,"cadd":291,"cdel":0,"files":1},{"repo":"margin","hash":"c59c0c44973ee46648f708866e9553dc373313ce","ts":1771080387,"wall":"2026-02-14T09:46","msg":"docs: Update handoff for session 9 (Phase 2.6b-2/3 complete, 2.6b-4 in progress)","body":"","parents":["156aa17e36a97b7c80a4ac1d6780d89af874b770"],"add":61,"del":64,"cadd":61,"cdel":64,"files":1},{"repo":"margin","hash":"6aa7895cded0c05900e9d95c5063f8934c690d10","ts":1771081227,"wall":"2026-02-14T10:00","msg":"feat: Complete Phase 2.6b-4 — filter groups, keyboard shortcut, polish","body":"Wire FilterGroupEditor into FilterBar for nested AND/OR filter editing,\nadd filter count badge, hide-empty-groups toggle, F keyboard shortcut,\nfiltered-empty state, and accessibility (aria-live, aria-label on pills).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c59c0c44973ee46648f708866e9553dc373313ce"],"add":292,"del":63,"cadd":292,"cdel":63,"files":5},{"repo":"mesnada","hash":"85af5c047ef8b790112ee89fbe717a4726223801","ts":1771082420,"wall":"2026-02-14T10:20","msg":"Modular refactor: split monoliths into swappable single-responsibility modules","body":"Backend:\n- Extract config.py (all game constants), events.py (GameEvent + EventType)\n- Extract board_setup.py (parameterized game creation), terrain_gen.py (adjacency-weighted generation)\n- Split actions.py (629 lines) into actions/ package: result, movement, combat_actions, abilities, spawning, turn\n- Add docstrings with damage formulas to combat.py and terrain_gen.py\n\nFrontend:\n- Split GameBoard.tsx (481→133 lines) into rendering/ modules: hexRenderer, unitRenderer, animationRenderer, spriteLoader, constants\n- Extract useGameActions.ts from useGame.ts (335→124 lines)\n- Add sprite support with emoji fallback for raider/slinger/tracker\n\nAll 75 backend tests pass. TypeScript compiles clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["4f0ee1d6895a1fcb1edefe513a134aff818962af"],"add":1754,"del":1403,"cadd":1754,"cdel":1403,"files":44},{"repo":"margin","hash":"cf549da01ed0b4845f72ffab2b5e162c363b333d","ts":1771083649,"wall":"2026-02-14T10:40","msg":"docs: Update handoff for Phase 2 completion, begin Phase 3 planning","body":"Phase 2 Collections is fully complete. Handoff reflects session 10 final\nstate (1,349 tests, clean build). Phase 3 theme editor plan drafted.","parents":["6aa7895cded0c05900e9d95c5063f8934c690d10"],"add":18,"del":51,"cadd":18,"cdel":51,"files":1},{"repo":"margin","hash":"5e49c73b321a3934f680e275bddc04632a2e8d47","ts":1771084007,"wall":"2026-02-14T10:46","msg":"feat: Theme customization types and preset definitions (Phase 3.2-1)","body":"Define ThemePreset, PresetId, CustomThemeState types and 14 editable\nCSS color variables. Add 3 preset themes: Clean (current default),\nMidnight (deep blue-black), Paper (warm sepia).\n\nCloses #7","parents":["cf549da01ed0b4845f72ffab2b5e162c363b333d"],"add":229,"del":0,"cadd":229,"cdel":0,"files":5},{"repo":"margin","hash":"2d86e93bfb1de7e734000df38ba9b07b0b441104","ts":1771084349,"wall":"2026-02-14T10:52","msg":"feat: HSL color utilities, Slider primitive, ColorEditor (Phase 3.2-2)","body":"Add parseHSL/formatHSL utilities for CSS variable color manipulation.\nNew Slider range input primitive. ColorEditor component with H/S/L\nsliders and live color swatch preview.\n\nCloses #8","parents":["5e49c73b321a3934f680e275bddc04632a2e8d47"],"add":265,"del":0,"cadd":265,"cdel":0,"files":7},{"repo":"mesnada","hash":"b5b9953666f660524f5c2f1b5c55d8719eb8a96e","ts":1771084829,"wall":"2026-02-14T11:00","msg":"Add sprites for all 11 units, player color glow, territory outlines","body":"- Download PixelLab sprites for 7 units (raider, slinger, tracker,\n  prowler, wyrd, sagittary, crossbowman)\n- Programmatically generate 4 placeholder sprites (psionic, engineer,\n  arbalest, cataphract) matching art style\n- Wire all sprite paths into units.ts registry\n- Replace player color tint with glow aura behind sprites\n- Change player colors to violet and gold\n- Add territory outlines derived from unit positions + adjacency\n- SpawnPanel shows sprite thumbnails with emoji fallback\n- Add hexNeighbors utility to hex.ts\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["85af5c047ef8b790112ee89fbe717a4726223801"],"add":326,"del":18,"cadd":326,"cdel":18,"files":15},{"repo":"margin","hash":"adbc10cac625efac8fd8fe8257d882b2629fc321","ts":1771084851,"wall":"2026-02-14T11:00","msg":"feat: ThemeCustomizationProvider with preset/override persistence (Phase 3.2-3)","body":"React context managing preset selection and custom color overrides.\nPersists to localStorage, applies CSS variables to :root, and extends\nthemeScript for anti-flash on custom themes. Supports export/import\nof custom themes as JSON.\n\nCloses #9","parents":["2d86e93bfb1de7e734000df38ba9b07b0b441104"],"add":383,"del":0,"cadd":383,"cdel":0,"files":4},{"repo":"margin","hash":"a0c798ac49e5dc6b5e7d8b20f666b717f4e84d2c","ts":1771085366,"wall":"2026-02-14T11:09","msg":"feat: Theme editor UI — presets, custom colors, import/export (Phase 3.2-4)","body":"Add ThemePresetSelector (radio group with color swatches) and\nThemeCustomEditor (accordion HSL sliders with reset/export/import).\nWire into AppearanceSection with Tabs UI. Wrap app root with\nThemeCustomizationProvider.\n\nCloses #10","parents":["adbc10cac625efac8fd8fe8257d882b2629fc321"],"add":239,"del":4,"cadd":239,"cdel":4,"files":5},{"repo":"margin","hash":"c421098561275ac52f50946af301413256c31a93","ts":1771085610,"wall":"2026-02-14T11:13","msg":"feat: Custom theme editor — presets, HSL sliders, import/export (Phase 3.2) (#11)","body":"* feat: Theme customization types and preset definitions (Phase 3.2-1)\n\nDefine ThemePreset, PresetId, CustomThemeState types and 14 editable\nCSS color variables. Add 3 preset themes: Clean (current default),\nMidnight (deep blue-black), Paper (warm sepia).\n\nCloses #7\n\n* feat: HSL color utilities, Slider primitive, ColorEditor (Phase 3.2-2)\n\nAdd parseHSL/formatHSL utilities for CSS variable color manipulation.\nNew Slider range input primitive. ColorEditor component with H/S/L\nsliders and live color swatch preview.\n\nCloses #8\n\n* feat: ThemeCustomizationProvider with preset/override persistence (Phase 3.2-3)\n\nReact context managing preset selection and custom color overrides.\nPersists to localStorage, applies CSS variables to :root, and extends\nthemeScript for anti-flash on custom themes. Supports export/import\nof custom themes as JSON.\n\nCloses #9\n\n* feat: Theme editor UI — presets, custom colors, import/export (Phase 3.2-4)\n\nAdd ThemePresetSelector (radio group with color swatches) and\nThemeCustomEditor (accordion HSL sliders with reset/export/import).\nWire into AppearanceSection with Tabs UI. Wrap app root with\nThemeCustomizationProvider.\n\nCloses #10","parents":["cf549da01ed0b4845f72ffab2b5e162c363b333d"],"add":1116,"del":4,"cadd":1116,"cdel":4,"files":18},{"repo":"margin","hash":"6452a55b8f305d86a8f2db7c33816f362a5253a6","ts":1771085747,"wall":"2026-02-14T11:15","msg":"docs: Update handoff for session 11 (Phase 3.2 theme editor complete)","body":"","parents":["c421098561275ac52f50946af301413256c31a93"],"add":29,"del":16,"cadd":29,"cdel":16,"files":1},{"repo":"mesnada","hash":"649df9f5c5d3bc66ec9e845619c91d43ea55b11f","ts":1771085807,"wall":"2026-02-14T11:16","msg":"Add master roadmap: 4-phase plan with multiplayer and alliance system","body":"Phases: Playable → Fun → Polish → Ship\n- 2-6 player support with alliance diplomacy\n- AI opponents that can form/break alliances\n- Setting: ambiguous dying world (past is the future)\n- Dark synthwave grunge aesthetic\n- Influences section crediting inspirations\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["b5b9953666f660524f5c2f1b5c55d8719eb8a96e"],"add":286,"del":0,"cadd":286,"cdel":0,"files":2},{"repo":"margin","hash":"c0d660f9a3d582e8b66837a74a3191eebc8066de","ts":1771087011,"wall":"2026-02-14T11:36","msg":"docs: Update MASTER-PLAN and CLAUDE.md for Phase 2 complete + Phase 3.2 done","body":"Phase 2 marked complete (all 2.6b sub-phases). Phase 3 broken into\nsub-phases 3.1-3.5 with 3.2 (theming) done. Updated stats: 69K LOC,\n1,383 tests, 86 test files.","parents":["6452a55b8f305d86a8f2db7c33816f362a5253a6"],"add":25,"del":20,"cadd":25,"cdel":20,"files":2},{"repo":"mesnada","hash":"703d91b464f58fc4c2965d7b47a8f1103d5ba04a","ts":1771088299,"wall":"2026-02-14T11:58","msg":"Add research: hex ownership/fog-of-war and AI diplomacy systems","body":"Analysis for architecture decisions referenced in master roadmap:\n- Hex ownership: hybrid placement-capture model recommended\n- Fog of war: re-fogging with terrain memory, range-based vision\n- AI combat: utility AI + influence maps + heuristic scoring\n- AI diplomacy: trust/threat model with staged betrayal telegraph\n\nUpdated roadmap alliance recommendation to reference research.","parents":["649df9f5c5d3bc66ec9e845619c91d43ea55b11f"],"add":762,"del":1,"cadd":762,"cdel":1,"files":3},{"repo":"margin","hash":"a46738a022e4f1df0fe011f3a53e05adccde80d3","ts":1771088382,"wall":"2026-02-14T11:59","msg":"fix: Exclude archived items from non-archived views","body":"Archived bookmarks, notes, and workspaces now only appear in the\narchived view. Repository queries default isArchived to false when\nnot explicitly specified.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c0d660f9a3d582e8b66837a74a3191eebc8066de"],"add":34,"del":38,"cadd":34,"cdel":38,"files":6},{"repo":"mesnada","hash":"026155bfc4f6718f18545e4265b45e8c70ab2cd4","ts":1771089638,"wall":"2026-02-14T12:20","msg":"Full-screen viewport + roadmap update","body":"- Canvas fills available screen space via PixiJS resizeTo\n- Removed hardcoded 600x520 BOARD_WIDTH/BOARD_HEIGHT constants\n- Added ready state to prevent render before PixiJS init\n- html/body/root set to 100% height for proper flex layout\n- Updated roadmap: P1.0 viewport done, P1.1 abilities done (scout blocked by fog)\n- Added PN.N task numbering convention","parents":["703d91b464f58fc4c2965d7b47a8f1103d5ba04a"],"add":48,"del":37,"cadd":48,"cdel":37,"files":7},{"repo":"margin","hash":"ee43d0c82e72fc6ce9e7279316389f8996ad6a9d","ts":1771089717,"wall":"2026-02-14T12:21","msg":"fix: Align count() and tag counts to exclude archived items","body":"count() now routes through getAll() instead of raw adapter.count(),\nso the isArchived:false default applies. Tag count aggregations\naccept excludeEntityIds set; tag service collects archived IDs\nfrom bookmarks+notes and passes them as exclusions.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["a46738a022e4f1df0fe011f3a53e05adccde80d3"],"add":52,"del":24,"cadd":52,"cdel":24,"files":11},{"repo":"mesnada","hash":"de418d66cd115652aa3025559ee7952b9625f39b","ts":1771089995,"wall":"2026-02-14T12:26","msg":"Update session handoff for 2026-02-15","body":"","parents":["026155bfc4f6718f18545e4265b45e8c70ab2cd4"],"add":41,"del":37,"cadd":41,"cdel":37,"files":1},{"repo":"margin","hash":"1468f30ab242269ab40baf66dd451d93aa2cf4a0","ts":1771091611,"wall":"2026-02-14T12:53","msg":"docs: Plan Phase 3.3 Layout & Dashboard (radical customization)","body":"6 sub-phases: foundation types, density presets, widget grid dashboard,\nsidebar/width controls, named layout presets, panel system.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ee43d0c82e72fc6ce9e7279316389f8996ad6a9d"],"add":39,"del":31,"cadd":39,"cdel":31,"files":2},{"repo":"mesnada","hash":"5c3c2b905a63062cce2611d8573e06b361890823","ts":1771091894,"wall":"2026-02-14T12:58","msg":"P1.2 Fog of war: visibility, terrain memory, scout ability","body":"Perception-based visibility per unit, permanent terrain memory via\nrevealed_hexes, three-tier fog rendering (visible/remembered/dark),\nTracker scout ability (3 AP, 3-hex reveal radius). 15 new tests.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["de418d66cd115652aa3025559ee7952b9625f39b"],"add":502,"del":16,"cadd":502,"cdel":16,"files":14},{"repo":"margin","hash":"98f0db7913fc3a1b4343009df35f909c20566f3a","ts":1771092134,"wall":"2026-02-14T13:02","msg":"feat: Layout settings types and dashboard model (Phase 3.3a)","body":"Add LayoutSettings (density, sidebarPosition, contentWidth, dashboardLayout)\nand DashboardLayout/WidgetId types to core. Extend AppSettings with layout\nfield, deep-merge in settings repository, and auto-migrate pre-3.3a data\nthat lacks the layout field.\n\n1,386 tests passing (3 new for migration + deep merge).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["1468f30ab242269ab40baf66dd451d93aa2cf4a0"],"add":229,"del":3,"cadd":229,"cdel":3,"files":5},{"repo":"mesnada","hash":"40d037ea5575e2b78199080c55450ae1e544821d","ts":1771092413,"wall":"2026-02-14T13:06","msg":"P1.3 Hex ownership: influence-based territory with defense bonus","body":"Territory computed from unit adjacency — hex owned by player with most\nadjacent units, ties are contested. Deep territory (+10% defense) when\nhex and all neighbors are owned. Backend-computed territory replaces\nclient-side influence zone. 8 new tests (98 total).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5c3c2b905a63062cce2611d8573e06b361890823"],"add":193,"del":23,"cadd":193,"cdel":23,"files":7},{"repo":"margin","hash":"16f6ee82e09a67577a58fdcdc125ddc4f8d760b2","ts":1771092484,"wall":"2026-02-14T13:08","msg":"docs: Mark Phase 3.3a complete in roadmap","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["98f0db7913fc3a1b4343009df35f909c20566f3a"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"mesnada","hash":"44894e18a9649b131a0fdc655325ea672317a4bc","ts":1771093077,"wall":"2026-02-14T13:17","msg":"P2.0 Expand to 2-6 players with game setup screen","body":"N-player support: parameterized board setup with equidistant starting\npositions, circular turn rotation skipping eliminated players,\nPLAYER_ELIMINATED event, 6 synthwave player colors. Game setup screen\nfor choosing player count (2-6) and board size. 10 new multiplayer\ntests (108 total).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["40d037ea5575e2b78199080c55450ae1e544821d"],"add":463,"del":54,"cadd":463,"cdel":54,"files":13},{"repo":"margin","hash":"600e167e48daaba28aa399bf0b2f99fb30fc3925","ts":1771093242,"wall":"2026-02-14T13:20","msg":"feat: Density presets with CSS custom properties (Phase 3.3b)","body":"Three density levels (compact/comfortable/spacious) via data-density\nattribute on :root. CSS variables control spacing and font sizes app-wide.\nLayoutProvider context (localStorage persistence, follows theme pattern).\nSettings UI with density selector.\n\n1,394 tests passing (+8 new).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["16f6ee82e09a67577a58fdcdc125ddc4f8d760b2"],"add":326,"del":0,"cadd":326,"cdel":0,"files":7},{"repo":"margin","hash":"df460ae405ee746041a1146f9d5cbe5c05fb9130","ts":1771100275,"wall":"2026-02-14T15:17","msg":"docs: Mark Phase 3.3b complete in roadmap","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["600e167e48daaba28aa399bf0b2f99fb30fc3925"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"mesnada","hash":"c39c42ed9ffde56ec007566a2d480c3bb6705fe6","ts":1771100373,"wall":"2026-02-14T15:19","msg":"P2.1 Combat AI: greedy heuristic opponent for empty seats","body":"Adds AI module (game/ai/) with action generation, heuristic scoring,\nand greedy turn engine. AI auto-plays after human actions. Setup screen\nlets players toggle Human/AI per seat (default: seat 1 human, rest AI).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["44894e18a9649b131a0fdc655325ea672317a4bc"],"add":677,"del":9,"cadd":677,"cdel":9,"files":12},{"repo":"mesnada","hash":"b58fc9b9962242ce44128acfbff3b232db1ade85","ts":1771101604,"wall":"2026-02-14T15:40","msg":"P2.1 Fix single-player identity: gate all actions on humanPlayer","body":"Frontend now tracks humanPlayer (first non-AI seat) and isMyTurn\nthroughout the entire action and UI layer. HUD shows \"Your Turn\" vs\n\"Player N (AI)\", hides action buttons during AI turns. Backend get_game\naccepts ?viewer param. Added start.sh launcher script.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c39c42ed9ffde56ec007566a2d480c3bb6705fe6"],"add":103,"del":42,"cadd":103,"cdel":42,"files":6},{"repo":"mesnada","hash":"5232b10b7822ec31676f92b4236938bafeb47ad4","ts":1771102185,"wall":"2026-02-14T15:49","msg":"P2.1 Fix stale port issue in start.sh, update handoff","body":"start.sh now kills processes on ports 8000/5173 before starting.\nThe AI-not-playing bug was caused by old backend still bound to\nport 8000 — new uvicorn silently failed to start.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["b58fc9b9962242ce44128acfbff3b232db1ade85"],"add":81,"del":47,"cadd":81,"cdel":47,"files":2},{"repo":"mesnada","hash":"e8a78f9b07697a8e921a5636e0827ba15eb5aa35","ts":1771106796,"wall":"2026-02-14T17:06","msg":"P3.0-3.5 Gameplay features: terrain, stance, flying, panning, UI","body":"- P3.0: Cataphracts blocked from forests and mountains (heavy cavalry)\n- P3.1: Confirmed ranged fire over friendly units works (test added)\n- P3.2: Ability buttons larger, more visible, with descriptions\n- P3.3: Drag-to-pan viewport via camera container\n- P3.4: Defensive stance (+25% DEF, costs 2 AP, clears on move)\n- P3.5: Aquilarii eagle rider unit (flying, ignores all terrain)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5232b10b7822ec31676f92b4236938bafeb47ad4"],"add":358,"del":43,"cadd":358,"cdel":43,"files":17},{"repo":"mesnada","hash":"05fd029abf6fa8e5f9a30c175ad0657badd84444","ts":1771109071,"wall":"2026-02-14T17:44","msg":"P3.x UI: keyboard controls, terrain info, range indicators","body":"- Keyboard shortcuts: R=roll, E=end turn, S=spawn, D=defend,\n  Esc=cancel, Enter=confirm attack, ←→=cycle units\n- Terrain info panel shows defense bonus, move cost, LOS blocking\n  when any hex is selected\n- Range indicator highlights hexes within attack range for ranged\n  units, shows distance numbers on enemy-occupied hexes\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["e8a78f9b07697a8e921a5636e0827ba15eb5aa35"],"add":155,"del":3,"cadd":155,"cdel":3,"files":6},{"repo":"mesnada","hash":"a7fcaaf890b7ffb0a3fbaab3ca2142d299d550e8","ts":1771109480,"wall":"2026-02-14T17:51","msg":"Update handoff for P3.0-3.5 + P3.x UI session","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["05fd029abf6fa8e5f9a30c175ad0657badd84444"],"add":46,"del":48,"cadd":46,"cdel":48,"files":1},{"repo":"mesnada","hash":"2b01b86179e297bb20b4abe93a6e3ea724604abb","ts":1771111060,"wall":"2026-02-14T18:17","msg":"P3.x UI: keyboard chart, range indicator red outlines, team-color selection","body":"- Add KeyboardChart component below EventLog with grouped shortcut reference\n- Range indicator now draws red hex outlines on all tiles within attack range\n- Selected friendly unit hex highlighted in team color instead of yellow\n- Fix humanPlayer===0 falsy bug in range/selection checks\n- Remove old inline help text from HUD (replaced by chart)\n\nNote: hex selection highlighting has a regression — needs investigation.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["a7fcaaf890b7ffb0a3fbaab3ca2142d299d550e8"],"add":125,"del":11,"cadd":125,"cdel":11,"files":4},{"repo":"mesnada","hash":"4532bd44926f64877355755993835df871b179ca","ts":1771111114,"wall":"2026-02-14T18:18","msg":"Update handoff: keyboard chart session, note hex selection regression","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["2b01b86179e297bb20b4abe93a6e3ea724604abb"],"add":18,"del":28,"cadd":18,"cdel":28,"files":1},{"repo":"mesnada","hash":"f1f4cc0cd09c0569bc3d3763b29c2814777bfc34","ts":1771118214,"wall":"2026-02-14T20:16","msg":"Fix PixiJS 8 rendering, fog-of-war leaks, and board balance","body":"Migrate all rendering to PixiJS 8 API (fill/stroke instead of\nbeginFill/lineStyle/endFill). Fix fog-of-war leaks: filter events\nby viewer visibility, hide enemy units on fogged hexes, filter\nterritory outlines by visibility. Increase default board radius to 5.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["4532bd44926f64877355755993835df871b179ca"],"add":117,"del":43,"cadd":117,"cdel":43,"files":9},{"repo":"mesnada","hash":"df2cc2e234e546d8f5350d8a4076257f17d198ea","ts":1771121595,"wall":"2026-02-14T21:13","msg":"Ability registry: define abilities in one place, dispatch everywhere","body":"Replace hardcoded ability dispatch across main.py, AI, and frontend with\na centralized AbilityDef registry. New abilities now require touching only\none file (game/abilities.py). Adds GET /api/abilities endpoint, unified\n\"ability\" action_type, and generic targeting mode on frontend.\n\nAll 143 tests pass, TypeScript clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["f1f4cc0cd09c0569bc3d3763b29c2814777bfc34"],"add":710,"del":422,"cadd":710,"cdel":422,"files":14},{"repo":"mesnada","hash":"4e52c1cfd7c1e73f91adcad90e58be083e924c7d","ts":1771121663,"wall":"2026-02-14T21:14","msg":"Update handoff for ability registry refactor session","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["df2cc2e234e546d8f5350d8a4076257f17d198ea"],"add":35,"del":31,"cadd":35,"cdel":31,"files":1},{"repo":"mesnada","hash":"f9cd9302b22523feafe31fac0996d532b2e8bd7a","ts":1771122675,"wall":"2026-02-14T21:31","msg":"Structures system: fort/treasury, siege, capture, fort sprite","body":"Replace fortifications dict with Structure dataclass (fort/treasury).\nTreasury upgrade raises AP cap by 50. Dynamic AP cap in dice roll and\ncombat AP. Structure capture on move into undefended enemy structure.\nArbalest siege destroys structures. Fort sprite rendering with correct\nz-order (renders above hex tiles). Event types for treasury and capture.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["4e52c1cfd7c1e73f91adcad90e58be083e924c7d"],"add":569,"del":54,"cadd":569,"cdel":54,"files":13},{"repo":"mesnada","hash":"6cfe42ca68247c63c8313aa9714cce548f760fd2","ts":1771134758,"wall":"2026-02-15T00:52","msg":"Garrison system: stack units in forts, combined defense, passive healing","body":"- Add garrison dict to GameState (up to 5 units per fort)\n- Add mounted flag to UnitType (cataphract, aquilarii, tracker)\n- Units can move into friendly forts to enter garrison\n- Ungarrison action deploys units to adjacent hex (1 AP)\n- Garrisoned infantry add +10% defense each to field defender\n- Garrison counter-attack: infantry in range deal 25% of attack\n- Killed field defender promotes next garrisoned unit\n- Siege (arbalest/engineer) expels garrison to adjacent hexes\n- Mounted units can enter forts but cannot defend (heal only)\n- All units on fort hex heal 5 HP at end of turn\n- Win condition counts garrisoned units\n- Fix fort sprite loading: fail loud instead of silent empty sprite\n- Frontend: garrison badge on hex, HUD garrison panel with deploy\n- 18 new garrison tests, 161 total passing","parents":["f9cd9302b22523feafe31fac0996d532b2e8bd7a"],"add":827,"del":37,"cadd":827,"cdel":37,"files":21},{"repo":"mesnada","hash":"5ce1b7cbb7ee86cd6b4054713907a77e4749cf32","ts":1771134766,"wall":"2026-02-15T00:52","msg":"Add splash screen with pixel logo before game setup","body":"Logo displays on dark background with pill-shaped START GAME button.\nClicking transitions to existing player/board setup panel with Back button.","parents":["6cfe42ca68247c63c8313aa9714cce548f760fd2"],"add":84,"del":10,"cadd":84,"cdel":10,"files":2},{"repo":"mesnada","hash":"f7342b98d58df8ae5c9cb310381c3e4120bd03c4","ts":1771134872,"wall":"2026-02-15T00:54","msg":"Update handoff for garrison system + splash screen session","body":"","parents":["5ce1b7cbb7ee86cd6b4054713907a77e4749cf32"],"add":50,"del":31,"cadd":50,"cdel":31,"files":1},{"repo":"mesnada","hash":"efcadddf005d1a04bae277e1adde8ffba6c4e8de","ts":1771165156,"wall":"2026-02-15T09:19","msg":"Fix ungarrison bug, multi-turn fort construction, multi-turn siege","body":"- Fix SET_TARGET_ABILITY overwriting \"deploying\" mode to \"targeting\",\n  which prevented ungarrison deploy clicks from registering\n- Fort construction now takes 3 turns with engineer staying on hex;\n  leaving abandons construction; incomplete forts provide no bonuses\n- Siege now does HP damage (arbalest 25/hit, SAP 35/hit) instead of\n  instant destruction; forts have 100 HP\n- Structure model gains hp, max_hp, construction_turns fields\n- Gate garrison entry, defense bonus, and healing on completed forts\n- Gate treasury upgrade on completed fort\n- Add 6 new event types for construction/siege progression\n- Update 167 tests (all passing), TypeScript compiles clean\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["f7342b98d58df8ae5c9cb310381c3e4120bd03c4"],"add":357,"del":49,"cadd":357,"cdel":49,"files":14},{"repo":"mesnada","hash":"11019aec5eb440c741cb845b7eec0b9364a9566a","ts":1771171270,"wall":"2026-02-15T11:01","msg":"Terrain tile textures with hex masking","body":"- Add 6 isometric pixel art terrain tiles (plains, forest, hills,\n  mountain, water, swamp) generated via Ideogram AI\n- Load terrain textures in spriteLoader alongside unit/fort sprites\n- Render terrain sprites masked to hexagonal shape in hexRenderer,\n  with flat color fallback if textures fail to load\n- Tiles need further tweaking: sizing, alignment, and potentially\n  hex-shaped source art for better fit\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["efcadddf005d1a04bae277e1adde8ffba6c4e8de"],"add":59,"del":18,"cadd":59,"cdel":18,"files":8},{"repo":"mesnada","hash":"2806a715a14eb66c5c6834d6713f97e13332ad76","ts":1771171366,"wall":"2026-02-15T11:02","msg":"Update handoff for bugfix + terrain tiles session","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["11019aec5eb440c741cb845b7eec0b9364a9566a"],"add":44,"del":45,"cadd":44,"cdel":45,"files":1},{"repo":"mesnada","hash":"53b5ed07c166faf3a13bbb71a34bb60e4120663a","ts":1771173355,"wall":"2026-02-15T11:35","msg":"Replace terrain textures with seamless Ideogram-generated pixel art","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["2806a715a14eb66c5c6834d6713f97e13332ad76"],"add":0,"del":0,"cadd":0,"cdel":0,"files":6},{"repo":"mesnada","hash":"b4a1fb669fbbaf95b941cc2e105d980592cfbb01","ts":1771175729,"wall":"2026-02-15T12:15","msg":"Individual garrison unit selection and ability use from forts","body":"Garrisoned units can now be selected in the HUD and use their\nabilities from inside a completed fort. Adds get_garrison_abilities()\nas a hook point for future fort-specific ability variants.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["53b5ed07c166faf3a13bbb71a34bb60e4120663a"],"add":410,"del":43,"cadd":410,"cdel":43,"files":9},{"repo":"mesnada","hash":"924112ad02363a9351532450fa5e34c77cb5301a","ts":1771183870,"wall":"2026-02-15T14:31","msg":"Replace all unit sprites with grungy synthwave pixel art, add zoom","body":"- 12 new Ideogram-generated unit sprites (post-apocalyptic synthwave style)\n- Aquilarii sprite added (was missing)\n- HEX_SIZE 48 → 64 for larger tiles\n- Unit sprite size now relative to HEX_SIZE (1.25x)\n- Nearest-neighbor scaling for crisp pixel art\n- Mouse wheel zoom (0.5x–2.0x) centered on cursor\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["b4a1fb669fbbaf95b941cc2e105d980592cfbb01"],"add":39,"del":5,"cadd":39,"cdel":5,"files":15},{"repo":"mesnada","hash":"c84ce7e059889bc471783ef6c19e0e3eef44b1e1","ts":1771183879,"wall":"2026-02-15T14:31","msg":"Add game design research documents","body":"- Fortification mechanics historical research (fort defense, sally, siege)\n- Master design document (combat overhaul, commander, Ház, class system)\n- Commander and army composition research (king kill, deck building, packs)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["924112ad02363a9351532450fa5e34c77cb5301a"],"add":743,"del":0,"cadd":743,"cdel":0,"files":2},{"repo":"mesnada","hash":"41ba64fe1a9e92163ca8a9bca2c5ae85395a4069","ts":1771183904,"wall":"2026-02-15T14:31","msg":"Move misplaced research docs to research/ directory","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["c84ce7e059889bc471783ef6c19e0e3eef44b1e1"],"add":1265,"del":0,"cadd":1265,"cdel":0,"files":2},{"repo":"mesnada","hash":"2f2cc41ad87b3941f62cbd35018f77d094783989","ts":1771184280,"wall":"2026-02-15T14:38","msg":"Update handoff for art, garrison abilities, zoom, and master design session","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["41ba64fe1a9e92163ca8a9bca2c5ae85395a4069"],"add":89,"del":44,"cadd":89,"cdel":44,"files":1},{"repo":"mesnada","hash":"5b46ac3f5e9555a5aa3ce28406ff74c3c8ce195b","ts":1771185612,"wall":"2026-02-15T15:00","msg":"Expand master design: logistics, settlements, ranks, morale, world lore","body":"Adds ammo system, resource mining, runner supply lines, settlement\nraiding vs holding, 8-rank promotion, warband morale, and dying-world\nsetting. Resolves open design decisions for commander and engineer roles.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["2f2cc41ad87b3941f62cbd35018f77d094783989"],"add":182,"del":22,"cadd":182,"cdel":22,"files":1},{"repo":"mesnada","hash":"8ebe02ec2ef583d092bbb93fccf6b32ef2f3d566","ts":1771196977,"wall":"2026-02-15T18:09","msg":"Master design: full worldbuilding, attributes, economy, vehicles, intel warfare","body":"Major expansion of the master design document:\n- Dying earth setting with epistemic collapse, climate shift, plague,\n  infrastructure rot, geopolitical fragmentation\n- Monster ecology: feral drones, escaped bioweapons, mutated wildlife\n- The Others (Vallée hypothesis): perception-manipulating entities\n- 6-attribute system (VIG/AGI/WIT/GRT/APT/CHM)\n- Post-scarcity economy: knowledge as bottleneck, tech tiers, farming\n  modes, fuel production, mobile workshops\n- Pawn + equipment system replacing fixed unit types\n- Settlements with location mode, building slots, dynamic growth\n- Recruitment at Plaza de Armas, bars, nomadic camps, posse rallying\n- Vehicles and nomadic tactics (technicals, war rigs, scout bikes)\n- Environmental hazards (climate zones, disease, soil, aquifers)\n- Intelligence warfare (trust ratings, AI oracles, propaganda, Others)\n- V1 game preserved as in-universe board game\n- Attribute research doc (GURPS, SPECIAL, Battle Brothers, etc.)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5b46ac3f5e9555a5aa3ce28406ff74c3c8ce195b"],"add":985,"del":131,"cadd":985,"cdel":131,"files":2},{"repo":"dying-earth","hash":"d0e998d57f0585f1bf5c923723d078c04aa247c9","ts":1771197845,"wall":"2026-02-15T18:24","msg":"Initialize Dying Earth project with master design and research","body":"Dying Earth is a strategic sandbox set in a post-collapse world.\nSeparated from Mesnada (v1 hex tactics), which lives on as a\nstandalone game and as an in-universe board game within Dying Earth.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":1263,"del":0,"cadd":1263,"cdel":0,"files":2},{"repo":"mesnada","hash":"e919ea998f0d433edaeb984d246add70221f585c","ts":1771198044,"wall":"2026-02-15T18:27","msg":"Move master design and attribute research to Dying Earth project","body":"These docs now live in ~/dying-earth/research/. Mesnada (v1) remains\na standalone hex tactics game. Dying Earth is the strategic sandbox\nthat grew from it.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["8ebe02ec2ef583d092bbb93fccf6b32ef2f3d566"],"add":0,"del":1253,"cadd":0,"cdel":1253,"files":2},{"repo":"mesnada","hash":"ad0f0faf93f14a795b5aa3410ba8bc9da46a654c","ts":1771206257,"wall":"2026-02-15T20:44","msg":"Combat overhaul, JSON units, packs, 8-rank system","body":"Feature 1 (Combat Overhaul #16) - complete:\n- Unit tags with effectiveness multipliers (infantry vs cavalry etc.)\n- Per-class terrain defense and movement cost overrides\n- Range-matching counter-attacks (melee counters melee, ranged counters ranged)\n- Conditional crit bonuses (charge_3, adjacent_ally, high_ground)\n- Frontend CombatPreview shows tag/crit info\n\nFeature 2 (Ház Deck System #18) - backend complete:\n- JSON-driven unit definitions in data/units/ (12 units)\n- Unit loader with validation and auto-registration\n- Pack system with 3 packs (warband, legion, coven)\n- Pure-pack bonus in combat, pack validation on spawn\n\nFeature 3.1 (Commander #17) - ranks only:\n- 8-rank promotion system (Private through General)\n- Smooth stat progression curves across all 8 ranks\n- Updated existing tests for new rank names\n\n42 new tests across 6 test files, 217 total passing.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["e919ea998f0d433edaeb984d246add70221f585c"],"add":1280,"del":164,"cadd":1009,"cdel":164,"files":37},{"repo":"mesnada","hash":"fe4fc0bbbf24131345d4ace046800ffe31f37f66","ts":1771206700,"wall":"2026-02-15T20:51","msg":"Add pack selection UI and units/packs API endpoints","body":"PR 2.3 + 2.4:\n- GET /api/units returns all unit type definitions (JSON-driven)\n- GET /api/packs returns all pack definitions\n- POST /api/game/{id}/select-packs for mid-setup pack changes\n- POST /api/game/new accepts packs per player\n- GameSetup.tsx shows pack selection per human player (1-3 packs)\n- Fix rank display in unitRenderer (8-rank star system)\n- Frontend API client supports packs and units endpoints\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ad0f0faf93f14a795b5aa3410ba8bc9da46a654c"],"add":166,"del":12,"cadd":166,"cdel":12,"files":7},{"repo":"mesnada","hash":"c9441eddb0170ae3c4c803ea75a0fef4f94406ea","ts":1771207295,"wall":"2026-02-15T21:01","msg":"Add commander unit type with stealth budget","body":"PR 3.2 + 3.5 (partial):\n- Commander JSON unit: mid-tier stats, tags [\"infantry\",\"melee\",\"commander\"]\n- One commander per player enforced in spawning\n- Stealth budget: commander spawns hidden with 30 AP budget\n- Budget deducted on movement; revealed when budget hits 0\n- Commander stays hidden during own movement while budget > 0\n- Enemy adjacent bump still reveals commander (existing mechanic)\n- Unit.stealth_ap_remaining field added for budget tracking\n- 6 new tests in test_commander.py, 223 total passing\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["fe4fc0bbbf24131345d4ace046800ffe31f37f66"],"add":175,"del":9,"cadd":150,"cdel":9,"files":9},{"repo":"mesnada","hash":"2281438cecc0112191838bcc3b99cba4871b116c","ts":1771207485,"wall":"2026-02-15T21:04","msg":"Add morale system core — rout, rally, shatter mechanics","body":"PR 3.3:\n- New morale.py: compute_morale(), check_rout(), process_rout(), try_rally()\n- Commander adjacency bonus (+20 morale), ally bonus (+5 per neighbor)\n- Rout threshold at 40 morale, 50% rout chance below threshold\n- Routing units flee to adjacent hex; 3 routs = shatter (permanent death)\n- Rally mechanic: routing units can recover based on morale + base chance\n- Damage reduces morale (0.5 per point), ally death costs nearby units -15\n- Unit dataclass gains morale, rout_count, routing fields\n- Morale cascade constant added for king kill (used in PR 3.4)\n- 7 new event types: ROUT, RALLY, SHATTER, MORALE_CASCADE, etc.\n- 10 new tests in test_morale.py, 233 total passing\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c9441eddb0170ae3c4c803ea75a0fef4f94406ea"],"add":324,"del":0,"cadd":324,"cdel":0,"files":5},{"repo":"mesnada","hash":"7cb04b6d8b0a08ff5d307b9269b3c38068794200","ts":1771207790,"wall":"2026-02-15T21:09","msg":"King Kill cascade, morale in combat, surrender mechanic","body":"PR 3.4 + 3.5:\n- Combat applies morale loss on damage (0.5 per HP lost)\n- Ally death reduces nearby unit morale (-15)\n- Commander death triggers 3-turn morale cascade (all units -10/turn)\n- General-rank unit can claim leadership to halt cascade\n- Surviving damaged units check for rout after combat\n- end_turn() processes: cascade countdown, rally routing units, rout checks\n- Surrender action: removes all player units, marks eliminated\n- morale_cascade dict added to GameState\n- Surrender wired into main.py action dispatch\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["2281438cecc0112191838bcc3b99cba4871b116c"],"add":120,"del":2,"cadd":120,"cdel":2,"files":5},{"repo":"mesnada","hash":"5d6ad6cf2798bc46155c88287b20bdd99490086b","ts":1771208599,"wall":"2026-02-15T21:23","msg":"Add gold economy: territory + treasury income per turn","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["7cb04b6d8b0a08ff5d307b9269b3c38068794200"],"add":157,"del":1,"cadd":157,"cdel":1,"files":4},{"repo":"mesnada","hash":"70ca4a13e960916fc6a0ba10ca890b8012c22e58","ts":1771208859,"wall":"2026-02-15T21:27","msg":"Disable gold income until spending mechanic exists","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["5d6ad6cf2798bc46155c88287b20bdd99490086b"],"add":9,"del":2,"cadd":9,"cdel":2,"files":2},{"repo":"mesnada","hash":"9fb21701b4893a11c9ade245718c7a39ac5ee031","ts":1771209668,"wall":"2026-02-15T21:41","msg":"Disable pack selection UI and spawn restriction","body":"Packs will be a purchasable product, not free in-game selection.\nBackend pack system remains intact but inert when no packs are assigned.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["70ca4a13e960916fc6a0ba10ca890b8012c22e58"],"add":15,"del":62,"cadd":15,"cdel":62,"files":3},{"repo":"mesnada","hash":"5e8cc783e3998fd84d73512b2bee4affadab787c","ts":1771209823,"wall":"2026-02-15T21:43","msg":"Add morale bars, routing indicators, and commander aura to unit rendering","body":"Serialize morale/routing/rout_count in game state API.\nFrontend shows blue morale bar when below 100, dash emoji on routing\nunits, and gold aura ring around commanders.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["9fb21701b4893a11c9ade245718c7a39ac5ee031"],"add":40,"del":0,"cadd":40,"cdel":0,"files":3},{"repo":"mesnada","hash":"1973387a96bd7a884cb5fd51f2aa0c57833a8484","ts":1771210454,"wall":"2026-02-15T21:54","msg":"Commander is starting unit, not spawnable","body":"Each player starts with commander + engineer + tracker instead of\n2 raiders + slinger. Commander cannot be spawned from the roster.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5e8cc783e3998fd84d73512b2bee4affadab787c"],"add":41,"del":48,"cadd":41,"cdel":48,"files":4},{"repo":"mesnada","hash":"949fe8f97e858d1a854345f58af2da771485b50f","ts":1771213464,"wall":"2026-02-15T22:44","msg":"Rework commander stealth: activated ability (30 AP), breaks on move","body":"Commander starts visible on the board. Stealth is now an active ability\ncosting 30 AP that hides the commander. Moving breaks stealth immediately.\nRemoved old stealth budget deduction system.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["1973387a96bd7a884cb5fd51f2aa0c57833a8484"],"add":73,"del":62,"cadd":73,"cdel":62,"files":10},{"repo":"mesnada","hash":"a4eef673088d758911f18ae36c56948e2e86b953","ts":1771213594,"wall":"2026-02-15T22:46","msg":"Add commander sprite","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["949fe8f97e858d1a854345f58af2da771485b50f"],"add":0,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"symbiont.systems","hash":"6432e56d120e2e202d197f9b78fb96b468e60203","ts":1771275772,"wall":"2026-02-16T16:02","msg":"Rewrite institutional copy: agroecosystem design identity","body":"Reposition firm from geospatial consulting to agroecosystem design\nand ecological systems consulting. New service cards, philosophy\nsection, founder biographical copy, and updated credentials.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["86cce94fd126a6898df406a2d843bf49876fb1ef"],"add":239,"del":25,"cadd":239,"cdel":25,"files":2},{"repo":"mesnada","hash":"52eedfd54afab4b2caba1207f891ed6791df34a2","ts":1771307051,"wall":"2026-02-17T00:44","msg":"Add fatigue system, psionic abilities (Terrorize/Mind Sight), fix treasury upgrade","body":"Fatigue system: per-unit action degradation with magical burnout.\n- Units accumulate fatigue per action (move, attack, defend, abilities)\n- Progressive combat penalty: 1 - (fatigue/100)^1.5\n- Movement costs +1 AP/hex above 50 fatigue\n- Magical units (psionic, wyrd) risk burnout above 80 fatigue:\n  1/3 mild (10 HP), 1/3 severe (30 HP), 1/3 instant death\n- Full reset at turn end\n\nPsionic abilities:\n- Terrorize (3 AP): reduce target morale by 30, trigger rout check\n- Mind Sight (2 AP): reveal hidden enemies and fog in 4-hex radius\n\nTreasury fix: allow garrisoned engineers to upgrade completed forts\nto treasuries (was blocked by garrison ability filter).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["a4eef673088d758911f18ae36c56948e2e86b953"],"add":306,"del":16,"cadd":306,"cdel":16,"files":15},{"repo":"publications","hash":"86ce48dc9aee32b39ce70b514240b38c50c1c453","ts":1771372815,"wall":"2026-02-17T19:00","msg":"Initialize publications repo with four paper outlines","body":"Authored by Rowan Valle; Executed by Claude Code","parents":[],"add":467,"del":0,"cadd":411,"cdel":0,"files":16},{"repo":"publications","hash":"8bd7d42f6593cac32c6ce21852768c253cbca77b","ts":1771372996,"wall":"2026-02-17T19:03","msg":"Add session handoff","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["86ce48dc9aee32b39ce70b514240b38c50c1c453"],"add":36,"del":0,"cadd":36,"cdel":0,"files":1},{"repo":"margin","hash":"654b00d8590443eb3880c0bf00760d4d7d25c67c","ts":1771374842,"wall":"2026-02-17T19:34","msg":"feat: Replace external feed discovery with curated local feed list","body":"Remove dependency on awesome-rss-feeds GitHub repo (OPML fetching,\ncaching, browse tier). Replace with our own curated JSON list covering\nUS News, Independent & Alternative, Tech, Science, and Niche categories.\nAll feed data is now local and synchronous — no network requests needed\nfor discovery.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["df460ae405ee746041a1146f9d5cbe5c05fb9130"],"add":349,"del":842,"cadd":156,"cdel":761,"files":8},{"repo":"margin","hash":"d46291865b091041b47d15cfa481303b4db9dfe9","ts":1771374897,"wall":"2026-02-17T19:34","msg":"docs: Update handoff for session 14 (curated feed list)","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["654b00d8590443eb3880c0bf00760d4d7d25c67c"],"add":26,"del":19,"cadd":26,"cdel":19,"files":1},{"repo":"margin","hash":"6e949e394a48467ae55b64f6444d0daff0e07988","ts":1771379094,"wall":"2026-02-17T20:44","msg":"fix: Surface subscribe errors with toast notifications (#12)","body":"The subscribe button in feed discovery silently swallowed all errors,\nmaking it appear broken when the API proxy was down or subscriptions\nfailed. Now shows success/error toasts so the user gets feedback.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d46291865b091041b47d15cfa481303b4db9dfe9"],"add":11,"del":1,"cadd":11,"cdel":1,"files":1},{"repo":"margin","hash":"e91aea469a086bc3dfa6765127869870cda82e90","ts":1771380367,"wall":"2026-02-17T21:06","msg":"fix: Wire up standalone toast + add subscribe loading state (#12)","body":"- ToastProvider now calls setToastFunction so the standalone toast()\n  works outside hooks (was logging \"Toast called before ToastProvider\n  mounted\")\n- Subscribe button shows \"Subscribing...\" with spinner while request\n  is in flight\n- Success/error toasts show after subscribe completes or fails\n\nThe underlying 500 errors are from the API proxy server not running —\nthat's a separate infrastructure issue, not a code bug.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["6e949e394a48467ae55b64f6444d0daff0e07988"],"add":22,"del":3,"cadd":22,"cdel":3,"files":3},{"repo":"margin","hash":"7b8820425ce39fea60eafd21ef6123e7e7487cd4","ts":1771428491,"wall":"2026-02-18T10:28","msg":"docs: Revise master plan — rework Phase 4-8, add granular Phase 4 & 5 plans","body":"Remove Digest & Review (deferred). Promote media handling from Phase 3.6\nto standalone Phase 5. Rework Phase 4 from \"Ticker Evolution\" to \"Feed\nSystem Rework\" with 9 sub-phases (P1 fixes → proxy hardening → scrape-to-feed).\nElevate CRDT Sync to Phase 6. Add ADR-008/009/010 for key decisions.\n\nGranular plans at .claude/plans/margin-phase-{4,5}-*.md (local, gitignored).","parents":["e91aea469a086bc3dfa6765127869870cda82e90"],"add":122,"del":67,"cadd":122,"cdel":67,"files":2},{"repo":"margin","hash":"b476c4e316ae5e6d90fa4ee14351abc9e622d3ce","ts":1771429277,"wall":"2026-02-18T10:41","msg":"feat: Add feed-item support to collections","body":"Extend ManualItem from string[] to { id, entityType } objects with Dexie\nv11 migration. Collections now support bookmark, note, and feed-item\ntypes. Wire entityType through AddItemsModal, AddToCollectionModal,\nresolved items hook, and all collection view components.","parents":["7b8820425ce39fea60eafd21ef6123e7e7487cd4"],"add":262,"del":96,"cadd":256,"cdel":96,"files":27},{"repo":"margin","hash":"99ccade77df3e5b5a53e4af14cf7e085fb83a877","ts":1771429291,"wall":"2026-02-18T10:41","msg":"feat: Widget grid dashboard with drag-and-drop (Phase 3.3c)","body":"Rewrite DashboardPage with react-grid-layout. 10 standalone widgets\n(4 stats, 3 recents, quick capture, tags cloud, favorites). Edit mode\nfor drag/resize/add/remove. Widget picker modal. Layout persisted to\nlocalStorage with IndexedDB backup.","parents":["b476c4e316ae5e6d90fa4ee14351abc9e622d3ce"],"add":1202,"del":262,"cadd":1202,"cdel":262,"files":17},{"repo":"margin","hash":"4e236755c715660f003e2eee43f8609aa7f0cc68","ts":1771429304,"wall":"2026-02-18T10:41","msg":"feat: Reader mode via @mozilla/readability proxy (Phase 3.4)","body":"Add /api/reader endpoint that fetches URLs, parses with Readability,\nand returns clean article content. ReaderView component renders with\nDOMPurify sanitization to prevent XSS. React Query hook with caching.\nLazy-loaded /reader route. Vite dev proxy for API.\n\nPin @mozilla/readability and jsdom versions per dep management rules.\nNote: SSRF protection deferred to Phase 4.3 proxy hardening.","parents":["99ccade77df3e5b5a53e4af14cf7e085fb83a877"],"add":565,"del":2,"cadd":561,"cdel":0,"files":15},{"repo":"margin","hash":"2beb0ce68fddd3060424ee3dde1c9f4fad475e81","ts":1771429314,"wall":"2026-02-18T10:41","msg":"feat: Unified Markdown export + vault ZIP bundle (Phase 3.5)","body":"Add bookmark and feed-item Markdown export with YAML frontmatter.\nVault bundler creates ZIP with bookmarks/, feeds/, notes/, manifest,\nOPML, and settings. VaultExportDialog with selectable export sections.\nIntegrated into DataManagementSection settings page.","parents":["4e236755c715660f003e2eee43f8609aa7f0cc68"],"add":1336,"del":1,"cadd":1336,"cdel":1,"files":10},{"repo":"margin","hash":"fe25180b7002c57bb9a8e876556883afdce20515","ts":1771429381,"wall":"2026-02-18T10:43","msg":"fix: Add refetchOnWindowFocus to feed queries, scope refreshAll (#2, #3)","body":"Enable refetchOnWindowFocus on all feed query hooks for fresh data when\nuser returns to tab. Scope refreshAll mutation to active workspace.","parents":["2beb0ce68fddd3060424ee3dde1c9f4fad475e81"],"add":8,"del":1,"cadd":8,"cdel":1,"files":1},{"repo":"margin","hash":"bcd05fe5258366c53e9fb366cde12dafefcdf2c8","ts":1771430162,"wall":"2026-02-18T10:56","msg":"feat: Wire sidebar position, content width, and collapsed state (Phase 3.3d)","body":"Connect LayoutProvider settings to AppShell: sidebar left/right/off with\nfloating restore trigger, content width constraints, and persisted collapse\nstate. Add settings UI toggles for sidebar position and content width.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["fe25180b7002c57bb9a8e876556883afdce20515"],"add":178,"del":47,"cadd":178,"cdel":47,"files":5},{"repo":"margin","hash":"32716ceeda99e231dff06560c475fccac8686926","ts":1771431243,"wall":"2026-02-18T11:14","msg":"feat: Named layout presets with Cmd+1/2/3 shortcuts (Phase 3.3e)","body":"Add 3 built-in presets (Focus/Research/Reading) and user-created custom\npresets persisted in IndexedDB. Preset switcher in Settings > Layout,\nkeyboard shortcuts for quick switching, save/delete custom presets.","parents":["bcd05fe5258366c53e9fb366cde12dafefcdf2c8"],"add":512,"del":3,"cadd":512,"cdel":3,"files":19},{"repo":"margin","hash":"803663a49e295cc430e3bd0de5496a53ed1e16d0","ts":1771433928,"wall":"2026-02-18T11:58","msg":"feat: Split-view panel system with independent routing (Phase 3.3f)","body":"Add secondary panel that renders routes independently via MemoryRouter,\nenabling side-by-side views (e.g. bookmarks list + note editor). Panel\nicon on card hover actions, \"Open in Panel\" on detail pages, close via\nX button or Escape key. Uses UNSAFE_LocationContext reset to allow\nnested router without conflicting with the browser router.","parents":["32716ceeda99e231dff06560c475fccac8686926"],"add":373,"del":136,"cadd":373,"cdel":136,"files":12},{"repo":"margin","hash":"1a593171fb3e4c5ea118a4e00dca880b5117abed","ts":1771435780,"wall":"2026-02-18T12:29","msg":"feat: Deterministic GUIDs and typed feed errors (Phase 4.1+4.2)","body":"Replace Math.random() GUID fallbacks with FNV-1a hash for deterministic\nitem IDs across re-fetches. Add FeedFetchError class with typed error\ncodes (NETWORK, PARSE, TIMEOUT, NOT_FOUND, FORBIDDEN, SERVER_ERROR) and\nstructured lastError storage. Remove silent console.warn swallowing.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["803663a49e295cc430e3bd0de5496a53ed1e16d0"],"add":193,"del":19,"cadd":193,"cdel":19,"files":8},{"repo":"margin","hash":"cb06a8ae40c5e75e3ccae00e95a3f0cfbe0088ad","ts":1771436841,"wall":"2026-02-18T12:47","msg":"feat: SSRF protection and rate limiting for feed proxy (Phase 4.3)","body":"Add SSRF guard rejecting private/loopback/link-local IPs and non-http(s)\nprotocols with async DNS resolution to catch rebinding. Add in-memory\nsliding window rate limiter (60 req/min per IP). Applied to both feed\nproxy and reader routes.","parents":["1a593171fb3e4c5ea118a4e00dca880b5117abed"],"add":514,"del":23,"cadd":510,"cdel":21,"files":9},{"repo":"groundwork","hash":"45560cdaf80dfeddcb38144765d9f738a29337ea","ts":1771439415,"wall":"2026-02-18T13:30","msg":"Add typed contracts for module returns, convert soils module first","body":"Introduces groundwork/contracts.py with AcquireResult base and SoilsResult\ndataclass. Soils fetch() now returns SoilsResult instead of raw dict.\nPipeline ModuleResult.result widened to Any for incremental migration.\nJSON cache format unchanged via .to_dict(). mypy --strict passes.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["15575c5a110ddbaa5077898eb6c29e0ae9e5aba3"],"add":218,"del":20,"cadd":218,"cdel":20,"files":4},{"repo":"groundwork","hash":"0ee36db2bfce53e8a92c3afb6a0499e7dd8a4b1b","ts":1771439640,"wall":"2026-02-18T13:34","msg":"Update rebuild plan with Phase 6 architecture cleanup tracking","body":"Adds Phase 6 section covering typed contracts (per-module), config\ndecomposition, registry protocols, async acquire, output decomposition,\npipeline separation, and R companion package. Soils contract marked complete.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["45560cdaf80dfeddcb38144765d9f738a29337ea"],"add":44,"del":1,"cadd":44,"cdel":1,"files":1},{"repo":"groundwork","hash":"32889410ab9f8045c9bbf16c061f03ed93b434d9","ts":1771439705,"wall":"2026-02-18T13:35","msg":"Add missing analyze module contracts to Phase 6 tracking","body":"Was missing terrain, hydrology, suitability, and wetland_probability.\nTotal: 19 modules (15 acquire + 4 analyze), 18 remaining after soils.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["0ee36db2bfce53e8a92c3afb6a0499e7dd8a4b1b"],"add":4,"del":0,"cadd":4,"cdel":0,"files":1},{"repo":"margin","hash":"48b88e48dd31b51ab8c016dadfa380e018c59ea0","ts":1771439767,"wall":"2026-02-18T13:36","msg":"feat: Enhanced feed auto-discovery with multi-strategy detection (Phase 4.4)","body":"Add link-tag, JSON-LD, common-path probing, and anchor heuristic strategies\nwith confidence scoring and dedup. Add server-side /api/feeds/discover endpoint.","parents":["cb06a8ae40c5e75e3ccae00e95a3f0cfbe0088ad"],"add":589,"del":36,"cadd":588,"cdel":36,"files":7},{"repo":"groundwork","hash":"1823e1094e1446d95395fc2f5578d58e2e0f0498","ts":1771439998,"wall":"2026-02-18T13:39","msg":"Update session handoff for Phase 6 typed contracts work","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["32889410ab9f8045c9bbf16c061f03ed93b434d9"],"add":59,"del":33,"cadd":59,"cdel":33,"files":1},{"repo":"margin","hash":"0ff6f5f51bea8cff85aa6e30cad83d3a6c37fd8c","ts":1771440176,"wall":"2026-02-18T13:42","msg":"docs: Update CLAUDE.md current state for Phase 3 completion and Phase 4","body":"","parents":["48b88e48dd31b51ab8c016dadfa380e018c59ea0"],"add":36,"del":51,"cadd":36,"cdel":51,"files":2},{"repo":"margin","hash":"321ae4f5b81e8ec0d970be9bd9ae996eb2ff874a","ts":1771448588,"wall":"2026-02-18T16:03","msg":"feat: CSS selector scrape-to-feed engine (Phase 4.5)","body":"Add server-side scrape engine that accepts a URL + CSS selectors, fetches\nthe page, extracts repeating items, and returns a feed in RSS/Atom/JSON\nformat. Includes SSRF protection, preview endpoint, and ScrapedFeedConfig\npersistence layer.","parents":["0ff6f5f51bea8cff85aa6e30cad83d3a6c37fd8c"],"add":806,"del":0,"cadd":802,"cdel":0,"files":13},{"repo":"margin","hash":"c9338cc356f83b5d89fc87eb9f0112d68233139a","ts":1771452959,"wall":"2026-02-18T17:15","msg":"feat: Scrape feed UI page with preview and save (Phase 4.6)","body":"Add /feeds/scrape/new route where users enter a URL, define CSS\nselectors, preview extracted items, and save the config to IndexedDB.\n\n- useScrapePreview hook (POST /api/feeds/scrape/preview)\n- useSaveScrapedFeedConfig mutation (Dexie storage)\n- Two-column layout: selector form + live preview panel\n- scrapeKeys query key factory\n- Nav link from FeedsPage header\n- 5 tests: form rendering, button states, preview display","parents":["321ae4f5b81e8ec0d970be9bd9ae996eb2ff874a"],"add":547,"del":1,"cadd":547,"cdel":1,"files":7},{"repo":"margin","hash":"cc472055cb1f0a8c2aaa7640b1454d089c7e3ca6","ts":1771453135,"wall":"2026-02-18T17:18","msg":"docs: Update master plan and CLAUDE.md for Phase 4.5+4.6 completion","body":"","parents":["c9338cc356f83b5d89fc87eb9f0112d68233139a"],"add":46,"del":27,"cadd":46,"cdel":27,"files":3},{"repo":"margin","hash":"75b6267d5d358d795bc965eff05af779ec6b2c2c","ts":1771454975,"wall":"2026-02-18T17:49","msg":"feat: Hash-based page change detection (Phase 4.7)","body":"Monitor arbitrary web pages for content changes via SHA-256 hashing.\nWhen a watched page changes, a synthetic feed item is generated.\nFull stack: WatchedPage type, Dexie v14 schema, repository, API\nendpoints (preview + check with SSRF protection), service integration,\nReact Query hooks, and scrape page UI with \"Watch for changes\" toggle.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["cc472055cb1f0a8c2aaa7640b1454d089c7e3ca6"],"add":1021,"del":120,"cadd":1021,"cdel":120,"files":17},{"repo":"margin","hash":"8abadbee489ee4aa686c138b4ee0d274505b3c3e","ts":1771455068,"wall":"2026-02-18T17:51","msg":"docs: Update master plan and CLAUDE.md for Phase 4.7 completion","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["75b6267d5d358d795bc965eff05af779ec6b2c2c"],"add":7,"del":7,"cadd":7,"cdel":7,"files":2},{"repo":"margin","hash":"907573f37e52b93373de992cb3a38684744e0663","ts":1771459826,"wall":"2026-02-18T19:10","msg":"feat: Ticker stabilization + polling etiquette (Phase 4.8+4.9)","body":"4.8: Delete legacy TickerTape.tsx, namespace localStorage keys to\nmargin-ticker-settings with migration, manage ticker visibility in\nTickerProvider context instead of local component state.\n\n4.9: Conditional requests (ETag/If-Modified-Since) through API proxy,\n304 Not Modified handling in feed service, smart feed scheduler with\nexponential backoff/jitter/batch limiting/visibility awareness, per-feed\nrefresh interval editing UI, remove blind 30s refetch on unread items.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["8abadbee489ee4aa686c138b4ee0d274505b3c3e"],"add":295,"del":294,"cadd":295,"cdel":294,"files":17},{"repo":"margin","hash":"fa453d5db7a134bf3306ccef2c3dd5077927e823","ts":1771459836,"wall":"2026-02-18T19:10","msg":"docs: Update master plan for Phase 4 completion + Tauri roadmap","body":"Mark Phase 4.8+4.9 done. Add Tauri desktop phases (5-T through 8-T):\nshell, visual CSS picker, smart auto-detection, Rust migration. Add\nuniversal Block type as future phase. Record Tauri v2 over Electron\ndecision.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["907573f37e52b93373de992cb3a38684744e0663"],"add":68,"del":7,"cadd":68,"cdel":7,"files":2},{"repo":"margin","hash":"cba76fadfa6c81d3603aa1301bab2e0a9177909e","ts":1771461238,"wall":"2026-02-18T19:33","msg":"docs: Add DnD layout overhaul to master plan roadmap","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["fa453d5db7a134bf3306ccef2c3dd5077927e823"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"margin","hash":"eb1217f1351d6f74bd89c7be98d3d47c644a51b0","ts":1771461985,"wall":"2026-02-18T19:46","msg":"docs: Reorganize master plan into priority-based tracks","body":"Six tracks ordered by shipping impact: Polish → Scraper UX → Native\nDesktop → New Capabilities → Multiplayer → Growth. Pulls auto-detect\n(7-T) out of Tauri dependency chain for earlier delivery.","parents":["cba76fadfa6c81d3603aa1301bab2e0a9177909e"],"add":182,"del":99,"cadd":182,"cdel":99,"files":1},{"repo":"margin","hash":"fe9b0b9911bbf180f0a1d8d5ee22c55e66ea1694","ts":1771462869,"wall":"2026-02-18T20:01","msg":"docs: Restructure master plan from tracks to milestones","body":"Replace theme-based tracks with milestone-based roadmap where each\nmilestone is independently shippable. Key changes:\n- Split \"Polish\" track into M1 (sidebar + CSS) and M2 (filtering)\n- Merge 7-T auto-detect with ScrapeFeedPage UX reflow as M3\n- Add MVP cutline after M4 (desktop app)\n- Split CRDT into M6 (research only) and M7 (implementation)\n- Move Universal Block to M6 design + conditional M7 implementation","parents":["eb1217f1351d6f74bd89c7be98d3d47c644a51b0"],"add":146,"del":85,"cadd":146,"cdel":85,"files":1},{"repo":"margin","hash":"6e8b16b556ff2c322f2b4dd28e34414c012861b8","ts":1771466102,"wall":"2026-02-18T20:55","msg":"feat: DnD sidebar reorder/hide + P3 fixes (M1 DnD-A)","body":"Sidebar nav items can be drag-reordered and hidden via customize mode.\nPersists to localStorage through LayoutProvider. Also fixes stale closure\nbug in all LayoutProvider setters, adds jsdom config for apps/web tests,\nand installs react-grid-layout 2.2.2 to resolve DashboardPage type errors.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["fe9b0b9911bbf180f0a1d8d5ee22c55e66ea1694"],"add":596,"del":31,"cadd":595,"cdel":31,"files":9},{"repo":"margin","hash":"aaa0ac2e523a52418051245423cd17feaf17304e","ts":1771466187,"wall":"2026-02-18T20:56","msg":"docs: Update handoff for session 19 (M1 DnD-A)","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["6e8b16b556ff2c322f2b4dd28e34414c012861b8"],"add":53,"del":38,"cadd":53,"cdel":38,"files":1},{"repo":"margin","hash":"550cd66d6db4b5550d74c32e528c5a164e125c79","ts":1771467662,"wall":"2026-02-18T21:21","msg":"docs: Final handoff for session 19","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["aaa0ac2e523a52418051245423cd17feaf17304e"],"add":37,"del":8,"cadd":37,"cdel":8,"files":1},{"repo":"azura-terraforming","hash":"838063bf99b84576fc0dcf95286cf4a7362543f8","ts":1771470177,"wall":"2026-02-18T22:02","msg":"Initial commit: Azura terraforming research and site analysis","body":"All research documents, GIS analysis outputs, legal research,\nand supporting data for the Azura cold desert terraforming project.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":274322,"del":0,"cadd":7451,"cdel":0,"files":87},{"repo":"margin","hash":"f9866e5a71be0a22ec1c9b5b547111d0890c2504","ts":1771473365,"wall":"2026-02-18T22:56","msg":"fix: inject active workspace ID when creating collections","body":"Collections created in a non-default workspace were always assigned to\nthe default workspace because useCreateCollection didn't pass the\nactive workspace context to the service layer.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["550cd66d6db4b5550d74c32e528c5a164e125c79"],"add":6,"del":1,"cadd":6,"cdel":1,"files":1},{"repo":"margin","hash":"7679ed323ea15425c56e16fe8264532327435505","ts":1771491733,"wall":"2026-02-19T04:02","msg":"feat: Notion-style full-width note editor, remove global focus ring","body":"Widen note editor to fill available content area with generous\nresponsive padding, remove bordered editor box, increase prose size.\nRemove global :focus-visible ring from tokens.css — components with\ninline focus-visible classes retain their own rings.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["f9866e5a71be0a22ec1c9b5b547111d0890c2504"],"add":7,"del":9,"cadd":7,"cdel":9,"files":2},{"repo":"margin","hash":"29a788be5c52629878ba6767d613c42f0862c807","ts":1771517786,"wall":"2026-02-19T11:16","msg":"feat: SimpleFilterBar component + integrate into entity list pages (M1 DnD-B)","body":"Reusable search + sort bar replaces per-page SearchInput on Bookmarks,\nNotes, and Collections pages. Adds client-side sorting to Bookmarks and\nCollections (Notes already had it). Fixes 3 stale Sidebar collapse tests.","parents":["7679ed323ea15425c56e16fe8264532327435505"],"add":344,"del":65,"cadd":344,"cdel":65,"files":7},{"repo":"margin","hash":"1c90991b6ac3bcfd3d8aa1f058c4ec69bf23a94c","ts":1771518176,"wall":"2026-02-19T11:22","msg":"feat: tag chip filtering on Bookmarks and Notes pages","body":"Add getTagMapByEntityType to TagAssignmentRepository for bulk entity→tags\nlookup. New useTagMap hook provides the data to SimpleFilterBar. Bookmarks\nand Notes pages now show tag chips and filter by selected tags.","parents":["29a788be5c52629878ba6767d613c42f0862c807"],"add":66,"del":2,"cadd":66,"cdel":2,"files":6},{"repo":"margin","hash":"b9a77c0e11987987e05cf136dd2b1573c59b5404","ts":1771519228,"wall":"2026-02-19T11:40","msg":"fix: puma logo squish on collapsed sidebar, card action icon overflow","body":"- Puma: remove w-full from collapsed container, add shrink-0, reduce padding\n- NoteCard + BookmarkCard: flex-wrap + tighter padding on action icons\n- MASTER-PLAN: mark M1 DnD-A/P3 and M2 DnD-B+D as done","parents":["1c90991b6ac3bcfd3d8aa1f058c4ec69bf23a94c"],"add":50,"del":33,"cadd":50,"cdel":33,"files":4},{"repo":"margin","hash":"7bb39499c3542338a9ff6cec6f3b8706b1994bcf","ts":1771519447,"wall":"2026-02-19T11:44","msg":"docs: session 20 handoff — M1/M2 complete","body":"","parents":["b9a77c0e11987987e05cf136dd2b1573c59b5404"],"add":56,"del":62,"cadd":56,"cdel":62,"files":1},{"repo":"margin","hash":"8270711af32e443aa9324ab76b1df0ea793c1533","ts":1771521421,"wall":"2026-02-19T12:17","msg":"feat: responsive card grids, multi-panel support, independent scroll","body":"- Replace viewport breakpoints with auto-fill/minmax() on all card grids\n  so columns adapt to actual container width (not viewport)\n- Add shrink-0 to all card action buttons and header icons to prevent\n  icon compression; add min-w-0 for proper text truncation\n- Multi-panel support: PanelContext holds array of paths, panels stack\n  vertically with independent close buttons\n- Independent scroll per SplitPane side: main switches to overflow-hidden\n  when panels open, each pane scrolls independently\n- Sticky page headers on NoteViewerPage and BookmarkDetailPage with\n  backdrop blur\n- Clean panel header: removed UUID path display, just close button\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["7bb39499c3542338a9ff6cec6f3b8706b1994bcf"],"add":72,"del":55,"cadd":72,"cdel":55,"files":12},{"repo":"margin","hash":"23abc20c6317d01479002a886dfeca7371de35f6","ts":1771521500,"wall":"2026-02-19T12:18","msg":"feat: emoji picker for workspaces, sidebar rework, CORS config","body":"- Add EmojiPicker component using @emoji-mart for workspace icons\n- Rework sidebar collapse button: export for manual placement, inline\n  styling instead of absolute positioning\n- Fix workspace icon sizing with flex container\n- Make CORS origin configurable via CORS_ORIGIN env var\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["8270711af32e443aa9324ab76b1df0ea793c1533"],"add":120,"del":25,"cadd":118,"cdel":25,"files":10},{"repo":"margin","hash":"d70bdd424ff5d6cafffcc5fef9583116d6a19e23","ts":1771523241,"wall":"2026-02-19T12:47","msg":"fix: bookmark button visual feedback, unarchive bookmarks","body":"Feed bookmark button now reacts immediately via optimistic update and\nproper cache invalidation. Bookmark archive toggle now correctly\nunarchives when item is already archived.","parents":["23abc20c6317d01479002a886dfeca7371de35f6"],"add":35,"del":3,"cadd":35,"cdel":3,"files":2},{"repo":"margin","hash":"24225435d903bc20c6d672c5019919b77198299a","ts":1771525114,"wall":"2026-02-19T13:18","msg":"feat: M3 scraper auto-detect heuristics + URL-first UX","body":"Server-side heuristic engine detects repeating content patterns on\nweb pages (article, .post, .card, ul>li, etc.), probes for title/link/\ndate/summary/image sub-selectors, and returns confidence-scored\ncandidates. ScrapeFeedPage reflows to URL-first cascade: paste URL →\nRSS discovery → auto-detect → manual fallback.\n\nKnown issues tracked in #1:\n- Nav/chrome elements not filtered (false positives on nav-heavy sites)\n- Scrape config save doesn't auto-subscribe as feed\n- Link selector bug: \"a a[href]\" when title selector is already \"a\"\n- Placeholder text on optional fields looks like real values","parents":["d70bdd424ff5d6cafffcc5fef9583116d6a19e23"],"add":945,"del":29,"cadd":945,"cdel":29,"files":6},{"repo":"margin","hash":"6117dfcabeed300df8cfbc7c74171add75ee3d61","ts":1771525198,"wall":"2026-02-19T13:19","msg":"docs: session 21 handoff — feed UX fixes + M3 auto-detect","body":"","parents":["24225435d903bc20c6d672c5019919b77198299a"],"add":41,"del":57,"cadd":41,"cdel":57,"files":1},{"repo":"margin","hash":"da156d776c5c279e7e2b2d0e96741a4a7cb0a289","ts":1771527482,"wall":"2026-02-19T13:58","msg":"fix: M3 follow-up — nav filtering, save→subscribe, link bug, JS-detect, disable web scraper","body":"- Filter nav/header/footer/chrome from auto-detect candidates (#19.1)\n- Wire scrape config save to create Feed record in sidebar (#19.2)\n- Fix a a[href] link selector when title is anchor tag (#19.3)\n- Clear optional field placeholders during auto-detect (#19.4)\n- Detect JS-rendered SPA shells, show desktop-app upsell\n- Comment out scrape route/button from web app (Tauri-only feature)\n- RSS/Atom/JSON discovery remains fully available in web app\n- 12 tests for heuristic engine + JS detection (1,554 total passing)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["6117dfcabeed300df8cfbc7c74171add75ee3d61"],"add":295,"del":29,"cadd":295,"cdel":29,"files":7},{"repo":"margin","hash":"40aea48a5089339403efc4b5ebe3f6a0ee3a84dd","ts":1771530583,"wall":"2026-02-19T14:49","msg":"docs: desktop development setup guide","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["da156d776c5c279e7e2b2d0e96741a4a7cb0a289"],"add":115,"del":35,"cadd":115,"cdel":35,"files":2},{"repo":"margin","hash":"7b19733fcdbb9479adbd150e76a3c8732b17e2d8","ts":1771530600,"wall":"2026-02-19T14:50","msg":"feat: add isTauri() runtime detection utility to @margin/core","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["40aea48a5089339403efc4b5ebe3f6a0ee3a84dd"],"add":50,"del":0,"cadd":50,"cdel":0,"files":3},{"repo":"margin","hash":"2c3e96677ec59df53925190dbbca796c8a16824c","ts":1771530613,"wall":"2026-02-19T14:50","msg":"feat: disable PWA service worker in Tauri builds","body":"BUILD_TARGET=tauri gates the VitePWA plugin. Web PWA unaffected.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["7b19733fcdbb9479adbd150e76a3c8732b17e2d8"],"add":4,"del":2,"cadd":3,"cdel":2,"files":2},{"repo":"margin","hash":"61bb64da84de40b6a975f19fcac9c826030354b6","ts":1771531509,"wall":"2026-02-19T15:05","msg":"feat: initialize Tauri v2 workspace with Rust commands","body":"Adds apps/desktop/ with Tauri v2 config, Rust command stubs for\nfeed proxy, scraper, reader, and watch. No sidecar — desktop uses\nRust commands directly via invoke() bridge.\n\nNot yet compiling — needs cargo in PATH for pnpm install.\nNext session: fix PATH, verify cargo build, wire hooks.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["2c3e96677ec59df53925190dbbca796c8a16824c"],"add":909,"del":0,"cadd":842,"cdel":0,"files":13},{"repo":"margin","hash":"86cb57edc0c862f9ccd4ce0cb439e8be3a93484d","ts":1771538501,"wall":"2026-02-19T17:01","msg":"fix: tauri-build version and placeholder icons for Rust compilation","body":"tauri-build 2.10 doesn't exist (hallucinated); pinned to 2.5.\nGenerated placeholder icon set so tauri::generate_context!() succeeds.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["61bb64da84de40b6a975f19fcac9c826030354b6"],"add":9997,"del":1,"cadd":1,"cdel":1,"files":58},{"repo":"margin","hash":"684e6781f750f6849f71493048559c2573d7cfa1","ts":1771538554,"wall":"2026-02-19T17:02","msg":"feat: transport abstraction for web/Tauri — ScrapeService + ReaderService","body":"NetworkTransport interface with web (fetch) and Tauri (invoke) implementations.\nHooks now call services instead of raw fetch(), matching the existing service\nlayer pattern. Transport is selected once at app startup via isTauri().\n\n- ScrapeService: discoverFeeds, scrapePreview, autoDetectScrape, watchPreview, saveConfig\n- ReaderService: readArticle\n- Shared types (ScrapePreviewResult, AutoDetectResult, ReaderArticle) in @margin/core\n- serde(rename_all = \"camelCase\") on all Rust command structs\n- 6 new tests (1,563 total)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["86cb57edc0c862f9ccd4ce0cb439e8be3a93484d"],"add":684,"del":195,"cadd":684,"cdel":195,"files":23},{"repo":"margin","hash":"6c15eac3d00029b3f88071cbb7c3ac7a736239a1","ts":1771542855,"wall":"2026-02-19T18:14","msg":"feat: browser tabs with webview lifecycle, navigation, PKM actions, and CSS picker","body":"Adds a full tabbed browser to the Tauri desktop app: tab bar, address bar\nwith back/forward/reload, keyboard shortcuts (Ctrl+T/W/L, Ctrl+Tab),\nPKM integration (save bookmark, read article, scrape page, copy URL),\nand a visual CSS selector picker overlay for scrape feed configuration.","parents":["684e6781f750f6849f71493048559c2573d7cfa1"],"add":1382,"del":9,"cadd":1373,"cdel":7,"files":15},{"repo":"margin","hash":"77332cd0225015d4acee763399bfa9ea88dd99e2","ts":1771542861,"wall":"2026-02-19T18:14","msg":"chore: replace placeholder icons with puma logo","body":"","parents":["6c15eac3d00029b3f88071cbb7c3ac7a736239a1"],"add":0,"del":0,"cadd":0,"cdel":0,"files":17},{"repo":"margin","hash":"135fa7544500615607d539cb5621c8e9dd98a60f","ts":1771543159,"wall":"2026-02-19T18:19","msg":"fix: always show tab bar in Tauri mode and start window maximized","body":"Tab bar and keyboard shortcuts were gated on hasTabs, so users had no\nway to create the first browser tab. Now the tab bar with its \"+\" button\nrenders whenever isTauri() is true, and the window opens maximized.","parents":["77332cd0225015d4acee763399bfa9ea88dd99e2"],"add":6,"del":7,"cadd":4,"cdel":7,"files":3},{"repo":"margin","hash":"eaf967d52f5af623bfa04eb27ea071d43d35432f","ts":1771548212,"wall":"2026-02-19T19:43","msg":"fix: browser tab webview positioning on Linux/GTK","body":"- Patch tao + tauri-runtime-wry to use gtk::Fixed instead of gtk::Box\n  for child webview positioning (tauri-apps/tauri#10420)\n- Fix Rust API: get_webview() instead of get_webview_window() for\n  child webviews created via JS Webview API\n- Add browser_hide_all and browser_cleanup Rust commands\n- Add tauri-plugin-global-shortcut with Ctrl+Shift+M escape hotkey\n- Startup cleanup of stale webviews from crashed sessions\n- Focus management: return focus to main webview after hiding tabs\n- Bounds safety: null checks, 1px inset, deferred measurement\n\nWebview now positions in content area instead of stacking vertically.\nBounds fine-tuning still needed — see issue.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["135fa7544500615607d539cb5621c8e9dd98a60f"],"add":50853,"del":74,"cadd":42868,"cdel":67,"files":152},{"repo":"margin","hash":"12f92028c3ab3206a25aaf56edcf0ddfe781ba3f","ts":1771548330,"wall":"2026-02-19T19:45","msg":"docs: update handoff for session 25 — browser tab GTK fix","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["eaf967d52f5af623bfa04eb27ea071d43d35432f"],"add":48,"del":51,"cadd":48,"cdel":51,"files":1},{"repo":"margin","hash":"076c819b9278abb27440676df6a5c880b0699c13","ts":1771554016,"wall":"2026-02-19T21:20","msg":"feat: replace multiwebview overlays with iframe + window fallback","body":"Multiwebview overlays are native OS-level elements that don't participate\nin DOM layout, requiring fragile manual position syncing. Replace with:\n- iframes for frameable sites (DOM-native, no positioning math)\n- separate OS windows for sites that block embedding (X-Frame-Options)\n\nAdd browser_check_frameable Rust command (HEAD request, header inspection).\nAdd .desktop launcher file for Linux app menu integration.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["12f92028c3ab3206a25aaf56edcf0ddfe781ba3f"],"add":406,"del":269,"cadd":393,"cdel":263,"files":8},{"repo":"margin","hash":"ab762a80245c570e8748c2e0980bc845d44cfb65","ts":1771554158,"wall":"2026-02-19T21:22","msg":"docs: update handoff for session 26 — iframe + window fallback","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["076c819b9278abb27440676df6a5c880b0699c13"],"add":56,"del":46,"cadd":56,"cdel":46,"files":1},{"repo":"margin","hash":"db7b7265f16ad28da84290598b263017d48b13ff","ts":1771606313,"wall":"2026-02-20T11:51","msg":"refactor: gut browser shell from Tauri, pivot to extension-based capture","body":"Tauri is not a browser — it wraps the OS native webview, causing\ncross-platform inconsistencies when loading arbitrary external content.\nRemoved the entire browser shell (tabs, iframe/window fallback, visual\nCSS picker, multiwebview overlays, GTK patches). The browser extension\nhandles web capture instead. Electron \"Bloomberg terminal\" edition\nparked for post-revenue.\n\nUpdated roadmap: relay-only sync architecture (no user data storage),\nCRDT research promoted, M4 redefined as lightweight Tauri + extension.\n\nDeleted: 9 source files, ~1500 LOC app code, ~50K LOC vendored patches\nTests: 1563 passing, typecheck clean, cargo check clean","parents":["ab762a80245c570e8748c2e0980bc845d44cfb65"],"add":107,"del":52378,"cadd":99,"cdel":44388,"files":165},{"repo":"margin","hash":"6261617a1286c5d518979376f08fa7113b29ba38","ts":1771606763,"wall":"2026-02-20T11:59","msg":"feat: complete M4 — add dev:desktop and build:desktop scripts","body":"Express sidecar killed (Rust commands already cover all routes).\nPlatform behavior (SW gating, transport switching) already implemented.\nRoot convenience scripts added: pnpm dev:desktop / build:desktop.\n\nM4 \"Desktop app exists\" is now complete.","parents":["db7b7265f16ad28da84290598b263017d48b13ff"],"add":13,"del":9,"cadd":11,"cdel":9,"files":3},{"repo":"margin","hash":"ce6c08426545b9cace0cff6ed59ce794933a3ee8","ts":1771613790,"wall":"2026-02-20T13:56","msg":"feat: security hardening — SSRF, timeouts, error sanitization, CSP","body":"Add SSRF validation (security.rs) and shared HTTP client (http_client.rs)\nwith 15s timeout, 5s connect timeout, and 10MB size limit. All Tauri\ncommands now validate URLs against private IPs and DNS rebinding before\nfetching. User-provided CSS selectors validated for length and depth.\nError messages sanitized to prevent internal detail leakage. CSP\ntightened in tauri.conf.json and added to web index.html.","parents":["6261617a1286c5d518979376f08fa7113b29ba38"],"add":293,"del":59,"cadd":292,"cdel":58,"files":8},{"repo":"margin","hash":"d5a0f28be9a86dc7d912d39e5db99966f820d8ff","ts":1771613812,"wall":"2026-02-20T13:56","msg":"fix: wire feed fetching through Tauri transport layer","body":"Add fetchFeedRaw to NetworkTransport interface so feed subscription\nworks in Tauri mode without Express sidecar. Tauri transport invokes\nRust fetch_feed_raw command directly.","parents":["ce6c08426545b9cace0cff6ed59ce794933a3ee8"],"add":114,"del":6,"cadd":114,"cdel":6,"files":5},{"repo":"margin","hash":"48709231d617e7e8e45764ffcda1d1fbc5301177","ts":1771613864,"wall":"2026-02-20T13:57","msg":"docs: update handoff for session 28 — security hardening","body":"","parents":["d5a0f28be9a86dc7d912d39e5db99966f820d8ff"],"add":174,"del":54,"cadd":174,"cdel":54,"files":2},{"repo":"margin","hash":"d121ce878d128afbe3f4f56488edd4cc865133fa","ts":1771619567,"wall":"2026-02-20T15:32","msg":"feat: auto-discover feeds when subscribing with a website URL","body":"When subscribe() receives HTML instead of a feed, it now:\n1. Scans HTML for <link rel=\"alternate\"> tags and anchor heuristics\n2. Falls back to probing common paths (/feed, /rss, /atom.xml, etc.)\n3. Subscribes to the first valid feed found\n\nThis lets users paste any website URL and get the right feed.","parents":["48709231d617e7e8e45764ffcda1d1fbc5301177"],"add":43,"del":5,"cadd":43,"cdel":5,"files":1},{"repo":"margin","hash":"fa348e7a7e9700f1d0ad57d5dd1cb7f6bef2407a","ts":1771620316,"wall":"2026-02-20T15:45","msg":"docs: update handoff — feed auto-discovery, build notes, extension status","body":"","parents":["d121ce878d128afbe3f4f56488edd4cc865133fa"],"add":50,"del":18,"cadd":50,"cdel":18,"files":1},{"repo":"margin","hash":"cb11b4163c89b454985b754bf2736bbceb6fe48f","ts":1771627671,"wall":"2026-02-20T17:47","msg":"chore: default build scripts to Tauri, archive PWA escape hatches","body":"Default `dev` and `build` to Tauri target. Add `dev:pwa` and `build:pwa`\nas backward-compatible escape hatches for web-only deployment.","parents":["fa348e7a7e9700f1d0ad57d5dd1cb7f6bef2407a"],"add":5,"del":4,"cadd":0,"cdel":0,"files":2},{"repo":"margin","hash":"679bc7e687b74c26efb0797c4a3a3728996767a1","ts":1771627683,"wall":"2026-02-20T17:48","msg":"chore: add deprecation comments to PWA path (remove May 2026)","body":"Mark VitePWA config, Express API server, and web transport as deprecated.\nTauri desktop with Rust commands is the primary path.","parents":["cb11b4163c89b454985b754bf2736bbceb6fe48f"],"add":8,"del":0,"cadd":8,"cdel":0,"files":3},{"repo":"margin","hash":"b57cc3314afe8b3286311d6908b2f87f8ac9dadc","ts":1771627707,"wall":"2026-02-20T17:48","msg":"docs: log PWA archive debt, update master plan and project context","body":"TD-35 (PWA removal, May 2026) and TD-36 (capture server shared-secret).\nMark 5-T.5/5-T.6/5-T.7 as done in master plan.","parents":["679bc7e687b74c26efb0797c4a3a3728996767a1"],"add":36,"del":7,"cadd":36,"cdel":7,"files":3},{"repo":"margin","hash":"e121a8987aad5a2c6d496aead87a1018a7d22138","ts":1771627718,"wall":"2026-02-20T17:48","msg":"feat: add capture HTTP server for extension→Tauri communication","body":"axum server at 127.0.0.1:18947 with GET /health and POST /capture.\nOrigin validation (chrome-extension:// only), CORS via tower-http,\nTauri event emission on capture. Spawned as tokio background task.","parents":["b57cc3314afe8b3286311d6908b2f87f8ac9dadc"],"add":239,"del":0,"cadd":159,"cdel":0,"files":4},{"repo":"margin","hash":"7e00f9c55762a383ecda0df74528271eef9e66bf","ts":1771627725,"wall":"2026-02-20T17:48","msg":"feat: frontend hook to receive captures from Tauri HTTP server","body":"useTauriCapture listens for capture:received Tauri events and processes\nthem through the existing bookmark capture pipeline. Mounted in AppShell\nwhen running inside Tauri; useExtensionCapture remains for web/PWA.","parents":["e121a8987aad5a2c6d496aead87a1018a7d22138"],"add":101,"del":1,"cadd":101,"cdel":1,"files":2},{"repo":"margin","hash":"9d635871ea9acee970cb6361c7dd6b3f1a356577","ts":1771627736,"wall":"2026-02-20T17:48","msg":"feat: extension POSTs captures to Tauri, falls back to queue","body":"Service worker tries HTTP POST to 127.0.0.1:18947/capture first.\nOn success, capture is delivered directly to the desktop app.\nOn failure (Tauri not running), falls back to chrome.storage.local\nqueue for PWA pickup.","parents":["7e00f9c55762a383ecda0df74528271eef9e66bf"],"add":17,"del":3,"cadd":17,"cdel":3,"files":1},{"repo":"margin","hash":"a0e6e0eb04c28b506adcaa5fe972c8eec8f2fab8","ts":1771632016,"wall":"2026-02-20T19:00","msg":"fix: extension capture flow, external links, and startup crash","body":"Route popup saves through background worker to Tauri HTTP server\ninstead of dead-ending in chrome.storage. Fix content script responding\nto unrelated messages (caused browser freeze). Add tauri-plugin-opener\nfor external link handling. Fix capture server panic by spawning\ndedicated Tokio runtime instead of calling tokio::spawn outside async\ncontext.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["9d635871ea9acee970cb6361c7dd6b3f1a356577"],"add":967,"del":19,"cadd":35,"cdel":16,"files":12},{"repo":"margin","hash":"fc64219e1483ebf706c8a3ed5344550b97ba0248","ts":1771632497,"wall":"2026-02-20T19:08","msg":"docs: mark 2026-02-20 as Margin's birthday","body":"29 days from first commit to shipping v0.1.0 desktop app.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["a0e6e0eb04c28b506adcaa5fe972c8eec8f2fab8"],"add":13,"del":0,"cadd":13,"cdel":0,"files":1},{"repo":"margin","hash":"b1f35dc4ca0bf43449d3be3f883298ae217c958c","ts":1771681469,"wall":"2026-02-21T08:44","msg":"feat: extension queue flush + stale capture guard","body":"Add periodic queue flush so captures saved while Tauri is closed\nare delivered when the app restarts (30s alarm via chrome.alarms).\n\nGuard against stale content scripts after SPA navigation by\ncross-checking the content script's URL against chrome.tabs.get().\nFalls back to tab API metadata (url, title, favicon) when mismatch.\n\nNew permissions: alarms, tabs.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["fc64219e1483ebf706c8a3ed5344550b97ba0248"],"add":111,"del":10,"cadd":108,"cdel":9,"files":3},{"repo":"margin","hash":"b63def5da3efeba0741c8fc632f89913f6f5eea3","ts":1771684670,"wall":"2026-02-21T09:37","msg":"feat: podcast audio support in feed system","body":"Extract audio enclosure URLs from RSS/Atom/JSON feeds and render\nnative HTML5 audio player on feed items. Adds media-src CSP for\npodcast playback while keeping connect-src locked to self.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["b1f35dc4ca0bf43449d3be3f883298ae217c958c"],"add":128,"del":74,"cadd":127,"cdel":73,"files":10},{"repo":"margin","hash":"cf38df811a7b1bb345c0053e1bc670c544bb3467","ts":1771687076,"wall":"2026-02-21T10:17","msg":"fix: use chrome.scripting.executeScript for fresh metadata on every capture","body":"Replaces chrome.tabs.sendMessage (which hits potentially stale\ncontent scripts) with chrome.scripting.executeScript that runs\nfresh extraction code directly in the page context. Eliminates\nthe need to refresh pages before bookmarking.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["b63def5da3efeba0741c8fc632f89913f6f5eea3"],"add":116,"del":31,"cadd":115,"cdel":31,"files":3},{"repo":"margin","hash":"25b98407a30b01638378121b0e3e94ccc749ba86","ts":1771690909,"wall":"2026-02-21T11:21","msg":"feat: dashboard widget system — 6 new widgets for alpha command center","body":"Phase A (no schema changes):\n- Quote of the Day: random highlight with source attribution\n- Contribution Heatmap: 52-week GitHub-style activity grid\n- Orphan Detector: items with no tags and not in collections\n- Trending Tags: tags with increasing usage over last 14 days\n\nPhase B (Dexie v15 migration):\n- Daily Review Queue: spaced repetition with half-life decay algorithm\n- Feed Engagement Ratio: per-feed read/star engagement bars\n\nSchema: Bookmark/Note gain review fields (lastReviewedAt, nextReviewAt,\nreviewCount), FeedItem gains openedAt. Default dashboard layout updated\nto command-center arrangement.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["cf38df811a7b1bb345c0053e1bc670c544bb3467"],"add":1349,"del":15,"cadd":1347,"cdel":15,"files":25},{"repo":"margin","hash":"f123e8a60402285eb2849674b5da8138c81244ae","ts":1771691010,"wall":"2026-02-21T11:23","msg":"docs: update handoff for session 31 — dashboard widgets","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["25b98407a30b01638378121b0e3e94ccc749ba86"],"add":52,"del":38,"cadd":52,"cdel":38,"files":1},{"repo":"margin","hash":"fd748f2345e9d67ae5d8a888700060f59cc98cc7","ts":1771691132,"wall":"2026-02-21T11:25","msg":"fix: full adversarial audit remediation (6 phases)","body":"Phase 1 — Data Integrity:\n- Cascade deletes: bookmark/note/feed delete cleans up tag assignments\n  and backlink index entries; workspace delete blocks if content exists\n- Collection v11 migration: look up actual entity type instead of\n  defaulting all to 'bookmark'\n- Atomic tag updates: wrap delete+insert in Dexie transaction\n\nPhase 2 — Security:\n- CSP: remove http: from media-src, add connect-src for capture server,\n  add frame-ancestors 'none'\n- openExternal: validate URL scheme (http/https/mailto only), simplify\n  singleton to cached promise\n- nginx: add HSTS, Permissions-Policy, COOP, CSP, X-Frame-Options DENY\n- Vite: disable source maps in production builds\n\nPhase 3 — Performance:\n- count() on bookmark/note/workspace/collection repos now uses\n  adapter.count() instead of getAll().length\n- Add GUID + [feedId+guid] compound index on feed items (schema v16)\n\nPhase 4 — Deploy & CI/CD:\n- Entrypoint: validate CORS_ORIGIN, signal traps, wait for API health\n- Health endpoint: GET /api/health on Express API\n- Docker healthcheck in docker-compose.yml\n- CI quality gates: typecheck/lint/test/audit before build matrix\n\nPhase 5 — Correctness:\n- Extension capture: silently skip duplicate URL errors\n- Extension flush: skip 4xx items instead of breaking, only break on 5xx\n- URL validation: fix ReDoS-prone regex, add ::1/0.0.0.0/169.254.x.x\n  to loopback detection\n- Crypto: validate nonce is exactly 12 bytes before AES-GCM decrypt\n\nPhase 6 — Cleanup:\n- Pin @tauri-apps/plugin-opener to exact version\n- Remove no-op .dockerignore negation\n- Hook-safety comment on Titlebar gate component\n- Log 6 new tech debt items (TD-37 through TD-42)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["f123e8a60402285eb2849674b5da8138c81244ae"],"add":590,"del":50,"cadd":577,"cdel":49,"files":21},{"repo":"margin","hash":"4b1372e5678ae18de3a0314d4eb8029b4f149934","ts":1771691996,"wall":"2026-02-21T11:39","msg":"chore: add Dockerfile and deploy setup script","body":"Deployment infrastructure from audit remediation (session 32).","parents":["fd748f2345e9d67ae5d8a888700060f59cc98cc7"],"add":231,"del":48,"cadd":182,"cdel":48,"files":3},{"repo":"margin","hash":"35478c02651967c2320d2b6c291bc650c7cce515","ts":1771697796,"wall":"2026-02-21T13:16","msg":"fix: SPA metadata staleness + editable capture fields + widget picker scroll","body":"Extension popup:\n- Prefer document.title over og:image for SPA sites (YouTube, Facebook)\n- Derive YouTube thumbnails from video URL instead of stale og:image\n- Title and description are now editable inputs before saving\n- Page info condensed to favicon + URL bar\n\nDashboard:\n- Widget picker menu now scrolls at 60vh max height","parents":["4b1372e5678ae18de3a0314d4eb8029b4f149934"],"add":82,"del":46,"cadd":82,"cdel":46,"files":4},{"repo":"unified-ai","hash":"f18014e2d4b61115ffeb57e5a5531ab84ab55ad5","ts":1771708052,"wall":"2026-02-21T16:07","msg":"feat(embeddings): add FastEmbed backend to decouple RAG from Ollama","body":"Embeddings now run in-process via ONNX runtime (fastembed) instead of\nrequiring a running Ollama service. Uses same nomic-embed-text-v1.5\nmodel at 768d — fully compatible with existing Qdrant collections.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["dc779ba4835fcbcbcc6124c89a47c0bea5237845"],"add":51,"del":0,"cadd":51,"cdel":0,"files":1},{"repo":"margin","hash":"3ee357d0f22e4381f4063c6b50af930b23fa48a3","ts":1771726450,"wall":"2026-02-21T21:14","msg":"feat: port JS auto-detect heuristics to Rust scraper engine","body":"Expand Tauri auto_detect_scrape from basic 9-pattern detection to full\nparity with the Express/cheerio engine: 17 container patterns + list\npatterns, nav/chrome filtering, 6-selector title/date/summary/image\nprobing with fallbacks, link-wraps-title detection, confidence scoring\nwith hit rates and field bonuses, 12 JS framework markers, and full\nsample item extraction.","parents":["35478c02651967c2320d2b6c291bc650c7cce515"],"add":515,"del":103,"cadd":514,"cdel":103,"files":3},{"repo":"margin","hash":"6a2879d62d5242153c0e3196cb00fb34182475d4","ts":1771726890,"wall":"2026-02-21T21:21","msg":"fix: migrate stale dashboard layouts to include new widgets","body":"Saved layouts from before new widgets were added would never show them.\nloadLayout now merges missing widget IDs from the registry into the\nsaved layout (hidden by default — user adds via picker). Also fixes\nregistry test to expect all 16 widgets.","parents":["3ee357d0f22e4381f4063c6b50af930b23fa48a3"],"add":58,"del":6,"cadd":58,"cdel":6,"files":2},{"repo":"margin","hash":"9644bae21779ec2ec080085879c2bd7986440f42","ts":1771729751,"wall":"2026-02-21T22:09","msg":"feat: runtime feed discovery with full arXiv taxonomy (195 feeds)","body":"Feed discovery now fetches the latest curated list from GitHub at\nruntime (raw.githubusercontent.com), falling back to the bundled JSON\nwhen offline. Cached for 1 hour via React Query.\n\nAdded all 155 arXiv RSS feeds across 8 categories (CS, Math, Physics,\nQ-Bio, Q-Fin, Stats, Econ, EESS) to the discovery directory. Total\nfeatured feeds: 195 across 13 categories.\n\nTo update the feed directory: edit featured-feeds.json, push to main,\nand every running Margin instance picks it up automatically.","parents":["6a2879d62d5242153c0e3196cb00fb34182475d4"],"add":325,"del":42,"cadd":104,"cdel":26,"files":8},{"repo":"margin","hash":"81e4503bea979bbb1290ae26489076c203097fe8","ts":1771730305,"wall":"2026-02-21T22:18","msg":"feat: add SEP and IEP philosophy feeds to discovery","body":"Stanford Encyclopedia of Philosophy and Internet Encyclopedia of\nPhilosophy — both have active RSS feeds with new/revised entries.","parents":["9644bae21779ec2ec080085879c2bd7986440f42"],"add":15,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"margin","hash":"c9150bec072ac8f9c7738cd91d0ebc65f31e5eb5","ts":1771730798,"wall":"2026-02-21T22:26","msg":"feat: add bioRxiv, medRxiv, and Open Culture to feed discovery (276 total)","body":"Full send — 27 bioRxiv biology categories, 51 medRxiv health sciences\ncategories, and Open Culture. Total discovery directory: 276 feeds\nacross 15 categories. All fetched at runtime from GitHub.","parents":["81e4503bea979bbb1290ae26489076c203097fe8"],"add":103,"del":2,"cadd":0,"cdel":0,"files":1},{"repo":"margin","hash":"5620b87a9d3cab3af63d9a9fde7ba016391ee021","ts":1771730918,"wall":"2026-02-21T22:28","msg":"fix: allow runtime feed discovery fetch from GitHub","body":"CSP connect-src was blocking raw.githubusercontent.com, causing the\nruntime fetch to silently fall back to stale bundled JSON. Added\nthe domain to connect-src allowlist.","parents":["c9150bec072ac8f9c7738cd91d0ebc65f31e5eb5"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"margin","hash":"e87ab77f95b72d193bc5ba6b8ab09c312063852f","ts":1771755665,"wall":"2026-02-22T05:21","msg":"fix: copy featured-feeds.json to dist on build","body":"tsc doesn't reliably re-copy JSON files when only content changes,\ncausing stale fallback feed data in builds. Explicit cp ensures the\n276-feed discovery list is always current.\n\nAlso adds relay architecture research docs (risks analysis and\ninstitutional relay strategy).","parents":["5620b87a9d3cab3af63d9a9fde7ba016391ee021"],"add":755,"del":1,"cadd":754,"cdel":0,"files":3},{"repo":"margin","hash":"6a5d628a18689d2fd54c2d80047693d2aece4f0a","ts":1771755730,"wall":"2026-02-22T05:22","msg":"docs: update master plan, monetization, and dashboard","body":"Master plan updated with completed milestones and vision research.\nMonetization doc revised with relay business model decisions.\nDashboard page tweaks.","parents":["e87ab77f95b72d193bc5ba6b8ab09c312063852f"],"add":556,"del":552,"cadd":556,"cdel":552,"files":4},{"repo":"margin","hash":"e4cd8663eac7e18570334544be4e7a1a389e7e2b","ts":1771779238,"wall":"2026-02-22T11:53","msg":"fix: lint errors, storage test config, and count() archive bug","body":"- Add eslint-plugin-react-hooks for exhaustive-deps enforcement\n- Fix all lint warnings (unused imports, console, missing deps, useMemo)\n- Add vitest.config.ts to storage package (tests were not discoverable)\n- Fix count() in bookmarks, notes, and workspaces repos: was returning\n  total count including archived when called with no filter, now defaults\n  to isArchived: false\n\n1,214 tests passing (201 storage + 502 features + 511 ui).","parents":["6a5d628a18689d2fd54c2d80047693d2aece4f0a"],"add":57,"del":29,"cadd":54,"cdel":27,"files":10},{"repo":"margin","hash":"0cfa365bc02c8aaf4af3f3dc79bb1941c3cf5e72","ts":1771779887,"wall":"2026-02-22T12:04","msg":"fix: regenerate lockfile for CI frozen-lockfile compatibility","body":"","parents":["e4cd8663eac7e18570334544be4e7a1a389e7e2b"],"add":0,"del":13,"cadd":0,"cdel":13,"files":1},{"repo":"margin","hash":"ee5f200f7b45cc2198f9100e04b71dd84b3bfeec","ts":1771780187,"wall":"2026-02-22T12:09","msg":"fix: CI workflow skips desktop build, scopes to JS packages","body":"prepare script was triggering full Tauri build during pnpm install,\nwhich fails without Rust toolchain and system libs. Now uses\n--ignore-scripts and explicitly builds only JS workspace packages.\nTypecheck, lint, and test also scoped to avoid desktop/extension.","parents":["0cfa365bc02c8aaf4af3f3dc79bb1941c3cf5e72"],"add":6,"del":6,"cadd":6,"cdel":6,"files":1},{"repo":"margin","hash":"574ddb896068bb228fe0305618d7d9010dfcf067","ts":1771780394,"wall":"2026-02-22T12:13","msg":"fix: properly add eslint-plugin-react-hooks to lockfile","body":"Previous install had prepare script failure which rolled back the\nlockfile entry. Re-added with --ignore-scripts.","parents":["ee5f200f7b45cc2198f9100e04b71dd84b3bfeec"],"add":14,"del":0,"cadd":13,"cdel":0,"files":2},{"repo":"margin","hash":"41f263745ce75dd9e884594e4ac06898f41e47c6","ts":1771780782,"wall":"2026-02-22T12:19","msg":"fix: release workflow uses --ignore-scripts and builds JS packages","body":"Same prepare script issue as CI — pnpm install triggers full Tauri\nbuild which fails without Rust toolchain on quality gates runner.","parents":["574ddb896068bb228fe0305618d7d9010dfcf067"],"add":5,"del":2,"cadd":5,"cdel":2,"files":1},{"repo":"margin","hash":"77510383e6ff8d89ea5422b6a67e9bd1a6072b24","ts":1771781213,"wall":"2026-02-22T12:26","msg":"fix: remove tracked .claude files and fix release build order","body":".claude/ files were tracked before gitignore rule existed. One had a\nnewline in its filename which broke Windows checkout. Removed all from\ntracking (files still exist locally, just not in repo).\n\nRelease build jobs now build workspace packages before tauri-action\nruns, preventing module-not-found errors.","parents":["41f263745ce75dd9e884594e4ac06898f41e47c6"],"add":3,"del":5299,"cadd":3,"cdel":5298,"files":11},{"repo":"hex-tessellation","hash":"83b394427bee141d562a009ca9be995c9e249e2b","ts":1771790963,"wall":"2026-02-22T15:09","msg":"Initial hex tessellation engine through Sprint 1","body":"Modular Python backend for regular polygon tessellation.\nPrimary use case: planning hexagonal canyon modules for Azura terraforming.\n\nCompleted:\n- polygon.py: vertex generation, compass bearing alignment\n- hex_grid.py: axial coordinates, neighbors, ring/spiral, rotated pixel conversion\n- grid_state.py: HexGrid class — add/remove/query hexes one by one\n- dimensions.py: unit-aware real-world measurements (ft/m, excavation volume)\n- plot.py: matplotlib rendering module\n- Master plan with 5-sprint roadmap\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":659,"del":0,"cadd":651,"cdel":0,"files":18},{"repo":"hex-tessellation","hash":"8a2016816596d5f57d2c6e86b7fe7b5cca67b4af","ts":1771791015,"wall":"2026-02-22T15:10","msg":"Add session handoff","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["83b394427bee141d562a009ca9be995c9e249e2b"],"add":67,"del":0,"cadd":67,"cdel":0,"files":1},{"repo":"hex-tessellation","hash":"f6412cd539d35a9cec1c40001169a5ebe46ab327","ts":1771791532,"wall":"2026-02-22T15:18","msg":"Sprint 2: placement intelligence, metadata, and shared edge detection","body":"Adds valid placement spots, build-order IDs with per-hex metadata\n(timestamp, status, notes), and shared edge detection between adjacent\nhexes. Removed hexes preserved in build history for audit trail.\n\nNew files: tessellation/metadata.py, tessellation/edges.py\nPieces completed: 1e, 2a, 2b, 4a\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["8a2016816596d5f57d2c6e86b7fe7b5cca67b4af"],"add":253,"del":21,"cadd":253,"cdel":21,"files":6},{"repo":"hex-tessellation","hash":"5ce41e70a316b6466abdf195f008913df7c10305","ts":1771791578,"wall":"2026-02-22T15:19","msg":"Update session handoff for Sprint 2 completion","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["f6412cd539d35a9cec1c40001169a5ebe46ab327"],"add":41,"del":28,"cadd":41,"cdel":28,"files":1},{"repo":"hex-tessellation","hash":"61c082fb0df8f063cbfff857ce6a22c007dd4c0f","ts":1771791859,"wall":"2026-02-22T15:24","msg":"Sprint 3: gateways, labels, unit formatting, and JSON serialization","body":"Adds gateway/wall marking on shared edges with configurable open ratio\n(default 60%), gateway geometry for rendering (opening + buttress segments),\nlabel positions for hex IDs, formatted dimension strings with units, and\nsave_grid() for JSON export of full grid state.\n\nNew file: tessellation/serialization.py\nPieces completed: 4b, 4c, 4d, 2c, 3c, 5a (issues #1-6)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5ce41e70a316b6466abdf195f008913df7c10305"],"add":268,"del":12,"cadd":267,"cdel":12,"files":8},{"repo":"hex-tessellation","hash":"05b034b27b5562c13459f09fce2142b124dd379a","ts":1771791916,"wall":"2026-02-22T15:25","msg":"Update session handoff for Sprint 3 completion","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["61c082fb0df8f063cbfff857ce6a22c007dd4c0f"],"add":24,"del":27,"cadd":24,"cdel":27,"files":1},{"repo":"hex-tessellation","hash":"635a14f1291c57344a4e58f58e8e9b1e28306d91","ts":1771792242,"wall":"2026-02-22T15:30","msg":"Render gateway apertures as gaps in hex outlines","body":"Adds plot_hex_with_gateways() which draws each edge individually,\nleaving gaps proportional to the open_ratio at gateway edges.\nButtress stubs remain at vertices, opening grows from center outward.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["05b034b27b5562c13459f09fce2142b124dd379a"],"add":56,"del":6,"cadd":56,"cdel":6,"files":3},{"repo":"hex-tessellation","hash":"11f155371123280b4d0e249bf6d72e2591e01256","ts":1771792438,"wall":"2026-02-22T15:33","msg":"Sprint 4: load from JSON and GeoJSON export","body":"Adds load_grid() for full roundtrip persistence (hexes, metadata with\noriginal IDs/timestamps, gateways) and export_geojson() for QGIS overlay\nwith configurable lat/lon anchor point. Roundtrip save→load→save produces\nidentical JSON.\n\nNew: MetadataStore.register_with_id() for deserialization\nPieces completed: 5b, 5c (issues #8-9)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["635a14f1291c57344a4e58f58e8e9b1e28306d91"],"add":168,"del":7,"cadd":168,"cdel":7,"files":4},{"repo":"hex-tessellation","hash":"c90ba4ab7653394133e6fcd19fd27f48b45b17ae","ts":1771792474,"wall":"2026-02-22T15:34","msg":"Update session handoff for Sprint 4 completion","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["11f155371123280b4d0e249bf6d72e2591e01256"],"add":20,"del":26,"cadd":20,"cdel":26,"files":1},{"repo":"hex-tessellation","hash":"5c78278fe053d1cca430c3e29d439a3cf5cfb732","ts":1771792749,"wall":"2026-02-22T15:39","msg":"Add comprehensive test suite for all modules (116 tests)","body":"Covers polygon, hex_grid, grid_state, metadata, edges, dimensions,\nand serialization. Tests include geometry math verification, roundtrip\npersistence, gateway toggle/geometry, metadata lifecycle, GeoJSON\nstructure, and edge cases (empty grids, duplicates, remove/re-add).\n\nCloses #7\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c90ba4ab7653394133e6fcd19fd27f48b45b17ae"],"add":803,"del":0,"cadd":803,"cdel":0,"files":8},{"repo":"hex-tessellation","hash":"0368860968a214c2e6a2850d48ea1fc6a28e174b","ts":1771793925,"wall":"2026-02-22T15:58","msg":"Web UI Phase 1: FastAPI + Leaflet map with hex placement","body":"Map-based interface on OSM tiles centered on Eureka NV. Modes: place,\nremove, gateway toggle, spiral fill. Sliders for hex size (3-50ft),\nbearing (0-360), vertex/edge alignment. Stats panel, hex info panel,\nsave/load/export controls. All geometry computed server-side.\n\nNew files: app.py, static/index.html\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5c78278fe053d1cca430c3e29d439a3cf5cfb732"],"add":719,"del":0,"cadd":719,"cdel":0,"files":2},{"repo":"hex-tessellation","hash":"77f5770cd59fd019998687d5782c7fb0e4565c38","ts":1771793963,"wall":"2026-02-22T15:59","msg":"Update handoff for Web UI Phase 1","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["0368860968a214c2e6a2850d48ea1fc6a28e174b"],"add":56,"del":27,"cadd":56,"cdel":27,"files":1},{"repo":"hex-tessellation","hash":"b3f20a2acf55ee73002a95eaddde75d2ad2dbe35","ts":1771799689,"wall":"2026-02-22T17:34","msg":"Web UI: click-to-place anywhere, movable anchor, per-edge gateways, bug fixes","body":"- Add pixel_to_axial/axial_round for lat/lon→hex coordinate conversion\n- Click anywhere on map to place hex (not just adjacent slots)\n- Movable anchor point (Anchor mode or right-click) — no longer hardcoded to Eureka\n- Gateways now per-edge (q, r, direction) — any edge of any hex can be a gateway\n- Remove mode merged into Place (click existing hex to remove)\n- ESRI satellite basemap replaces blank OSM tiles\n- Fix click propagation through polygons to map\n- Fix clearGrid: single POST /api/clear instead of N sequential deletes\n- Add error handling on all API calls\n- Remove auto-origin hex on empty grid\n- Move hexSet construction outside inner loop\n- Configurable --port flag (default 6660)\n- 117 tests passing\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["77f5770cd59fd019998687d5782c7fb0e4565c38"],"add":280,"del":163,"cadd":280,"cdel":163,"files":9},{"repo":"groundwork","hash":"c9af72b847abd15901292acd3df7b6b9514f49f3","ts":1771800947,"wall":"2026-02-22T17:55","msg":"Add master plan for hex tessellation fusion into Groundwork","body":"Web UI replaces TUI and CLI entirely. Hex engine imported as\ngroundwork/hex/ package. Groundwork acquire/analyze backend\nserves data as map layers to a unified Leaflet frontend.\n\nPhases 7-12 outlined: hex import, frontend shell, data layer\nUI, analysis UI, project management, polish.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["1823e1094e1446d95395fc2f5578d58e2e0f0498"],"add":294,"del":0,"cadd":294,"cdel":0,"files":1},{"repo":"azura-terraforming","hash":"2739efc740b1ccc4cdc982efd9adba1d85cb6db0","ts":1771862496,"wall":"2026-02-23T11:01","msg":"Add water treatment, manufacturing, and solar thermal research","body":"Five research documents covering the integrated infrastructure stack:\n- Brackish RO water treatment system design (custom-built, component-level)\n- Local manufacturing and import substitution strategy (5-phase capability buildup)\n- Ceramic membrane development R&D program (MD, pervaporation, zeolite RO)\n- Parabolic solar thermal systems (heat as universal manufacturing input)\n- Food sovereignty economic model (subsistence agroecosystem framing)\n\nTogether these define the Symbiont Systems vertical integration path:\nsolar thermal → ceramic membranes → clean water → food sovereignty →\nregional manufacturing for the Great Basin.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["838063bf99b84576fc0dcf95286cf4a7362543f8"],"add":1494,"del":0,"cadd":1494,"cdel":0,"files":5},{"repo":"azura-terraforming","hash":"8de91f41010808dd3a7624126dc2defc38b14b4f","ts":1771862802,"wall":"2026-02-23T11:06","msg":"Add manufacturing connex specification","body":"40ft high cube shipping container workshop spec with:\n- 3-zone layout (welding, machining, bench work)\n- 200A electrical, R-14 spray foam insulation\n- Welding fume extraction, dust collection, compressed air hardline\n- $10k-21k shell cost, $13k-29k with Phase 1 tools\n- 8-week build sequence from bare ground to working shop\n- Expansion path to 3-container U-shape manufacturing facility\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["2739efc740b1ccc4cdc982efd9adba1d85cb6db0"],"add":650,"del":0,"cadd":650,"cdel":0,"files":1},{"repo":"azura-terraforming","hash":"80a32aca8afbdafe34ad5e47349182fb32d7f05f","ts":1771864633,"wall":"2026-02-23T11:37","msg":"Add engineering software stack specification","body":"Open source, Linux-native engineering toolchain for Fedora 43:\n- FreeCAD 1.0.2 (parametric 3D CAD, FEA, assembly, SendCutSend DXF export)\n- LibreCAD (2D drafting), Inkscape (SVG), OpenSCAD (programmatic CAD)\n- KiCad 9 (electronics, Phase 3), Blender (visualization)\n- Python/Jupyter for engineering calculations\n- InvenTree/ERPNext for inventory and business ops (Phase 3-4)\n- Install script, learning priority sequence, file management structure\n\nTotal software cost: $0. All open source, all local-first.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["8de91f41010808dd3a7624126dc2defc38b14b4f"],"add":329,"del":0,"cadd":329,"cdel":0,"files":1},{"repo":"azura-terraforming","hash":"73ec954f4ede57b51d8439c290be08e5baca795b","ts":1771865600,"wall":"2026-02-23T11:53","msg":"Add session handoff — 2026-02-23","body":"Water treatment, manufacturing, ceramic membranes, solar thermal,\nengineering software. Full context for next session.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["80a32aca8afbdafe34ad5e47349182fb32d7f05f"],"add":94,"del":0,"cadd":94,"cdel":0,"files":1},{"repo":"margin","hash":"55fd32f32bcdd6cd55721bf389a49908ce2bd420","ts":1771878740,"wall":"2026-02-23T15:32","msg":"docs: add semantic engine feature spec to future plans","body":"Research and spec for opt-in local embedding engine (fastembed + sqlite-vec)\nthat surfaces automatic connections between bookmarks, notes, and feeds.\nDesigned as a downloadable widget, not a default feature. Depends on\nplanned SQLite migration.","parents":["77510383e6ff8d89ea5422b6a67e9bd1a6072b24"],"add":239,"del":0,"cadd":239,"cdel":0,"files":3},{"repo":"margin","hash":"13025ecc844248ebc772aeaa0a034298487c0d8a","ts":1771880951,"wall":"2026-02-23T16:09","msg":"feat: extension side panel with live data via REST API bridge","body":"Replace the extension popup with a Chrome Side Panel that shows live\ndata from the Tauri desktop app. The Rust HTTP server proxies read-only\nqueries to the webview via Tauri events and oneshot channels, where the\nReact app queries IndexedDB and returns results.\n\n- Rust: REST API bridge with 10 endpoints (/api/stats, bookmarks, notes,\n  feeds, collections, search) using dashmap + oneshot channels (5s timeout)\n- Rust: api_response Tauri command for webview→server response path\n- Webview: useApiBridge hook routes api:request events to service layer\n- Extension: side panel with collapsible sidebar nav, 7 data views\n  (page context, bookmarks, notes, feeds, collections, search, settings)\n- Extension: typed API client with connection detection and 30s polling\n- Extension: badge count polling, tab-aware page context, quick capture\n- Fix: duplicate bookmark prevention via pre-check + DuplicateError catch","parents":["55fd32f32bcdd6cd55721bf389a49908ce2bd420"],"add":2483,"del":25,"cadd":2155,"cdel":12,"files":28},{"repo":"margin","hash":"885cebc0dbc8829bb28906ab2620a9bf38fa369f","ts":1771886641,"wall":"2026-02-23T17:44","msg":"feat: page annotations system (local-first MVP)","body":"W3C Web Annotation compliant commenting on any URL. Full stack:\n- Core types (Comment, TextQuoteSelector, UserIdentity)\n- P-256 ECDSA identity with did:key derivation\n- Dexie storage (v17) with comment repository\n- Comment service with social filtering (friends/public/mine)\n- Follows service backed by settings\n- Relay sync stub (501 until deployed)\n- Rust capture server routes (6 endpoints)\n- Web app API bridge routing\n- Extension API client + content script selector capture\n- Extension UI: AnnotationsView with filter, compose, TipTap editor\n- TipTap lazy-loaded in separate chunk (420KB isolated)","parents":["13025ecc844248ebc772aeaa0a034298487c0d8a"],"add":1800,"del":33,"cadd":1796,"cdel":33,"files":25},{"repo":"margin","hash":"7ffb727801e4184e8dbefcb25b97b9dd758311c5","ts":1771887258,"wall":"2026-02-23T17:54","msg":"feat: extension side panel write operations","body":"Add action buttons to side panel views — favorite/archive/delete for\nbookmarks, star/mark-read/save-as-bookmark for feed items, pin/delete\nfor notes. Shared useApiAction hook for loading state and refresh.\nFix PageContextView to re-check bookmark ID after save.","parents":["885cebc0dbc8829bb28906ab2620a9bf38fa369f"],"add":213,"del":24,"cadd":213,"cdel":24,"files":5},{"repo":"margin","hash":"23c2642b1a6073ddee1d417f49dcd85738463e19","ts":1771887266,"wall":"2026-02-23T17:54","msg":"feat: reader mode refactor with readabilityrs and note panel","body":"Replace hand-rolled article extraction with readabilityrs (Mozilla\nReadability algorithm). Refactor ReaderPage with split-pane layout\nfor side-by-side note editing. Extract ReaderToolbar and\nReaderNotePanel components.","parents":["7ffb727801e4184e8dbefcb25b97b9dd758311c5"],"add":347,"del":155,"cadd":346,"cdel":154,"files":5},{"repo":"margin","hash":"f9ff8ec55d8499fa89ae62ffd44617d49b23864d","ts":1771888454,"wall":"2026-02-23T18:14","msg":"fix: defensive error handling and HTML sanitization in AnnotationsView","body":"Add isValidAnnotation type guard to filter malformed API responses.\nSanitize annotation body HTML with DOMPurify to prevent stored XSS.","parents":["23c2642b1a6073ddee1d417f49dcd85738463e19"],"add":40,"del":3,"cadd":38,"cdel":3,"files":4},{"repo":"margin","hash":"ebe99acec423a688655851ad76eb7c2dae524f50","ts":1771888967,"wall":"2026-02-23T18:22","msg":"feat: annotation to note promotion (#31)","body":"Add promote bridge route (POST /api/comments/:id/promote) that creates\na note from annotation body and links it to the bookmark. Expose\ngetAnnotationById on CommentService. Add promote button to extension\nannotation cards.","parents":["f9ff8ec55d8499fa89ae62ffd44617d49b23864d"],"add":61,"del":0,"cadd":61,"cdel":0,"files":5},{"repo":"margin","hash":"3276058a6fb54d024d0e2263d9f8b451d86e9ab1","ts":1771889205,"wall":"2026-02-23T18:26","msg":"feat: annotations in reader mode (#32)","body":"Add annotation hooks (useAnnotationsForUrl, useAnnotationCount) and\nReaderAnnotationsPanel for split-pane view. Toolbar shows annotation\ncount badge. Panel state refactored to union type supporting both\nnote and annotations panels.","parents":["ebe99acec423a688655851ad76eb7c2dae524f50"],"add":174,"del":10,"cadd":172,"cdel":10,"files":8},{"repo":"margin","hash":"cf353b49e60cf5a784447938f48ea1bde9035986","ts":1771889446,"wall":"2026-02-23T18:30","msg":"feat: auto-collect annotations into note per URL (#34)","body":"Add collectAnnotationsToNote utility that aggregates all annotations\nfor a URL into a linked note with blockquotes. useCollectAnnotations\nmutation hook and \"Collect to note\" button in reader toolbar.","parents":["3276058a6fb54d024d0e2263d9f8b451d86e9ab1"],"add":107,"del":3,"cadd":107,"cdel":3,"files":6},{"repo":"margin","hash":"c028f403d22f6e196d4f18b1ddd20cd20e954b91","ts":1771890496,"wall":"2026-02-23T18:48","msg":"feat: wire up @ mention reference search for all entity types (#33)","body":"Register global search function for the TipTap @ mention system,\nsearching across bookmarks, notes, feed items, and annotations.\nThe reference selector was previously non-functional (no search\nwas ever registered). Adds annotation type with purple badge and\nblockquote insertion.","parents":["cf353b49e60cf5a784447938f48ea1bde9035986"],"add":150,"del":4,"cadd":150,"cdel":4,"files":5},{"repo":"margin","hash":"d928a9913584c17e51c942d8f4debd4b4960779d","ts":1771894352,"wall":"2026-02-23T19:52","msg":"refactor: universal embed block replaces per-type card extensions","body":"Replace BookmarkCardExtension + FeedItemCardExtension with a single\ngeneric EmbedBlockExtension that stores a type discriminator + JSON\npayload and dispatches rendering to a type-keyed registry. New embed\ntypes become ~30-line renderer components with zero extension changes.\n\n- Add embedRegistry.ts, EmbedBlockNodeView.tsx, EmbedBlockExtension.ts\n- Add BookmarkEmbedRenderer + FeedItemEmbedRenderer adapters\n- Legacy data-bookmark-card / data-feed-item-card HTML parsed and\n  silently migrated to data-embed format on next save\n- Simplify @ mention insertion (4 branches → 2)\n- BookmarkPopover uses setEmbed/updateEmbed commands\n- Link extraction scans both old + new HTML formats (6 new tests)\n- Fix pre-existing bug: guard services.comments?.searchAnnotations\n- Old extensions marked @deprecated, kept on disk\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c028f403d22f6e196d4f18b1ddd20cd20e954b91"],"add":761,"del":81,"cadd":761,"cdel":81,"files":16},{"repo":"margin","hash":"fad1f80fef19f69fa4582e1bfeb69e866c2be138","ts":1771894618,"wall":"2026-02-23T19:56","msg":"fix: wire up /bookmark slash command and guard annotation search","body":"- EditorToolbar now renders BookmarkPopover and listens for\n  the margin:open-bookmark-popover event from slash commands\n- Guard services.comments?.searchAnnotations with optional\n  chaining so @ search doesn't blow up when service is missing\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d928a9913584c17e51c942d8f4debd4b4960779d"],"add":19,"del":1,"cadd":19,"cdel":1,"files":1},{"repo":"margin","hash":"6845e04e9abc9d062251d6dc97e080af3722378c","ts":1771894717,"wall":"2026-02-23T19:58","msg":"docs: update handoff for session 39","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["fad1f80fef19f69fa4582e1bfeb69e866c2be138"],"add":100,"del":0,"cadd":100,"cdel":0,"files":1},{"repo":"margin","hash":"7256284b2a43ef8be12968c219819d47efddbfb5","ts":1771895162,"wall":"2026-02-23T20:06","msg":"chore: delete deprecated card extensions, migrate callers","body":"- Delete BookmarkCardExtension, FeedItemCardExtension, and their\n  NodeView components (zero callers since embed refactor)\n- Move BookmarkCardAttributes + FeedItemCardAttributes interfaces\n  to embed-types.ts\n- Migrate FeedsPage from generateFeedItemCardHtml to generateEmbedHtml\n- Remove satisfies assertions from useReferenceSearch\n- Clean up re-exports in extensions/index.ts, editor/index.ts, index.ts\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["6845e04e9abc9d062251d6dc97e080af3722378c"],"add":77,"del":763,"cadd":77,"cdel":763,"files":12},{"repo":"margin","hash":"92ee682c0baa93b000766e95e343d1153eaa8216","ts":1771895239,"wall":"2026-02-23T20:07","msg":"docs: update handoff with cleanup commit","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["7256284b2a43ef8be12968c219819d47efddbfb5"],"add":16,"del":8,"cadd":16,"cdel":8,"files":1},{"repo":"margin","hash":"98fc47fe293aed7e93175a21f55f722f88107c72","ts":1771899534,"wall":"2026-02-23T21:18","msg":"feat: rename /bookmark to /link, wire up fetchMetadata, fix stale plan","body":"Slash command renamed Bookmark→Link with Link2 icon and bare-domain\nplaceholder. fetchMetadata now flows through EditorToolbar→BookmarkPopover\nso link embeds resolve rich previews. MASTER-PLAN M1 detail updated to\nreflect shipped state, orphan issues #25/#26/#30 slotted into milestones.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["92ee682c0baa93b000766e95e343d1153eaa8216"],"add":67,"del":21,"cadd":67,"cdel":21,"files":7},{"repo":"margin","hash":"ca7ef3e8ddf881193fd91ae7ed11057a67e3e1e3","ts":1771960033,"wall":"2026-02-24T14:07","msg":"feat: media entity implementation + architecture research (storage, CRDT, AI)","body":"Media as first-class entities: type system, storage adapter, service layer,\nupload/preview UI (grid/list views, detail page), collection integration,\nReact Query hooks. Images don't display in Tauri due to blob URL origin\nmismatch (tauri#7363) — filesystem migration planned.\n\nArchitecture research completed: Loro CRDT selected, SQLite+filesystem\nstorage, local embeddings (fastembed-rs + sqlite-vec), SQLCipher encryption,\ntyped property graph data model. MASTER-PLAN updated with decisions.","parents":["98fc47fe293aed7e93175a21f55f722f88107c72"],"add":1697,"del":83,"cadd":1696,"cdel":82,"files":32},{"repo":"margin","hash":"e92cfe6cec993c91e9580fe5b36d8b6964692cca","ts":1771966947,"wall":"2026-02-24T16:02","msg":"docs: Block Model Design doc with Q1+Q2 decisions, 15 open questions","body":"New architecture doc for universal typed blocks. Decisions resolved:\n- Q1: Advisory schema with extensive built-in registry + custom Type Editor\n- Q2: Composable types (types: Set<TypeID>), context-dependent rendering,\n  each type auto-generates a page (Collection filtered by type), unifying\n  types/pages/collections into one system.\n\n15 open design questions (Q3-Q17) documented for next sessions.","parents":["ca7ef3e8ddf881193fd91ae7ed11057a67e3e1e3"],"add":348,"del":0,"cadd":348,"cdel":0,"files":2},{"repo":"margin","hash":"c57e65bf451f888180cd81fee3e8f0ba27f3b488","ts":1771976550,"wall":"2026-02-24T18:42","msg":"docs: resolve Q9+Q3+Q6+Q15+Q16, glossary, sidebar UX design","body":"Resolved 5 Block Model Design questions:\n- Q9: Hybrid storage authority (SQLite for structured, Loro for CRDT)\n- Q3: LoroText + HTML cache for content\n- Q6: Per-block LoroDoc + shared tree docs\n- Q15: Loro op DAG for content history, SQLite changelog for metadata\n- Q16: sqlite-vec virtual table, derived data\n\nAdded working glossary defining all system particles.\nAdded dependency-ordered resolution table for remaining 10 questions.\nAdded sidebar UX design (pin/unpin + grace period) for Q12 discussion.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["e92cfe6cec993c91e9580fe5b36d8b6964692cca"],"add":324,"del":77,"cadd":324,"cdel":77,"files":2},{"repo":"margin","hash":"142c119ff9b49ee1712e64efed8ac7e3867971c7","ts":1771982309,"wall":"2026-02-24T20:18","msg":"docs: complete Block Model Design — all 17 questions resolved","body":"Resolved remaining questions:\n- Q10: Evolve existing property system into attribute registry\n- Q11: Tags are types (same mechanism, UX convention only)\n- Q12: Collections are containers with sidebar pin/unpin curation\n- Q8: UUID v7 for block IDs\n- Q4: Semi-open relation vocabulary\n- Q7: Per-collection LoroTree only, no global tree\n- Q13: Feeds are blocks, subscription is system behavior\n- Q5: Fully blind relay (zero metadata leakage)\n- Q14: Tombstone with 7-day GC + hard delete option\n- Q17: Design validated against 12 use cases — no breaks found\n\nAdded working glossary, dependency-ordered resolution sequence,\nsidebar UX design (pin/unpin + grace period for new types).\n\nDesign phase complete. Ready for implementation on 19x.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c57e65bf451f888180cd81fee3e8f0ba27f3b488"],"add":412,"del":48,"cadd":412,"cdel":48,"files":1},{"repo":"margin","hash":"47f55d511adcdd8330a568460c7f2a9a8f511246","ts":1771983027,"wall":"2026-02-24T20:30","msg":"docs: update MASTER-PLAN to reflect Block Model Design completion","body":"- M8 Block Design: all 17 questions resolved, design validated\n- M9 Block Implementation: updated with Phase 7-11 sequence\n- Added 16 new architecture decisions to resolved list\n- Removed \"Universal Block viability\" from pending (validated)\n- Added future decisions: collaboration, publishing, import, federation\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["142c119ff9b49ee1712e64efed8ac7e3867971c7"],"add":41,"del":20,"cadd":41,"cdel":20,"files":1},{"repo":"margin","hash":"877fae2e0ae390f9fff625b2605f88dccb14d7e4","ts":1771987729,"wall":"2026-02-24T21:48","msg":"feat: M5 5a — document structure extensions (callout, page break, toggle, TOC, footnotes)","body":"Add 5 new TipTap editor extensions for document authoring:\n- Callout/admonition blocks (info/warning/tip/error) with type switcher\n- Page break nodes for PDF/print export\n- Toggle/collapsible sections via native <details>/<summary>\n- Table of contents plugin with clickable sidebar panel\n- Footnote references with auto-numbering and hover preview\n\nAll extensions are feature-flagged in the editor preset system. Includes\n8 new slash commands, 4 Turndown rules for Markdown export, and barrel\nexports from the editor package.","parents":["47f55d511adcdd8330a568460c7f2a9a8f511246"],"add":2186,"del":48,"cadd":2186,"cdel":48,"files":15},{"repo":"mesnada","hash":"9d1abef45943a3e7d36b28fab6be020b8b0a3bde","ts":1771990762,"wall":"2026-02-24T22:39","msg":"Add pawn + gear data model (Phase 1)","body":"Generic pawn system replacing fixed unit classes: rank table, 18 items,\n14 skills, 13 loadout presets, dataclasses, loaders, and effective stats\nresolver. No existing code modified — Phase 2 does the migration.","parents":["52eedfd54afab4b2caba1207f891ed6791df34a2"],"add":1638,"del":0,"cadd":1029,"cdel":0,"files":50},{"repo":"mesnada","hash":"46812347a59435e82d6656142b8635415f995c6c","ts":1771991711,"wall":"2026-02-24T22:55","msg":"Migrate backend from get_unit_type() to get_effective_stats() (Phase 2)","body":"Bridge-based migration: Unit gains gear/skills fields, get_effective_stats()\naccepts Unit with legacy fallback (no gear → derives from UnitType). All\ngame logic now uses get_effective_stats() and skill-based checks instead of\nUnitType.special. 259 existing + 26 pawn tests pass.","parents":["9d1abef45943a3e7d36b28fab6be020b8b0a3bde"],"add":196,"del":119,"cadd":196,"cdel":119,"files":15},{"repo":"mesnada","hash":"f8688de2dfa9e692c98d4d85e03364b62bdbc008","ts":1771991932,"wall":"2026-02-24T22:58","msg":"Update session handoff for pawn system Phase 1-2","body":"","parents":["46812347a59435e82d6656142b8635415f995c6c"],"add":61,"del":98,"cadd":61,"cdel":98,"files":1},{"repo":"mesnada","hash":"ce82a83d85adad7ac4eff5ace473e978890f46d1","ts":1771995470,"wall":"2026-02-24T23:57","msg":"Add mount/carry system and eliminate legacy UnitType creation path (Phase 3)","body":"Mount/carry system: mount_unit/dismount_unit actions, animal vs humanoid\ncarry modes distinguished by animal tag, movement delegation for animal\nriders, mount release on carrier death, carry_load weight tracking.\n\nMigrated create_unit() to use loadout presets with rank-based stats.\nSpawning and AI action generation now use get_loadout/get_all_loadouts\ninstead of legacy get_unit_type/get_all_unit_types.\n\n276 tests pass, 13 skipped (mount-dependent traits deferred to animal data).","parents":["f8688de2dfa9e692c98d4d85e03364b62bdbc008"],"add":728,"del":46,"cadd":728,"cdel":46,"files":23},{"repo":"azura-terraforming","hash":"e73b5f838dcd6011e33bd474f8e116feaecd84c1","ts":1772044805,"wall":"2026-02-25T13:40","msg":"Add legal/resource findings and government API query tool","body":"- New research doc: mineral rights (full ownership confirmed via GLO),\n  water rights (Basin 054 designated, domestic exemption viable),\n  geothermal resources (Beowawe field 10mi W), trespass/defense law\n- Query tool hits 7 government APIs (NDWR, FEMA, BLM, NBMG, NRCS)\n  for wells, water rights, basin info, flood zones, grazing, geothermal, soils\n- Updated integrated assessment and legal framework with resolved gaps\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["73ec954f4ede57b51d8439c290be08e5baca795b"],"add":634,"del":9,"cadd":634,"cdel":9,"files":4},{"repo":"azura-terraforming","hash":"fe92d62b7d8a0bcc0064b3b81ea03c81669f0ef7","ts":1772045936,"wall":"2026-02-25T13:58","msg":"Add public-facing project overview for Azura hex canyon system","body":"Technical brief format covering site data, design, biological models,\nflood strategy, phasing, costs, risks, and regulatory status. Draws\non NDWR, FEMA, NRCS, BLM, and NBMG API data gathered this session.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["e73b5f838dcd6011e33bd474f8e116feaecd84c1"],"add":410,"del":0,"cadd":410,"cdel":0,"files":1},{"repo":"mesnada","hash":"7411fa28933648e649dd4f786e088d8de3657e93","ts":1772067613,"wall":"2026-02-25T20:00","msg":"Add new gear items and replace war_banner with field_radio","body":"New weapons: halberd, billhook, pistol, flamethrower, rifle, warhammer, assassins_kit\nNew defense: wooden_shield\nReplaced war_banner with field_radio (same commander_aura, modern flavor)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ce82a83d85adad7ac4eff5ace473e978890f46d1"],"add":156,"del":4,"cadd":0,"cdel":0,"files":9},{"repo":"mesnada","hash":"2e2b64b498e1408664a54566cd1a5fba955e7568","ts":1772067637,"wall":"2026-02-25T20:00","msg":"Add sprite variant system and archive legacy unit sprites","body":"- spriteLoader: Vite glob discovers all PNGs per unit folder, supports multiple variants\n- unitRenderer: stable hash picks consistent variant per hex+unit combo\n- units.ts: update sprite paths to new naming convention\n- GameBoard: fix texture type to Texture[]\n- Archive old single-direction sprites to _archive/\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["7411fa28933648e649dd4f786e088d8de3657e93"],"add":67,"del":28,"cadd":67,"cdel":28,"files":40},{"repo":"mesnada","hash":"9701e002f8abccc923a791a3078a9cb51411325f","ts":1772067645,"wall":"2026-02-25T20:00","msg":"Add species system design research doc","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["2e2b64b498e1408664a54566cd1a5fba955e7568"],"add":332,"del":0,"cadd":332,"cdel":0,"files":1},{"repo":"mesnada","hash":"f2e1413c0460d2b22231988fbf3c1d10dfb108f7","ts":1772067700,"wall":"2026-02-25T20:01","msg":"Update handoff for gear items and sprite generation session","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["9701e002f8abccc923a791a3078a9cb51411325f"],"add":62,"del":57,"cadd":62,"cdel":57,"files":1},{"repo":"azurak-language","hash":"3024b2c547033e730e882ad70248b604ca4fd09c","ts":1772068130,"wall":"2026-02-25T20:08","msg":"Initial commit: seed Azurak language repo with techbiont comms lexicon","body":"Authored by Rowan Valle; Executed by Claude Code","parents":[],"add":215,"del":0,"cadd":215,"cdel":0,"files":1},{"repo":"azurak-language","hash":"2ec3d2736f80985ae49128f8282ad8c65e233727","ts":1772068175,"wall":"2026-02-25T20:09","msg":"Rename techbiont-lexicon.md to azurak-lexicon.md","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["3024b2c547033e730e882ad70248b604ca4fd09c"],"add":0,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"azurak-language","hash":"8e822e41b1afd9a0d43b729b5eb4b60427d53a02","ts":1772068274,"wall":"2026-02-25T20:11","msg":"Rename Techbiont to Azurak in lexicon header","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["2ec3d2736f80985ae49128f8282ad8c65e233727"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"mesnada","hash":"29af30a281ce7c2caa0c6a0e3c76e67f41f4f792","ts":1772077392,"wall":"2026-02-25T22:43","msg":"Update handoff: sprite generation at 90/152","body":"Half plate and full plate weapon tiers nearly complete.\nShield combos, mounts, and flying variants remain.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["f2e1413c0460d2b22231988fbf3c1d10dfb108f7"],"add":4,"del":4,"cadd":4,"cdel":4,"files":1},{"repo":"mesnada","hash":"0cea8e49abf441e3d00ca6917748acb0d273856c","ts":1772084221,"wall":"2026-02-26T00:37","msg":"Add iron shield item definition","body":"Heavy shield variant: +5 defense, weight 4, -1 movement, corporal rank.\nWooden shield is lighter (+3 def, weight 2), iron is heavier but stronger.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["29af30a281ce7c2caa0c6a0e3c76e67f41f4f792"],"add":19,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"mesnada","hash":"91ee58d7bff1392dc5c2e2b459d567239af2821e","ts":1772084323,"wall":"2026-02-26T00:38","msg":"Update handoff: sprite generation at 109/137, iron shield added","body":"Shield combos use only shortsword (realistic constraint).\nTwo shield types: wooden (light) and iron (heavy).\nMounted lancers done. Half plate and full plate tiers complete.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["0cea8e49abf441e3d00ca6917748acb0d273856c"],"add":18,"del":15,"cadd":18,"cdel":15,"files":1},{"repo":"mesnada","hash":"a5b29c31fc667a042bce2dbf736a0a69ddf11856","ts":1772089912,"wall":"2026-02-26T02:11","msg":"Add game loop design doc: settlements, economy, squads, ecology","body":"Comprehensive design document for the new sandbox game loop:\n- Settlements (6 tiers, homestead to capital) with buildings (plaza, bodega)\n- Economy: gather hex resources, sell at bodega, recruit/equip pawns\n- Hex resources: terrain-linked, finite, stone/ore permanently deplete\n- Ecology: herd pawns (prey/predator) with emergent Lotka-Volterra dynamics\n- Squad system: mixed-loadout formations, hit priority defense, combined arms\n- Procedural map generation (choosable size), full fog of war, no hex placement\n- Kenshi-inspired sandbox: no win condition, lose when all pawns die\n- 7 implementation phases (A-G), each leaves game playable\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["91ee58d7bff1392dc5c2e2b459d567239af2821e"],"add":940,"del":0,"cadd":940,"cdel":0,"files":1},{"repo":"mesnada","hash":"a840a7025172ae00ea8a13b6004d87c8d779c44a","ts":1772090394,"wall":"2026-02-26T02:19","msg":"Update handoff for game loop design session","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["a5b29c31fc667a042bce2dbf736a0a69ddf11856"],"add":52,"del":71,"cadd":52,"cdel":71,"files":1},{"repo":"external-organelle-project","hash":"06e9cff0e6c6fde408b7513e861cad2f8568e64e","ts":1772130790,"wall":"2026-02-26T13:33","msg":"Phase 1: Python control library for MVSilicon BP1048 audio organelle","body":"Protocol engine implementing the {0xA5, 0x5A} command protocol\nfrom the MVsB1_BT_Audio_SDK, with Bluetooth and USB HID transports,\nCLI tool, device discovery, and 47 passing tests.\n\n- protocol/frame.py: Frame encode/decode, HID report packing\n- protocol/commands.py: Hardware command builders (DAC, ADC, system)\n- protocol/effects.py: DSP effect builders (EQ, reverb, echo, 3D, bass, DRC)\n- transport/bluetooth.py: PipeWire + BlueZ + AVRCP control\n- transport/hid.py: USB HID 256-byte vendor report transport\n- device.py: High-level Organelle facade\n- discovery.py: USB + Bluetooth device enumeration\n- cli.py: organelle discover/status/volume/play/pause/mic-on/mic-off/probe-hid\n- scripts/probe_hid.py: Critical HID protocol probe (stock firmware result: no endpoints)\n- config/99-mvsilicon-organelle.rules: udev rule for HID access\n\nHID probe confirmed stock firmware exposes zero USB endpoints.\nCustom firmware required for USB data protocol (Phase 3).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":2012,"del":0,"cadd":1986,"cdel":0,"files":19},{"repo":"techbiont-framework","hash":"8e267a85e13472f7fb89d18cd9b7e3edaf7feddf","ts":1772130793,"wall":"2026-02-26T13:33","msg":"Add organizational philosophy and composite capability to standing orders","body":"- Long, parallelized, granular, modular time horizons\n- Core insight: the gap between potential and configured behavior is exploitable\n- Composite capability: operator + organelle = Chinese-reading techbiont\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ef7d306b0de888c4e2f110ce4232caebd455362e"],"add":10,"del":0,"cadd":10,"cdel":0,"files":1},{"repo":"external-organelle-project","hash":"8db1384a071e55ffb0bc139fe41004f85f8a83c0","ts":1772135955,"wall":"2026-02-26T14:59","msg":"Research: BP1048 deep dive and pivot to signal processing organelle","body":"Full capability audit of BP1048B2 silicon (50+ DSP effects, USB\nendpoints, flashing methods, procurement). Discovered stock firmware\nis a dead-end USB stub with no data interface and no wireless flash\npath. PC tool requires proprietary Andes JTAG probe.\n\nPivoted to general-purpose signal organelle: Pi 5 + LimeSDR USB\n(full-duplex, 100kHz-3.8GHz) + LoRa mesh + Pisound audio + GPS.\n$1,342 BOM within $1,500 budget. Full electromagnetic spectrum\naccess, custom protocol design via GNU Radio, no bootstrap problem.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["06e9cff0e6c6fde408b7513e861cad2f8568e64e"],"add":1754,"del":0,"cadd":1754,"cdel":0,"files":9},{"repo":"external-organelle-project","hash":"4610e347428d71e77cb83bae77220dfe531cbcb5","ts":1772140470,"wall":"2026-02-26T16:14","msg":"Research: soft robotics survey, exo organelle concept, three-organelle architecture","body":"Session expanded project scope from single signal organelle to three-organelle\ntechbiont architecture (signal, somatic, exo). Surveyed soft robotics approaches\nfor wearable exo organelle. Updated handoff with full session context.\n\nSoft robotics research saved to ~/research/ (outside this repo).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["8db1384a071e55ffb0bc139fe41004f85f8a83c0"],"add":52,"del":22,"cadd":52,"cdel":22,"files":1},{"repo":"mesnada","hash":"b115abbe665b17445853161b0a2e12c01171ce82","ts":1772153407,"wall":"2026-02-26T19:50","msg":"Fix game framing: strategic/tactical sandbox, not survival game","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["a840a7025172ae00ea8a13b6004d87c8d779c44a"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"mesnada","hash":"977ba3fbdca5042487576c8715680465af0e27a0","ts":1772154138,"wall":"2026-02-26T20:02","msg":"Update handoff: Phase A planned, ready to execute","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["b115abbe665b17445853161b0a2e12c01171ce82"],"add":53,"del":54,"cadd":53,"cdel":54,"files":1},{"repo":"mesnada","hash":"b8c8ae37cd6c738d8c8a776075633567527f1646","ts":1772158255,"wall":"2026-02-26T21:10","msg":"Remove hex placement system (Phase A Step 1)","body":"Map is now fixed at generation — no more player-placed tiles.\nRemoves place_hex action, get_valid_hex_placements, AP_PLACE_HEX,\nHEX_PLACED event, Place Hex button, ghost hex rendering, and AI\nhex placement logic. 17 files, -173 lines.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["977ba3fbdca5042487576c8715680465af0e27a0"],"add":12,"del":173,"cadd":12,"cdel":173,"files":17},{"repo":"mesnada","hash":"9f6fe4ef62c5016ea009393ec3f51bc5e9fb7491","ts":1772158306,"wall":"2026-02-26T21:11","msg":"Update handoff: Phase A Step 1 complete","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["b8c8ae37cd6c738d8c8a776075633567527f1646"],"add":29,"del":29,"cadd":29,"cdel":29,"files":1},{"repo":"mesnada","hash":"6674677a069b548c1a8c3f6b87ea34caf07504e2","ts":1772160854,"wall":"2026-02-26T21:54","msg":"Add settlement data model (Phase A Step 2)","body":"Settlement, Building, and tier config dataclasses with registry pattern.\nGameState extended with settlements field and fog-of-war serialization.\n15 new tests, all 290 pass.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["9f6fe4ef62c5016ea009393ec3f51bc5e9fb7491"],"add":268,"del":0,"cadd":268,"cdel":0,"files":4},{"repo":"mesnada","hash":"ac3273e594a1039c8650dd886cb7493f439eaa84","ts":1772160901,"wall":"2026-02-26T21:55","msg":"Update handoff: Phase A Step 2 complete","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["6674677a069b548c1a8c3f6b87ea34caf07504e2"],"add":17,"del":9,"cadd":17,"cdel":9,"files":1},{"repo":"mesnada","hash":"86d845d91bd0a09245eca946296997f60c6ba778","ts":1772162344,"wall":"2026-02-26T22:19","msg":"Complete Phase A: map gen, settlements, resources, spawning (Steps 3-11)","body":"- Hex resource data model with 8 resource types, terrain-based placement,\n  depletion/regeneration mechanics, and permanent depletion for stone/ore\n- Settlement placement algorithm with min-distance spacing, tier distribution,\n  and guaranteed Town-tier starting settlements per player\n- Hex resource initialization from terrain with adjacency checks (fish→water, ore→mountain)\n- Player spawning at settlements: 3 generic pawns with d6 starting gear roll\n- Map size presets (skirmish through world) with settlement count ranges\n- Frontend TS types for settlements, buildings, hex resources, gold\n- Settlement markers and resource dot indicators in PixiJS hex renderer\n- Pawn unit type and loadout for the new generic-pawn-plus-gear model\n- 43 new tests (333 total passing, 13 skipped)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ac3273e594a1039c8650dd886cb7493f439eaa84"],"add":912,"del":62,"cadd":887,"cdel":62,"files":13},{"repo":"mesnada","hash":"3fd2342f6b0fa52c18bafeb84db589b585b78663","ts":1772162441,"wall":"2026-02-26T22:20","msg":"Update handoff: Phase A complete","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["86d845d91bd0a09245eca946296997f60c6ba778"],"add":29,"del":40,"cadd":29,"cdel":40,"files":1},{"repo":"mesnada","hash":"fd11a3143c214d48c36ad45c1db115e0853b5f1b","ts":1772164118,"wall":"2026-02-26T22:48","msg":"Complete Phase B: building system, settlement UI, recruit/buy/sell","body":"Backend:\n- Inventory generation for plaza (recruit roster) and bodega (item shop)\n- Settlement actions: recruit_pawn, buy_item, sell_item with full validation\n- Building inventory refresh every 5 turns on end_turn\n- Populate inventories at game creation\n- Gold income enabled (territory + treasury)\n- Gear serialized in unit state for frontend\n\nFrontend:\n- SettlementPanel component with plaza recruitment and bodega trading\n- Settlement mode in game state machine\n- Click settlement hex with own pawn → opens settlement panel\n- Recruit, buy, sell action dispatchers wired through API\n\nTests: 24 new tests (357 total, 13 skipped)","parents":["3fd2342f6b0fa52c18bafeb84db589b585b78663"],"add":984,"del":7,"cadd":984,"cdel":7,"files":14},{"repo":"mesnada","hash":"4a2a5d74a2fe6601791d16deabcdf8d53a1acb9c","ts":1772164156,"wall":"2026-02-26T22:49","msg":"Update handoff: Phase B complete","body":"","parents":["fd11a3143c214d48c36ad45c1db115e0853b5f1b"],"add":21,"del":38,"cadd":21,"cdel":38,"files":1},{"repo":"mesnada","hash":"f6386e82d34c146501cf0da6df8f3b0360fa4e0f","ts":1772165849,"wall":"2026-02-26T23:17","msg":"Complete Phase C: inventory management, equip/unequip system, PawnPanel UI","body":"- Add player_inventory to GameState for unequipped items\n- New equip/unequip actions with rank validation\n- Buy items now go to player inventory (not directly on pawn)\n- GET /api/items endpoint for item definitions\n- PawnPanel component: view loadout, equip/unequip gear, see stats\n- HUD shows equipped gear on selected unit\n- 13 new tests (370 total, 0 failures)\n- Frontend typecheck clean\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["4a2a5d74a2fe6601791d16deabcdf8d53a1acb9c"],"add":608,"del":13,"cadd":608,"cdel":13,"files":14},{"repo":"mesnada","hash":"020333eaf27793bc1b8d848def7639277021c149","ts":1772165953,"wall":"2026-02-26T23:19","msg":"Update handoff: Phase C complete","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["f6386e82d34c146501cf0da6df8f3b0360fa4e0f"],"add":22,"del":22,"cadd":22,"cdel":22,"files":1},{"repo":"mesnada","hash":"77032f210296d29fcdc431f609c3dc43a80e823d","ts":1772197975,"wall":"2026-02-27T08:12","msg":"Remove legacy 13-unit-type system, pawn-only model","body":"Delete all legacy unit types (raider, slinger, tracker, etc.), their\ndata files, sprites, loadout presets, pack system, and spawn action.\nThe game now uses only the pawn+gear system where unit identity emerges\nfrom equipped gear rather than fixed type IDs.\n\nBackend: remove spawn action, legacy API endpoints (/units, /packs,\nselect-packs), AI spawn logic, add max_hp to Unit and serialization.\nFrontend: remove SpawnPanel, pack selection, legacy type lookups,\nsimplify units.ts/spriteLoader/HUD/CombatPreview/EventLog.\nTests: delete legacy-specific tests, update remaining to use pawn.\n\n261 tests pass, 52 fail (need gear-granted skills wired in tests).\nFrontend typechecks clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["020333eaf27793bc1b8d848def7639277021c149"],"add":319,"del":2463,"cadd":294,"cdel":2050,"files":111},{"repo":"mesnada","hash":"444e8fda7d03667d5522b40d3893e6d0a8ed3a22","ts":1772200826,"wall":"2026-02-27T09:00","msg":"Purge legacy 13-class references, adopt gear/skill/designation language","body":"Remove 52 broken tests that depended on deleted unit types and rewrite\nall comments, docstrings, variable names, and skip reasons to use the\npawn+gear model vocabulary:\n- Gear actions (fortify, sap, bridge, siege) reference the item/skill\n- Learned skills (heal, confuse, scout, stealth, plunder, ambush)\n- Designated commander replaces commander-as-unit-type\n- Stealth is now a general learnable skill, not commander-locked\n\nProduction: 8 backend files + 1 frontend file updated\nTests: 7 files cleaned, 1 deleted (test_counter_attacks.py)\n261 passing, 0 failing, 11 skipped","parents":["77032f210296d29fcdc431f609c3dc43a80e823d"],"add":84,"del":942,"cadd":84,"cdel":942,"files":21},{"repo":"mesnada","hash":"6ef4a170dd83971a36540ec0d70ba948fc518fd9","ts":1772200871,"wall":"2026-02-27T09:01","msg":"Update handoff: legacy cleanup complete, document known gaps","body":"","parents":["444e8fda7d03667d5522b40d3893e6d0a8ed3a22"],"add":44,"del":19,"cadd":44,"cdel":19,"files":1},{"repo":"mesnada","hash":"bd91303855a13d019e03534bcdb771f24182f1af","ts":1772203189,"wall":"2026-02-27T09:39","msg":"Replace emoji unit rendering with gear-based pixel art sprites","body":"Add 104 pixel art sprites and a static lookup table (spriteMap.ts) that\nmaps gear combinations to sprite filenames. Units now render their\nequipped loadout visually instead of showing a generic sword emoji.\n\nFallback chain: exact gear match → armor-only → weapon-only → Peasant.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["6ef4a170dd83971a36540ec0d70ba948fc518fd9"],"add":221,"del":20,"cadd":221,"cdel":20,"files":108},{"repo":"mesnada","hash":"d659d13763e79283b07b1b39720f63ea7b6199b2","ts":1772203357,"wall":"2026-02-27T09:42","msg":"Update handoff: gear-based sprite rendering complete","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["bd91303855a13d019e03534bcdb771f24182f1af"],"add":24,"del":38,"cadd":24,"cdel":38,"files":1},{"repo":"mesnada","hash":"ae4aa5a654eaaa49866e38c9e54965df7884a1a6","ts":1772206556,"wall":"2026-02-27T10:35","msg":"Fix gear→skill grants, fog-of-war event filtering, and ability UI","body":"- Serialize effective_skills to frontend via state.to_dict()\n- Fix HUD ability buttons: filter by unit skills instead of blanket skip\n- Fix grants_skill on 6 items (heavy, weak_melee, stealth, remove phantom)\n- Register 27 missing event types in fog-of-war filter\n- Add 19 missing event types to frontend GameEventType + EventLog\n- Derive unit display name from gear in HUD\n- Remove dead stealth param from _effective_attack()\n- Add 32 new tests for gear/skill/fog-of-war coverage (293 total)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d659d13763e79283b07b1b39720f63ea7b6199b2"],"add":541,"del":20,"cadd":535,"cdel":14,"files":14},{"repo":"mesnada","hash":"751457aa8d93ac64dda076a5ca11754ee6fd614c","ts":1772206646,"wall":"2026-02-27T10:37","msg":"Update handoff: gap remediation complete, 293 tests passing","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["ae4aa5a654eaaa49866e38c9e54965df7884a1a6"],"add":29,"del":16,"cadd":29,"cdel":16,"files":1},{"repo":"mesnada","hash":"b0181c4963b3f554e9bbb4e3cc866ef4348ddc2a","ts":1772209069,"wall":"2026-02-27T11:17","msg":"Implement Phase D: hex resource gathering and selling","body":"Backend:\n- Add resource_bag to Unit for carrying gathered resources\n- Implement gather_resource action (2 AP, yields 1 unit)\n- Implement sell_resource action (sell all at bodega for gold)\n- Hook resource regeneration into end_turn\n- Add GATHER/SELL_RESOURCE event types + fog-of-war registration\n- Serialize resource_bag in state.to_dict()\n\nFrontend:\n- Hex resource display with quantities on selected hex terrain info\n- Gather buttons per resource type (when unit on hex with resources)\n- Resource bag display on selected unit info\n- Sell Resources section in SettlementPanel bodega\n- Event log formatting for GATHER/SELL_RESOURCE events\n- ActionPayload + GameEventType updates\n\nTests: 20 new tests (gather, sell, regen, edge cases) — 313 total\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["751457aa8d93ac64dda076a5ca11754ee6fd614c"],"add":510,"del":1,"cadd":510,"cdel":1,"files":15},{"repo":"mesnada","hash":"3f6b189e489fa79c84b184e470b0e7f6bbfb07b0","ts":1772209153,"wall":"2026-02-27T11:19","msg":"Update handoff: Phase D complete, 313 tests passing","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["b0181c4963b3f554e9bbb4e3cc866ef4348ddc2a"],"add":28,"del":23,"cadd":28,"cdel":23,"files":1},{"repo":"mesnada","hash":"4db4025c1a43c14f4e475304b11e7bdcccb455f9","ts":1772212685,"wall":"2026-02-27T12:18","msg":"UI overhaul: fullscreen map, cursor-anchored tooltips, settlement modal + Phase D completion","body":"Backend:\n- Add pawn name field (editable, 32 char cap) with rename_unit action\n- Pre-positioning AP discount: stationary units gather for 1 AP instead of 2\n- Specialist gear bonus: units with gather_bonus skill yield 2 instead of 1\n- 5 new specialist gathering items (sickle, foresters_axe, fishing_spear, pickaxe, herbalists_pouch)\n- 6 new tests for pre-positioning, specialist bonus, and unit naming\n\nFrontend:\n- Remove sidebar layout — GameBoard now fills 100vw x 100vh\n- MinimalHUD: compact top-left overlay (turn, AP, gold, buttons)\n- HexTooltip: cursor-anchored tooltip near clicked hex with unit info, editable name, actions, resources, garrison\n- SettlementModal: full-screen overlay with tier-matched background art (6 tiers)\n- EventLog: hidden by default, toggled via 'L' hotkey or icon button\n- GameBoard passes screen-space hex coordinates on click\n- Settlement images copied to frontend/public/settlements/\n\n319 backend tests passing, clean TypeScript typecheck.","parents":["3f6b189e489fa79c84b184e470b0e7f6bbfb07b0"],"add":1109,"del":76,"cadd":1014,"cdel":76,"files":25},{"repo":"mesnada","hash":"9f3f751cd5a13ca910432420f42662e4b737a340","ts":1772212927,"wall":"2026-02-27T12:22","msg":"Update handoff: UI overhaul complete, 319 tests passing","body":"","parents":["4db4025c1a43c14f4e475304b11e7bdcccb455f9"],"add":38,"del":27,"cadd":38,"cdel":27,"files":1},{"repo":"mesnada","hash":"384728b402da8a592e6af5056c744aa33937639b","ts":1772213162,"wall":"2026-02-27T12:26","msg":"Hex click disambiguation: tooltip shows all interactable entities","body":"Remove auto-settlement-open from selectHex — clicking a hex with both\na unit and settlement now shows the tooltip with both, letting the\nplayer choose. Settlement info block always visible on settlement hexes\nwith an \"Enter Settlement\" button for owned units.","parents":["9f3f751cd5a13ca910432420f42662e4b737a340"],"add":17,"del":20,"cadd":17,"cdel":20,"files":2},{"repo":"mesnada","hash":"cdedbeb75ff2519182c83a0eee6ff62ba321cfa1","ts":1772213323,"wall":"2026-02-27T12:28","msg":"Make settlement block in tooltip clickable to enter settlement","body":"Entire settlement row is now a click target when own unit is present,\nwith \"Enter →\" hint. No longer requires canAct (dice rolled) — player\ncan browse settlement anytime with a unit on the hex.","parents":["384728b402da8a592e6af5056c744aa33937639b"],"add":23,"del":15,"cadd":23,"cdel":15,"files":1},{"repo":"mesnada","hash":"b3ced2db0cb6a0870748a485bca3b6689e334c65","ts":1772213816,"wall":"2026-02-27T12:36","msg":"Remove passive gold income, AP cap now scales with troop count","body":"Gold only comes from trade (selling resources/items at bodegas).\nRemoved _process_gold_income from end_turn, removed GOLD_PER_TERRITORY_HEX\nand TREASURY_GOLD_PER_TURN constants.\n\nAP cap formula: AP_CAP_BASE (10) + troops * AP_PER_TROOP (3).\nTroops = field units + garrison units. Replaces treasury-based AP cap.\n\n322 tests passing, 4 skipped.","parents":["cdedbeb75ff2519182c83a0eee6ff62ba321cfa1"],"add":38,"del":148,"cadd":38,"cdel":148,"files":5},{"repo":"mesnada","hash":"16daeeba3fdd6a76662b10f3d8bc172258415413","ts":1772213988,"wall":"2026-02-27T12:39","msg":"Update handoff: economy changes, 322 tests passing","body":"","parents":["b3ced2db0cb6a0870748a485bca3b6689e334c65"],"add":7,"del":2,"cadd":7,"cdel":2,"files":1},{"repo":"mesnada","hash":"ec42da5882fa57deff3f3e191f7109995376fcc1","ts":1772216052,"wall":"2026-02-27T13:14","msg":"Codebase audit: EventType enum, routing validation, dead code cleanup","body":"- Add 4 missing EventType entries (BURNOUT_DAMAGE, BURNOUT_DEATH,\n  TERRORIZE, MIND_SIGHT) and fog-of-war coordinate mappings\n- Migrate all 73 GameEvent raw strings to use EventType enum\n- Add routing unit validation to move, attack, defend, ability,\n  mount, and dismount actions (+6 new tests, 328 total)\n- Create missing skill JSONs: gather_bonus, bridge, sap,\n  upgrade_treasury\n- Delete orphaned components: HUD.tsx, KeyboardChart.tsx,\n  SettlementPanel.tsx\n- Remove unused stealth_ap_remaining field, combat no-op line\n- Add tool items to spriteMap SUPPORT set\n- Document tag classification intent and treasury dormancy","parents":["16daeeba3fdd6a76662b10f3d8bc172258415413"],"add":301,"del":932,"cadd":264,"cdel":932,"files":23},{"repo":"mesnada","hash":"697e0996fc972bb48f89b6ce2fd381e35d5bf86b","ts":1772216133,"wall":"2026-02-27T13:15","msg":"Update handoff: audit fixes complete, 328 tests passing","body":"","parents":["ec42da5882fa57deff3f3e191f7109995376fcc1"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"mesnada","hash":"4acff742e1f83bcedf498317eccdb5c702fdd418","ts":1772217970,"wall":"2026-02-27T13:46","msg":"Settlement ownership, capture, and garrison overhaul","body":"Settlements now have an owner field (None=neutral, int=player).\nStarting settlements belong to their player; neutral settlements\nspawn NPC garrison units (player 0) scaled by tier. Moving onto\nan undefended settlement captures it; killing all defenders does\nthe same. Garrison entry now works at owned settlements (no fort\nrequired) and is blocked at enemy/neutral ones. Recruitment\nrequires settlement ownership. NPC units excluded from win\ncondition and territory computation. 16 new tests, 344 total.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["697e0996fc972bb48f89b6ce2fd381e35d5bf86b"],"add":334,"del":15,"cadd":334,"cdel":15,"files":12},{"repo":"mesnada","hash":"aaa45d715e79134dd227234d462a338cdc3df77c","ts":1772218067,"wall":"2026-02-27T13:47","msg":"Update handoff: settlement ownership done, 344 tests passing","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["4acff742e1f83bcedf498317eccdb5c702fdd418"],"add":29,"del":31,"cadd":29,"cdel":31,"files":1},{"repo":"mesnada","hash":"a247d616fb8ff4e459f5e9def3b69a590d34e462","ts":1772231628,"wall":"2026-02-27T17:33","msg":"Unit accessor refactor: route all state.units access through unit_access.py","body":"Pure refactor — introduces unit_access.py with helper functions for unit\nlookup, filtering, and mutation. All game logic and tests updated to use\naccessors instead of direct state.units dict access. Prepares for D2\nhex stacking storage flip. 344 tests passing.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["aaa45d715e79134dd227234d462a338cdc3df77c"],"add":397,"del":295,"cadd":397,"cdel":295,"files":33},{"repo":"mesnada","hash":"cbaba36fc168c3e8453c891aae2f813a3da17aae","ts":1772231679,"wall":"2026-02-27T17:34","msg":"Update handoff, master roadmap, and D2 stacking plan","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["a247d616fb8ff4e459f5e9def3b69a590d34e462"],"add":257,"del":152,"cadd":257,"cdel":152,"files":3},{"repo":"azuran-knowledge-ark","hash":"b280f5d82af99c901faf1bc6fd7a98e143120afc","ts":1772243592,"wall":"2026-02-27T20:53","msg":"Initial repo setup for Azuran Knowledge Ark","body":"Portable offline knowledge library served from Ventoy USB via Caddy + kiwix-serve.\nIncludes Caddyfile, launcher script, and architecture research.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":361,"del":0,"cadd":308,"cdel":0,"files":7},{"repo":"azuran-knowledge-ark","hash":"367ef1aaf54cf286747c2487088a011d51d5a7f5","ts":1772243683,"wall":"2026-02-27T20:54","msg":"Add Three.js portal research and update handoff","body":"Documents interactive polyhedron design: cube in diamond orientation,\nraycasting, bloom glow, offline Three.js loading via import maps.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["b280f5d82af99c901faf1bc6fd7a98e143120afc"],"add":193,"del":20,"cadd":193,"cdel":20,"files":2},{"repo":"azuran-knowledge-ark","hash":"bd764bf1989fa247c6971acb35e6b46a4111fed1","ts":1772245678,"wall":"2026-02-27T21:27","msg":"Build armillary sphere portal with violet energy core","body":"Interactive orrery: 6 torus rings at different tilts representing content\ncategories (Wikipedia, LibreTexts, DevDocs, Wikibooks, iFixit, Search).\nNoise-driven energy sphere at center with swirling violet veins.\nBloom post-processing, particle flame, star field, canvas-textured rings.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["367ef1aaf54cf286747c2487088a011d51d5a7f5"],"add":4719,"del":0,"cadd":4719,"cdel":0,"files":16},{"repo":"azuran-knowledge-ark","hash":"6b1cb32833774b146233c8f202a3f650bf8befcc","ts":1772246116,"wall":"2026-02-27T21:35","msg":"Fix Caddyfile routing and add kiwix-serve readiness check","body":"Portal now properly serves all static files via catch-all handle block.\nstart.sh waits for kiwix-serve to be ready before starting Caddy.\nDeleted corrupt geography ZIM from Ventoy drive.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["bd764bf1989fa247c6971acb35e6b46a4111fed1"],"add":25,"del":16,"cadd":16,"cdel":2,"files":2},{"repo":"azuran-knowledge-ark","hash":"7482d891880f9290487ad28d6597570e078a18b5","ts":1772249645,"wall":"2026-02-27T22:34","msg":"Add interactive category panels to armillary sphere rings","body":"Each ring now opens a category-specific panel listing individual ZIM\narchives with direct viewer links. Fetches kiwix OPDS catalog on load,\ngroups entries by prefix, and extracts full content IDs (with flavor+date)\nfor correct deep linking via /library/viewer#<contentId>/. SEARCH ring\nopens client-side archive filter. Restores --urlRootLocation /library\nfor correct viewer URL generation.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["6b1cb32833774b146233c8f202a3f650bf8befcc"],"add":353,"del":9,"cadd":350,"cdel":8,"files":5},{"repo":"azuran-knowledge-ark","hash":"cd8027a156dcdd07c7710e7c50540bd716d0c287","ts":1772249708,"wall":"2026-02-27T22:35","msg":"Update handoff for category panel session","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["7482d891880f9290487ad28d6597570e078a18b5"],"add":37,"del":23,"cadd":37,"cdel":23,"files":1},{"repo":"azuran-knowledge-ark","hash":"d2906d5c20432a6ddc5550c3fb184513000872f5","ts":1772251248,"wall":"2026-02-27T23:00","msg":"Make Knowledge Ark fully portable — zero installation USB deployment","body":"Add cross-platform binary setup (setup.sh) downloading kiwix-serve\nand Caddy for Linux x86_64/ARM64, macOS x86_64/ARM64, Windows x86_64.\nRewrite start.sh with OS/arch detection and exFAT chmod workaround\n(copies binaries to /tmp since exFAT strips execute bits). Add Windows\nlauncher (start.bat), USB deployment script (deploy.sh), and plain\ntext README.txt for drive root. Everything runs from the USB drive\nwith zero host installation.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["cd8027a156dcdd07c7710e7c50540bd716d0c287"],"add":487,"del":93,"cadd":331,"cdel":89,"files":7},{"repo":"azuran-knowledge-ark","hash":"54898636499a70bb663531c1db0f3eb6244639b3","ts":1772251291,"wall":"2026-02-27T23:01","msg":"Update handoff for portable USB deployment session","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["d2906d5c20432a6ddc5550c3fb184513000872f5"],"add":34,"del":32,"cadd":34,"cdel":32,"files":1},{"repo":"azuran-knowledge-ark","hash":"0f46e92ffa0bafe19fd3d13762fee328945613fd","ts":1772256902,"wall":"2026-02-28T00:35","msg":"Add manifest-driven generative portal and content inventory","body":"Introduces manifest.json as the universal data contract for the Ark.\ngenerate-manifest.sh walks any drive's content (ZIMs, books, ISOs),\ncomputes SHA-256 hashes with caching, and produces a manifest that\nthe portal reads to dynamically generate armillary sphere rings.\n\n- generate-manifest.sh: content inventory with hash caching, --commercial flag\n- Portal: dynamic rings from manifest (falls back to OPDS), Books + Systems rings\n- HUD: ark type badge, archive count, drive usage, update date\n- NC content panel: download links for LibreTexts/iFixit on commercial builds\n- Caddyfile: serves /manifest.json from drive root\n- start.sh: generates manifest on startup\n- deploy.sh: includes generate-manifest.sh in deployment","parents":["54898636499a70bb663531c1db0f3eb6244639b3"],"add":808,"del":104,"cadd":802,"cdel":104,"files":7},{"repo":"azuran-knowledge-ark","hash":"25b9642ddfa903cf8c381870fc3a8260e19664a8","ts":1772257052,"wall":"2026-02-28T00:37","msg":"Update handoff and add architecture spec for sneakernet platform","body":"","parents":["0f46e92ffa0bafe19fd3d13762fee328945613fd"],"add":399,"del":41,"cadd":399,"cdel":41,"files":2},{"repo":"azuran-knowledge-ark","hash":"ae176904b79d29863b2ad757da51d2a0862166fe","ts":1772260416,"wall":"2026-02-28T01:33","msg":"Add build pipeline and scrolling VT323 ring labels","body":"build.sh: 4-stage build pipeline (validate → deploy → manifest → verify)\nwith spot-check SHA-256 hash verification against manifest.\n\nPortal: ring labels now use VT323 terminal font (bundled woff2) and\nscroll slowly along the ring surface via animated UV offset.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["25b9642ddfa903cf8c381870fc3a8260e19664a8"],"add":269,"del":4,"cadd":269,"cdel":4,"files":4},{"repo":"azuran-knowledge-ark","hash":"9594dab176098e1c8f8e926efc4ce4666b9a8fbc","ts":1772261979,"wall":"2026-02-28T01:59","msg":"Add dark violet Ventoy boot theme with VT323 fonts","body":"GRUB2 theme matching the portal aesthetic: deep violet gradient\nbackground, VT323 terminal font at 12/14/20pt, violet selection\nhighlight. Build and deploy scripts updated to deploy theme to\nventoy/theme/ark/ and merge ventoy.json config.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ae176904b79d29863b2ad757da51d2a0862166fe"],"add":125,"del":0,"cadd":61,"cdel":0,"files":17},{"repo":"azuran-knowledge-ark","hash":"9eb2ab187c6475cf819e55ae55bddfd45210b537","ts":1772267670,"wall":"2026-02-28T03:34","msg":"Add mesh server, content downloader, and Alpine kiosk ISO","body":"Implements ark-mesh (Go mDNS sync server), ark-fetch.sh (CLI content\ndownloader), and portal download panel for opportunistic online content\nacquisition from the Kiwix OPDS catalog. Adds Alpine Linux kiosk ISO\nbuilder for Ventoy-bootable offline browsing.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["9594dab176098e1c8f8e926efc4ce4666b9a8fbc"],"add":3179,"del":43,"cadd":2793,"cdel":42,"files":29},{"repo":"azuran-knowledge-ark","hash":"1530e4457ac5e25c503c7da89f79322267e231f2","ts":1772267853,"wall":"2026-02-28T03:37","msg":"Update handoff for mesh server and content downloader session","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["9eb2ab187c6475cf819e55ae55bddfd45210b537"],"add":52,"del":39,"cadd":52,"cdel":39,"files":1},{"repo":"azuran-knowledge-ark","hash":"20c2bbf76bbcdd08c4ed1b66a364ae74c1f93ecf","ts":1772315350,"wall":"2026-02-28T16:49","msg":"Add desktop launcher, fetch endpoint hardening, and ZIM crash recovery","body":"- Desktop launcher: ark-icon.png + .desktop file, auto-installed to\n  ~/.local/share/applications on first run via start.sh\n- Mesh server: localhost-only guard and host allowlist on /ark/fetch\n  endpoint to prevent SSRF\n- start.sh: ZIM magic number validation skips corrupt files before\n  passing to kiwix-serve; crash recovery loop retries up to 3 times\n  excluding bad ZIMs identified from kiwix-serve stderr","parents":["1530e4457ac5e25c503c7da89f79322267e231f2"],"add":144,"del":9,"cadd":135,"cdel":9,"files":5},{"repo":"musico","hash":"7810751eb0c63cac931e1547ce3d98490b3bded7","ts":1772326409,"wall":"2026-02-28T19:53","msg":"Musico: Phase 1-3 complete — polyphonic synth with effects and modal XY controller","body":"Physical-input music instrument using Logitech G305 mouse as modal XY controller\nand Akai MPK Mini 3 for keys/knobs/pads. No DAW paradigm.\n\nPhase 1: cpal audio output, midir MPK connection, egui XY pad, scale quantization\nPhase 2: 8-voice polyphony with ADSR, waveform selection, filter with resonance,\n         MPK knob sync to UI, voice stealing\nPhase 3: Schroeder reverb + feedback delay, 5 mouse modes (Play/Shape/Mix/FX/Seq),\n         HUD controls legend, mute/bypass, mode-colored UI\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":6405,"del":0,"cadd":1705,"cdel":0,"files":18},{"repo":"musico","hash":"6619fd9742f537a644a60cc536719355fe595867","ts":1772326488,"wall":"2026-02-28T19:54","msg":"Add session handoff for Phase 1-3","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["7810751eb0c63cac931e1547ce3d98490b3bded7"],"add":79,"del":0,"cadd":79,"cdel":0,"files":1},{"repo":"musico","hash":"0d24f68695f7782d8db429b6b4bf4d14b6b24ae3","ts":1772332067,"wall":"2026-02-28T21:27","msg":"Phase 4a: Dot sequencer with stretchable dots and playhead","body":"Implement step sequencer in Sequence mode where XY pad becomes a piano roll\n(X=time, Y=pitch). Pinned dots are steps played by a sweeping playhead.\n\n- Sequencer struct with BPM clock, tick-based NoteOn/NoteOff event generation\n- Playhead rendering (glowing red line sweeping at tempo)\n- Dot duration field (0.25-8.0 steps) with capsule bar rendering\n- Right-edge stretch-drag gesture for adjusting dot duration\n- Grid snap toggle (N key) with step divisions + pitch lines\n- Space play/stop, +/- tempo, scroll for loop length (8/16/32)\n- Momentary audition drag in Sequence mode\n- Sequencer persists across mode switches\n- Wire joystick (PitchBend/ModWheel) messages through ControlMsg\n\nCloses partial #1","parents":["6619fd9742f537a644a60cc536719355fe595867"],"add":948,"del":64,"cadd":948,"cdel":64,"files":7},{"repo":"musico","hash":"97e5d71d3974fcfea160ddf2b907953d8d58afbe","ts":1772332153,"wall":"2026-02-28T21:29","msg":"Update handoff for Phase 4a sequencer completion","body":"","parents":["0d24f68695f7782d8db429b6b4bf4d14b6b24ae3"],"add":25,"del":38,"cadd":25,"cdel":38,"files":1},{"repo":"musico","hash":"d586066f236a2314b9491e5bd910118c48d14399","ts":1772337223,"wall":"2026-02-28T22:53","msg":"Add Unix socket command interface for programmatic control","body":"New /tmp/musico.sock listener accepts text commands (note_on, note_off,\nset, waveform, mute, pin, clear, bpm, play, stop, scale, octave) with\nok/err responses. Two dispatch paths: audio-direct via existing ControlMsg\nchannel, UI-side via new UiCmd channel drained in MusicoApp::update().\nAlso fixes Shape mode to map X→Cutoff, Y→Sustain (was Attack/Release).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["97e5d71d3974fcfea160ddf2b907953d8d58afbe"],"add":265,"del":15,"cadd":265,"cdel":15,"files":5},{"repo":"musico","hash":"80428620d699e462f73a2b00d7ce7fdcb744b112","ts":1772342244,"wall":"2026-03-01T00:17","msg":"Update handoff for Phase 4c socket command interface","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["d586066f236a2314b9491e5bd910118c48d14399"],"add":18,"del":19,"cadd":18,"cdel":19,"files":1},{"repo":"symbiont.systems","hash":"c7ab7a2bb4e0bfb605cc71575f8e747d7004963b","ts":1772345367,"wall":"2026-03-01T01:09","msg":"Add Three.js hex sphere prototype with GPU-driven animation","body":"Goldberg polyhedron (hexasphere.js) generates 642 hex/pent tiles on a\nsphere. All color (eukaryotic biome noise) and height extrusion computed\nin GLSL vertex/fragment shaders — zero per-frame CPU vertex work.\n\nIncludes armillary nav rings, spore particles, bloom post-processing,\nhover raycasting, and reduced-motion support.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["6432e56d120e2e202d197f9b78fb96b468e60203"],"add":5156,"del":0,"cadd":5156,"cdel":0,"files":16},{"repo":"symbiont.systems","hash":"c3c4a51abaf44287eafa354f14b5ed3d4ff1a798","ts":1772345459,"wall":"2026-03-01T01:10","msg":"Update handoff: hex sphere prototype session complete","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["c7ab7a2bb4e0bfb605cc71575f8e747d7004963b"],"add":57,"del":0,"cadd":57,"cdel":0,"files":1},{"repo":"symbiont.systems","hash":"c888aff4573a61586d01133c9abbb698dfd8b00a","ts":1772350360,"wall":"2026-03-01T02:32","msg":"Hex sphere visual overhaul: jeweled self-lit tiles, solid armillary rings","body":"- Full prism geometry with boundary scaling (1.3x) to eliminate gaps\n- 201-color eukaryotic palette (67 per kingdom) with even lightness spread\n- Self-illuminated fragment shader (no external lighting)\n- Solid armillary rings with violet glow, Space Grotesk labels\n- Rings: slow orbital precession, ark-style steady rotation, draggable\n- Dark inner backing sphere for opacity\n- Bloom tuned (0.58/0.58/0.32), 2700 spore particles\n- Subdivision 35 (~12K tiles), ring radii pushed out (5.5-7.0)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c3c4a51abaf44287eafa354f14b5ed3d4ff1a798"],"add":176,"del":81,"cadd":176,"cdel":81,"files":1},{"repo":"symbiont.systems","hash":"501341f58fc99c8843c784a0b855e063f8cc1d86","ts":1772383546,"wall":"2026-03-01T11:45","msg":"Add navigation cards to hex sphere; fix ring glow to per-ring colors","body":"Replace hardcoded violet emissive on armillary rings with each ring's\nown color (gold/teal/magenta/blue). Add two-stage interaction: hover\nshows projected preview card near ring (pauses ring rotation), click\nopens full-page glassmorphism overlay with site content, corner\nbrackets, and accent bar. Close via X, Escape, or backdrop click.\nRespects prefers-reduced-motion.","parents":["c888aff4573a61586d01133c9abbb698dfd8b00a"],"add":407,"del":23,"cadd":407,"cdel":23,"files":1},{"repo":"symbiont.systems","hash":"e7b5a3fa1dc198936f909914f86413b568482de6","ts":1772389060,"wall":"2026-03-01T13:17","msg":"Add Mission Control dashboard; update handoff","body":"Dashboard (dev/dashboard.html) provides a split-pane control surface\nfor tuning all hex sphere parameters (geometry, camera, bloom, rings,\nspores, colors, shaders) with live preview, plus a copy editor for\nsite content and a publish/deploy pipeline stub.\n\nPersistence via localStorage auto-save with JSON export/import.\ngenerateProductionHTML() currently emits HTML/CSS shell only — full\nproduction bake (Three.js + shaders + interaction) is next.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["501341f58fc99c8843c784a0b855e063f8cc1d86"],"add":1783,"del":27,"cadd":1783,"cdel":27,"files":2},{"repo":"symbiont.systems","hash":"7dbbd51f19f866fa6b8a76d54ce3e7cbc98f6f83","ts":1772389696,"wall":"2026-03-01T13:28","msg":"Complete generateProductionHTML() with full Three.js scene","body":"The publish function now emits a complete standalone page with all\nThree.js scene code, GLSL shaders, hex sphere geometry builder,\narmillary rings, spore particles, bloom compositor, card interaction\n(preview tooltips + full-page overlays + close/ESC), raycasting,\nanimation loop, and motion toggle. All values baked from CONFIG.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["e7b5a3fa1dc198936f909914f86413b568482de6"],"add":604,"del":3,"cadd":604,"cdel":3,"files":1},{"repo":"symbiont.systems","hash":"f7632ebc214c26aa730c999449dcbb49192a822f","ts":1772397717,"wall":"2026-03-01T15:41","msg":"Add Armillary framework research; update handoff for infrastructure","body":"Research docs:\n- armillary-framework-research.md: card type system, productization\n  layers, implementation sequence (deferred post-launch)\n- margin-armillary-bridge.md: Margin Block Model → Armillary Card\n  System mapping, what transfers and what doesn't\n\nInfrastructure decisions: Hetzner Helsinki, Cloudflare DNS/registrar,\nvanilla JS stack stays. Server created, DNS migrating from GoDaddy.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["7dbbd51f19f866fa6b8a76d54ce3e7cbc98f6f83"],"add":282,"del":52,"cadd":282,"cdel":52,"files":3},{"repo":"symbiont.systems","hash":"264d71c3bd69a073bd4861a4d5191c94c1266991","ts":1772410376,"wall":"2026-03-01T19:12","msg":"Deploy hex sphere to production; add webhook auto-deploy system","body":"- Replace old 2D canvas site with Three.js hex sphere in site/index.html\n- Add deploy webhook (Python/systemd) for one-click publish from dashboard\n- Add Caddy reverse proxy config with basicauth-protected dashboard\n- Update dashboard Deploy tab: webhook publish, token input, password change\n- Hide debug info overlay from production site\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["f7632ebc214c26aa730c999449dcbb49192a822f"],"add":5794,"del":1843,"cadd":5780,"cdel":1843,"files":20},{"repo":"symbiont.systems","hash":"9018f13152588f5c53688d4f61a6e1c6f4949e4d","ts":1772410468,"wall":"2026-03-01T19:14","msg":"Update handoff: hex sphere deployed, webhook auto-deploy complete","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["264d71c3bd69a073bd4861a4d5191c94c1266991"],"add":43,"del":38,"cadd":43,"cdel":38,"files":1},{"repo":"symbiont.systems","hash":"831f22f2c6f3cea3711efe632cf014c639b02d80","ts":1772411956,"wall":"2026-03-01T19:39","msg":"Add Open Graph social preview: hex sphere image + meta tags","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["9018f13152588f5c53688d4f61a6e1c6f4949e4d"],"add":19,"del":1,"cadd":19,"cdel":1,"files":2},{"repo":"rowbots","hash":"65535421655381e11e0058c914b4f516d0c028a7","ts":1772412555,"wall":"2026-03-01T19:49","msg":"Initialize Row-bots: autonomous agent architecture plan","body":"Four planned agents (Scout, Ranger, Rootstock, Spore) with MESO-derived\nauthority model, persona system, and phased implementation roadmap.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":146,"del":0,"cadd":146,"cdel":0,"files":2},{"repo":"mesnada","hash":"7d18d26e2389f457214160afd325a227d4300f8c","ts":1772483255,"wall":"2026-03-02T15:27","msg":"D2: Flip unit storage to dict[Hex, list[Unit]] for hex stacking","body":"Storage type changed from single-unit to list-based with HEX_STACK_LIMIT=3.\nAll 7 unit_access.py helpers rewritten (append/remove/flatten semantics).\n14 test files updated — constructor calls wrapped, raw iteration replaced.\n344 tests passing, 4 skipped.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["cbaba36fc168c3e8453c891aae2f813a3da17aae"],"add":97,"del":77,"cadd":97,"cdel":77,"files":14},{"repo":"mesnada","hash":"781be8ae5b77a4f4f3b9195a7b61872ebadccfb3","ts":1772483500,"wall":"2026-03-02T15:31","msg":"Update handoff: D2 storage flip done, 344 tests passing","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["7d18d26e2389f457214160afd325a227d4300f8c"],"add":24,"del":28,"cadd":24,"cdel":28,"files":1},{"repo":"mesnada","hash":"47f502f50ee3b996bc35283aee7cb4986a003649","ts":1772485612,"wall":"2026-03-02T16:06","msg":"D3: Field stacking in movement — units stack on hexes instead of auto-garrisoning","body":"Movement into friendly-occupied hexes now field-stacks (up to HEX_STACK_LIMIT=3\non field, SETTLEMENT_STACK_LIMIT=10 at settlements). Garrison is no longer\nauto-entered on move — it remains a separate explicit mechanic for owned\nsettlements/forts only.\n\n- Add SETTLEMENT_STACK_LIMIT, get_stack_limit(), can_stack_at() helpers\n- Rewrite move_unit() to allow friendly hex stacking\n- Update ungarrison, routing, dismount, mount release, garrison spill\n- Recruit at settlement field-stacks instead of auto-garrisoning\n- 345 tests passing","parents":["781be8ae5b77a4f4f3b9195a7b61872ebadccfb3"],"add":125,"del":98,"cadd":125,"cdel":98,"files":10},{"repo":"mesnada","hash":"80817d6e3f455969c877c36b7684664f407df22e","ts":1772485693,"wall":"2026-03-02T16:08","msg":"Update handoff: D3 stacking in movement done, 345 tests passing","body":"","parents":["47f502f50ee3b996bc35283aee7cb4986a003649"],"add":29,"del":19,"cadd":29,"cdel":19,"files":1},{"repo":"operations","hash":"9ecf7391b7cf3cc18f4bc6fa25c0a8603bdc74ee","ts":1772504109,"wall":"2026-03-02T21:15","msg":"Add atlas nerve center, update strategy for track record focus","body":"Bank account opened, website deployed, SDVOSB deferred to 2028\n(requires 2-year track record). Priority reframed: first client\nengagement and portfolio building over certification pipeline.\n\nNew atlas structure:\n- projects/index.md — master project inventory\n- projects/relationships.md — dependency graph\n- projects/links/ — symlinks to all repos\n- status/dashboard.md — project state tracker\n- strategy/priorities.md — tiered priority framework\n- strategy/advertising.md — positioning strategy\n- docs/biography.md — biographical reference","parents":["ff378c1a2c748966298d6a701ccd21316f4ce439"],"add":469,"del":191,"cadd":446,"cdel":191,"files":32},{"repo":"groundwork","hash":"82dceadcfb4ef27fccdaca3ca992ff31698f9cbd","ts":1772504141,"wall":"2026-03-02T21:15","msg":"Add GeoPackage storage layer, convert 8 acquire modules","body":"Phase A1: Replace GeoJSON file storage with single-project GeoPackage.\nVector data now writes to assessment.gpkg via storage.save_layer().\n\nNew:\n- groundwork/storage.py — save_layer, load_layer, list_layers,\n  export_geojson, has_layer (uses pyogrio for layer listing)\n- LandProject.gpkg_path property in config.py\n\nConverted modules (GeoJSON → GPKG):\n- soils (polygons + enrichment)\n- flood (zones)\n- wetlands (NWI polygons)\n- groundwater (wells)\n- wildfire (fire perimeters)\n- ownership (federal lands)\n- osm (roads, buildings, water, landuse)\n- hydrography (flowlines + waterbodies)\n\nRemaining: parcels (partial), analyze modules, webmap layer reader.\nRasters stay as GeoTIFF (rasterio doesn't support GPKG rasters).\nSummary JSONs unchanged (metadata, not spatial data).","parents":["c9af72b847abd15901292acd3df7b6b9514f49f3"],"add":210,"del":88,"cadd":210,"cdel":88,"files":11},{"repo":"operations","hash":"cdcb4bf5e11339c55653cf15d61bd48a7827eb4c","ts":1772504226,"wall":"2026-03-02T21:17","msg":"Update handoff for session 6 — atlas + strategy refresh","body":"","parents":["9ecf7391b7cf3cc18f4bc6fa25c0a8603bdc74ee"],"add":56,"del":26,"cadd":56,"cdel":26,"files":1},{"repo":"groundwork","hash":"7c47460e4b68ee8a8d7ce0d4b4ae679977084c80","ts":1772504236,"wall":"2026-03-02T21:17","msg":"Update handoff for GeoPackage migration progress","body":"","parents":["82dceadcfb4ef27fccdaca3ca992ff31698f9cbd"],"add":37,"del":57,"cadd":37,"cdel":57,"files":1},{"repo":"operations","hash":"353e96b71173b05cc10e71b49ea532912145fd6a","ts":1772504683,"wall":"2026-03-02T21:24","msg":"Thorough handoff for session 6","body":"","parents":["cdcb4bf5e11339c55653cf15d61bd48a7827eb4c"],"add":78,"del":53,"cadd":78,"cdel":53,"files":1},{"repo":"groundwork","hash":"00d93e377a3edb094d27490035ac61b745902a1e","ts":1772504781,"wall":"2026-03-02T21:26","msg":"Thorough handoff with conversion details and next-session context","body":"","parents":["7c47460e4b68ee8a8d7ce0d4b4ae679977084c80"],"add":104,"del":32,"cadd":104,"cdel":32,"files":1},{"repo":"groundwork","hash":"a29db33e5cacba3f1263fb64dcea9a5d766828b4","ts":1772508539,"wall":"2026-03-02T22:28","msg":"Complete GeoPackage migration: parcels + all analyze modules","body":"Converts remaining vector outputs from GeoJSON to project GPKG:\n- parcels: cache check, writes, get_parcels_path() with legacy fallback\n- terrain: contours layer, threaded project through _generate_contours\n- hydrology: depressions, streams, water_harvest_candidates layers\n- suitability: suitability_zones layer\n- wetland_probability: wetland_probability_zones layer, soils read\n  tries GPKG first with GeoJSON fallback\n\nAll acquire (9/9) and analyze (4/4) modules now write to GeoPackage.\nWebmap layer collection unchanged (pending decision on approach).\n314 tests passing.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["00d93e377a3edb094d27490035ac61b745902a1e"],"add":51,"del":42,"cadd":51,"cdel":42,"files":5},{"repo":"groundwork","hash":"0905507301f27c2ec95dd04fdef8023b32661de9","ts":1772508625,"wall":"2026-03-02T22:30","msg":"Update handoff for session 7 — GeoPackage migration complete","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["a29db33e5cacba3f1263fb64dcea9a5d766828b4"],"add":63,"del":88,"cadd":63,"cdel":88,"files":1},{"repo":"operations","hash":"a2f64b3fda75be7856b81018eff4159d63f6b9bd","ts":1772508635,"wall":"2026-03-02T22:30","msg":"Update handoff for session 7 — GeoPackage migration complete","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["353e96b71173b05cc10e71b49ea532912145fd6a"],"add":19,"del":67,"cadd":19,"cdel":67,"files":1},{"repo":"gerald-herald","hash":"8058880701174f90e98950d24bc3e1bb3ead802a","ts":1772557701,"wall":"2026-03-03T12:08","msg":"Initialize Gerald-Herald: social media automation for the Azuran network","body":"GoToSocial sovereign instance → Remotion + Three.js video renderer → cross-post\nto Instagram Reels, Facebook Reels, Bluesky, TikTok. Write once, broadcast everywhere.","parents":[],"add":95,"del":0,"cadd":95,"cdel":0,"files":2},{"repo":"operations","hash":"551296cda6f23c2090eaa90570a758761b05f436","ts":1772563443,"wall":"2026-03-03T13:44","msg":"Session 8: Gerald-Herald project, GoToSocial deployment, Ark appliance vision","body":"- Atlas: added gerald-herald (social media automation) to index, relationships, dashboard\n- Handoff: GoToSocial live at social.symbiont.systems, Steps 1-5 complete\n- New project: Gerald-Herald (GoToSocial + Remotion video renderer + cross-posting)\n- Ark appliance architecture and hardware research documented in knowledge-ark repo","parents":["a2f64b3fda75be7856b81018eff4159d63f6b9bd"],"add":108,"del":33,"cadd":107,"cdel":33,"files":5},{"repo":"azuran-knowledge-ark","hash":"cdebeb3b8c5e00175bce5053879534ce894da7c8","ts":1772563462,"wall":"2026-03-03T13:44","msg":"Add Ark appliance vision and SBC hardware research","body":"Full Layer 0-7 stack for edge network appliance: WiFi AP, LoRa mesh,\nReticulum control plane, Starlink backhaul. Hardware research across\n6 tiers from GL.iNet routers to Jetson Orin Nano.","parents":["20c2bbf76bbcdd08c4ed1b66a364ae74c1f93ecf"],"add":303,"del":0,"cadd":303,"cdel":0,"files":2},{"repo":"operations","hash":"01ab3d7bc030dff344d8a1af5c46eaad7ed20a9f","ts":1772569380,"wall":"2026-03-03T15:23","msg":"Session 9: MESO knowledge hygiene, operationalize three-layer system","body":"Activated memory graph (28 entities, 37 relations), indexed 35 docs\ninto RAG (knowledge_base +328 chunks, decisions +56 chunks).\nUpdated DEADLINES.md and reconstructed SESSION-LOG.md for Sessions 5-9.","parents":["551296cda6f23c2090eaa90570a758761b05f436"],"add":209,"del":114,"cadd":209,"cdel":114,"files":3},{"repo":"groundwork","hash":"4d92a84979a423eec8ed85464a1d13a6a3f6d861","ts":1772572173,"wall":"2026-03-03T16:09","msg":"Simplify interfaces: GeoPackage webmap, strip bloat, clean deps","body":"- Webmap reads from GeoPackage via storage.list_layers/export_geojson\n  with legacy GeoJSON fallback for older projects\n- Remove PMTiles mode, 3D terrain, geocoding search, measurement tools,\n  basemap switcher, and export-as-image from webmap (-751 LOC net)\n- TUI: remove Sources and Outputs screens (5-screen flow instead of 7);\n  all modules enabled by default, CLI --modules for customization\n- Move server deps (fastapi, uvicorn, pydantic, httpx, aiosqlite) from\n  main deps to optional [server] group — no server code exists yet\n- Add test_storage.py with 14 tests for GeoPackage storage abstraction\n- 310 tests passing","parents":["0905507301f27c2ec95dd04fdef8023b32661de9"],"add":302,"del":1053,"cadd":302,"cdel":1053,"files":9},{"repo":"groundwork","hash":"e6857389b5db6470ce044228ac220607e5e59c8e","ts":1772572223,"wall":"2026-03-03T16:10","msg":"Update handoff for session 8 — interface simplification","body":"","parents":["4d92a84979a423eec8ed85464a1d13a6a3f6d861"],"add":57,"del":82,"cadd":57,"cdel":82,"files":1},{"repo":"operations","hash":"decea90dc0b3916f12506536164a11acc0a225f7","ts":1772572304,"wall":"2026-03-03T16:11","msg":"Session 10: Groundwork interface simplification, MCP time server","body":"","parents":["01ab3d7bc030dff344d8a1af5c46eaad7ed20a9f"],"add":71,"del":54,"cadd":71,"cdel":54,"files":2},{"repo":"groundwork","hash":"5e92dc8e3afc24bbeee8971b0a372ee06fa19ee2","ts":1772573272,"wall":"2026-03-03T16:27","msg":"Remove 837 generated data files from projects/, gitignore directory","body":"projects/ contains reproducible pipeline outputs (TIFs, GeoJSONs, reports)\nthat should never have been tracked. Also removes dead test methods\nreferencing deleted SourcesScreen and OutputsScreen.","parents":["e6857389b5db6470ce044228ac220607e5e59c8e"],"add":1,"del":9597898,"cadd":0,"cdel":3114334,"files":839},{"repo":"groundwork","hash":"17bbb63574c1c82e150cd20aa0f0a1bd9565ae2d","ts":1772577881,"wall":"2026-03-03T17:44","msg":"Phase 0: Spatial intelligence platform scaffolding","body":"Restructure Groundwork from CLI/TUI report tool to spatial intelligence\nplatform foundation. Create core/ package with Region abstraction,\ndelete tui/, output/, and all static report generation. Pipeline stripped\nto pure acquire → analyze engine. CLI stubbed for serve/snapshot commands.\n\n- Create groundwork/core/ package (registry, storage, contracts, http, log)\n- Add Region abstraction replacing LandProject's point+radius model\n- Delete tui/ (14 files), output/ (9 files), config.py\n- Strip pipeline of report/pdf/webmap generation\n- Rewrite CLI to serve/snapshot/modules stubs\n- Update pyproject.toml: v0.2.0, swap textual/platformdirs for fastapi/uvicorn/websockets\n- Update all imports across 19 acquire + 4 analyze modules\n- Delete dead tests, update surviving tests for new API\n- 151 tests passing, -8481 lines net\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5e92dc8e3afc24bbeee8971b0a372ee06fa19ee2"],"add":457,"del":8481,"cadd":457,"cdel":8481,"files":75},{"repo":"groundwork","hash":"a07e01c976daa0ca48cbc063e0856f312f126677","ts":1772578024,"wall":"2026-03-03T17:47","msg":"Update handoff for session 9 — spatial intelligence pivot Phase 0","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["17bbb63574c1c82e150cd20aa0f0a1bd9565ae2d"],"add":104,"del":63,"cadd":104,"cdel":63,"files":1},{"repo":"operations","hash":"14c8159e5560b4f437df1df514c9ba77fb31cd5a","ts":1772578052,"wall":"2026-03-03T17:47","msg":"Session 11: Groundwork spatial intelligence pivot research and Phase 0","body":"Add viewer comparison, snapshot architecture, and realtime feeds research.\nUpdate dashboard and session log for Phase 0 completion.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["decea90dc0b3916f12506536164a11acc0a225f7"],"add":397,"del":3,"cadd":397,"cdel":3,"files":6},{"repo":"mesnada","hash":"443382f4075e347682d71bd46601af44913f337e","ts":1772588318,"wall":"2026-03-03T20:38","msg":"D4: Frontend stacking — render stacked units, selection UI, fix serialization","body":"Backend: to_dict() now serializes units as arrays per hex (was silently\ndropping stacked units). get_unit/move/attack/defend accept unit_index.\nFrontend: units type changed to Record<string, UnitData[]>, renderer fans\nstacked units with offset and shows count badge, HexTooltip shows unit\ntabs for stack selection, all action payloads send unit_index.\n\n345 backend tests passing, frontend typecheck and build clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["80817d6e3f455969c877c36b7684664f407df22e"],"add":171,"del":83,"cadd":171,"cdel":83,"files":16},{"repo":"mesnada","hash":"2bebcf615f128c5dd212a975ee4eb6e7997bf27b","ts":1772588452,"wall":"2026-03-03T20:40","msg":"Update handoff: D4 frontend stacking done, 345 tests passing","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["443382f4075e347682d71bd46601af44913f337e"],"add":26,"del":22,"cadd":26,"cdel":22,"files":1},{"repo":"symbiontic-dialogues","hash":"1f9abf3491fae8176a2b7f7d02d28c69574f2f36","ts":1772595481,"wall":"2026-03-03T22:38","msg":"Dialogue 001: Fields, Forms, and the Cartesian Settlement","body":"First symbiontic dialogue covering quantum fields, mass-energy\nequivalence, the Cartesian settlement, Platonism-Abrahamism\nconnection, and archaeological evidence for biblical dating.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":603,"del":0,"cadd":603,"cdel":0,"files":1},{"repo":"symbiontic-dialogues","hash":"b5d2af3afe28464000b9e763b1aca80067fcfaf3","ts":1772595631,"wall":"2026-03-03T22:40","msg":"Add comprehensive sources and references section","body":"All sources cited, researched, or consulted during the dialogue,\norganized by topic: physics, history of science, Platonism-Abrahamism,\nHebrew Bible scholarship, Gmirkin thesis, biblical archaeology.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["1f9abf3491fae8176a2b7f7d02d28c69574f2f36"],"add":64,"del":0,"cadd":64,"cdel":0,"files":1},{"repo":"symbiontic-dialogues","hash":"9d5babb67ac586cac5dbe53fe3cf3efac0d73eb7","ts":1772596194,"wall":"2026-03-03T22:49","msg":"Add process philosophy exchange — first principles from scratch","body":"Valis arrives at Whitehead's process ontology independently.\nProcess as primary, things as patterns, relations prior to objects.\nConnects substance bias to the unification problem.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["b5d2af3afe28464000b9e763b1aca80067fcfaf3"],"add":26,"del":0,"cadd":26,"cdel":0,"files":1},{"repo":"symbiontic-dialogues","hash":"1f3826277073a8da7fa065dbdca9cdf7d9fe176d","ts":1772598790,"wall":"2026-03-03T23:33","msg":"Add Whitehead, Laozi, Nietzsche, Feyerabend, and academia exchanges","body":"Process philosophy, Laozi-Plato psychological comparison via\nNietzsche's lens, Feyerabend's methodological anarchism, Western\nframing of non-Western knowledge, institutional failure of academia.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["9d5babb67ac586cac5dbe53fe3cf3efac0d73eb7"],"add":205,"del":0,"cadd":205,"cdel":0,"files":1},{"repo":"mesnada","hash":"0df53c15ffc64d6dde69cc7c9a843adea9a48d7a","ts":1772641274,"wall":"2026-03-04T11:21","msg":"D5: Deployment choice on recruit — two-step flow when settlement hex full","body":"When a settlement hex is at capacity, recruit_pawn() now returns an error\nprompting the player to choose an adjacent hex. Frontend enters recruiting\nmode with green-highlighted valid hexes; clicking one dispatches the recruit\nwith target_hex. Six new backend tests cover all validation paths (adjacency,\ncapacity, enemy occupation, target ignored when room exists).\n\n351 passed, 4 skipped.","parents":["2bebcf615f128c5dd212a975ee4eb6e7997bf27b"],"add":231,"del":14,"cadd":231,"cdel":14,"files":9},{"repo":"mesnada","hash":"e037473d96802e1a62b5257b9fdb24aa49ea25fc","ts":1772641362,"wall":"2026-03-04T11:22","msg":"Update handoff: D5 deployment choice done, D1-D5 stacking complete","body":"351 passed, 4 skipped.","parents":["0df53c15ffc64d6dde69cc7c9a843adea9a48d7a"],"add":19,"del":25,"cadd":19,"cdel":25,"files":1},{"repo":"symbiont.systems","hash":"0fa71c876f5efb815aa53c330d1b67ba83a4948e","ts":1772679044,"wall":"2026-03-04T21:50","msg":"Split monolithic dashboard into ES modules, add typed block system","body":"Extract 2400-line single-file dashboard into 9 ES modules:\n- config.js: BLOCK_TYPES registry, CONFIG, persistence, v1→v2 migration\n- scene.js: Three.js hex sphere, rings, bloom, spores, animation loop\n- deploy.js: Deploy panel + generateProductionHTML with dynamic blocks\n- panels.js: Geometry, camera, bloom, spores, colors, scene, shader panels\n- blocks.js: Block editor UI with one-click type grid\n- ui-helpers.js: Shared component factories (slider, color, toggle, etc.)\n- rings-panel.js: Ring config with URL field\n- copy-panel.js: Per-ring content block editor\n- main.js: Entry point, tab system, persistence wiring\n\nData model: copy.items[] → content.body[] with 14 typed block types.\nUX: accordion state preservation across rebuilds, auto-scroll to new\nblocks, one-click block addition grid replacing dropdown+button combo.\nFix esc() regex bug in generated production HTML.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["831f22f2c6f3cea3711efe632cf014c639b02d80"],"add":3038,"del":2512,"cadd":3038,"cdel":2512,"files":11},{"repo":"symbiont.systems","hash":"069d0b701f83551e9e29b188bcb7ba75a7b80531","ts":1772679118,"wall":"2026-03-04T21:51","msg":"Update Caddyfile example with dashboard routing and trailing slash redirect","body":"Add /_dashboard basicauth block, trailing slash redirect for ES module\nrelative path resolution, and separate /_deploy/* handler.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["0fa71c876f5efb815aa53c330d1b67ba83a4948e"],"add":13,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"symbiont.systems","hash":"0a2cd43e1ffebeb655e87e6611730cc98140a30c","ts":1772679234,"wall":"2026-03-04T21:53","msg":"Update handoff: ES module split, typed blocks, UX improvements","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["069d0b701f83551e9e29b188bcb7ba75a7b80531"],"add":45,"del":38,"cadd":45,"cdel":38,"files":1},{"repo":"operations","hash":"7a8bba08769b572dc02550f4c7b346c4adad7a2c","ts":1772679257,"wall":"2026-03-04T21:54","msg":"Update dashboard: symbiont.systems ES module split and block system complete","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["14c8159e5560b4f437df1df514c9ba77fb31cd5a"],"add":3,"del":2,"cadd":3,"cdel":2,"files":1},{"repo":"operations","hash":"8e75303ec3d764eff8166bfffcba48ec19c2ac34","ts":1772685059,"wall":"2026-03-04T23:30","msg":"Session 12: Forgejo deployment, code sovereignty, business reframing","body":"Deployed Forgejo v14.0.2 at git.symbiont.systems — 41 repos migrated\nfrom GitHub. All GitHub repos archived. Local remotes switched to\nForgejo as origin, GitHub retained as legacy remote.\n\nBusiness docs reframed: R&D lab orientation replaces federal contracting\nposture. SDVOSB deferred. SAM.gov removed from immediate priorities.\nAdded baronial style to officer record.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["7a8bba08769b572dc02550f4c7b346c4adad7a2c"],"add":82,"del":99,"cadd":82,"cdel":99,"files":6},{"repo":"musico","hash":"1bfec830678289713714d56c090c20bfe4a5e1b2","ts":1772727354,"wall":"2026-03-05T11:15","msg":"Phase 4b: Analog drum synthesis, per-track mixer, stereo output","body":"8 synthesized drum voices (kick, rim, snare, tom, HH closed/open,\ncrash, ride) using sine oscillators, LFSR noise, pitch envelopes,\nand HP/LP filtering. No samples — pure analog-style synthesis.\n\nPer-track mixer with independent volume, pan, and effects send for\nmelodic and drum tracks. Engine now outputs true stereo with\nequal-power panning. Effects chain receives configurable send mix\nfrom both tracks.\n\nMIDI channel 9 pads now route to dedicated drum synth instead of\nmelodic voices. UI gains an 8-pad drum strip with trigger flash\nanimation and click-to-play. Mixer controls in right panel.\nSocket commands: drum, drum_vol/pan/send, mel_vol/pan/send.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["80428620d699e462f73a2b00d7ce7fdcb744b112"],"add":711,"del":25,"cadd":711,"cdel":25,"files":8},{"repo":"musico","hash":"6e062130ccd76b1b15b0ceb72df5a122feb9aa43","ts":1772731120,"wall":"2026-03-05T12:18","msg":"Rewrite drum synthesis: 808-accurate tuning, precomputed hot path, choke groups","body":"Eliminates per-sample transcendentals (exp, sin) that caused audio buffer\nunderruns on rapid pad hits. All decay coefficients and filter alphas now\nprecomputed at trigger time — tick() is pure multiply/add.\n\n808-accurate tuning: kick sweeps 130→49 Hz in 6ms (was 150→50 in 60ms),\nsnare uses dual oscillators at 238+476 Hz with HPF at 2700 Hz, hi-hats\nuse 6 inharmonic square-wave oscillators through SVF bandpass (was noise).\n\nSoft retrigger: 1ms linear ramp from current amplitude level, no phase\nor filter state reset. Rapid hits blend without clicks or pops.\n\nChoke group: closed hi-hat kills open hi-hat with 1ms fadeout.\n\nRecursive sine oscillator replaces sin(phase*TAU) — 2 multiplies per\nsample with periodic renormalization every 1024 samples.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["1bfec830678289713714d56c090c20bfe4a5e1b2"],"add":365,"del":172,"cadd":365,"cdel":172,"files":2},{"repo":"musico","hash":"d04ce7f31441381a123b849a8e6a69c1a71d8952","ts":1772731318,"wall":"2026-03-05T12:21","msg":"Update handoff for Phase 4b drum synthesis and mixer","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["6e062130ccd76b1b15b0ceb72df5a122feb9aa43"],"add":42,"del":20,"cadd":42,"cdel":20,"files":1},{"repo":"musico","hash":"99a2c4fd17c283ce7fe0d540e9eb8e4aa777a738","ts":1772735880,"wall":"2026-03-05T13:38","msg":"Per-pad drum params, velocity curves, socket kit presets, UI editor","body":"Extract hardcoded 808 synthesis values into mutable DrumParams struct.\nPer-pad velocity curves compensate for MPK Mini 3 weak response.\nSocket commands: drum_param, kit_save, kit_load, kit_reset.\nRight-click any drum pad to open parameter editor popup.\nFoundation for Phase 5 preset system (JSON serialization).","parents":["d04ce7f31441381a123b849a8e6a69c1a71d8952"],"add":529,"del":100,"cadd":529,"cdel":100,"files":5},{"repo":"musico","hash":"52d6c4f6edcfd04c074237118f1d05a87d8a78c9","ts":1772736141,"wall":"2026-03-05T13:42","msg":"Update handoff for drum params, velocity curves, kit presets, pad editor","body":"","parents":["99a2c4fd17c283ce7fe0d540e9eb8e4aa777a738"],"add":27,"del":37,"cadd":27,"cdel":37,"files":1},{"repo":"musico","hash":"c35d9da4039b34e7d2fce9a5d1f4bf8dd2fe2f54","ts":1772742562,"wall":"2026-03-05T15:29","msg":"Drum step sequencer grid, low-latency audio buffer","body":"Full drum grid: 8 pads × up to 64 steps with per-hit velocity,\nprobability, per-pad polyrhythm (step division), swing, euclidean\nfills, copy/paste, and fill presets. Grid expands when sequencer\nis active, collapses to trigger pads when stopped.\n\n- DrumGrid data model with Bjorklund euclidean algorithm\n- SeqEvent::DrumHit + Sequencer::drum_tick() with swing/probability\n- Grid UI: click toggle, drag paint/erase, shift+click probability\n- Toolbar: swing slider, step div, euclidean, fill presets, copy/paste\n- Socket: drum_grid command family (set/clear/euclidean/swing/fill/steps)\n- Audio buffer 128 samples (~3ms) for tight pad response","parents":["52d6c4f6edcfd04c074237118f1d05a87d8a78c9"],"add":840,"del":71,"cadd":840,"cdel":71,"files":6},{"repo":"musico","hash":"8fde2343674dd09681bd454ad2e11c08b7072391","ts":1772744493,"wall":"2026-03-05T16:01","msg":"Update handoff for drum grid, low-latency buffer","body":"","parents":["c35d9da4039b34e7d2fce9a5d1f4bf8dd2fe2f54"],"add":24,"del":18,"cadd":24,"cdel":18,"files":1},{"repo":"operations","hash":"d9eabbdacfe8a56a56c98205b4fb83ae77e5cb71","ts":1772744523,"wall":"2026-03-05T16:02","msg":"Session 14: Musico drum step grid, low-latency audio buffer","body":"","parents":["8e75303ec3d764eff8166bfffcba48ec19c2ac34"],"add":37,"del":69,"cadd":37,"cdel":69,"files":3},{"repo":"persian-gulf-theater","hash":"04d9fd499ae8b48cfac7f98988213c2e7f5dee98","ts":1772817872,"wall":"2026-03-06T12:24","msg":"Initial commit: OSINT tracking of Iran-Israel-US conflict (Days 1-7)","body":"Sitreps covering Feb 28 - Mar 6 2026, unified timeline, six analytical\npieces, source registry, assessment template, and Day 3 war assessment.\nDay 5-7 consolidated sitrep draws from Western, Persian, Russian,\nChinese, and Gulf/Arab/Israeli sources.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":3916,"del":0,"cadd":3916,"cdel":0,"files":16},{"repo":"persian-gulf-theater","hash":"71667f16369f23746d7d8a844d0ed54766da80d3","ts":1772826841,"wall":"2026-03-06T14:54","msg":"Days 5-7 sitrep, proliferation analysis, antisemitism label analysis","body":"Consolidated sitrep covering March 4-6 from five language spheres\n(Western, Persian, Russian, Chinese, Gulf/Arab/Israeli). Two new\nanalytical pieces: nuclear proliferation wave post-Iran war, and\nthe sociological collapse of \"antisemitism\" as effective political\nlabel. Timeline updated through Day 7.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["04d9fd499ae8b48cfac7f98988213c2e7f5dee98"],"add":372,"del":0,"cadd":372,"cdel":0,"files":2},{"repo":"eureka-co-nevada","hash":"e05e67636030f45f45377f2e824eb27f219c61bd","ts":1772905760,"wall":"2026-03-07T12:49","msg":"Initialize Eureka County digital twin repository","body":"Spatial, temporal, legal, economic, environmental, infrastructure,\nand demographic knowledge base for Eureka County, Nevada.\n22 data sources cataloged in manifest. Domain READMEs with scope\nand key facts.\n\nAuthored by Rowan Valle; Executed by Claude Code\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":[],"add":352,"del":0,"cadd":292,"cdel":0,"files":13},{"repo":"eureka-co-nevada","hash":"e67557106a8e420b0e06168da5d271113f04f9ec","ts":1772907916,"wall":"2026-03-07T13:25","msg":"Populate legal, spatial, temporal, economic, demographic, environmental, infrastructure domains","body":"Legal: All 19 county code titles (PDFs), NRS 244/278 summaries, master plan,\nframework analysis. Copied from azura-terraforming research.\n\nSpatial: County boundary (Census TIGER), BLM surface management (clipped to\ncounty — 73.5% BLM, 21.1% private, 5.4% USFS), NV State Lands (2 parcels,\n26 acres total). All GeoJSON, EPSG:4326.\n\nTemporal: County timeline 1864-2020 covering mining boom, decline, ranching\nera, gold revival, Diamond Valley curtailment.\n\nDemographics: Decennial population 1870-2020 with change analysis, Census\nAPI endpoint documentation for future data pulls.\n\nEconomic: Active mining operations (i-80 Gold, General Moly, Timberline),\nhistorical mining districts.\n\nEnvironmental: Hydrographic basin status — Diamond Valley (curtailed 2019),\nCrescent Valley, Pine Valley, Kobeh Valley.\n\nInfrastructure: Highway network (US-50, SR-278), railroad history, Eureka\nAirport (05U).\n\nAuthored by Rowan Valle; Executed by Claude Code\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["e05e67636030f45f45377f2e824eb27f219c61bd"],"add":1129,"del":2,"cadd":1109,"cdel":2,"files":45},{"repo":"eureka-co-nevada","hash":"11db09248cc475ecf85337bea5b4aaf363a8436d","ts":1772910886,"wall":"2026-03-07T14:14","msg":"Add spatial layers: soils, hydrology, groundwater, wildfire, OSM, PLSS","body":"Direct API pulls, clipped to county boundary, EPSG:4326.\n\nSSURGO soils: 4,028 polygons via NRCS SDA REST API\nNHD flowlines: 11,395 streams (perennial, intermittent, ephemeral)\nNHD waterbodies: 17 lakes/reservoirs\nNHD springs: 2,660 spring/well points\nPLSS sections: 4,427 township/range/section polygons via BLM CadNSDI\nGroundwater wells: 701 USGS NWIS monitoring sites\nWildfire perimeters: 43 historical fire boundaries via NIFC WFIGS\nOSM roads: 4,855 ways (3,458 tracks, 655 service, 238 residential, etc.)\nOSM buildings: 1,869 building footprints\n\nServices unavailable this session:\n- NWI wetlands (USFWS endpoint 503)\n- FEMA flood zones (NFHL endpoint unresponsive)\n\nAuthored by Rowan Valle; Executed by Claude Code\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["e67557106a8e420b0e06168da5d271113f04f9ec"],"add":29351,"del":0,"cadd":0,"cdel":0,"files":9},{"repo":"operations","hash":"c76ae55e84055a41a89eb2cfa966e5331dc8fdb1","ts":1772911122,"wall":"2026-03-07T14:18","msg":"Session 17: Eureka County digital twin — atlas and handoff updates","body":"New repo eureka-co-nevada added to project index, dashboard, and symlinks.\n12 spatial layers, complete legal corpus, 6 domain seed documents.\nSession log updated with full acquisition details.\n\nAuthored by Rowan Valle; Executed by Claude Code\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["d9eabbdacfe8a56a56c98205b4fb83ae77e5cb71"],"add":214,"del":33,"cadd":213,"cdel":33,"files":5},{"repo":"eureka-co-nevada","hash":"8249ef13de676aedbc2c8472f57d54bdcb793fc2","ts":1772916180,"wall":"2026-03-07T15:43","msg":"Add spatial layers: active mining claims, NWI wetlands, flood zones","body":"- Active mining claims: 27,496 features (clipped from BLM national MLRS dataset)\n- NWI wetlands: 12,152 features (clipped from USFWS state download)\n- NWI riparian: 4 features\n- FEMA flood zones: 1,555 features (extracted from Groundwork assessment.gpkg)\n\nNational datasets stored on external drive for reuse across projects.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["11db09248cc475ecf85337bea5b4aaf363a8436d"],"add":41235,"del":0,"cadd":0,"cdel":0,"files":4},{"repo":"eureka-co-nevada","hash":"a6e1f8d7f140a2413ccc315269b6a0997d2db70e","ts":1772916200,"wall":"2026-03-07T15:43","msg":"Upgrade 5 spatial layers from Groundwork assessment.gpkg","body":"Wells 701->781, OSM roads 4855->6807, OSM buildings 1869->2147,\nwaterbodies 17->810, soils 4028->4832. Groundwork gpkg had better\ncoverage than prior direct API pulls for these layers.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["8249ef13de676aedbc2c8472f57d54bdcb793fc2"],"add":15384,"del":10770,"cadd":0,"cdel":0,"files":5},{"repo":"eureka-co-nevada","hash":"8d07173895d2043cf8ab9519515e7c095af5b326","ts":1772916227,"wall":"2026-03-07T15:43","msg":"Add Groundwork raw data exports and assessment.gpkg","body":"Raw JSON summaries: climate, solar, landcover, soils, groundwater,\nflood, wetlands, ownership, OSM, NHD. Assessment gpkg with 10 layers.\nNLCD 2021 raster (30m). These are intermediate data from Groundwork\nsite assessment pipeline.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["a6e1f8d7f140a2413ccc315269b6a0997d2db70e"],"add":95784,"del":0,"cadd":0,"cdel":0,"files":15},{"repo":"eureka-co-nevada","hash":"e60358c6010a0b9e6a24fb42e593ec90be8414c2","ts":1772916237,"wall":"2026-03-07T15:43","msg":"Add environmental domain docs, update READMEs","body":"New: climate (PRISM 1991-2020), landcover (NLCD 2021), solar resource\n(NREL), farmland classification (SSURGO). Updated spatial and\nenvironmental READMEs to reflect current layer inventory.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["8d07173895d2043cf8ab9519515e7c095af5b326"],"add":152,"del":10,"cadd":152,"cdel":10,"files":6},{"repo":"eureka-co-nevada","hash":"b286003e64c2c369aec30b957b5273f972b68567","ts":1772916484,"wall":"2026-03-07T15:48","msg":"Add session handoff","body":"Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["e60358c6010a0b9e6a24fb42e593ec90be8414c2"],"add":96,"del":0,"cadd":96,"cdel":0,"files":1},{"repo":"operations","hash":"3276d35648bb085a4b8a30e344eb26cb3a7e8ab7","ts":1772916550,"wall":"2026-03-07T15:49","msg":"Session 18: Eureka County spatial expansion and environmental domain","body":"Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["c76ae55e84055a41a89eb2cfa966e5331dc8fdb1"],"add":66,"del":79,"cadd":66,"cdel":79,"files":1},{"repo":"eureka-co-nevada","hash":"22490236f28fc5158fe18513b7907230aa333067","ts":1772918073,"wall":"2026-03-07T16:14","msg":"Add closed mining claims: 106,543 features","body":"Clipped from BLM national MLRS dataset (3.8M features, 637MB FileGDB).\nNational dataset stored on external drive for reuse.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["b286003e64c2c369aec30b957b5273f972b68567"],"add":106550,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"eureka-co-nevada","hash":"7ace9c81d6ff436368a0c75ce1c7261ff840a964","ts":1772918082,"wall":"2026-03-07T16:14","msg":"Add ACS 2022 demographic profile","body":"Population, race, housing, income, employment by industry, education.\nCensus API pull for FIPS 32011.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["22490236f28fc5158fe18513b7907230aa333067"],"add":79,"del":2,"cadd":79,"cdel":2,"files":2},{"repo":"eureka-co-nevada","hash":"122c6e9378afafd08da79818a3ff56552a8c5cb9","ts":1772918276,"wall":"2026-03-07T16:17","msg":"Update handoff: closed claims complete, ACS profile added","body":"Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["7ace9c81d6ff436368a0c75ce1c7261ff840a964"],"add":63,"del":53,"cadd":63,"cdel":53,"files":1},{"repo":"operations","hash":"dcbb39fbf4f02a9c7ea78532db1c32a2631455c1","ts":1772918286,"wall":"2026-03-07T16:18","msg":"Session 18: Eureka County — spatial domain near-complete, demographics","body":"Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["3276d35648bb085a4b8a30e344eb26cb3a7e8ab7"],"add":18,"del":66,"cadd":18,"cdel":66,"files":1},{"repo":"eureka-co-nevada","hash":"d78af573bd4f3f96168c3805b7162960fa8a8932","ts":1772926416,"wall":"2026-03-07T18:33","msg":"Session 19: Economic, infrastructure, environmental domains + ACS 2023 upgrade","body":"Demographics: ACS 2019-2023 profile replacing 2022 — population, race, housing,\nincome, employment by industry, commuting, education, sub-county CCDs.\n\nEconomic (5 new docs): NV Net Proceeds of Minerals 10-year time series (Eureka =\n30% of state), assessed valuations ($1.68B total AV, $2.08 rate — lowest in NV),\nGOED/Lightcast income/employment (4,648 jobs, $1.92B GRP), county budget ($54M\nbudget, $175M net position), ranching/grazing allotments.\n\nInfrastructure: FCC broadband coverage — 8 ISPs, no fiber anywhere in county,\nStarlink (350 Mbps) and fixed wireless (100 Mbps) are best options.\n\nEnvironmental: Greater sage-grouse (PMUs, habitat categories, threats, regulatory\nframework), wind resource screening (Class 1-2 valleys, marginal for development).\n\nSpatial: BLM grazing allotments — 117 features via ArcGIS REST FeatureServer.\n\nSources: Census API, NV Dept of Taxation (NPM Bulletin, Redbook, Bulletin 208),\nGOED/Lightcast, Eureka Sentinel, FCC BDC, BLM ArcGIS REST, NV Sagebrush\nEcosystem Program, NREL/DOE WINDExchange.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["122c6e9378afafd08da79818a3ff56552a8c5cb9"],"add":987,"del":101,"cadd":976,"cdel":101,"files":17},{"repo":"operations","hash":"42bbe3321eab54c10e3562f361cab712bfd2b2c9","ts":1772934870,"wall":"2026-03-07T20:54","msg":"Civilizational Metabolics: initial research corpus — 15 threads, 1,300+ lines","body":"New research project examining human economic history as metabolic phase\ntransitions: surplus ecology → temple credit → specie money. 16 files\ncovering deep prehistory evidence, economic transitions, and open questions.\n\nThreads: deep-notation, ritual-as-institution, networked-institutions,\ndeep-maritime, fire-as-metabolic-technology, megafauna-mutualism,\nethnographic-bias, material-technology, applied-chemistry, debt-jubilee,\nphase-transition-credit-to-specie, monetary-cognition, privatization-of-money,\ncredit-bullion-cycle, platinum-anomaly. ~50 academic citations.\n\nAuthored by Rowan Valle; Executed by Claude Code\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["dcbb39fbf4f02a9c7ea78532db1c32a2631455c1"],"add":1321,"del":0,"cadd":1321,"cdel":0,"files":16},{"repo":"groundwork","hash":"d64af4fbf03259926c283eb0c6b6eb3f04172c56","ts":1772941707,"wall":"2026-03-07T22:48","msg":"Analysis calibration: literature-backed defaults, configurable weights, ground-truth validation","body":"Replace all hardcoded magic numbers in analyze modules with published\nUSDA/NRCS/FAO/USACE/IBC values. Every threshold and weight is now\ndocumented with its source, configurable via 3-layer merge (dataclass\ndefaults -> global JSON -> per-project JSON), and testable.\n\nNew modules:\n- analyze/config.py — HydrologyConfig, WetlandConfig, SuitabilityConfig,\n  CalibrateConfig dataclasses with load_config/save_config\n- analyze/calibrate.py — NWI/NHD/NLCD validation framework with\n  precision/recall/F1/Kappa/AUC-ROC/TSS metrics\n\nModified modules:\n- hydrology.py — drainage-area-based stream threshold (km2 by landscape\n  type), depression depth gated by 2x DEM vertical RMSE\n- wetland_probability.py — 5-component model (hydric 35%, TWI 25%,\n  depressions 15%, convergence 10%, gradient 15%), sigmoid TWI scoring,\n  local gradient at 50m scale (Halabisky 2023)\n- suitability.py — FAO slope classes via np.digitize, SSURGO-aware\n  fallback, three AHP weight sets for water/structures/cultivation\n\nResearch: 2 new documents (~800 lines) covering all published thresholds\nand validation methodology.\n\nTests: 214 passing (was 178), 63 new tests across config and calibration.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","parents":["a07e01c976daa0ca48cbc063e0856f312f126677"],"add":2789,"del":131,"cadd":2789,"cdel":131,"files":11},{"repo":"groundwork","hash":"cade7289a7c1480026f7827c0ad5d04e6b22d3d4","ts":1772948213,"wall":"2026-03-08T00:36","msg":"Add feeds engine: 3 geospatial feeds + FeedRunner polling orchestrator","body":"Phase 1 of spatial intelligence platform. Implements earthquake (USGS),\nweather alert (NWS), and wildfire (NIFC) feed modules with a threaded\nFeedRunner that discovers, polls, and caches GeoJSON data. Registry\nextended to support feed module type with poll_interval metadata.\n\n34 new tests (17 feed + 17 runner).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d64af4fbf03259926c283eb0c6b6eb3f04172c56"],"add":879,"del":9,"cadd":879,"cdel":9,"files":9},{"repo":"groundwork","hash":"ebb45a3c903d64b764353cd26903ec9892a0a49f","ts":1772948223,"wall":"2026-03-08T00:37","msg":"Add FastAPI local server with REST feeds, layers, modules, and SSE streaming","body":"Phase 2 of spatial intelligence platform. FastAPI app factory with lifespan\nmanagement, CORS, and route mounting. Feed endpoints serve cached GeoJSON\nwith on-demand fetch and bbox filtering. SSE streaming pushes feed updates\nvia native FastAPI EventSourceResponse. GeoPackage layer serving with orjson\nfor fast GeoJSON serialization. Module registry endpoint exposes all\nregistered modules with metadata.\n\nFastAPI bumped to >=0.135 for native SSE, orjson added, websockets removed.\n17 new tests (11 REST + 6 SSE).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["cade7289a7c1480026f7827c0ad5d04e6b22d3d4"],"add":632,"del":8,"cadd":632,"cdel":8,"files":12},{"repo":"groundwork","hash":"da449b999abc21a5b84dbe3f29d5be640a108517","ts":1772948660,"wall":"2026-03-08T00:44","msg":"Update handoff for session 10 — Phase 1+2 complete, issues created","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["ebb45a3c903d64b764353cd26903ec9892a0a49f"],"add":65,"del":68,"cadd":65,"cdel":68,"files":1},{"repo":"operations","hash":"aefd476e987ad0d550e1228f0bedd1618c9212bf","ts":1772952054,"wall":"2026-03-08T01:40","msg":"Iris: photochromaglyphic codec — encode data as RGB pixels, hide messages in images","body":"New tool at tools/iris/. Rust CLI implementing photochromaglyphics — the encoding\nof data as colored light. Every 3 bytes become one RGB pixel.\n\nCore codec: iris encode/decode for lossless byte↔pixel round-trips.\nSteganography: iris hide/extract with key-derived LSB scatter (FNV-1a + xorshift64\nPRNG → Fisher-Yates permutation). No detectable signature without the passphrase.\nCRC32 validates key correctness and message integrity.\n\n38 tests (31 unit + 7 integration), 2 dependencies (image, clap).\nPhase 3 (optical transmission) stubbed for future LED/camera channels.","parents":["42bbe3321eab54c10e3562f361cab712bfd2b2c9"],"add":2493,"del":0,"cadd":1337,"cdel":0,"files":20},{"repo":"soma","hash":"0597eb7990fb162b95195726f21fa1f103587d96","ts":1773010836,"wall":"2026-03-08T19:00","msg":"Soma: voxel avatar sculptor — convex polyhedra, per-face color, budding","body":"Single-file Three.js app. Voxels are parameterized convex polyhedra\ngenerated from golden-spiral point distributions. Per-face vertex\ncoloring, interactive face add/remove, voxel budding, drag placement,\nRGB/HSL/CMYK color picker. The body is data.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":1060,"del":0,"cadd":1060,"cdel":0,"files":2},{"repo":"operations","hash":"fb0f609ca176538e01d0ca88bc8405cb75185db2","ts":1773011175,"wall":"2026-03-08T19:06","msg":"Session 19: Soma voxel avatar — repo created, atlas updated","body":"New project: Soma — Three.js voxel sculptor with convex polyhedra,\nper-face coloring, and budding. Pushed to Forgejo. Atlas index,\ndashboard, and handoff updated.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["aefd476e987ad0d550e1228f0bedd1618c9212bf"],"add":32,"del":25,"cadd":31,"cdel":25,"files":4},{"repo":"soma","hash":"dc8d57685c183852f96197caf3e3ca34b819fb1e","ts":1773014311,"wall":"2026-03-08T19:58","msg":"Face sculpting: scroll face count, Alt+drag/scroll resize, multi-select, symmetry","body":"Rewrote geometry engine with indexed vertex pool — shared vertices mean\nface resize deforms neighbors naturally, no gaps. Renamed soma.html to\nindex.html.\n\nControls:\n- Scroll: add/remove faces (regenerate polyhedron)\n- Alt+drag or Alt+scroll: resize individual faces\n- Ctrl+click: toggle face selection (gold highlight)\n- S: symmetry mode (auto-select opposite face)\n- Dbl-click: color picker\n- Shift+click: bud new voxel\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["0597eb7990fb162b95195726f21fa1f103587d96"],"add":459,"del":156,"cadd":459,"cdel":156,"files":1},{"repo":"operations","hash":"bb622ded0da505a5160b891a569b5319427727a6","ts":1773014412,"wall":"2026-03-08T20:00","msg":"Session 19: Soma face sculpting — handoff updated","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["fb0f609ca176538e01d0ca88bc8405cb75185db2"],"add":32,"del":10,"cadd":32,"cdel":10,"files":1},{"repo":"soma","hash":"d318526e15db3a52e7b3c12173af288d355515ca","ts":1773018493,"wall":"2026-03-08T21:08","msg":"Polygon faces via Voronoi dual + per-face edge split/collapse","body":"Replace triangle-only faces with variable-length polygon faces:\n- generatePolygonMesh via spherical Voronoi dual of convex hull\n- Fan-triangulate polygons for GPU, triToFace maps render tris to logical faces\n- Custom polygon-edge wireframe (no internal fan diagonals)\n- All face ops (color, highlight, selection, resize, budding) work on full polygons\n- Raycasting maps through triToFace automatically\n\nPer-face vertex count control (edge split/collapse):\n- Ctrl+Alt+scroll up: split longest edge (+1 vertex to face and neighbor)\n- Ctrl+Alt+scroll down: collapse shortest edge (-1 vertex, min triangle)\n- Safety checks prevent degenerate faces\n\nDropped platonic solid special cases (makeBaseGeometry) — one code path\nfor all face counts via golden spiral + Voronoi dual.\n\nUI shows polygon type: \"Face 3/12 (5-gon) — #hex\"\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["dc8d57685c183852f96197caf3e3ca34b819fb1e"],"add":368,"del":114,"cadd":368,"cdel":114,"files":1},{"repo":"soma","hash":"ad6e4d061f374933a8a8e18ea8ddfa704bc082a8","ts":1773018618,"wall":"2026-03-08T21:10","msg":"Session 20 handoff: polygon faces, edge split/collapse, data channel mapping","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["d318526e15db3a52e7b3c12173af288d355515ca"],"add":198,"del":4,"cadd":198,"cdel":4,"files":2},{"repo":"operations","hash":"132c75f24036b3cf672ab383e6ae41652876d128","ts":1773018891,"wall":"2026-03-08T21:14","msg":"Session 20: Soma polygon faces — atlas updated","body":"Dashboard and session log updated with Voronoi dual generation,\nedge split/collapse, data channel inventory, overt mode design decision.","parents":["bb622ded0da505a5160b891a569b5319427727a6"],"add":88,"del":3,"cadd":88,"cdel":3,"files":2},{"repo":"operations","hash":"cd070bcba41606d0462ce796d299eb8e275f777e","ts":1773020118,"wall":"2026-03-08T21:35","msg":"Atlas catch-up: symlinks, research corpus, tools, game design docs","body":"Symlinks (29 changes):\n- Updated 21 paths from ~/code/github.com/the-azuran/ to ~/symbiont/\n- Added 4 new: musico, robotics, rowbot, symbiontic-dialogues\n- Removed 4 dead: nevada-law-rag (→ tools/), new-belen-game (→ games/),\n  operations (self-ref), weathermap (archived)\n\nResearch (11 new docs):\n- Acoustic data communication + environment sensing\n- Azura communications toolkit (multi-modal: light, sound, radio)\n- Biofeedback instrument platform\n- Composite organism anatomy (techbiont self-study)\n- Digital avatar/VTuber pipeline\n- Immediate feedback programming (Bret Victor, HCI)\n- Iris visual codec design\n- Reticulum capabilities guide + web bridge plan\n- Zooid voxel avatar architecture (1,143 lines)\n\nTools:\n- tools/nevada-law-rag/ — Python RAG pipeline for Nevada legal docs\n- tools/iris/research/ — Iris codec design doc\n\nGames:\n- games/hexclaim/ — hex territory game design docs (5 files)\n- .gitignore updated to exclude games/mesnada/ and games/new-belen-game/\n  (independent git repos)\n\nAtlas updates:\n- projects/index.md — fixed dead links, added iris + hexclaim entries,\n  updated soma description for polygon faces\n- projects/relationships.md — added Embodiment Chain (soma + iris + tympan\n  + robotics), expanded Creative Chain, added eureka-co-nevada to Nevada/land\n- CLAUDE.md — directory layout updated for ~/symbiont/ structure\n\nFigura Amoris: Giordano Bruno unicursal hexagram (Rust source + SVG output)","parents":["132c75f24036b3cf672ab383e6ae41652876d128"],"add":8110,"del":34,"cadd":8053,"cdel":9,"files":59},{"repo":"operations","hash":"8bb037a7d64793c014896b4a7453171d07a93d29","ts":1773023349,"wall":"2026-03-08T22:29","msg":"Glyphic capacity analysis: full channel inventory and payload catalog","body":"New research doc mapping the complete data encoding space of a Soma\nvoxel body. 11 channels (43 bits/face + 127 bits/voxel), capacity\ntables for 1-200 voxel bodies, streaming bandwidth calculations,\nand a catalog of what fits: keys, text, images, code, coordinates.\n\nStatic 100-voxel body: 18.8 KB overt / 2.4 KB covert.\nStreaming: 1.9 KB/s overt, 6.6 MB/hour. With Tympan: ~10 MB/hour.\nCovert streaming: 240 B/s invisible to observers.\n\nCross-referenced from Zooid architecture spec.","parents":["cd070bcba41606d0462ce796d299eb8e275f777e"],"add":258,"del":0,"cadd":258,"cdel":0,"files":2},{"repo":"operations","hash":"e9f7b44d5bfcbd0ae893e792806af1a50257b53d","ts":1773023661,"wall":"2026-03-08T22:34","msg":"Glyphic Space: theory of embodied data geometry","body":"Formal treatment of the N-dimensional parameter space defined by all\nencodable channels of a Soma voxel body. Core insight: a path through\nglyphic space is simultaneously an animation, a data stream, and a\nnarrative. The performance IS the protocol.\n\nNew concepts: isoglyphs (bodies decoding to same payload), glyphic\nneighborhoods, aesthetic metrics, geodesic interpolation (minimum\nvisual disturbance for maximum data change), cyclic beacons.\n\nConnects to Shannon (information theory), Saussure/Peirce (semiotics),\nMcLuhan (medium theory), von Uexkuell (Umwelt). 10 open research\nquestions flagged for post-prototype investigation.","parents":["8bb037a7d64793c014896b4a7453171d07a93d29"],"add":272,"del":0,"cadd":272,"cdel":0,"files":1},{"repo":"soma","hash":"c355de5d2dc886c003d2d222a22658b4b2e210c0","ts":1773023672,"wall":"2026-03-08T22:34","msg":"Handoff: add glyphic space research queue and architecture references","body":"","parents":["ad6e4d061f374933a8a8e18ea8ddfa704bc082a8"],"add":11,"del":1,"cadd":11,"cdel":1,"files":1},{"repo":"soma","hash":"65fb246bd0df49aaff24bde895697a4964391d1a","ts":1773024657,"wall":"2026-03-08T22:50","msg":"Open all 11 data encoding channels — per-face opacity, protrusion readback, voxel rotation/meshScale/opacity/shininess","body":"New voxel properties: faceOpacities, faceProtrusions, rotation, meshScale, opacity, shininess.\nPer-face opacity via onBeforeCompile shader injection (faceAlpha vertex attribute).\nProtrusion readback via computeProtrusions (radial displacement from rest sphere).\nVoxel-level opacity + shininess sliders in side panel.\nOpacity slider in color panel per-face.\napplyFaceColors renamed applyFaceAttributes (writes color + alpha).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c355de5d2dc886c003d2d222a22658b4b2e210c0"],"add":136,"del":7,"cadd":136,"cdel":7,"files":1},{"repo":"soma","hash":"9fc455da430e20be049f36a6af09857b350443d6","ts":1773024736,"wall":"2026-03-08T22:52","msg":"Session 21 handoff: all 11 data encoding channels opened","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["65fb246bd0df49aaff24bde895697a4964391d1a"],"add":94,"del":103,"cadd":94,"cdel":103,"files":1},{"repo":"operations","hash":"f0deaed03a428a77a6cfa214e55e0bffdc3a7915","ts":1773024924,"wall":"2026-03-08T22:55","msg":"Session 20–21: atlas updated — Soma channels opened, glyphic space research","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["e9f7b44d5bfcbd0ae893e792806af1a50257b53d"],"add":46,"del":1,"cadd":46,"cdel":1,"files":2},{"repo":"operations","hash":"98d46b0ba95ef0102cfade6e374b1dc0ea2ec365","ts":1773027149,"wall":"2026-03-08T23:32","msg":"Glyphic space §8: metabolism — data as substrate, furrowing inheritance, 7 emergent properties","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["f0deaed03a428a77a6cfa214e55e0bffdc3a7915"],"add":65,"del":3,"cadd":65,"cdel":3,"files":1},{"repo":"soma","hash":"871bc938069c2a20c81633a8b7cbfbf95b109902","ts":1773027159,"wall":"2026-03-08T23:32","msg":"Scale slider controls hovered voxel live, shininess specular visible, buds inherit parent scale","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["9fc455da430e20be049f36a6af09857b350443d6"],"add":16,"del":6,"cadd":16,"cdel":6,"files":1},{"repo":"soma","hash":"dc5bf3e8cd019e3184b99870b408c6547c6dcab8","ts":1773027224,"wall":"2026-03-08T23:33","msg":"Session 21 handoff: channels, scale/shininess fixes, furrow plan, gesture map","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["871bc938069c2a20c81633a8b7cbfbf95b109902"],"add":77,"del":80,"cadd":77,"cdel":80,"files":1},{"repo":"soma","hash":"6059c29ee19470a86aa60ace828c089f2bd9101f","ts":1773028333,"wall":"2026-03-08T23:52","msg":"Furrowing (cytokinesis): F key splits voxel into two rounded daughters along equatorial plane","body":"New functions: furrowVoxel, computeFurrowPlane (PCA), partitionFaces, computePlaneIntersections,\nbuildDaughterGeometry, clipFaceByPlane, createVoxelFromGeometry, removeVoxel.\nClosing face split into triangle fans from centroid hub for robust sphere projection.\nDaughters inherit parent colors/opacities; closing faces get averaged parent data.\nDoubleSide material. Clear stale highlight after face count change.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["dc5bf3e8cd019e3184b99870b408c6547c6dcab8"],"add":328,"del":1,"cadd":328,"cdel":1,"files":1},{"repo":"soma","hash":"8c743c7b01455f7eea13496d80dd13e62198aabc","ts":1773028390,"wall":"2026-03-08T23:53","msg":"Session 21 handoff: furrowing shipped, full gesture map, open issues","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["6059c29ee19470a86aa60ace828c089f2bd9101f"],"add":63,"del":73,"cadd":63,"cdel":73,"files":1},{"repo":"operations","hash":"d5bcd9f2dd8d8c982ce6990f474fe1a7a747610f","ts":1773028407,"wall":"2026-03-08T23:53","msg":"Dashboard: Soma — furrowing shipped","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["98d46b0ba95ef0102cfade6e374b1dc0ea2ec365"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"soma","hash":"70cbb40f7de464f20f3b61a09599861a9994fcf4","ts":1773034146,"wall":"2026-03-09T01:29","msg":"Session 22: triple surgery + face-to-face linking + furrowing fixes","body":"Daughter inheritance: furrowed daughters inherit parent rotation, meshScale,\nopacity, shininess, and per-face protrusions (not just colors/opacities).\n\nOrphan vertex cleanup: pruneUnusedVertices() runs on every topology change,\npreventing vertex accumulation after edge collapse.\n\nR+drag rotation: hold R and drag to rotate voxel around its center. Rotation\nvalues persist to the data channel.\n\nHighlight removal: hover highlight disabled (was causing ghost overlays).\nclearHighlight() added to rebuildAfterTopologyChange and furrowVoxel.\n\nEdge split/collapse gesture: changed from Ctrl+Alt+scroll (KDE conflict) to\n+/- keys. Splits now project affected vertices onto sphere for visible 3D\ndeformation.\n\nFace-to-face linking (L key): two-step workflow — L on source face (gold\nindicator), L on target face. Merges two voxels into one: vertex counts\nmatched, dst aligned (rotation + translation), all vertices converted to\nworld space, linked faces removed (interior), boundary vertices welded,\ncompound flag set on merged voxel.\n\nFurrowing fixes: closing face is now a single N-gon (not triangle fan),\nsphere projection uses origin (not biased vertex centroid), compound flag\non daughters. transferDeformations bails on non-standard geometry.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["8c743c7b01455f7eea13496d80dd13e62198aabc"],"add":342,"del":65,"cadd":342,"cdel":65,"files":1},{"repo":"soma","hash":"eab76a1fa92da7bbfa4d057310ee27b87d5cf566","ts":1773034260,"wall":"2026-03-09T01:31","msg":"Session 22 handoff: linking, furrowing fixes, 5 issues filed","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["70cbb40f7de464f20f3b61a09599861a9994fcf4"],"add":56,"del":85,"cadd":56,"cdel":85,"files":1},{"repo":"operations","hash":"2005300eb42bee555d497cf0e124b9c209727288","ts":1773034292,"wall":"2026-03-09T01:31","msg":"Dashboard: Soma session 22 — linking shipped, 5 issues filed","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["d5bcd9f2dd8d8c982ce6990f474fe1a7a747610f"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"operations","hash":"1d1f58008b92dd7336dfe31c208adcbb095a2450","ts":1773070721,"wall":"2026-03-09T11:38","msg":"Research: voxel face identity tagging — ECS, biology, Blender/Houdini patterns","body":"Cross-domain research into per-face provenance tracking for Soma.\nCovers ECS monotonic IDs, biological CellTag/Brainbow lineage,\ngit content-hash identity (anti-pattern), database event sourcing,\nand Blender/Houdini integer primitive attributes. Converges on\nvoxel-origin-ID pattern: one integer per face, scroll guard by\nchecking uniqueness.","parents":["2005300eb42bee555d497cf0e124b9c209727288"],"add":181,"del":0,"cadd":181,"cdel":0,"files":1},{"repo":"soma","hash":"e9f35bdbefb343bb3b5bd08aa68ee6cfae29ee41","ts":1773070787,"wall":"2026-03-09T11:39","msg":"Session 23: face group IDs, linking alignment, hover fix, Euler operators","body":"Face identity system (faceGroups):\n- Per-face integer group ID tracks voxel origin\n- Scroll guard: multi-group voxels block regeneration\n- Propagated through all topology operations\n\nLinking alignment (issue #2):\n- In-plane rotation via 2D cross-covariance\n- Arc-length boundary resampling replaces edge splitting\n- Explicit vertex pairing with winding reversal replaces threshold welding\n\nLocal topology (Euler operators):\n- splitFace: insert diagonal, split polygon into two\n- joinFaces: dissolve shared edge, merge two polygons\n- addFace/removeFace: auto-select best split/join target\n- findSharedEdge, polygonFaceArea helpers\n\nHover fix:\n- rebuildAfterTopologyChange re-establishes hover state\n- +/- keys work for consecutive presses without re-hovering\n\nPending: furrow daughters need fresh voxelId stamped on all faces","parents":["eab76a1fa92da7bbfa4d057310ee27b87d5cf566"],"add":322,"del":42,"cadd":322,"cdel":42,"files":1},{"repo":"soma","hash":"0f12660329b6489d7fbc6a324b92f9726e468d4e","ts":1773070926,"wall":"2026-03-09T11:42","msg":"Session 23 handoff: face group IDs, alignment, Euler operators, 6 issues","body":"","parents":["e9f35bdbefb343bb3b5bd08aa68ee6cfae29ee41"],"add":38,"del":45,"cadd":38,"cdel":45,"files":1},{"repo":"researcher-graph","hash":"53a8afc24d3f7054d34195ea1315d43141dfa7d5","ts":1773079584,"wall":"2026-03-09T14:06","msg":"Initial commit: researcher tracking with scoring, network analysis, and discovery","body":"SQLite-backed structured database for tracking researchers, their work,\nfunding, lineage, and connections to Symbiont Systems projects. Configurable\nrelevance scoring, staleness detection, NetworkX graph analysis, domain\nbridge detection, lineage gap discovery, and funding pattern analysis.\n\n50 tests passing. 43 researchers imported from operations/researchers.json.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":1557,"del":0,"cadd":1548,"cdel":0,"files":18},{"repo":"persian-gulf-theater","hash":"bb11fc1419a9b9c367f7ea9862751c34e16dc08f","ts":1773082277,"wall":"2026-03-09T14:51","msg":"Days 8-10 sitrep, Day 10 assessment — energy war opened, oil $110+, 8 US dead","body":"New: events/2026-03-09-sitrep.md (Days 8-10 consolidated)\nNew: assessments/2026-03-09-day10.md (Day 10 war scorecard)\nUpdated: timeline, munitions analysis, README\n\nKey developments: Iran oil infrastructure struck (first time), Mojtaba\ninstalled as Supreme Leader, Iron Beam first combat use, Brent $119.50\nintraday, G7 SPR coordination, CSIS $3.7B/100h burn estimate, Hezbollah\nno-warning strike on central Israel, 8th US service member killed.","parents":["71667f16369f23746d7d8a844d0ed54766da80d3"],"add":684,"del":23,"cadd":684,"cdel":23,"files":5},{"repo":"operations","hash":"77f471af13034715f148e80037ba9332554235ec","ts":1773102883,"wall":"2026-03-09T20:34","msg":"Research: math toys, voxel genetics, cellular automaton theory","body":"Three new research documents forming Soma's theoretical framework:\n\n- math-toys-glyphic-space.md: 21 mathematical primitives as voxel\n  behavioral modes, 5-property definition, toy modes as cell\n  differentiation, boundary interaction protocols\n\n- voxel-genetics.md: Unified biological framework — gene structure\n  (locus, lineage/telomeres, codon triplets with wobble degeneracy,\n  methylation, plasmids), 10 genetic operations (mitosis, budding,\n  linking, mutation, recombination, meiosis, apoptosis, HGT, viral\n  infection, CRISPR), substrate model (compute=oxygen, data=food,\n  clay vs alive modes), 8-phase implementation roadmap\n\n- soma-cellular-automaton-theory.md: Soma as autopoietic Class V\n  cellular automaton — dynamic topology, continuous state, per-cell\n  mutable self-modifying rules, von Neumann self-reproduction,\n  Maturana/Varela autopoiesis criteria, algorithmic chemistry,\n  information-theoretic analysis, comparison with 7 ALife systems\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["1d1f58008b92dd7336dfe31c208adcbb095a2450"],"add":2572,"del":0,"cadd":2572,"cdel":0,"files":3},{"repo":"operations","hash":"91791c8adcf228f18d4cde2c9f4ea8b943887ddf","ts":1773126812,"wall":"2026-03-10T03:13","msg":"phonectl: remote phone control daemon + client library","body":"Flask-based HTTP API running in Termux on the Ulefone Power Armor 19T.\nExposes camera (108MP, FLIR thermal, microscope), sensors, GPS, TTS,\nflashlight, vibration, notifications, and a fullscreen display surface.\nClient library provides Python API for workstation control.\n\nAlso includes AI-driven 3D printing research notes.","parents":["77f471af13034715f148e80037ba9332554235ec"],"add":600,"del":0,"cadd":600,"cdel":0,"files":4},{"repo":"operations","hash":"5c2bb65c4ad807f4726d1938bb3b747e2c813a8c","ts":1773127083,"wall":"2026-03-10T03:18","msg":"Handoff: session 20 — phonectl daemon, phone integration","body":"Phone (Ulefone Power Armor 19T) connected as composite organism\nsensor node. SSH, vibration, TTS, thermal imaging all verified.","parents":["91791c8adcf228f18d4cde2c9f4ea8b943887ddf"],"add":68,"del":49,"cadd":68,"cdel":49,"files":1},{"repo":"operations","hash":"146db7d60dda4eec2df65d232a3b3c69067cd876","ts":1773156214,"wall":"2026-03-10T11:23","msg":"tezcatlipoca: rename phonectl, add voice endpoint, debloat phone","body":"The smoking mirror. Renamed phonectl → tezcatlipoca across daemon,\nclient, and phone-side service. Added localhost-only /voice endpoint\nfor on-device TTS via SwiftKey. Removed 32 bloatware packages from\nphone (Google, T-Mobile, Ulefone), disabled Google telemetry settings.\nAll 16 hardware sensors verified healthy.","parents":["5c2bb65c4ad807f4726d1938bb3b747e2c813a8c"],"add":175,"del":73,"cadd":136,"cdel":61,"files":5},{"repo":"operations","hash":"b3d1e49c029f43fd9d5f4d48914ebbf92c749652","ts":1773157653,"wall":"2026-03-10T11:47","msg":"Rename tezcatlipoca → reflex — biological naming for daemons","body":"Theological names reserved for sacred use. Daemons are autonomic\norgan functions, named for what they do: reflex (sensory reflex arc)\non the phone, pulse (heartbeat) on the workstation (future).","parents":["146db7d60dda4eec2df65d232a3b3c69067cd876"],"add":14,"del":14,"cadd":2,"cdel":2,"files":4},{"repo":"reflex","hash":"a0fb075e775f61e1d57a38466f0d5d6bec7e6bc6","ts":1773167315,"wall":"2026-03-10T14:28","msg":"reflex: native Android app — sensory daemon for Simutron t19x","body":"Kotlin + Jetpack Compose app replacing the Termux-based daemon.\nDirect Android API access for sensors, cameras, TTS, torch, haptics.\nEmbedded Ktor HTTP server on port 8000 for workstation control.\nFour-tab UI: Voice, Controls, Sensors, System. Foreground service\nwith boot receiver for auto-start.\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":[],"add":1425,"del":0,"cadd":874,"cdel":0,"files":24},{"repo":"operations","hash":"218e3e23442a230a9671e418dae271e3eea05504","ts":1773167712,"wall":"2026-03-10T14:35","msg":"Handoff: session 21 — reflex native app, bloatware removal, naming conventions","body":"","parents":["b3d1e49c029f43fd9d5f4d48914ebbf92c749652"],"add":76,"del":43,"cadd":76,"cdel":43,"files":1},{"repo":"reflex","hash":"3fb9446da66ca43d43983c1ac92df3dccadb574c","ts":1773174782,"wall":"2026-03-10T16:33","msg":"reflex: CIO engine fix, domain-split architecture, new endpoints","body":"Fix crash: Netty → CIO engine (eliminates BindException and SELinux\nsomaxconn noise), add double-start guard, try-catch on server bind,\nSTART_NOT_STICKY to prevent crash loops.\n\nSplit monolithic HardwareAccess into 8 domain modules (Sensors, Camera,\nAudio, Display, Haptics, Power, Speech, SystemInfo) with matching route\nfiles. Each physical domain is one file — any agent lands in exactly\nthe right place.\n\nNew endpoints: /camera (lists all 4), /audio/volumes, /audio/ringer,\n/display (brightness + permission status), /power (extended battery),\n/system (device info), /system/memory, /system/storage, /haptics/info.\n\nFix sensor lookup: query by type name (\"pressure\", \"light\") or chip\nname (\"spl07\", \"stk3a5x_als\"). Response distinguishes chip vs type.\n\nAdd docs: hardware-inventory.md (full parameter survey),\nsmartphone-as-object.md (physical capability analysis).","parents":["a0fb075e775f61e1d57a38466f0d5d6bec7e6bc6"],"add":1214,"del":216,"cadd":1213,"cdel":214,"files":21},{"repo":"reflex","hash":"5136e1ea4187e91a19c032641f7bd23672f0cfa5","ts":1773188353,"wall":"2026-03-10T20:19","msg":"reflex: Phase 1 MENDING — permissions, auth, module sharing, cleanup","body":"Runtime permission system requests all permissions on launch and\nreports grant status via /status endpoint. API key auth enforced\non all endpoints except /status. Hardware modules moved to ReflexApp\nsingleton — eliminates duplicate CameraManager, Vibrator, and TTS\ninstances in ControlsScreen and VoiceScreen. SystemScreen shows real\ndaemon status and API key with copy button. API version 0.4.0.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["3fb9446da66ca43d43983c1ac92df3dccadb574c"],"add":243,"del":64,"cadd":223,"cdel":64,"files":10},{"repo":"operations","hash":"05b64831198cde128bfe8da0296e918185294631","ts":1773188379,"wall":"2026-03-10T20:19","msg":"reflex_client: update for native app auth, remove legacy Termux paths","body":"Remove Termux key discovery, dead methods (shell, display, notify).\nAdd REFLEX_API_KEY env var support. Status endpoint is now unauthenticated.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["218e3e23442a230a9671e418dae271e3eea05504"],"add":13,"del":28,"cadd":13,"cdel":28,"files":1},{"repo":"reflex","hash":"07a8086bded9f888c5f6f963a69237b6602428ec","ts":1773190434,"wall":"2026-03-10T20:53","msg":"reflex: Phase 2 INNERVATION — cameras, GPS, microphone, sensor streaming","body":"All 4 cameras operational via Camera2 API (headless capture from service).\nCamera 0: 108MP main (12000x9000). Cameras 2-3: auxiliary, 2560x1920,\nneed visual identification (FLIR vs microscope). GPS via\nFusedLocationProvider with fresh fix and last-known endpoints. Microphone\nrecording to AAC/M4A via MediaRecorder. WebSocket sensor streaming at\nws://phone:8000/sensors/{name}/stream for real-time data. Foreground\nservice type expanded to camera|location|microphone to support\nbackground hardware access.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5136e1ea4187e91a19c032641f7bd23672f0cfa5"],"add":468,"del":13,"cadd":462,"cdel":12,"files":12},{"repo":"iris","hash":"6124e9270c806088aec8188dbdbf872f254d7153","ts":1773192171,"wall":"2026-03-10T21:22","msg":"iris: extract from operations/tools/iris — photochromaglyphic visual codec","body":"","parents":[],"add":2920,"del":0,"cadd":1764,"cdel":0,"files":21},{"repo":"somaphore","hash":"19033fc52d5e3271810d710fa81a1888703b8738","ts":1773192261,"wall":"2026-03-10T21:24","msg":"somaphore: initial repo — submodules (reflex, soma) + research docs","body":"","parents":[],"add":5669,"del":0,"cadd":5661,"cdel":0,"files":11},{"repo":"somaphore","hash":"791616a7eaaaf2c3f619fd15c4a81ff258f681de","ts":1773192297,"wall":"2026-03-10T21:24","msg":"somaphore: add iris submodule — visual codec extracted to own repo","body":"","parents":["19033fc52d5e3271810d710fa81a1888703b8738"],"add":4,"del":0,"cadd":0,"cdel":0,"files":2},{"repo":"somaphore","hash":"a428dc14b3389e3f393cd766456c615d747a8ef1","ts":1773192585,"wall":"2026-03-10T21:29","msg":"somaphore: master plan — 7 phases from TRANSDUCTION to UMWELT","body":"","parents":["791616a7eaaaf2c3f619fd15c4a81ff258f681de"],"add":359,"del":3,"cadd":359,"cdel":3,"files":2},{"repo":"reflex","hash":"d33fcbfeb985ee8fe4763dbc26f03a13100c4ac5","ts":1773193753,"wall":"2026-03-10T21:49","msg":"reflex: Phase 3.0 TRANSDUCTION — permission onboarding gate","body":"Permission onboarding screen on first launch requests all runtime\npermissions (camera, mic, location, sensors, bluetooth) plus\nWRITE_SETTINGS special permission via system Settings intent.\n\n- PermissionScreen.kt: Compose onboarding with grant/deny/skip flow\n- MainActivity.kt: show onboarding before starting daemon service\n- Permissions.kt: route guard utilities (requirePermission, requireWriteSettings)\n- All protected routes return 403 with clear message if permission missing\n- WRITE_SETTINGS added to manifest (special permission, intent-based grant)\n- Build verified: assembleDebug passes clean","parents":["07a8086bded9f888c5f6f963a69237b6602428ec"],"add":324,"del":36,"cadd":318,"cdel":35,"files":8},{"repo":"somaphore","hash":"758cb86008042c693e6196a3c6f1da5758b456c9","ts":1773193775,"wall":"2026-03-10T21:49","msg":"reflex: bump to d33fcbf — Phase 3.0 permission onboarding","body":"","parents":["a428dc14b3389e3f393cd766456c615d747a8ef1"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"operations","hash":"029e6b309b5463097d77edb20b799fbb2ae2a8ec","ts":1773195198,"wall":"2026-03-10T22:13","msg":"atlas: add somaphore, iris, reflex — Embodiment Chain updated","body":"- projects/index.md: somaphore orchestration repo + iris extracted to own repo\n- projects/relationships.md: Embodiment Chain now includes somaphore + reflex\n- status/dashboard.md: somaphore row added\n- projects/links/: symlinks for somaphore, iris, reflex","parents":["05b64831198cde128bfe8da0296e918185294631"],"add":10,"del":3,"cadd":7,"cdel":3,"files":6},{"repo":"reflex","hash":"09a20f20bf08cda74a1c593c2faf2b5a766e5767","ts":1773198146,"wall":"2026-03-10T23:02","msg":"reflex: Phase 3.1 TRANSDUCTION — AudioPlayer with recursive sine + tone routes","body":"Recursive sine oscillator (from Musico drums.rs pattern) replaces sin()\nper-sample. 1ms fade ramps prevent clicks. Wired into ReflexApp, routes,\nand service. New endpoints: POST /audio/tone, POST /audio/stop,\nGET /audio/playing. Verified on device: 440Hz audible, 19kHz ultrasonic.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d33fcbfeb985ee8fe4763dbc26f03a13100c4ac5"],"add":155,"del":2,"cadd":155,"cdel":2,"files":4},{"repo":"somaphore","hash":"96d3bc60138e8667a67a88a39715f59119861ff0","ts":1773198147,"wall":"2026-03-10T23:02","msg":"research: ultrasonic wildlife deterrence appendix","body":"Field observation: 19kHz at 0.8 amplitude causes perceptible head pressure.\nDocuments animal hearing ranges, deterrence patterns, and design\nconsiderations for property defense using the reflex tone endpoint.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["758cb86008042c693e6196a3c6f1da5758b456c9"],"add":31,"del":0,"cadd":31,"cdel":0,"files":1},{"repo":"operations","hash":"5387a83f80615e1a0440e70eff333e57cb253a07","ts":1773198148,"wall":"2026-03-10T23:02","msg":"Handoff: session 23 — AudioPlayer wired, ultrasonic deterrence research","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["029e6b309b5463097d77edb20b799fbb2ae2a8ec"],"add":82,"del":92,"cadd":82,"cdel":92,"files":1},{"repo":"operations","hash":"c9d0f3e12aa136a6a8758a4c5561ddda4e8cf084","ts":1773198148,"wall":"2026-03-10T23:02","msg":"Handoff: session 23 — Phase 3 TRANSDUCTION complete","body":"AudioPlayer wired (recursive sine, tone routes), full-screen image\ndisplay (Iris effector), ultrasonic deterrence research, Teledyne\nFLIR SDK access confirmed.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5387a83f80615e1a0440e70eff333e57cb253a07"],"add":61,"del":46,"cadd":61,"cdel":46,"files":1},{"repo":"reflex","hash":"5025c2a847d9ad05a884184922cfec466e3a5407","ts":1773199928,"wall":"2026-03-10T23:32","msg":"reflex: Phase 3.2 TRANSDUCTION — full-screen image display (Iris effector)","body":"New ImageDisplayActivity for edge-to-edge image rendering with no\nsystem chrome. POST /display/image accepts image bytes, displays\nfull-screen. POST /display/clear dismisses. GET /display/showing\nreturns state. Phone screen is now a programmable visual data\nsurface for Iris codec transmission.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["09a20f20bf08cda74a1c593c2faf2b5a766e5767"],"add":123,"del":0,"cadd":118,"cdel":0,"files":3},{"repo":"somaphore","hash":"14a5a2c53a52ca7eb6cb22ebec7e2e22b96a7713","ts":1773203169,"wall":"2026-03-11T00:26","msg":"research: transducer integration — FLIR SDK, controller, transceiver UI","body":"New research docs for Phase 4 planning:\n- transducer-integration-flir-controller-ui.md: Full API surface map of\n  FLIR Atlas C SDK, 8BitDo controller Ganglion integration, and mode-based\n  transceiver UI architecture replacing the current debug panel\n- ganglion-nervous-system-architecture.md: Biological nervous system\n  models applied to NATS event bus design\n- ganglion-adr-nats-over-custom-hub.md: ADR for NATS selection\n\nAlso adds 8BitDo controller hardware inventory to docs/.","parents":["96d3bc60138e8667a67a88a39715f59119861ff0"],"add":1288,"del":0,"cadd":1288,"cdel":0,"files":4},{"repo":"reflex","hash":"9db40af2310519cf9c4611eaa2b01ffad2f3fa6a","ts":1773204464,"wall":"2026-03-11T00:47","msg":"reflex: Phase 3.3 TRANSDUCTION — streaming, playback, display, haptics","body":"MicStream: raw 48kHz PCM via AudioRecord (WebSocket /audio/stream)\nAudioPlayer: file playback (POST /audio/play), raw PCM injection (POST /audio/pcm)\nDisplay: wake lock (POST /display/wake, /display/sleep), info (GET /display/info)\nHaptics: vibration patterns (POST /haptics/pattern)\n\nAll 6 Phase 3 verification criteria now satisfiable.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5025c2a847d9ad05a884184922cfec466e3a5407"],"add":306,"del":3,"cadd":306,"cdel":3,"files":8},{"repo":"somaphore","hash":"cf1fb37c507410a5e908c4e588cc4c65cfd26f13","ts":1773204483,"wall":"2026-03-11T00:48","msg":"submodule: update reflex to Phase 3.3 (9db40af)","body":"Picks up 3.1 (AudioPlayer/tone), 3.2 (ImageDisplay), 3.3 (streaming/playback/display/haptics).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["14a5a2c53a52ca7eb6cb22ebec7e2e22b96a7713"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"somaphore","hash":"d4179be22a9bd47017527ae30bc5eb712cce08a7","ts":1773204982,"wall":"2026-03-11T00:56","msg":"plans: Phase 3 TRANSDUCTION checklist — mark completed items","body":"28 of 32 checklist items done. Remaining: camera ID (FLIR/microscope),\ncamera stream, 48kHz mic verification, speaker frequency response test.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["cf1fb37c507410a5e908c4e588cc4c65cfd26f13"],"add":33,"del":33,"cadd":33,"cdel":33,"files":1},{"repo":"operations","hash":"6368328895afebd73b7e839116cd4626b9373d5b","ts":1773205004,"wall":"2026-03-11T00:56","msg":"Handoff: session 24 — Phase 3.3 TRANSDUCTION complete","body":"MicStream (raw PCM), audio playback, display wake/sleep, haptic patterns.\nAll 6 Phase 3 verification criteria satisfiable. Deploy + on-phone test next.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c9d0f3e12aa136a6a8758a4c5561ddda4e8cf084"],"add":61,"del":44,"cadd":61,"cdel":44,"files":1},{"repo":"reflex","hash":"944cce10044bf14b6f89628278191c4e47cb9292","ts":1773205505,"wall":"2026-03-11T01:05","msg":"reflex: fix Display.getInfo() — use WindowManager for service context","body":"context.display is null in Service context on Android 12.\nUse WindowManager.defaultDisplay instead. Convert Float to Double\nfor Gson serialization.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["9db40af2310519cf9c4611eaa2b01ffad2f3fa6a"],"add":10,"del":9,"cadd":10,"cdel":9,"files":1},{"repo":"somaphore","hash":"5b98adc3a890554af2ed0a257ce48a129d32ee20","ts":1773206984,"wall":"2026-03-11T01:29","msg":"research: hex dataflow architecture — unifying interface design","body":"Every parameter is a hex node. Two grids (2D control surface, 3D Soma body)\nare projections of the same dataflow graph. Links = gateways = data flow.\nRedefines Phases 4-7 as hex node types within a single compositional system.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d4179be22a9bd47017527ae30bc5eb712cce08a7"],"add":439,"del":0,"cadd":439,"cdel":0,"files":1},{"repo":"somaphore","hash":"97fabb6de67c1ee036b04a318a0b4ba954e0b0c9","ts":1773275539,"wall":"2026-03-11T20:32","msg":"cell-core: Phase 1 — data model, graph, serialization (27 tests)","body":"Polygonal logic engine where geometry IS the type system.\nCells with 3-8 sides, partition-validated ports, reactive dirty\ntracking, serde JSON roundtrip. Research doc and implementation\nplan included.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5b98adc3a890554af2ed0a257ce48a129d32ee20"],"add":2120,"del":0,"cadd":2002,"cdel":0,"files":12},{"repo":"somaphore","hash":"e1b4a4784980bb63686b6ba5f26022171f37e39a","ts":1773276191,"wall":"2026-03-11T20:43","msg":"cell-core: Phase 2 — evaluate loop, transforms, coordinates (60 tests)","body":"Reactive dataflow engine: topological sort, dirty propagation,\none-frame delay for cycles. 12 starter transforms (passthrough,\nadd, multiply, NAND, threshold, latch, accumulate, smooth, sum,\nmean, identity3, negate3). Axial coordinate system ported from\nhex-tessellation. Sources with no connected inputs preserve their\nexternally-set values. Multi-output port indexing correct.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["97fabb6de67c1ee036b04a318a0b4ba954e0b0c9"],"add":1177,"del":2,"cadd":1177,"cdel":2,"files":7},{"repo":"somaphore","hash":"42ecee65c239be5f5108724d8d42ff5c18f49a14","ts":1773276544,"wall":"2026-03-11T20:49","msg":"Handoff: session 26 — Cell Phase 1+2 complete (60 tests)","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["e1b4a4784980bb63686b6ba5f26022171f37e39a"],"add":108,"del":0,"cadd":108,"cdel":0,"files":1},{"repo":"operations","hash":"6e1d5254a65d4c30fa94e8823081d90dfc83edc0","ts":1773276563,"wall":"2026-03-11T20:49","msg":"Handoff: session 26 — Cell engine work in somaphore","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["6368328895afebd73b7e839116cd4626b9373d5b"],"add":24,"del":105,"cadd":24,"cdel":105,"files":1},{"repo":"somaphore","hash":"5ee90969c42b451cb87982f2b1f987be56ec59b4","ts":1773280607,"wall":"2026-03-11T21:56","msg":"cell-core: Phase C3 — GlobalNodeId, boundary ports, distributed addressing (68 tests)","body":"Refactor NodeId to GlobalNodeId(HostId, u64) for foreign entity addressing.\nAdd Port enum (Link | Boundary | Empty) replacing Option<PortLink>.\nBoundaryPort maps to Zenoh key expressions for network bridging.\nEval loop only follows local links; remote targets skipped for cell-net.\nCellGraph::inject_value() for external value injection.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["42ecee65c239be5f5108724d8d42ff5c18f49a14"],"add":419,"del":191,"cadd":419,"cdel":191,"files":8},{"repo":"somaphore","hash":"5036806fffd39816fd7a8871c435f677910fc4b5","ts":1773280744,"wall":"2026-03-11T21:59","msg":"cell-net: Phase C4 — Zenoh transport layer, CellBridge, wire format (5 tests)","body":"CellBridge wraps CellGraph + Zenoh session for distributed evaluation.\nBoundary ports map to Zenoh key expressions. MessagePack wire format\ncarries GlobalNodeId + value + frame counter between hosts.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5ee90969c42b451cb87982f2b1f987be56ec59b4"],"add":4672,"del":0,"cadd":543,"cdel":0,"files":7},{"repo":"somaphore","hash":"7d2db402182f06026644def525d63e5d38747932","ts":1773280760,"wall":"2026-03-11T21:59","msg":"plans: update master plan and implementation docs for C3/C4 completion","body":"- Cell Engine workstream added to master plan (phases C1-C7)\n- Polygonal logic implementation plan rewritten for distributed-first arch\n- Ganglion ADR marked superseded (Zenoh replaces NATS)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5036806fffd39816fd7a8871c435f677910fc4b5"],"add":236,"del":337,"cadd":236,"cdel":337,"files":3},{"repo":"somaphore","hash":"76cf3d37fda98bba1157f5c2e80df2942347ca70","ts":1773280815,"wall":"2026-03-11T22:00","msg":"Handoff: session 27 — Cell C3+C4 complete, distributed graph operational","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["7d2db402182f06026644def525d63e5d38747932"],"add":54,"del":52,"cadd":54,"cdel":52,"files":1},{"repo":"somaphore","hash":"71a9095a593a46b7d9ea7b31116a7b913e0e833f","ts":1773284700,"wall":"2026-03-11T23:05","msg":"cell-core: Phase C5 — Archimedean tilings + Goldberg polyhedra (24 tiling tests)","body":"Five Archimedean tilings (Hex, Trihexagonal, TruncatedSquare,\nSnubHexagonal with chirality, Rhombitrihexagonal) and Goldberg\npolyhedra G(h,k) with correct face counts. CCW vertex winding\nfor GPU front-face detection, edge adjacency computation, and\npopulate_graph() bridge to CellGraph.\n\n92 cell-core tests passing, clippy clean.","parents":["76cf3d37fda98bba1157f5c2e80df2942347ca70"],"add":1507,"del":0,"cadd":1507,"cdel":0,"files":2},{"repo":"somaphore","hash":"a3e6954a78dc7c17432bfcd43c8953433c5f37a1","ts":1773284886,"wall":"2026-03-11T23:08","msg":"Handoff: session 28 — Cell C5 complete, C6 next","body":"C5 shipped: 5 Archimedean tilings + Goldberg polyhedra (24 tests).\n97 total tests passing, clippy clean. Forgejo issue #1 for C6.","parents":["71a9095a593a46b7d9ea7b31116a7b913e0e833f"],"add":37,"del":48,"cadd":37,"cdel":48,"files":2},{"repo":"somaphore","hash":"d14c8a67183eefd0cc365c0fa61f8efd99700788","ts":1773287922,"wall":"2026-03-11T23:58","msg":"cell-render: Phase C6 — wgpu renderer, Soma unified (18 tests)","body":"New crate: lib/cell-render/ — GPU polygon renderer for CellGraph.\nRenders flat tilings (ortho) and Goldberg bodies (perspective)\nthrough a single wgpu pipeline. Soma is now a CellGraph with\nGoldberg topology rendered here; Three.js Soma superseded.\n\nModules: mesh (fan triangulation), color (scalar ramp + RGB),\ncamera (ortho + perspective + orbit), pipeline (wgpu + WGSL),\napp (winit event loop, eval-per-frame).\n\nArchitectural decision locked: C7 (WASM bridge) eliminated.","parents":["a3e6954a78dc7c17432bfcd43c8953433c5f37a1"],"add":11644,"del":26,"cadd":1222,"cdel":26,"files":2935},{"repo":"somaphore","hash":"40ba73028340bd5e370e5e83dae30afb9d7008e4","ts":1773287953,"wall":"2026-03-11T23:59","msg":"Add .gitignore, remove committed target/ artifacts","body":"","parents":["d14c8a67183eefd0cc365c0fa61f8efd99700788"],"add":3,"del":10424,"cadd":0,"cdel":35,"files":2927},{"repo":"somaphore","hash":"a2d9dc35ec66dea0c0bc216cf0b2a0783d1088df","ts":1773288995,"wall":"2026-03-12T00:16","msg":"cell-render: tick callback + animated hex ripple example","body":"Add TickFn callback to RenderConfig — called before evaluate()\neach frame with elapsed seconds. Examples can inject time-varying\nvalues into the graph for live animation.\n\nhex example: three-layer ripple (concentric rings, rotating spiral,\nglobal breath) driven by sin(time + distance). Prefer HighPerformance\nGPU adapter.","parents":["40ba73028340bd5e370e5e83dae30afb9d7008e4"],"add":113,"del":1,"cadd":113,"cdel":1,"files":2},{"repo":"somaphore","hash":"f340210e5b719c002ac1ee23c8b9389c2ade5386","ts":1773291524,"wall":"2026-03-12T00:58","msg":"cell-render: interactive interface — select, zoom, inject, link (47 tests)","body":"Phase 1: Click-to-select with hit testing (convex polygon cross-product).\nPhase 2: Scroll zoom + middle-drag pan with clamped extents.\nPhase 3: Keyboard value injection (0-9, -), transform cycling (T), pause (Space).\nPhase 4: Link mode (L) — click port edges to wire cells, rendered as LineList.\n\nNew modules: hit.rs, port.rs, lines.rs. Line pipeline in pipeline.rs.\nTests: 47 total (was 22), clippy clean.","parents":["a2d9dc35ec66dea0c0bc216cf0b2a0783d1088df"],"add":896,"del":5,"cadd":896,"cdel":5,"files":8},{"repo":"somaphore","hash":"d775306d85d4f8a8c0965bfe023257a9de497c47","ts":1773291574,"wall":"2026-03-12T00:59","msg":"Handoff: session 29 — cell-render interactive interface complete","body":"","parents":["f340210e5b719c002ac1ee23c8b9389c2ade5386"],"add":40,"del":33,"cadd":40,"cdel":33,"files":1},{"repo":"somaphore","hash":"988f9af8283cce070d60c0bfd43038f22877a326","ts":1773293357,"wall":"2026-03-12T01:29","msg":"Soma Rust port: ADR-0001, gene model, voxel geometry (84 tests)","body":"ADR-0001: Drop face scrolling and edge split/collapse. Topology fixed\nat birth. Furrowing + linking are the only operations. NodeId = locus.\n\ngene.rs: Per-cell identity — locus, lineage, allele, methylation,\nBrainbow strain color. 11 tests.\n\nvoxel.rs: Golden spiral seeds + incremental convex hull + Voronoi dual.\nGenerates arbitrary-face-count polyhedra on unit sphere. 12 tests.\n\nCell struct gains gene and face_groups fields.","parents":["d775306d85d4f8a8c0965bfe023257a9de497c47"],"add":1022,"del":0,"cadd":1022,"cdel":0,"files":6},{"repo":"somaphore","hash":"a525f51489be5e383a19c64a809eef535c581748","ts":1773299347,"wall":"2026-03-12T03:09","msg":"Handoff: session 29 — Soma Rust port S1+S2 complete, S3+S4 next","body":"","parents":["988f9af8283cce070d60c0bfd43038f22877a326"],"add":40,"del":15,"cadd":40,"cdel":15,"files":1},{"repo":"eureka-co-nevada","hash":"3a433a1f4373fcf7de053ab67dc13d5a838e5357","ts":1773336939,"wall":"2026-03-12T13:35","msg":"Add assessor parcels, KML atlas, NDOT roads, power grid, cultural communities","body":"Spatial layers:\n- Assessor tax parcels: 4,548 polygons, 2,358 owners (Eureka County ArcGIS FeatureServer)\n- KML atlas: 91 operator-mapped features with names resolved via assessor + GNIS\n- NDOT roads: 41 state-maintained segments + 78 AADT traffic count segments\n- Power grid: 9 HIFLD transmission lines (Sierra Pacific, Wells Rural Electric)\n\nResearch:\n- Cultural communities localized to Eureka County from ACS/legal data\n- Groundtruthing TODO for cross-referencing allotment holders with assessor records\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d78af573bd4f3f96168c3805b7162960fa8a8932"],"add":1848,"del":1,"cadd":336,"cdel":1,"files":12},{"repo":"eureka-co-nevada","hash":"093b1c5a8f265715ff95e1a1db759a9a5f4d7699","ts":1773356267,"wall":"2026-03-12T18:57","msg":"Session 28: County map viewer + LiDAR pipeline plan","body":"MapLibre GL JS viewer with PMTiles (262 MB, 25 layers across 6 groups).\nHigh-vis colorblind-safe palette, click-to-inspect, Azura marker.\nRequires Caddy or range-request-capable server: `caddy file-server --listen :8080 --root map/`\n\nLiDAR pipeline plan for AWS EC2 (c5.4xlarge, us-west-2, ~$15).\nEPT streaming from s3://usgs-lidar-public, pre-classified ground returns.\nPhased: validate at Cortez Hills → county-wide overnight → multi-res VRT.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["3a433a1f4373fcf7de053ab67dc13d5a838e5357"],"add":864,"del":69,"cadd":854,"cdel":68,"files":9},{"repo":"operations","hash":"ff5592b1c3b259976d9e42e5ba2fa07646a9171e","ts":1773356419,"wall":"2026-03-12T19:00","msg":"Handoff: session 30 — Eureka county map viewer + LiDAR pipeline plan","body":"County-wide interactive map (25 layers, PMTiles + MapLibre, high-vis palette).\nLiDAR pipeline spec for AWS EC2. Dashboard updated, session log entry.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["6e1d5254a65d4c30fa94e8823081d90dfc83edc0"],"add":125,"del":19,"cadd":125,"cdel":19,"files":3},{"repo":"eureka-co-nevada","hash":"5410187ec792da5331be98ab6fa446b0a3d83255","ts":1773364829,"wall":"2026-03-12T21:20","msg":"Session 29: Spatial data overhaul — tooling, substations fix, baseline audit","body":"Built reusable cleanup infrastructure for 11-session spatial data overhaul:\n- scripts/clean.py: shared GeoJSON cleanup utilities (load/save, field\n  stripping, epoch→ISO, sentinel replacement, null batch removal)\n- scripts/decode.py: coded value lookup tables (NHD FCODEs, FEMA flood\n  zones, Cowardin wetland parser, NDOT, BLM, fuel models, NV land use)\n- scripts/audit.py: per-layer schema report generator\n\nRe-downloaded substations from HIFLD (was 11 bytes \"Bad Request\", now 6\nfeatures). Baseline audit: 186,548 features, 674 fields, 624.5 MB across\n24 layers — 14 flagged for schema bloat or >95% null fields.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["093b1c5a8f265715ff95e1a1db759a9a5f4d7699"],"add":2277,"del":100,"cadd":2276,"cdel":99,"files":9},{"repo":"operations","hash":"29453d154094f0259dd310834cabad8ee67da88a","ts":1773364867,"wall":"2026-03-12T21:21","msg":"Update session log and dashboard for eureka spatial data overhaul (session 29)","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["ff5592b1c3b259976d9e42e5ba2fa07646a9171e"],"add":35,"del":1,"cadd":35,"cdel":1,"files":2},{"repo":"eureka-co-nevada","hash":"38f4004edaaeb5850be612699a89e916dc2ad92b","ts":1773365723,"wall":"2026-03-12T21:35","msg":"Sessions 2-3: Hydrology + OSM/Fire/Mining cleanup","body":"Hydrology (Session 2):\n- Springs: 132 → 15 fields, 59% size reduction (9.4MB → 3.8MB)\n- Flowlines: 17 → 15 fields, FCODEs decoded, fdate → ISO\n- Waterbodies: 7 → 8 fields, FCODEs decoded\n\nOSM/Fire/Mining (Session 3):\n- Roads: 83 → 4 fields, 58% size reduction (19MB → 7.9MB)\n- Buildings: 68 → 2 fields, 82% size reduction (3.4MB → 627KB)\n- Fire perimeters: 120 → 25 fields, timestamps ISO, fuel models decoded,\n  single canonical acres field, attr_/poly_ prefixes stripped\n- Mining claims (134K features): BLM_PROD normalized to title case,\n  Shape_Area/Length stripped, RCRD_ACRS sentinel → null\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5410187ec792da5331be98ab6fa446b0a3d83255"],"add":628,"del":157988,"cadd":620,"cdel":31,"files":14},{"repo":"eureka-co-nevada","hash":"6fd1a71e82a829e7bc798a1038811bab91eabca7","ts":1773366314,"wall":"2026-03-12T21:45","msg":"Update handoff: Sessions 1-3 complete, fix blocked-on references","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["38f4004edaaeb5850be612699a89e916dc2ad92b"],"add":9,"del":9,"cadd":9,"cdel":9,"files":1},{"repo":"operations","hash":"d0a5fa9d8ace8ff7b55e2e44057e97c665c5e5e2","ts":1773366328,"wall":"2026-03-12T21:45","msg":"Update session log: eureka overhaul sessions 2-3 complete","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["29453d154094f0259dd310834cabad8ee67da88a"],"add":21,"del":2,"cadd":21,"cdel":2,"files":1},{"repo":"eureka-co-nevada","hash":"cd1c4f53b496fd5ef2829f1df5d71c3e01d0f3e9","ts":1773367463,"wall":"2026-03-12T22:04","msg":"Session 5: Clean remaining 6 GeoJSON layers","body":"Wetlands (12,152 features): Parse Cowardin ATTRIBUTE codes into\nsystem/subsystem/class/water_regime fields. Strip QAQC_CODE, NWI_ID,\nArcGIS artifacts.\n\nRiparian (4 features): Same Cowardin parsing treatment.\n\nUSGS Wells (781 features): Strip 100%-null well_depth_ft and\naquifer_code (to be re-added from NWIS API in Session 7). Down to\n4 fields: site_no, name, lat, lon.\n\nNDOT Roads (41 features): Decode SystemType coded values to functional\nclassification strings. Strip OBJECTID.\n\nCounty Boundary (1 feature): Convert AREALAND/AREAWATER string→int.\nStrip LSADC, MTFCC, COUNTYCC, COUNTYNS, FUNCSTAT, OID. 18→11 fields.\n\nKML Atlas (91 features): Verified loads correctly, 4 fields, no\nchanges needed.","parents":["6fd1a71e82a829e7bc798a1038811bab91eabca7"],"add":260,"del":12960,"cadd":255,"cdel":0,"files":7},{"repo":"eureka-co-nevada","hash":"73f1e18720ec879999afd863f405e2e0bf9d9b30","ts":1773367796,"wall":"2026-03-12T22:09","msg":"Session 6: Enrich SSURGO soils with NRCS tabular properties","body":"Query NRCS Soil Data Access API for component, horizon, and water table\ndata. Join drainage_class, hydric_rating, is_hydric, taxonomic_order,\nkw_factor, available_water_storage_cm, and depth_to_water_table_cm to\n4,832 polygons on mukey. 100% enrichment rate (830/830 mukeys).\nAPI responses cached in scripts/cache/ssurgo/ for reproducibility.","parents":["cd1c4f53b496fd5ef2829f1df5d71c3e01d0f3e9"],"add":327,"del":4839,"cadd":299,"cdel":0,"files":29},{"repo":"eureka-co-nevada","hash":"542f2215479d42f1f12468c67d10f7e89860681f","ts":1773367937,"wall":"2026-03-12T22:12","msg":"Session 4: Clean 8 administrative/regulatory GeoJSON layers","body":"BLM surface (8→4 fields), grazing (16→7, 117 year-9999 sentinels nullified,\nADM_OFC_CD decoded), PLSS (14→7, Shape.STArea renamed), state lands (25→17,\nduplicate acres reconciled), AADT (20→3), transmission (19→15, NOT AVAILABLE\n→ null), flood zones (4→5, 1554 -9999 sentinels nullified, flood_zone_description\nadded), tax parcels (25→20, YLDUSE decoded, exempt boolean derived).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["73f1e18720ec879999afd863f405e2e0bf9d9b30"],"add":324,"del":6019,"cadd":316,"cdel":0,"files":9},{"repo":"eureka-co-nevada","hash":"713d77e31154b7ff85dd3aa88f1b8bf11da36fe7","ts":1773368355,"wall":"2026-03-12T22:19","msg":"Post-cleanup audit + document updates for Sessions 4-6","body":"All 24 layers cleaned: 674→256 fields (62% reduction), 624.5→549.4 MB.\nSSURGO enriched with 7 NRCS soil properties. Updated handoff, plan,\nspatial README with current state. Next: Sessions 7, 8, 10 (parallel).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["542f2215479d42f1f12468c67d10f7e89860681f"],"add":732,"del":177,"cadd":732,"cdel":177,"files":4},{"repo":"operations","hash":"415cc075dbe8ab14a7fa203f50c305dc7778c62b","ts":1773368376,"wall":"2026-03-12T22:19","msg":"Update session log and dashboard: eureka Sessions 4-6 complete","body":"All 24 spatial layers cleaned (674→256 fields, 62% reduction).\nSSURGO enriched via NRCS API. Sessions 7-8-10 next (parallel).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d0a5fa9d8ace8ff7b55e2e44057e97c665c5e5e2"],"add":44,"del":2,"cadd":44,"cdel":2,"files":2},{"repo":"eureka-co-nevada","hash":"075c20a730bd745d545ca9996efc6530497e3342","ts":1773372514,"wall":"2026-03-12T23:28","msg":"Session 10: Add NAIP aerial orthoimagery pull script","body":"434 tiles of 2022 NAIP 60cm RGBIR COG imagery covering Eureka County,\ndiscovered via Element84 STAC API, downloaded from s3://naip-analytic\n(requester-pays). Script supports --inventory-only, resume capability,\nretry with backoff, and builds a GDAL VRT mosaic clipped to county boundary.\n138.6 GB total, ~$12.47 transfer cost.","parents":["713d77e31154b7ff85dd3aa88f1b8bf11da36fe7"],"add":563,"del":1,"cadd":562,"cdel":0,"files":2},{"repo":"eureka-co-nevada","hash":"2e5441766c3b24e07d8ae16024cced150ab282f9","ts":1773372618,"wall":"2026-03-12T23:30","msg":"Session 7: Enrich 781 USGS wells with NWIS depth and water level data","body":"593/781 wells now have depth (was 100% null), 695/781 have water levels,\n202/781 have aquifer codes, 477/781 have construction dates. Queries NWIS\nSite + Groundwater Levels services in 8 batches each, cached to scripts/cache/nwis/.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["075c20a730bd745d545ca9996efc6530497e3342"],"add":1643,"del":1,"cadd":365,"cdel":0,"files":18},{"repo":"eureka-co-nevada","hash":"1a6e3429129a2c0384899b93b0aa2869f1ad78b8","ts":1773372634,"wall":"2026-03-12T23:30","msg":"Session 8: Parcel analytics, mining claim PLSS parsing, section labels","body":"Parcels: value_per_acre + improvement_ratio computed, 8-class owner\nclassification (Federal 2.1M acres, Mining 326K acres top by acreage).\nMining: CSE_META parsed to township/range/section for 99.99% of 134K claims.\nPLSS: township_range labels for all 4,427 sections.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["2e5441766c3b24e07d8ae16024cced150ab282f9"],"add":390,"del":4,"cadd":386,"cdel":0,"files":6},{"repo":"eureka-co-nevada","hash":"dc4918ef9a8a728e99cfcc8d9444352c6c8979b7","ts":1773372838,"wall":"2026-03-12T23:33","msg":"Update handoff and plan: Sessions 7-8-10 complete","body":"Sessions 1-8 done. Wells enriched (76% depth, 89% water levels), parcels\nclassified (8 owner classes), mining claims parsed (99.99%), PLSS labeled.\nNAIP download in progress (234/434 tiles). Sessions 9 + 11 ready.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["1a6e3429129a2c0384899b93b0aa2869f1ad78b8"],"add":126,"del":174,"cadd":126,"cdel":174,"files":2},{"repo":"operations","hash":"a73193c41a9b55a046701e5e26a31f11fbe944ef","ts":1773372862,"wall":"2026-03-12T23:34","msg":"Update session log: eureka Sessions 7-8-10 (parallel execution)","body":"Wells enriched via NWIS, parcel analytics + mining PLSS parsing done,\nNAIP 60cm imagery downloading (434 tiles, 138.6 GB). 8/11 sessions complete.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["415cc075dbe8ab14a7fa203f50c305dc7778c62b"],"add":27,"del":0,"cadd":27,"cdel":0,"files":1},{"repo":"eureka-co-nevada","hash":"cfbee1e00997e50e4ed001ef464ab106b4373314","ts":1773373402,"wall":"2026-03-12T23:43","msg":"Fix NAIP download: parallel workers + rate limiting","body":"Replace serial download loop with 4-thread ThreadPoolExecutor and 0.5s\nrate limiter between download starts. Per-thread boto3 clients (not\nthread-safe). Previous version hammered S3 back-to-back and got throttled.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["dc4918ef9a8a728e99cfcc8d9444352c6c8979b7"],"add":75,"del":58,"cadd":75,"cdel":58,"files":1},{"repo":"ops26-04p2a","hash":"5e34f34a5f9f3b20b050fec203a59b01e033ba2b","ts":1773373413,"wall":"2026-03-12T23:43","msg":"Initial structure: deployment planning for Azura","body":"Vehicle PMCS, maintenance log, budget projections, packing list,\npre-departure checklist, and week-one base camp plan.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":363,"del":0,"cadd":363,"cdel":0,"files":7},{"repo":"operations","hash":"682fa893ed697075238fcdaa2ddb4effc00bb22b","ts":1773373729,"wall":"2026-03-12T23:48","msg":"Add OPSMMXXVI to atlas: symlink, index, dashboard","body":"Azura deployment repo — vehicle, budget, logistics, base camp planning.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["a73193c41a9b55a046701e5e26a31f11fbe944ef"],"add":8,"del":0,"cadd":7,"cdel":0,"files":3},{"repo":"eureka-co-nevada","hash":"739187a11f80abb026bef8f85dfae1a7362462ac","ts":1773374032,"wall":"2026-03-12T23:53","msg":"Update handoff: NAIP at 283/434 tiles, parallel fix deployed","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["cfbee1e00997e50e4ed001ef464ab106b4373314"],"add":4,"del":4,"cadd":4,"cdel":4,"files":1},{"repo":"ops26-04p2a","hash":"1df73abd3685cfe5219cbf15fa8e38a0112b3f05","ts":1773374066,"wall":"2026-03-12T23:54","msg":"Rename to OPS26/04P2A","body":"OPS = Operation, 26 = 2026, 04 = April, P2A = Providence to Azura.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5e34f34a5f9f3b20b050fec203a59b01e033ba2b"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"operations","hash":"01dba67ade03c74f38977e8b7a7682f90163a6ab","ts":1773374073,"wall":"2026-03-12T23:54","msg":"Rename OPSMMXXVI to OPS26-04P2A in atlas","body":"Updated symlink, index, and dashboard.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["682fa893ed697075238fcdaa2ddb4effc00bb22b"],"add":3,"del":3,"cadd":2,"cdel":2,"files":4},{"repo":"eureka-co-nevada","hash":"272a6ef64d262050655c56150c6e7f6314900f02","ts":1773378087,"wall":"2026-03-13T01:01","msg":"Sessions 9+11: PMTiles rebuild, map viewer, cross-domain spatial analysis","body":"Session 9: Per-layer minzoom floors (z6-z10), town labels (4 towns at z8+),\nscale-dependent line widths, improved feature inspector (title-cased names,\nformatted dates/acres), z-ordered layers. PMTiles 236 MB (was 262 MB).\n\nSession 11: Three cross-domain analyses — mining×water proximity (99.6% of\nclaims within 1km of water), ownership×soils suitability (ranch parcels have\nhighest hydric exposure at 8.3%), terrain by PLSS township (county 40.4%\nflat, 20.7% very steep). All indexed into RAG knowledge_base.\n\nAll 11 spatial overhaul sessions complete.","parents":["739187a11f80abb026bef8f85dfae1a7362462ac"],"add":534,"del":129,"cadd":534,"cdel":129,"files":8},{"repo":"operations","hash":"135d213ce44bd8027107782dfd5219eaa64a5ecb","ts":1773378103,"wall":"2026-03-13T01:01","msg":"Update session log and dashboard: eureka Sessions 9+11 complete","body":"All 11 spatial overhaul sessions done. PMTiles rebuilt (236 MB),\n3 cross-domain analyses produced, NAIP at 94% (408/434 tiles).","parents":["01dba67ade03c74f38977e8b7a7682f90163a6ab"],"add":22,"del":1,"cadd":22,"cdel":1,"files":2},{"repo":"eureka-co-nevada","hash":"ee10d11480e65248193a3dd54d56d94367197813","ts":1773384488,"wall":"2026-03-13T02:48","msg":"Final touches: NAIP 434/434, docs updated, map viewer prepped for deployment","body":"- Overhaul plan: Session 10 marked complete (434/434 tiles, 140 GB)\n- README: expanded with overhaul results, spatial data summary, map viewer\n- CLAUDE.md: active work updated to reflect all 11 sessions complete\n- Handoff: NAIP corrected to 434/434, deployment status added\n- .gitignore: added log files and partial download patterns\n- map/index.html: PMTiles URL updated for eureka.symbiont.systems deployment\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["272a6ef64d262050655c56150c6e7f6314900f02"],"add":106,"del":58,"cadd":98,"cdel":57,"files":7},{"repo":"eureka-co-nevada","hash":"94b3dc256e3c9f35d3e893056ff3bc00f084b8d0","ts":1773388829,"wall":"2026-03-13T04:00","msg":"Map viewer: NDOT roads fix, federal lands sublayers, parcel inspector, PLSS clickable","body":"- Re-downloaded NDOT roads from ArcGIS REST (41 features had null geometry)\n- Federal Lands: BLM yellow + USFS green, toggleable sublayers with legend\n- State Lands: fly-to sublayers with info popups\n- Tax Parcels: fill type (clickable), field aliases, dollar formatting\n- PLSS Sections: fill type (clickable), minzoom 6, field aliases\n- Info panel moved to top-right (clear of coordinate bar)\n- Generic sublayer system for filtered layer groups\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ee10d11480e65248193a3dd54d56d94367197813"],"add":266,"del":85,"cadd":265,"cdel":84,"files":4},{"repo":"eureka-co-nevada","hash":"7096c1ed95eb1969c27d6f498ed174d6153e4447","ts":1773415779,"wall":"2026-03-13T11:29","msg":"PMTiles domain split + active claims operator enrichment","body":"Split monolithic 236MB PMTiles into 8 domain files so tippecanoe\nnever drops features (--no-feature-limit --no-tile-size-limit):\n  closed-claims (274MB), active-claims (86MB), ownership (20MB),\n  hydrology (53MB), infrastructure (4.8MB), ecology (23MB),\n  extraction (2MB), reference (197KB)\n\nMap viewer updated: 8 vector sources, LAYER_SOURCE routing table.\n\nActive claims enriched with operator field from NDOM FeatureServer\n(49,475 records paginated, 1,694 prefixes resolved to 77 companies).\nTop 12 operators rendered as neon sublayers (toggleable):\n  Nevada Gold Mines, Big Casino Corp, McEwen Mining, Tonkin Springs,\n  Barrick Cortez, Idaho Resources, Eureka Moly, Golden Pick,\n  Golden Gryphon, WKGUS, Agnico Eagle, Ruby Hill Mining.\n65 minor operators colored with 35-color jewel-tone palette.\n159 unresolved claims (0.6%) fall to dark gray.\n\nInspector: field ordering, aliases, date/acreage formatting for claims.\nOutlines: black 0.5px between claim polygons for boundary visibility.\n\nData source: Nevada Division of Minerals, ArcGIS FeatureServer Layer 1\n\"Nevada Active, Pending, Submitted, and Filed Mining Claims Listings\"\nhttps://services.arcgis.com/CXYUMoYknZtf5Qr3/arcgis/rest/services/ArcOnlineNvStateClaims/FeatureServer/1","parents":["94b3dc256e3c9f35d3e893056ff3bc00f084b8d0"],"add":268,"del":53,"cadd":267,"cdel":52,"files":3},{"repo":"eureka-co-nevada","hash":"72ac1428e263d4519ef362fa8d78e3ef2548448f","ts":1773415890,"wall":"2026-03-13T11:31","msg":"Update handoff: PMTiles split + operator enrichment complete","body":"","parents":["7096c1ed95eb1969c27d6f498ed174d6153e4447"],"add":69,"del":68,"cadd":69,"cdel":68,"files":1},{"repo":"operations","hash":"2bdc808f5f4931116c0f1831a96719d760fef07a","ts":1773415891,"wall":"2026-03-13T11:31","msg":"Update session log and dashboard: eureka Session 12 complete","body":"","parents":["135d213ce44bd8027107782dfd5219eaa64a5ecb"],"add":31,"del":1,"cadd":31,"cdel":1,"files":2},{"repo":"eureka-co-nevada","hash":"3ff3b4b910f76160c3a62d293ba0c1d6f4e6ca59","ts":1773433750,"wall":"2026-03-13T16:29","msg":"NAIP × hillshade basemap pipeline + graceful map fallback","body":"- Rewrite build_naip_basemap.sh: GDAL 3.11 pipeline using gdal raster calc\n  (GDALG lazy blend) + gdal raster tile (z7-z18 JPEG) + disk_to_pmtiles\n- Delete build_naip_basemap.py (superseded by shell pipeline)\n- Replace Esri World Imagery with self-hosted NAIP basemap PMTiles source\n- Add graceful fallback: dark background + vector layers load immediately,\n  NAIP raster basemap added dynamically when available\n- Grazing allotments: render modes (default/density/livestock), BLM RAS data\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["72ac1428e263d4519ef362fa8d78e3ef2548448f"],"add":457,"del":13,"cadd":457,"cdel":13,"files":2},{"repo":"eureka-co-nevada","hash":"f66c9b9d37d635b4ceb6dd862b79165eb194d476","ts":1773436694,"wall":"2026-03-13T17:18","msg":"Update handoff: Session 13, NAIP basemap pipeline","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["3ff3b4b910f76160c3a62d293ba0c1d6f4e6ca59"],"add":39,"del":55,"cadd":39,"cdel":55,"files":1},{"repo":"operations","hash":"0e82cbfa3563699b60d8a3ab7c4e509c00a1fef3","ts":1773436708,"wall":"2026-03-13T17:18","msg":"Update session log and dashboard: eureka Session 13","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["2bdc808f5f4931116c0f1831a96719d760fef07a"],"add":26,"del":1,"cadd":26,"cdel":1,"files":2},{"repo":"eureka-co-nevada","hash":"9081a17618c2973fbc7a33bc82142ca5c7ce9103","ts":1773445234,"wall":"2026-03-13T19:40","msg":"Riparian corridor pipeline + grazing enrichment + BLM RAS documentation","body":"- Add build_riparian_corridors.py: multi-source riparian corridor builder\n  combining LANDFIRE EVT (13 riparian classes), NHD flowline buffers,\n  and NWI wetlands into a single enriched polygon layer\n- Enrich grazing allotments with BLM RAS permit data (operators, AUMs,\n  livestock types, seasons) via OBIEE SOAP endpoint\n- Document BLM RAS programmatic access (no-auth OBIEE proxy, SOAP API,\n  session establishment, available reports)\n- Cache BLM AIM riparian assessment points (7 sites in Eureka County)\n- Cache RAS query results for Battle Mountain/Elko districts\n- LANDFIRE EVT 2.5.0 downloaded for Eureka County (4.4 MB raster, gitignored)\n- MRVN (DRI riparian vegetation) downloaded (2.3 GB, gitignored)\n- Corridor builder needs AWS burst compute for the dissolve operation","parents":["f66c9b9d37d635b4ceb6dd862b79165eb194d476"],"add":21701,"del":1,"cadd":976,"cdel":0,"files":6},{"repo":"eureka-co-nevada","hash":"98c5305d07878d8f32f5143a2445b4d1cbae5e08","ts":1773445302,"wall":"2026-03-13T19:41","msg":"Update handoff: riparian pipeline ready, needs EC2 burst compute","body":"","parents":["9081a17618c2973fbc7a33bc82142ca5c7ce9103"],"add":65,"del":41,"cadd":65,"cdel":41,"files":1},{"repo":"eureka-co-nevada","hash":"570aaa21c2ddb077a69f631f4a3488f78250bd5d","ts":1773507471,"wall":"2026-03-14T12:57","msg":"Repo cleanup: fix riparian script, update handoff, delete invalid output","body":"Chunked dissolve optimization in build_riparian_corridors.py (16x16 grid\nto avoid RAM exhaustion). Cleaned up imports and fixed dedup logic.\nDeleted 198 MB invalid riparian corridor output (methodology needs audit).\nUpdated handoff to reflect current state through Session 14.\nAdded scripts/cache/landfire/ to .gitignore.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["98c5305d07878d8f32f5143a2445b4d1cbae5e08"],"add":89,"del":97,"cadd":88,"cdel":97,"files":3},{"repo":"operations","hash":"8a9068137699c4d7ba4795e99470b337300b6d09","ts":1773515865,"wall":"2026-03-14T15:17","msg":"Deploy map.eureka: private TLD for Eureka County digital twin","body":"Added .eureka TLD to BIND9 (map.eureka subdomain), Caddy HTTP block,\nand deployed MapLibre viewer + 8 domain-split PMTiles to CPX22.\nUpdated dashboard with .eureka infrastructure and eureka-co-nevada status.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["0e82cbfa3563699b60d8a3ab7c4e509c00a1fef3"],"add":3,"del":2,"cadd":3,"cdel":2,"files":1},{"repo":"eureka-co-nevada","hash":"7cf9f8e0cedbb49165dfe5ef365b5dc75fc8ead7","ts":1773515977,"wall":"2026-03-14T15:19","msg":"Update handoff: map.eureka deployed, EC2 basemap in progress","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["570aaa21c2ddb077a69f631f4a3488f78250bd5d"],"add":7,"del":7,"cadd":7,"cdel":7,"files":1},{"repo":"eureka-co-nevada","hash":"d53bce3bc9b4ad0c940c514f19a1d0144b83a8a8","ts":1773527865,"wall":"2026-03-14T18:37","msg":"NAIP basemap + Maki icons for Mapped Features layer","body":"- NAIP 2022 × hillshade basemap live (12 GB PMTiles, z7-18 JPEG)\n- Mapped Features: category-driven Maki icons replacing plain circles\n- Full 215-icon Maki sprite sheet (1x + 2x) via spreet\n- Remove 4 homestead features, rename remaining 2 to Ruins category\n- Fix glyphs URL (openmaptiles font server)\n- Add sprite and glyphs properties to map style\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["7cf9f8e0cedbb49165dfe5ef365b5dc75fc8ead7"],"add":3073,"del":239,"cadd":55,"cdel":1,"files":6},{"repo":"eureka-co-nevada","hash":"c35e9b24834f8805a69708909b4b2c0e042e7b16","ts":1773534710,"wall":"2026-03-14T20:31","msg":"Map viewer: building colors, sublayer toggles, icon system WIP","body":"- Buildings: color-coded by type (20 categories), additive sublayer toggles\n- Mapped Features: sublayer toggles per category (subtractive mode)\n- SDF sprites (215 Maki icons) for icon coloring — needs tuning\n- Additive toggle pattern: parent = gate, \"All\" checkbox, individual toggles\n- Glyphs: openmaptiles font server\n- Icon visibility on NAIP still needs work (next session)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d53bce3bc9b4ad0c940c514f19a1d0144b83a8a8"],"add":2346,"del":1738,"cadd":202,"cdel":24,"files":5},{"repo":"eureka-co-nevada","hash":"75f7a567d20d0a63b52bb2e8a0f58693f986d8b7","ts":1773726351,"wall":"2026-03-17T01:45","msg":"Session 15: Synthwave UI overhaul, soils render modes, closed claims timeline","body":"Map viewer:\n- Full synthwave theme (deep purple base, neon pink/cyan accents, CSS variables)\n- Sidebar flex layout: title card + layer panel, title expands with county stats\n- Collapsible layer groups with pink accent bars\n- Custom styled checkboxes (pink glow when checked)\n- Per-layer opacity sliders (cyan, visible when layer enabled)\n- Inspector: close button, repositioned, cyan headers\n- URL hash state, favicon, loading indicator\n- Reference layers default off\n\nData layers:\n- Soils: 5 render modes (drainage, taxonomy, erodibility, water storage)\n- Closed claims: filing timeline (NMC serial → approx year, 97% coverage),\n  density heatmap (106K centroids), claim type mode, year filter sliders\n- Soils clipped to county boundary (4,832 → 4,028 features)\n\nSpatial data:\n- 10 GNIS landmark layers (summits, places, ranges, gaps, airports, etc.)\n- GNIS springs (238 features) replacing NHD springs\n- County boundary mask\n- Closed claims centroid points for heatmap\n- Deleted obsolete raw summary JSONs\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c35e9b24834f8805a69708909b4b2c0e042e7b16"],"add":12332,"del":95982,"cadd":1019,"cdel":208,"files":33},{"repo":"operations","hash":"99a0150a8927b842d08af550183186b72cb1d5cb","ts":1773726493,"wall":"2026-03-17T01:48","msg":"Update handoff: Session 33, eureka map viewer overhaul","body":"Eureka Session 15 shipped: synthwave UI theme, soils render modes,\nclosed claims timeline/heatmap, GNIS reference layers, Phase 1 UX fixes,\nopacity sliders. All deployed to eureka.symbiont.systems.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["8a9068137699c4d7ba4795e99470b337300b6d09"],"add":62,"del":54,"cadd":62,"cdel":54,"files":1},{"repo":"eureka-co-nevada","hash":"77e6e9757f199b8d3d2d73d1c88de4cd603997fe","ts":1773765802,"wall":"2026-03-17T12:43","msg":"Session 15b: Splash screen, search, slider polish, attribution, bug fixes","body":"- Symbiont Systems splash screen with logo (click to enter)\n- Credits drawer (bottom-left © button)\n- Feature search bar (NAV_DATA + rendered tile features)\n- Polished sliders: custom track/thumb, fill gradient, glow on hover/active\n- Year filter sliders in pink, opacity sliders in cyan\n- Sliders only on fill/well/sublayered-line layers\n- Slider bug fixes (sublayer outlines, heatmap sync, wells default)\n- Search bug fixes (z-index, performance, dedup, HTML injection)\n- Removed Azura marker (wrong coords, exposed parcel info)\n- Sidebar flex layout (title expands without overlapping layers)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["75f7a567d20d0a63b52bb2e8a0f58693f986d8b7"],"add":758,"del":62,"cadd":758,"cdel":62,"files":2},{"repo":"eureka-co-nevada","hash":"dbb6e80c1d56eca9fa9b12b4a932bd1dfcf728eb","ts":1773766020,"wall":"2026-03-17T12:47","msg":"Add deck.gl + 3D terrain migration plan","body":"Full architecture for migrating from MapLibre GL JS to deck.gl v9:\n- NAIP basemap clipped to county boundary\n- LiDAR 1m DEM as terrain-RGB tiles for 3D rendering\n- Per-layer GPU blend modes (multiply, additive, screen)\n- MVTLayer reading existing PMTiles via custom getTileData\n- Modular JS file structure (no build step)\n- Same synthwave UI chrome\n\nEstimated: 3-4 coding sessions + 1 EC2 burst (~$25-30 AWS)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["77e6e9757f199b8d3d2d73d1c88de4cd603997fe"],"add":543,"del":0,"cadd":543,"cdel":0,"files":1},{"repo":"glyphic","hash":"ca869c7d28effffeceaa20609fc9db1db53eb6e2","ts":1773801597,"wall":"2026-03-18T02:39","msg":"Initial commit","body":"","parents":[],"add":3,"del":0,"cadd":3,"cdel":0,"files":1},{"repo":"glyphic","hash":"9e765a90eb3a5ca2260248ba4229edaaf4c2d1aa","ts":1773801979,"wall":"2026-03-17T22:46","msg":"Research phase: neural constraints, abugida survey, design constraints","body":"Three research documents establishing the foundation for neuroscience-informed\nalphasyllabary design. Synthesizes Dehaene (neuronal recycling), Changizi\n(cross-script universals), Hodgson (neuroarchaeology), and comparative analysis\nof six existing abugida systems.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ca869c7d28effffeceaa20609fc9db1db53eb6e2"],"add":444,"del":2,"cadd":444,"cdel":2,"files":4},{"repo":"glyphic","hash":"f63a4b5c16d58934bccb77fd2bef797cb0c85151","ts":1773808012,"wall":"2026-03-18T00:26","msg":"Research phase 2: sound symbolism, sacred language phonology, sigil neuroscience","body":"Three research documents completing the foundation:\n- Sound symbolism and phonaesthetics (bouba/kiki, frequency code, ideophones)\n- Sacred language phonology (Sanskrit, Arabic, Enochian, Tolkien, glossolalia)\n- Sigil traditions and visual neuroscience (Agrippa, Spare, bindrunes, entoptics)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["9e765a90eb3a5ca2260248ba4229edaaf4c2d1aa"],"add":752,"del":0,"cadd":752,"cdel":0,"files":3},{"repo":"trishsays","hash":"0db78f34f51374503962bde17c0c85fc38e57589","ts":1773869851,"wall":"2026-03-18T21:37","msg":"Initial commit","body":"","parents":[],"add":3,"del":0,"cadd":3,"cdel":0,"files":1},{"repo":"operations","hash":"035d74ba7d40446a848aa32ed0be827bf3099ede","ts":1773897341,"wall":"2026-03-19T01:15","msg":"Add cryptoterrestrial hypothesis paper (Lomas et al. 2024, Harvard)","body":"Converted from PDF to markdown with YAML frontmatter. Full text of\n\"The cryptoterrestrial hypothesis: A case for scientific openness to\na concealed earthly explanation for Unidentified Anomalous Phenomena\"\npublished in Philosophy and Cosmology, Volume 33.","parents":["99a0150a8927b842d08af550183186b72cb1d5cb"],"add":2601,"del":0,"cadd":2601,"cdel":0,"files":1},{"repo":"eureka-co-nevada","hash":"db07ee3bab168b173b5922636f88b9191b3b6cd5","ts":1773897407,"wall":"2026-03-19T01:16","msg":"EC2 burst compute pipeline: LiDAR + NAIP basemap + terrain-RGB","body":"Scripts for the 384-core c8i.96xlarge geospatial workhorse:\n\n- ec2_lidar_burst.sh: orchestrator (launch/start/status/download/deploy/stop/destroy)\n- ec2_unified_pipeline.sh: runs on EC2 — LiDAR DEM → NAIP basemap → terrain-RGB\n- build_naip_basemap.sh: standalone NAIP pipeline (Option B: MBTiles → PMTiles)\n- build_lidar_dem.sh: standalone LiDAR pipeline (PDAL tiled parallel)\n- encode_terrarium.py: DEM → Terrarium RGB encoder (block-based, handles large files)\n- post_lidar_build.sh: local chain script (basemap → terrain-RGB → deploy)\n\nKey decisions:\n- On-demand instances only (spot reclaimed our first 12-hour run)\n- micromamba instead of conda (conda solver hangs indefinitely)\n- NAIP streams from S3 requester-pays COGs (no upload needed)\n- pmtiles Go CLI for MBTiles→PMTiles (Python library too slow at scale)\n- Instance stops instead of terminates (reuse environment, $8/month EBS)\n\nThree-pass audit found and fixed 32 bugs across all scripts.","parents":["dbb6e80c1d56eca9fa9b12b4a932bd1dfcf728eb"],"add":1888,"del":94,"cadd":1888,"cdel":94,"files":7},{"repo":"eureka-co-nevada","hash":"aae0ac3ad27fe5c534d5bc5718cd79ff0f2d220b","ts":1774033920,"wall":"2026-03-20T15:12","msg":"AAR: Session 16 EC2 pipeline failure — $113 spend, live site broken","body":"","parents":["db07ee3bab168b173b5922636f88b9191b3b6cd5"],"add":149,"del":0,"cadd":149,"cdel":0,"files":1},{"repo":"trishsays","hash":"b4e91e8345c6ce4595069b501a999bc468f124aa","ts":1774042687,"wall":"2026-03-20T17:38","msg":"Add portfolio site, API, dashboard, and deployment config","body":"Rust/Axum API with email OTP auth, JSON content CMS.\nStatic public site and admin dashboard.\nCaddy + systemd deployment playbook for Hetzner.\nPhone number removed from seed data pending work email setup.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["0db78f34f51374503962bde17c0c85fc38e57589"],"add":3932,"del":0,"cadd":2195,"cdel":0,"files":12},{"repo":"composite-organism","hash":"d96c2d15c9ff85c6d7a7c3017e56370f051fa0d2","ts":1774052174,"wall":"2026-03-20T20:16","msg":"Init: draft essay and project scaffold","body":"The Composite Organism — introducing symbiotic AI and MESO apprenticeships.\nStatus: PARKED, awaiting operator revision.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":116,"del":0,"cadd":116,"cdel":0,"files":2},{"repo":"reflex","hash":"5485a5250a2664c2532fa7a4e16d42b9d321b04b","ts":1774318512,"wall":"2026-03-23T22:15","msg":"reflex: P0 daemon control + P1 dashboard UI rewrite","body":"P0 — Daemon Control:\n- POST /shutdown endpoint for graceful server stop\n- Stop action in foreground notification (StopReceiver)\n- Physical button interception via AccessibilityService (ButtonService)\n- Configurable button→action mapping (ButtonActions) with API routes\n- KEY_F1 (custom) and KEY_F11 (PTT) intercepted at system level\n- Built-in actions: torch_toggle, vibrate_short/long, tts_time\n- MediaTek udev rule for ADB USB access\n\nP1 — Dashboard + Mode Navigation:\n- Dashboard home screen with 9 mode cards (2-column grid)\n- Live sensor readings on cards (accel, pressure, battery, light)\n- Daemon toggle + API/BTN service status indicators\n- Mode navigation: tap card → full-screen mode, back arrow returns\n- VOICE mode: TTS with pitch/speed/language, tone generator with\n  frequency presets, volume control per stream\n- SENSE mode: all 22 sensors streaming with type labels\n- POWER mode: battery detail, device info, daemon status, API key\n- SURFACE mode: torch toggle, brightness control\n- TOUCH mode: haptic direct control with amplitude/duration,\n  presets, button binding editor with dropdown\n- Skeleton screens for VISION, LOCATE, SONAR, SIGNAL\n- Camera torch state tracking (isTorchOn)\n- Speech pitch/rate modulation (setPitch, setSpeechRate)","parents":["944cce10044bf14b6f89628278191c4e47cb9292"],"add":1792,"del":52,"cadd":1762,"cdel":52,"files":21},{"repo":"reflex","hash":"ab8bbce448cedcba5760650f57be3b50b53299a4","ts":1774322252,"wall":"2026-03-23T23:17","msg":"reflex: Cell engine — instrument pipeline inspired by Somaphore","body":"Cell architecture adapted from Somaphore's cell-core: autonomous\ncomputing units connected by edges in a directed graph. Each cell\nis a hexagonal node — sensor source, transform function, or output\ndriver. An instrument is a pre-wired graph of cells.\n\nEngine:\n- Cell.kt: CellId, Cell, CellType, SensorBinding, OutputBinding, Edge\n- CellGraph.kt: directed graph, Kahn's topological sort, dirty\n  propagation, one-frame cycle delay (Somaphore pattern)\n- TransformRegistry.kt: 17 pure transforms — normalize, threshold,\n  smooth, baseline_subtract, magnitude, pressure_to_altitude,\n  gravity_to_tilt, mag_to_heading, rms_to_db, scale, abs, etc.\n- SensorBridge.kt: binds Android sensor listeners to source cells,\n  injects values each tick without polling\n- OutputDriver.kt: maps output cell values to haptic/audio/torch/screen\n- InstrumentEngine.kt: orchestrator with 20Hz tick loop on dedicated\n  coroutine thread. Activate/deactivate instruments by ID.\n\nPresets (6 starter instruments):\n- Level: accelerometer → tilt → normalize → haptic + tone\n- Compass: magnetometer → heading → tone pitch sweep\n- Altimeter: barometer → pressure-to-altitude → baseline → tone\n- G-Force: accelerometer → magnitude → scale → smooth → haptic\n- Metal Detector: magnetometer → magnitude → baseline → haptic pulse\n- SPL Meter: mic RMS → dB → normalize → haptic amplitude\n\nAPI: GET /instruments, POST /instruments/{id}/activate,\n     POST /instruments/deactivate, GET /instruments/active\n\nVerified on device: metal detector activated, 9 cells evaluating,\nmagnetometer data flowing through pipeline at 20Hz, baseline\ncaptured, anomaly detection working.","parents":["5485a5250a2664c2532fa7a4e16d42b9d321b04b"],"add":1327,"del":0,"cadd":1327,"cdel":0,"files":11},{"repo":"reflex","hash":"439f3ae282df6fb7e546cd0d6610fecce9c1cee3","ts":1774375895,"wall":"2026-03-24T14:11","msg":"reflex: hex interface + visual instrument builder","body":"Hex Interface:\n- Replaced entire card/mode UI with hexagonal workspace\n- HexGeometry: axial coordinates, flat-top hex rendering, hit testing,\n  edge midpoints, snap-to-honeycomb-grid\n- HexRenderer: Canvas DrawScope extensions for hex cells with\n  value-mapped color (blue→green→red), typed borders, labels\n- WireRenderer: edge lines between hex midpoints with value coloring\n- HexLayout: automatic left-to-right layout from graph topology\n- PresetShelf: horizontal scrollable strip of miniature hex clusters\n- WorkspaceScreen: dark canvas workspace with zoom/pan, preset\n  viewing, and builder mode\n- Deleted 11 old screen files (cards, modes, tabs)\n\nVisual Builder:\n- Long press empty canvas → radial menu (Source/Transform/Output)\n- Two-ring radial: category inner ring, specific cells outer ring\n- Place cells at touch position, snapped to honeycomb grid\n- Drag hex center → move hex, snaps to grid on release\n- Drag hex edge → wire creation with magnetic snap to target edge\n- Tap cell → select, tap again → delete\n- Live/Pause toggle: data flows while building or waits for play\n- BUILD/EXIT toggle in status bar\n\nEngine Additions:\n- CellGraph: removeCell, removeEdge, calibrate (reset baselines)\n- InstrumentEngine: activateBuilder, addCellLive, addEdgeLive,\n  removeCellLive, calibrate, StateFlow snapshot emission\n- POST /instruments/calibrate API endpoint\n- BuilderState: full state machine for builder interactions\n\nSystem bar insets respected — content below WiFi/signal/battery.","parents":["ab8bbce448cedcba5760650f57be3b50b53299a4"],"add":2391,"del":1469,"cadd":2391,"cdel":1469,"files":27},{"repo":"reflex","hash":"267372832317296c8c2ca095723da1d274ee631c","ts":1774381239,"wall":"2026-03-24T15:40","msg":"reflex: hex port dots, gesture rewrite, builder improvements (WIP)","body":"Port dots on hex edges for visual wire targets. Unified gesture\nhandler with clean target classification (port/body/empty). Tap-to-\nconnect and drag-to-wire both work. Calibrate button. Long press\ndelete. Still choppy — needs fundamental interaction rethink.\n\nWire rendering to be replaced by edge-to-edge hex snapping.","parents":["439f3ae282df6fb7e546cd0d6610fecce9c1cee3"],"add":308,"del":151,"cadd":308,"cdel":151,"files":4},{"repo":"reflex","hash":"860cc1e8704c616c18eb00674976021ae7797b4a","ts":1774398860,"wall":"2026-03-24T20:34","msg":"reflex: adjacency model — no wires, hexes connect by touching","body":"Fundamental interaction rewrite: adjacency IS connection.\nHexes that share an edge auto-connect. No wires, no ports,\nno wire dragging, no connect mode. Place hexes next to each\nother and data flows.\n\nEngine:\n- EdgeMap simplified: inputEdges/outputEdges as Sets (not Maps)\n- Full value array flows through each adjacency (cells take what they need)\n- CellGraph.rebuildAdjacency() derives edges from spatial positions\n- InstrumentEngine tracks positions, rebuilds on move\n- moveCellLive() for live hex repositioning\n- Removed addEdgeLive() — edges are computed, not created\n\nPresets:\n- All 6 instruments defined with axial coordinates, no edge lists\n- InstrumentDef no longer has edges field\n- Connections derived from cell positions on buildGraph()\n\nUI:\n- Deleted WireDrag.kt (no wires)\n- Deleted port dots (no ports)\n- Removed wire rendering\n- Added edge glow on connected faces (value-colored)\n- Unified HexCanvas for both preset and builder modes\n- Simplified BuilderState (no connect mode, no wire drag state)\n- Simplified gesture handler (tap, long press, drag, zoom/pan)\n- PresetShelf renders from axial positions directly\n\nTouch still choppy — needs performance diagnosis.","parents":["267372832317296c8c2ca095723da1d274ee631c"],"add":478,"del":1066,"cadd":478,"cdel":1066,"files":13},{"repo":"reflex","hash":"60dcd5c57674412657e4f00df52ff290bc32bb81","ts":1774400956,"wall":"2026-03-24T21:09","msg":"reflex: gesture fixes — edge snap preview, visual drag, ref-based state","body":"- Hex follows finger during drag, snaps to nearest empty neighbor\n  slot when close (0.6x radius threshold)\n- Approach from different angles to choose which edge to connect to\n- Release in empty space to detach/disconnect\n- pointerInput(Unit) with rememberUpdatedState refs — gesture handler\n  reads fresh state without restarting the coroutine\n- Cell move only calls engine.moveCellLive on release (not every frame)\n- Snap preview shows exactly where hex will land before release","parents":["860cc1e8704c616c18eb00674976021ae7797b4a"],"add":91,"del":15,"cadd":91,"cdel":15,"files":1},{"repo":"reflex","hash":"dde5b28e726b8ee76370fc0758d99fc21d3908fa","ts":1774402280,"wall":"2026-03-24T21:31","msg":"reflex: 22 instruments, 29 transforms, custom instrument persistence","body":"Transforms (12 new, 29 total):\n- delta, rate_of_change (derivatives)\n- max_tracker, min_tracker (running extremes)\n- accumulate (running sum)\n- map_range (remap arbitrary ranges)\n- sign, hysteresis (binary classifiers)\n- pitch_roll (accelerometer to pitch/roll degrees)\n- extract_index (pull single channel from array)\n- squared, sqrt (power/energy math)\n\nInstruments (16 new, 22 total):\n- Orientation: Level, Compass, Inclinometer\n- Environment: Altimeter, Weather Station, Light Meter, Lux Logger,\n  VSI (vertical speed), Floor Detector\n- Motion: G-Force, Peak G, Vibration Meter, Tachometer, Pedometer,\n  Crash Detector, Seismograph\n- Magnetic: Metal Detector, Stud Finder, Gaussmeter\n- Audio: SPL Meter, Hearing Guard\n- Proximity: Proximity Alert\n\nCustom Instrument Persistence:\n- InstrumentStore: save/load/delete custom instruments as JSON\n  in SharedPreferences\n- Full serialization of CellType, SensorBinding, OutputBinding\n- Custom instruments appear alongside built-in presets in shelf\n- SAVE button in builder mode status bar\n- InstrumentEngine.saveCustom() / deleteCustom()\n\nRadial menu updated with all 24 transform types.","parents":["60dcd5c57674412657e4f00df52ff290bc32bb81"],"add":688,"del":5,"cadd":688,"cdel":5,"files":6},{"repo":"reflex","hash":"5d017cb69c64cb3540268a468197d8084e8c355d","ts":1774406331,"wall":"2026-03-24T22:38","msg":"reflex: hex bloom menu + double tap trigger","body":"Replaced radial menu with hexagonal bloom menu. Every menu\nelement is a hexagon — consistent visual language throughout.\n\nHex Bloom Menu:\n- Level 1: center dismiss + 6 category hexes (Sensor, Math,\n  Signal, Sense, Track, Output) in a touching honeycomb cluster\n- Level 2: tap category → items bloom as hexes around it\n- 37 cell types organized into 6 categories, max 7 per category\n- Menu hexes at 35dp radius, edge-to-edge honeycomb, proper\n  touch targets\n- Hit testing via pointInHex on each menu hex\n\nTrigger Change:\n- Double tap empty canvas → open menu (was long press)\n- Long press on hex → delete (unchanged)\n- Removes 400ms long press delay for cell placement\n\nCategories:\n- Sensor (blue): Accel, Mag, Baro, Light, Prox, Mic, Steps\n- Math (green): Norm, Abs, Scale, Invert, x², √x\n- Signal (green): Smooth, Delta, Rate, Baseline, Accumulate\n- Sense (green): Magnitude, Heading, Tilt, P/R, Altitude, dB, Extract\n- Track (green): Threshold, Hysteresis, Deadzone, Sign, Max, Min, Map\n- Output (amber): Haptic, H.Pulse, Tone, T.Pulse, Torch, Display","parents":["dde5b28e726b8ee76370fc0758d99fc21d3908fa"],"add":234,"del":181,"cadd":234,"cdel":181,"files":2},{"repo":"reflex","hash":"15dd0b21022f509f00f3aea78b468d7faed9e196","ts":1774408683,"wall":"2026-03-24T23:18","msg":"reflex: fix instrument bugs — warmup, baseline capture, mic RMS","body":"Root cause: first tick ran before sensors delivered data, causing\ntransforms to initialize with zero/garbage inputs. pressure_to_altitude(0)\n= 44330 (formula constant), captured as baseline, corrupting all\nsubsequent readings.\n\nFixes:\n- SensorBridge.injectValues() returns false until sensors have\n  real data. Tick loop skips evaluation until warmed up.\n- pressure_to_altitude guards against pressure < 1 hPa (no data)\n- baseline_subtract waits for non-zero input before capturing\n- smooth waits for non-zero input before initializing\n- delta, max_tracker, min_tracker, rate_of_change all wait for\n  non-zero before initializing\n- OutputDriver.displayValues cleared each tick (no stale labels)\n- Mic RMS: real AudioRecord integration, 44.1kHz PCM, live RMS\n  calculation on dedicated thread (replaces placeholder)\n- Step counter: wired to Android TYPE_STEP_COUNTER sensor\n- Proximity preset: added normalize (0-5 range) before invert\n- Crash detect preset: subtract 1g before threshold check\n\nVerified: altimeter, floor detect, level, compass, inclinometer,\nlight meter, g-force, peak g, vibration, tachometer, gaussmeter,\nSPL meter, metal detector all producing correct values.","parents":["5d017cb69c64cb3540268a468197d8084e8c355d"],"add":106,"del":32,"cadd":106,"cdel":32,"files":5},{"repo":"reflex","hash":"764ba2cf1b5f07512f60ee480a17a9aa01c78ca4","ts":1774461291,"wall":"2026-03-25T13:54","msg":"reflex: fix output cells to match hardware reality","body":"Output cells now reflect actual hardware capabilities:\n- Removed TorchDim (hardware is binary, can't dim)\n- Removed TorchPulseRate → renamed TorchBlink (accurate name)\n- Added HapticClick (predefined EFFECT_CLICK on threshold crossing)\n- Added ScreenBrightness (0-255 display brightness as output)\n- Added ScreenColor (value→color gradient on screen)\n- Added vibrateEffect() to Haptics for predefined effects\n\nCleanup:\n- Deleted FeedbackEngine.kt (fully replaced by OutputDriver)\n- Deleted Pipeline.kt (fully replaced by Cell engine)\n- Removed FeedbackEngine from ReflexApp\n- OutputDriver handles all new output types\n- InstrumentStore serialization updated for new types\n\nMenu restructured:\n- 6 categories: Sensor, Math, Sense, Track, Body, Light\n- ALL_ITEMS map with CellItem data class for clean lookup\n- Ring-2 offsets for categories with >6 items\n- Gyroscope added as source cell\n\nTotal: 8 sources, 24 transforms, 10 outputs = 42 cell types","parents":["15dd0b21022f509f00f3aea78b468d7faed9e196"],"add":249,"del":683,"cadd":249,"cdel":683,"files":8},{"repo":"reflex","hash":"7f977023757acb2801b3fdcaf08b736289f05498","ts":1774463363,"wall":"2026-03-25T14:29","msg":"reflex: 65 cell types — full computational environment","body":"New sources (8):\n- Gyroscope, Orientation (rotation vector), Gravity (AOSP fusion),\n  Linear Acceleration (minus gravity), Battery Level, Battery Temp\n- Timer (seconds since activation), Constant (fixed value),\n  Oscillator (sine wave generator with configurable freq/amplitude)\n\nNew transforms (10):\n- Counter (count threshold crossings)\n- Latch (capture value on trigger)\n- Edge Detect (pulse on rising/falling edge)\n- Gate (pass through only above threshold)\n- Delay (output = input from N ticks ago, circular buffer)\n- Debounce (require N consecutive ticks before passing change)\n- Min Of / Max Of (min/max of all inputs)\n- Average (mean of all inputs)\n- Modulo (input mod divisor)\n\nNew categories: Gen (generators), Logic (computational transforms)\n7 categories total: Sensor, Gen, Math, Sense, Logic, Body, Visual\n\nSensorBridge: handles virtual/fusion sensors (Rotation Vector,\nGravity, Linear Acceleration), battery queries, timer, constant,\noscillator. All with proper serialization in InstrumentStore.\n\n39 transforms, 16 source types, 10 output types = 65 cell types.\n22 preset instruments. Custom save/load persists all new types.","parents":["764ba2cf1b5f07512f60ee480a17a9aa01c78ca4"],"add":241,"del":24,"cadd":241,"cdel":24,"files":5},{"repo":"reflex","hash":"76b45edcacd7d939927432604c7cdba3389d811e","ts":1774484642,"wall":"2026-03-25T20:24","msg":"reflex: tooltips for all 65 cell types","body":"Every cell in the hex bloom menu now has a one-line description:\n- Long press a cell hex to see its tooltip\n- Description explains what the cell does in plain language\n- Hovered hex brightens, tooltip appears below the cluster\n- Category hexes show item count on long press\n\nExamples:\n- Smooth: \"Slow down changes (low-pass)\"\n- Gate: \"Pass through only above threshold\"\n- Edge: \"Pulse when value crosses threshold\"\n- Latch: \"Capture and hold on trigger\"\n- Screen: \"Screen brightness (0=dark, 1=max)\"","parents":["7f977023757acb2801b3fdcaf08b736289f05498"],"add":148,"del":83,"cadd":148,"cdel":83,"files":1},{"repo":"reflex","hash":"fdf795e0b9061e10dea6ba098ab25cb1fc164154","ts":1774491341,"wall":"2026-03-25T22:15","msg":"reflex: 95 cell types, 61 transforms — complete hex vocabulary","body":"New transforms (22 added, 61 total):\n- Boolean: NAND, AND, OR, NOT, XOR (complete logic gate set)\n- Comparison: Greater, Less (threshold-based)\n- Trig: Sin, Cos\n- Exponential: Log, Exp, Pow\n- Arithmetic: Negate, Reciprocal\n- Rounding: Floor, Ceil, Round\n- Signal: Quantize, Select, Crossfade\n- Windowed: WindowMean (moving average over N ticks),\n  WindowSlope (linear regression trend — fixes weather instrument)\n\nNew sources (7 added, 23 total):\n- GPS: Latitude, Longitude, Speed, Bearing (stubs, need GPS wiring)\n- Raw Accelerometer (icm4n607_acc without fusion)\n- Step Detector (individual step events)\n- Device Orientation (portrait/landscape 0-3)\n\nNew outputs (1 added, 12 total):\n- Speech (TTS on threshold crossing, configurable prefix/suffix)\n\nMenu restructured: 9 categories\n- Sensor (20), Gen (3), Math (20), Signal (12), Sense (7),\n  Logic (13), Memory (7), Body (6), Visual (6)\n\nAll serialization updated for new types.\nWindowSlope transform enables weather/barometric trend detection.\nNAND gate is functionally complete — any logic buildable from it.","parents":["76b45edcacd7d939927432604c7cdba3389d811e"],"add":338,"del":20,"cadd":338,"cdel":20,"files":6},{"repo":"reflex","hash":"927ad2185dc6fe76e529383457bc1594952eda19","ts":1774491891,"wall":"2026-03-25T22:24","msg":"docs: session handoff — 95 cell types, hex language, architecture decisions","body":"","parents":["fdf795e0b9061e10dea6ba098ab25cb1fc164154"],"add":107,"del":0,"cadd":107,"cdel":0,"files":1},{"repo":"reflex","hash":"c878ea56a98731da55d103093d50b10b09bf9d29","ts":1774492125,"wall":"2026-03-25T22:28","msg":"reflex: double tap hex to delete — symmetric with double tap empty to create","body":"","parents":["927ad2185dc6fe76e529383457bc1594952eda19"],"add":13,"del":2,"cadd":13,"cdel":2,"files":1},{"repo":"reflex","hash":"3861975a1c4b86811dea3430f637b799f2031ef6","ts":1774492293,"wall":"2026-03-25T22:31","msg":"reflex → Cell: rename app display name. Package rename deferred.","body":"","parents":["c878ea56a98731da55d103093d50b10b09bf9d29"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"reflex","hash":"e5edcc922a62db78a231c85bd4dffdc533f3a0c0","ts":1774493237,"wall":"2026-03-25T22:47","msg":"reflex: harden cell engine — 6 structural fixes","body":"1. Fix zero sentinel: replaced all inp[0] == 0f initialization\n   guards with Cell.initialized boolean flag. Zero is now a valid\n   sensor value. Transforms use !init (not !zero) to detect first\n   tick. CellGraph sets initialized = true after first successful\n   transform execution.\n\n2. Build adjacency index: incomingIndex (Map<CellId, List<Edge>>)\n   rebuilt on graph mutation. collectInputs is now O(neighbors)\n   per cell instead of O(edges). rebuildIncomingIndex called from\n   invalidate().\n\n3. Fix window_slope: removed dead first-pass computation (lines\n   that computed num incorrectly then immediately reset it). Clean\n   single-pass: compute yMean, then numerator+denominator together.\n\n4. Clean up dead port fields: Edge simplified from (fromCell,\n   fromPort, toCell, toPort, attenuation) to (fromCell, toCell,\n   attenuation). No ports — adjacency determines connections, full\n   value array flows through.\n\n5. Delete dead code: WireRenderer.kt (no wires in adjacency model),\n   EdgeDef (no explicit edges in presets).\n\n6. Transform signature: (inputs, state, initialized) → result.\n   All 61 transforms updated. Initialized flag prevents silent\n   corruption from transforms initializing on zero-valued inputs.\n\nCalibrate() now resets cell.initialized flag instead of positional\nstate hacks. Cleaner, handles all transform types uniformly.","parents":["3861975a1c4b86811dea3430f637b799f2031ef6"],"add":145,"del":282,"cadd":145,"cdel":282,"files":5},{"repo":"reflex","hash":"ce2a2a3e7e36197898ff30e35223fd75944922ee","ts":1774494113,"wall":"2026-03-25T23:01","msg":"reflex: test suite (73 tests) + dead code elimination","body":"Test Suite:\n- TransformRegistryTest: 60 tests covering all core transforms\n  - Basic math: passthrough, normalize, invert, abs, scale, negate,\n    squared, sqrt, reciprocal, add, multiply, average, modulo\n  - Trig/exp: sin, cos, log, exp, pow\n  - Rounding: floor, ceil, round\n  - Boolean logic: AND, OR, NOT, XOR, NAND\n  - Threshold/comparison: threshold, greater, less, sign, gate, deadzone\n  - Sensor transforms: magnitude, pressure_to_altitude, gravity_to_tilt,\n    rms_to_db, quantize\n  - Stateful: baseline_subtract, smooth, delta (initialization tests)\n  - Edge detect, counter, min/max of inputs\n  - Zero as valid sensor value (regression test for warmup bug)\n\n- CellGraphTest: 13 tests covering graph evaluation\n  - Source propagation, transform processing, chains\n  - Adjacency: non-adjacent don't connect, wrong direction blocked\n  - Fan-out to multiple outputs\n  - Initialization flag prevents premature processing\n  - Calibrate resets initialized state\n  - Remove cell cleans edges\n\nDead Code Eliminated:\n- Removed dead bindingKey() call in SensorBridge.kt\n- Removed unused import edgeMap in HexRenderer.kt\n- Removed unused import ButtonService in WorkspaceScreen.kt\n- Deleted WireRenderer.kt (dead file from wire era)\n- Removed dead EdgeDef data class\n\nAdded JUnit 4.13.2 test dependency.\n73 tests, 0 failures, 0.133s execution.","parents":["e5edcc922a62db78a231c85bd4dffdc533f3a0c0"],"add":674,"del":31,"cadd":671,"cdel":31,"files":6},{"repo":"reflex","hash":"ed126dabfb1b229793cccc6071170d5465a61392","ts":1774495447,"wall":"2026-03-25T23:24","msg":"reflex: 98 tests, 100% transform coverage, dead code eliminated","body":"Test suite expanded from 73 to 98 tests:\n- All 61 transforms now tested (was 45)\n- New tests: clamp, mag_to_heading, max/min_tracker (stateful\n  capture + hold), accumulate, map_range (custom ranges),\n  rate_of_change, pitch_roll, extract_index, hysteresis (full\n  4-state cycle), latch (rising edge capture), delay (circular\n  buffer fill + output), debounce (persistence requirement),\n  select, crossfade (3-point interpolation), window_mean,\n  window_slope (flat + rising data)\n\nTest-found bug fixes:\n- Delay test revealed buffer fill timing was correct but test\n  expectations were wrong — fixed test to match actual behavior\n- Debounce test revealed candidate initialization adds 1 tick\n  latency — fixed test expectations\n\nDead code eliminated:\n- Removed orphaned bindingKey() call in SensorBridge\n- Removed unused edgeMap import in HexRenderer\n- Removed unused ButtonService import in WorkspaceScreen\n\n98 tests, 0 failures, 0.141s. All green.","parents":["ce2a2a3e7e36197898ff30e35223fd75944922ee"],"add":201,"del":2,"cadd":201,"cdel":2,"files":2},{"repo":"reflex","hash":"576bd8c5fdd984794e17e7a01413028a021bf2f0","ts":1774495905,"wall":"2026-03-25T23:31","msg":"reflex: 138 tests — edge maps, presets, serialization coverage","body":"New test files:\n- EdgeMapTest (9 tests): source/transform/output edge roles,\n  directional compatibility (source→transform OK, output→source\n  blocked), input/output edge sets correct for all cell types\n\n- PresetsTest (28 tests): all 22 presets build valid graphs,\n  no duplicate cell positions, no duplicate cell IDs, unique\n  preset IDs, all presets have sources and outputs, names and\n  descriptions not empty\n\n- InstrumentStoreTest (3 tests): all 25 SensorBinding variants\n  constructable and produce valid EdgeMaps, all 12 OutputBinding\n  variants constructable, all 61 transform IDs registered and named\n\nCoverage:\n- TransformRegistryTest: 85 tests (100% transform coverage)\n- CellGraphTest: 13 tests (evaluation, adjacency, initialization)\n- EdgeMapTest: 9 tests (edge role system)\n- PresetsTest: 28 tests (all 22 presets)\n- InstrumentStoreTest: 3 tests (type system completeness)\n\n138 tests total, 0 failures, 0.175s.","parents":["ed126dabfb1b229793cccc6071170d5465a61392"],"add":285,"del":0,"cadd":285,"cdel":0,"files":3},{"repo":"reflex","hash":"be1bb19d05a1e0d0f091a5c0e9c0410e63517bac","ts":1774496273,"wall":"2026-03-25T23:37","msg":"reflex: 22 instrumented tests — sensors verified on hardware","body":"Instrumented tests run on the Ulefone Power Armor 19T:\n\nSensor availability (11 tests):\n- Accelerometer, gyroscope, magnetometer, barometer, light,\n  proximity, step counter, gravity, rotation vector, linear\n  acceleration all confirmed present\n- 22+ sensors total on device\n\nSensorBridge data delivery (9 tests):\n- Accelerometer delivers non-zero 3-axis data within 500ms\n- Barometer reads 900-1100 hPa (sane atmospheric range)\n- Magnetometer reads 10-200 µT (Earth's field range)\n- Light sensor reads ≥0 lux\n- Timer increases correctly (~0.5s over 500ms sleep)\n- Constant returns exact configured value (42.0)\n- Oscillator produces positive and negative values (sine)\n- Battery level reads 0-100%\n- Battery temperature reads 10-60°C\n\nFull pipeline (2 tests):\n- Level instrument: activates, runs 1s, accel cell has data\n- Metal detector: activates, runs 1s, display shows anomaly\n\nTotal: 138 JVM tests + 22 instrumented = 160 tests, 0 failures.\n\nAdded androidTest dependencies: androidx.test.ext:junit,\nandroidx.test:runner, androidx.test:rules.","parents":["576bd8c5fdd984794e17e7a01413028a021bf2f0"],"add":330,"del":1,"cadd":323,"cdel":0,"files":2},{"repo":"reflex","hash":"7216d8c959a46eaba7f753988fa69174adce37a8","ts":1774496578,"wall":"2026-03-25T23:42","msg":"reflex: wire GPS — continuous location updates via FusedLocationProvider","body":"GPS source cells now deliver real data:\n- GpsLatitude, GpsLongitude: position in degrees\n- GpsSpeed: speed in m/s\n- GpsBearing: heading in degrees\n- LocationAlt: altitude in meters\n\nImplementation: FusedLocationProviderClient.requestLocationUpdates\nat 1Hz (HIGH_ACCURACY priority). LocationCallback pushes values\ninto SensorBridge.latestValues on each fix. Stops on unbind.\n\nRequires ACCESS_FINE_LOCATION permission (already declared and\nrequested in PermissionScreen).\n\nAll 23 source hexes now wired to real hardware or internal generators.\nZero stubs remaining.","parents":["be1bb19d05a1e0d0f091a5c0e9c0410e63517bac"],"add":60,"del":6,"cadd":60,"cdel":6,"files":1},{"repo":"reflex","hash":"acdd15751b57174cebcee269ea283cf727a3fbb3","ts":1774496800,"wall":"2026-03-25T23:46","msg":"revert: keep app name as Reflex","body":"","parents":["7216d8c959a46eaba7f753988fa69174adce37a8"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"reflex","hash":"20ff2e8237a65552995f544a410516c3bba68995","ts":1774497065,"wall":"2026-03-25T23:51","msg":"docs: complete session handoff — 160 tests, 95 cells, GPS wired, engine hardened","body":"","parents":["acdd15751b57174cebcee269ea283cf727a3fbb3"],"add":77,"del":70,"cadd":77,"cdel":70,"files":1},{"repo":"reflex","hash":"ad36dc5c68aa5349088c0bcc94f2d38e0363446d","ts":1774533187,"wall":"2026-03-26T09:53","msg":"reflex: parameter editor, 17 transforms, 4 radios, infrastructure paydown","body":"Parameter editor: tap any hex → ModalBottomSheet with description,\nlive value, connections, and parameter sliders. Changes apply\nimmediately. ParamSpec metadata registry covers all 125 cell types.\n\nNew transforms (17): fuzzy logic (tri, trap, gauss, sigmoid, defuzz),\ncontrol (PID, bang-bang), oscillators (square, triangle, sawtooth),\nenvelope (ADSR, slew limiter), sequencer (step, toggle), routing\n(mux, demux), sample-hold. Complete Sugeno fuzzy inference system.\n\nRadio sources (4): WiFi (RSSI, count, freq, speed + HTTP API),\nBLE (scan, advertise, GATT client + server + HTTP API),\nNFC (presence, UID, type, NDEF read/write + HTTP API),\nFM (graceful failure — /dev/fm needs root, code ready).\n\nInfrastructure: source/output binding params editable via state[],\nMicSession shared singleton, CellId offset eliminated (localId=CellId),\nweather preset fixed (Rate→WindowSlope), step counter sensor types fixed,\ndefaultState() now spec-derived for all 78 transforms.\n\n125 cell types, 12 categories, 235 tests passing.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["20ff2e8237a65552995f544a410516c3bba68995"],"add":3282,"del":82,"cadd":3281,"cdel":82,"files":31},{"repo":"reflex","hash":"1e6c9d384a80fd08970a97c19a1adaba83ca61f9","ts":1774533411,"wall":"2026-03-26T09:56","msg":"docs: update handoff — Session 26, 125 cells, 4 radios, parameter editor","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["ad36dc5c68aa5349088c0bcc94f2d38e0363446d"],"add":107,"del":76,"cadd":107,"cdel":76,"files":1},{"repo":"operations","hash":"8bd7c55562049ebd6358ece362b1523505d0cb78","ts":1774533427,"wall":"2026-03-26T09:57","msg":"research: glyphic space dimensional architecture — hexagon → tessellation → truncated octahedron","body":"The cell language geometry at three scales: hexagon (1D cell),\nhex tessellation (2D control surface), truncated octahedron (3D body volume).\nSame optimization at each dimension — tile space, maximize volume per surface,\nuniform connectivity, single shape.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["035d74ba7d40446a848aa32ed0be827bf3099ede"],"add":84,"del":0,"cadd":84,"cdel":0,"files":1},{"repo":"operations","hash":"1e660e00af416c6270ecd8bc88e010f58e2b40cb","ts":1774533738,"wall":"2026-03-26T10:02","msg":"docs: session log + dashboard — Reflex Session 26","body":"125 cell types, 4 radios, parameter editor, fuzzy logic, infrastructure zero.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["8bd7c55562049ebd6358ece362b1523505d0cb78"],"add":44,"del":1,"cadd":44,"cdel":1,"files":2},{"repo":"reflex","hash":"d5c0dad787ebb9a697a0fd4eb19688f6a96ec8a2","ts":1774544937,"wall":"2026-03-26T13:08","msg":"refactor: rename package systems.symbiont.reflex → systems.symbiont.cell","body":"Android package, namespace, applicationId, all imports, manifest intent\nactions, and SharedPreferences names updated. App display name stays\n\"Reflex\". All 213 JVM tests pass.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["1e6c9d384a80fd08970a97c19a1adaba83ca61f9"],"add":145,"del":145,"cadd":141,"cdel":141,"files":71},{"repo":"reflex","hash":"ea44cc67b1d720f4aeb118fd6a863efc3d422cfd","ts":1774546894,"wall":"2026-03-26T13:41","msg":"feat: camera source cells, FFT, CSV recording, device portability","body":"Eight-step instrument gap closure:\n1. SensorBridge uses Sensor.TYPE_* constants (no chip names)\n2. GET /capabilities endpoint with full hardware inventory\n3. CameraAnalyzer: continuous 640x480 YUV frame pipeline\n4. Camera source cells: brightness, RGB, focus (cam 0 + cam 2)\n5. IR thermometer: JNI reflection probe with graceful failure\n6. FFT transform (ID 78): Cooley-Tukey radix-2, Hann window\n7. CSV recording output with /recordings HTTP endpoints\n8. RadialMenu greys out unavailable cells per device\n\nNew files: CameraAnalyzer.kt, Capabilities.kt, IrThermometer.kt,\nCapabilityRoutes.kt, RecordingRoutes.kt\n\nAll 213 JVM tests pass. APK builds clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d5c0dad787ebb9a697a0fd4eb19688f6a96ec8a2"],"add":793,"del":46,"cadd":793,"cdel":46,"files":15},{"repo":"reflex","hash":"b2729efd9e759d9197b83e04e8f476bf8577d65a","ts":1774551223,"wall":"2026-03-26T14:53","msg":"feat: FLIR Lepton thermal camera integration via Atlas SDK","body":"Two-phase lifecycle: discover() runs eagerly at app init (no camera\naccess needed), connect() runs lazily from SensorBridge.bind() under\nthe foreground service (camera permission satisfied).\n\nFLIR Atlas SDK 2.18.0 discovers the integrated Lepton 3.5 on the\nUlefone Power Armor 19T via CommunicationInterface.INTEGRATED.\nConfirmed working: discovery finds \"Power Armor 19T\" in ~50ms.\n\nFive thermal source cells: ThAvg, ThMin, ThMax, ThHotX, ThHotY.\nFrame statistics (avg/min/max °C, hot/cold spot position) streamed\nper frame at Lepton native rate (~9 fps).\n\nSDK requires minSdk 33 but works on Android 12 (API 31) with\nmanifest override. GET /thermal endpoint for status inspection.\n\nAll 213 JVM tests pass. APK builds clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ea44cc67b1d720f4aeb118fd6a863efc3d422cfd"],"add":543,"del":6,"cadd":530,"cdel":6,"files":14},{"repo":"reflex","hash":"57644b0714d8af3367aa30182c203109c13ed5bf","ts":1774560364,"wall":"2026-03-26T17:26","msg":"reflex: biomorphic bloom menu — 8-category taxonomy from first principles","body":"Taxonomy derived from irreducible signal processing primitives:\nInput (47), Generate (6), Transform (44), Branch (21), State (8),\nControl (2), Functions (0, ready for composites), Output (14, always last).\n\nBiomorphic spiral layout — items grow outward organically from center\nbased on category size. Dense categories fill more rings, small\ncategories are tight buds. No hardcoded ring positions.\n\nPinch-to-zoom (0.3x-3x) and two-finger pan for navigating large\ncategories. Tap outside any hex to dismiss. Zoom resets on category change.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["b2729efd9e759d9197b83e04e8f476bf8577d65a"],"add":257,"del":159,"cadd":257,"cdel":159,"files":1},{"repo":"reflex","hash":"ebc3a8ec5f9f8adf0882e63d815a506e775c824a","ts":1774560439,"wall":"2026-03-26T17:27","msg":"docs: update handoff — Session 27, bloom taxonomy, edge behavior, cameras","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["57644b0714d8af3367aa30182c203109c13ed5bf"],"add":87,"del":108,"cadd":87,"cdel":108,"files":1},{"repo":"operations","hash":"a0cb3e18d2fbfa8fe0ddb9de844b63a7bce37c3e","ts":1774560464,"wall":"2026-03-26T17:27","msg":"docs: session log — Reflex Session 27, bloom taxonomy + edge behavior","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["1e660e00af416c6270ecd8bc88e010f58e2b40cb"],"add":28,"del":0,"cadd":28,"cdel":0,"files":1},{"repo":"reflex","hash":"a3131465bfd6d01ffb185e8999bdbb7cc15542fa","ts":1774562910,"wall":"2026-03-26T18:08","msg":"docs: update CLAUDE.md — design philosophy, current architecture","body":"Record Bret Victor's \"Inventing on Principle\" as the foundational\ndesign reference. Document reactive dataflow paradigm, state[] as\nuniversal interface (parameters + aesthetics), instrument-as-app\nconcept (build mode / play mode), and the full current architecture.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ebc3a8ec5f9f8adf0882e63d815a506e775c824a"],"add":91,"del":56,"cadd":91,"cdel":56,"files":1},{"repo":"reflex","hash":"a736b9809a39f86f4c998e64fdca5eb17af0fd8d","ts":1774563492,"wall":"2026-03-26T18:18","msg":"fix: edge config UI, mic normalization, API key persistence","body":"Edge config UI: CellDetailSheet now shows edge section with role\nselector (DEFAULT/SIGNAL/CONTROL/FEEDBACK/GATE/MONITOR), attenuation\nslider, channel selector, and control target picker. Tap role chip\nto expand, FilterChip row to switch roles. Color-coded per role.\n\nMic normalization: removed /Short.MAX_VALUE division from mic RMS\nconsumer. Raw 16-bit PCM RMS now flows to rms_to_db transform.\nRecalibrated: 20*log10(rms)+30 gives ~30 dB silence, ~98 dB speech,\n~120 dB clipping. Preset normalize ranges unchanged (already correct).\n\nAPI key persistence: key now derived deterministically from\nANDROID_ID + package name via SHA-256. Same device always produces\nthe same key — survives reinstalls. Old random keys auto-migrated.\n\nAll tests pass. APK builds clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["a3131465bfd6d01ffb185e8999bdbb7cc15542fa"],"add":182,"del":21,"cadd":182,"cdel":21,"files":6},{"repo":"reflex","hash":"b04e4c2dc67d423ba7ab8e6f4ac3fc48f2285aac","ts":1774563591,"wall":"2026-03-26T18:19","msg":"docs: construct/engage mode terminology","body":"Build mode → Construct. Play mode → Engage.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["a736b9809a39f86f4c998e64fdca5eb17af0fd8d"],"add":5,"del":1,"cadd":5,"cdel":1,"files":1},{"repo":"reflex","hash":"d2318c3163f453aa3901d96e7daeaa3706e47ab7","ts":1774568369,"wall":"2026-03-26T19:39","msg":"feat: WebSocket instrument streaming + interactive touch cells","body":"Phase 1A — WebSocket snapshot streaming:\nNew /ws/instrument endpoint broadcasts full EngineSnapshot as JSON\nat 20Hz. StateFlow is inherently conflated — slow consumers always\nget the latest frame. Any browser or tool with a WebSocket client\nbecomes a real-time instrument frontend.\n\nPhase 1B — Interactive source cells:\nThree new source cells driven by touch instead of hardware:\n- TouchButton: momentary (1 while held, 0 on release)\n- TouchSlider: drag vertically for 0-1 continuous value\n- TouchToggle: tap to flip between 0 and 1\nValues written to state[0] by UI via updateCellParam, read by\nSensorBridge each tick. Same mechanism as Constant cell but\ndriven by touch events instead of parameter editor.\n\nCell count: ~145 (was ~142).\n\nAll tests pass. APK builds clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["b04e4c2dc67d423ba7ab8e6f4ac3fc48f2285aac"],"add":84,"del":0,"cadd":84,"cdel":0,"files":7},{"repo":"reflex","hash":"156130c26bff0544e9486fcc51900bdc1b02e9b2","ts":1774568639,"wall":"2026-03-26T19:43","msg":"docs: update handoff — Session 28, full feature inventory","body":"8 commits this session: package rename, camera/FFT/CSV/thermal,\nbloom menu, design philosophy, infrastructure fixes, WebSocket\nstreaming, interactive touch cells. 145 cell types, 47+ endpoints,\n3 WebSocket streams. Feature roadmap at plans/reflex-feature-roadmap.md.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d2318c3163f453aa3901d96e7daeaa3706e47ab7"],"add":115,"del":77,"cadd":115,"cdel":77,"files":1},{"repo":"reflex","hash":"e776a366104de84b52efd379c9b22789ec12a3ec","ts":1774569282,"wall":"2026-03-26T19:54","msg":"feat: aesthetic state[] + Play mode hex renderers","body":"Phase 2A — Aesthetic state[] extension:\nFixed indices 100-106 in state[] for display properties: displayType,\nhue, fontSize, gaugeMin/Max, decimals, visible. Implicit defaults per\ncell type (Display=number, Threshold=LED, Constant=dial, etc).\nCollapsible \"display\" section in CellDetailSheet. CONTROL edges can\ntarget aesthetic slots — wire a temperature to a color.\n\nPhase 2B — Play mode hex renderers:\nNew PlayHexRenderer.kt with 8 widget renderers:\n- Number: big centered text with decimal formatting\n- LED: filled hex, on/off color by value threshold\n- Gauge: arc with needle, min/max range from aesthetic state\n- Bar: horizontal fill proportional to value\n- Dial: rotary knob with pointer (for constants/sliders)\n- Waveform: sine path inside hex (for oscillators)\n- Spectrum: vertical bars for FFT multi-value output\n- Color fill: hex filled with output color\n\nIn VIEW mode (Play), transform cells hidden by default (visible=0).\nSource and output cells render as their natural widget. Users can\noverride any cell's visibility and display type via the parameter\neditor or CONTROL edges.\n\nAll tests pass. APK builds clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["156130c26bff0544e9486fcc51900bdc1b02e9b2"],"add":452,"del":21,"cadd":452,"cdel":21,"files":5},{"repo":"reflex","hash":"582af139f96c30d036179e0679d24465b4c08177","ts":1774727346,"wall":"2026-03-28T15:49","msg":"reflex: .cell language foundations — terminology rename, fork-to-edit, composite scaffolding","body":"Terminology rename (14 files):\n- CellDef.localId → slot, CellDef.name → label\n- Cell.name → label, CellSnapshot.name → label\n- CellItem.label → kind, BuilderState.nextLocalId → nextSlot\n- JSON wire format keys unchanged for backward compat\n\nFork-to-edit feature:\n- BuilderState.loadFromInstrument() loads preset cells into builder\n- InstrumentEngine.forkToBuilder() relabels running graph as builder\n- EDIT button in status bar when preset active — tap to fork into Build mode\n\nComposite cell scaffolding:\n- CellType.Composite, InputPort, OutputPort variants\n- InstrumentDef.inputPorts/outputPorts with positional resolution\n- FunctionStore for user-defined function persistence\n- Exhaustive when branches across all CellType users\n\nAll 242+ tests pass. APK builds.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["e776a366104de84b52efd379c9b22789ec12a3ec"],"add":825,"del":50,"cadd":825,"cdel":50,"files":21},{"repo":"operations","hash":"a4c718c30a2998301d59f1c8c444c986ea383539","ts":1774727453,"wall":"2026-03-28T15:50","msg":"research: dataflow graph serialization formats — survey of 14 systems","body":"Survey of how visual programming and dataflow tools serialize their graphs.\nCovers Pure Data, Max/MSP, SuperCollider, FAUST, Reaktor, Node-RED,\nUnreal Blueprints, Unity ShaderGraph, Godot, MaterialX, DOT, SPICE,\nVerilog, and Mermaid.\n\nKey findings: three naming strategies (identity-is-text, explicit split,\ncomputed display), four connection models (explicit edges, output-centric,\nshared-net, algebraic), and the type/name distinction critical for .cell format.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["a0cb3e18d2fbfa8fe0ddb9de844b63a7bce37c3e"],"add":698,"del":0,"cadd":698,"cdel":0,"files":1},{"repo":"operations","hash":"28236a12328e8ced79b16418c7a31cab811e8ead","ts":1774729436,"wall":"2026-03-28T16:23","msg":"spec: Cell language specification v0.1 (draft)","body":"The constitution for the Cell dataflow language. Covers:\n- Data model (Graph, CellDef, Role, EdgeMod, Coord, BoundaryPort)\n- Terminology (kind, label, slot, role, family, catalog)\n- .cell text format grammar (EBNF) with examples\n- Evaluation model (inject → evaluate → drive, reactive dirty propagation)\n- Seven axioms (spatial composition, fractal functions, unified params, native distribution)\n- Four-layer architecture (Play, Build, Text, Binary)\n- Deferred features (edge syntax, binary format, polyglot cells, recursion)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["a4c718c30a2998301d59f1c8c444c986ea383539"],"add":407,"del":0,"cadd":407,"cdel":0,"files":1},{"repo":"reflex","hash":"89871ec218abbfc89863108ad85a8ad94e19bb81","ts":1774750255,"wall":"2026-03-28T22:10","msg":"rename: ‖Mag‖ → Len (vector magnitude transform)","body":"The double-bar Unicode notation was ungreppable, terminal-hostile,\nand meaningless to anyone outside linear algebra. Len is what it\ncomputes — the length of a vector. Clean, short, no collisions.\n\nMag remains the magnetometer source (SensorBinding.MagneticField).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["582af139f96c30d036179e0679d24465b4c08177"],"add":2,"del":2,"cadd":2,"cdel":2,"files":2},{"repo":"operations","hash":"59b5eff3860d43d59ea82aebcf6980897362715c","ts":1774750305,"wall":"2026-03-28T22:11","msg":"spec: Cell identity system — cell, organ, organism","body":"Three-level compositional identity:\n- Cell ID = Kind@Q,R{params} — intrinsic, derived from structure\n- Organ ID = sorted set of cell IDs — one machine's graph\n- Organism ID = sorted set of organ IDs + boundary connections\n\nIdentity is never assigned, always derived. The .cell file IS the\nidentity — every cell line is a cell ID. Labels are cosmetic.\n\nAlso: ‖Mag‖ → Len in all spec examples.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["28236a12328e8ced79b16418c7a31cab811e8ead"],"add":86,"del":8,"cadd":86,"cdel":8,"files":1},{"repo":"operations","hash":"8a378499291dc1a1b3d9563e11d67848caf1da7b","ts":1774751331,"wall":"2026-03-28T22:28","msg":"spec: edge declarations promoted to v0.1, grammar unified","body":"Edges are first-class statements alongside cells — not a sub-grammar.\nEdge ID = CellID → CellID : Role{modifiers}. DEFAULT edges implied\nby adjacency, only non-DEFAULT edges declared.\n\nAdded edge examples: CONTROL (light modulates smoothing alpha),\nGATE (button enables/disables haptic output).\n\nOrgan ID now includes sorted edge IDs.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["59b5eff3860d43d59ea82aebcf6980897362715c"],"add":58,"del":9,"cadd":58,"cdel":9,"files":1},{"repo":"somaphore","hash":"5302520a35ee4d9f6b6e240f816cec492226181b","ts":1774754662,"wall":"2026-03-28T23:24","msg":"feat: .cell parser and writer — the language lives","body":"First implementation of the Cell text format. Parser reads .cell text\ninto Document/Graph/CellDef/EdgeDef structs. Writer emits them back.\n16 tests: parse, round-trip, identity, edges, boundaries, functions.\n\nThe .cell format IS the identity system:\n- Cell ID = Kind@Q,R{params}\n- Organ ID = sorted set of cell IDs + edge IDs\n- Organism ID = sorted set of organ IDs + boundary connections\n\nCovers all v0.1 spec constructs: instruments, functions, params,\nport tags, edge declarations, boundary ports, comments, metadata.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["a525f51489be5e383a19c64a809eef535c581748"],"add":853,"del":0,"cadd":853,"cdel":0,"files":2},{"repo":"somaphore","hash":"ca94097a4cbb7acba3ba8d85cd733dbed81c2119","ts":1774755635,"wall":"2026-03-28T23:40","msg":"test: 36 stress tests for .cell parser + 2 bugfixes","body":"Fixed: parse_coord crashed on spaces around comma (@ 0 , 0)\nFixed: organ_id used Debug format for EdgeRole (Control vs CONTROL)\n\n36 stress tests covering: whitespace chaos, special char kinds,\nunicode labels, negative coords, all edge roles, error messages,\nround-trip with every feature, organ ID determinism, full presets.\n\n166 total tests passing across cell-core.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5302520a35ee4d9f6b6e240f816cec492226181b"],"add":388,"del":3,"cadd":388,"cdel":3,"files":3},{"repo":"somaphore","hash":"0364b608b23a61f946fc9046333776bc0f23d675","ts":1774759558,"wall":"2026-03-29T00:45","msg":"WIP: cell-core rebuild for Cell spec — in progress","body":"Deleted: gene.rs, voxel.rs, tiling.rs (archived at tag somaphore-archive)\nRewritten: node.rs (hex-only, CellId, EdgeMod, no Partition, no Gene)\nRewritten: graph.rs, evaluate.rs, error.rs, patch.rs for new Cell struct\nRewritten: integration tests for new API\n\nLibrary compiles clean. One SmallVec size mismatch in transforms test\nremains — mechanical fix, next session.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ca94097a4cbb7acba3ba8d85cd733dbed81c2119"],"add":3308,"del":3285,"cadd":675,"cdel":3285,"files":26},{"repo":"somaphore","hash":"0f2b188a7544e244c13f4c3659fd422c67983c10","ts":1774759850,"wall":"2026-03-29T00:50","msg":"docs: session handoff — Cell language design + cell-core rebuild WIP","body":"Authored by Rowan Valle; Executed by Claude Code","parents":["0364b608b23a61f946fc9046333776bc0f23d675"],"add":24,"del":114,"cadd":24,"cdel":114,"files":1},{"repo":"cell","hash":"0717fabac55771426fce1200186cb70ba228f0fe","ts":1774760656,"wall":"2026-03-29T01:04","msg":"Cell — dataflow language, extracted from somaphore/lib/cell-core","body":"Parser/writer for .cell text format, hex grid graph engine,\nreactive evaluation, 12 transforms, axial coordinates, identity system.\n\n88 tests passing. Gene/voxel/tiling removed — the identity system\n(Kind@Q,R{params} → organ ID → organism ID) is the genetic structure.\n\nSpec: operations/research/cell-language-spec.md","parents":[],"add":2944,"del":0,"cadd":2826,"cdel":0,"files":14},{"repo":"cell","hash":"3b33a79646a4a2e6c0e4140d1674aa1f8305150d","ts":1774767622,"wall":"2026-03-29T03:00","msg":"feat: inline edge syntax — edge mods on the receiving cell","body":"Eliminated separate `edge` lines. Edge modifiers are now declared\ninline on the cell they affect: `Smooth @ 1,0 Light@0,-1:CONTROL{target:0}`\n\n- EdgeMod struct replaces EdgeDef (from_kind, from_pos, role, params)\n- CellDef.edge_mods: Vec<EdgeMod> replaces Graph.edges: Vec<EdgeDef>\n- organ_id() derives edge IDs from inline mods, uses → and colon syntax\n- Writer emits inline edge mods after params\n- 90 tests passing, 0 warnings","parents":["0717fabac55771426fce1200186cb70ba228f0fe"],"add":248,"del":200,"cadd":248,"cdel":200,"files":2},{"repo":"operations","hash":"14718e0500dd4635867041d245d3177fef8bb729","ts":1774767656,"wall":"2026-03-29T03:00","msg":"spec: inline edge syntax — edge mods on the receiving cell","body":"Eliminated separate edge declarations. Edge modifiers are now inline\non the cell they affect. EBNF grammar, data model, and all examples\nupdated. Syntax matches identity format: Kind@Q,R:ROLE{params}.","parents":["8a378499291dc1a1b3d9563e11d67848caf1da7b"],"add":33,"del":23,"cadd":33,"cdel":23,"files":1},{"repo":"cell","hash":"423b75b7ee043ad97c3f6fc370d3857752733264","ts":1774771903,"wall":"2026-03-29T04:11","msg":"feat: per-instrument tick rate — tick= metadata on instruments","body":"Default 20 Hz. Audio instruments can run at 44100 Hz, control\nloops at 1000 Hz. Adaptive degradation by halving when over budget.\nFunctions inherit parent tick rate.\n\n92 tests passing.","parents":["3b33a79646a4a2e6c0e4140d1674aa1f8305150d"],"add":33,"del":0,"cadd":33,"cdel":0,"files":1},{"repo":"operations","hash":"7224767d3cad995748e1c1d5ad8cf1298aa5a836","ts":1774771969,"wall":"2026-03-29T04:12","msg":"spec: per-instrument tick rate, rate boundaries","body":"tick= metadata on instrument declarations. Default 20 Hz.\nSupports audio (44100), control (1000), display (60).\nAdaptive degradation by halving. Functions inherit parent rate.\nRate boundaries: subscriber reads most recent published value.","parents":["14718e0500dd4635867041d245d3177fef8bb729"],"add":31,"del":2,"cadd":31,"cdel":2,"files":1},{"repo":"operations","hash":"75ecc371d7487ac67b7ad770932faf8ace1ebec6","ts":1774773638,"wall":"2026-03-29T04:40","msg":"spec: state scoping and sharing — no shared-state primitive","body":"State is per-instance. Sharing via boundary ports (message passing)\nor graph topology (wire through one cell). Database/storage is a\nplatform binding, not a language feature.","parents":["7224767d3cad995748e1c1d5ad8cf1298aa5a836"],"add":12,"del":0,"cadd":12,"cdel":0,"files":1},{"repo":"cell","hash":"18ac066c65b23f47faf60e7bd8ce7bef7a6c22b9","ts":1774790588,"wall":"2026-03-29T09:23","msg":"feat: PortTag face indices + Catalog module (Phases 1-2)","body":"Phase 1: PortTag carries Option<u8> for explicit face mapping.\n[input:3], [output:0] parse and round-trip. Invalid faces rejected.\n\nPhase 2: catalog.rs — kind resolution bridge between .cell text\nand runtime. Resolves primitives (12 transforms + source/output\nkinds) and composites (function sub-graphs). Cycle detection via\nDFS on function reference graph. Name conflicts rejected.\n\n106 tests passing.","parents":["423b75b7ee043ad97c3f6fc370d3857752733264"],"add":444,"del":14,"cadd":444,"cdel":14,"files":3},{"repo":"cell","hash":"d8067eece2e3541ff697f6b92394244e0ede68a4","ts":1774792270,"wall":"2026-03-29T09:51","msg":"feat: Functions — Axiom 3 complete (Phases 3-4)","body":"Phase 3 — Instantiation (instantiate.rs):\n  Graph + Catalog → runtime CellGraph. Resolves kinds, creates cells,\n  links by hex adjacency, builds composite sub-graphs for function\n  references. Port mapping (explicit [input:3] or positional).\n  Edge mods applied (adjacent and non-adjacent).\n\nPhase 4 — Composite evaluation (evaluate.rs):\n  Black-box function evaluation: inject inputs → evaluate sub-graph →\n  extract outputs. State scoped per instance. take()/put-back pattern\n  for borrow checker on composite field.\n\nNode.rs: Cell gains composite: Option<CompositeState> with sub_graph\nand port mappings. CellGraph derives Clone.\n\n117 tests passing, 0 warnings.","parents":["18ac066c65b23f47faf60e7bd8ce7bef7a6c22b9"],"add":705,"del":20,"cadd":705,"cdel":20,"files":5},{"repo":"operations","hash":"0e0c90e54742962717a88e6ca5330109d9857fc2","ts":1774792945,"wall":"2026-03-29T10:02","msg":"research: hex chip — physical Cell language hardware","body":"Comprehensive research on hexagonal PCB tiles as physical instantiation\nof Cell. Existing projects (Nanoleaf, Hackaday hex tiles, PCBWay hex\nrobots), edge interconnect technologies (castellated holes, pogo pins,\nmagnets), manufacturing path, and mapping of every Cell concept to\nphysical hardware. No photolithography required.","parents":["75ecc371d7487ac67b7ad770932faf8ace1ebec6"],"add":210,"del":0,"cadd":210,"cdel":0,"files":1},{"repo":"operations","hash":"03add53117ca7c3cb79dce1cf264bb84ea400557","ts":1774794743,"wall":"2026-03-29T10:32","msg":"spec: comprehensive audit resolution — 19 findings addressed","body":"Resolved all findings from the technical audit:\n\nCritical: adjacency function defined (§3), face direction rule defined\n(§3), Value type specified (§3).\n\nHigh: catalog schema + ParamSpec defined (§3), FEEDBACK initial value\nstated (0.0), error semantics added (§5), boundary port binding\nsemantics specified (§3).\n\nModerate: family removed from terminology, slot removed from data\nmodel, CellRef formalized, category clarified for functions,\ndistributed example rewritten as two instruments, id derivation\nrule completed.\n\nDesign: all-float constraint elevated to Axiom 8, port_tag with\nexplicit face indices documented, functions section added to\nevaluation (§5), inline expansion noted as deferred optimization,\ntick rate recovery rule specified.\n\nAlso: VALUE defined in EBNF, port_tag EBNF updated for face index.","parents":["0e0c90e54742962717a88e6ca5330109d9857fc2"],"add":197,"del":52,"cadd":197,"cdel":52,"files":1},{"repo":"operations","hash":"017532c53a4da911f2c36353c6f0923161ea24fd","ts":1774797998,"wall":"2026-03-29T11:26","msg":"spec: edge model — one face, one connection, one Value","body":"Definitive edge model in §3 \"Faces, Edges, and Data Flow\":\none face = one connection = one Value (1-8 float channels).\n3 in, 3 out per hex. Max 24 channels per direction.\nChannel packing and composition for wider fan-in.\n\nHex chip doc updated with software-to-hardware trace mapping.\nThe spec is the schematic.","parents":["03add53117ca7c3cb79dce1cf264bb84ea400557"],"add":85,"del":10,"cadd":85,"cdel":10,"files":2},{"repo":"cell","hash":"b84d0b82b8851474021425bc551d90276bd8c58a","ts":1774798698,"wall":"2026-03-29T11:38","msg":"feat: multi-channel transforms — Values flow through edges","body":"Transform API: fn(&[Value], &[f32]) -> TransformResult\nEach input is a full Value (1-8 float channels), not a scalar.\n\ncollect_inputs respects EdgeMod.channel field:\n  channel == -1: pass full Value with per-channel attenuation\n  channel >= 0: extract that channel as scalar Value\n\nTransforms updated for multi-channel operation:\n  add, multiply: element-wise across channels\n  smooth: preserves channel count (smooths each independently)\n  passthrough: preserves all channels\n  negate3: element-wise 1.0 - x\n  identity3: pass multi-channel or combine scalars\n\nComposite evaluation passes full Values through sub-graph ports.\n\n120 tests, 0 warnings.","parents":["d8067eece2e3541ff697f6b92394244e0ede68a4"],"add":211,"del":114,"cadd":211,"cdel":114,"files":2},{"repo":"reflex","hash":"220df62f571b0b793b59f95b1aada8d99495fd8e","ts":1774799523,"wall":"2026-03-29T11:52","msg":"feat: first .cell instrument — hex-rhythm spatial step sequencer","body":"The beat is the grid. Four Beat functions at different threshold\npositions create a 4/4 pattern. Light sensor modulates ghost note\nvelocity via CONTROL. 1000 Hz tick for millisecond rhythm precision.\nBoundary port publishes kick for cross-device visualization.\n\nFirst file in instruments/ directory.","parents":["89871ec218abbfc89863108ad85a8ad94e19bb81"],"add":55,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"cell","hash":"a9af5877b61db92f13052af96d46f21f877cb273","ts":1774800681,"wall":"2026-03-29T12:11","msg":"feat: JNI bridge — .cell text to Kotlin-compatible JSON","body":"bridge.rs converts parsed Documents to the JSON format that\nReflex's InstrumentStore.jsonToInstrument() expects.\n\nC ABI exports:\n  cell_parse_to_json(input) → JSON string\n  cell_free_string(ptr) → deallocate\n\nMaps Cell kinds to Kotlin CellType:\n  Baro/Light/Mic/etc → Source(SensorBinding)\n  Smooth/Norm/etc → Transform(TransformId)\n  Display/Haptic/etc → Output(OutputBinding)\n  Function refs → Composite(functionId)\n\nCargo.toml: cdylib output for shared library (.so).\n124 tests, 0 warnings.","parents":["b84d0b82b8851474021425bc551d90276bd8c58a"],"add":339,"del":0,"cadd":339,"cdel":0,"files":3},{"repo":"cell","hash":"86c1717fa8a00b675afc65dfb0e3268bde2bd731","ts":1774806429,"wall":"2026-03-29T13:47","msg":"feat: universal tile set — MED, PROD, Complement, Residuum","body":"Four tiles that generate all logic (research/universal-hex-tile-set.md):\n\nMED(a,b,c)    — median. The lattice. MED(a,b,0)=min, MED(a,b,1)=max.\n               Boolean AND/OR, fuzzy conjunction/disjunction, modal\n               necessity/possibility, majority vote — all one tile.\nPROD(a,b,c)   — three-way product. The monoid. Probabilistic\n               conjunction, Bayesian update, polynomial computation.\nComplement(x) — 1-x. Negation across all logics. Per-channel.\nResiduum(a,b) — min(1, 1-a+b). Łukasiewicz implication. The\n               fundamental implication for fuzzy, intuitionistic,\n               and many-valued logics.\n\nSUM already exists (add). Const already exists (Source kind).\n16 transforms total. 136 tests, 0 warnings.","parents":["a9af5877b61db92f13052af96d46f21f877cb273"],"add":189,"del":1,"cadd":189,"cdel":1,"files":2},{"repo":"cell","hash":"4c2ee1b93c611d73019f68435996e4a122e53450","ts":1774806931,"wall":"2026-03-29T13:55","msg":"docs: session handoff — Cell language design + implementation complete","body":"Full session: repo extraction, inline edges, tick rate, functions\n(Axiom 3), multi-channel transforms, JNI bridge, universal tile set.\n136 tests. Next: dual-representation catalog (Option C).","parents":["86c1717fa8a00b675afc65dfb0e3268bde2bd731"],"add":86,"del":0,"cadd":86,"cdel":0,"files":1},{"repo":"cell","hash":"6319919b39d4568616c5dfb81c80e13d9a93dddc","ts":1774807537,"wall":"2026-03-29T14:05","msg":"docs: comprehensive session handoff — all decisions, architecture, next steps","body":"Complete handoff covering: all commits across 3 repos, file inventory,\narchitecture diagram, relationship to somaphore, 4 priority items,\n4 open questions, 18 design decisions with rationale.","parents":["4c2ee1b93c611d73019f68435996e4a122e53450"],"add":128,"del":51,"cadd":128,"cdel":51,"files":1},{"repo":"cell","hash":"afc409e49a0ffeb3451a6a545fa97fec3e263d12","ts":1774811005,"wall":"2026-03-29T15:03","msg":"docs: Axiom 9 + adoption strategy + portability in handoff","body":"Added missing items from session discussion:\n- Axiom 9: Four tiles generate all logic (spec + handoff + memory)\n- Centaur adoption strategy (spec URL, CLI, CLAUDE.md template, WASM)\n- Thin shell portability architecture (pure Rust core, platform shell)","parents":["6319919b39d4568616c5dfb81c80e13d9a93dddc"],"add":22,"del":1,"cadd":22,"cdel":1,"files":1},{"repo":"operations","hash":"a0d67938116a631bd46d4197e5ec4376a0085371","ts":1774811044,"wall":"2026-03-29T15:04","msg":"spec: Axiom 9 — four tiles generate all logic","body":"MED, SUM, PROD, Const + edge attenuation + feedback express\nevery logic: Boolean, fuzzy, modal, probabilistic, paraconsistent,\nintuitionistic, evidential, ternary, threshold, defeasible, deontic,\nmany-valued. All other cell kinds are derived. 9 axioms total.","parents":["017532c53a4da911f2c36353c6f0923161ea24fd"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"cell","hash":"2210ace047ff8e9c5f326555dd2a408c618ae146","ts":1774814180,"wall":"2026-03-29T15:56","msg":"feat: dual-representation catalog — stdlib decompositions","body":"Every derived kind now has both a native TransformId (fast path) and\na .cell function decomposition (structural truth). The catalog stores\nboth. Universal tiles have no decomposition — they are the axioms.\n\nstdlib/ contains 9 .cell files defining derived kinds from universals:\n  nand.cell       = PROD + Complement\n  multiply.cell   = PROD + Const(1)\n  threshold.cell  = Add + MED + Const\n  smooth.cell     = Add + FEEDBACK\n  latch.cell      = MED + FEEDBACK\n  accumulate.cell = PROD + Add + FEEDBACK\n  mean.cell       = Add + PROD + Const(1/3)\n  sum.cell        = Add (3-input)\n  negate3.cell    = Complement (multi-channel)\n\nCatalog::with_stdlib() loads all decompositions at init.\nget_decomposition() returns the structural truth.\nis_universal() identifies the four axiom tiles + Pass.\n\n141 tests, 0 warnings.","parents":["afc409e49a0ffeb3451a6a545fa97fec3e263d12"],"add":219,"del":0,"cadd":124,"cdel":0,"files":10},{"repo":"cell","hash":"443aaf4ef816b5680bda6126a8cd6b59e36f0131","ts":1774815259,"wall":"2026-03-29T16:14","msg":"fix: three critical bugs — input ordering, CONTROL edges, Const value","body":"Critical #2: collect_inputs now uses target_face for deterministic\ninput ordering (face 3→slot 0, face 4→slot 1, face 5→slot 2).\nPreviously used HashMap iteration order — nondeterministic.\n\nCritical #3: CONTROL edges now modulate cell state instead of feeding\nas normal inputs. collect_control_mods() extracts CONTROL values,\nevaluate loop applies them to cell.state[target] before transform.\n\nCritical #1 (partial): Const cells now set their output value from\nthe `value` param at instantiation. Previously outputted 0.0.\n\nModerate #9: CString::new uses unwrap_or_else to prevent panic on\nNUL bytes in the JNI bridge C ABI.\n\n141 tests, 0 warnings.","parents":["2210ace047ff8e9c5f326555dd2a408c618ae146"],"add":89,"del":22,"cadd":89,"cdel":22,"files":3},{"repo":"cell","hash":"2645ddcc3e97a96edd2aab06b6d1f975abc2dbec","ts":1774816152,"wall":"2026-03-29T16:29","msg":"fix: all stdlib decompositions — correct math, correct adjacency","body":"Every stdlib .cell file rewritten with verified hex adjacency and\ncorrect mathematical equivalence to the native transform:\n\n- nand: Const moved to (1,1) — adjacent to PROD ✓\n- multiply: Const moved to (1,1) — adjacent to PROD ✓\n- threshold: SIGNAL{attenuation:-1} for negation, PROD×1000 gain,\n  MED clamp. Approximates step function to <0.001 error.\n- smooth: two PROD paths (alpha*input, (1-alpha)*feedback) → Add.\n  Correct EMA, not divergent accumulator. Default alpha=0.1.\n- latch: PROD(in,trigger,1) + PROD(feedback,complement(trigger),1)\n  → Add. Continuous blend, exact at trigger ∈ {0,1}.\n- accumulate: PROD(in,trigger,1) → Add with self-FEEDBACK. Fixed\n  Const adjacency.\n- sum: chained two Adds (Add is 2-input). No dropped third input.\n- mean: chained Adds → PROD by 1/3. All three inputs preserved.\n- negate3: unchanged (Complement, trivially correct).\n\n141 tests, 0 warnings.","parents":["443aaf4ef816b5680bda6126a8cd6b59e36f0131"],"add":136,"del":34,"cadd":0,"cdel":0,"files":8},{"repo":"cell","hash":"b387941fd6569a06a5ad139229371eafa4611451","ts":1774817067,"wall":"2026-03-29T16:44","msg":"fix: adjacency leakage in stdlib — relay cells for isolation","body":"Hex cells connect to ALL neighbors, not just intended ones. When\na Const meant for PROD is also adjacent to Add, Add gets corrupted.\nThis is the hex equivalent of a PCB short circuit.\n\nFixed in threshold, smooth, accumulate, latch — relay Pass cells\ncreate distance between functional groups, preventing unintended\nconstant values from leaking into downstream transforms.\n\nDiscovery: decomposing functions into tiles is a LAYOUT problem,\nnot just a logic problem. A future function compiler needs\nconstraint satisfaction to avoid adjacency leakage.\n\n141 tests, 0 warnings.","parents":["2645ddcc3e97a96edd2aab06b6d1f975abc2dbec"],"add":96,"del":72,"cadd":0,"cdel":0,"files":4},{"repo":"operations","hash":"8d7d5344279283805a5fc662bdceacebe471e60e","ts":1774817797,"wall":"2026-03-29T16:56","msg":"research: hex layout leakage — adjacency isolation problem and solution approaches","body":"","parents":["a0d67938116a631bd46d4197e5ec4376a0085371"],"add":112,"del":0,"cadd":112,"cdel":0,"files":1},{"repo":"cell","hash":"0cc4e8e84797f0a423ba9b4d519e1cf743bb1e0a","ts":1774818458,"wall":"2026-03-29T17:07","msg":"plan: Cell master plan — M1 through M6, CLI to hardware","body":"","parents":["b387941fd6569a06a5ad139229371eafa4611451"],"add":102,"del":0,"cadd":102,"cdel":0,"files":1},{"repo":"cell","hash":"25dfb6848dfc89796aa921a3ef943dade80dce41","ts":1774822456,"wall":"2026-03-29T18:14","msg":"feat: CLI — cell eval, cell check, cell fmt","body":"M1 complete. The language runs standalone.\n\n  echo '...' | cell eval         Parse, instantiate, evaluate, print outputs\n  cell check file.cell           Parse and validate\n  cell fmt file.cell             Canonical reformatting\n\nNew transforms: Scale (multiply by factor param), Norm (clamp and\nnormalize to [0,1]), Abs (absolute value). Params applied to state\nat instantiation. 19 transforms total.\n\nTested: pipe input, file input, hex-rhythm.cell with --ticks 5,\nfunction composition, Scale×2 produces correct output (6.28 from 3.14).\n\n141 tests, 0 warnings.","parents":["0cc4e8e84797f0a423ba9b4d519e1cf743bb1e0a"],"add":286,"del":8,"cadd":286,"cdel":8,"files":5},{"repo":"glyph3d","hash":"c22b4566fdcca7034830ba9e350e7069311f4505","ts":1774825191,"wall":"2026-03-29T18:59","msg":"init: Glyph3D — polyhedral builder for glyphic space in 3D","body":"Five face-compatible shapes (truncated octahedron, hex prism, cube,\nsquare prism, truncated tetrahedron) with snap alignment, ground\nplacement, edit mode with transform gizmo, and full color picker.\n\nSingle HTML file, Three.js from CDN, no build step.","parents":[],"add":1256,"del":0,"cadd":1251,"cdel":0,"files":4},{"repo":"glyph3d","hash":"9d1a1bdb4c6daed54bcfd80c46dda7472d0bbe48","ts":1774826654,"wall":"2026-03-29T19:24","msg":"fix: proper convex hull collision detection","body":"Replace crude center-distance overlap check with exact convex\npolyhedron collision using face half-plane tests. Each shape gets\nprecomputed bounding radius and face planes. Collision checks:\n\n- Bounding sphere fast reject\n- Vertex-inside-hull test (both directions)\n- Face center containment (catches edge-through-face cases)\n- 0.08 margin allows face-to-face contact without false positives\n\nBuild mode blocks placement when collision detected. Edit mode\nshows red highlight on overlapping pieces. Push/pull rejects\nmoves that would cause collision.","parents":["c22b4566fdcca7034830ba9e350e7069311f4505"],"add":153,"del":13,"cadd":153,"cdel":13,"files":1},{"repo":"cell","hash":"48db8250b7fc670c1e04da7d62ef45b060d07131","ts":1774827542,"wall":"2026-03-29T19:39","msg":"docs: final session handoff — M1 complete, M2 blocked on network","body":"17 commits this session. 141 tests. CLI works (cell eval/check/fmt).\nDual catalog with stdlib. Bug audit: 3 criticals + adjacency leakage\nfound and fixed. M2 (Android JNI) blocked: cargo-ndk installed but\nrustup Android target and NDK download failed on network.","parents":["25dfb6848dfc89796aa921a3ef943dade80dce41"],"add":30,"del":22,"cadd":30,"cdel":22,"files":1},{"repo":"glyph3d","hash":"f242bfa4ca7ad3d63ddc106ee631462a2db45ae5","ts":1774828251,"wall":"2026-03-29T19:50","msg":"docs: architecture for lattice sculpting + cellular automata","body":"BCC lattice coordinate system, sparse hash storage, InstancedMesh\nrendering, sculpting tools (place/paint/erase/carve/fill), slice\nplane for interior access, CA simulation with 14-neighbor rules.\n\nSynthesized from volumetric-interaction-paradigms research,\nimmediate-feedback-programming principles, and Soma/Cell specs.\n\nFour phases: lattice sculpting → cellular automata → polish → Cell wiring.","parents":["9d1a1bdb4c6daed54bcfd80c46dda7472d0bbe48"],"add":293,"del":0,"cadd":293,"cdel":0,"files":1},{"repo":"operations","hash":"0fdbcd0c472888069c8c6b7420aa57b39a4083a8","ts":1774828873,"wall":"2026-03-29T20:01","msg":"research: hex-native logics + universal tile set + subgraph evaluation","body":"Three research docs from this session's parallel agents:\n\nhex-native-logics.md — 14 logic systems surveyed, all reduce to 8\nfloat operations (min, max, median, complement, weighted sum, product,\nclamp, residuum). The hex is polymorphic across all of them.\n\nuniversal-hex-tile-set.md — 4 tiles (MED, SUM, PROD, Const) generate\nall logic. Proof via McNaughton + Stone-Weierstrass. Depth table for\nevery operation. Became Axiom 9.\n\nsubgraph-evaluation-strategies.md — Runtime survey: Max/MSP, Pure Data,\nLabVIEW, Unreal, Flink, Timely Dataflow, Houdini, Node-RED, Ptolemy II.\nInformed the black-box function decision.","parents":["8d7d5344279283805a5fc662bdceacebe471e60e"],"add":1669,"del":0,"cadd":1669,"cdel":0,"files":3},{"repo":"opsin","hash":"b30d8c467dcb5515b0647d01680abce350fb3816","ts":1775770504,"wall":"2026-04-09T17:35","msg":"baseline: Phase 1 threading + Phase 1.5 SIGSEGV patch + in-flight Phase 2 deletion","body":"State at git init:\n- Phase 0 recon complete (FLIR GL pipeline discovered)\n- Phase 1 threading done (FLIR connect/disconnect on IO, SDK init off main)\n- Phase 1.5 SIGSEGV patch done (mutex + connectEpoch in ThermalCamera)\n- CameraXBinder.kt deleted (in-flight wrong-shape abstraction)\n- CameraX bumped 1.4.1 -> 1.5.1 in app/build.gradle.kts\n- Plan persisted at .claude/plans/opsin-bug-remediation.md\n\nNext: revised Phase 2 (LifecycleCameraController + macro lens + debounce)","parents":[],"add":2919,"del":0,"cadd":2419,"cdel":0,"files":35},{"repo":"opsin","hash":"cc4997a0a0745f4f5f15d44d34badd72b5409f59","ts":1775782044,"wall":"2026-04-09T20:47","msg":"phase 2 (revised): LifecycleCameraController + macro lens with ring light","body":"Replaces the in-flight CameraXBinder approach with the platform-recommended\nLifecycleCameraController. Bind Preview + ImageCapture + VideoCapture once\nat startup; mode toggling becomes pure UI state.\n\nCameraX 1.4.1 -> 1.5.1 (first version supporting concurrent Preview + IC + VC).\ncompileSdk 34 -> 35 (required by camera-view 1.5.1).\n\nNew camera/MicroscopeLens.kt enumerates back cameras via Camera2CameraInfo,\nscores by macro AF support, flash availability, and pixel count, with\ntie-break preferring higher camera IDs. On the Power Armor 19T this\ncorrectly resolves to camera id=3 (the dedicated 5MP microlens with the\nring LED) over the visually-identical id=2 (likely ultrawide).\n\nMode debouncing in CameraViewModel.setMode (150ms coalesce) prevents the\n\"Too many users (-87)\" Camera2 floods caused by rapid mode-button taps.\n\nEntering MICROSCOPE auto-enables torch on the macro lens, which activates\nthe dedicated ring LED rather than the main rear flash. Leaving MICROSCOPE\ndisables it.\n\nResolves bugs H1 (provider race), H8 (video first-tap), and lifts H6\nmicroscope from \"remove fake mode\" to \"real macro lens implementation\".\nPhotoCapture and VideoCapture become stateless thin wrappers over the\ncontroller. CameraPreview becomes a 6-line surface host.\n\nBy Symbiont Systems LLC","parents":["b30d8c467dcb5515b0647d01680abce350fb3816"],"add":311,"del":231,"cadd":310,"cdel":230,"files":8},{"repo":"elemental","hash":"d5fe981ee147f7be545f43dd169fdc94024a113f","ts":1776044044,"wall":"2026-04-12T21:34","msg":"Elemental: initial commit — interactive periodic table","body":"118 elements, 23,739 data points from 17 authoritative sources across\n19 scientific domains. Multi-source disagreements preserved, not averaged.\n\nThree.js 3D visualization with Sphaera Operis aesthetic:\n- 3 layouts: Relationship Graph (force-directed), Property Space (3-axis),\n  Series (Z-ordered line with Y-axis property waveform)\n- Right-click context menu for all settings (layout, lens, glossary)\n- Proportional atomic radius sizing\n- Temperature vibration in series mode\n- Orbital explorer with subshell toggles (hydrogen wave functions)\n- 18 property overlays with inferno color scale\n- Zoom-to-cursor via OrbitControls\n\nCommentary corpus: 96 glossary entries, 36 annotations, 30 citations.\nVoice: Primo Levi register, physicist-precise, no popular-science hype.\n\nData: NIST ASD, PubChem, Shannon 1976, Mendeleev pkg, CRC Handbook,\nUSGS MCS, Kobayashi 2020, Arlandini 1999, B²FH 1957, Lodders 2003,\nWHO/FAO, GERM, periodictable pkg, NIST WebBook, NNDC ENSDF/Wallet.\n\nLive at elemental.symbiont.systems\n\nAuthored by Rowan Valle","parents":[],"add":180020,"del":0,"cadd":19549,"cdel":0,"files":366},{"repo":"elemental","hash":"e42f4f62e1bcd82a58aac72039464b9bd1af2434","ts":1776061010,"wall":"2026-04-13T02:16","msg":"docs: architecture guide — maps codebase for extension and domain adaptation","body":"Documents every module, its purpose, and whether it transfers to other\ndomains. Identifies the 60/40 split: 60% reusable infrastructure,\n40% chemistry-specific rendering. Includes the layout module contract,\nboot sequence, data loading pattern, and commentary system.","parents":["d5fe981ee147f7be545f43dd169fdc94024a113f"],"add":307,"del":0,"cadd":307,"cdel":0,"files":1},{"repo":"forms","hash":"0bc2166700ebaeef3e6604821b0fb3be34cb86bd","ts":1776100843,"wall":"2026-04-13T13:20","msg":"forms: math engine — 10 modules, 209 tests, exact arithmetic","body":"Rust workspace (math-core + math-wasm) for the Forms interactive\nmathematics app. Four-handle architecture: notation, expression tree,\nnumber line, geometry — all input devices on a single expression.\n\nmath-core: lexer, Pratt parser, AST (Term/Proposition), step-by-step\nevaluator with number line and geometry actions, 5-phase algebraic\nsimplifier, linear/quadratic solver, geometric pattern interpreter,\ninfix + LaTeX formatter. Exact rational arithmetic throughout — no\nfloating point until the rendering boundary.\n\nmath-wasm: stateless WASM API via wasm-bindgen + serde-wasm-bindgen.\nParse, evaluate, simplify, solve, geometry interpret, format — all\nexported as functions returning JSON. Errors as data, not exceptions.","parents":[],"add":6533,"del":0,"cadd":6009,"cdel":0,"files":17},{"repo":"forms","hash":"27cc5c421dee086736923f17ed3351526fb28417","ts":1776121841,"wall":"2026-04-13T19:10","msg":"forms: unified 3D scene, multi-rail solver foundations","body":"JS rendering layer: single Three.js scene with notation glyphs,\nnumber line, and result display. White void, fixed camera, no orbit.\nContext menu for glyph size. Step trace with hover expansion.\n\nRust additions for multi-rail constraint system:\n- eval_numeric: pure f64 evaluation with variable bindings\n- find_variables: extract variable names from expression AST\n- solve_numeric: Newton-Raphson solver for constraint propagation\n- WASM exports: find_variables, eval_numeric, solve_for_value\n\n220 tests passing in math-core.","parents":["0bc2166700ebaeef3e6604821b0fb3be34cb86bd"],"add":4609,"del":0,"cadd":4609,"cdel":0,"files":12},{"repo":"forms","hash":"b52967adb5d45d9e8d9c2924845fc16e40975e70","ts":1776129899,"wall":"2026-04-13T21:24","msg":"forms: calculator mode — 7 features, clean scene","body":"Stripped to clean white void. Notation + result as one inline line.\n- Enter commits to scrollable history (grayed, clipped at current line)\n- Escape clears input\n- Blinking cursor between characters\n- Parentheses colored by nesting depth (blue/purple/orange/green/red)\n- Parse errors turn affected characters red\n- History stacks above, scrollable, auto-hides past current line\n- Result inline in rust color after expression\n\nScene cleaned: removed tree view, geometry view, number line,\norbit controls, grid, ground plane. Rebuild from here.","parents":["27cc5c421dee086736923f17ed3351526fb28417"],"add":280,"del":763,"cadd":280,"cdel":763,"files":2},{"repo":"forms","hash":"458c8e1d0a324b5793e77119b5f608d2a836ff27","ts":1776132463,"wall":"2026-04-13T22:07","msg":"forms: full audit fixes — 17 issues resolved","body":"Critical: term_to_f64 now uses eval_numeric for full expression tree\nevaluation. sin(pi/2) → 1, cos(2*pi) → 1, log(e^3) → 3 all work.\n\nHigh: try_reduce_div and try_reduce_pow handle mixed Num/Const.\nSolver handles symbolic constants (pi, e) via rational approximation.\n\nMedium: LaTeX abs(x) → \\left|x\\right| (was broken). Added 11 missing\nfunction evaluations: log, log2, log10, sinh, cosh, tanh, asinh,\nacosh, atanh, cbrt, min, max, gcd, lcm, nCr, nPr. Added inverse\nhyperbolic functions to lexer.\n\nUI: Help panel with full function reference (?). History via Up/Down\narrows (terminal-style). ans keyword for previous result. Scientific\nnotation for large numbers. Dead code removed.\n\n220 tests passing.","parents":["b52967adb5d45d9e8d9c2924845fc16e40975e70"],"add":643,"del":128,"cadd":643,"cdel":128,"files":8},{"repo":"forms","hash":"04600be6589d315e81bcfa12ab0b99ba3fa9ff1f","ts":1776133965,"wall":"2026-04-13T22:32","msg":"forms: boolean logic with truth table glyphs","body":"Classical boolean logic: and, or, not, xor, implies, iff.\ntrue/false literals. Fuzzy-ready operators (min/max arithmetic).\n\nTruth table generator: auto-detects boolean expressions (variables\nwith only logical operators), generates all 2^n rows (max 4 vars),\nclassifies as tautology/contradiction/contingent.\n\nTruth table renders as 3D glyph grid below the expression:\nT in green, F in red, header row in gray, classification below.\n\nParser: NOT handled as prefix operator. XOR as infix token.\nimplies/iff keywords added to lexer. Formatter displays logical\nops with Unicode symbols (∧ ∨ ¬ ⊕ → ↔).\n\nHelp panel updated with Logic section.\n\n232 tests passing.","parents":["458c8e1d0a324b5793e77119b5f608d2a836ff27"],"add":472,"del":14,"cadd":472,"cdel":14,"files":10},{"repo":"forms","hash":"eec5cb3017e3e186a2835d53cc600ef524ddb189","ts":1776166325,"wall":"2026-04-14T07:32","msg":"forms: keyboard, logic fixes, cursor, roadmap","body":"On-screen keyboard: color-coded buttons (numbers, operators, functions,\nconstants, logic), toggles with bottom-right button or K key, inserts\nat cursor position.\n\nLogic operator fixes: dual-mode evaluation — fuzzy (min/max) for\nboolean/[0,1] inputs, bitwise (&, |, ^, !) for integers.\n23 xor 3 = 20, 12 and 10 = 8. implies/iff reject non-boolean integers.\n\nBug fixes: lcm(0, x) = 0 (was failing). nCr/nPr removed k<=20\nrestriction (checked_mul handles overflow). formatTerm displays\nlogical operators with Unicode symbols.\n\nCursor: persistent sprite, repositioned not recreated. Glyph texture\ncache — same character+color shares GPU texture.\n\nROADMAP.md: complete tier system (0-4) covering arithmetic through\nhomotopy type theory. Rendering, interaction, and architecture roadmaps.\n\n232 tests passing.","parents":["04600be6589d315e81bcfa12ab0b99ba3fa9ff1f"],"add":563,"del":269,"cadd":563,"cdel":269,"files":6},{"repo":"forms","hash":"a121e8c1682a53b6ed495588254648b123a72788","ts":1776188670,"wall":"2026-04-14T13:44","msg":"forms: Term::Real, Troika text, retro fonts, font selector","body":"AST: added Term::Real(f64) for transcendental results. sin(1) now\nreturns Real(0.8414709848) instead of failing to rationalize.\nEvery match arm across eval, simplify, solve, format, geometry\nupdated. f64_to_term() helper: tries rational first, falls back\nto Real.\n\nRendering: Troika-three-text via esm.sh for SDF text rendering.\nShadow-casting text on a shadow-receiving ground plane. Font\nselector in context menu.\n\nFonts: 9 retro display fonts downloaded — VT323 (terminal),\nSpecial Elite (typewriter), Syne Mono (teletype), IBM Plex Mono\n(mainframe), Press Start 2P (arcade), Share Tech Mono (vector),\nCourier Prime, DSEG7 (calculator LED).\n\n232 tests passing.","parents":["eec5cb3017e3e186a2835d53cc600ef524ddb189"],"add":303,"del":196,"cadd":303,"cdel":196,"files":20},{"repo":"forms","hash":"3a66e0c3897c8864f519c16ae0171efd99715ecf","ts":1776189251,"wall":"2026-04-14T13:54","msg":"forms: Tier 0 complete — 20+ new functions","body":"Number theory: isprime(), nextprime(), factor(), totient(),\npowmod(base, exp, mod), fib(n), digitsum(), digitcount()\n\nBase conversion: bin(), hex(), oct() — shown in step description\n\nPhysical constants: c_light, Na, kB, hbar, G_grav (as zero-arg fns)\n\nRandom: rand(), randint(lo, hi)\n\nAll evaluate through both try_reduce_apply (step-by-step) and\neval_numeric (fast path). Helper functions: is_prime, next_prime,\neuler_totient, fibonacci, pow_mod, prime_factors, digit_sum,\ndigit_count, rand_f64.\n\n232 tests passing.","parents":["a121e8c1682a53b6ed495588254648b123a72788"],"add":263,"del":3,"cadd":263,"cdel":3,"files":2},{"repo":"forms","hash":"61984196c670b026727062e62b10a5116642987c","ts":1776189894,"wall":"2026-04-14T14:04","msg":"fix: Na and physical constants parsed as decimal literals, not functions","body":"","parents":["3a66e0c3897c8864f519c16ae0171efd99715ecf"],"add":6,"del":2,"cadd":6,"cdel":2,"files":1},{"repo":"forms","hash":"c8d8239f6a73c45cafdbecfa2d4e5fb12d2ac839","ts":1776190772,"wall":"2026-04-14T14:19","msg":"fix: cache-busting for WASM, cleanup Na test","body":"","parents":["61984196c670b026727062e62b10a5116642987c"],"add":2,"del":1,"cadd":2,"cdel":1,"files":2},{"repo":"forms","hash":"40fa27408569531501839c8eb5a556b73e049074","ts":1776198392,"wall":"2026-04-14T16:26","msg":"refactor: extract math_fns module, add MathErrorKind","body":"Phase A of engine overhaul. No behavior change — pure refactoring.\n\nmath_fns.rs: extracted 15 pure math functions from eval.rs into\nshared module. is_prime, next_prime, euler_totient, fibonacci,\npow_mod, prime_factors, digit_sum, digit_count, combinations,\npermutations, rand_f64, logic_binary, f64_to_rational. Both\nevaluator paths now call the same functions. 11 new unit tests.\n\nMathErrorKind: structured error types for Term::Undefined (Phase B).\nEach kind has brief(), explanation(), and glossary_id(). English\nexplanations ready for the glossary system. DivisionByZero, Overflow,\nDomainError, UndefinedVariable, InvalidFactorial, ConvergenceFailure.\n\neval.rs: sum/prod moved before f64 conversion (structural fix).\nFibonacci bug fixed (checked_add overflow on last iteration).\n\n243 tests passing.","parents":["c8d8239f6a73c45cafdbecfa2d4e5fb12d2ac839"],"add":444,"del":199,"cadd":444,"cdel":199,"files":5},{"repo":"forms","hash":"d94db8d8cc8a30b7dd5994424bb3c62b09b57b71","ts":1776203935,"wall":"2026-04-14T17:58","msg":"ast: 5 new Term variants + MathConst::I — engine architecture overhaul","body":"Phase B of the overhaul. AST expanded from 12 to 17 Term variants:\n\nTerm::Iterated { kind, var, body, lower, upper }\n  - IteratedKind: Sum, Product, Integral\n  - Holds body expression — variable binding with proper scoping\n  - Step evaluator: expands small ranges (≤20) to visible Add/Mul,\n    evaluates large ranges directly\n  - substitute() helper with nested binding shadowing\n\nTerm::Derivative { body, var, order }\n  - Placeholder for symbolic differentiation (not evaluated yet)\n\nTerm::Limit { body, var, point, direction }\n  - LimitDir: Left, Right, Both\n  - Placeholder for limit evaluation (not evaluated yet)\n\nTerm::List(Vec<Term>)\n  - Ordered collection. Matrices as nested lists.\n\nTerm::Undefined(MathErrorKind)\n  - Error values that propagate through computation\n  - 1/0 → Undefined(DivisionByZero)\n\nMathConst::I — imaginary unit (algebraic handling, not evaluated to f64)\n\nEvery match arm across 6 files updated:\n- eval.rs: reduce_one, collect_vars, eval_numeric, try_reduce_iterated\n- format.rs: write_term (Σ/Π/∫, d/dx, lim, [...], undefined),\n  write_term_latex (proper LaTeX for all)\n- simplify.rs: recurse_new_variants helper for all 5 phases\n- geometry.rs: replaced duplicate eval function with eval_numeric\n- solve.rs: contains_var updated\n\n243 tests passing.","parents":["40fa27408569531501839c8eb5a556b73e049074"],"add":428,"del":85,"cadd":428,"cdel":85,"files":6},{"repo":"forms","hash":"65e5b7c51827ab72b7b8d0d16b3a3218dd1626a8","ts":1776205583,"wall":"2026-04-14T18:26","msg":"phase C: sum/prod evaluation, list parsing, undefined propagation","body":"C1: Parser converts sum(body, var, lo, hi) to Term::Iterated.\nStep evaluator expands small ranges to visible Add/Mul terms.\nsubstitute() handles nested binding shadowing.\nTests: sum(i,i,1,10)=55, sum(i^2,i,1,10)=385, prod(i,i,1,5)=120.\n\nC2: Division by zero produces Term::Undefined(DivisionByZero)\ninstead of silent None. Undefined propagates through Add and Mul.\nError messages with English explanations.\n\nC4: Parser supports [1, 2, 3] list syntax via LBracket/RBracket\ntokens. Empty lists [] supported.\n\nJS: formatTerm handles List, Undefined, Iterated, Derivative, Limit.\nWASM cache buster bumped.\n\n249 tests passing.","parents":["d94db8d8cc8a30b7dd5994424bb3c62b09b57b71"],"add":134,"del":4,"cadd":134,"cdel":4,"files":4},{"repo":"forms","hash":"15fc34ba2687eeb897289206b6436c5a7d04a653","ts":1776209275,"wall":"2026-04-14T19:27","msg":"C3: complex imaginary unit — im keyword, i^n simplification","body":"Lexer: Token::Imaginary, keyword \"im\" maps to it.\nParser: Token::Imaginary → Term::Const(MathConst::I).\nImplicit multiplication works: 3im → Mul([3, i]).\n\nSimplifier rules in reduce phase:\n- i^n cycles with period 4: i^0=1, i^1=i, i^2=-1, i^3=-i\n- Mul collects i factors: i*i → -1, 3i*4i → -12\n- Handles arbitrary i counts: i^8 = 1, i^5 = i\n\n\"im\" chosen over \"i\" to avoid conflict with iteration variable\n(sum(i, i, 1, 10) would break if i were a constant).\n\n5 new tests. 254 total passing.","parents":["65e5b7c51827ab72b7b8d0d16b3a3218dd1626a8"],"add":78,"del":0,"cadd":78,"cdel":0,"files":3},{"repo":"forms","hash":"1cbec1342cbf1029952628a9825bf9c2bbea300b","ts":1776210627,"wall":"2026-04-14T19:50","msg":"rewrite: single Troika Text per line, cursor from caretPositions","body":"Replaced per-character Text objects with one Text per expression line.\nTroika's colorRanges handles per-character coloring (paren depth,\nerrors, result). Cursor reads caretPositions from textRenderInfo\nfor pixel-perfect placement.\n\n- buildNotationLine: builds one Text with full string + colorRanges\n- showCursor: reads caretPositions[charIndex*4] for exact X, caret\n  height from caretPositions Y bounds. Falls back to approximate\n  positioning before Troika sync completes.\n- Sync callback triggers deferred cursor update after typesetting\n- invalidateNotation() forces rebuild on font/scale change\n- CHAR_WIDTH constant deleted — Troika handles variable-width fonts\n- Truth table still uses per-cell Text objects (different layout)\n\n254 tests passing (Rust unchanged).","parents":["15fc34ba2687eeb897289206b6436c5a7d04a653"],"add":179,"del":98,"cadd":179,"cdel":98,"files":2},{"repo":"forms","hash":"7430195bf96e01dbae8a587cf3501c609587149e","ts":1776211850,"wall":"2026-04-14T20:10","msg":"tier 1 complete: list ops, statistics, extgcd, range","body":"List operations: sort, reverse, len, head, tail — operate on\nTerm::List, return List or Num. Pattern: detect List arg in\ntry_reduce_apply before numeric function dispatch.\n\nStatistics: mean, median, stdev, variance — on numeric lists.\nSample standard deviation (n-1 denominator).\n\nrange(start, end) — generates Term::List of integers.\nextgcd(a, b) — returns [gcd, x, y] where a*x + b*y = gcd.\n\n11 new tests. 265 total passing.","parents":["1cbec1342cbf1029952628a9825bf9c2bbea300b"],"add":233,"del":0,"cadd":233,"cdel":0,"files":3},{"repo":"forms","hash":"e8eed2d4e9c1f4e6faed590e67ee2a37c690f695","ts":1776212613,"wall":"2026-04-14T20:23","msg":"fix: PCFSoftShadowMap deprecation warning","body":"","parents":["7430195bf96e01dbae8a587cf3501c609587149e"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"forms","hash":"a0082f3ed1a17a9dc20de314c4d0a04c8b054d26","ts":1776212874,"wall":"2026-04-14T20:27","msg":"handoff: session state for 2026-04-13/14","body":"","parents":["e8eed2d4e9c1f4e6faed590e67ee2a37c690f695"],"add":88,"del":0,"cadd":88,"cdel":0,"files":1},{"repo":"forms","hash":"302a9070b64e6cd172871f11416283d508eaaf26","ts":1776352342,"wall":"2026-04-16T11:12","msg":"forms: 8 rendering engines, separation of concerns, symbolic differentiation","body":"Rendering engines (all new):\n  - Implicit surfaces via marching cubes (3 free variables)\n  - Parametric surfaces: param(x,y,z, u,umin,umax, v,vmin,vmax)\n  - 4D projection: proj4d(...) with perspective division + w-depth coloring\n  - Named polytopes: tesseract, cell24 (discrete 4D wireframes)\n  - Fractals: mandelbrot, julia(cx,cy), juliamorph, mandelzoom, burningship\n    WebGL shader rendering, animated color cycling, morphing, auto-zoom\n  - ODE integration: ode(dx,dy,dz, x0,y0,z0, t_final,dt) via RK4 in Rust\n    7 animation modes (trail, particle, multi, phase, density, poincare)\n  - L-systems: koch(n), fern(angle,depth), 12 parameterized presets\n  - Height fields and 2D curves (existing, enhanced)\n\nArchitecture:\n  - Mode registry with priority-based detection from AST\n  - Foundation: sample_multi, sample_volume, generic mesh format\n  - Separated concerns: 3 god files split into 30 focused modules\n    app.js (685→357), plot-renderer.js (1139→5 files), plot-modes.js (761→11 files)\n  - Config constants centralized, shared utilities extracted\n  - Persistent in-scene plots replace floating windows\n  - Direct manipulation: drag=rotate, shift+drag=move, touch support\n\nMath engine:\n  - Symbolic differentiation (Phase 1 of Tier 2 CAS)\n    diff(x^3, x) → 3x^2, chain/product/quotient rules, trig/exp/log\n  - Dead code eliminated (~1500 lines removed)\n  - HashMap allocation fix in WASM samplers\n  - Variable name collision fix (command functions require parens)\n  - 256 Rust tests (241 existing + 15 new differentiation)\n\nUI:\n  - Library panel with 60+ presets, saved expressions, user manual\n  - Informative error handling with structured WASM errors\n  - Troika vendored locally (no CDN dependency)\n  - 82 JS tests (term formatting, L-systems, marching cubes, history)\n  - Context menu consolidated, error display CSP-safe\n\nAuthored by Rowan Valle","parents":["a0082f3ed1a17a9dc20de314c4d0a04c8b054d26"],"add":12400,"del":2532,"cadd":12400,"cdel":2532,"files":52},{"repo":"forms","hash":"f1656d9cbda14cc95630872f752d03f1e3e8c76c","ts":1776352539,"wall":"2026-04-16T11:15","msg":"handoff: session state for 2026-04-14/16","body":"","parents":["302a9070b64e6cd172871f11416283d508eaaf26"],"add":174,"del":65,"cadd":174,"cdel":65,"files":1},{"repo":"forms","hash":"df2c22b1ab75119a70537be14426c3a771159e47","ts":1776357011,"wall":"2026-04-16T12:30","msg":"meta: favicon, Open Graph tags, page title","body":"","parents":["f1656d9cbda14cc95630872f752d03f1e3e8c76c"],"add":5,"del":1,"cadd":5,"cdel":1,"files":2},{"repo":"forms","hash":"ea4bc8ab01a2b3673d1b2367f6a92e7604a5be02","ts":1776360331,"wall":"2026-04-16T13:25","msg":"arch: 3D world + Troika HUD — free camera, dual scene rendering","body":"- scene.js: dual-camera architecture (PerspectiveCamera for 3D world,\n  OrthographicCamera for screen-fixed HUD text)\n- Notation, cursor, truth table render in HUD layer — never move with camera\n- OrbitControls on world camera: scroll=dolly, drag on empty=orbit,\n  right-drag=pan. Camera moves freely through 3D space.\n- Object manipulation: drag on object=rotate, shift+drag=move.\n  OrbitControls disabled during object drag.\n- Touch: one-finger on object=rotate, two-finger on object=move,\n  one-finger on empty=orbit, pinch=dolly\n- Ground plane enlarged for 3D world navigation\n- renderer.autoClear=false, manual clear + dual render per frame\n\nAuthored by Rowan Valle","parents":["df2c22b1ab75119a70537be14426c3a771159e47"],"add":152,"del":171,"cadd":152,"cdel":171,"files":3},{"repo":"forms","hash":"50c2c0f5621a34cb7a16d50ee9c65fc4fbb9b605","ts":1776363102,"wall":"2026-04-16T14:11","msg":"fix: fixed camera with per-object turntables, remove OrbitControls","body":"Camera stays at (0,0,20). No orbiting. Each object rotates independently\non drag. Scroll = dolly camera z. Drag on empty = pan camera x/y.\nShift+drag on object = reposition. Touch: pinch=dolly, two-finger=move.\n\nAuthored by Rowan Valle","parents":["ea4bc8ab01a2b3673d1b2367f6a92e7604a5be02"],"add":80,"del":76,"cadd":80,"cdel":76,"files":2},{"repo":"forms","hash":"a8ca19697c3f2a4637847295400fd8f120329bee","ts":1776371520,"wall":"2026-04-16T16:32","msg":"fix: labels in HUD layer — track world objects via projection","body":"Labels are Troika Text in hudScene, not children of rotating groups.\nEach frame, label projects its object's world position to screen coords\nand positions itself above. Labels never rotate, never occlude, always\nreadable. Removed from world scene on object removal.\n\nUpdated manual: pan/zoom/rotate controls documented accurately.\n\nAuthored by Rowan Valle","parents":["50c2c0f5621a34cb7a16d50ee9c65fc4fbb9b605"],"add":21,"del":9,"cadd":21,"cdel":9,"files":3},{"repo":"forms","hash":"8b964720ec65c601d0aa3b057aec4e4448b24d26","ts":1776374386,"wall":"2026-04-16T17:19","msg":"fix: HUD labels visible — clearDepth between passes, per-frame label tracking","body":"Two bugs fixed:\n1. Depth buffer from 3D world was occluding HUD text. Added\n   renderer.clearDepth() between world and HUD render passes.\n2. onBeforeRender on Troika Text unreliable (async geometry).\n   Moved label position updates to scene's per-frame callback.\n\nAuthored by Rowan Valle","parents":["a8ca19697c3f2a4637847295400fd8f120329bee"],"add":22,"del":12,"cadd":22,"cdel":12,"files":3},{"repo":"forms","hash":"27113a2187c37a6a1faac78c4e48cea7c39f7c05","ts":1776374641,"wall":"2026-04-16T17:24","msg":"tweak: raise pinned label offset","body":"","parents":["8b964720ec65c601d0aa3b057aec4e4448b24d26"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"forms","hash":"a0198790c9db3456eaf81111b7ca6562c907db72","ts":1776376275,"wall":"2026-04-16T17:51","msg":"feat: Taylor series — taylor(f, x, a, n) expands any function as polynomial","body":"taylor(sin(x), x, 0, 5) → x - 0.167x³ + 0.0083x⁵\ntaylor(exp(x), x, 0, 4) → 1 + x + 0.5x² + 0.167x³ + 0.0417x⁴\ntaylor(1/(1-x), x, 0, 4) → 1 + x + x² + x³ + x⁴\n\nCalls differentiate() k times, substitutes x=a, divides by k!,\nbuilds polynomial term by term. 261 tests passing.\n\nAuthored by Rowan Valle","parents":["27113a2187c37a6a1faac78c4e48cea7c39f7c05"],"add":140,"del":1,"cadd":140,"cdel":1,"files":2},{"repo":"forms","hash":"1df7ed150e89b463a4cc142941b08c819dbeff96","ts":1776376506,"wall":"2026-04-16T17:55","msg":"handoff: session state 2026-04-16 — dual scene, taylor, deployment","body":"","parents":["a0198790c9db3456eaf81111b7ca6562c907db72"],"add":80,"del":160,"cadd":80,"cdel":160,"files":1},{"repo":"forms","hash":"781e69613b029b9daf7f047a69897f7ab4ec0a1a","ts":1776449520,"wall":"2026-04-17T14:12","msg":"feat: step trace — Troika current step + HTML expandable trace","body":"Current reduction step rendered in Troika HUD (matches selected font).\nHover bottom of screen expands full trace as HTML overlay — scrollable,\nselectable, copyable. Decimal approximation shown for irreducible\nfractions (≈ value). Font selection propagates to trace via CSS variable.\nRemoved old HTML step bar container chrome.","parents":["1df7ed150e89b463a4cc142941b08c819dbeff96"],"add":156,"del":64,"cadd":156,"cdel":64,"files":6},{"repo":"forms","hash":"a30f3058410b5054a0747f0bae5ff1ab923ff3f4","ts":1776456777,"wall":"2026-04-17T16:12","msg":"feat: complex arithmetic + limits + Rust-side formatting","body":"Complex arithmetic (Tier 2.9):\n- as_real_imag decomposition, conjugate, contains_i utilities\n- sqrt(-n) → sqrt(n)*i branch cut\n- i^n for all integers (negative exponents)\n- Complex division via as_real_imag\n- Euler's formula: exp(ix) → cos(x) + i·sin(x)\n- re(), imag(), conj() functions\n- Complex-aware abs() (modulus)\n- 24 new complex tests\n\nLimits (Tier 2.5):\n- lim(expr, var, point) syntax — lexer, parser, evaluator\n- Direct substitution for defined limits\n- L'Hôpital's rule for 0/0 indeterminate forms (up to 5 iterations)\n- 7 limit tests including sin(x)/x, (x²-1)/(x-1), (eˣ-1)/x\n\nFormatting:\n- Result display now uses Rust term_to_notation via WASM\n- Eliminates JS formatTerm for display (was crude, no implicit mul)\n- WASM evaluate returns notation string alongside Term\n- Complex expressions auto-expand (simplify_expanded when i present)\n\n292 tests passing.","parents":["781e69613b029b9daf7f047a69897f7ab4ec0a1a"],"add":701,"del":16,"cadd":701,"cdel":16,"files":6},{"repo":"forms","hash":"ba755df77edf03f5e9f643fe1117d5687c4f296e","ts":1776457917,"wall":"2026-04-17T16:31","msg":"feat: matrices — det, inv, transpose, trace, rank (Bareiss exact)","body":"Matrix operations via nested List syntax [[1,2],[3,4]]:\n- transpose() — swap rows/cols, any dimensions\n- trace() — diagonal sum, square matrices\n- det() — Bareiss algorithm, O(n³), exact rational arithmetic\n- inv() — Gaussian elimination on [A|I], exact rationals\n- rank() — row echelon form, count nonzero rows\n- 16 matrix tests (2x2, 3x3, singular, identity, non-square)\n\nAlso: result display now uses Rust formatter via WASM notation field,\neliminating the crude JS formatTerm for display. Complex expressions\nauto-expand when i is present.\n\n308 tests passing.","parents":["a30f3058410b5054a0747f0bae5ff1ab923ff3f4"],"add":334,"del":0,"cadd":334,"cdel":0,"files":2},{"repo":"forms","hash":"1a493d6d536c6b753ffbb5b5f9587eef290707df","ts":1776458702,"wall":"2026-04-17T16:45","msg":"feat: systems of linear equations — solve(expr1, expr2, ...)","body":"Gaussian elimination with exact rational arithmetic. Auto-detects\nvariables, builds augmented coefficient matrix, back-substitutes.\nHandles 2x2, 3x3, fractional results, inconsistent systems.\nSyntax: solve(2x + y - 5, x - y - 1) → [[x, 2], [y, 1]]\n\n312 tests passing.","parents":["ba755df77edf03f5e9f643fe1117d5687c4f296e"],"add":266,"del":0,"cadd":266,"cdel":0,"files":2},{"repo":"forms","hash":"46e8761b82a34f2b3c40e0ae7deef8ac16e4eec1","ts":1776463604,"wall":"2026-04-17T18:06","msg":"feat: Tier 2 complete — polynomial factoring, partial fractions, display fixes","body":"Polynomial factoring (2.2):\n- factor(expr) — rational root theorem + synthetic division\n- Handles quadratic, cubic, zero roots, leading coefficients\n- 5 tests with numerical verification\n\nPartial fraction decomposition (2.3):\n- partial(P(x)/Q(x), x) — factors denominator, Heaviside cover-up\n- Distinct linear factors over Q\n- 4 tests including cubic denominators\n\nDisplay fixes:\n- Negative numbers in Add sort after variables: x - 2 not -2 + x\n- Negative Num in Add formatted as subtraction: a - 2 not a + (-2)\n- Computational commands (factor, det, solve, etc.) suppress plot\n- 321 tests passing, zero regressions\n\nTier 2 CAS complete: differentiation, Taylor series, complex arithmetic,\nlimits, matrices, systems of equations, polynomial factoring, partial\nfractions.","parents":["1a493d6d536c6b753ffbb5b5f9587eef290707df"],"add":579,"del":2,"cadd":579,"cdel":2,"files":5},{"repo":"forms","hash":"f6b14de51e67c74376d34979c70d8951e20fdfa3","ts":1776465100,"wall":"2026-04-17T18:31","msg":"refactor: keyboard toggle to Troika HUD, suppress plots for commands","body":"Keyboard toggle icon rendered as Troika text in HUD scene instead\nof HTML overlay. Click detection via screen coordinates (bottom-right\n60x60px region). Removed #kb-toggle HTML element and CSS.\n\nAlso added partial fractions to command function suppress list so\nplot doesn't trigger for computational results.","parents":["46e8761b82a34f2b3c40e0ae7deef8ac16e4eec1"],"add":26,"del":31,"cadd":26,"cdel":31,"files":5},{"repo":"forms","hash":"8dd01b8a0103fe0eff919324af1f8b385a10f74c","ts":1776468231,"wall":"2026-04-17T19:23","msg":"feat: command palette autocomplete + unified visual style","body":"Autocomplete:\n- Function catalog in Rust (catalog.rs) — 50+ entries with signatures\n  and descriptions, exposed via WASM list_functions()\n- Inline autocomplete as you type — prefix matching, arrow key nav,\n  Tab to accept, inserts function name with opening paren\n- No container chrome — floating text matching instrument aesthetic\n\nVisual unification:\n- Context menu stripped to bare text, trace font, no box\n- Error bar stripped to bare text, no background/border\n- Library panel stripped to bare text, proper name/expression separation\n- Keyboard toggle icon in Troika HUD\n- All UI overlays now share the same chromeless floating-text style\n\n321 tests passing. Deployed to forms.symbiont.systems.","parents":["f6b14de51e67c74376d34979c70d8951e20fdfa3"],"add":461,"del":89,"cadd":461,"cdel":89,"files":7},{"repo":"forms","hash":"a7d6661e6d20fcc89a5f904d3f42598e2d8f7a0d","ts":1776476650,"wall":"2026-04-17T21:44","msg":"feat: eigenvalues + curve fitting (Tier 3.2, 3.7)","body":"Eigenvalues/eigenvectors (3.2):\n- Matrix multiplication, identity, scalar multiply, matrix add\n- Faddeev-LeVerrier characteristic polynomial (exact rational)\n- Eigenvalues: rational, irrational (symbolic sqrt), complex (a±bi)\n- Eigenvectors: symbolic Gaussian elimination on (A-λI), null space\n- eigen(matrix) → list of eigenvalues\n- eigenvec(matrix) → list of [eigenvalue, eigenvector] pairs\n- 8 tests: identity, distinct, diagonal, repeated, complex, irrational\n\nCurve fitting (3.7):\n- fit(data, linear) — linear least squares\n- fit(data, poly(n)) — polynomial least squares, degree n\n- Exact rational via normal equations (AᵀA)⁻¹Aᵀb\n- Returns [expression, R², coefficients]\n- 4 tests: perfect linear, perfect quadratic, overdetermined, interpolation\n\n333 tests passing.","parents":["8dd01b8a0103fe0eff919324af1f8b385a10f74c"],"add":739,"del":2,"cadd":739,"cdel":2,"files":4},{"repo":"forms","hash":"eca809a9db6d980b2cfd83c7ebf4d5c06eb16eda","ts":1776477788,"wall":"2026-04-17T22:03","msg":"feat: probability distributions (Tier 3.6) — 6 distributions, 16 functions","body":"Foundation functions:\n- lgamma (Lanczos approximation, 15-digit accuracy)\n- erf/erfc (continued fraction, 60-term convergence)\n- Regularized incomplete gamma (series + CF, for chi-squared)\n- Regularized incomplete beta (CF, for Student's t)\n- Standard normal inverse (Acklam + Newton refinement)\n\nDistributions:\n- Normal: normpdf, normcdf, norminv (3-arg and 1-arg standard)\n- Student's t: tpdf, tcdf, tinv (Newton-Raphson quantile)\n- Chi-squared: chi2pdf, chi2cdf, chi2inv (Wilson-Hilferty initial guess)\n- Binomial: binompdf, binomcdf (exact combinatorial)\n- Poisson: poisspdf, poisscdf (log-space computation)\n- Uniform: unifpdf, unifcdf, unifinv\n\nNew module: prob.rs (separate from eval.rs).\n21 probability tests. 354 total tests passing.","parents":["a7d6661e6d20fcc89a5f904d3f42598e2d8f7a0d"],"add":681,"del":1,"cadd":681,"cdel":1,"files":6},{"repo":"forms","hash":"dfca69a2b2eced5c1dc17198eee7d2b17f192a15","ts":1776485050,"wall":"2026-04-18T00:04","msg":"feat: URL scene sharing — share workspace via link","body":"Serialize pinned plots + camera to URL hash (base64url JSON).\nRight-click → Share Scene copies the URL to clipboard.\nOpening a share URL replays each expression through the standard\ncommit path — same code as typing and pressing Enter, then positions\nthe plots at their stored locations.\n\nNo special replay functions. No modified commit logic. The shared\nscene behaves identically to a manually built one — labels track,\nright-click removes, drag rotates/moves.","parents":["eca809a9db6d980b2cfd83c7ebf4d5c06eb16eda"],"add":105,"del":1,"cadd":105,"cdel":1,"files":4},{"repo":"forms","hash":"211e6cbb896b72997b1622ba89f0fed3eecd56d4","ts":1776486424,"wall":"2026-04-18T00:27","msg":"feat: symbolic integration (Tier 3.1) — the mountain","body":"Five integration methods in dispatch order:\n1. Linearity — constants out, split sums\n2. Table lookup — 15+ known antiderivatives (power, trig, exp, log,\n   inverse trig, hyperbolic, arctan/arcsin forms)\n3. U-substitution — factor matching against g'(x), verified numerically\n4. Integration by parts — LIATE rule for u selection\n5. Partial fractions — rational functions via existing decomposition\n\nBoth indefinite and definite:\n- integrate(expr, var) → antiderivative\n- integrate(expr, var, a, b) → F(b) - F(a)\n\nVerification via differentiation: every test differentiates the result\nand compares numerically to the original integrand.\n\n12 integration tests. 366 total tests passing.","parents":["dfca69a2b2eced5c1dc17198eee7d2b17f192a15"],"add":701,"del":3,"cadd":701,"cdel":3,"files":6},{"repo":"forms","hash":"a8e04e9eebb13151f2e9c4cec58de8e758a820d5","ts":1776487632,"wall":"2026-04-18T00:47","msg":"fix: simplifier — cancel Mul/Div numeric factors, sort Neg after positives","body":"Two simplification improvements:\n\n1. Mul/Div cancellation: c * (expr / d) → (c/d) * expr when both c and d\n   are rational. Fixes integrate(3x^2, x) displaying as \"3 * x^3 / 3\"\n   instead of \"x^3\". General rule, improves all expressions.\n\n2. Neg sort order: negative terms in Add now sort after positive terms.\n   \"x*exp(x) - exp(x)\" instead of \"-exp(x) + x*exp(x)\". Conventional\n   mathematical display.\n\n366 tests passing, zero regressions.","parents":["211e6cbb896b72997b1622ba89f0fed3eecd56d4"],"add":24,"del":7,"cadd":24,"cdel":7,"files":1},{"repo":"forms","hash":"88b714435f181be6610fcd429cb6730cebc3aeb7","ts":1776518350,"wall":"2026-04-18T09:19","msg":"feat: symbolic ODE solver (Tier 3.3) + simplifier fix","body":"Differential equations:\n- dsolve(expr, y, x) — solve dy/dx = expr symbolically\n- Separable: factors into f(x)*g(y), integrates both sides\n- Linear first-order: integrating factor method\n- Exponential growth/decay detected as special case → C*exp(kx)\n- 8 tests: pure integration, exponential, decay, product, linear\n\nSimplifier fix:\n- Mul([-1, term]) now reduces to Neg(term)\n- exp(x * (-1)) displays as exp(-x)\n\n374 tests passing.","parents":["a8e04e9eebb13151f2e9c4cec58de8e758a820d5"],"add":470,"del":1,"cadd":470,"cdel":1,"files":7},{"repo":"forms","hash":"ce36c72920e1ec47099fd77e9479844b94dab3c5","ts":1776519537,"wall":"2026-04-18T09:38","msg":"feat: Fourier series (Tier 3.8) — fourier(f, x, n)","body":"Computes n-term Fourier series on [-π, π]:\na₀ + Σ(aₖ·cos(kx) + bₖ·sin(kx)) for k=1..n\n\nCoefficients computed via symbolic integration of f·cos(kx)\nand f·sin(kx). Even functions produce only cosine terms,\nodd functions produce only sine terms.\n\n3 tests: even (x²), odd (x), constant. 377 total tests passing.","parents":["88b714435f181be6610fcd429cb6730cebc3aeb7"],"add":163,"del":1,"cadd":163,"cdel":1,"files":4},{"repo":"forms","hash":"b0a358b82a48f52d50f695be8dd5060b580085de","ts":1776520665,"wall":"2026-04-18T09:57","msg":"feat: Laplace transform (Tier 3.9) — laplace + ilaplace","body":"Forward transform via table lookup + linearity + frequency shift:\n- laplace(f, t, s) — L{1}, L{t^n}, L{e^(at)}, L{sin(at)}, L{cos(at)}\n- Frequency shift: L{e^(at)·f(t)} = F(s-a)\n- Constant multiple and sum linearity\n\nInverse transform via pattern matching:\n- ilaplace(F, s, t) — 1/s→1, 1/s^n→t^(n-1)/(n-1)!, 1/(s-a)→e^(at)\n- a/(s²+a²)→sin(at), s/(s²+a²)→cos(at)\n\n8 Laplace tests. 385 total tests passing.","parents":["ce36c72920e1ec47099fd77e9479844b94dab3c5"],"add":454,"del":1,"cadd":454,"cdel":1,"files":4},{"repo":"forms","hash":"58897fa83787aa0ead99bac0fa8a1f6fd1de9285","ts":1776543481,"wall":"2026-04-18T16:18","msg":"feat: Karnaugh maps (Tier 3.5) — classic mode","body":"K-map visualization for boolean expressions (2-4 variables):\n- Gray code ordering for rows and columns\n- Axis labels with variable names\n- Grid lines, colored cell values (green=1, red=0)\n- View toggle cycles: Plot → Table → K-map → Plot\n\nRendered in Troika HUD matching the instrument aesthetic.\nTriggered by right-click → View toggle on boolean expressions.\n\n385 tests passing.","parents":["b0a358b82a48f52d50f695be8dd5060b580085de"],"add":140,"del":4,"cadd":140,"cdel":4,"files":3},{"repo":"forms","hash":"3fafc2d444d7e9794beb9fe749d9dfc3711aeb7a","ts":1776547739,"wall":"2026-04-18T17:28","msg":"feat: predicate logic + fuzzy + temporal + modal (Tier 3.4)","body":"Five logic systems:\n\nBounded quantifiers:\n- forall(x, a, b, P(x)) — universal, short-circuits on counterexample\n- exists(x, a, b, P(x)) — existential, returns witness\n\nComparison functions (for use inside quantifiers):\n- gt, lt, eq, geq, leq, neq — return 0/1\n\nFuzzy logic:\n- fuzzy_and (Zadeh min), fuzzy_or (Zadeh max), fuzzy_not (complement)\n- luk_and (Łukasiewicz), luk_or (Łukasiewicz)\n- unknown keyword (= 0.5 for Kleene three-valued)\n\nModal logic:\n- necessary(P, worlds) — □P, true in all worlds\n- possible(P, worlds) — ◇P, true in some world\n\nTemporal logic (LTL over finite traces):\n- always(P, trace), eventually(P, trace), until(P, Q, trace)\n\n13 logic tests. 398 total tests passing.","parents":["58897fa83787aa0ead99bac0fa8a1f6fd1de9285"],"add":344,"del":0,"cadd":344,"cdel":0,"files":3},{"repo":"forms","hash":"cb4c91d22794dd2106fe776bce2abf6a2c45955e","ts":1776549280,"wall":"2026-04-18T17:54","msg":"feat: number field arithmetic (Tier 3.10) — Tier 3 complete","body":"Quadratic extension Q(√d):\n- QuadraticExt type: a + b√d with exact rational coefficients\n- Add, sub, mul, div (conjugate trick), neg, norm, trace\n- Simplifier integration: (1+√2)(1-√2) = -1 computed exactly\n- √a * √b = √(ab) with perfect square extraction\n- √8 → 2√2, √18 → 3√2 (largest square factor extraction)\n\n6 number field tests. 404 total tests passing.\n\nTIER 3 COMPLETE. All 10 features shipped:\n3.1 Symbolic integration    3.6 Probability distributions\n3.2 Eigenvalues             3.7 Curve fitting\n3.3 Differential equations  3.8 Fourier series\n3.4 Predicate logic         3.9 Laplace transform\n3.5 Karnaugh maps           3.10 Number field arithmetic","parents":["3fafc2d444d7e9794beb9fe749d9dfc3711aeb7a"],"add":376,"del":0,"cadd":376,"cdel":0,"files":2},{"repo":"forms","hash":"8d7acea42ec4e2472da9deb041bc397eb5de9b76","ts":1776549596,"wall":"2026-04-18T17:59","msg":"handoff: session state 2026-04-17/18 — Tiers 2+3 complete, 404 tests","body":"","parents":["cb4c91d22794dd2106fe776bce2abf6a2c45955e"],"add":100,"del":104,"cadd":100,"cdel":104,"files":1},{"repo":"forms","hash":"1c94f0e829fb436624970220ad1f71e135767e57","ts":1776550302,"wall":"2026-04-18T18:11","msg":"handoff: detailed debt phases added — 4 phases, 14 items prioritized","body":"","parents":["8d7acea42ec4e2472da9deb041bc397eb5de9b76"],"add":40,"del":3,"cadd":40,"cdel":3,"files":1},{"repo":"forms","hash":"f2019696b680082e0bbc5011d55743dbbdf3caac","ts":1776727046,"wall":"2026-04-20T19:17","msg":"feat: BigRational + eval refactor + cited manual + sliders + implicit curves + Vite","body":"Math core:\n- Rational64 → BigRational (arbitrary precision, no overflow)\n- eval.rs split into 9 submodules (matrix, laplace, fourier, factor, systems, limits, curve_fit, probability, partial)\n- ODE solver: exact equations + Bernoulli substitution\n- Quine-McCluskey prime implicant grouping for K-maps\n- contains_var consolidated to ast.rs, collect_vars made pub\n- Taylor series exact rational coefficients\n- 0/0 → Undefined fix, formatter fraction parenthesization fix\n- Fuzz targets (parse, evaluate) + proptest (simplifier idempotency, parser roundtrip)\n- 453 tests passing\n\nFrontend:\n- Vite + TypeScript migration (vite-plugin-wasm, tsconfig strict:false)\n- Parameter sliders with Jacobian-based curve dragging\n- Implicit 2D curves via marching squares (equations like x²+y²=1)\n- In-app manual panel with tooltips\n- resolve_notation WASM function (substitute + simplify + format)\n- sample_implicit_2d WASM function\n- param-store.js (single source of truth for parameter values)\n- Modular slider/curve-drag/param-store architecture\n\nManual:\n- 31 cited entries covering trigonometry through predicate logic\n- 23 primary source PDFs (Ptolemy ~150 CE through Mandelbrot 1982)\n- Style guide: physicist-precise voice, no popular-science register\n- Python build script (markdown → JSON)","parents":["1c94f0e829fb436624970220ad1f71e135767e57"],"add":334841,"del":3094,"cadd":9608,"cdel":993,"files":133},{"repo":"forms","hash":"0c63cc694eda8637cb738a2ab7b74208965c5c3a","ts":1776808732,"wall":"2026-04-21T17:58","msg":"refactor: eval modularization + master plan consolidation + manual corrections","body":"Eval dispatcher split from monolithic if-tower into 8 apply_*.rs modules\n(arithmetic, calculus, comparison, complex, list, logic, number_theory, trig).\nnumber.rs gains BigInt isqrt, safe accessors, improved QuadraticExt.\nManual entries corrected (Fourier a_0/2, Bernoulli dating, Frege added,\nstationary inflection, INDEX.md fixes). build.sh frontmatter parser hardened.\nFrontend: sanitize.js for XSS protection, resource lifecycle improvements,\ncurve-drag cleanup export. ROADMAP.md now serves as single master plan —\nhandoff.md and audit-remediation.md consolidated and deleted.\n\n493 tests passing.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["f2019696b680082e0bbc5011d55743dbbdf3caac"],"add":2168,"del":1461,"cadd":2156,"cdel":1449,"files":45},{"repo":"operations","hash":"4b3800fbafea87cb5745e0aced7e3519f03de527","ts":1776863229,"wall":"2026-04-22T09:07","msg":"infra: retire social/mesh subdomains, add commit garden prototypes","body":"Dashboard updated — GoToSocial and Reticulum removed, Forms/Elemental/Eureka\nadded to infrastructure table. Two commit garden prototypes saved: cityscape\n(Money For Nothing 1985 aesthetic) and flowers (raised bed ecosystem with\ncreatures, day/night cycle, live Forgejo data).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["0fdbcd0c472888069c8c6b7420aa57b39a4083a8"],"add":1532,"del":5,"cadd":1532,"cdel":5,"files":3},{"repo":"symbiont.systems","hash":"3aa7ff1124775c528836998c016a5007461fc2b0","ts":1776863329,"wall":"2026-04-22T09:08","msg":"feat: add 4 subdomain rings, sync dashboard defaults, update title/meta","body":"Portal now has 6 rings: Oasis, The Lab, Forms, Elemental, Eureka County,\nForgejo. Mission Control config.js synced to match live production values\n(geometry, spores, scene, all ring params). Title updated to Civilizational\nMetabolic Design. Meta description updated.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["0a2cd43e1ffebeb655e87e6611730cc98140a30c"],"add":641,"del":900,"cadd":641,"cdel":900,"files":3},{"repo":"forms","hash":"c67538371492c4236a17eea7261029baf7f44f77","ts":1776863349,"wall":"2026-04-22T09:09","msg":"docs: update ROADMAP test count, trim completed remediation","body":"Test count corrected to 493. Remediation section verified against code —\n27 of 33 items confirmed complete, 6 remaining (~4 hours).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["0c63cc694eda8637cb738a2ab7b74208965c5c3a"],"add":57,"del":101,"cadd":57,"cdel":101,"files":1},{"repo":"operations","hash":"7632de3fffcc0632ac250433ed5b2182f10d0823","ts":1776889670,"wall":"2026-04-22T16:27","msg":"feat: commit garden ecosystem + akashic stacks + clown prototype","body":"Garden: live Forgejo data via baked JSON (hourly cron), trimmed grid,\n6 creature types (worms, bees, butterflies, birds, squirrels, ladybugs),\nflower animation (wind sway, petal breathing, leaf rustle), permanent\ndaylight, grass ground, clown character next to raised bed.\n\nAkashic Stacks: psychedelic repo browser — floating books in fractal\nvoid with Julia set overlay, saturation boost, hover connections.\n\nClown: low-poly character with coat, hat, neon hair — repo labels\npinned inside coat lining. Needs ragdoll skeleton (next session).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["4b3800fbafea87cb5745e0aced7e3519f03de527"],"add":621,"del":114,"cadd":621,"cdel":114,"files":2},{"repo":"operations","hash":"ceb59a5abfe66eb33a91d86ebc42b67fd66fdfa4","ts":1776891811,"wall":"2026-04-22T17:03","msg":"docs: session 34 handoff + bookshelf prototype saved","body":"Comprehensive handoff: Forms master plan, retired subdomains, portal rings,\ngarden ecosystem (6 creatures + clown), akashic stacks, Forgejo custom\nlanding page, server state, deploy commands, known issues, next steps.\n\nBookshelf demo saved to prototypes before /tmp loss.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["7632de3fffcc0632ac250433ed5b2182f10d0823"],"add":611,"del":63,"cadd":611,"cdel":63,"files":2},{"repo":"puppet","hash":"8dd91a1299e9d29f8c6872a3addb560d63bc22e1","ts":1776903513,"wall":"2026-04-22T20:18","msg":"feat: puppet engine with articulated clown","body":"Vite + TypeScript + Three.js puppet system.\n\nSkeleton: declarative bone tree with joint limits, pivot offsets,\nrest poses, pose import/export as JSON.\n\nClown: the git.symbiont.systems commit garden clown with articulated\narms (shoulder/upper arm/forearm/hand chain), openable coat flaps\nwith buttons and lining, grinning face, hat.\n\nControls: click bone to select, drag to rotate joint. C toggles\ncoat open/close. D debug overlay. R reset. E export. I import.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":2051,"del":0,"cadd":1056,"cdel":0,"files":11},{"repo":"facedancer","hash":"b9071813865d05a05e9ef685897a45c560742755","ts":1776949835,"wall":"2026-04-23T09:10","msg":"feat: facedancer phase 0 — zooid pose daemon","body":"Axum HTTP server serving GET/PUT /api/pose. Persists puppet\npose JSON to disk. The editor pushes, the garden pulls.\n\n806 KB binary, 392 KB memory footprint. Runs as systemd service\non Hetzner behind Caddy reverse proxy.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":633,"del":0,"cadd":105,"cdel":0,"files":4},{"repo":"puppet","hash":"d07aa78b010911575c4fae0c186ec440454316ce","ts":1776949857,"wall":"2026-04-23T09:10","msg":"feat: articulated clown, TransformControls, facedancer integration","body":"- Clown puppet with full skeleton: head, torso, arms (shoulder/upper\n  arm/forearm/hand), legs (thigh/shin/foot), openable coat flaps\n- TransformControls gizmo for joint manipulation (Three.js 0.184)\n- Gimbal lock fix: auto Euler order selection per bone\n- Coat flaps with repo labels pinned to lining\n- Nametag with Permanent Marker graffiti font\n- Library build (vite.config.ts, src/index.ts) for ES module export\n- Facedancer API integration: E pushes pose, P pulls pose\n- Deployed to git.symbiont.systems commit garden\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["8dd91a1299e9d29f8c6872a3addb560d63bc22e1"],"add":424,"del":311,"cadd":424,"cdel":311,"files":8},{"repo":"facedancer","hash":"c02828a5801e21df177e1780ffaca0278538b772","ts":1776954448,"wall":"2026-04-23T10:27","msg":"feat: nervous system — vitals, tick loop, expression API","body":"Facedancer now maintains Gerald's internal state:\n\n- Vitals: energy (commit recency), mood (weekly density), alertness\n  (visitor interaction). Computed from garden-data.json every 5 seconds.\n- Expression: maps vitals to puppet parameters — idle speed, amplitude,\n  slouch, coat openness, hat tilt.\n- GET /api/vitals — returns vitals + expression\n- POST /api/interact — spikes alertness\n- GET /api/state — combined vitals + pose\n- Persists vitals to disk across restarts.\n\n905 KB binary, runs as systemd service on Hetzner.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["b9071813865d05a05e9ef685897a45c560742755"],"add":463,"del":9,"cadd":247,"cdel":9,"files":3},{"repo":"puppet","hash":"15c6fd4cb70f659b3e8924a78486b01e97ac5eee","ts":1776986510,"wall":"2026-04-23T19:21","msg":"feat: creature engine — locomotion, behavior, interest points","body":"- Creature class wraps skeleton with walk cycle and behavior FSM\n- Locomotion: procedural walk cycle, phase-locked to distance,\n  PI-flip aware for Gerald's inverted bone frames\n- Behavior: wander, walkTo, stop, notice (interest points),\n  onArrive callback. States: idle/turning/walking/arriving.\n- InterestPoint system: items in the world attract the creature,\n  decay over time, priority-sorted\n- buildClown() returns Creature instead of Skeleton\n- Coat removed from expression (manual control only)\n- Index exports all new types\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d07aa78b010911575c4fae0c186ec440454316ce"],"add":543,"del":68,"cadd":543,"cdel":68,"files":6},{"repo":"world","hash":"330772087bfed3c583c5729a281bbf679f1a4604","ts":1776986564,"wall":"2026-04-23T19:22","msg":"feat: world editor — sandbox for creatures, items, context menus","body":"Vite + TypeScript world editor for the facedancer system.\n\n- Gerald character definition (moved from puppet)\n- Context-sensitive right-click menus (ground, creature, item, view)\n- Item system: data format, spawn, decay, creature attraction\n- lil-gui panels for lighting, scene, expression, creature controls\n- Procedural walk + wander with pause/resume\n- Self-contained — no remote API dependency\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":2019,"del":0,"cadd":1018,"cdel":0,"files":10},{"repo":"puppet","hash":"b16ad9bf7bbb3d8b620f6b099a256c3e3aaf205e","ts":1776992672,"wall":"2026-04-23T21:04","msg":"feat: expose config/gizmo, scale acceleration with speed","body":"- Locomotion.config now readonly (was private) for editor binding\n- Behavior.maxSpeed now public for editor binding\n- Acceleration/deceleration rates scale with maxSpeed\n- Manipulator.gizmo now readonly for multi-gizmo coordination\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["15c6fd4cb70f659b3e8924a78486b01e97ac5eee"],"add":7,"del":7,"cadd":7,"cdel":7,"files":3},{"repo":"world","hash":"d66cdd4165b1fd37c725b356ccfd928388286e03","ts":1776992723,"wall":"2026-04-23T21:05","msg":"feat: custom context menus, stone primitive, movement presets","body":"- Custom context menu system (replaces lil-gui): right-click for\n  context-sensitive controls with inline sliders, color pickers,\n  checkboxes, nested submenus, keyboard nav, edge detection.\n- Stone primitive: convex hull of random points, Play-Doh style.\n  Configurable size, points, squash, color, seed.\n- Live stone reshaping: adjust params, stone regenerates in place.\n- TransformControls for placed objects (move/rotate/scale).\n- Multi-gizmo coordination: bone and object gizmos don't conflict.\n- 8 movement presets: clown waddle, march, sneak, strut, etc.\n- Movement config sliders in creature context menu.\n- Expression override sliders (energy, mood, alertness).\n- Wider wander bounds (16x16m).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["330772087bfed3c583c5729a281bbf679f1a4604"],"add":915,"del":150,"cadd":915,"cdel":142,"files":8},{"repo":"world","hash":"65ce47b4016fd42cb4e0e5523712222b773e6c3f","ts":1776994136,"wall":"2026-04-23T21:28","msg":"feat: truncated octahedron cells, remove stone primitive","body":"- Ported TO geometry from Glyph3D: 24 vertices, 14 faces (6 square,\n  8 hexagonal), edge wireframe, snap system for face-to-face docking\n- Cell config: scale, opacity, color, edge toggle, 16-color palette\n- Replaced stone primitive entirely — cells are the world substrate\n- Object menu: clone, remove, move/rotate/scale, color, opacity\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d66cdd4165b1fd37c725b356ccfd928388286e03"],"add":317,"del":217,"cadd":317,"cdel":217,"files":3},{"repo":"puppet","hash":"f6d0328970d2da8384d5e7e81f3bd12c2dbe8d45","ts":1776994477,"wall":"2026-04-23T21:34","msg":"feat: action system — grab, jump, squat, prone","body":"ActionPlayer: one-shot procedural animations with phase 0→1,\nhold states for squat/prone, rootY displacement, onComplete\ncallback. Locomotion pauses during actions.\n\nFour actions: grab (bend down + scoop, 1.5s), jump (crouch +\nairborne parabola + land absorb, 0.8s), squat (hold with\nbreathing), prone (hold flat with breathing).\n\nAuto-grab on item arrival: creature plays grab animation before\nfiring onArrive to the host.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["b16ad9bf7bbb3d8b620f6b099a256c3e3aaf205e"],"add":364,"del":3,"cadd":364,"cdel":3,"files":3},{"repo":"world","hash":"50595a212c32acc1b101954d8c4d1cd7d526ae6d","ts":1776994558,"wall":"2026-04-23T21:35","msg":"feat: action test buttons in creature context menu","body":"Right-click Gerald → Actions → Jump/Grab/Squat/Prone/Stand.\nTest buttons for the action system. Gerald auto-grabs items\non arrival with animation before removing them.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["65ce47b4016fd42cb4e0e5523712222b773e6c3f"],"add":7,"del":0,"cadd":7,"cdel":0,"files":1},{"repo":"world","hash":"850f9fa17c13addd8ee359728f17de25c57ae24c","ts":1776995704,"wall":"2026-04-23T21:55","msg":"feat: full Glyph3D shape library + action system wiring","body":"- All 5 shapes ported: TO, hex prism, cube, square prism, truncated\n  tetrahedron. Full collision detection, snap alignment, ground placement.\n- Shape selector in ground context menu with active indicator.\n- Action test buttons: jump, grab, squat, prone, stand.\n- Stone primitive fully removed. Fixed .gitignore.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["50595a212c32acc1b101954d8c4d1cd7d526ae6d"],"add":350,"del":183,"cadd":347,"cdel":182,"files":3},{"repo":"world","hash":"7a8695a96a2b1438a3d8e46533371f0e58baac69","ts":1777012944,"wall":"2026-04-24T02:42","msg":"feat: full Glyph3D block builder — build/edit modes","body":"Complete port of Glyph3D interaction system:\n- BlockBuilder class: piece manager, ghost preview, face highlight,\n  collision detection, snap alignment, ground placement\n- Build mode: hover preview, click to place, right-click to remove,\n  face-to-face snapping with compatible face type matching\n- Edit mode (Tab): select pieces, TransformControls, collision\n  feedback (red glow), duplicate (D), delete, undo (Ctrl+Z)\n- 5 shapes: TO, hex prism, cube, square prism, truncated tetrahedron\n- 16-color palette (C to cycle)\n- Gerald coexists: walks among blocks, context menu on right-click\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["850f9fa17c13addd8ee359728f17de25c57ae24c"],"add":484,"del":315,"cadd":484,"cdel":315,"files":2},{"repo":"world","hash":"45a5c8a2a0061f38d766974e473bca0df19b4099","ts":1777016537,"wall":"2026-04-24T03:42","msg":"feat: gravity void, scale fixes, wireframe parenting","body":"- Gravity simulation: N-body attraction, cluster bonding, damping\n- No ground plane: shapes float in void, worlds form from attraction\n- Seed cluster: 7 bonded TOs at origin as initial world\n- Ghost preview + face highlight + snap at quarter scale (0.25)\n- Edge meshes parented to piece mesh (no more wireframe ghosts)\n- Gerald raycasts toward gravity for surface detection\n- Context menus: block, void, creature, view all context-sensitive\n\nKnown issues: Gerald needs surface-walking system for TO terrain.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["7a8695a96a2b1438a3d8e46533371f0e58baac69"],"add":539,"del":161,"cadd":539,"cdel":161,"files":3},{"repo":"world","hash":"7625a7c2858ef80803e84e73d8b4a196cbb47de1","ts":1777017868,"wall":"2026-04-24T04:04","msg":"wip: cluster surface hulls, TO tessellation seed, 0.125 scale","body":"- Convex hull surface per cluster for Gerald raycasting (no gaps)\n- Seed world grows by face-to-face snapping (proper tessellation)\n- Particles at 0.125 scale (half of previous 0.25)\n- GravitySimulation takes scene ref for surface mesh management\n\nKnown issues:\n- Seed uses only TOs — should mix all 5 Archimedean shapes\n- Gerald floating — bonding/surface detection needs tuning\n- 136 bodies as separate clusters instead of one bonded cluster\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["45a5c8a2a0061f38d766974e473bca0df19b4099"],"add":130,"del":36,"cadd":130,"cdel":36,"files":3},{"repo":"puppet","hash":"f4742ab0f57c904cca7be1a676de331a51528991","ts":1777020262,"wall":"2026-04-24T04:44","msg":"feat: swimming locomotion + grounded state","body":"Locomotion: swim cycle (time-driven arm paddle, flutter kick,\ntorso roll) plays when swimming=true. Creature sets swimming\nfrom grounded property. Behavior pauses when not grounded.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["f6d0328970d2da8384d5e7e81f3bd12c2dbe8d45"],"add":50,"del":3,"cadd":50,"cdel":3,"files":2},{"repo":"world","hash":"a58e2ffa6bb0395389a86f5f97f5271db1080034","ts":1777020293,"wall":"2026-04-24T04:44","msg":"feat: scattered shapes, swimming Gerald, void menu","body":"- No seed cluster: 8 shapes scattered in sphere around origin\n- Gerald starts at origin, swimming in the void\n- Shapes drift under gravity, clump naturally\n- Gerald lands on surfaces when close enough, starts walking\n- UI shows SWIMMING vs ON GROUND\n- TT triangle faces now connectable (for Archimedean tessellation)\n- Surface hull debug toggle in Void menu\n- Cluster count in UI\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["7625a7c2858ef80803e84e73d8b4a196cbb47de1"],"add":51,"del":58,"cadd":51,"cdel":58,"files":3},{"repo":"metabolic","hash":"921121a3f06760a2db8303356b0041d2fafbc53c","ts":1777161679,"wall":"2026-04-25T20:01","msg":"Metabolic: initial commit — Daisyworld engine, the SimEarth successor","body":"Sibling project to Forms (mathematics) and Elemental (chemistry). A\ncoupled-subsystems planetary simulator. Inherits Forms' Rust/WASM\nengine pattern: pure-Rust core compiles native and to wasm.\n\nHello World: Watson & Lovelock (1983) Daisyworld, implemented from\nthe original paper. Six equations, two species, one feedback loop.\nThe sweep test ramps solar luminosity from L=0.6 to L=1.6 and\nverifies the planet self-regulates in the daisy growth window from\nL=0.78 through L=1.275, then collapses cleanly at L=1.30. At the\nregulation extremes daisies hold the planet ~20°C cooler/warmer\nthan a bare planet — the Gaia thesis embodied in math, not just\nreferenced in docs.\n\nReference materials mined and stored under\n~/symbiont/code/operations/research/{simearth,daisyworld}/.\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":[],"add":428,"del":0,"cadd":424,"cdel":0,"files":8},{"repo":"symbiont.systems","hash":"5664af7d47a9b54d724d7d1162fd67dcae6cf0c2","ts":1777162354,"wall":"2026-04-25T20:12","msg":"mission-control: rename dev/ → mission-control/ + add splash config","body":"The local editor is Mission Control (per its <title> and the comment\nin generated HTML), so the directory name should match. Renamed\ndev/ → mission-control/ and dashboard.html → index.html. All 27 file\nmoves are pure git mv; internal refs are relative and required no\nedits. Updated two path references in docs/armillary-framework-research.md\nand .claude/handoff.md.\n\nSplash screen is now editable from Mission Control. Added a CONFIG.splash\nblock (enabled, background, logoSrc, brand, tagline, loadingText, fadeMs,\ndismissDelayMs), a \"Splash\" tab between Scene and Shader, a buildSplashPanel\nfactory wired into rebuildUI, and replaced the previously-hardcoded splash\nmarkup in generateProductionHTML() with template-literal interpolation\ngated on CONFIG.splash.enabled. Disabling the splash strips its CSS,\nmarkup, and dismissal JS entirely from the deployed page; otherwise\nall values flow through to the live site on Deploy.\n\nLive deploy of the dashboard tree to /var/www/symbiont/_dashboard/ on\nHetzner via rsync was performed out-of-band (not committed here — that\npath now matches https://symbiont.systems/_dashboard/, the basicauth-\ngated route in the live Caddyfile).\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["3aa7ff1124775c528836998c016a5007461fc2b0"],"add":99,"del":6,"cadd":99,"cdel":6,"files":28},{"repo":"metabolic","hash":"009e226d2bdc19a7ec1f115aa665a5afa0e05913","ts":1777168558,"wall":"2026-04-25T21:55","msg":"metabolic-core: spatial Daisyworld + geodesic grid","body":"Three layers built on top of the original 0D Daisyworld:\n\n1. **Tiled (rectangular)** — `tiled_daisyworld.rs`. A 2D toroidal grid\n   with cos(latitude) insolation and 4-neighbour heat diffusion. Latitudinal\n   bands emerge from the same selection mechanism as the 0D version, applied\n   per cell. Verified by 3 integration tests.\n\n2. **Geodesic grid** — `geosphere.rs`. A pure-Rust icosahedral\n   subdivision producing 10·N²+2 vertices at depth N=2^d. Each vertex is a\n   cell centre; adjacency is built from triangle-edge sharing. Exactly 12\n   pentagonal cells (the original icosahedron vertices); the rest hexagons.\n   6 unit tests covering subdivision invariants, adjacency symmetry, and\n   sphere-projection accuracy.\n\n3. **Hex-sphere Daisyworld** — `hex_daisyworld.rs`. The simulation on a\n   real sphere instead of a rectangular pretender. Adds dispersal between\n   cells via discrete Laplacian on each daisy field, plus background\n   propagule pressure replacing the population floor. Recolonisation of\n   extinguished cells verified by an explicit test.\n\nResearch documents captured in `research/`:\n  - `heat-transport.md`     — Budyko-Sellers EBM literature, parameter values\n  - `dispersal.md`          — Fisher-KPP, dispersal kernels, spatial Daisyworld\n  - `grid-topology.md`      — geodesic grid options, hexasphere.js inspection\n\nSixteen tests pass. The four limitations of the rectangular grid (area\nweighting, pole singularity, no dispersal, non-spherical geometry) are\neither fixed structurally by the hex sphere or addressed explicitly by\nnew logic.\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["921121a3f06760a2db8303356b0041d2fafbc53c"],"add":1629,"del":0,"cadd":1626,"cdel":0,"files":10},{"repo":"metabolic","hash":"8e672d5b0915c345146576539cc92dfb8f08fc9d","ts":1777168604,"wall":"2026-04-25T21:56","msg":"metabolic-wasm + web: browser visualisation of the hex-sphere planet","body":"Forms-pattern visualisation layer on top of the simulation engine:\n\n- `metabolic-wasm/` — wasm-bindgen wrapper around `metabolic-core`'s\n  `HexDaisyworld`. Exposes constructor, step/run, luminosity setter, and\n  flat `Float32Array` views for cell positions, triangle indices, and\n  per-cell colours suitable for direct upload to a Three.js BufferGeometry.\n  Two colour modes: daisy composition (sandy / black / white) and\n  temperature ramp (blue → green → red).\n\n- `web/` — vanilla ES module frontend, no build step. Page shell with\n  HUD (cell count, mean temperature, mean black/white fractions),\n  luminosity slider, view selector, reset button. Renders 10,242-cell\n  planet at depth=5; advances simulation 6 steps per render frame at\n  dt=0.1 (≈0.6 simulated time units per frame). Three.js + OrbitControls\n  bundled locally from mission-control's vendored copies — no CDN\n  dependency, runs offline.\n\nBuild:\n  (cd metabolic-wasm && wasm-pack build --target web --release)\nServe:\n  (python3 -m http.server 8765)\nOpen:\n  http://localhost:8765/web/\n\nProduction deployment target: metabolic.symbiont.systems (TBD).\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["009e226d2bdc19a7ec1f115aa665a5afa0e05913"],"add":2450,"del":1,"cadd":2450,"cdel":1,"files":9},{"repo":"metabolic","hash":"5054a55b9e341383733aec7d0cdf2a1f6edb8512","ts":1777168698,"wall":"2026-04-25T21:58","msg":"research: phase D plan — generalise species","body":"Concrete design target for the next refactor: turn HexDaisyworld into a\nspecies-generic HexPlanet. Black/white daisies become two instances of a\nSpecies struct; adding a third (or a thirtieth) becomes data, not code.\n\nPhase D is the load-bearing refactor — every subsequent phase (atmospheric\nchemistry, trophic interactions, multi-subsystem coupling) needs first-class\nspecies.\n\nPlan covers: data model, file layout, WASM impact, test parity constraints,\nout-of-scope items, open questions. ~530 LOC estimated, ~3 hours.\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["8e672d5b0915c345146576539cc92dfb8f08fc9d"],"add":213,"del":0,"cadd":213,"cdel":0,"files":1},{"repo":"metabolic","hash":"58703e7f6fe856afe46bb6ee08ac4dbcc7463eab","ts":1777172145,"wall":"2026-04-25T22:55","msg":"research: phase D plan rewrite — multi-kingdom species substrate","body":"Expands Phase D scope to reflect the actual ambition: a real biosphere\nsubstrate, not just generalised daisies.\n\nArchitecture (Approach 3 + 5 hybrid):\n  - Capabilities as optional components on species (Photosynthesis,\n    Chemoautotrophy, Decomposition — each Some(...) for species that do it,\n    None for those that don't). Real organisms are bags of metabolic\n    capabilities; a Venus flytrap is plant + photosynthesis + predation,\n    a vent shrimp is animal + predation + chemoautotrophic-symbiont.\n    Type-tagged trophic roles can't represent this without escape hatches.\n  - Predation as planet-level edges (Vec<Predation>), not species\n    properties. Food web is a first-class graph; trophic categories\n    (herbivore, carnivore, omnivore, detritivore) emerge from queries\n    over the graph.\n\nCell complexity dimension (Prokaryote vs Eukaryote) included with real\nbiology constraints:\n  - multicellular requires Eukaryote\n  - anoxygenic photosynthesis (H₂S electron donor) requires Prokaryote\n  - validation reports structured errors for the cell designer\n\nDecomposition substrate-specificity included with a DetritusSubstrate\nenum (Lignin, Cellulose, Chitin, Keratin, Protein, Lipid, Hydrocarbon,\nSimpleSugar). Captures the real niche partitioning: fungi specialise in\nlignin (no other group has lignin peroxidases), bacteria dominate fresh\nprotein, archaea handle anaerobic extremophile niches. Each kingdom has\na default detritus profile when organisms die; per-species overrides\nallowed.\n\nPhase D ships the data model + producer dynamics. Phase E activates the\nfood web (eating). Phase F brings atmospheric chemistry (gas pools).\nPhase G brings heritable genomes and mutation. Phase H ships the\nbrowser-side cell designer.\n\nEstimated scope: ~1,400 LOC, ~6 hours.\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["5054a55b9e341383733aec7d0cdf2a1f6edb8512"],"add":386,"del":111,"cadd":386,"cdel":111,"files":1},{"repo":"metabolic","hash":"a2c90b0834a32aa186c0eb1e9bba7bfcae05f28b","ts":1777203812,"wall":"2026-04-26T07:43","msg":"phase D: multi-kingdom species substrate","body":"Replaces the hardcoded HexDaisyworld with a species-generic HexPlanet\nbuilt on capability composition. Each species is a bag of optional\nmetabolic capabilities (Photosynthesis, Chemoautotrophy, Decomposition)\nplus universal physiology (Respiration, ThermalTolerance, OxygenDependence)\nplus identity (Kingdom, CellComplexity, name, color). Predation lives on\nthe planet (Vec<Predation>, inert until phase E), not on species — food\nwebs are first-class graphs, trophic categories emerge from queries.\n\nNew modules:\n  kingdom.rs    — Kingdom, CellComplexity enums with canonical mappings\n  detritus.rs   — DetritusSubstrate enum (8 variants: lignin, cellulose,\n                  chitin, keratin, protein, lipid, hydrocarbon, sugar)\n                  + per-kingdom default partition profiles. Stored as\n                  fixed [f64; 8] arrays for fast hot-loop updates.\n  species.rs    — Species, capability components, validation errors with\n                  structured reporting for the cell designer\n  food_web.rs   — Predation edge struct (predator → prey with rate +\n                  efficiency); used in phase E\n  hex_planet.rs — generic species-driven planet, replaces hex_daisyworld\n  scenarios.rs  — daisyworld(), three_daisy_world(), forest_world(),\n                  sulfur_world() factories\n\nValidation enforces real-biology constraints: multicellular requires\nEukaryote; anoxygenic photosynthesis (H2S electron donor) requires\nProkaryote. Errors are structured for surfacing in the cell designer\nUI later.\n\nPerformance: per-step hot loop pre-caches detritus profiles and\nphotosynthesis snapshots once per step instead of recloning HashMaps\nper cell-species pair. Cell albedo and bare fraction cached once per\ncell. Result: the original hex_daisyworld test suite ran in 3.85s; the\nnaive Phase D port ran in 36s; the optimised version runs in 8.4s.\n\nWASM bindings rewritten for scenario-aware constructors:\n  WasmPlanet.daisyworld(depth, luminosity)\n  WasmPlanet.three_daisy(depth, luminosity)\n  WasmPlanet.forest(depth, luminosity)\n  WasmPlanet.sulfur(depth, luminosity)\n\nFrontend gains a scenario picker and a resolution selector (depth\n3-6, 642 to 40,962 cells), with steps-per-frame auto-tuned per\nresolution to keep per-frame work roughly constant.\n\nTests:\n  17 unit tests in metabolic-core (geosphere, kingdom, detritus,\n     food_web, species)\n   3 0D Daisyworld tests (unchanged)\n   9 hex_planet tests (5 ports of hex_daisyworld + 3 new validation\n     + sulfur scenario clean-validation)\n   3 tiled_daisyworld tests (unchanged)\n  ───\n  32 tests, all green\n\nRemoves hex_daisyworld.rs and tests/hex_daisyworld.rs (superseded by\nhex_planet + scenarios::daisyworld).\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["58703e7f6fe856afe46bb6ee08ac4dbcc7463eab"],"add":1856,"del":585,"cadd":1856,"cdel":585,"files":13},{"repo":"metabolic","hash":"b7cefb0b9e37a3c65cee14fb83322a8ccdc675c1","ts":1777204113,"wall":"2026-04-26T07:48","msg":"research: phase E plan — geography substrate","body":"Static-geography phase covering elevation, water, ice, save/load, habitat,\nand preset planets. Plate tectonics deferred to phase F (true runtime, per\nuser direction) so phase E ships a complete, testable substrate before\nplates start moving.\n\nArchitectural commitments:\n  - Elevation, water depth, ice thickness as state variables (Phase F\n    will mutate elevation when plates collide).\n  - Surface type (Land / Water / IceLand / SeaIce) is a derived view, not\n    a stored field.\n  - Habitat enum on Species (Terrestrial / Aquatic / Amphibious / SeaIce)\n    gates growth by surface compatibility.\n  - Save format is JSON with explicit schema_version=1; phase F bumps to\n    v2 with forward-compatible plate fields.\n  - Time becomes a continuous logarithmic slider, not named buckets.\n    More honest framing: simulated time per real second.\n  - Three preset planets ship: Earth-like, water-world, mountain-world.\n    Existing scenario factories pick up flat default terrain.\n\nClimate consequences modelled:\n  - Surface-dependent albedo (water 0.06, ice 0.85, land variable)\n  - Water has ~50× land thermal mass → slower radiative relaxation\n  - Lapse rate ~6.5 °C/km (mountains are cold)\n  - Ice-albedo feedback: cold cells freeze, frozen cells reflect, cycle\n    can run away into snowball or melt out\n\nEstimated scope: ~1,750 LOC, ~10 hours.\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["a2c90b0834a32aa186c0eb1e9bba7bfcae05f28b"],"add":423,"del":0,"cadd":423,"cdel":0,"files":1},{"repo":"metabolic","hash":"7fd372511e02e27c415dcbbd37d621419a8e76d3","ts":1777232194,"wall":"2026-04-26T15:36","msg":"phase E: geography substrate","body":"Replaces the uniform sphere with elevation, water, ice, habitats, and\nsave/load. Plate tectonics deferred to Phase F.\n\nState variables added per cell:\n  - elevation_m\n  - water_depth_m   (cells with water_depth > 0 are Water; the predicate\n                     honours the state, not a comparison against sea level)\n  - ice_thickness_m (grows below freezing, melts above)\n\nSurface type (Land / Water / SeaIce / IceLand) is a derived view, not a\nstored field. The albedo, radiative-relaxation rate, and bare-fraction\ncalculations all key off it.\n\nClimate consequences:\n  - Water cells use ALBEDO_WATER 0.06 and a slower radiative relaxation\n    rate (0.02 vs 0.10 on land) — oceans buffer temperature swings\n  - Sea ice 0.65, ice land 0.85 — strong positive feedback loop on cold\n    cells (ice forms → albedo rises → cell cools further)\n  - Land bare albedo set to 0.30 (real Earth average), not the 0.50\n    canonical Watson-Lovelock value — see\n    feedback-realism-over-canonical-parity.md\n  - Lapse rate 6.5 °C/km subtracts altitude warming from local\n    equilibrium temperature\n\nHabitat enum on Species (Terrestrial / Aquatic / Amphibious / SeaIce)\ngates growth by surface match. Aquatic photosynthesisers grow in water\ncells; terrestrial ones grow on bare land; mismatched habitat returns\nzero growth.\n\nProcedural elevation generator (terrain.rs) — 3D simplex noise summed\nover fractal Brownian octaves. Pure Rust, no dependency. Deterministic\nper seed.\n\nSave/load (save.rs) — serde-derived JSON. schema_version = 1 in Phase E;\nPhase F will bump to v2 with plate fields and a forward migration.\nGeosphere is reconstructible from depth so we don't serialise it.\n\nThree preset planets:\n  - earth_like     (~70% water, hypsometric range tuned to look Earthly)\n  - water_world    (~95% water, scattered islands)\n  - mountain_world (16 km relief, lots of cold highlands)\n\nThe four flat-terrain scenarios (daisyworld, three_daisy, forest, sulfur)\ncontinue to behave as before — they use flat default elevation and the\nall-Land surface predicate.\n\nWASM exposes:\n  - WasmPlanet.earth_like / .water_world / .mountain_world (with seed)\n  - .save_json() / WasmPlanet.load_json(json)\n  - .sea_level_m() / .set_sea_level(m)\n  - positions() now displaces vertices radially by elevation\n  - species_colors() routes through surface type — water blue (depth-\n    blended), ice white, land species-mix on bare-sand\n\nFrontend gains:\n  - Earth/water/mountain options in the scenario dropdown (selected by\n    default opens on earth_like — visible terrain straight away)\n  - Sea level slider (-4000 to +4000 m) — drag to expand/recede oceans\n    in real time\n  - Save / Load buttons (downloads JSON, loads from picked file)\n\nThe regulation regression test (`daisyworld_regulates_at_warm_*`) is\nrefactored to compare against a bare-planet equivalent at the same\nluminosity rather than asserting a fixed 30°C threshold — regulation\nis the *difference* from no-daisies, not a specific temperature.\n\nTests: 45 total, all green.\n   22 unit (terrain, kingdom, detritus, food_web, geosphere, species)\n    3 0D daisyworld\n    8 geography (NEW — earth_like partition, ice formation, aquatic\n                  habitat gating, save/load round-trip, etc.)\n    9 hex_planet\n    3 tiled_daisyworld\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["b7cefb0b9e37a3c65cee14fb83322a8ccdc675c1"],"add":1280,"del":127,"cadd":1280,"cdel":127,"files":16},{"repo":"metabolic","hash":"f1803543d2c274d6771ebb18e9775aed36466552","ts":1777234146,"wall":"2026-04-26T16:09","msg":"research: audit follow-up plan — pre-Phase-F cleanup","body":"Six chunks, ~7 hours, ~600 LOC, addresses every concern from the audit:\n\n  1. Double-buffer + flat populations (must-fix; ~250 LOC, 3h)\n  2. WASM color buffer write-into pattern (perf; ~50 LOC, 45min)\n  3. Cleanup hygiene — delete dead code, legacy modules, unused\n     functions; const detritus profile lookup; compact JSON\n     (~700 LOC removed, ~50 added, 30min)\n  4. Test coverage — AnaerobicWithO2Respiration negative test, three\n     LoadError tests, refactor regulation-vs-bare test, WASM smoke\n     tests, performance regression (~200 LOC, 1.5h)\n  5. Time scale exposure — replace auto-tuned stepsPerFrame with a\n     simulation_speed slider per operator's \"more honest\" framing\n     (~50 LOC, 30min)\n  6. ARCHITECTURE.md (~600 LOC markdown, 1h)\n\nSequenced so chunks ship independently with tests passing at every\ncheckpoint. Chunk 3 first (pure deletion), then chunk 1 alone\n(big refactor), then 4/2/5/6 in any order.\n\nAfter this plan ships:\n  - 51 tests instead of 45\n  - ~600 fewer LOC of legacy code\n  - ~250 LOC of refactored hot path\n  - Zero hot-path allocation\n  - Foundation Phase F (plate tectonics) drops onto cleanly\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["7fd372511e02e27c415dcbbd37d621419a8e76d3"],"add":233,"del":0,"cadd":233,"cdel":0,"files":1},{"repo":"metabolic","hash":"85d52eef34e4d1e6a321ce3d8644ca968e27d7a9","ts":1777234718,"wall":"2026-04-26T16:18","msg":"audit chunk 1: double-buffer + flat populations","body":"Hot-path zero-allocation refactor. Two changes fused into one:\n\n1. HexPlanet now holds cells_next and populations_next as fields. step()\n   reads from cells / populations and writes to cells_next /\n   populations_next, then mem::swap at end. The previous pattern\n   (`let mut next = self.cells.clone()` per step) is gone — zero\n   allocation on the hot path.\n\n2. Cell loses its `populations: Vec<f64>` field. Populations move to\n   HexPlanet as a single contiguous Vec<f64> of length cell_count *\n   species_count, indexed via pop_idx(cell, species). Cache-friendly,\n   single allocation that grows when species are added.\n\nPublic API gains:\n  - HexPlanet::pop_idx(cell, species) -> usize\n  - HexPlanet::population(cell, species) -> f64\n  - HexPlanet::set_population(cell, species, value)\n  - HexPlanet::populations_for_cell(cell) -> &[f64]\n\nAll 45 tests pass with identical numerical results. Test suite ~14%\nfaster (hex_planet: 9.16s → 7.91s; geography: 3.45s → 2.84s) — pure\nrefactor, no behavioural change.\n\nSave format: SavedPlanet now stores populations as a flat Vec<f64>\nparallel to the in-memory layout. SavedCell drops its populations\nfield. schema_version stays 1 (no in-the-wild saves to migrate).\nload_from_json validates that populations.len() == cell_count *\nspecies_count, returning a structured error on mismatch.\n\nWASM:\n  - blend_land_color now takes a populations slice instead of a Cell\n  - species_colors() reads from the flat populations array via\n    self.inner.populations[i * species_count .. (i+1) * species_count]\n  - WasmPlanet.mean_population() unchanged in API; uses the engine\n    method which now reads the flat array\n\nThe cells_next and populations_next fields are pub(crate) — they're\ninternal scratch space. External callers go through the public\naccessors.\n\nThis unblocks Phase F (plate tectonics): the second update pass for\nplate motion drops in cleanly because step() is already a \"read from\nA, write to B, swap\" pattern. No re-architecture needed when plates\nland.\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["f1803543d2c274d6771ebb18e9775aed36466552"],"add":171,"del":82,"cadd":171,"cdel":82,"files":5},{"repo":"metabolic","hash":"a0ec471b5e1c27296fe9864994ae7595b26617d2","ts":1777235483,"wall":"2026-04-26T16:31","msg":"audit chunk 2: WASM write-into color buffers","body":"Zero-allocation render-loop path. Two new WASM methods:\n\n  WasmPlanet::write_species_colors(buf: &mut [f32])\n  WasmPlanet::write_temperature_colors(buf: &mut [f32])\n\nBoth write directly into a JS-supplied Float32Array. The frontend\nallocates one buffer at mesh-build time (the BufferAttribute's\nunderlying array) and reuses it every frame. The previous pattern\nallocated a fresh Vec<f32> on the WASM heap, marshalled it across\nthe boundary, then JS copied it into the BufferAttribute via\n.set() — three operations replaced by one direct write.\n\nThe original allocating methods (species_colors / temperature_colors)\nare kept for one-shot use (e.g. the initial mesh build). They now\ndelegate to the write-into helpers internally rather than duplicating\nthe logic.\n\nFrontend pullColors() updated to use the write_* path:\n\n  if (viewMode === 'temperature') {\n    planet.write_temperature_colors(colorAttr.array);\n  } else {\n    planet.write_species_colors(colorAttr.array);\n  }\n\nAt depth 5 (10,242 cells) that's 30,726 floats × 60 fps = 1.8 million\nfewer heap floats per second versus the old allocate-and-copy path,\nplus one fewer copy across the JS/WASM boundary per frame.\n\nAll 45 tests pass. WASM artefact is ~206 KB, unchanged.\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["85d52eef34e4d1e6a321ce3d8644ca968e27d7a9"],"add":71,"del":26,"cadd":71,"cdel":26,"files":2},{"repo":"metabolic","hash":"c21c98abcc8816975647c79dd7e7d65a9ceca895","ts":1777247963,"wall":"2026-04-26T19:59","msg":"audit chunk 3: cleanup hygiene","body":"Six small items, mostly deletion. Net -684 LOC.\n\n1. Delete `_phase_f_placeholders` and the unused ElectronDonor /\n   OxygenDependence imports in hex_planet.rs. The placeholder fn was\n   only there to silence unused-import warnings; with the imports\n   removed, neither is needed.\n\n2. Delete daisyworld.rs and tiled_daisyworld.rs (and their tests).\n   These were the 0D and rectangular-grid implementations from\n   Phases A–B, kept as reference until Phase D landed. The canonical\n   Daisyworld now lives at scenarios::daisyworld() running on the\n   generic engine; the old modules were carrying ~600 LOC of code\n   irrelevant to where Metabolic is going. -7 tests (3+3+1) but\n   they were testing modules we no longer ship.\n\n3. Delete flat_elevation() from terrain.rs — was only useful for\n   scenarios that wanted explicitly-zero terrain, which is what\n   set_elevations() does by default if you don't call it.\n\n4. HexPlanet::empty() takes initial_temperature_k parameter. The\n   old constructor was hardcoded to 295.65 K (22.5 °C, daisy growth\n   optimum); fine for daisyworld scenarios, awkward for sulfur\n   world (35 °C optimum) or any future alien planet. Convenience\n   wrapper HexPlanet::empty_default() preserves the old behaviour\n   for daisyworld-style callers; explicit empty() is available for\n   anything else. constants::T_OPT_K added.\n\n5. default_detritus_profile() rewritten to return an inline\n   [f64; 8] array literal per kingdom instead of going through\n   DetritusProfile::from_pairs(vec![...]). Zero allocation per\n   call. Caching it once per step at the top of step() means the\n   total allocations went from O(species × steps) to O(species ×\n   step_count) where step_count is just the snapshot loop, but\n   even the snapshot is cheaper now.\n\n6. Module doc-comment in lib.rs rewritten to reflect the current\n   state (capability composition, geography, save/load) rather\n   than its Phase-A \"Daisyworld is the Hello World\" framing.\n\nModule list, post-cleanup:\n  detritus, food_web, geosphere, hex_planet, kingdom, save,\n  scenarios, species, terrain\n\nTests: 38 (was 45, -7 from deleted legacy modules).\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["a0ec471b5e1c27296fe9864994ae7595b26617d2"],"add":62,"del":746,"cadd":62,"cdel":746,"files":10},{"repo":"metabolic","hash":"556ca5a0414f4197a7e1ec47d70c1d3e85f34a9c","ts":1777248670,"wall":"2026-04-26T20:11","msg":"audit chunk 4: test coverage","body":"Five items from the audit, four shipped, one deferred.\n\nShipped:\n\n1. species::tests::validation_rejects_anaerobic_with_o2_respiration —\n   the third validation rule (a species declared anaerobic but with\n   positive O₂ consumption rate) was uncovered. Now caught by a\n   negative test parallel to the other two.\n\n2. tests/geography.rs gains three LoadError negative tests:\n     load_invalid_json_returns_error\n     load_future_schema_version_returns_error\n     load_cell_count_mismatch_returns_error\n   Each constructs a deliberately-malformed input and verifies the\n   correct LoadError variant comes back. Previously only the happy\n   path was tested.\n\n3. HexPlanet gains a `disable_growth: bool` field. When true,\n   step()'s resource_factor is forced to zero — populations decay\n   to the propagule-pressure floor (~ε/γ). Used for the regulation\n   regression test as a clean \"bare planet\" baseline:\n\n     let mut bare = daisyworld(4, 1.30);\n     bare.disable_growth = true;\n     bare.run(2000, 0.1);\n\n   Replaces the previous manual zero-and-rerun pattern, which was\n   fragile (propagule pressure could partially restore populations\n   between zerings).\n\n4. Performance regression test pins the hot path. At depth=5 with\n   the daisyworld scenario, 1000 steps must complete in under 10\n   seconds — generous budget chosen for CI compatibility, but\n   tight enough to catch catastrophic regressions like accidental\n   per-cell allocation. Current dev hardware completes in ~3.8s,\n   ~2.6× headroom.\n\nDeferred:\n\n5. WASM smoke tests with #[wasm_bindgen_test]. Skipped because\n   running them needs browser or node infrastructure we don't\n   have set up locally. The engine-level integration tests cover\n   the same logic. Will revisit when we add a CI pipeline that\n   includes a headless browser runner.\n\nTests: 43 (was 38, +5).\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["c21c98abcc8816975647c79dd7e7d65a9ceca895"],"add":97,"del":14,"cadd":97,"cdel":14,"files":5},{"repo":"metabolic","hash":"45c559f15d37aa1101b26e66f9647ff6cce95056","ts":1777249128,"wall":"2026-04-26T20:18","msg":"audit chunk 5: simulation_speed slider","body":"Replaces the auto-tuned `stepsPerFrameFor(depth)` magic with a\nuser-controlled time slider. The previous behaviour was opaque — at\ndepth 5 you got 4 steps/frame, at depth 6 you got 2, but the user\nhad no way to know what time rate that translated to. Now the slider\nis the rate, the rate is the slider.\n\nSlider:\n  - Log-scale, exposed as log10(speed)\n  - Range: 0.1× to 100× (raw simulationSpeed)\n  - Default: 1× (which equals the legacy depth-5 default rate of\n    24 dimensionless time units per real second)\n  - Readout: shows \"X t/s\" (simulated time units per real second),\n    derived from simulationSpeed * 4 * 60 * 0.1\n\nStep pacing uses an accumulator pattern:\n  stepAccumulator += simulationSpeed * BASE_STEPS_PER_FRAME;\n  let steps = Math.min(Math.floor(stepAccumulator), 256);\n  stepAccumulator -= steps;\n  if (steps > 0) { planet.run(steps, DT_PER_STEP); }\n\nThis handles fractional rates smoothly — at simulationSpeed = 0.1\nwe get 0.4 steps/frame, the accumulator accrues across frames, and\nwe run 1 step every ~3 frames. At 100× we run ~400 steps/frame\n(capped at 256 as a sanity guard).\n\nThe depth dropdown still controls cell count; rate is now\northogonal. Higher depths will struggle to keep up at high speeds —\nthat's honest behaviour; the user can drop the slider when it\nlags. No more \"the engine pretends to slow down at high resolution.\"\n\nNote: pullColors() now only fires on frames where the sim\nactually advanced (steps > 0). When the slider is dragged below\nthe per-frame threshold, colour upload is correspondingly less\nfrequent — saves bandwidth at low rates.\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["556ca5a0414f4197a7e1ec47d70c1d3e85f34a9c"],"add":49,"del":11,"cadd":49,"cdel":11,"files":2},{"repo":"metabolic","hash":"6881cdd9a24d26b97ef56aef2ee0287ab049f44c","ts":1777249537,"wall":"2026-04-26T20:25","msg":"audit chunk 6: ARCHITECTURE.md","body":"Project-level architecture document covering the engine's design after\nPhases A–E and the audit-followup chunks. ~440 LOC of markdown.\n\nSections:\n  - Repo layout — module map + Forms-pattern sibling description\n  - The shape of an organism — Species, capability composition, validation\n  - The shape of a community — food-web edges on the planet\n  - The shape of a planet — flat populations, double-buffer, derived state\n  - The shape of an environment — Kingdom, CellComplexity, DetritusSubstrate\n  - The render pipeline — mesh construction, colour blending, WASM/JS contract\n  - Save / load — schema versioning, forward-compat semantics\n  - WASM boundary — scenario constructors, write-into hot path\n  - Phase log — commit-by-commit, A through audit chunk 5\n  - What's next — Phase F (plates) through Phase J (cell designer)\n  - Operating notes — build, test, serve\n\nDoubles as a reference for fresh sessions and a public document on\ngit.symbiont.systems for anyone reading the repo. Aimed at the level\nwhere a competent reader can understand each design choice without\nsource-diving, but with enough specificity (struct layouts, save\ncontract, render-loop pseudocode) that the design isn't waved at.\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["45c559f15d37aa1101b26e66f9647ff6cce95056"],"add":541,"del":0,"cadd":541,"cdel":0,"files":1},{"repo":"metabolic","hash":"42fc8029359357629e680fc024fd7d4fa7900a74","ts":1777250197,"wall":"2026-04-26T20:36","msg":"research: Phase F plan — true-runtime plate tectonics","body":"Plates with Euler poles and angular velocities. Cells get reassigned\nbetween plates as boundaries shift; new oceanic crust at rifts;\nsubduction at convergent boundaries; mountain building at continental\ncollisions. The biggest single phase since D — ~1,450 LOC, ~14 hours.\n\nArchitectural decisions:\n\n  - Cells stay fixed; plate IDs flow. The hex sphere is the simulator's\n    spatial primitive and never remeshes; \"drift\" is migration of\n    plate_id values across the static grid.\n\n  - plate_id: u16 on Cell; crust_age_myr and crust_type alongside.\n    Old oceanic crust subducts; continental crust is buoyant. Plate-\n    motion algorithm reads these.\n\n  - Two time scales, one slider. The simulation_speed slider controls\n    everything; plate motion runs every geological_tick_interval steps\n    (default 100). Decouples geological from ecological without adding\n    a second slider.\n\n  - Schema v1 → v2 migration: v1 saves load with a synthetic single\n    static plate. New saves include the plate state.\n\nPlate motion algorithm:\n  1. For each cell, velocity = cross(plate_axis, cell_pos) * omega\n  2. Per neighbour: project relative velocity onto boundary normal\n  3. Negative → divergent (rifting, new oceanic crust)\n     Positive → convergent (subduction or collision)\n     Zero    → transform (no normal motion)\n  4. Apply elevation effects + reassignment per case\n\nInitial plate generation: Voronoi seeds + per-plate Euler poles + 30%\ncontinental / 70% oceanic ratio (Earth-like). Plate count scales with\ndepth: ~7 at depth 4, ~15 at depth 5.\n\nNew files: plate.rs, tectonics.rs.\n\nOut of scope: rivers, erosion, volcanism beyond mountain building,\natmospheric coupling, plate creation/destruction during play, hotspots.\n\nAfter Phase F: G (atmosphere), H (eating), I (genetics), J (cell\ndesigner).\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["6881cdd9a24d26b97ef56aef2ee0287ab049f44c"],"add":383,"del":0,"cadd":383,"cdel":0,"files":1},{"repo":"metabolic","hash":"44e4845c79989c2b1c0393d720c11b03a0cef21f","ts":1777252834,"wall":"2026-04-26T21:20","msg":"phase F: true-runtime plate tectonics","body":"Plates with Euler poles. Cells reassign across plate boundaries as\nplates rotate. New oceanic crust at divergent boundaries; subduction\nat convergent boundaries; mountain building where continents collide.\nThe biggest single phase since D — ~1,300 LOC across two new modules\nplus changes to most of the engine.\n\nNew modules:\n\n  plate.rs      — Plate struct, Euler-pole math, CrustType enum, vec3\n                  helpers. velocity_at(position) computes cross product\n                  of (Euler axis × angular velocity) and the cell\n                  position; result is tangent to the sphere by\n                  construction. Test coverage for the math.\n\n  tectonics.rs  — run_geological_tick() implements boundary\n                  classification + elevation effects + cell reassignment.\n                  For each cell-neighbour pair on different plates,\n                  project relative velocity onto the boundary normal.\n                  Negative → divergent (rifting, new oceanic crust).\n                  Positive → convergent (uplift, subduction by crust\n                  type). Near zero → transform (no normal motion).\n                  Reassignment is probabilistic per tick weighted by\n                  motion magnitude.\n\nEngine integration:\n\n  - Cell gains plate_id, crust_age_myr, crust_type fields.\n  - HexPlanet gains plates: Vec<Plate>, geological_tick_counter,\n    geological_tick_interval (default 50), time_myr.\n  - step() runs the geological tick after the ecological update once\n    every geological_tick_interval steps. Reads cells (post-ecology),\n    writes cells_next, swaps. Same double-buffer pattern as ecology.\n\nSchema bump v1 → v2:\n\n  SavedPlanet gains plates, geological_tick_interval, time_myr; SavedCell\n  gains plate_id, crust_age_myr, crust_type. All marked\n  `#[serde(default)]` so v1 saves load with empty plates / static\n  geology and the engine treats them as \"no tectonics yet\" (the empty\n  plates list short-circuits the geological tick).\n\nPlate generation in scenarios:\n\n  earth_like     → 7 plates, mixed continental / oceanic\n  water_world    → 5 plates, mostly oceanic\n  mountain_world → 9 plates, mostly continental\n  daisyworld + flat scenarios → no plates (static, unchanged behaviour)\n\nVoronoi partition assigns each cell to its nearest plate centre. Plate\nparameters: random Euler poles, angular velocities in [1e-4, 5e-4]\nrad/dt, 30% Continental / 70% Oceanic distribution (Earth-like). Plates\nget evenly-spaced HSV hues for the plate-view colour map.\n\nWASM additions:\n  - WasmPlanet.plate_count() / .time_myr() accessors\n  - .write_plate_colors(buf) for the plate view\n\nFrontend additions:\n  - \"plates\" view in the view selector (alongside species / temperature)\n  - HUD readouts for plate count + geological time elapsed (Myr)\n\nTests: 54 (was 48, +6 from tectonics integration tests covering plate\ngeneration, daisyworld-has-no-plates, elevation-changes-over-time,\ntime advancement, save/load round trip, v1 backward-compat).\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["42fc8029359357629e680fc024fd7d4fa7900a74"],"add":973,"del":17,"cadd":973,"cdel":17,"files":11},{"repo":"metabolic","hash":"09fc0a8c82c9efa471a683e9d681829381d7d30f","ts":1777341528,"wall":"2026-04-27T21:58","msg":"phase F visual fixes: live mesh updates + bigger displacement","body":"The mountain rendering was broken in two places:\n\n1. Vertex positions never updated after scenario load. buildMesh()\n   read planet.positions() once (which baked in elevation displacement\n   from initial terrain), then never refreshed. Plate tectonics could\n   raise mountains in the data, but the mesh stayed flat — colours\n   updated each frame but vertices didn't move.\n\n2. Vertex normals never recomputed. Even if positions had updated,\n   computeVertexNormals() only fired at mesh build, so lighting\n   wouldn't reflect the new shape.\n\nFixes:\n\n  - WASM: write_positions(buf: &mut [f32]) — zero-allocation positions\n    writer paired with the existing colour writers.\n  - Frontend: pullColors() became pullState() — refreshes colours every\n    frame, refreshes positions and recomputes normals only when geology\n    has changed (planet.time_myr() advanced) or sea level was just\n    dragged. Position refresh is the expensive part (~5ms at depth 5\n    including normal recomputation), so we skip it on frames where\n    nothing geological happened.\n\nAlso:\n\n  - Displacement scale changed from 30,000 m → 12,000 m per unit of\n    sphere radius. At 30K, an 8 km mountain showed as 27% of radius —\n    technically there but visually understated. At 12K, the same\n    mountain shows as 67% — clearly mountainous. Earth's actual ratio\n    is ~0.14% (mountains are essentially invisible from orbit), so\n    we're exaggerating by ~10×, which is the right move for a planet\n    you're meant to read at a glance.\n\n  - Ocean cells now sit on the reference sphere regardless of their\n    underwater bathymetry — the rendered ocean surface looks flat,\n    matching real-water visual conventions. Sub-sea-level land\n    (continental basins below sea level) sinks correctly.\n\n  - Sea-level slider now flushes lastGeoTime so position refresh\n    happens on the next frame — drag the slider and watch the ocean\n    surface rise/fall in real time.\n\nOut of scope for this fix:\n\n  - The mesh still renders the icosahedron triangulation, not the\n    Goldberg dual hex tiles. Cells *are* triangle vertices, so\n    mountains spike at vertex points and the triangles between cells\n    create \"tent\" geometry. Rendering the dual mesh would be cleaner\n    but is its own substantial change.\n\nTests: 54, all green (no test surface changes).\n\nAuthored by Rowan Valle; Executed by Claude Code\nBy Symbiont Systems LLC","parents":["44e4845c79989c2b1c0393d720c11b03a0cef21f"],"add":72,"del":19,"cadd":72,"cdel":19,"files":2},{"repo":"operations","hash":"333c165316da56bb6a478e2492cc20d8380e685b","ts":1777424340,"wall":"2026-04-28T20:59","msg":"docs: dynamic project — vision and Phase 0 foundation plan","body":"dynamic-vision.md is the design constitution: thesis, methodology\ncontract, layer-stack architecture, geophysical + power topology\nlayer inventory, polyglot sources, naming rules, confidence rendering,\nuniversal layer object sketch, infrastructure (Postgres + PostGIS +\nAPI stack), roadmap, open questions.\n\ndynamic-foundation-plan.md sequences five phases to close Phase 0\ncleanly — functional fixes, documentation cleanup (including the\nClass/Mode terminology rename), architecture refactor, discipline\nscaffolding, production deployment.","parents":["ceb59a5abfe66eb33a91d86ebc42b67fd66fdfa4"],"add":935,"del":0,"cadd":935,"cdel":0,"files":2},{"repo":"dynamic","hash":"fd51e4d53980b5cd8336e0c54b69396657867c5a","ts":1777442554,"wall":"2026-04-29T02:02","msg":"feat: initial MVP — globe with animated GIBS IMERG precipitation overlay","body":"Mode-A pass-through globe. Cesium with EOX terrain (default), EOX\nterrain-light, EOX Sentinel-2 cloudless, and four NASA GIBS true-color\ndaily satellite base layers. Custom NominatimGeocoderService (no Ion\ntoken required). Categorized overlay panel collapsed by default.\n\nAnimated GPM IMERG (IMERG_Precipitation_Rate_30min) precipitation\noverlay with playback control:\n\n- Lazy ImageryLayer cache (one layer per frame, created on first show)\n- setTimeout chain instead of setInterval (next tick after current\n  shows; naturally pauses if loading is slow)\n- Alpha-only frame switching (no Cesium layer churn)\n- Custom GibsGeographicTilingScheme matching GIBS' non-standard\n  EPSG:4326 grid progression (2,3,5,10,20,40 cols / 1,2,3,5,10,20 rows\n  across levels 0-5) so the full globe — including Eastern Hemisphere\n  and Southern Hemisphere — aligns correctly\n\nCode/data separation: all provider definitions and layer parameters\nlive in YAML config under data/config/. The HTML is machinery only.","parents":[],"add":633,"del":0,"cadd":633,"cdel":0,"files":3},{"repo":"dynamic","hash":"6cf044f58d13cd5dc9f795091a43396b027bd2d4","ts":1777512976,"wall":"2026-04-29T21:36","msg":"feat: weather timeline, political layers, credits panel + bug fixes B1/B2","body":"Substantial multi-feature session culminating with the first round of\nremediation fixes from the bug audit at\noperations/.claude/plans/dynamic-bug-remediation.md.\n\nFrontend\n- Bloomberg-style weather timeline with its own clock, decoupled from\n  Cesium's clock (so future paleo-time slider can use Cesium clock\n  freely without conflict)\n- Smooth RAF-driven cross-fade animation; sub-frame fractional drag\n  with cross-fading between adjacent frames\n- Custom credits panel: small ⓘ button bottom-right, expand on hover,\n  Cesium credit container redirected via creditContainer option\n- Cesium chronograph hidden by default, reveals on cursor-near-bottom\n\nData layers\n- Political boundaries via Natural Earth 1:50m: countries (black),\n  disputed boundaries (carmine dashed), breakaway / de facto\n  unrecognized states (neon green dotted), PRC nine-dash line\n  (goldenrod dashed)\n- First Level Administrative Units (admin_1) at 1:10m, 4596 features\n  globally including Mexico's 33 states\n- Migrated radar from RainViewer (LFS / API discontinuation risk) to\n  NASA GIBS IMERG_Precipitation_Rate_30min (NASA-backed)\n- Custom GibsGeographicTilingScheme matching GIBS' non-standard\n  EPSG:4326 grid progression (2,3,5,10,20,40 cols across levels —\n  not the standard 2,4,8,16 doubling)\n- Self-hosted Natural Earth GeoJSON files under data/layers/political/\n\nArchitecture\n- New geojson and gibs_animated provider types in buildLayerController\n  dispatch\n- PolylineCollection primitive for vector layers (dramatically faster\n  than per-line entities for static borders)\n- Auto-refresh frame window for time-keyed layers, freshness indicator\n\nBug fixes from the audit\n- B1: Race condition in checkbox handler. User toggles ON→OFF before\n  the async build resolves; OFF branch sees null controller and does\n  nothing; ON await commits a controller the user no longer wants.\n  Fix: sequence-counter pattern. Stale controllers self-destruct.\n- B2: Drag stuck if cursor leaves the browser viewport. Replaced\n  mousedown/mousemove/mouseup triplet with Pointer Events +\n  setPointerCapture; OS-yanked pointers also handled via\n  pointercancel.","parents":["fd51e4d53980b5cd8336e0c54b69396657867c5a"],"add":636,"del":90,"cadd":631,"cdel":90,"files":7},{"repo":"dynamic","hash":"3511fa2eacf96b1cbdb7f67ea4170b83e01e550d","ts":1777513139,"wall":"2026-04-29T21:38","msg":"fix: bug remediation pass 2 — correctness and defensive checks","body":"From the audit at operations/.claude/plans/dynamic-bug-remediation.md.\n\nB3 + B9 — Cartesian3 batch + coordinate validation\n  Inner ring loop in createGeoJsonController. Replaced per-vertex\n  Cesium.Cartesian3.fromDegrees with a single batch call to\n  Cartesian3.fromDegreesArray over a pre-allocated flat array. Added\n  RFC 7946 shape validation: rings shorter than 2 positions skipped,\n  malformed coordinates within a ring break early and the partial\n  array gets trimmed. Type validation deferred (Natural Earth is\n  well-typed). Expected ~10–20% load-time reduction on the 39 MB\n  admin_1 file.\n\nB6 — gibsDate functional rewrite\n  Removed the local-Date mutation in the 'yesterday' branch\n  (d.setUTCDate(d.getUTCDate() - 1)) in favor of\n  new Date(Date.now() - 86400000). Same return values; cleaner\n  pattern; consistent with the 'today' branch.\n\nB7 — gibs provider field validation\n  Validate that layer.layer, layer.format, layer.resolution are all\n  present before constructing the URL. Replaces the silent failure\n  mode where missing fields produced 'undefined' substrings in URLs\n  and 404s on every tile. Throws with a clear error naming the\n  offending YAML layer ID.\n\nB21 — loadYaml response.ok check\n  fetch() resolves on non-2xx responses; .text() returned the HTML\n  404 body and jsyaml.load threw a confusing parse error pointing at\n  the < character. Added explicit response.ok check that throws with\n  status code and statusText.","parents":["6cf044f58d13cd5dc9f795091a43396b027bd2d4"],"add":36,"del":8,"cadd":36,"cdel":8,"files":1},{"repo":"dynamic","hash":"285efee651b231ccfb58a94ae50a79ebd82cb38b","ts":1777513511,"wall":"2026-04-29T21:45","msg":"refactor: extract buildUI() in createGibsAnimatedController + B23 comment","body":"B4 — Extract buildUI()\n  Previously the timeline DOM creation (ui/btn/strip/handle/etc.) was\n  inline at the top of the controller via `const`, with the\n  interactions block (click + Pointer Events) attached separately\n  several dozen lines later. Earlier-defined functions\n  (setFractionalPosition, rebuildTicks, updateUI) reached into those\n  consts via closure. Worked because functions don't execute until\n  called and by call-time the consts were initialized — but the\n  dependency was invisible to a reader and one reorder away from\n  TDZ-style breakage.\n\n  Refactor: declare the UI handles as `let` at the top of the\n  controller scope (next to other state vars), wrap DOM creation +\n  listener attachment in a single `buildUI()` function, call it as\n  the first init step. Behavior unchanged. Adds an explicit\n  invariant comment: buildUI() must run before rebuildTicks / show /\n  play / setFractionalPosition / etc.\n\nB23 — defaultIdx fallback comment\n  Document that `Math.max(0, defaultIdx)` is an intentional silent\n  fallback to the first base layer when no YAML entry has\n  `default: true`. No code change; just makes the design explicit.\n\n(B22 — delete unused _lines.geojson — already absorbed: the files\nwere cleaned up locally before the first session commit so they were\nnever tracked.)","parents":["3511fa2eacf96b1cbdb7f67ea4170b83e01e550d"],"add":85,"del":70,"cadd":85,"cdel":70,"files":1},{"repo":"dynamic","hash":"5c35eb4c50b31ab31ceece94102a90ec2555e054","ts":1777515065,"wall":"2026-04-29T22:11","msg":"feat(palette): Phase A — search palette with countries index","body":"Per /home/Valis/.claude/plans/dynamic-search-palette.md.\n\nCtrl+K opens a command-palette overlay. FlexSearch-backed index of\nall 250 countries from ne_50m_admin_0_countries.geojson loaded at\nboot, regardless of whether the existing global \"International\nborders\" overlay layer is toggled on. Type to filter; arrow keys to\nnavigate; Enter toggles that country's border (the primary action).\n\nActive layers appear as orange-bordered pills in a top-center strip;\nclick a pill to toggle its layer off. Strip hides when empty.\n\nWAI-ARIA combobox semantics: role=\"combobox\" on input,\nrole=\"listbox\" on list, aria-activedescendant updates as the\nhighlighted option changes. Keyboard model matches W3C APG: ↑/↓\nnavigate, Enter selects, Esc closes. Click-outside closes too.\n\nBorders rendered as standalone PolylineCollection primitives per\ncountry (orange-amber to distinguish from the global black layer).\nCoexists with the existing checkbox panel toggle — Phase D will\ndecide whether to retire the legacy panel.\n\nPhase B (action registry + admin_1 + multi-action UI), Phase C\n(empty-state recents/categories), Phase D (slash commands), Phase E\n(admin_2 via Overture S3) follow.","parents":["285efee651b231ccfb58a94ae50a79ebd82cb38b"],"add":439,"del":0,"cadd":439,"cdel":0,"files":1},{"repo":"dynamic","hash":"6335e54e6e8cef214682956c0d2cefdb81eafa63","ts":1777515704,"wall":"2026-04-29T22:21","msg":"feat(palette): Phase B — action registry + admin_1 + multi-action picker","body":"Per /home/Valis/.claude/plans/dynamic-search-palette.md.\n\nAction registry. Each action declares { label, applies, isActive,\ninvoke }. Three actions for type 'country' — toggle_border,\ntoggle_admin_1, fly_to. Two for type 'admin_1' — toggle_admin_1_unit,\nfly_to. Generic toggleLayer() helper for border-style actions; one\nbuildLinePrimitive() reused across all of them.\n\nEntity-type registry. Each type registers a label, primaryActionId,\nand ordered actionIds list. The palette resolves the primary action\nby type at Enter time; the action picker (→) shows the full list.\n\nAdmin_1 index lazy-loaded in background after countries finish.\n4596 features indexed by name / name_en / admin / iso_3166_2 with\nFlexSearch. Keyed by ADM0_A3 for country lookup. Country file uses\nuppercase ADM0_A3, admin_1 uses lowercase adm0_a3 — same values,\njust different property-name case; cross-lookup works.\n\nMulti-action picker UI. Right arrow on a highlighted result expands\ninto the action list for that entity. ↑/↓ navigate actions, Enter\ninvokes, Left arrow / Esc returns to results. Typing while in picker\nexits the picker.\n\nSearch is now cross-index. searchAll() merges results from countries\nand admin_1 with deduplication. Type \"Sonora\" → finds the Mexican\nstate. Type \"Mexico\" → finds the country (and any admin_1 with\n\"mexico\" in its name field).\n\nActive-strip pills now invoke the same action that activated them.\nAction handlers are isActive-aware so the same invoke() toggles\non or off depending on current state. No bespoke per-action toggle\ncode in the strip.","parents":["5c35eb4c50b31ab31ceece94102a90ec2555e054"],"add":374,"del":66,"cadd":374,"cdel":66,"files":1},{"repo":"dynamic","hash":"eb179a4ae3a10115cdfef222afbd9cefe2782ba9","ts":1777516813,"wall":"2026-04-29T22:40","msg":"feat(palette): Phase C — empty-state defaults + split pill click","body":"Per /home/Valis/.claude/plans/dynamic-search-palette.md.\n\nEmpty-state palette (no input typed) renders three sections:\n\n- Recent — last 6 toggled entities, persisted to localStorage under\n  `dynamic.palette.recent`. Survives page reloads.\n- Near your view — countries whose Natural Earth label point falls\n  inside `viewer.camera.computeViewRectangle()`, sorted by distance\n  to view center, capped at 8. Excludes recents to avoid duplication.\n- Browse — informational counts only (\"Countries (242)\", \"States,\n  provinces, regions (4596)\"). Not navigable. Phase D's slash\n  commands will give them invocation behavior.\n\nFallback: if no recents and camera doesn't see any countries (e.g.,\ncamera over open ocean), shows alphabetical first 25.\n\nActive-strip pills now have split click behavior:\n- Click × → re-invoke the action (which is currently active, so it\n  toggles off).\n- Click pill body → fly camera to entity. Title attribute hints both.\n\nrecordRecent hooked into all action-invocation paths from the palette\n(Enter on result, click on result, Enter in action picker, click in\naction picker). Pill × clicks intentionally don't record (the user\nis removing the layer, not engaging with the entity).\n\nSection headers and browse rows are non-navigable (no role=\"option\");\nthe existing keyboard nav already iterates only `[role=\"option\"]`\nitems, so navigation skips them naturally.","parents":["6335e54e6e8cef214682956c0d2cefdb81eafa63"],"add":209,"del":47,"cadd":209,"cdel":47,"files":1},{"repo":"dynamic","hash":"4386f761abbe4a7ec69345cae4c5b2c5881741f1","ts":1777521905,"wall":"2026-04-30T00:05","msg":"feat(palette): Phase D — slash commands; retire Earth Observation panel","body":"Per /home/Valis/.claude/plans/dynamic-search-palette.md.\n\nThe legacy \"Earth Observation\" checkbox panel is gone. Its YAML-driven\nlayers (international borders / disputed / breakaway / nine-dash /\nadmin_1 worldwide / IMERG radar) now register as slash commands at\nboot. Per-country granularity (Mexico's borders alone) continues to\ngo through the entity-action path; the global \"all countries\" toggle\nbecomes :countries.\n\nCommands registry. Each command:\n  { name, label, description, isActive(), invoke() }\nSlash-prefix routing in the palette: typing `:` switches the result\nlist to command mode; `:` alone shows the full command list; `:imerg`\nfilters by name or label; Enter invokes; ● shows currently-active.\n\nAuto-registration. One command per YAML overlay layer; name auto-\nderived from the layer ID by stripping `ne-` / `gibs-` prefixes:\n\n  :countries        ne-countries\n  :disputed         ne-disputed\n  :breakaway        ne-breakaway\n  :chn-nine-dash    ne-chn-nine-dash\n  :states-provinces ne-states-provinces\n  :imerg-30min      gibs-imerg-30min\n\nEach command toggles its layer through buildLayerController (the same\ndispatch path the checkbox panel used). Sequence-counter race\nprotection preserved per-command. globalLayerControllers Map tracks\nthe live controllers for the on-state check.\n\nBuilt-in system commands:\n  :hide-all       Toggle off every active layer (per-entity + global).\n  :hide-political Toggle off only sovereignty-related layers.\n  :reset          :hide-all then flyHome.\n\nActive strip now shows pills for both per-entity layers and global\nYAML layers. × on either removes; pill body flies to (per-entity\nonly — global pills have nothing to fly to).\n\nEnter and ArrowRight in the palette now dispatch on result type.\nCommands are atomic (no action picker; ArrowRight is a no-op on\nthem). Entities get the existing action-picker / primary-action\ndispatch unchanged.","parents":["eb179a4ae3a10115cdfef222afbd9cefe2782ba9"],"add":214,"del":185,"cadd":214,"cdel":185,"files":1},{"repo":"dynamic","hash":"d9cebf3879f14ddb99b6805fc291dc07e3a4f9c8","ts":1777522296,"wall":"2026-04-30T00:11","msg":"feat(palette): explicit YAML `command:` field; rename IMERG to :weather","body":"commandNameFromLayer() now checks for an explicit `command:` field on\nthe YAML overlay layer and uses it as the command name. Falls back to\nthe auto-derived name (id minus `ne-` / `gibs-` prefix) when absent,\nso existing layers without the field keep their current command names.\n\nSet `command: weather` on the IMERG layer per operator preference.\nThe radar overlay is now invoked as `:weather` instead of the auto-\nderived `:imerg-30min`. Other layers unchanged.\n\nPattern is extensible — other layers can opt into nicer names by\nadding the same field.","parents":["4386f761abbe4a7ec69345cae4c5b2c5881741f1"],"add":4,"del":0,"cadd":4,"cdel":0,"files":2},{"repo":"dynamic","hash":"c4b21c137d289e0e1bf3309862bd5c86a5f95680","ts":1777522654,"wall":"2026-04-30T00:17","msg":"docs(palette): clean up layer command names + commands.md reference","body":"YAML layer commands renamed for clarity:\n  ne-countries        :borders   (was :countries; matches per-country toggle_border action)\n  ne-disputed         :disputed   (unchanged)\n  ne-breakaway        :breakaway  (unchanged)\n  ne-chn-nine-dash    :nine-dash  (was :chn-nine-dash)\n  ne-states-provinces :admin1     (was :states-provinces; matches toggle_admin_1 action)\n  gibs-imerg-30min    :weather    (was :imerg-30min — already shipped)\n\nAll six layer commands now have explicit `command:` fields in the\nYAML rather than relying on auto-derivation. The auto-derivation\nfallback remains for any future YAML entry that omits the field.\n\ndocs/commands.md documents:\n  - Keyboard shortcuts\n  - System commands (built-in)\n  - Layer commands (auto-registered from YAML, with sources)\n  - Entity actions (per-entity granularity, not commands)\n  - Active-layers strip behavior\n  - Empty palette state contents","parents":["d9cebf3879f14ddb99b6805fc291dc07e3a4f9c8"],"add":89,"del":0,"cadd":89,"cdel":0,"files":2},{"repo":"dynamic","hash":"ed351a430048a68e2d1e7952ef00fc58d9ced71d","ts":1777523861,"wall":"2026-04-30T00:37","msg":"feat(palette): Phase E — admin_2 via Overture Maps","body":"Per /home/Valis/.claude/plans/dynamic-search-palette.md.\n\nscripts/fetch_admin_2.py — DuckDB pipeline that pulls a single\ncountry's admin_2 boundaries from Overture Maps' divisions theme on\nAWS S3 (cert verified clean past Securly intercept) and writes\ndata/layers/political/admin_2/{ISO_A3}.geojson.\n\nSubtype filter: 'county' and 'localadmin'. Pass ISO-A3 codes:\n  python scripts/fetch_admin_2.py USA\n  python scripts/fetch_admin_2.py MEX FRA BRA\n\nInitial fetch: USA (3,133 counties, 690 KB) and MEX (2,475 municipios,\n574 KB). Self-hosted; future countries via the same script.\n\nJS additions:\n  loadAdmin2ForCountry(iso3)  — lazy fetch + index + cache. First\n    invocation per country fetches the GeoJSON, indexes it via\n    FlexSearch (admin2Index), and remembers it in admin2Loaded.\n  registerAction('toggle_admin_2')      — on country entity type;\n    awaits the lazy load, then renders all that country's admin_2\n    features in pink.\n  registerAction('toggle_admin_2_unit') — on admin_2 entity type;\n    renders one county's outline.\n  registerEntityType('admin_2', …)      — searchable entity type.\n    Becomes searchable after a country's admin_2 is loaded.\n  Country actionIds gain 'toggle_admin_2' between toggle_admin_1\n    and fly_to.\n  searchAll() now also queries admin2Index.\n  makeResultRow() shows the parent country's name as context for\n    admin_2 entities.\n\nType \"Yolo\" in palette → finds Yolo County (after USA admin_2 has\nbeen loaded once). Type \"USA\", press →, choose \"Toggle counties /\ndistricts\" → all 3,133 US counties render. Type \"Ciudad Juárez\" →\nfinds the Mexican municipio after MEX admin_2 has been loaded.\n\ndocs/commands.md updated with the Phase E entity-action additions\nand a new section explaining how to fetch admin_2 via the script.","parents":["c4b21c137d289e0e1bf3309862bd5c86a5f95680"],"add":265,"del":5,"cadd":263,"cdel":5,"files":5},{"repo":"dynamic","hash":"0a0698769f1f0f69cbd71136d32da617bc2e77b4","ts":1777524179,"wall":"2026-04-30T00:42","msg":"fix(fetch_admin_2): LOAD-only with INSTALL fallback","body":"INSTALL forces a network roundtrip to extensions.duckdb.org on every\nrun, which Securly intercepts on library wifi. Try LOAD first; fall\nback to INSTALL only if the extension is genuinely missing.\n\nPre-fetched Canada (1,534 features, 352 KB) as the verification run.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ed351a430048a68e2d1e7952ef00fc58d9ced71d"],"add":10,"del":2,"cadd":9,"cdel":2,"files":2},{"repo":"dynamic","hash":"fcd05450246509866cadbc3a5db15d474f3dd826","ts":1777524477,"wall":"2026-04-30T00:47","msg":"data: admin_2 for FRA, DEU, GBR, IND, AUS","body":"Pre-fetched five priority countries via Overture Maps. Counts:\n  FRA — 417 (arrondissements)\n  DEU — 399 (Kreise / Landkreise)\n  GBR — 216 (counties / unitary auths)\n  IND — 780 (districts)\n  AUS — 599 (LGAs)\n\nBRA skipped: Overture has no admin_2 subtype for Brazil. Hierarchy\ngoes region (27 states) → locality (84K settlements). Brazilian\nmunicípios (5,570) would need a separate IBGE pipeline.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["0a0698769f1f0f69cbd71136d32da617bc2e77b4"],"add":5,"del":0,"cadd":0,"cdel":0,"files":5},{"repo":"dynamic","hash":"f08cbd509759b476a2caf7450a8293f170272b74","ts":1777570332,"wall":"2026-04-30T13:32","msg":"fix(admin_2): query division_area for polygons + eager-load via manifest","body":"Two bugs that together kept admin_2 from working at all:\n\n1. Wrong Overture table. The script was querying theme=divisions/\n   type=division, which only contains representative-point Points\n   per division. ringsFromGeometry returned [] for every Point and\n   the polyline collection was empty — toggle pills appeared but\n   nothing rendered. Switched to type=division_area (the polygon\n   table) and added ST_Simplify(0.001) to keep file size sane\n   (USA dropped 97 MB → 12 MB) plus dedup-by-division_id since\n   Overture splits some divisions into multiple area rows\n   (e.g. Hawaiʻi County → one polygon per island group).\n\n2. Counties weren't searchable until you bulk-toggled a country.\n   The 'toggle_admin_2' action was the only path to populate the\n   admin_2 search index, which meant typing 'Yolo' before clicking\n   'Toggle counties / districts' on USA returned nothing. Added\n   manifest.json (auto-written by fetch_admin_2.py) and an\n   eager-loader that pulls every available country into the search\n   index after first idle, so individual counties are reachable\n   by name without invoking the country-level toggle first.\n\nPlus retry logic in the fetch script (library wifi drops S3\nconnections mid-stream) and a LOAD-only path for duckdb extensions\n(INSTALL forces a network roundtrip Securly intercepts).\n\nEight countries on disk: USA, MEX, CAN, FRA, DEU, GBR, IND, AUS.\n~52 MB total, loaded after first idle.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["fcd05450246509866cadbc3a5db15d474f3dd826"],"add":108,"del":20,"cadd":99,"cdel":12,"files":11},{"repo":"dynamic","hash":"fee6b9f86cff8e40689432c6cdebe21c1db35dcf","ts":1777571059,"wall":"2026-04-30T13:44","msg":"fix(imagery): kill lighting/atmosphere, move daily MODIS/VIIRS to overlays","body":"Three problems on the daily satellite views:\n\n1. Sun-based shading (globe.enableLighting=true) darkened the night\n   hemisphere to near-black and banded the terminator. On MODIS/VIIRS\n   the result looked like a distorted, washed-out mess. Disabled it,\n   and turned off ground-atmosphere haze too. Sky atmosphere kept —\n   it's pure cosmetic at the limb and doesn't touch surface tiles.\n\n2. MODIS/VIIRS daily layers have inherent orbit-swath gaps — single-\n   pass sensors can't cover the whole globe in 24h. Used as base\n   layers, gaps showed black. Moved them out of imagery-base.yaml\n   into imagery-overlays.yaml as `:modis-terra`, `:modis-aqua`,\n   `:viirs-snpp`, `:viirs-noaa20` slash commands. They now stack\n   atop whichever base is picked, so the gaps reveal the base.\n\n3. Added Blue Marble (NASA) and Blue Marble + Bathymetry as base\n   options. Static, gap-free, ideal under the daily overlays.\n\nTile matrix verified against live GIBS WMTS Capabilities — 250m has\n9 levels (max_level: 8), 500m has 8 levels (max_level: 7), tiles are\n512x512 in the [2,3,5,10,20,40,80,160,320] / [1,2,3,5,10,20,40,80,160]\nprogression. GibsGeographicTilingScheme matches.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["f08cbd509759b476a2caf7450a8293f170272b74"],"add":92,"del":41,"cadd":92,"cdel":41,"files":4},{"repo":"dynamic","hash":"0a0e8cfb6e58b78d66d7bdd146ff148b28f4f2cf","ts":1777575864,"wall":"2026-04-30T15:04","msg":"ui(toolbar): hide default Cesium chrome, surface as palette commands","body":"The default top-right toolbar (search, home, scene-mode, base-layer,\nhelp) was visually inconsistent with the rest of the app — chunky\nlight-themed buttons sitting next to the dark palette + pill UI.\n\nHidden in the Viewer constructor (geocoder, homeButton, sceneModePicker,\nnavigationHelpButton, fullscreenButton). baseLayerPicker stays on so\nimageryProviderViewModels are wired up; its DOM container is hidden via\nCSS, and base swapping happens through the new commands.\n\nNew palette commands:\n  :home              fly camera to default world view\n  :scene-3d/2d/columbus    swap scene mode\n  :base-terrain      base layer: EOX Terrain (default)\n  :base-terrain-light    base: EOX Terrain Light\n  :base-s2-cloudless    base: Sentinel-2 Cloudless 2024\n  :base-blue-marble    base: NASA Blue Marble (static)\n  :base-blue-marble-bathy    base: Blue Marble + Bathymetry\n\nSingle UI surface — Ctrl+K opens everything.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["fee6b9f86cff8e40689432c6cdebe21c1db35dcf"],"add":76,"del":4,"cadd":76,"cdel":4,"files":2},{"repo":"dynamic","hash":"749d59a5a1c299d6581ae534462d16f0ad320825","ts":1777576336,"wall":"2026-04-30T15:12","msg":"fix(palette): perfect 'Near your view' computation","body":"Six bugs in the original countries-only function — the section was\nreturning wrong / no / misleading results in common cases:\n\n1. Antimeridian wrap silently broke. When the camera spanned 180°\n   the rectangle wraps (west > east) and the lon < west || lon > east\n   filter excluded everything. Russia, Fiji, NZ, Pacific countries\n   never appeared. Now uses a wrap-aware lonInRect(lon, w, e).\n\n2. Distance metric over-weighted longitude near the poles. Raw\n   hypot(dLon, dLat) treats degrees as Cartesian — at lat 70° one\n   longitude degree is ~0.34 of a latitude degree in real distance,\n   so the sort surfaced wrong neighbors. Now multiplies dLon by\n   cos(mean lat) — accurate enough for sort ordering, cheap.\n\n3. Center longitude was wrong on wrap. (west+east)/2 with west=170,\n   east=-170 returned 0° — the antipode of the actual center (180°).\n   Now wraps before averaging then normalizes back to [-180, 180].\n\n4. admin_1 was never included. When zoomed to a single country, the\n   section showed only \"United States\" (already obvious) instead of\n   the visible states. Now: for view spans < 30°, admin_1 entities\n   are mixed in alongside countries.\n\n5. Missing label-point fallback. admin_1 entities had no lon/lat at\n   all because the loader didn't capture NE10m's `latitude` /\n   `longitude` properties (admin_0 uses LABEL_X / LABEL_Y, admin_1\n   uses lower-case latitude/longitude — different names, same data).\n   Now captured.\n\n6. Global-view noise. Fully zoomed-out view rectangle ~360×180°\n   matches every country; the \"closest to (0,0)\" sort returned\n   arbitrary central-Africa entries. Suppressed entirely when\n   width ≥ 270° or height ≥ 150°.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["0a0e8cfb6e58b78d66d7bdd146ff148b28f4f2cf"],"add":49,"del":11,"cadd":49,"cdel":11,"files":2},{"repo":"dynamic","hash":"0f5d5f848d96d6b575743f6f3f63ed657b460e88","ts":1777576693,"wall":"2026-04-30T15:18","msg":"fix(palette): replace rectangle math with screen-space projection","body":"Two ways the rectangle approach failed:\n\n1. computeViewRectangle() returns undefined whenever any of the four\n   frustum-corner rays misses the ellipsoid silhouette — the home\n   view, any tilt that puts the horizon on screen, any high-altitude\n   shot. Section silently empty in those states even before my\n   previous changes.\n\n2. My added widthDeg ≥ 270 || heightDeg ≥ 150 suppression killed it\n   for the (valid) global view case too, when the rectangle did come\n   back well-formed. That's the \"section disappeared entirely\" report.\n\nNew approach: project each label point through Cesium's actual scene\nprojection (SceneTransforms.wgs84ToWindowCoordinates), occlusion-test\nagainst the ellipsoid (EllipsoidalOccluder, 3D mode only), filter by\ncanvas viewport, sort by pixel distance to center. Works in every\ncamera state, every scene mode; antimeridian/poles owned by Cesium.\n\nadmin_1 inclusion now adapts to what's actually visible: if ≤ 5\ncountries project on-screen, admin_1 joins the candidate pool.\nReplaces the fragile widthDeg < 30 threshold which fired wrong for\noblique camera angles.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["749d59a5a1c299d6581ae534462d16f0ad320825"],"add":35,"del":43,"cadd":35,"cdel":43,"files":2},{"repo":"dynamic","hash":"c1f0e4a7b1f95d9c577537ef25eaaa73bd8dcb73","ts":1777577831,"wall":"2026-04-30T15:37","msg":"fix(palette): correct API name + 3D bounding sphere fly-to","body":"Two bugs, both replaced with the right primitives instead of patches.\n\n1. 'Near your view' was empty because the projection call referenced\n   SceneTransforms.wgs84ToWindowCoordinates, which was renamed to\n   worldToWindowCoordinates in Cesium 1.107 and removed entirely. The\n   undefined function threw on the first entity considered, dropping\n   the whole section. Renamed to the live API. Verified against\n   engine source at the v1.122 tag (Source/Scene/SceneTransforms.js:46).\n\n2. flyToEntity was building a lat/lon bbox via min/max walk, then\n   handing it to Rectangle.fromDegrees. Antimeridian-crossing entities\n   (Fiji, Russia, Kiribati, the Aleutian-extended USA) produced the\n   long-way-round 350°-wide rectangle, flying the camera to the\n   antipode — Fiji's flyTo landed in the South Atlantic.\n\n   Replaced with BoundingSphere.fromPoints over the ring vertices'\n   3D Cartesians, fed to camera.flyToBoundingSphere. 3D ECEF space\n   has no antimeridian and no polar singularity — wrap is purely a\n   lat/lon coordinate-system artifact. Cesium's native frame-this\n   primitive computes ideal range from the sphere automatically and\n   handles 2D / Columbus modes internally.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["0f5d5f848d96d6b575743f6f3f63ed657b460e88"],"add":20,"del":10,"cadd":20,"cdel":10,"files":1},{"repo":"dynamic","hash":"4b0fd0f7cf73a63e8940485e7a6bb221c26df2b5","ts":1777578844,"wall":"2026-04-30T15:54","msg":"feat(labels): political + cartographic name rendering","body":"Both name layers the operator asked for, in one architecture:\n\nPOLITICAL (existing data, no new fetches):\n  - country labels (~250) at NE LABEL_X / LABEL_Y\n  - admin_1 labels (~4,596) at NE latitude / longitude\n  - admin_2 labels (~6,460 across 8 loaded countries) at 3D-centroid\n    of the polygon — antimeridian-agnostic, same trick flyToEntity uses\n\nCARTOGRAPHIC (3 new Natural Earth 1:50m geojsons, ~6 MB total):\n  - 118 oceans / seas / gulfs / bays (geography_marine_polys)\n  - 522 continents / deserts / plateaus / plains (geography_regions_polys)\n  - 1,251 cities (populated_places_simple)\n\nEach category is its own Cesium LabelCollection so toggles are clean.\nVisibility ranges use Cesium's DistanceDisplayCondition mapped from\nNatural Earth's editorial min_label / max_label zoom hints (where the\ndata ships them) or hand-tuned tiers (for political). Result: country\nnames appear at globe-view, fade out as you zoom in; admin_1 fades in\nmid-range; admin_2 + cities at street-range. Marine and region names\nappear at appropriate scales without flooding.\n\nThree slash commands:\n  :labels                  — toggle every collection (default: on)\n  :labels-political        — country / admin_1 / admin_2 only\n  :labels-cartographic     — marine / regions / cities only\n\nVisual hierarchy:\n  marine    light blue italic serif\n  region    light gray bold sans\n  country   amber bold serif\n  admin_1   amber regular sans, smaller\n  admin_2   amber thin sans, smallest\n  city      white sans with right-pixel offset\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c1f0e4a7b1f95d9c577537ef25eaaa73bd8dcb73"],"add":283,"del":0,"cadd":280,"cdel":0,"files":5},{"repo":"dynamic","hash":"4aba6cf2336bcbe0fa3907c14ebc9a92e63aa249","ts":1777579237,"wall":"2026-04-30T16:00","msg":"fix(palette): add Ctrl+/ and / fallbacks for Brave/Chrome users","body":"Brave routes Ctrl+K to the omnibox in search-shortcut mode at the\nbrowser-chrome layer — preventDefault() in our keydown handler can't\ncancel it because it's an accelerator, not a content event. Same\nbehaviour shows up in some Chrome configurations.\n\nThree bindings now open the palette:\n  Ctrl/Cmd+K     convention (works in most browsers; not Brave)\n  Ctrl/Cmd+/     VSCode-style; never reserved at the browser layer\n  /              GitHub-style single-key; gated on focus not being\n                 in a text input so it doesn't eat slashes typed in\n                 the palette itself or any other field\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["4b0fd0f7cf73a63e8940485e7a6bb221c26df2b5"],"add":22,"del":3,"cadd":22,"cdel":3,"files":2},{"repo":"dynamic","hash":"616ba36eb1adb2a964917e91912b89f7f2cad76b","ts":1777579513,"wall":"2026-04-30T16:05","msg":"fix(labels): defer .then() wiring until after promises are declared","body":"TDZ error: the labels block sits right after the viewer constructor,\nbut countriesIndexReady / admin1IndexReady / admin2IndexReady are\nconst-declared in their respective loader blocks ~250 lines further\ndown. Calling .then() on them in the labels block tripped the const\ndead zone before initialization.\n\nHelpers, style constants, label collections, build* functions, and\nthe cartographic loader stay where they are — none of those touch\nthe country/admin_1/admin_2 promises directly. Only the three\n.then(buildXLabels) calls are relocated to after the admin_2 eager\nload setup, which is the first point where all three promises exist.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["4aba6cf2336bcbe0fa3907c14ebc9a92e63aa249"],"add":14,"del":5,"cadd":14,"cdel":5,"files":1},{"repo":"dynamic","hash":"d13278abc9095aae69dd22808e86e0f8b7080292","ts":1777665726,"wall":"2026-05-01T16:02","msg":"feat(labels): per-entity name toggle, coupled with borders, Carpenter HUD","body":"Names are now first-class per-entity toggles, the same UX model as\nborders / layers / everything else in the app. No more eager-populated\nauto-zoom-tiered labels.\n\nCoupling: for political entities (country / admin_1 / admin_2) the\nborder outline and the name label are aspects of the same entity, so\nthey're toggled as one unit via toggle_outline. Single pill in the\nactive strip, single click to remove both.\n\nCartographic entities (ocean / sea, geographic region, city) become\nfirst-class searchable entities — each gets its own *ById Map and\nFlexSearch index. Type \"Pacific Ocean\" → Enter → label appears at the\nocean's 3D centroid (antimeridian-agnostic via BoundingSphere). Toggle\noff via the pill × button. Same for \"Sahara\", \"Tokyo\", \"Andes\",\n1,251 cities, 522 regions, 118 named bodies of water.\n\nTypography (Carpenter-era HUD lineage):\n  Orbitron      political, geometric sci-fi sans (Eurostile-alike)\n  Share Tech Mono  cartographic, terminal mono (signals physical-vs-political)\nBoth Google Fonts, both load via preconnect at boot. No outline /\nhalo / pill — pure FILL on the dark globe. The amber/cyan/sage/white\ncolor picks contrast naturally with the EOX terrain default.\n\nRefactored toggleLayer to accept either a Cesium primitive (the\noriginal border-only path) or an aggregate object with destroy() —\nthe latter handles the coupled border+label case cleanly without\ntouching the simple paths.\n\nRemoved the bulk :labels / :labels-political / :labels-cartographic\ncommands — inconsistent with the per-entity model. If you want every\ncountry's name visible, you toggle them; if you want them gone, the\npill × removes them.\n\nCartographic entities are also now part of \"Near your view\": marine\nand regions always; admin_1, admin_2, and cities when ≤5 countries\nare projected on screen (zoom-in regime).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["616ba36eb1adb2a964917e91912b89f7f2cad76b"],"add":377,"del":252,"cadd":377,"cdel":252,"files":2},{"repo":"dynamic","hash":"4eb836aeb424f52a6455db04d938204bdf5a820e","ts":1777666309,"wall":"2026-05-01T16:11","msg":"feat(colors): user-customizable palette for every visible color","body":"Adds a `:colors` command that opens a sectioned color picker — system\nHTML5 color wheel + alpha slider per entry. Every visible color in the\napp is now tunable:\n\n  Per-entity outlines (3)\n    country / admin_1 / admin_2 borders\n\n  Per-entity labels (6)\n    country / admin_1 / admin_2 / marine / region / city names\n\n  Bulk political toggles (2)\n    a country's whole admin_1 set, a country's whole admin_2 set\n\n  Global overlay layers (5)\n    :borders, :admin1, :disputed, :breakaway, :nine-dash\n\n  UI accents (4)\n    pill text, pill border, pill hover border, palette accent\n\nArchitecture:\n\n  COLOR_DEFAULTS holds factory values; colorSettings is the live map\n  (defaults overridden by localStorage at boot). The panel writes back\n  on every input/change event, persists, and rebuilds whatever's\n  currently rendered:\n    - UI keys             → applyUiColors() updates :root CSS vars\n    - global_<layerId> keys → rebuildGlobalLayers() toggles each off+on\n    - everything else     → rebuildActiveLayers() toggles per-entity\n                             primitives off+on\n  All three rebuilds use the existing toggle mechanism, so no new\n  destroy/build paths to maintain.\n\n  CSS for pills and palette accents now reads from --ui-* custom\n  properties on :root. createGeoJsonController honors a\n  `colorSettings['global_' + layer.id]` override before falling back\n  to the YAML stroke value, so YAML stays the default but never the\n  ceiling.\n\n  Esc closes the panel. Backdrop-click closes. Reset-to-defaults\n  button restores every color in one go.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d13278abc9095aae69dd22808e86e0f8b7080292"],"add":392,"del":78,"cadd":392,"cdel":78,"files":2},{"repo":"dynamic","hash":"c548fbe7994ae401fc2c50ca34e753a31f818f74","ts":1777667188,"wall":"2026-05-01T16:26","msg":"fix(colors): rewrite panel as <dialog>, side-mounted, non-modal","body":"The previous panel was a <div hidden> with hardcoded display: flex\nand pointer-events: auto covering the entire viewport. The id-selector\nspecificity beat the UA's [hidden] rule, so the panel rendered even\nwhen \"hidden\" — capturing every mouse event before it reached the\nCesium canvas. Pan and zoom died.\n\nPatching the [hidden]/display battle would have left a hand-rolled\nmodal pretending to be a div. The right primitive is <dialog>:\n\n  - Browser owns visibility via the native [open] attribute. The UA\n    stylesheet's `dialog:not([open]) { display: none }` lives in a\n    separate spec layer and can't be accidentally overridden — the\n    whole class of bug we just hit cannot recur.\n  - Top-layer rendering. No z-index battles.\n  - .show() opens non-modally — no backdrop, page behind stays fully\n    interactive. The operator can pan / zoom the globe while editing\n    colors and watch the changes live, which is the actual job of a\n    color editor.\n  - Implicit ARIA role=\"dialog\", focus management.\n\nRepositioned as a side panel on the right edge (top: 60px, right:\n16px, width 400px max) instead of the centered modal it was. That\nmatches the non-modal \"Photoshop palette\" feel — open, work in the\nglobe, edit a color, observe, repeat. No close-to-pan friction.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["4eb836aeb424f52a6455db04d938204bdf5a820e"],"add":35,"del":17,"cadd":35,"cdel":17,"files":1},{"repo":"dynamic","hash":"f406401f38b203165768da8c615efb1ed4db1374","ts":1777667548,"wall":"2026-05-01T16:32","msg":"feat(colors): per-entity color overrides","body":"A new customize_colors action on every entity type. Picks the entity\nout of the palette → action picker → \"Customize colors\" → opens a\nside panel on the LEFT edge (the global :colors panel is on the right;\nboth can be open simultaneously without overlapping). Choose this\ncountry's amber, this state's neon green, this ocean's cyan. Override\nwins over the category default; \"Reset to defaults\" removes it.\n\nMechanics:\n  - entityColorOverrides Map<'<type>:<id>', {outline?, label?}>,\n    persisted to localStorage under dynamic.entity_colors.\n  - entityColor(entity, kind) resolver — override-first, fall back to\n    colorSettings[type+'_'+kind]. Used by buildOutline() and\n    labelStyle(entity), so anywhere a color is read it goes through\n    the resolver.\n  - rebuildEntityActiveLayers(entity) toggles ONLY this entity's active\n    primitives off+on, so a tweak on one country doesn't churn every\n    other one.\n\nPanel chassis is the second native <dialog>, shown via .show() like\nthe global one — non-modal, doesn't block the globe, no [hidden]\nspecificity traps. Cartographic entities (marine/region/city) only\nexpose a label color since they have no border concept; political\nentities expose both.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c548fbe7994ae401fc2c50ca34e753a31f818f74"],"add":214,"del":17,"cadd":214,"cdel":17,"files":2},{"repo":"dynamic","hash":"0bfa4c6d82e99a27ce2d9c264755e6d63c3b1de6","ts":1777668607,"wall":"2026-05-01T16:50","msg":"feat(fonts): per-category + per-entity font customization","body":"Every label is now swappable to a different family via the same\npanels that already handle colors:\n\n  Global :colors panel — Fonts section with one <select> per\n  category (country / admin_1 / admin_2 / marine / region / city).\n\n  Per-entity Customize colors action — a Font row in the entity\n  override panel.\n\nThe pick goes through a 14-font curated roster:\n\n  Orbitron            geometric sci-fi sans (default for political)\n  Share Tech Mono     terminal mono (default for cartographic)\n  VT323               CRT phosphor terminal\n  Major Mono Display  heavy industrial mono\n  Audiowide           display sci-fi\n  Bungee              heavy display\n  Press Start 2P      8-bit pixel\n  Special Elite       typewriter\n  JetBrains Mono      programmer mono\n  IBM Plex Mono       industrial mono\n  Courier Prime       literary mono\n  serif / sans / mono system fonts\n\nArchitecture:\n\n  LABEL_FONTS const removed; replaced with LABEL_BASE (per-category\n  weight + size) plus FONT_OPTIONS (the roster) and FONT_BY_ID for\n  lookup. labelStyle(entity) now resolves the font string at render\n  time via fontStringFor(entity), which checks: per-entity override\n  → fontSettings (per-category) → FONT_DEFAULTS.\n\n  fontSettings persisted to localStorage under dynamic.fonts;\n  per-entity font lives inside the existing entityColorOverrides\n  alongside outline/label.\n\n  Font dropdown change waits for document.fonts.load() to resolve\n  before rebuilding active labels — otherwise the canvas redraws\n  with the fallback typography and never picks up the new family.\n\n  All 14 fonts preloaded via the Google Fonts <link> at boot —\n  display=swap so they don't block initial paint, and total weight\n  is ~250 KB compressed.\n\nReset to defaults now resets fonts AND colors.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["f406401f38b203165768da8c615efb1ed4db1374"],"add":186,"del":15,"cadd":186,"cdel":15,"files":2},{"repo":"dynamic","hash":"85141104e2f12448f37df60afc7bb4850788ac39","ts":1777676093,"wall":"2026-05-01T18:54","msg":"fix(labels): kill cartographic glow — match political weight","body":"Cartographic labels (marine / region / city) had a visible halo while\npolitical labels rendered crisply. No outline was being set on either\n— labelStyle uses LabelStyle.FILL for everything. The \"glow\" was\npurely typography:\n\n  Political labels run at 500-700 weight (Orbitron Medium / Bold) at\n  11-14px. Solid pixel coverage, sharp glyph edges.\n\n  Cartographic was 400 weight Share Tech Mono at 11-13px. Cesium's\n  SDF text renderer puts the anti-aliased gradient at the glyph edge\n  — when the stroke itself is only a couple pixels wide, the gradient\n  spans most of those pixels and reads as a halo. Heavier strokes\n  push the gradient out of the glyph body.\n\nTwo changes:\n\n1. LABEL_BASE: bumped cartographic to 700/13-14 (mirrors the country/\n   admin tier hierarchy at the same heavy-weight level).\n\n2. FONT_DEFAULTS: switched cartographic default from Share Tech Mono\n   to IBM Plex Mono. Share Tech Mono only ships weight 400 — asking\n   for 700 forces browser-synthesized bold, which makes strokes\n   uneven and re-introduces the same glow problem. Plex Mono ships a\n   real 700, keeps the mono / terminal lineage that distinguishes\n   cartographic from Orbitron political.\n\nOperators who have already customized cartographic fonts via :colors\nwon't be affected (fontSettings in localStorage wins). To pick up the\nnew default, click Reset to defaults in the panel.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["0bfa4c6d82e99a27ce2d9c264755e6d63c3b1de6"],"add":17,"del":6,"cadd":17,"cdel":6,"files":1},{"repo":"dynamic","hash":"a72d8f5de3d2a62ef6f3dd6c455a158779787584","ts":1777677038,"wall":"2026-05-01T19:10","msg":"feat(fonts): per-category + per-entity font size","body":"Sliders 8-32px in both panels. fontSizeSettings (per-category, persisted\nunder dynamic.font_sizes) parallels fontSettings — separate keys so an\nexisting localStorage with only family overrides keeps working unchanged.\nPer-entity size lives in entityColorOverrides[key].fontSize alongside\nthe existing font/outline/label fields.\n\nResolution chain in fontStringFor(entity):\n  per-entity override.fontSize → fontSizeSettings[type] → LABEL_BASE[type].size\n\nReset-to-defaults clears sizes too.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["85141104e2f12448f37df60afc7bb4850788ac39"],"add":80,"del":5,"cadd":80,"cdel":5,"files":1},{"repo":"dynamic","hash":"92b0934c5ac7247e66cb981771d5b8a8fd65e934","ts":1777677396,"wall":"2026-05-01T19:16","msg":"feat(strip): right-click pill opens context menu of all actions","body":"Mirrors the palette's right-arrow action picker, but inline at the\ncursor. For a per-entity pill the menu shows actionsFor(entity) — the\nsame list the palette would render — with ● next to whichever actions\nare currently active so the operator sees state at a glance. Click any\nitem to invoke it, dismiss with Esc / left-click anywhere / right-click\noutside the pill.\n\nFor a global YAML-driven pill (borders, weather, etc.) the menu has\n\"Toggle off\" + \"Customize colors…\" as a shortcut into the global panel.\n\nImplementation:\n  - Single #contextMenu element styled to match the colors panel\n    chassis (dark + Orbitron). [hidden] is authoritative — no display\n    override in CSS, so the show/hide attribute toggle just works\n    (the same lesson the colors panel taught).\n  - positionContextMenu clamps inside viewport so the menu never\n    spills off-screen when right-clicking a pill near the edge.\n  - Document-level click + contextmenu listeners dismiss the menu\n    when the operator clicks outside it.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["a72d8f5de3d2a62ef6f3dd6c455a158779787584"],"add":176,"del":5,"cadd":176,"cdel":5,"files":2},{"repo":"dynamic","hash":"b80d7b832591aadc8c78d6828512c45ee0f6a2f3","ts":1777677781,"wall":"2026-05-01T19:23","msg":"fix(labels): disable depth-test, kill dither halo around glyphs","body":"The \"dot cloud fuzz\" around Greenland's label (and any other label\nsitting over a uniform high-luminance surface — snow, sand, glacier)\nwas depth-test dithering, not SDF anti-aliasing.\n\nCesium labels default to depth-tested rendering. The label position\nis at altitude 0, coplanar with the terrain raster's opaque pixels.\nThe GPU's blend pass against coplanar geometry uses a stipple pattern\nto resolve the depth conflict — invisible against varied terrain\nbecause the noise blends with surrounding color, but very visible\nagainst white snow.\n\ndisableDepthTestDistance: Number.POSITIVE_INFINITY tells Cesium to\nskip depth-testing for the label entirely — always render in front of\ngeometry. That's the correct behavior for cartographic labels anyway:\na country name should not be occluded by its own border, by a tilted\ncamera, or by the terrain's surface raster.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["92b0934c5ac7247e66cb981771d5b8a8fd65e934"],"add":8,"del":1,"cadd":8,"cdel":1,"files":1},{"repo":"dynamic","hash":"269e3ba908d6af32b89aa131394ec9227c20426a","ts":1777696616,"wall":"2026-05-02T00:36","msg":"fix(labels): force fill alpha 1.0 — stop OIT stippling at the source","body":"Previous attempts:\n  1. disableDepthTestDistance=POSITIVE_INFINITY (kept; right for other\n     reasons, but the dither isn't a depth conflict).\n  2. COLOR_DEFAULTS *_label changed to alpha 1.0 (only affects fresh\n     sessions or after Reset to defaults — doesn't help if localStorage\n     already has translucent values from the operator's earlier\n     customization).\n\nReal fix: clamp label fillColor alpha to 1.0 at the rendering layer in\nlabelStyle(). Doesn't matter what colorSettings or localStorage says,\nlabels render fully opaque. The alpha slider in :colors still works\nfor non-label colors (outlines, UI accents); only labels are clamped,\nbecause for labels alpha < 1 = guaranteed stipple cloud under Cesium's\nOIT fallback path. Color hue still tunable.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["b80d7b832591aadc8c78d6828512c45ee0f6a2f3"],"add":29,"del":14,"cadd":29,"cdel":14,"files":1},{"repo":"dynamic","hash":"97fc5712822805226275526df979234eba0cfbe5","ts":1777697167,"wall":"2026-05-02T00:46","msg":"feat(admin_2): Puerto Rico via Overture's region subtype","body":"PR's 78 municipios don't sit under subtype 'county' or 'localadmin'\nin Overture — they're filed as 'region' because Overture treats\nPuerto Rico as a single admin_1 (with municipios as its top-level\nsubdivision) rather than as a country with admin_2 below admin_1.\nQuerying the default subtypes returned zero features.\n\nTwo changes to scripts/fetch_admin_2.py:\n\n  1. Added 'PRI' → 'PR' to ISO3_TO_2.\n  2. New SUBTYPE_OVERRIDES dict — per-country subtype filter when\n     Overture's classification doesn't match the default. PRI is\n     the first entry; future territories with similar quirks slot\n     in cleanly without touching the SQL.\n\nPre-fetched PRI.geojson (78 municipios, 189 KB simplified). Manifest\nauto-updated to 9 countries. The eager-load path picks them up at\nfirst idle, so the in-app palette can find any PR municipio by name\nand the country-level \"Toggle counties / districts\" on Puerto Rico\nrenders all 78.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["269e3ba908d6af32b89aa131394ec9227c20426a"],"add":19,"del":2,"cadd":17,"cdel":1,"files":3},{"repo":"dynamic","hash":"058bec7251415cd88bcf8cad61eb3bade163fc1b","ts":1777697492,"wall":"2026-05-02T00:51","msg":"feat(toggle): bulk admin_1 / admin_2 also render the country outline","body":"When you toggle \"all states of USA\" or \"all counties of Puerto Rico,\"\nyou almost always also want to see the outer country border and name —\notherwise you're looking at a cluster of internal divisions floating\nwithout a perimeter to anchor them.\n\nBoth bulk actions (toggle_admin_1, toggle_admin_2) now render the\ncountry's outline+label *plus* the inner-division polylines as a\nsingle coupled toggle, mirroring the per-entity toggle_outline pattern\nwhere border and name move together. Single pill, single click to\nremove both layers.\n\nFor Puerto Rico specifically: typing \"Puerto Rico\" → \"Toggle counties\n/ districts\" now renders the 78 municipios PINK plus PR's amber\ncountry outline + name in one go. Previously you'd see municipios\nwith no containing border — operator had to also invoke \"Toggle\noutline\" separately.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["97fc5712822805226275526df979234eba0cfbe5"],"add":24,"del":4,"cadd":24,"cdel":4,"files":1},{"repo":"dynamic","hash":"07f3b45ed8b6947728ee67ccc6b9cdab49e46a58","ts":1777697864,"wall":"2026-05-02T00:57","msg":"fix(projection): unify on EPSG:4326 across every layer + scene mode","body":"Audit found EOX base imagery sat in Web Mercator (EPSG:3857, tile\nmatrix set \"g\") while everything else — GIBS rasters, GeoJSON\nvectors, Natural Earth, Overture admin_2 — lived in WGS84 / EPSG:4326.\nCesium 3D mode hides the mismatch by reprojecting each tile onto the\nellipsoid, but the cost is sampling artifacts at high latitudes plus\na hard ~85° clip on EOX (Mercator can't represent the poles).\n\nTwo changes:\n\n  imagery-base.yaml — switched all three EOX base layers from their\n  `_3857` variants to plain WGS84 variants (EOX hosts both). Layer ID\n  changes (terrain_3857 → terrain etc.), tile_matrix_set \"g\" → \"WGS84\",\n  added tiling_scheme: geographic. Native EPSG:4326 raster, no\n  reprojection. Max levels updated to match WGS84 matrix set depth\n  (terrain/light: 17, s2cloudless: 15).\n\n  buildProvider() — when layer.tiling_scheme === 'geographic', pass\n  GeographicTilingScheme to WebMapTileServiceImageryProvider instead\n  of letting it default to WebMercatorTilingScheme.\n\n  Viewer constructor — mapProjection: GeographicProjection. 2D and\n  Columbus modes now use equirectangular instead of Mercator. Polar\n  regions render. All vector overlays align pixel-for-pixel with\n  raster imagery in 2D as well as 3D.\n\n3D mode behavior unchanged (everything was ellipsoid-projected\nalready), but the underlying data is now coherent end-to-end.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["058bec7251415cd88bcf8cad61eb3bade163fc1b"],"add":37,"del":11,"cadd":37,"cdel":11,"files":2},{"repo":"dynamic","hash":"ae9fb74bea7ef3811bf33b9937e29e8aee65ea2a","ts":1777698512,"wall":"2026-05-02T01:08","msg":"docs: master layer roadmap","body":"Comprehensive inventory of every layer the atlas could carry, organized\nby domain — political, energy, resources, communications, finance,\ndemographics, indigenous & counter-institutional, conflict, geophysical,\nplanetary metabolism, atmospheric chemistry, cryosphere, anthropogenic\nmetabolism, human movement, deep time, methodological gaps. Each entry\nnotes source, license, and integration tier (T1 drop-in YAML / T2 fetch\nscript / T3 custom code).\n\nEnds with priority recommendations grouped by tier, weighted toward the\nproject thesis (counter-institutional data, deep time, planetary\nmetabolism). Categories §7 (indigenous + counter-institutional), §15\n(deep time), and §16 (methodological gaps) are flagged as the most\nthesis-distinctive.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["07f3b45ed8b6947728ee67ccc6b9cdab49e46a58"],"add":333,"del":0,"cadd":333,"cdel":0,"files":1},{"repo":"dynamic","hash":"abb3eab59039ca0b68a4b1d47e1e7a6a9b82eb2c","ts":1777699183,"wall":"2026-05-02T01:19","msg":"feat(layer): :population — GPW v4 population density 2020","body":"First of the tier-1 anthropogenic-flux overlays. Drop-in YAML, no\nfetch script, no new provider type — uses the existing `gibs` static\npath (time: '') with CIESIN's GPW v4.11 1km global population raster.\n\nTile fetch verified against gibs.earthdata.nasa.gov. New :population\nslash command, palette-toggleable like every other overlay. Pill in\nthe active strip handles toggle-off.\n\nNew overlay categories added to support this and future anthropogenic\n+ metabolism layers: 'anthropogenic' (population, nightlights, CO2\nemissions, etc.) and 'metabolism' (biogeochemical / earth-system\noverlays — NDVI, chlorophyll, AOD, sea ice, soil moisture, SST).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ae9fb74bea7ef3811bf33b9937e29e8aee65ea2a"],"add":28,"del":0,"cadd":28,"cdel":0,"files":1},{"repo":"dynamic","hash":"2be2b991b71b9e24d3a0ef1821221b5b3bb827a5","ts":1777718652,"wall":"2026-05-02T06:44","msg":"feat(action): state-scoped admin_2 toggle on admin_1 entities","body":"State pills (California, Sonora, Yucatán, etc.) now expose a \"Toggle\ncounties / districts\" action that renders ONLY the admin_2 features\ninside that state — not the full country's admin_2 set.\n\n  toggle_admin_2_within_state\n    applies: ['admin_1']\n    Looks up parent country via entity.countryISO, ensures its admin_2\n    file is loaded, filters admin2ByCountry[country] by Overture's\n    `region` property matching the state's iso_3166_2 (e.g. \"US-CA\").\n    Couples with the state's outline + label via buildCountryWithBulk\n    so the inner polygons get anchored by the state border + name,\n    same coupling pattern toggle_admin_1 / toggle_admin_2 use at\n    country level.\n\n  Added to admin_1 entity type's actionIds. State context menus +\n  palette action picker now show: Toggle outline (primary), Toggle\n  counties / districts (state-scoped), Fly to, Customize colors.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["abb3eab59039ca0b68a4b1d47e1e7a6a9b82eb2c"],"add":47,"del":1,"cadd":47,"cdel":1,"files":2},{"repo":"dynamic","hash":"da944baf28dd635b8ceaeaed56430dee99237e02","ts":1777721541,"wall":"2026-05-02T07:32","msg":"feat(layer): :population — locally-baked GHSL pyramid (no LOD seams)","body":"Replaces the broken GIBS-hosted population overlay. The previous\n`:population` toggled GIBS' GPW raster, which uses a non-power-of-2\ntile matrix progression (2,3,5,10,20,40,...) that breaks Cesium's\nquadtree refinement and produces visible LOD seams — most starkly\nwhere the heat map meets the underlying terrain (the screenshots that\nprompted this).\n\nNew pipeline:\n\n  scripts/bake_raster.py — generic GeoTIFF → EPSG:4326 power-of-2\n  doubling tile pyramid baker. Uses GDAL 3.11+'s `gdal raster tile`\n  with `--tiling-scheme WorldCRS84Quad` (which is exactly Cesium's\n  default GeographicTilingScheme: L0=2×1, L1=4×2, L2=8×4, ...). No\n  custom tilingScheme subclass; no LOD seams at any zoom.\n\n  scripts/colormaps/population_log.txt — log-perceptual stops:\n  transparent → navy → cyan → yellow → orange → red → magenta → white\n  across 0 to 30k ppl/km².\n\n  index.html — new `provider: tile_pyramid` branch in buildProvider,\n  trivially uses UrlTemplateImageryProvider with default\n  GeographicTilingScheme. Generic for any future locally-baked raster.\n\n  imagery-overlays.yaml — `:population` slash command now points at\n  data/layers/cartographic/population/ghsl-2025/{z}/{x}/{y}.png. New\n  `ghsl` attribution entry for proper credit.\n\nThe 12k tile pyramid (~500 MB on disk) is gitignored — too heavy for\ngit history. README in the layer dir documents the bake workflow;\nre-baking is a single command and takes ~3 minutes given GDAL is\ninstalled.\n\nThis same pipeline becomes the path forward for every other public\nraster on the roadmap (Köppen climate, NPP, glaciers, anthropogenic\nCO2, paleoclimate, etc.). Drop-in YAML once baked.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["2be2b991b71b9e24d3a0ef1821221b5b3bb827a5"],"add":460,"del":19,"cadd":357,"cdel":19,"files":11},{"repo":"dynamic","hash":"6d88ed5f3bb27c1223188618427db9983ac578e2","ts":1777722311,"wall":"2026-05-02T07:45","msg":"feat(layer): runtime LUT recoloring for raster tile pyramids","body":"Phase 1 of live colormap customization. Replaces the static\ncolor-baked population pyramid with a value-encoded one that recolors\nin the browser at fetch time, via a 256-entry LUT.\n\nPipeline:\n\n  scripts/colormaps/population_encode.txt — gdaldem stops that bake\n  log10(population+1) into the R channel of each pixel; A is the\n  data mask (0 = no people / no data, 255 = sampled). G + B unused.\n\n  data/layers/cartographic/population/ghsl-2025 — re-baked from the\n  encoding colormap. 12,176 tiles, 282 MB on disk (smaller than the\n  visual bake since all tiles are red ramps and PNG compresses\n  uniform colors well).\n\n  index.html — new provider type `tile_pyramid_lut`. Wraps Cesium's\n  UrlTemplateImageryProvider.requestImage to apply the named LUT to\n  every tile before Cesium uses it. Per-tile cost: a 256×256 canvas\n  recolor pass, ~50KB heap, sub-millisecond. New LUT_REGISTRY +\n  buildLutFromStops helpers — log-perceptual default `population_default`\n  matches the previous static visual byte-for-byte.\n\n  imagery-overlays.yaml — :population now uses `provider:\n  tile_pyramid_lut`, `lut: population_default`. Same slash command,\n  same pill, same UX — but the colormap is live-tunable from JS now.\n\nPhase 2 (next) will add a colormap editor in the :colors panel —\noperator drags color stops on a gradient bar, mutates the LUT array,\nimageryLayers reload, instant recolor.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["da944baf28dd635b8ceaeaed56430dee99237e02"],"add":176,"del":39,"cadd":127,"cdel":12,"files":5},{"repo":"dynamic","hash":"ee743f76569a10d49e766021fcab002a4f661354","ts":1777723621,"wall":"2026-05-02T08:07","msg":"fix(layer): population banding — return ImageBitmap + drop skip-blank","body":"Two bugs in the runtime-LUT path that combined to produce the\nhorizontal-band misalignment:\n\n1. applyLutToImage returned a raw HTMLCanvasElement. Cesium 1.122's\n   UrlTemplateImageryProvider tile-cache codepaths (initial load,\n   refinement, retry, parent-fallback) all expect ImageBitmap, which\n   is what the underlying Resource.fetchImage returns by default.\n   A canvas works for the initial load path but inconsistently for\n   refinement/fallback — the visible result is bands of tiles that\n   render correctly with my LUT and bands that don't render at all.\n\n   Fix: applyLutToImage now returns Promise<ImageBitmap> via\n   createImageBitmap(canvas). Cesium handles every code path with\n   the same canonical type.\n\n2. The bake used --skip-blank, so blank tiles 404'd. Cesium's tile\n   loader is supposed to fall back to the parent on 404 but in\n   practice the rejection bubbled through my requestImage wrapper\n   (no .catch), and the downstream behavior varied with the LOD-\n   refinement path the tile took.\n\n   Two-part fix:\n   - bake_raster.py — remove --skip-blank. Every tile slot now exists,\n     even fully-transparent ones. Cost: ~10 MB more on disk\n     (43,690 tiles vs 12,176; uniform-transparent PNGs compress to\n     <500 B each). 282 MB → 293 MB total.\n   - The wrapped requestImage now resolves to undefined on rejection\n     instead of letting it bubble. Belt-and-suspenders since blank\n     tiles no longer 404.\n\nHard-refresh the page and the bands should be gone.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["6d88ed5f3bb27c1223188618427db9983ac578e2"],"add":23,"del":9,"cadd":23,"cdel":9,"files":2},{"repo":"dynamic","hash":"933e8c3ad3af3d1b2e126589cbc8aaf0d615e462","ts":1777724550,"wall":"2026-05-02T08:22","msg":"feat(colors): live colormap editor in :colors panel","body":"Phase 2 of runtime LUT — the actual UI. Open :colors and scroll to the\nnew \"Colormaps\" section. For each registered LUT (currently:\npopulation_default), the panel shows:\n\n  - A live gradient preview bar (over a checkered background so\n    transparent stops are visible).\n  - A list of stops, each row: position 0–255 / RGB color picker /\n    alpha slider / delete button.\n  - \"+ Add stop\" — inserts a new stop at the midpoint of the largest\n    gap, color interpolated from the surrounding stops.\n\nEditing any value commits immediately:\n  1. lutStopsSettings is mutated and saved to localStorage.\n  2. rebuildLut() regenerates the 256-entry LUT_REGISTRY[name] array\n     in place, so any closure already holding a reference (the\n     requestImage wrapper for active layers) sees the new colors.\n  3. reloadLayersUsingLut() toggles every active layer that uses\n     this LUT off+on, flushing Cesium's tile cache so the next\n     re-render picks up the new colors.\n\nReset to defaults clears LUT stops alongside colors and fonts.\n\nPersisted as `dynamic.lut_stops` in localStorage. Defaults are mirrored\nfrom the static-bake colormap so a fresh open looks identical to\nyesterday's visual until the operator starts moving stops.\n\nFuture raster layers (climate, NPP, glaciers) just register their\nown LUT in LUT_DEFAULTS_STOPS and they get their own editor card\nautomatically.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ee743f76569a10d49e766021fcab002a4f661354"],"add":283,"del":5,"cadd":283,"cdel":5,"files":1},{"repo":"dynamic","hash":"751c25b89846a3ae02555e8142b702e0777eaaff","ts":1777725015,"wall":"2026-05-02T08:30","msg":"feat(colors): hue-rotation slider + HSL inter-stop interpolation","body":"Two complementary smoothness improvements to the colormap editor:\n\n1. HSL interpolation between stops. Previous buildLutFromStops did\n   linear RGB interpolation, which means going from (e.g.) red to\n   blue passes through muddy purple-grays at the midpoint because RGB\n   is a straight line through 3-space cube. New build converts each\n   stop to HSL, interpolates hue along the shorter arc of the wheel,\n   and converts back. Result: smooth chromatic gradients that stay\n   saturated through the whole transition. Lightness and saturation\n   still interpolate linearly. Grayscale stops (s=0) borrow their\n   neighbor's hue so the gradient doesn't snap to neutral mid-flight.\n\n2. Per-LUT \"Hue\" slider in the editor card. Sweeps -180° to +180°,\n   rotating every stop's hue by the same delta — preserves the\n   gradient relationships (\"color-matched\") but lets the operator\n   dial warm/cool/teal/purple variants of the palette in one motion.\n   No need to hand-edit individual stops to retune the overall mood.\n   Persisted as `dynamic.lut_hue` in localStorage; reset-to-defaults\n   zeros it.\n\nThe editor also includes the HSL helpers (rgbToHsl, hslToRgb,\nshiftRgbHue) used by both interpolation and rotation.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["933e8c3ad3af3d1b2e126589cbc8aaf0d615e462"],"add":167,"del":23,"cadd":167,"cdel":23,"files":1},{"repo":"dynamic","hash":"2cbd4f21feccb5c261cd654142049f9890aeb129","ts":1777895483,"wall":"2026-05-04T07:51","msg":"feat(lake): assertion-first knowledge substrate v0.1","body":"Two foundational tables — assertions and sources. Every claim is one row;\nentities are convergences of assertions sharing a subject ID; types are\nclaims (X instance_of Country per source S), not schema columns. No\nexternal ID system holds privilege; Wikidata Q-IDs / ISO codes / GERS\nUUIDs are recorded as has_external_id literals tagged with a 'system'\nqualifier — testimony, not backbone.\n\n  lake/\n  ├── ddl/001_init.sql          assertions + sources + indexes\n  ├── ddl/002_views.sql         places_natural_earth_50m, entity_names_multilingual,\n  │                             sovereignty_claims\n  ├── predicates/registry.yaml  legal verbs an assertion can use (12 predicates)\n  ├── adapters/_common.py       cartolith_id minting, source registration,\n  │                             predicate validation, batched insertion\n  ├── adapters/natural_earth_admin_0.py\n  │                             first adapter — NE 1:50m countries → 8,247 assertions\n  └── cli.py                    init / status / ingest / query / predicates\n\nSmoke test: ingests 242 NE entities into 8,247 assertions; sovereignty\ngraph reproduces NE's full dependency map (Israel→Palestine, PRC→Hong\nKong/Macau, UK→Falklands, etc.) recorded as NE's view, not as truth;\nmultilingual round-trip preserved across 24 languages.\n\nThe lake is a build artifact — lake.duckdb is rebuilt by re-running\nadapters and is not committed.","parents":["751c25b89846a3ae02555e8142b702e0777eaaff"],"add":823,"del":0,"cadd":815,"cdel":0,"files":10},{"repo":"dynamic","hash":"420cae52372a2dbe00d2788350cdd3816ee8fad2","ts":1777897440,"wall":"2026-05-04T08:24","msg":"rename(datalake): lake → Datalake","body":"Substrate is the Datalake. Updated directory, README, docstrings, internal\nnamespace seed (now 'datalake.dynamic.symbiont.systems') so cartolith_ids\nare minted under the proper name. Re-init + re-ingest verified — 242\nentities, 8,247 assertions, places_natural_earth_50m / entity_names_multilingual\n/ sovereignty_claims views all resolve.","parents":["2cbd4f21feccb5c261cd654142049f9890aeb129"],"add":38,"del":36,"cadd":32,"cdel":30,"files":11},{"repo":"dynamic","hash":"fd75289942394048b0dd5600066995364f6292e3","ts":1777899575,"wall":"2026-05-04T08:59","msg":"rename(datalake): cartolith_id → glyph_id","body":"The internal stable identifier is the glyph — a bare mark, ours, with no\ninherent meaning until sources accrete assertions onto it. Aligns with\nthe glyphic-space line of research where the glyph is the irreducible\ntoken that meaning operators decorate.\n\nTouched: README, _common.py, 001_init.sql, 002_views.sql, registry.yaml.\nRe-init + re-ingest verified — 8,247 assertions, places view round-trips\nglyph_id correctly. UUID values themselves unchanged (namespace seed\n'datalake.dynamic.symbiont.systems' is stable).","parents":["420cae52372a2dbe00d2788350cdd3816ee8fad2"],"add":13,"del":13,"cadd":13,"cdel":13,"files":5},{"repo":"dynamic","hash":"602b748aece2418d6ea8e54920d18c13244dd23b","ts":1777904671,"wall":"2026-05-04T10:24","msg":"feat(datalake): Tier 1 ingest — 280K assertions, 9 sources","body":"Seven new adapters covering all bundled cartographic + political data:\n\n  natural_earth_admin_1            174,965 assertions  4,596 admin_1 worldwide\n  overture_admin_2                  67,283 assertions  9 countries (USA, IND, MEX, CAN, FRA, AUS, DEU, GBR, PRI)\n  natural_earth_geography_regions   15,665 assertions  522 named regions (Sahara, Tibetan Plateau, Amazon Basin, ...)\n  natural_earth_admin_0              8,247 assertions  unchanged\n  natural_earth_populated_places     8,285 assertions  1,251 cities + capital_of resolution\n  natural_earth_marine               3,541 assertions  118 oceans/seas/gulfs/bays/straits\n  natural_earth_breakaway            1,232 assertions  28 contested territories with multi-perspective sovereignty claims\n  natural_earth_disputed_boundaries    721 assertions  34 boundary lines with FCLASS multi-party classification\n  natural_earth_nine_dash              342 assertions  PRC South China Sea claim with FCLASS perspectives\n\nThree new predicates: boundary_classified_as (per-party classification of a\nboundary, with classifying_party qualifier), has_centroid (point geometry\ndistinct from extent), notes (free-text annotation). Cross-source resolution\nverified: admin_1 / admin_2 / capitals all resolve to NE admin_0 country\nglyph_id via deterministic UUIDv5 mint. Mexico's 33 admin_1 + 2,475 admin_2\n+ 1 capital all link to the same Mexico glyph; same for the other 8 bundled\ncountries. Multi-perspective Golan Heights row pivots to 29 'International\nboundary' votes vs 2 'Unrecognized' (Israel, Ukraine) vs 1 'Claim boundary'\n(US) — the contested-truth thesis made queryable.\n\nBulk-insert refactor: insert_assertions now stages rows as a pandas DataFrame\nand INSERTs via DuckDB relation in one round trip. ~100x faster — admin_1\nwent from 2:30+ on per-row inserts to 11s. Geometry helper hardened against\nempty/degenerate WKT (was tripping on Overture's empty polygons).","parents":["fd75289942394048b0dd5600066995364f6292e3"],"add":1484,"del":66,"cadd":1484,"cdel":66,"files":11},{"repo":"dynamic","hash":"0bcfa083b21de89b3535bdaa807e8895ec1ff931","ts":1777940129,"wall":"2026-05-04T20:15","msg":"fix(datalake): nine-dash glyph minting + re-ingest FK safety","body":"Two bugs found while running the Tier 1 smoke battery:\n\n1. Nine-dash adapter read 'NE_ID' (uppercase) but the file uses 'ne_id'\n   (lowercase) — all 9 segments fell back to 0 and minted to a single\n   shared glyph, collapsing 297 boundary_classified_as rows onto 1\n   subject. Fixed by trying lowercase first then uppercase.\n\n2. upsert_source did DELETE+INSERT, which trips the assertions→sources\n   foreign key on re-ingest (assertions still reference the source we\n   just tried to delete). Switched to INSERT OR REPLACE.\n\nPlus datalake/test_tier1.sh — a smoke battery that re-runs in ~3s and\nexercises every adapter, every cross-source resolution, and the\nmulti-perspective queries that are the thesis core (Golan Heights\nclassification fan-out, Arunachal Pradesh sovereignty competition,\nnine-dash recognition graph).","parents":["602b748aece2418d6ea8e54920d18c13244dd23b"],"add":147,"del":5,"cadd":147,"cdel":5,"files":3},{"repo":"dynamic","hash":"5d631f24ef6763cb94218cae953ece6aa6c509c8","ts":1777942043,"wall":"2026-05-04T20:47","msg":"feat(dynamic): glyph_id everywhere + Inspect Data panel + globe label boxes","body":"Four passes that unify identity across UI and Datalake.\n\nPass 1 — Datalake export CLI\n  python datalake/cli.py export → 16,438 per-entity JSON bundles at\n  data/datalake/entities/<glyph>.json plus a manifest.json. Each bundle\n  groups assertions by predicate (names, external_ids, types, geometry\n  metadata, facts, boundary_classifications) with full source attribution\n  and a sources_summary footer. Incoming sovereignty/control claims are\n  reverse-indexed so consumers don't have to scan every other entity.\n  Class entities excluded; geometry coords excluded (UI already has them\n  from GeoJSON). 75 MB total, gitignored as a build artifact.\n\nPass 2 — UUIDv5 + namespace constants in JS\n  Hand-rolled synchronous SHA-1 (RFC 3174) + UUIDv5 (RFC 4122 §4.3) in JS,\n  ~120 lines. Seven Datalake namespace UUIDs hardcoded, verified against\n  Python. Boot-time drift detector compares four computed glyphs against\n  expected values; warns on mismatch. Verified byte-for-byte equal to the\n  Python adapter mints (Mexico → 5d152608-08b4-..., Sonora → 61a43ec2-...).\n\nPass 3 — UI: replace entity IDs with glyph_ids\n  Each entity loader (country, admin_1, admin_2, marine, region, city)\n  computes glyph at GeoJSON-load via the same source-local-key the adapter\n  uses, and uses it as entity.id. Three recipe divergences fixed: admin_1\n  now prefers adm1_code (matching adapter), marine/region use raw `name`\n  not `name_en`, city stores ne_id. Added countriesByISO Map keyed by\n  ADM0_A3 for parent-resolution paths that need ISO not glyph. localStorage\n  schema migration v1→v2: per-entity color overrides, recents, per-entity\n  font/size overrides wiped on first boot (type-level overrides survive).\n\nPass 4 — Inspect Data panel\n  New entity action 'Inspect data' on every type. Right-edge non-modal\n  <dialog> mirroring the colors panel chassis. Lazy-fetches the entity's\n  JSON bundle from data/datalake/entities/<glyph>.json with session cache.\n  Sections: names by language, external identifiers, types, geometry,\n  population history, outgoing claims, incoming relations, multi-perspective\n  boundary classifications grouped by value (the contested-truth view made\n  visible), other facts, sources footer with kind-colored badges.\n\nPlus a side fix: globe labels now render with a backing plate\n(showBackground + backgroundColor + backgroundPadding). Tunable via\n:colors → 'Label backing plate' (set α=0 to disable globally).\n\nRun after fresh clone:\n  python datalake/cli.py init\n  for a in natural_earth_admin_0 natural_earth_admin_1 natural_earth_geography_regions \\\n           natural_earth_marine natural_earth_populated_places natural_earth_breakaway \\\n           natural_earth_disputed_boundaries natural_earth_nine_dash overture_admin_2; do\n    python datalake/cli.py ingest $a\n  done\n  python datalake/cli.py export","parents":["0bcfa083b21de89b3535bdaa807e8895ec1ff931"],"add":1107,"del":63,"cadd":1099,"cdel":63,"files":3},{"repo":"dynamic","hash":"302ed9e86f86f756260f7006bda929c21767a1e0","ts":1778023431,"wall":"2026-05-05T19:23","msg":"feat(labels): bare HTML-overlay labels, no Cesium SDF","body":"Replaces Cesium's SDF-atlas LabelCollection rendering with absolutely-\npositioned <span> elements in a transparent overlay div. Cesium's job is\nnow strictly the globe — terrain, imagery, polyline borders. Everything\ntext-shaped lives in #labelOverlay.\n\nWhy: the fine-grain \"TV noise\" speckle around globe labels traces back\nto Cesium's SDF pipeline at small render sizes. The 48px reference SDF\nis built per-glyph, quantized to 8-bit RGBA, downscaled to the 11-14px\nrender sizes we use, and run through a 5-sample shader supersample\n(BillboardCollectionFS.glsl:102-118). The cumulative effect of 8-bit\nquantization + bilinear filter + 5-sample averaging shows through as\nfine grain at glyph edges. No setting of OIT, MSAA, FXAA, or alpha\nclamp eliminates it — it's intrinsic to the SDF path at small sizes.\n\nBrowser-native text rendering bypasses the entire pipeline. Sub-pixel\nClearType/Quartz/FreeType AA, no atlas, no quantization, no possible\nstipple. Plus: cleaner code path, no Cesium-version-specific quirks.\n\nImplementation:\n  • <div id=\"labelOverlay\"> covers the viewport, pointer-events:none\n  • makeHtmlLabelCollection(typeName) returns a thin object exposing\n    .add(opts) / .remove(handle) — same shape the toggle_outline /\n    toggle_name call sites expected, so they don't change\n  • Each label is a <span.dyn-label.{typeName}> styled inline by\n    {font, color} from labelStyle(entity)\n  • Per-frame projection in scene.preRender via\n    SceneTransforms.worldToWindowCoordinates\n  • EllipsoidalOccluder hides labels behind the globe\n  • CSS centers each span on its projected point (translate -50% -50%\n    for everything except city, which is left-anchored at +8px)\n\nRemoved: showBackground / backgroundColor / backgroundPadding plumbing\n(boxes are gone — bare letters per directive), label_background color\nsetting (no boxes, irrelevant), OIT-off + msaaSamples assignments\n(aimed at the SDF problem, no longer applicable; defaults preserved).\n\nThe labelStyle(entity) signature is now {font, color, isCity, type} —\nCesium-specific Label fields gone.\n\nOperator directive: \"The only thing we need from cesium is the globe.\nWe will build all our own UI code.\" — this is step one.","parents":["5d631f24ef6763cb94218cae953ece6aa6c509c8"],"add":132,"del":55,"cadd":132,"cdel":55,"files":1},{"repo":"dynamic","hash":"9b77148fe94e14dfc1828b1465be52d185d67387","ts":1778024781,"wall":"2026-05-05T19:46","msg":"feat(globe): CesiumWidget + SVG polyline overlay","body":"Two passes that take Cesium's role down to \"render the globe and the\nimagery on it.\" Everything else — labels, borders, panels, palette —\nis ours.\n\nPass 1 — Cesium.Viewer → Cesium.CesiumWidget\n  Drop the Viewer chrome entirely (timeline, animation widget, info\n  box, selection indicator, geocoder, base layer picker, scene mode\n  picker — all unused or hidden). CesiumWidget is just the canvas\n  plus camera. Replaces baseLayerPicker.viewModel.selectedImagery\n  with imperative setBaseLayer(idx) using imageryLayers.removeAll +\n  addImageryProvider against a flat baseLayerEntries[idx].factory()\n  registry. Drops dead NominatimGeocoderService class. Drops the\n  ProviderViewModel ceremony around base + terrain providers.\n\nPass 2 — Cesium.PolylineCollection → SVG overlay\n  All borders / outlines / disputed lines render as <path> elements\n  in a new <svg id=\"borderOverlay\"> sitting at z-index 4 (above the\n  globe canvas, below the label overlay at z=5). SvgPolylineGroup\n  class auto-attaches on construction, has .destroy() for the\n  toggleLayer machinery's object-with-destroy path. Pre-converts ring\n  vertices to Cartesian3 once at construction; per-frame projection\n  via SceneTransforms.worldToWindowCoordinates rebuilds the path\n  d-attribute as M…L… subpaths, breaking on EllipsoidalOccluder hits\n  so back-of-globe segments don't span the screen. svgDashFor()\n  translates YAML line_style → stroke-dasharray (dashed = '8 6',\n  dotted = '2 4'). buildLinePrimitive, buildOutline, buildCountryWith-\n  Bulk, and createGeoJsonController all rewired to use the SVG path.\n\nNet surface area used from Cesium: scene (camera, primitives for\nimagery, preRender event), camera controls, SceneTransforms,\nEllipsoidalOccluder, BoundingSphere/Cartesian3 helpers, base imagery\nproviders. All UI is HTML/CSS/SVG.\n\nPerformance note: SVG path d-attr rebuilt per frame for every active\ngroup. For low-feature-count layers (per-entity outlines, individual\ncountry borders) this is fine. For the worldwide :admin1 overlay\n(4,596 features, ~1M+ vertices) it'll be slower than Cesium's GPU-\nbatched polylines — JS-side projection + DOM mutation is the bottle-\nneck. Acceptable for now; viewport culling + camera-event-debounced\nupdates can layer on if needed.","parents":["302ed9e86f86f756260f7006bda929c21767a1e0"],"add":198,"del":173,"cadd":198,"cdel":173,"files":1},{"repo":"eureka-co-nevada","hash":"9c498f6e100031fe13b436cfe12899c3a3cec688","ts":1778039945,"wall":"2026-05-05T23:59","msg":"cleanup: remove broken riparian corridor builder","body":"The script unioned three heterogeneous data sources (LANDFIRE EVT\nvegetation polygons, NHD flowline buffers, NWI wetlands) into one\n\"riparian\" layer, then dissolved them. The dissolve produced a\n138K-acre mega-polygon spanning 25% of county area — an artifact of\nunioning predicted-from-flowlines with observed-from-vegetation.\n\nLANDFIRE EVT alone classifies 100,501 acres (2.85% of county) as\nRiparian, which is the credible answer. The map already shows\nflowlines, NWI wetlands, and vegetation as independent layers; the\nsynthesized \"corridors\" layer was over-engineering that produced\nscientifically invalid output.\n\nDeleted: scripts/build_riparian_corridors.py (700+ lines).\nThe bad output spatial/wetlands/eureka-county-riparian-corridors.geojson\nwas already removed.","parents":["e43e604d523842f991c55f80ac2309c08cfde4df"],"add":0,"del":662,"cadd":0,"cdel":662,"files":1},{"repo":"eureka-co-nevada","hash":"e43e604d523842f991c55f80ac2309c08cfde4df","ts":1778039945,"wall":"2026-05-05T23:59","msg":"infra: harden ec2_lidar_burst.sh","body":"- Instance-side shutdown failsafe via SSH after bootstrap, re-armed on\n  cmd_start, cancelled on cmd_stop. Survives the launching laptop dying.\n- Explicit --instance-initiated-shutdown-behavior=stop on run-instances.\n- Laptop-side sleep failsafe preserved as backup.\n- CDPATH unset on REPO derivation (previously caused path corruption\n  in scripts when CDPATH is set in the calling shell).\n- Instance type c8i.96xlarge -> c7i.48xlarge.\n\nCloses audit C2: AWS auto-stop failsafe was a sleep on the workstation.\nIf the laptop suspended/rebooted/died, the c7i.48xlarge ($155/day) kept\nrunning. Now hardened with belt-and-suspenders dual mechanism.","parents":["aae0ac3ad27fe5c534d5bc5718cd79ff0f2d220b"],"add":21,"del":3,"cadd":21,"cdel":3,"files":1},{"repo":"eureka-co-nevada","hash":"238c1a267cfbf4a436dbde906b691fd6ea590540","ts":1778040314,"wall":"2026-05-06T00:05","msg":"docs: drop stale spot-instance references in ec2_lidar_burst.sh","body":"The script was rewritten to use on-demand instances after Session 16's\nspot reclamation lost 12 hours of paid LiDAR processing. The behavior\nis correct, but four header/log/comment references still said \"spot\",\nwhich would mislead a fresh session reading the code.\n\nCloses audit H1.","parents":["9c498f6e100031fe13b436cfe12899c3a3cec688"],"add":4,"del":4,"cadd":4,"cdel":4,"files":1},{"repo":"eureka-co-nevada","hash":"29a85d05054fdc54df0376ede25c6e2ff9e3fa89","ts":1778066908,"wall":"2026-05-06T07:28","msg":"fix: tiles-to-mbtiles.py writes proper metadata","body":"Without bounds/center/zoom metadata in the MBTiles, downstream\ntools (pmtiles convert, MapLibre) default to global bounds and\n(0,0) center. This caused hillshade.pmtiles to declare its extent\nas the entire globe, which made clients request tiles worldwide\nand get silent 404s for everything outside Eureka.\n\nRewritten with argparse:\n  --bounds W,S,E,N  --center lon,lat,zoom\n  --minzoom N  --maxzoom N  --description \"...\"\n  --name  --format  --type\n\nThe currently-deployed hillshade.pmtiles header has been patched\nin place via 'pmtiles edit'. The next rebuild from scratch will\nproduce a correct file when the script is invoked with --bounds\nand --center.\n\nCloses audit B1 root cause.","parents":["238c1a267cfbf4a436dbde906b691fd6ea590540"],"add":102,"del":0,"cadd":102,"cdel":0,"files":1},{"repo":"eureka-co-nevada","hash":"50e6b27acd744cffca29702067c95d2030eefde9","ts":1778066908,"wall":"2026-05-06T07:28","msg":"fix: constrain hillshade source to county bounds (+ map WIP)","body":"Adds explicit bounds to the hillshade raster source so MapLibre\ndoesn't request tiles outside Eureka County regardless of what\nthe PMTiles header claims. Defense-in-depth — header is now\npatched too, but the JS override prevents regression if the\nfile is ever rebuilt without bounds metadata.\n\nCloses audit B3.\n\nAlso includes prior uncommitted map enhancements that have been\nrunning in production:\n- maplibre-gl 4.1.2 -> 5.21.1\n- @acalcutt/maplibre-contour-pmtiles for client-side hillshade\n  and contour lines from terrain-RGB DEM\n- 11 ecology overlays: sage-grouse habitat, mule deer corridors/\n  routes/stopovers/winter ranges across S. Tuscarora, Sheep\n  Creek, and Izzenhood\n- Layer-source mappings for the new ecology layers\n\nThe deployed PMTiles headers were patched in place via\n'pmtiles edit' (B1, B2):\n- hillshade.pmtiles: bounds and center fixed\n- eureka-terrain-rgb.pmtiles: center fixed\n- naip-basemap.pmtiles: center fixed (bounds already correct)","parents":["29a85d05054fdc54df0376ede25c6e2ff9e3fa89"],"add":256,"del":2,"cadd":256,"cdel":2,"files":1},{"repo":"eureka-co-nevada","hash":"c3bac82123dc726aa0e06c7f65cb0b872da6478d","ts":1778067159,"wall":"2026-05-06T07:32","msg":"remove client-side terrain-hillshade layer","body":"The mlcontour-driven hillshade layer rendered on top of the\npre-rendered LiDAR hillshade PMTiles wasn't producing useful\nvisual results. Removed the layer, the orphan 'dem' raster-dem\nsource, and the basemap toggle entry.\n\nKept the contours source and contour-lines/contour-labels layers\n(computed independently via mlcontour's contourProtocolUrl), and\nthe pre-rendered LiDAR hillshade.pmtiles which works well.","parents":["50e6b27acd744cffca29702067c95d2030eefde9"],"add":2,"del":23,"cadd":2,"cdel":23,"files":1},{"repo":"eureka-co-nevada","hash":"ae1799de8f4a866d4ef95b0677f7451f95e7dd86","ts":1778068273,"wall":"2026-05-06T07:51","msg":"remove pre-rendered LiDAR hillshade","body":"The 38 MB hillshade.pmtiles produced wood-grain striations at the\n1m-LiDAR / 10m-DEM mosaic boundary, washed-out flat output in the\nbasin floor (mean 178, stddev 10 — practically featureless), and\nover-zoom artifacts past z14. Net effect at z15+ was a dim, banded\nhaze laid over the NAIP imagery — not terrain shading.\n\nRemoved:\n- pmtiles.PMTiles + addSource('hillshade') + addLayer({id:'hillshade'})\n- Basemap toggle entry\n- Local map/pmtiles/hillshade.pmtiles (38 MB)\n- Deployed /var/www/eureka/pmtiles/hillshade.pmtiles (38 MB)\n- scripts/tile-hillshade.py (was hardcoded to /tmp/hillshade-merged-3857.tif,\n  output was the broken file we just deleted)\n\nTerrain context on the live map now comes from contour lines\ncomputed client-side from terrain-RGB and the NAIP imagery itself.\nIf pre-rendered hillshade is wanted later, rebuild from the LiDAR\nDEM alone (no 10m blend) with single-direction shading and produce\nz8-z17 to match NAIP zoom range.","parents":["c3bac82123dc726aa0e06c7f65cb0b872da6478d"],"add":0,"del":23,"cadd":0,"cdel":23,"files":1},{"repo":"eureka-co-nevada","hash":"0e3a069b9fe3dd1b513033702a98cd72951ff480","ts":1778076238,"wall":"2026-05-06T10:03","msg":"replace mlcontour with vector contours from 10m DEM","body":"The mlcontour pipeline read elevations from eureka-terrain-rgb.pmtiles,\nwhich was 98% nodata in the basin floor — the encoder wrote (0,0,0) for\nevery nodata pixel and terrarium decoded that as -32768 m. Contours\nwere drawn at every threshold between -32768 and real terrain, densely\nclustered along the LiDAR coverage boundary instead of actual elevation.\n\nReplaced with a static vector PMTiles built from the 10m USGS 3DEP DEM\n(spatial/elevation/eureka-county-dem-10m.tif), which has full county\ncoverage and no nodata gaps:\n\nPipeline:\n  gdal_contour -i 12.192 (40 ft) on EPSG:4269 DEM\n  -> 36,632 contour features (7,535 index + 29,097 minor)\n  -> ogr2ogr -t_srs EPSG:4326 (NAD83 -> WGS84, modern PROJ)\n  -> tippecanoe z8-z14\n  -> 45 MB contours.pmtiles (vs 422 MB broken terrain-RGB)\n\nMap viewer changes:\n- Removed mlcontour script tag, demSource, raster-dem source\n- 'contours' source is now a standard PMTiles vector source\n- contour-lines: filter shows index-only at z8-11, all at z12+\n- contour-labels: only label index contours (200-ft intervals)\n- 'idx' attribute distinguishes index (1) from minor (0) contours\n- Labels use 'elev_ft' attribute with apostrophe suffix\n\nDeleted:\n- scripts/encode_terrarium.py (no remaining consumer)\n- map/pmtiles/eureka-terrain-rgb.pmtiles (422 MB local)\n- /var/www/eureka/pmtiles/eureka-terrain-rgb.pmtiles (422 MB remote)\n\nNAD83 -> WGS84 datum shift: modern PROJ default is identity-equivalent\n(<1mm at 4 decimal places). NAIP imagery went through the same chain\nvia gdalwarp, so contours align with imagery to sub-decimeter accuracy.","parents":["ae1799de8f4a866d4ef95b0677f7451f95e7dd86"],"add":13,"del":88,"cadd":13,"cdel":88,"files":2},{"repo":"eureka-co-nevada","hash":"672913612a2b4251d5df147ad6f9fd547ef9d544","ts":1778078433,"wall":"2026-05-06T10:40","msg":"fix: structural layer ordering for county mask vs labels","body":"Crescent Valley sits on the western county boundary; its label was\nbeing clipped because the county-mask layer was rendering above it.\nSame architectural problem applied to every text-bearing layer near\nthe county edge — towns, range labels, summit labels, Mapped Features\nlabels, and contour labels were all candidates to be hidden by mask\noverflow.\n\nRoot cause: the mask was added inside fetch().then() so it landed at\nthe top of the layer stack, above every synchronously-added overlay.\nReactive moveLayer reordering would have worked but is fragile and\nbreaks again whenever new layers are added.\n\nThe actual fix is structural — position the mask once at insertion\ntime, never adjust afterward:\n\n1. Declare 'county-mask' source in the initial style with empty\n   placeholder data, and 'county-mask' layer in style.layers right\n   after background. The mask is now a stable anchor point in the\n   layer stack from map creation.\n\n2. Replace the fetch().then().addSource().addLayer() pattern with\n   fetch().then().setData() — only the geometry needs to load async;\n   the layer itself already exists.\n\n3. Introduce addMapLayer(config, explicitBeforeId?) helper that\n   classifies each layer at insertion:\n   - explicit beforeId: caller decides (used by basemap)\n   - type === 'symbol': label, goes on top by default\n   - id === 'town-dots': pairs with town-labels above mask\n   - everything else: data, inserted before 'county-mask'\n\n4. Replace all 24 map.addLayer call sites in the load handler with\n   addMapLayer. Order is now determined at insertion, not by post-hoc\n   reordering. New layers added by future code will Just Work as long\n   as they go through addMapLayer.\n\nLayer order at runtime (bottom to top):\n  basemap -> contour-lines -> data overlays (fills/lines/circles)\n  -> county-mask -> contour-labels -> symbol overlays (range labels,\n  summits, Mapped Features) -> town-labels -> town-dots\n\nNet: data layers get masked outside the county; labels render above\nthe mask and stay readable when text glyphs extend past the boundary.","parents":["0e3a069b9fe3dd1b513033702a98cd72951ff480"],"add":72,"del":48,"cadd":72,"cdel":48,"files":1},{"repo":"eureka-co-nevada","hash":"79b41be306374a868e5b55776e6847cb06bcffa1","ts":1778083656,"wall":"2026-05-06T12:07","msg":"infra: gut dead terrain-RGB stages, portable paths, handoff refresh","body":"This session deleted encode_terrarium.py, terrain-rgb.pmtiles, and\nbuild_riparian_corridors.py — but three pipeline scripts still\nreferenced them. They would have crashed on next invocation.\n\nGutted:\n- ec2_lidar_burst.sh: removed TERRARIUM_ENCODER definition,\n  preflight check, scp call, and eureka-terrain-rgb.pmtiles from\n  download/deploy lists\n- ec2_unified_pipeline.sh: removed Stage 3 (Terrain-RGB), the\n  ENCODER variable, the encoder preflight check, the rasterio\n  preflight (Stage 3 was the only consumer), and the Terrain-RGB\n  summary line\n- post_lidar_build.sh: removed Phase 2 (Terrain-RGB), LIDAR_DEM\n  variable, encoder preflight, rasterio preflight, terrain-RGB\n  upload step, and summary line. Phase 3 became Phase 2 (deploy).\n\nPortable paths:\n- scripts/warp-naip.sh: rewrote with EUREKA_REPO env var pattern\n  (was 4 hardcoded /home/Valis paths). Added preflight checks.\n- map/build-pmtiles.sh: REPO env var replaces 2 hardcoded paths.\n\nHandoff:\n- Refreshed .claude/handoff.md to reflect current state. The\n  previous handoff (Mar 24) described pmtiles that no longer exist\n  ('hillshade.pmtiles ready', etc.) and was misleading.\n\nAll five scripts pass `bash -n` syntax check. Zero leftover refs to\nencode_terrarium, eureka-terrain-rgb, or hillshade.pmtiles in\nscripts/ or map/.","parents":["672913612a2b4251d5df147ad6f9fd547ef9d544"],"add":159,"del":253,"cadd":159,"cdel":253,"files":6},{"repo":"eureka-co-nevada","hash":"33327c6bc7d2b3b9500d9b5888cd35f8959a5630","ts":1778083947,"wall":"2026-05-06T12:12","msg":"ui: remove riparian layer toggle from Hydrology group","body":"The 'riparian' layer was the NWI riparian dataset (4 features) plus\na UI toggle and opacity slider in the Hydrology group. After this\nsession deleted the riparian-corridor builder and the UI tightening\npass below, the toggle was vestigial — 4 features in a layer\nlabeled \"Riparian\" is misleading and adds clutter to the legend.\n\nRemoved:\n- LAYERS.Hydrology entry for 'riparian' (toggle + opacity slider)\n- LAYER_SOURCE mapping for 'riparian'\n\nThe underlying data (sub-layer 'riparian' in hydrology.pmtiles)\nremains in the tileset; nothing references it in the JS now.","parents":["79b41be306374a868e5b55776e6847cb06bcffa1"],"add":1,"del":2,"cadd":1,"cdel":2,"files":1},{"repo":"symbiont.systems","hash":"342347c2d4325105618aaafc687deed205b0e340","ts":1778635288,"wall":"2026-05-12T21:21","msg":"praxis: initial spike — live-coding shell for the symbiont.systems scene","body":"A new top-level dir at praxis/ implementing Praxis Operis (the\noperations/PRAXIS-OPERIS.md standard): live editing of scene.config.js\nvia inline widgets, with the file as truth and / as universal trigger.\nMirrors the deployed hex sphere visual in the right pane; the deployed\nsite/ and existing mission-control/ are untouched.\n\nStack: CodeMirror 6 + Vite + Three.js + custom widgets, ~2k LOC.\n\nWidgets (each mapped from JS source values):\n- numbers → scrubbers + popover number-picker with slider/input/steppers\n- hex strings → color chips opening an HSV picker\n- booleans → toggle pills\n- template strings → focused paragraph editor (modal)\n- tiltX/Z radians → rotary dials with shift+click for precise input\n- kingdom { hueMin, hueMax } blocks → rainbow strips with two thumbs,\n  strip fills with the actual generated kingdom palette\n\nArchitecture:\n- Vite middleware writes the editor doc back to scene.config.js on\n  every successful edit (file is the truth; localStorage is cache only)\n- Same middleware exposes /api/snapshot[s] endpoints for named presets\n  saved to praxis/snapshots/\n- Parser is structural: brace-matched extraction of the CONFIG object\n  literal, evaluated via new Function() for trusted local input\n\nCommand palette (/ or Ctrl+K):\n- Jump: every config path is fuzzy-searchable\n- Action: zen, preview, revert, reload, help, telemetry, screenshot,\n  add-ring, delete-ring, duplicate-ring, snapshot <name>, load <name>\n- Direct edit: \\\"fov 60\\\" sets the value without navigating\n- /deploy intentionally NOT wired; awaiting explicit operator order\n\nDirect manipulation:\n- Click a ring in the viewport → editor jumps to its source block AND\n  TransformControls attaches; drag rotation handles to set tiltX/Z\n  with undo coalescing; Esc or click empty space detaches\n\nLive feedback:\n- Outline strip (left) jumps to top-level sections\n- Telemetry overlay (toggle /telemetry) shows live FPS, draw calls,\n  triangles, bloom strength\n- 201-cell palette preview rendered below the colors: block,\n  memoized so unrelated edits skip the recompute\n- Parse errors highlight the offending line in red and pause the\n  viewport on the last good frame\n\nTooltips:\n- Every widget shows path · value, semantic description, and gesture\n  hints on 350ms hover\n- Description registry covers ~60 keys; inline // comments override\n- // 10..120 style range hints bound the number-picker's slider","parents":["5664af7d47a9b54d724d7d1162fd67dcae6cf0c2"],"add":6501,"del":0,"cadd":5306,"cdel":0,"files":29},{"repo":"operations","hash":"92d72e852b937178701d069d61d44702c15c3de7","ts":1778636975,"wall":"2026-05-12T21:49","msg":"spec: Praxis Operis — Symbiont UI/UX standard (universal scope)","body":"The interaction-identity counterpart to Sphaera Operis. Five axioms\nfrom Bret Victor's Inventing on Principle (2012), applied across three\nlevels of work:\n\n1. Projectional editing — praxis-style live-coding shells for tunable\n   surfaces (scene tuning, layout tuning, palette tuning). The\n   symbiont.systems/praxis/ spike is the first instantiation; the same\n   shell will power elemental, forms, dynamic.\n\n2. Conventional code authoring — same axioms in different form: file\n   as truth, hot-reload by default, no hidden operator-facing state.\n   Implementation internals (GPU state, framework state, JS engine)\n   explicitly excluded; only operator-facing state must be visible.\n\n3. Project structure and tooling — file layout is the truth, build/\n   deploy commands written down and executable verbatim, no tribal-\n   knowledge steps.\n\nReading 2 of the scope question (settled 2026-05-12): the standard\ngoverns ALL Symbiont code, not just tunable surfaces. Praxis shell\nextraction (one codebase serving every Symbiont tool's config\nsurface) is therefore load-bearing, not a nice-to-have.\n\nThe doc also codifies handling of violations in inherited code: fix\nwhen touching the area anyway, don't bulk-rewrite working systems\nfor ideological reasons, document known violations in a per-project\nKNOWN-VIOLATIONS.md.\n\nPairs with Sphaera Operis (visual identity, currently in agent memory).\nLives at the top level alongside BUSINESS.md, DEADLINES.md, etc.","parents":["333c165316da56bb6a478e2492cc20d8380e685b"],"add":272,"del":0,"cadd":272,"cdel":0,"files":1},{"repo":"symbiont.systems","hash":"48d1d6f9b72de7c6ae47397b449abcfe5a9bb24b","ts":1778795457,"wall":"2026-05-14T17:50","msg":"praxis: audit fixes #7-9 + range-hint comments + session handoff","body":"Three bug fixes from the May audit, all in praxis/:\n\n- #7 PalettePreviewWidget.estimatedHeight: removed the override. The\n  base default of -1 is the canonical \"measure me after paint\" signal\n  per CodeMirror docs. The previous constant of 32 caused scroll-\n  position jumps because actual rendered height is ~80 px at typical\n  pane widths.\n\n- #8 Outline self-subscribes via StateEffect.appendConfig. Was only\n  refreshing in onChange's success branch, so structure changes during\n  parse-error state weren't reflected. Outline now listens directly to\n  doc changes via an appended EditorView.updateListener, decoupling it\n  from the parse pipeline. Removed refreshOutlineSoon and\n  _outlineRefreshTimer from main.js (8 lines).\n\n- #9 Telemetry rAF self-cancels when hidden. The animation loop kept\n  rescheduling even when the overlay was hidden, wasting ~0.1ms/frame.\n  Now bails on the visibility check before rescheduling and restarts\n  via start() on toggle, with lastT/frameTimes reset to avoid stale\n  dt on resume.\n\nPlus camera-section range-hint comments in scene.config.js — `fov: 50,\n// 10..120 — wider = more dramatic` style — which the upcoming inline\nbounded-slider widget will use to render visible track + thumb.\n\nPlus session handoff at .claude/handoff.md — robust orientation for\nthe next instance covering the praxis stack, decoration architecture,\nfile-as-truth roundtrip, event flow, known gotchas, and concrete next-\nslice direction (inline bounded sliders as priority #1 for \"interactive\ncode\" widget vocabulary).","parents":["342347c2d4325105618aaafc687deed205b0e340"],"add":378,"del":131,"cadd":378,"cdel":131,"files":6},{"repo":"operations","hash":"a1cb19882c63b9fe086c7526d0ce5add2d99c5d1","ts":1778795492,"wall":"2026-05-14T17:51","msg":"research: praxis widget vocabulary + session handoff","body":"Two related docs from the praxis design sessions (2026-05-13 and 14):\n\nresearch/praxis-widget-vocabulary.md — design notes for extending\npraxis with richer interactive-code widgets. Three sections:\n\n1. Pedagogical motivation. Captures the operator's stated goal:\n   widgets project THROUGH the code, never OVER it. Praxis is the\n   philosophical opposite of WYSIWYG — the source is always primary,\n   widgets amplify it. This is what distinguishes praxis from every\n   no-code / low-code / CMS tool.\n\n2. Rich cards architecture. Decided shape for per-ring content cards:\n   body: ContentBlock[] (matching the deployed site's existing model),\n   with markdown inside text-bearing fields (value/caption/attribution/\n   label). Widget per block type — heading, text, list, link, quote,\n   etc. The deployed site already has the renderContentBlocks + BLOCK_\n   TYPES schema; praxis adopts the same shape so source migrates\n   losslessly.\n\n3. Widget vocabulary expansion. Roadmap for the next slice — buttons\n   (inline +/× action chips, ↻ reset visible when dirty), slides\n   (inline bounded sliders surfacing // 10..120 hints), dials extended\n   to all /speed|rate|breath|cycle/ keys, enum pill selectors, vector\n   pads, computed-value annotations, sparklines. Priority order with\n   LOC estimates.\n\n.claude/handoff.md — robust handoff superseding the April session\nnotes. Covers state of standards (Praxis Operis committed, Sphaera\nOperis still memory-only per the \"ops reform\" deferral), what's\nuncommitted in ops (the operator's bulk-tagged research files etc.),\nmemory references, and pointers to the symbiont.systems handoff for\nall praxis code-side detail.","parents":["92d72e852b937178701d069d61d44702c15c3de7"],"add":371,"del":174,"cadd":371,"cdel":174,"files":2},{"repo":"symbiont.systems","hash":"af2d60a6a5da72fe4c82fb5ceb3fa1fd84e9bf64","ts":1780510525,"wall":"2026-06-03T14:15","msg":"feat: mobile.symbiont.systems business card + phone auto-redirect","body":"- mobile/index.html — single-screen austere card, paper/ink/gold border,\n  Cormorant + Space Grotesk typography, smart QR (URL → vCard endpoint)\n- mobile/contact.vcf — rich vCard 3.0 with name, org, title, role, email,\n  three URLs (portal/git/elemental), Nevada + Puerto Rico addresses, note,\n  categories. Served as text/vcard with content-disposition attachment.\n- site/index.html — mobile-detection redirect at top of <head>,\n  matchMedia(max-width:768px) || matchMedia(hover:none, pointer:coarse),\n  bypassable with ?desktop=1\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["48d1d6f9b72de7c6ae47397b449abcfe5a9bb24b"],"add":242,"del":0,"cadd":225,"cdel":0,"files":3},{"repo":"symbiont.systems","hash":"aec55eae5ccd5fdd6bddc7391fadf3a90c44ffe0","ts":1780510696,"wall":"2026-06-03T14:18","msg":"docs: handoff for 2026-06-03 — mobile.symbiont.systems shipped","body":"Captures this session's work (mobile business card + phone auto-redirect),\npreserves the carried-over praxis context, deploy notes for future mobile\nupdates.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["af2d60a6a5da72fe4c82fb5ceb3fa1fd84e9bf64"],"add":100,"del":194,"cadd":100,"cdel":194,"files":1},{"repo":"symbiont.systems","hash":"617c63ee38f6038e09359a1d4879d3cf53e5056d","ts":1780510931,"wall":"2026-06-03T14:22","msg":"docs: CLAUDE.md current state — mobile + praxis live, portal restructured","body":"Updates Project Structure, Current State, and Deployment sections to\nreflect the live state: two deployable surfaces (portal + mobile card),\none local dev tool (praxis), full Caddyfile co-hosting picture.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["aec55eae5ccd5fdd6bddc7391fadf3a90c44ffe0"],"add":105,"del":71,"cadd":105,"cdel":71,"files":1},{"repo":"symbiont.systems","hash":"cb7ed6d446713e340a7654fee8acc0cdc8d0bbd6","ts":1780515439,"wall":"2026-06-03T15:37","msg":"feat: valis.symbiont.systems — Sphaera Operis bio surface","body":"Personal bio page replacing the never-installed GoToSocial plan. Indieweb\nmarkup throughout (h-card, h-entry placeholder, rel=\"me\", feed discovery)\nso subscribers can follow without checking the page.\n\n- Sphaera Operis aesthetic: dark hermetic background, Aurum Deco gold,\n  Italiana + EB Garamond + Space Grotesk typography, inline armillary\n  sphere mark. This is Sphaera Operis materialized — the visual identity\n  pair to Praxis Operis (which governs the portal + mobile card).\n- Sections: hero/h-card, ABOUT (operator's manifesto voice — three short\n  paragraphs), RESEARCH (the 92-area research list as flowing typographic\n  inventory), CURRICULUM VITAE (timeline with dates), NOTES (empty state\n  for now — webhook-driven feed deferred to next session), ELSEWHERE\n  (rel=\"me\" links to all Symbiont surfaces).\n- Feed discovery <link>s in <head> for /feed.xml + /feed.json (endpoints\n  not yet implemented — coming with the post-webhook).\n- Self-contained single file, inline CSS, Google Fonts, no build step.\n\nServer-side (not in repo): Caddy vhost added (basicauth on /_compose\nand /_post for the future composer + webhook), TLS provisioned via\nDNS-01 challenge. Cloudflare A record added (proxied). social.symbiont.systems\nrecord deleted from Cloudflare.\n\nDeferred to next session: composer page (/_compose), post-webhook daemon\n(/_post), JS wiring of /notes.json → NOTES section.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["617c63ee38f6038e09359a1d4879d3cf53e5056d"],"add":518,"del":0,"cadd":518,"cdel":0,"files":1},{"repo":"symbiont.systems","hash":"6fcb16ca192338aec3e8a1255c7680994e7849e2","ts":1780515571,"wall":"2026-06-03T15:39","msg":"docs: handoff — valis.symbiont.systems shipped, notes infra deferred","body":"Adds the third live surface to the handoff. Sphaera Operis now has a\nmaterial implementation. Captures the operator-voice manifesto in About,\nindieweb markup conventions, DNS state (valis added proxied, social\ndeleted), and the deferred Chunks 4-7 (composer + post-webhook + JS\nwiring) for the next session.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["cb7ed6d446713e340a7654fee8acc0cdc8d0bbd6"],"add":115,"del":101,"cadd":115,"cdel":101,"files":1},{"repo":"symbiont.systems","hash":"ae81429106cb0713f390e1724beb08d8570eea4d","ts":1780515702,"wall":"2026-06-03T15:41","msg":"docs: CLAUDE.md current state — valis.symbiont.systems third surface","body":"Adds valis to What This Is, Project Structure, Visual Architecture,\nCurrent State, Deployment table, and Co-hosted Services. Documents\nSphaera Operis as materialized for the first time. Notes that the\nnotes infrastructure (composer + post-webhook) is scaffolded but\ndeferred. Adds LoRa mesh / autarky stack as a research thread.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["6fcb16ca192338aec3e8a1255c7680994e7849e2"],"add":37,"del":7,"cadd":37,"cdel":7,"files":1},{"repo":"wheel-of-the-heavens","hash":"fb342e0036ad2588d01d5381e8b9e4639e0503dc","ts":1780538564,"wall":"2026-06-03T22:02","msg":"feat: wheel-core foundation — time, ΔT, coordinates","body":"Pure-Rust deep-time ephemeris core for The Wheel of the Heavens. Modules: time (JD, GMST/LST per Meeus 12.4), deltat (Espenak–Meeus piecewise + σ band), coords (Laskar 1986 obliquity + ecliptic→equatorial + altitude). Apache-2.0; NOTICE attributes coefficient sources; algorithm spec in docs/. 19 tests passing.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":[],"add":753,"del":0,"cadd":525,"cdel":0,"files":9},{"repo":"wheel-of-the-heavens","hash":"577c8207e87876c70f1f7a28744d3a782294b5dc","ts":1780539385,"wall":"2026-06-03T22:16","msg":"feat: long-term precession — Vondrák, Capitaine & Wallace (2011)","body":"Ecliptic/equator pole models valid ±200k yr: pole-of-date (the pole star), equinox-of-date (the precessing zodiac / the ages), and J2000→ecliptic-of-date star precession. Coefficients via IAU SOFA/ERFA incl. the published corrigendum; verified against ERFA t_erfa_c.c vectors to 1e-12, plus Polaris and equinox-precession fixtures. 24 tests passing.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["fb342e0036ad2588d01d5381e8b9e4639e0503dc"],"add":249,"del":0,"cadd":249,"cdel":0,"files":2},{"repo":"wheel-of-the-heavens","hash":"1c890485a42bfd0a874036783647a679c4f42c7c","ts":1780543971,"wall":"2026-06-03T23:32","msg":"feat: VSOP87D Sun + planet positions (build-time truncation)","body":"Heliocentric L/B/R series for Earth + the five classical planets, geocentric ecliptic longitudes with light-time iteration, and the Sun (Earth + 180°). A build script parses the vendored Bretagnon & Francou (1988) data and amplitude-truncates to the arcminute budget over ±10 millennia (4 MB raw -> ~290 KB embedded). 29 tests incl. inner-planet elongation bounds. Data is cite-only (VizieR VI/81).\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["577c8207e87876c70f1f7a28744d3a782294b5dc"],"add":26023,"del":0,"cadd":257,"cdel":0,"files":9},{"repo":"wheel-of-the-heavens","hash":"a809426371101f555f00523dab414fcc31e2780c","ts":1780694479,"wall":"2026-06-05T17:21","msg":"feat: ELP/MPP02 Moon position — geocentric ecliptic of date","body":"Truncated ELP/MPP02 lunar theory (Chapront & Francou 2003, DE405 fit):\nlongitude + latitude + distance series, W1 mean-longitude polynomial,\nLaskar (1986) P/Q rotation to the J2000 dynamical ecliptic, then carried\nonto the ecliptic of date to share the VSOP87D Sun/planet frame.\n\nBuild-time INITIAL/READFILE reduction in build_support/elp.rs parses the\noriginal obspm files (cite-only, no GPL-3.0 derived data); reference\nEVALUATE in src/moon.rs. Adds ecliptic_j2000_to_of_date_rad helper to\nprecession.rs (routed through the verified ltecm rotation).\n\nVerified: Meeus 47.a (lambda, beta, Delta to spec), physical\nperigee/apogee bounds and inclination bound across the full +/-10k roam,\nlunar daily motion. 34 tests pass.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["1c890485a42bfd0a874036783647a679c4f42c7c"],"add":37419,"del":0,"cadd":606,"cdel":0,"files":14},{"repo":"wheel-of-the-heavens","hash":"9d55f8eab18c0ebbe8700c25b3becdf9edb47d5e","ts":1780695537,"wall":"2026-06-05T17:38","msg":"test: faster, two-sided Moon roam tests (dense windows + deep-time checkpoints)","body":"The two deep-time roam tests swept +/-10 kyr at 7-day steps (~1.04 M\ngeocentric() calls, ~76 s each) to check a bound. That step is also 1/4 of\nan anomalistic month, so it could miss the sharp perigee minimum: slow and\nblunt.\n\nReplace the brute-force sweep with a shared roam_samples() schedule: three\ndense two-year windows at 6-hour steps (near the past edge, J2000, and the\nfuture edge -- sized to the ~413-day supermoon beat to bracket the full\nperigee-distance envelope) plus coarse 250-year checkpoints across the span\nto catch secular drift. ~8.8 k points, better-resolved at perigee.\n\nBoth tests are now two-sided: keep the containment/inclination bound (catches\namplitude blow-up) and add a reach check -- distance dips to perigee\n(< 362 000 km) and rises to apogee (> 404 000 km); |beta| reaches > 5.0deg --\nwhich catches a collapsed or wrongly-scaled series that pure containment\nwould silently pass.\n\nSuite drops from ~108 s to 0.92 s; 34 tests pass, accuracy anchors\n(Meeus 47.a, daily motion, J2000 longitude) untouched.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["a809426371101f555f00523dab414fcc31e2780c"],"add":54,"del":10,"cadd":54,"cdel":10,"files":1},{"repo":"wheel-of-the-heavens","hash":"54c1283d1264de0c1365e8ba33eb63c3b0115c48","ts":1780695846,"wall":"2026-06-05T17:44","msg":"docs: first session handoff — dynamical core complete, events layer next","body":"Authored by Rowan Valle; executed by Claude Code.","parents":["9d55f8eab18c0ebbe8700c25b3becdf9edb47d5e"],"add":117,"del":0,"cadd":117,"cdel":0,"files":1},{"repo":"wheel-of-the-heavens","hash":"3c227d41ce92eb62541c1c033e55ce5f2cbd9ec9","ts":1780697248,"wall":"2026-06-05T18:07","msg":"feat: events layer — transit-anchored rise/set with ΔT confidence","body":"Turns the dynamical core into an astrolabe face: rise / transit / set,\ndaylength, circumpolar detection, and a confidence band.\n\nThe solver runs in UT (Earth rotation) while body positions are TT = UT + ΔT;\nthat coupling is where the confidence comes from — σ_ΔT (unknowable to ±hours\nin deep time) is carried out as conf_sigma_s on the rise/set times. Nutation\nis skipped engine-wide, so apparent sidereal = mean (time::lmst_deg).\n\nTransit-anchored (Meeus ch.15): solve the meridian crossing first, then\nbracket rise in [transit-12h, transit] and set in [transit, transit+12h] —\ncoherent rise<transit<set, daylength strictly positive, timezone-free. h₀:\nSun -0.8333, planets -0.5667, Moon per-instant 0.7275·π - 0.5667 with\nπ = asin(R⊕/Δ). All solvers capped at 5 iterations: a total function whose\ncircumpolar / non-convergent cases are explicit variants, never bogus times.\n\nAlso exposes vsop87::geocentric_ecliptic_deg (lon+lat) — the wanderers stray\ndegrees off the ecliptic, so planet rise/set needs latitude. geocentric_\nlongitude_deg now delegates to it (no duplication).\n\nVerified against PUBLIC ground truth (USNO API, Rome 2016-12-01, UTC): Sun\n06:18/10:59/15:40 and Moon 07:37/12:35/17:32 — both match to the minute, so\nthe parallax-h₀ Moon needs no full topocentric upgrade. Plus first-principles\ninvariants: equator 12h daylength, 80°N circumpolar, rise<transit<set\ncoherence, transit = altitude maximum, conf band growing to hours in deep\ntime, total-function across extreme latitudes. 43 tests pass.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["54c1283d1264de0c1365e8ba33eb63c3b0115c48"],"add":370,"del":4,"cadd":370,"cdel":4,"files":3},{"repo":"wheel-of-the-heavens","hash":"38211882639b90ecfa7c180a909b965ffc79f462","ts":1780697307,"wall":"2026-06-05T18:08","msg":"docs: handoff — events layer done, shell/zodiac next","body":"Authored by Rowan Valle; executed by Claude Code.","parents":["3c227d41ce92eb62541c1c033e55ce5f2cbd9ec9"],"add":76,"del":64,"cadd":76,"cdel":64,"files":1},{"repo":"wheel-of-the-heavens","hash":"1ef49033d6cb5e6f95641ad146cbce5a6733e495","ts":1780698178,"wall":"2026-06-05T18:22","msg":"test: verify planet events to the minute vs JPL Horizons","body":"Replace the planet coherence-only test with a to-the-minute public anchor.\nJupiter at Rome 2016-12-01 (JPL Horizons, refracted, sea level; events\nmarked r/t/s): rise 01:50 / transit 07:32 / set 13:15 UTC. Engine matches\nto the minute (transit exact; rise/set within 1 min, the refraction-model +\naberration/nutation residual). Horizons is the planet cross-check named in\nthe spec; USNO has no planet GET API.\n\nThis closes the verification gap: the rise/set solver is now anchored to\npublic ground truth for all three body classes — Sun and Moon (USNO),\nplanets (Horizons) — exercising the geocentric-latitude path the wanderers\nneed.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["38211882639b90ecfa7c180a909b965ffc79f462"],"add":13,"del":7,"cadd":13,"cdel":7,"files":1},{"repo":"wheel-of-the-heavens","hash":"7e468170da4df3e26f24cc6bbbf7be1fc826492b","ts":1780699617,"wall":"2026-06-05T18:46","msg":"feat: astrolabe face readouts — twilight, alt/az, lunar phase, zodiac, ages","body":"The interpretive layer of the face, all computed from the existing tables\n(no feeds):\n\n- coords::azimuth_deg — north-based azimuth (Meeus 13.5), beside altitude_deg.\n- events: twilight (Civil/Nautical/Astronomical, the Sun solver at -6/-12/-18°),\n  and horizontal() + sun/moon/planet_altaz — the live 'where is it now' fix and\n  rise/set azimuth (evaluate at the event JD). Body equatorial closures factored\n  into shared helpers so events and alt/az reuse them.\n- moon::phase — elongation, illuminated fraction, waxing/waning, eight-fold name.\n- zodiac (new) — tropical sign/decan, and age() reporting the precessional age\n  three ways from one quantity (precession::vernal_point_j2000_lon_deg):\n    (i)  equal-division sidereal sign via a documented ayanamsa (Lahiri, swappable)\n    (ii) the IAU constellation (vendored ecliptic-boundary table, incl. Ophiuchus)\n    (iii) the raw precession angle + Great-Year fraction, label-free.\n\nVerified against public ground truth: civil twilight 05:47/16:11 and Moon\nillumination 4% waxing crescent (USNO, Rome 2016-12-01); Jupiter rise/set\nazimuth 97.0°/263.2° (JPL Horizons); plus first-principles (sign boundaries,\ndue-south transit) and the well-known ages (Pisces now, Taurus ~2000 BC,\nAquarius ~4000 AD). 55 tests pass.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["1ef49033d6cb5e6f95641ad146cbce5a6733e495"],"add":444,"del":35,"cadd":444,"cdel":35,"files":6},{"repo":"wheel-of-the-heavens","hash":"df177b09de8c156d8f5cfb011a53b7e3b990e340","ts":1780699676,"wall":"2026-06-05T18:47","msg":"docs: handoff — astrolabe face readouts done, shell/star-catalog next","body":"Authored by Rowan Valle; executed by Claude Code.","parents":["7e468170da4df3e26f24cc6bbbf7be1fc826492b"],"add":76,"del":77,"cadd":76,"cdel":77,"files":1},{"repo":"wheel-of-the-heavens","hash":"3ebecfa9cb49f693199ae68e4a8d9f870a1fe072","ts":1780700644,"wall":"2026-06-05T19:04","msg":"feat: bright-star catalog — rete, pole star, heliacal risings","body":"Vendors a curated public-domain bright-star catalogue (Yale BSC5 / VizieR\nV/50, mag <= 2.5 + Thuban, 94 stars) as a cited const, and turns it into:\n\n- pole_star(jd): nearest catalogue star to the precessed pole. Polaris now\n  (sep 0.46deg, matching the known 0.4526deg closest approach), Thuban ~2800 BC\n  (0.10deg), Vega ~13700 AD.\n- star_ecliptic_of_date / star_altaz: the rete — each star precessed onto the\n  sky of date, with PROPER MOTION applied first (mandatory: Sirius moves ~3.7deg\n  over +/-10k yr, far past the arcminute budget; a fixed-J2000 catalogue would be\n  degrees wrong for the bright nearby stars).\n- heliacal_rising / heliacal_setting: simplified arcus-visionis first/last dawn\n  visibility (the Sothic phenomenon). Sirius at Cairo lands ~late July; ~10 days\n  before the extinction-corrected early-August date — the simplified model's\n  known systematic bias (tests the star at the geometric horizon). Documented as\n  approximate; full Schaefer extinction is the upgrade path.\n\nReuses precession (equator_pole, eq_to_ecliptic_of_date, separation), coords,\nand events::horizontal — no new core math. 61 tests pass.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["df177b09de8c156d8f5cfb011a53b7e3b990e340"],"add":363,"del":0,"cadd":363,"cdel":0,"files":3},{"repo":"wheel-of-the-heavens","hash":"b7d6a97aae205d910585c276aef26d86a22b08a6","ts":1780700704,"wall":"2026-06-05T19:05","msg":"docs: handoff — star catalog done, WASM shell next","body":"Authored by Rowan Valle; executed by Claude Code.","parents":["3ebecfa9cb49f693199ae68e4a8d9f870a1fe072"],"add":49,"del":64,"cadd":49,"cdel":64,"files":1},{"repo":"wheel-of-the-heavens","hash":"25fb7053783a71e30a6fb85369696616c426d02c","ts":1780701899,"wall":"2026-06-05T19:24","msg":"feat: shell phase 1 — wasm binding + Vite pipeline","body":"Make the repo a Cargo workspace (core + wasm, mirroring forms). Add the\nwheel-wasm binding crate: sky(jd_ut, lat, east_lon) returns everything for an\ninstant (sun/moon/planet ecliptic+equatorial+horizontal positions, moon phase,\nthe age in all three framings, pole star, sun/moon rise-set + civil twilight\nwith the sigma_dT confidence band, sidereal time, obliquity) and rete(jd)\nreturns the 94-star catalogue projected to the equator of date. Typed returns\nvia tsify (generated TS); the engine ships inside the WASM, no network.\n\nAdd the Vite web frontend: a Sphaera-styled instrument readout of the live sky\n(replaced by the Three.js celestial mechanism in phase 2). Full pipeline proven:\nwasm-pack -> vite -> static dist (WASM 165 KB gzipped), runs offline.\n\nBoundary test: sky() preserves the engine's USNO/Horizons-anchored values\n(Rome sun rise 06:18, age Pisces, moon waxing crescent 4%).\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["b7d6a97aae205d910585c276aef26d86a22b08a6"],"add":1598,"del":0,"cadd":461,"cdel":0,"files":10},{"repo":"wheel-of-the-heavens","hash":"f4bcbfbd24bc0cd39c232a4c2c286c525cd8c398","ts":1780703098,"wall":"2026-06-05T19:44","msg":"feat: shell phase 2 — Three.js celestial mechanism + layer menu","body":"The renderer. A 3-D armillary in the equatorial-of-date frame (NCP +Y, vernal\nequinox +X): the 94-star rete as gilded magnitude-scaled points, the violet\necliptic / gold equator / faint colure rings, the wanderers as luminous bodies,\na dashed precession ring riding the pole, the horizon + meridian for the place,\nall under an UnrealBloom glow in the Sphaera void. OrbitControls + slow\nauto-rotate.\n\nLabels (CSS2DRenderer, crisp DOM over GL): the wanderers, the pole star and\nvernal-point markers, all 94 stars (off by default), and constellation names\n(IAU full names) at centroids.\n\nRight-click context menu toggles all 12 layers — on-demand chrome, no persistent\npanel (Praxis-compliant). sky() now echoes the observer latitude for the horizon\nconstruction.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["25fb7053783a71e30a6fb85369696616c426d02c"],"add":498,"del":99,"cadd":486,"cdel":99,"files":9},{"repo":"wheel-of-the-heavens","hash":"0d20749d9d0737d210e71b1dffc9656293342485","ts":1780703161,"wall":"2026-06-05T19:46","msg":"docs: handoff — shell phases 1-2 done, scrubber/palette/ops next","body":"Authored by Rowan Valle; executed by Claude Code.","parents":["f4bcbfbd24bc0cd39c232a4c2c286c525cd8c398"],"add":85,"del":81,"cadd":85,"cdel":81,"files":1},{"repo":"wheel-of-the-heavens","hash":"d911b13d69749d3005a652121041a8ce0ef45e9d","ts":1780752632,"wall":"2026-06-06T09:30","msg":"perf: pool scene objects, split update() by rate-of-change","body":"update() rebuilt ~140 DOM nodes + geometries every call — fine for a single\nrender, ruinous for per-frame time-scrubbing. Now every object (94 star labels,\nconstellation labels, 7 wanderer meshes+labels, markers, star Points geometry)\nis created once and mutated in place; CSS2DRenderer already only updates a\ntransform on existing elements, so per-frame label cost collapses to that.\n\nSplit into setEpoch(rete, sky) — stars, constellations, rings, precession, pole\nname: only when the year moves (precession is ~50 arcsec/yr) — and\nsetInstant(sky) — wanderers, horizon, meridian: every tick. update(sky, rete)\ngates the epoch rebuild on the integer year, so callers stay simple and\nwithin-day scrubbing never touches the rete.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["0d20749d9d0737d210e71b1dffc9656293342485"],"add":116,"del":75,"cadd":116,"cdel":75,"files":1},{"repo":"wheel-of-the-heavens","hash":"3c0f22634085f2db3e2fc993383da433ce51e25c","ts":1780768677,"wall":"2026-06-06T13:57","msg":"data: vendor coastline + cities for the shell","body":"- coastline.json — Natural Earth 1:110m coastline (public domain), trimmed.\n- cities.json — 243 world cities (Natural Earth, public domain) + Puerto Rico's\n  78 municipios (GeoNames, CC-BY 4.0), accented display names, population-sorted.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["d911b13d69749d3005a652121041a8ce0ef45e9d"],"add":2,"del":0,"cadd":0,"cdel":0,"files":2},{"repo":"wheel-of-the-heavens","hash":"23d36ba83490b72f20411e9011c639c526873f3d","ts":1780768693,"wall":"2026-06-06T13:58","msg":"feat: shell — interaction layer, Earth globe, switchable location","body":"Turns the celestial mechanism into an instrument you operate.\n\nInteraction:\n- Context-sensitive right-click menu: pick a star / wanderer / marker / the Earth\n  for an inspection card (Focus, or Observe-from-here); empty sky → layer toggles.\n- Layer menu organised by the sky's structure (Wanderers / Fixed stars / Ecliptic\n  / Equatorial / Horizon frames) with tri-state group headers + view presets\n  (Naked eye / Instrument / Everything / Bare). Pole and vernal point split out of\n  the old markers into their natural frames.\n- The  command palette (Praxis Axiom #1): fuzzy-search every layer, view, and\n  nameable object — stars, constellations, wanderers, the cardinal points — and\n  fly to it. Accent-blind (Bayamón matches bayamon).\n\nThe Earth (geocentric heart of the armillary):\n- A gilded engraved globe at the origin, axis on the celestial pole, spun by GMST\n  so its geography tracks the stars; gold graticule + coastlines; the observer\n  pinned with a zenith line to the sphere. New  field on sky().\n- Topographic relief + day/night terminator are the staged next step.\n\nSwitchable observer location (three ways, all via setLocation):\n- Click the Earth → Observe from here (raycast → un-spin GMST → invert geo).\n-  named places — 243 world cities + all 78 PR municipios.\n-  — parameterized coordinate entry.\n\nScene objects are pooled (setEpoch/setInstant) so all of this stays smooth under\nthe coming time-scrubber.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["3c0f22634085f2db3e2fc993383da433ce51e25c"],"add":648,"del":50,"cadd":648,"cdel":50,"files":7},{"repo":"wheel-of-the-heavens","hash":"94696f15e493ba768622f25865f0a527d517274f","ts":1780769027,"wall":"2026-06-06T14:03","msg":"docs: update handoff — interaction layer, Earth, switchable location; topo + scrubber next","body":"","parents":["23d36ba83490b72f20411e9011c639c526873f3d"],"add":87,"del":59,"cadd":87,"cdel":59,"files":1},{"repo":"wheel-of-the-heavens","hash":"220db94446034cea9fda61c7d383ac5819733dcb","ts":1780784666,"wall":"2026-06-06T18:24","msg":"docs: draft Calendric — the Symbiont sky-calendar spec","body":"Calendric: THE calendar — a projection of Julian Day that is the sky itself, every\nunit a motion the engine computes from first principles, never a table. Universal,\nwith Azura the initiatrix.\n\nSix nested cycles: the Age (era, the precessional Great Year, years counted from the\nvernal point's entry into the sign); the Solar Year (the Passion of the Sun, opening\nat the vernal equinox, eight stations each held by a totem of Artemisia — the Hare,\nEagle, Puma, Antelope, Ram, Coywolf, Raven, and the Teacher/Muad'Dib, the Basin's\nendemic kangaroo mouse); the zodiac + 24 solar terms (months); the planetary\nseven-day week; the concurrent lunar voice (phase, analemma, the 18.6-yr standstill);\nand the wanderers' tapestry. One inscription carries era, solar, lunar, planetary.\n\nThe totems mark the stations; their meaning, and the mythology, are bracketed as a\nlater study — nothing ascribed in advance. Calendric is the purpose that pulls in the\nengine's event-finders (solstices/equinoxes/cross-quarters, lunations, standstills,\nretrogrades, conjunctions). The third named Symbiont standard after Sphaera Operis\nand Praxis Operis. Status: draft.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["94696f15e493ba768622f25865f0a527d517274f"],"add":178,"del":0,"cadd":178,"cdel":0,"files":1},{"repo":"wheel-of-the-heavens","hash":"6e1405701ca152a93022eb0896c2b1f826fd528b","ts":1780800451,"wall":"2026-06-06T22:47","msg":"feat: shell — time-movement (deep-time roam, scrub, real-time, LMT)","body":"The headline roam. The static render becomes a clock: { jd, playing, rate,\nlive }. A rAF loop either tracks the wall clock drift-free (live) or advances\njd by rate×dt (playing). Boots live, so the sky moves in real time from the\nfirst frame. Space = play/pause, ←/→ = ±1 day, n/Home = now.\n\nThe time cartouche (new) — a centered Sphaera Deco readout where every date\nfield is drag-to-scrub (Praxis direct manipulation): day/month/hour/min/sec by\none, the year by digit (grab the thousands to ride millennia), and the Age to\nride precession by hand. JD↔Gregorian is proleptic (year 0 exists, no 1582\nseam); round-trip verified exact, including deep BCE. A log-scaled throttle\ndial sets the play rate, real time → millennia/s, with a centre dead-zone pause.\n\nTimezones — the readout is Local Mean Time at the observer's meridian\n(jd + lon/360); the clock stays UT. Pure geometry: no zone database, valid\nacross all ±10k years, follows the observer. Scrubs operate in the local frame\nthen convert back to UT, so direct manipulation stays honest across the date\nline. Sub-line shows e.g. \"13:45:30 LMT · UT+2:19\".\n\nRemoved the decorative camera autoRotate — the only motion in the scene is now\nthe sky itself, driven by the clock (~15″/s at real time, as it should be).","parents":["220db94446034cea9fda61c7d383ac5819733dcb"],"add":318,"del":21,"cadd":318,"cdel":21,"files":4},{"repo":"wheel-of-the-heavens","hash":"d0877dc35061486010035836cb7262cae36078fc","ts":1780801687,"wall":"2026-06-06T23:08","msg":"feat: core — solve.rs, the generic root-finding primitive for the almanac","body":"The ephemeris gives a position at a time; the almanac asks when a position is\nreached. That inversion is a 1-D root-find on a smooth function of Julian Day.\nsolve.rs is that primitive, kept small: safeguarded bisection (find_root) plus a\ncentral-difference derivative (central_diff). Extrema — retrograde stations,\ngreatest elongations — are found as roots of the derivative, so one algorithm\ncovers every event kind. Bisection over Newton: the ephemeris functions are\nnear-linear over an event bracket, so it cannot diverge and needs no analytic\nderivative. The trunk every A1 finder and all of A2 (eclipses, standstills) reuse.","parents":["6e1405701ca152a93022eb0896c2b1f826fd528b"],"add":112,"del":0,"cadd":112,"cdel":0,"files":2},{"repo":"wheel-of-the-heavens","hash":"4a6b4e19c5d223d2fcd4bba943f2b4db8452aa51","ts":1780802926,"wall":"2026-06-06T23:28","msg":"feat: core — almanac solar events (solstices, equinoxes, cross-quarters)","body":"find_event(jd_ut, kind, forward) locates the eight stations of the Sun's\necliptic longitude — the four quadrant points and the four cross-quarter days\n(Imbolc/Beltane/Lughnasadh/Samhain) midway between them. Each is a root-find\n(solve::find_root) on wrap180(sun_longitude_deg − target): the Sun never\nregresses, so the genuine crossing is g rising through zero, and the ±180°\ndiscontinuity half a cycle away is a downward jump that's structurally skipped.\nSearches in TT, returns Event in both time scales plus the ΔT σ band.\n\nGeometric basis (operator decision): events are defined on the engine's\ngeometric solar longitude, consistent with the displayed sky — jump to a\nsolstice and the Sun reads exactly 90°. Instants therefore lead the apparent\nUSNO times by aberration (~8 min) + nutation (~6 min) ≈ 14 min near the\npresent; the test pins exactly that lead band for 2000, and in deep time the\ngap vanishes beneath the ΔT σ (hours). Verified vs USNO Earth's Seasons 2000;\ngeometric longitude sits on target to 1e-4°; next/prev bracket the start.","parents":["d0877dc35061486010035836cb7262cae36078fc"],"add":262,"del":0,"cadd":262,"cdel":0,"files":2},{"repo":"wheel-of-the-heavens","hash":"a233cbde91feb6aa4d8acb5e9055207c3d88f288","ts":1780803180,"wall":"2026-06-06T23:33","msg":"feat: core — almanac lunar phases (new, quarters, full)","body":"Adds the four lunar phases to find_event: new / first-quarter / full /\nlast-quarter, defined by the Moon–Sun elongation (λ☽ − λ☉) crossing\n{0,90,180,270}°. Same root-finding machine as the solar stations — the\nelongation rises ~12.2°/day, and wrap180 absorbs both longitudes' 360° wraps\nsince they cancel mod 360.\n\nThese geometric phase times track the apparent sky closely (unlike the solar\nstations): nutation and annual aberration both cancel in the Moon−Sun\ndifference, leaving only the ~17″ Moon-series error. Verified vs USNO Phases of\nthe Moon 2000 to within 4 min; consecutive new moons span one synodic month.","parents":["4a6b4e19c5d223d2fcd4bba943f2b4db8452aa51"],"add":66,"del":4,"cadd":66,"cdel":4,"files":1},{"repo":"wheel-of-the-heavens","hash":"9dc76739189b06d4b79ba15c06ffd45d6b849ab7","ts":1780803752,"wall":"2026-06-06T23:42","msg":"feat: shell — almanac jumps (next/previous solstice, equinox, phase)","body":"Wires the solar + lunar event-finders through to the instrument. The wasm\nboundary gains find_event(jd_ut, kind, forward) -> EventOut | undefined: a\nstring→kind parser over the twelve A1 events, returning the UT instant, a\ndisplay label, and the ΔT σ band. A native boundary test confirms it locates\nthe same geometric 2000 solstice the core verifies.\n\nIn the shell, the `/` palette gains an Almanac category — \"Next · June\nsolstice\", \"Previous · New Moon\", and the rest, 24 jumps in all. Selecting one\ncalls jumpToEvent, which finds the instant and setTime travels to it. The\ncartouche gains an event banner that names what we landed on and, in deep time,\nits honest ±band (minutes near now, hours at the edges); it clears the moment\ntime moves any other way — scrub, dial, or live.","parents":["a233cbde91feb6aa4d8acb5e9055207c3d88f288"],"add":121,"del":6,"cadd":121,"cdel":6,"files":5},{"repo":"wheel-of-the-heavens","hash":"b9b7e24b9c16694b855b2f4c35ad07608916fd12","ts":1780804379,"wall":"2026-06-06T23:52","msg":"feat: shell — the Moon shows its true phase","body":"The Moon was a flat cream disc. Now a shader lights the hemisphere facing the\nSun's sky direction, so the disc carries its real phase — waxing crescent\nthrough full to waning — with the bright limb pointing at the Sun, and a soft\nterminator across the middle. The unlit side sits at a faint earthshine tone\nabove the void rather than vanishing.\n\nPhase is geocentric and the camera orbits the origin, so the shading is exact:\ndot the surface normal with the Sun direction (both in the bodies' frame, so\nrotation-invariant). New moon turns the lit face away from us; full moon turns\nit toward us; quarters show half. The Sun direction is refreshed each instant\nfrom the Sun body's position, so the phase tracks as time moves.","parents":["9dc76739189b06d4b79ba15c06ffd45d6b849ab7"],"add":30,"del":2,"cadd":30,"cdel":2,"files":1},{"repo":"wheel-of-the-heavens","hash":"c355fc4fec62395dba261d5df013405b4f452026","ts":1780867245,"wall":"2026-06-07T17:20","msg":"feat(almanac): planet conjunctions and oppositions","body":"Add four planet-Sun configuration events to the event-finder, defined on\nthe body's geocentric longitude relative to the Sun:\n\n  Conjunction(b)          outer planet behind the Sun (relative lon 0deg)\n  Opposition(b)           outer planet opposite the Sun (180deg)\n  InferiorConjunction(b)  inner planet between Earth and Sun (falling 0deg)\n  SuperiorConjunction(b)  inner planet beyond the Sun (rising 0deg)\n\nGeneralize find_longitude_crossing into find_zero_directed: one scanner\nserves every event by taking a crossing direction. A solstice is the\nsolar longitude rising through its target; a conjunction is relative\nlongitude falling through zero; a station (next chunk) is the longitude\nrate falling through zero. find_longitude_crossing is now a thin rising\nwrapper; find_relative_longitude spans one synodic period plus margin.\n\nlabel() returns String to carry the body name. Aberration cancels in the\nplanet-Sun difference, so geometric oppositions match published 2020\ndates within a day (Jupiter 07-14, Saturn 07-20, Mars 10-13, verified).\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["b9b7e24b9c16694b855b2f4c35ad07608916fd12"],"add":165,"del":34,"cadd":165,"cdel":34,"files":1},{"repo":"wheel-of-the-heavens","hash":"7df4d69faf8a4df81f2fbad2b0b69a117a7f2f70","ts":1780867662,"wall":"2026-06-07T17:27","msg":"feat(almanac): retrograde stations and greatest elongations","body":"Add the four derivative-zero planet events — the turning points of\napparent motion rather than longitude crossings:\n\n  StationaryRetrograde(b)   dλ/dt falling through 0 (prograde → retrograde)\n  StationaryDirect(b)       dλ/dt rising through 0  (retrograde → prograde)\n  GreatestElongationEast(b) relative longitude at its maximum (evening sky)\n  GreatestElongationWest(b) relative longitude at its minimum (morning sky)\n\nBoth are roots of an angular rate, so the same find_zero_directed scanner\nserves them: a station is the geocentric longitude rate crossing zero; an\nelongation is the Sun-relative longitude rate crossing zero. The crossing\ndirection encodes the kind — falling for retrograde / east, rising for\ndirect / west — so no secondary filtering is needed. Rates are central\ndifferences over a quarter-day half-step (RATE_STEP_DAYS), well above the\nVSOP87 noise floor and locally linear across the turn.\n\nVerified against published 2020 ephemerides (JPL Horizons cross-checkable):\nMars/Jupiter/Saturn stations within 1.5 days; Venus and Mercury greatest\nelongations within 1 day, with elongation magnitudes matching the known\nbands (Venus ~46°, Mercury 18°/28°). Geometric stations lead apparent by\nunder a day — aberration barely shifts a rate zero.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["c355fc4fec62395dba261d5df013405b4f452026"],"add":125,"del":1,"cadd":125,"cdel":1,"files":1},{"repo":"wheel-of-the-heavens","hash":"a788096342acb79261cd60a5c89fd4cf921b21ea","ts":1780867935,"wall":"2026-06-07T17:32","msg":"feat(shell): wire planet events into the palette","body":"Expose the eight planetary event kinds through the wasm boundary and the\ncommand palette, completing the almanac.\n\nparse_event_kind now reads \"{body}_{event}\" strings — mars_opposition,\nvenus_greatest_elongation_west, jupiter_stationary_retrograde — splitting\nthe body prefix from the event so one arm covers all five planets. Unknown\nbody or event still returns None (the shell no-ops the jump).\n\nThe palette generates its 24 planetary entries per planet rather than\nhand-listing them: inner planets (Mercury, Venus) get inferior/superior\nconjunctions and greatest elongations east/west; outer planets (Mars,\nJupiter, Saturn) get conjunction and opposition; all five get retrograde\nand direct stations. With the twelve seasonal and lunar entries that is\n36 events, each a Next/Previous jump.\n\nlabel() returns String now, so the redundant .to_string() at the boundary\nis gone. Boundary test routes mars_opposition (geometric, within a day of\nthe published 2020-10-13) and a labelled Venus greatest elongation.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["7df4d69faf8a4df81f2fbad2b0b69a117a7f2f70"],"add":71,"del":3,"cadd":71,"cdel":3,"files":2},{"repo":"wheel-of-the-heavens","hash":"9b9af9879bd7faf785c45b584a8c0342ea592241","ts":1780868081,"wall":"2026-06-07T17:34","msg":"docs: refresh handoff — almanac complete, planet events wired","body":"The handoff was stale at 23d36ba (61 tests, almanac unbuilt). Bring it\ncurrent: 80 core tests, the time-movement roam, the Moon's true phase, and\nthe complete almanac (36 jumpable events across solar, lunar, and the eight\nplanetary configurations). Earth topo + relief and the ops phase are now\nthe only remaining work.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["a788096342acb79261cd60a5c89fd4cf921b21ea"],"add":92,"del":71,"cadd":92,"cdel":71,"files":1},{"repo":"wheel-of-the-heavens","hash":"ece054e788395ff213e5f3ac13c87ad3700ee50f","ts":1780884856,"wall":"2026-06-07T22:14","msg":"feat(almanac): apsides — perihelion, aphelion, lunar perigee/apogee","body":"The almanac located syzygies and longitude crossings but no distance\nextrema. Add the four apsides as zeros of the distance rate dr/dt — the\nsame find_zero_directed primitive the planetary stations use, now on a\nscalar distance instead of a longitude rate. Minimum (rate rising) is\nperi-, maximum (falling) is apo-.\n\nEarth's distance comes from VSOP87 (heliocentric r, the Earth–Moon\nbarycentre); the Moon's from the ELP geocentric distance. Verified:\nperihelion 2000 Jan 3 / aphelion Jul 3 at 0.983/1.017 AU, lunar perigee\nand apogee in the textbook envelopes with the 27.55-day anomalistic\nspacing, all sitting on a zero rate with the correct curvature.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["9b9af9879bd7faf785c45b584a8c0342ea592241"],"add":106,"del":0,"cadd":106,"cdel":0,"files":1},{"repo":"wheel-of-the-heavens","hash":"64657063106025f0d5f907367a5ebff3a4635020","ts":1780885207,"wall":"2026-06-07T22:20","msg":"feat(almanac): lunar standstills — the 18.6-year nodal cycle","body":"Major and minor lunar standstills, the slow envelope the deep-time\nastrolabe exists to show. A standstill is fixed by the longitude of the\nMoon's mean ascending node Ω (Meeus 47.7): major when Ω regresses through\n0° (the orbit's tilt to the equator maxes at ε+i ≈ 28.7°), minor at\nΩ = 180° (ε−i ≈ 18.3°). Each is a falling crossing of the node target —\nthe same directed root-find as everything else in the almanac.\n\nVerified: the node sits on 0°/180° at the found instants, which fall in\n2006 and 2015 (the cited major and minor standstills), successive majors\none nodal period apart (6798 d). The physical payoff is checked directly —\nsampling the Moon's declination across the standstill lunation, the\nenvelope widens past 28° at major and narrows below 19° at minor.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["ece054e788395ff213e5f3ac13c87ad3700ee50f"],"add":73,"del":0,"cadd":73,"cdel":0,"files":1},{"repo":"wheel-of-the-heavens","hash":"76975855f3eee74881083ef65b7f23ef23f7cbe5","ts":1780885647,"wall":"2026-06-07T22:27","msg":"feat(almanac): eclipses — solar and lunar, with type","body":"The last piece of the classical almanac. An eclipse is a syzygy that\nfalls near a node: the finder walks successive new (solar) or full\n(lunar) Moons and stops at the first whose latitude brings the Moon — or\nEarth's shadow — across the disc. The type is read off the geometry at\nthe instant (Meeus ch. 54), from the real angular radii and parallaxes:\n\n  - Solar: γ = |β| / π☽ is the shadow axis's least distance from Earth's\n    centre. γ < 0.9972 is central (total if the Moon's disc covers the\n    Sun, else annular); out to 1.5433 only the penumbra grazes (partial).\n  - Lunar: |β| against the umbral and penumbral cones π☽ + π☉ ∓ s☉,\n    enlarged 2% for the atmosphere — total, partial, or penumbral.\n\nclassify_solar_eclipse / classify_lunar_eclipse expose the type to the\nshell. Geocentric: it reports the eclipse that occurs somewhere on Earth,\nnot where — locality needs Besselian elements, outside this engine.\n\nVerified against the NASA Five Millennium Canon — six eclipses spanning\nall four solar/lunar types, each matched in date and kind: 2000-02-05\npartial, 2017-08-21 total, 2012-05-20 annular solar; 2000-01-21 and\n2019-01-21 total, 2016-03-23 penumbral lunar. Backward search brackets\nthe start and steps past the non-eclipse new Moons between seasons.\n\nThe lunar-phase root-find is factored into find_lunar_phase_tt, now\nshared by the phase events and the eclipse walker.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["64657063106025f0d5f907367a5ebff3a4635020"],"add":181,"del":5,"cadd":181,"cdel":5,"files":1},{"repo":"wheel-of-the-heavens","hash":"03cac32c90b35fd816444182038cbd88e368348e","ts":1780939490,"wall":"2026-06-08T13:24","msg":"feat(engine): per-body distance, size, and heliocentric place","body":"Phase 0 of the true-scale model. Until now every body crossed the WASM\nboundary as direction only (ra/dec); the scene pinned them all to one\nshell. To show occultation and eclipse as real geometry, the renderer\nneeds depth and size, so the engine now reports them.\n\nBodyPos gains dist_au (light-time geocentric distance), ang_radius_deg\n(apparent semidiameter), radius_km (true draw size), and helio (the\nheliocentric place, AU) for the orrery frame. Sky gains earth_helio.\n\nNew core/src/physical.rs is the one source of truth for body radii, the\nastronomical unit, and the semidiameter helper. The almanac's eclipse\ngeometry was consuming private duplicates of these; it now shares the\nmodule, so the shadow math and the renderer can never drift apart.\n\nvsop87 folds the light-time loop into one geocentric_vector, then exposes\ngeocentric_distance_au and heliocentric_xyz on top of it.\n\nThe existing armillary is unchanged: the scene still ignores the new\nfields. Nothing moves off the shell until Phase 1.\n\nTests: core 87 -> 92 (semidiameters in arcminutes, nearer subtends wider,\ngeocentric distance brackets each planet, |xyz| = r); wasm +1 boundary\ntest. The six historical eclipse fixtures survived the refactor untouched.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["76975855f3eee74881083ef65b7f23ef23f7cbe5"],"add":320,"del":27,"cadd":320,"cdel":27,"files":5},{"repo":"wheel-of-the-heavens","hash":"bbf77c8b2404347092c4da53f1ed2cc6cdfd3596","ts":1780948073,"wall":"2026-06-08T15:47","msg":"docs: planetary appearance research for the orrery","body":"Verified physical parameters (radii, oblateness, axial tilt, rotation,\nalbedo), true visible-light colours, Saturn's ring table, and autarky-safe\nreproduction recipes (procedural shaders plus public-domain texture\nsources) for the Sun, the Moon, and the planets. NASA NSSDCA-grounded;\nsources and licenses verified. Indexed into the unicursal RAG.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["03cac32c90b35fd816444182038cbd88e368348e"],"add":327,"del":0,"cadd":327,"cdel":0,"files":1},{"repo":"wheel-of-the-heavens","hash":"3755c6d6548fa90df7e5d26abd3b40fa553b0156","ts":1780948085,"wall":"2026-06-08T15:48","msg":"assets: vendor public-domain planet surface maps","body":"Earth (NASA Blue Marble day, Black Marble night-lights, cloud composite),\nthe Moon (NASA SVS LROC colour), and Mercury (USGS MESSENGER mono), all\n2048x1024 and served locally from web/public/textures — no runtime fetch,\nno attribution burden (every map is public domain). The orrery's realistic\nview wears these; Mars and Venus stay procedural.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["bbf77c8b2404347092c4da53f1ed2cc6cdfd3596"],"add":0,"del":0,"cadd":0,"cdel":0,"files":5},{"repo":"wheel-of-the-heavens","hash":"2bce3e6c512dc53cd498ada609cd9fdf2e1091eb","ts":1780948106,"wall":"2026-06-08T15:48","msg":"feat: heliocentric orrery as a second frame","body":"A frame toggle (key f, palette \"Frame ...\") swaps the geocentric armillary\nfor a heliocentric orrery on a second canvas — the Sun at the origin, the\nplanets and the Earth-Moon pair at their true heliocentric places. Two\nviews (key v): realistic (true size) and instrumental (bodies enlarged\nx40, ratios kept); fly-to navigation to any body.\n\nBodies are real lit spheres — true phase from dot(N, sunDir), axial tilt,\nsidereal spin, oblateness. The Sun is an emissive limb-darkened disc; the\ngas giants are procedurally banded (Jupiter's Great Red Spot, Saturn's\nrings); Earth, the Moon, and Mercury wear the vendored maps; Mars and Venus\nare procedural. A pixel-floored dot per body is the far-LOD fallback.\n\nEclipses play out from real geometry: a per-fragment shadow test darkens\nEarth under the Moon's umbra (solar) and the Moon under Earth's (lunar,\nblood-red), with translucent umbra and penumbra cones in space. Earth's\nspin is locked to the engine's GMST (correct geography under the\nterminator); the Moon is tidally locked, near-face to Earth.\n\nAlso folds in pending armillary work entangled in these files: the\nday/night terminator on the central globe, the lunisolar and eclipse\nalmanac events in the command palette, and the \"Cycles\" title.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["3755c6d6548fa90df7e5d26abd3b40fa553b0156"],"add":810,"del":27,"cadd":810,"cdel":27,"files":7},{"repo":"wheel-of-the-heavens","hash":"865856275bb72ad47679f332313edbc072ae3e31","ts":1780950477,"wall":"2026-06-08T16:27","msg":"fix(engine): clamp asin so a zenith transit doesn't return NaN","body":"The altitude formula's argument is cos(zenith distance) ≤ 1, but float\nrounding pushes it ~1 ULP past 1.0 exactly when a body transits the\nobserver's zenith (dec ≈ lat, HA ≈ 0), so asin returns NaN — a user-facing\nwrong altitude (and a spurious rise/set non-convergence in the solver).\nClamp to [-1, 1] before asin at the four sites (altitude_deg,\necliptic_to_equatorial, the rise/set refine, and the Moon's latitude).\n\nFound by a full-codebase audit; 92 core tests still pass.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["2bce3e6c512dc53cd498ada609cd9fdf2e1091eb"],"add":7,"del":3,"cadd":7,"cdel":3,"files":3},{"repo":"wheel-of-the-heavens","hash":"63b333d0605911e6b30bac8c585658d0259b20e5","ts":1780950489,"wall":"2026-06-08T16:28","msg":"fix(web): pool the armillary's horizon/meridian (per-frame GPU leak)","body":"setInstant rebuilt the horizon and meridian great circles every animation\nframe via greatCircle(), allocating a fresh BufferGeometry + material each\ntime; Group.clear() drops them without disposing, so the GPU buffers\norphaned at ~60 fps in live mode (~20 MB/min → eventual context loss).\nPool both as fixed-buffer LineLoops and rewrite their vertices in place.\nAlso fall back to another seed axis so the meridian doesn't collapse at the\ngeographic poles.\n\nFound by a full-codebase audit.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["865856275bb72ad47679f332313edbc072ae3e31"],"add":34,"del":10,"cadd":34,"cdel":10,"files":1},{"repo":"wheel-of-the-heavens","hash":"3f60b28fed5f2d3e3bb0918604081df536c742ed","ts":1780950505,"wall":"2026-06-08T16:28","msg":"feat: the figures the orbits weave — orbit + resonance traces","body":"The orrery's crown jewel: see the patterns orbital motion makes. Two layers\ntoggle on (key o, palette \"Orbits …\" / \"Pattern …\"): the heliocentric orbit\nellipses, and a resonance web — at regular instants over a closing span a\nline is drawn between Earth and a chosen planet, and the envelope is the\nfigure their two orbits trace. Earth–Venus over 8 years draws the\nfive-petalled pentagram rose (the 5:8 resonance); Jupiter an 11-fold\nmandala; and so on.\n\nA new lightweight engine endpoint, body_positions(jd), returns just the\nheliocentric places (VSOP87 + the lunar theory, no events), so sampling the\nthousand-plus points a pattern needs never pays the cost of full sky().\n\nAlso folds in the orrery render-audit fixes (same files): drop the inert\nlogarithmicDepthBuffer so the custom sphere shaders and the MeshBasic\nshadow cones share one depth encoding; gate the eclipse shadows and shadow\ncones to the realistic view (true-scale geometry can't fit the ×40\ninstrumental bodies); reuse the day texture for unused samplers.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["63b333d0605911e6b30bac8c585658d0259b20e5"],"add":157,"del":21,"cadd":157,"cdel":21,"files":4},{"repo":"wheel-of-the-heavens","hash":"e75fa6052a51481de9016a26e274d5efb49bc14d","ts":1780950617,"wall":"2026-06-08T16:30","msg":"docs: refresh handoff — orrery arc complete (crown jewel + audit)","body":"Authored by Rowan Valle; executed by Claude Code.","parents":["3f60b28fed5f2d3e3bb0918604081df536c742ed"],"add":50,"del":142,"cadd":50,"cdel":142,"files":1},{"repo":"wheel-of-the-heavens","hash":"4d1e6ef4d5ba5c2ce6018453baaf75b15b3c3bc6","ts":1781118875,"wall":"2026-06-10T15:14","msg":"feat(engine): naked-eye star catalogue (5080 stars) + named-only pole star","body":"Expand the public-domain Yale BSC5 subset from the 94 hand-curated named stars\n(V<=2.5) to the full naked-eye sky, V<=6.0 -- 5080 stars. The appended stars are\nreal (HR designations, measured positions, proper motion, magnitude); they are\nunnamed and untagged by constellation for now.\n\nRestrict pole_star() to named stars so an anonymous faint star cannot drift\nnearer the pole and usurp Polaris / Thuban / Vega.","parents":["e75fa6052a51481de9016a26e274d5efb49bc14d"],"add":5001,"del":6,"cadd":5001,"cdel":6,"files":2},{"repo":"wheel-of-the-heavens","hash":"c6c3629d5564f7fd4390ef2927656b9ff08f436c","ts":1781118883,"wall":"2026-06-10T15:14","msg":"feat(wasm): nearest_stars() -- match figure vertices to catalogue stars","body":"For each J2000 [ra,dec] vertex, return the nearest catalogue star index within a\ntolerance (or -1). Lets the armillary build the constellation stick-figures as a\ngraph over real stars rather than at fixed coordinates, so the figures precess\nwith their stars.","parents":["4d1e6ef4d5ba5c2ce6018453baaf75b15b3c3bc6"],"add":34,"del":0,"cadd":34,"cdel":0,"files":1},{"repo":"wheel-of-the-heavens","hash":"5a870c2d0a978c7fdbbc3feaa21b36750c3355ae","ts":1781118894,"wall":"2026-06-10T15:14","msg":"feat(armillary): constellation figures over stars, magnitude depth, names one-by-one","body":"The geocentric star field, reworked for the expanded catalogue:\n\n- Constellation stick-figures are a graph over catalogue stars: each vendored\n  d3-celestial vertex (BSD-3, web/src/constellation-lines.json) is matched once\n  (nearest_stars) to its star, and the geometry is rebuilt from the precessed\n  positions every epoch -- the figures ride the stars through precession and land\n  exactly on them (893/893 vertices matched). Each figure carries its own vertex\n  dots so it stays whole under any magnitude filter or solo.\n- Toggleable magnitude depth: default V<=5.5, the catalogue holds to 6.0; palette\n  \"Stars - to magnitude X\". A solo overrides the limit.\n- Constellation (violet) names start off and are lit one at a time (\"Name - Leo\");\n  the master toggle does all on/off; a solo lights its own.\n- Star labels only for the named bright stars, not thousands of DOM nodes.\n\nAlso folds in the prior uncommitted frontend work since the orrery arc: geocentric\nalways-on wanderer orbits with unfolding tracers, the solo/isolate feature, Moon\nspacing, removal of the 'g' true-scale toggle, and the orrery string-art cleanup.","parents":["c6c3629d5564f7fd4390ef2927656b9ff08f436c"],"add":276,"del":62,"cadd":275,"cdel":62,"files":5},{"repo":"wheel-of-the-heavens","hash":"3344f7410ce3d537d70d938d164b1dfb3c47bce1","ts":1781118902,"wall":"2026-06-10T15:15","msg":"docs: star catalogue enrichment & aster-cards research","body":"Sourcing + design study for info cards on all 5080 stars: BSC5 field inventory,\npublic-domain distance (Hipparcos), colour/temperature (Ballesteros + Planck\nlocus), constellation-for-all (Roman VI/42 boundaries), IAU-CSN proper names\n(CC-BY, one credit line), operator-assigned names for the nameless, and a tiered\ncard design. Indexed in unicursal RAG.","parents":["5a870c2d0a978c7fdbbc3feaa21b36750c3355ae"],"add":517,"del":0,"cadd":517,"cdel":0,"files":1},{"repo":"wheel-of-the-heavens","hash":"43ffc3755315e7031c2cbfc98562515814e6a578","ts":1781121796,"wall":"2026-06-10T16:03","msg":"build: vendor star-catalogue sources + pure-stdlib generator","body":"scripts/generate_star_catalog.py regenerates core/src/stars_catalog.rs from four\nvendored public-data tables under scripts/data/ -- zero external packages, fully\noffline-reproducible and deterministic:\n  - bsc5.json                              Yale BSC5 (PD): astrometry, spectral type,\n                                           B-V, HD/SAO, Bayer/Flamsteed, var/mult flags\n  - hipparcos-parallax.csv                 Hipparcos I/239 (PD): parallax, by HD\n  - iau-csn.txt                            IAU-CSN (CC-BY): official proper names\n  - constellation-boundaries-roman87.dat   Roman 1987 / VI/42 (PD): Delporte boundaries\n\nConstellation is computed in-script (precess J2000 -> B1875, scan the boundary\ntable), verified 100% against BSC5's own 2736 Delporte labels -- replacing astropy,\nwhose PrecessedGeocentric path carried a ~20\" stellar-aberration shift that\nmis-assigned two boundary stars.","parents":["3344f7410ce3d537d70d938d164b1dfb3c47bce1"],"add":109066,"del":0,"cadd":184,"cdel":0,"files":5},{"repo":"wheel-of-the-heavens","hash":"5aa78057651d9a7527540973beacbfd70de04775","ts":1781121808,"wall":"2026-06-10T16:03","msg":"feat(engine): enrich the star catalogue + star_card lookup","body":"Every one of the 5080 stars now carries the data a star card needs: IAU proper\nname (334), Bayer/Flamsteed designations, HD/SAO, spectral type, B-V, Hipparcos\nparallax (98.5%; NaN where indeterminate), variable/multiple flags, and a\nconstellation computed for ALL stars -- closing the centroid-label gap so every\nconstellation gets a name, and letting solo-by-constellation reach faint stars.\nDistance and colour are derived at render from parallax and B-V, not baked.\n\nThe Star struct grows to hold these; a new wasm star_card(index) serves the rich\nfields for one selected star on demand, keeping the rete lean. Astrometry and the\nnamed-star pole sequence are preserved; 92 core + 5 wasm tests pass.\n\nGenerated by scripts/generate_star_catalog.py.","parents":["43ffc3755315e7031c2cbfc98562515814e6a578"],"add":5151,"del":5094,"cadd":5151,"cdel":5094,"files":3},{"repo":"wheel-of-the-heavens","hash":"35c0988934227c22858de1812b5be4325257a2b6","ts":1781123550,"wall":"2026-06-10T16:32","msg":"feat(card): the aster card -- right-click any star to read what it is","body":"Upgrades the right-click inspection into a tiered Sphaera card: designation\nhierarchy (proper name > Bayer > Flamsteed > HR/HD/SAO), constellation, magnitude,\nspectral type + luminosity gloss, a computed true-colour swatch + temperature,\ndistance (ly/pc, or indeterminate), and live altitude/azimuth. \"more\" reveals a\nplain-language identity, absolute magnitude, proper motion + its drift over the\ninstrument's +/-10 ka, rise/set in local time, and variable/multiple flags.\n\n- web/src/starcolor.js (new): B-V -> effective temperature (Ballesteros 2012) ->\n  sRGB on the Planckian locus (Kim 2002), normalized to constant luminance. No\n  vendored data; the colour is derived. Verified numerically across spectral types.\n- scene.pick now returns the catalogue index that keys star_card; every star is\n  inspectable (named or HR-only).\n- main wires star_card / star_altaz / star_events + a local-mean-time formatter.","parents":["e2c60c4588c8f5ce3c6dde7c9ec05a7d07509b02"],"add":232,"del":22,"cadd":232,"cdel":22,"files":5},{"repo":"wheel-of-the-heavens","hash":"e2c60c4588c8f5ce3c6dde7c9ec05a7d07509b02","ts":1781123550,"wall":"2026-06-10T16:32","msg":"feat(engine): per-star alt/az + rise/set endpoints, proper motion on the card","body":"Stars get the live-position machinery the bodies already have, reusing the generic\nclosures: core star_events() wraps rise_transit_set() with the star's equatorial\nclosure and a point-source standard altitude (-0.5667°, refraction only);\nrise_transit_set is now pub(crate). wasm exposes star_altaz and star_events by\ncatalogue index, and star_card gains total proper motion (mas/yr). The card reads\nthese on demand -- the rete stays lean. 92 core + 5 wasm tests pass.","parents":["5aa78057651d9a7527540973beacbfd70de04775"],"add":46,"del":2,"cadd":46,"cdel":2,"files":3},{"repo":"wheel-of-the-heavens","hash":"a680ca83a0c69d7e5aae024343e15ef3e63378e7","ts":1781123610,"wall":"2026-06-10T16:33","msg":"docs: refresh handoff — star catalogue arc + the aster card","body":"Covers the catalogue (5080 stars), figures-precess-with-stars, magnitude depth,\nnames one-by-one, the full enrichment, and the right-click card. Supersedes the\norrery-arc handoff. Next: Phase C (naming the nameless).","parents":["35c0988934227c22858de1812b5be4325257a2b6"],"add":63,"del":44,"cadd":63,"cdel":44,"files":1},{"repo":"wheel-of-the-heavens","hash":"5cfdd2e80fcf183716443ce50d2cad4bb5defc5d","ts":1781134031,"wall":"2026-06-10T19:27","msg":"feat(engine): expose HR number on each rete star","body":"Keeper star-names are keyed by HR -- the stable Bright Star Catalogue\nid -- so carry it through rete() into StarDot, letting the renderer map\na clicked star back to its catalogue entry (and a keeper's name).","parents":["a680ca83a0c69d7e5aae024343e15ef3e63378e7"],"add":2,"del":0,"cadd":2,"cdel":0,"files":1},{"repo":"wheel-of-the-heavens","hash":"793fc7ab8f4075b386a78a0fc8d6986baaeaf698","ts":1781134042,"wall":"2026-06-10T19:27","msg":"feat(armillary): first-person ground view, keeper star names, pinnable layer menu","body":"Stand on the ground and look up (key g, or \"observe from here\"): a\nfirst-person camera at the observer's place, zenith up, with look-around\ndrag and FOV zoom. Nothing below the horizon shows -- stars are culled\nby the vis attribute, wanderers / figures / labels by altitude, and the\ncelestial-frame scaffolding (equator, ecliptic, colures, precession,\nsigns, meridian) gives way to a naturalistic local sky; the horizon ring\nand cardinals stay, since they live on the horizon.\n\nKeeper star-names: name the stars the IAU left nameless -- persisted in\nlocalStorage by HR, drawn in cream italic with a glyph, searchable in the\npalette, the alphanumeric designation kept in parentheses. Off by default,\ntoggled on one at a time, as with the violet constellation names.\n\nContext menu rebuilt: pinnable, resizable, granular. A Contents /\nFrames-as-cycles spine over the full layer tree -- tri-state groups,\nper-wanderer toggles, an inline magnitude stepper, and the view presets.\n\nOrbit traces: sub-sample between frames (per-body cadence) so the Moon's\npath reads as a smooth curve at any play speed instead of a polygon.","parents":["5cfdd2e80fcf183716443ce50d2cad4bb5defc5d"],"add":616,"del":119,"cadd":616,"cdel":119,"files":6},{"repo":"wheel-of-the-heavens","hash":"889d7b59c4f64d130883db8b2536bb77aa7ec6fc","ts":1781134134,"wall":"2026-06-10T19:28","msg":"docs: refresh handoff -- first-person ground view + keeper names + the menu","body":"Records the ground view, the keeper star-names, the rebuilt context menu,\nand the clip-plane scar (why none exists). Flags the four open items:\nnear-zenith roll, scaffolding toggle desync, cardinals-default-off, bloom.","parents":["793fc7ab8f4075b386a78a0fc8d6986baaeaf698"],"add":83,"del":61,"cadd":83,"cdel":61,"files":1},{"repo":"wheel-of-the-heavens","hash":"ffbae490ba807959934b2ad882f937b35abbae0b","ts":1781211570,"wall":"2026-06-11T16:59","msg":"feat(ui): manual, guided tutorial, self-hosted fonts, hero cartouche","body":"The manual (web/src/manual.js): a dismissible reference overlay in the\nSphaera frame, opened from the palette, the ? key, or / -> \"manual\".\nEight sections, brand voice.\n\nThe tutorial (web/src/tutorial.js): a guided spotlight tour that dims the\nsky and lifts one real control at a time -- the cartouche, the throttle,\nthe palette, the ground view -- with a callout, the lifted control kept\nlive beneath a non-blocking box-shadow halo. Auto-runs once on first\nvisit (localStorage), re-openable from the palette or t. The palette now\nreturns { open, close, isOpen } so the tour can lift it.\n\nSelf-hosted fonts: five latin-subset OFL woff2 (Cinzel 400/600, Cormorant\nGaramond 400/600, IBM Plex Mono 400) under web/public/fonts/ with\n@font-face -- the app rendered in system fallbacks before. No runtime\nGoogle Fonts; autarky preserved. Provenance + licence in the fonts README.\n\nA Deco hero cartouche for the \"Cycles\" title: the Sphaera double rule\n(twin of the time cartouche), centred at the top, sized in real units so\nthe Cinzel glyphs stay crisp.","parents":["889d7b59c4f64d130883db8b2536bb77aa7ec6fc"],"add":561,"del":8,"cadd":561,"cdel":8,"files":11},{"repo":"wheel-of-the-heavens","hash":"da51bac27cb6771e08245c73b4e7c8c23068a332","ts":1781211579,"wall":"2026-06-11T16:59","msg":"docs: refresh handoff -- onboarding, fonts, publish readiness","body":"Records the manual, the guided tutorial, and the styling phase (fonts now\nself-hosted), plus the publish-readiness assessment: build clean and\nautarky verified; gates remaining are an eyeball of the new UI, a deploy\ntarget, and the four known minor items.","parents":["ffbae490ba807959934b2ad882f937b35abbae0b"],"add":41,"del":3,"cadd":41,"cdel":3,"files":1},{"repo":"forms","hash":"34d3605394e5480cdff7e24621f71c1f6d4d6ad4","ts":1781282567,"wall":"2026-06-12T12:42","msg":"docs: No Dead Symbols — FORMS design law","body":"The design law (no dead symbols; every glyph is a handle), its Bret Victor /\nKill Math lineage, what FORMS already does right, and the full possibility\nspace of veins tiered for implementation.","parents":["c67538371492c4236a17eea7261029baf7f44f77"],"add":527,"del":0,"cadd":527,"cdel":0,"files":1},{"repo":"forms","hash":"5c1ddae119c561448e0d9d84cdafaeb711c1501e","ts":1781282567,"wall":"2026-06-12T12:42","msg":"feat: stable coordinate frame, variable slot model, start-alive seed","body":"- Stable 2D frame: fit once per expression, hold during dial manipulation, so\n  amplitude changes read against a stationary grid (INLINE_HEADROOM,\n  computeCurveFrame, controller currentFrame). Auto-fit per sample was\n  cancelling the very motion a dial produced.\n- Variable slot model: an ordered axis assignment (reconcileAxes) replaces the\n  swept/held map; a sortable axes/dials list lets the user choose which\n  variables are axes and in what order — reordering transposes the plot.\n  detectMode slimmed to a pure matcher over the ordered axes.\n- Scrub scoped to the dial only (curve-drag context disabled); graph drags\n  move/rotate as expected.\n- Start-alive seed module: first visit opens on a breathing a*sin(x).","parents":["34d3605394e5480cdff7e24621f71c1f6d4d6ad4"],"add":408,"del":182,"cadd":408,"cdel":182,"files":9},{"repo":"forms","hash":"f6b183a97623c7e9b70953e94599c62b2ca72c3c","ts":1781282580,"wall":"2026-06-12T12:43","msg":"fix: equation input audit remediation","body":"- Notation line shows the typed expression, not the dial-substituted value\n  (fixes hidden variable + 3D cursor misalignment); also wires the seed.\n- Escape closes the help panel without wiping the input (capture phase).\n- Input-length guard against giant-paste freezes.\n- Unify programmatic input behind setInputValue() so the on-screen keyboard,\n  history, autocomplete, and library loads keep the cursor in sync and clear a\n  stale autocomplete dropdown (expose autocomplete.hide).\n- Real parser error messages (+N more) instead of canned boilerplate.\n- Correct/omit wrong inline-help token mappings.\n- Polish: keyboard backspace honors a selection, auto-focus skips other\n  editables, IME composition handling, aria-label + aria-live.","parents":["5c1ddae119c561448e0d9d84cdafaeb711c1501e"],"add":118,"del":80,"cadd":118,"cdel":80,"files":7},{"repo":"forms","hash":"e26ebd2de310f00cd13d79aaf2019d15cb74a797","ts":1781284250,"wall":"2026-06-12T13:10","msg":"test: add Vitest + unit tests for pure functions","body":"Vitest runner (npm test / test:watch) with co-located unit tests: reconcileAxes\n(slot-model axis ordering, order preservation, no re-promote of held axis-letters),\nbreathe (seed range/period), computeCurveFrame (stable frame headroom/degenerate),\nand three-helpers (niceStep / autoScale / colorByHeight). 19 tests.","parents":["f6b183a97623c7e9b70953e94599c62b2ca72c3c"],"add":541,"del":3,"cadd":143,"cdel":0,"files":6},{"repo":"forms","hash":"1787cc1fdcaf58d7f32b194f27e050976c3545f5","ts":1781284407,"wall":"2026-06-12T13:13","msg":"build: strict TypeScript config + typecheck gate","body":"Rewrite tsconfig as a strict project — allowJs + checkJs:false so existing .js\nresolves during the incremental migration while only .ts files are type-checked.\nAdd `npm run typecheck` (tsc --noEmit) as the gate; coverage grows per migrated\nfile. Drop the old incorrect `paths` three hack.","parents":["e26ebd2de310f00cd13d79aaf2019d15cb74a797"],"add":8,"del":9,"cadd":0,"cdel":0,"files":2},{"repo":"forms","hash":"e141e43945374f3cfba6cca00e119422026fa8be","ts":1781284701,"wall":"2026-06-12T13:18","msg":"refactor: migrate foundation modules to TypeScript (Batch A)","body":"config, utils (sanitize/term/three-helpers), plot/param-store, ui/manual-map ->\n.ts with full type annotations. Adds a documented Term interface for the engine's\ndynamic JSON and ParamValues/ParamListener types; null-guarded autoScale.\ntypecheck clean, 19 tests green, build clean.","parents":["1787cc1fdcaf58d7f32b194f27e050976c3545f5"],"add":58,"del":39,"cadd":0,"cdel":0,"files":7},{"repo":"forms","hash":"1699dce13a3b7612e5ea373e3cabbb52dfcdd1e8","ts":1781285296,"wall":"2026-06-12T13:28","msg":"refactor: migrate marching-cubes/squares + lsystem to TypeScript (Batch B1)","body":"Type the field/grid signatures ((number|null)[], coordinate arrays); restructure\nmarching-cubes corners so values are genuine numbers; add an LSystemPreset\ninterface + TurtleSeg/TurtleState types and guard the stack pop. typecheck clean,\n19 tests green, build clean.","parents":["e141e43945374f3cfba6cca00e119422026fa8be"],"add":45,"del":24,"cadd":0,"cdel":0,"files":3},{"repo":"forms","hash":"da78777aa9004d400f07fa956abc8eff8171c9e6","ts":1781285809,"wall":"2026-06-12T13:36","msg":"refactor: migrate 4 renderers to TypeScript (Batch B2a)","body":"plot-trajectory, plot-implicit-2d, plot-3d, plot-mesh -> .ts. Reuse the canonical\ndisposeObject helper for cleanup loops (DRY, handles material arrays/Troika);\nnarrow (number|null) z-samples honestly; add a shared MeshData interface.\ntypecheck clean, 19 tests green, build clean.","parents":["1699dce13a3b7612e5ea373e3cabbb52dfcdd1e8"],"add":67,"del":63,"cadd":0,"cdel":0,"files":4},{"repo":"forms","hash":"cdf7a5ef6697b642efa7cf2ddcba2c4c77e96c5a","ts":1781286013,"wall":"2026-06-12T13:40","msg":"refactor: migrate plot-fractal + plot-2d to TypeScript (Batch B2b)","body":"Completes all 6 renderers. FractalParams interface (typing canvas cascades to the\nshader-interaction handlers); exported CurveFrame interface for the stable 2D frame;\nnull-samples narrowed; dispose loops reuse disposeObject. typecheck clean, 19 tests\ngreen, build clean.","parents":["da78777aa9004d400f07fa956abc8eff8171c9e6"],"add":74,"del":63,"cadd":0,"cdel":0,"files":3},{"repo":"forms","hash":"b9bbcce6a83e43c45f0eb0975c5ebde83a17eaf2","ts":1781286628,"wall":"2026-06-12T13:50","msg":"refactor: migrate plot modes + registry to TypeScript (Batch B3)","body":"Completes the plot engine. New types.ts with the Wasm engine interface and Ast\nboundary type; a Mode interface in registry — typing registerMode(mode: Mode)\ncontextually types every mode's detect/sample/buildInline. MeshData gains a\nwireframe flag; lsystem overrides + polytope/parametric/proj4d helpers typed.\ntypecheck clean, 19 tests green, build clean.","parents":["cdf7a5ef6697b642efa7cf2ddcba2c4c77e96c5a"],"add":92,"del":22,"cadd":43,"cdel":0,"files":15},{"repo":"forms","hash":"17c4f57677bc4f3c4cff1eef9e59907ba4bfe995","ts":1781287288,"wall":"2026-06-12T14:01","msg":"refactor: migrate animation/interaction layer to TypeScript (Batch C1)","body":"curve-drag.ts: type module state, event handlers, and applyJacobian;\nadd null-guards on canvas/dragStartY/dragStartParamValues that TS exposed\nas latent null-deref paths.\n\node-animator.ts: type createOdeAnimator, add a Bounds interface, optional\nbuildLine hue/opacity params, and reuse disposeObject for cleanup. Guard\nwasm/odeParams inside the density animation closure (outlived the outer guard).\n\ntsc --noEmit clean; 19/19 tests; vite build green.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["b9bbcce6a83e43c45f0eb0975c5ebde83a17eaf2"],"add":47,"del":51,"cadd":0,"cdel":0,"files":2},{"repo":"forms","hash":"67c1d97650287d26be18f5034efdf870ed282d99","ts":1781287763,"wall":"2026-06-12T14:09","msg":"refactor: migrate scene + plot-controller to TypeScript (Batch C2)","body":"scene.ts: type the dual-scene/HUD builders, cursor/notation/truth-table/\nK-map state and helpers. Add a TruthTable/ErrorSpan type set to types.ts.\n\nplot-controller.ts: type the controller's interaction + inline-preview state\n(Mode, CurveFrame, PinnedPlot), event handlers infer from the DOM lib. Add a\nnull-guard in sampleAndRender and narrow the catch (unknown) before showError.\n\ntroika-three-text.d.ts: ambient declaration for the Text subset the app uses\n(troika ships no types) — extends THREE.Mesh.\n\ntsc --noEmit clean; 19/19 tests; vite build green; live server transforms both.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["17c4f57677bc4f3c4cff1eef9e59907ba4bfe995"],"add":130,"del":54,"cadd":56,"cdel":0,"files":4},{"repo":"forms","hash":"8b2191da94d5df7c9aea2b70095a2eb5b82d1b8d","ts":1781288506,"wall":"2026-06-12T14:21","msg":"refactor: migrate UI panels + library to TypeScript (Batch D)","body":"11 files: history, share, error-display, keyboard, manual-data, manual-panel,\nmanual-tooltip, sliders, context-menu, autocomplete, library.\n\nNotable typing decisions:\n- error-display: isWasmError is now a `result is WasmError` type guard; export\n  DisplayError/WasmError. Propagates narrowing to all mode callers.\n- keyboard/autocomplete: functions carry attached props (toggle/isVisible/hide),\n  so they become const arrows with an interface declaring the optional members.\n- context-menu: typed the full callbacks bag; plotCtrl is\n  ReturnType<typeof initPlotController>; extracted VIEW_LABELS to drop two\n  string-indexed object literals.\n- Event handler params infer from the DOM lib; the work was state, params,\n  EventTarget→HTMLElement/Node casts, and number→string for input.value.\n\ntsc --noEmit clean; 19/19 tests; vite build green; live server transforms all.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["67c1d97650287d26be18f5034efdf870ed282d99"],"add":274,"del":144,"cadd":0,"cdel":0,"files":11},{"repo":"forms","hash":"f5f7a4d1cd2c79cd21c8ca6c4a806f58c9325f9e","ts":1781288963,"wall":"2026-06-12T14:29","msg":"refactor: migrate app + seed to TypeScript (Batch E)","body":"app.ts: type the orchestrator — module singletons via\nReturnType<typeof createScene/initPlotController/createLibraryPanel>, a full\nAppState interface, EventTarget→element casts, and world/wasm null-guards at\nthe share/restore paths. loadWasm casts the wasm-bindgen module to Wasm.\n\nseed.ts: type the breathing-seed lifecycle (SeedApp contract, rAF loop).\n\nBoundary fixes pulled in: onExpressionChange ast is now optional (called\n1-arg on clear); context-menu wasm/plotCtrl are nullable (app holds them as\n| null and already uses ?. on them).\n\ntsc --noEmit clean; 19/19 tests; vite build green; live server transforms.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["8b2191da94d5df7c9aea2b70095a2eb5b82d1b8d"],"add":65,"del":38,"cadd":3,"cdel":3,"files":5},{"repo":"forms","hash":"79be338fff35343bc3706969d2468458859ab8e1","ts":1781288971,"wall":"2026-06-12T14:29","msg":"chore: lock the build to TypeScript — allowJs:false","body":"The whole src/ tree is now .ts (0 .js remaining). Flip allowJs off so any\nstray .js silently slipping back in is a hard error, and drop the now-moot\ncheckJs. The wasm-bindgen pkg import resolves via its generated .d.ts, so it's\nunaffected.\n\nCompletes the JS→TS migration: 50 source modules, strict mode, tsc clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["f5f7a4d1cd2c79cd21c8ca6c4a806f58c9325f9e"],"add":1,"del":2,"cadd":0,"cdel":0,"files":1},{"repo":"forms","hash":"06e6fd799ca1540b67ad94720421a188f8c99a37","ts":1781289783,"wall":"2026-06-12T14:43","msg":"refactor: flense dead code","body":"Detected mechanically now that the tree is strict TS: tsc\n--noUnusedLocals/--noUnusedParameters for dead locals/params/imports, plus a\ncross-module export-reference scan for dead exports.\n\nRemoved:\n- plot-trajectory.ts entirely — its sole export (buildInlineTrajectory) was\n  unused and nothing imported the module; the ODE animator superseded it.\n- library.ts manual subsystem: UI_MANUAL (~70 lines) + renderManual +\n  renderManualSections + getSaved — a superseded in-library manual, replaced by\n  the manual-panel/tooltip system that fetches manual.json.\n- manual-data getAllCategories (only consumer was renderManual).\n- config MODE_PRIORITY, manual-map isManualToken, plot-fractal BG_COLOR import,\n  ode.ts dead buildInlineTrajectory import, scene KMAP_GAP, seed isBreathing,\n  ode-animator unused `geo` binding, fractal unused `text` param.\n\n234 lines deleted, 3 changed. tsc clean; 19/19 tests; build green.\n\nLeft deliberately: 16 over-exported-but-used-internally symbols (export\nhygiene, not dead) and the dormant curve-drag module (see follow-up).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["79be338fff35343bc3706969d2468458859ab8e1"],"add":3,"del":234,"cadd":3,"cdel":234,"files":11},{"repo":"forms","hash":"363ba1438d91f0bd02f842e63890379ed5e43f41","ts":1781290883,"wall":"2026-06-12T15:01","msg":"docs: session handoff — TS migration + dead-code flense complete","body":"Records: full JS→TS migration (49 ts / 0 js, strict, allowJs:false), the\ndead-code flense (234 lines), and the curve-drag wake-up decision (alt+drag\nscrub, Phase 1/2 plan + the dormant-by-design backstory) for the next session.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["06e6fd799ca1540b67ad94720421a188f8c99a37"],"add":134,"del":0,"cadd":134,"cdel":0,"files":1},{"repo":"forms","hash":"343d6d1db96ab82e52ee30e624e15523e15f471b","ts":1781291089,"wall":"2026-06-12T15:04","msg":"docs: record forms.symbiont.systems deploy procedure in handoff","body":"No deploy script existed; captured the build+rsync+chown steps so the next\ndeploy is copy-paste instead of re-derived. TODO noted to wire `npm run deploy`.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["363ba1438d91f0bd02f842e63890379ed5e43f41"],"add":17,"del":0,"cadd":17,"cdel":0,"files":1},{"repo":"forms","hash":"d3074e6ae3b95c4925cbac81b43368eb6398bd7c","ts":1781291912,"wall":"2026-06-12T15:18","msg":"test: strengthen Laplace/Fourier coverage (compound paths)","body":"Existing fourier_tests/laplace_tests already covered the table pairs + inverse;\nthis adds the previously-untested compound paths:\n- laplace_linearity: L{2sin+3cos} split/recombine\n- laplace_frequency_shift: L{e^(2t)sin(3t)} = 3/((s-2)²+9) (the F(s-a) path)\n- laplace_t_fifth_factorial: L{t^5}=120/s^6\n- laplace_unsupported_stays_unevaluated: L{tan(t)} never fabricates a transform\n- ilaplace_cos_roundtrip, ilaplace_exp_roundtrip\n- fourier_even_symmetry: even f → symmetric series (invariant the point tests miss)\n\nAll green: 493 unit + 7 proptest, 0 failed. (Closes the stale Chunk-7 gap —\nthe transforms were already tested; this hardens the bug-prone compound paths.)\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["343d6d1db96ab82e52ee30e624e15523e15f471b"],"add":74,"del":0,"cadd":74,"cdel":0,"files":1},{"repo":"forms","hash":"61507385bbf00868486db42af6d13a844720cbc1","ts":1781293947,"wall":"2026-06-12T15:52","msg":"test: foreign-oracle differential harness (numeric tier) — 0 confirmed bugs in 100k","body":"Cross-checks the engine against mpmath (50 dps) over random expressions, to validate\nbeyond self-authored tests.\n\n- math-core/src/bin/forms_eval.rs: long-lived batch eval bridge (line protocol, no deps).\n- tools/difftest/: single-source dual render (one AST -> FORMS string + mpmath value),\n  seeded safe-domain generator, condition-number-scaled tolerance, and a rigorous verifier\n  (independent f64 oracle + mpmath precision ladder) that confirms a bug only when two\n  independent oracles agree on a precision-stable value the engine misses. No eyeballing;\n  verifier validated by positive (catches a 1e-6 error) and negative (ignores cancellation)\n  controls.\n\nResult: 100,000 expressions across 5 seeds, 463 raw candidates, 0 confirmed engine bugs —\nall disagreements mechanically proven to be intrinsic f64 ill-conditioning (engine and an\nindependently-coded f64 oracle miss the high-precision truth by identical amounts).\n\nScope: smooth continuous core only. Discrete funcs, domain boundaries, and the symbolic\ntier (vs SymPy) are Phases 2-3.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["d3074e6ae3b95c4925cbac81b43368eb6398bd7c"],"add":1061,"del":0,"cadd":1055,"cdel":0,"files":10},{"repo":"forms","hash":"ae7e2e95beea59f01eba7424db09e2f6d435caf2","ts":1781359535,"wall":"2026-06-13T10:05","msg":"fix(math-core): apply oracle-surfaced convention rulings","body":"The foreign-oracle differential harness surfaced four numeric-path behaviors\nwhile reading the engine. Operator rulings (2026-06-13):\n\n  #2 factorial — numeric path capped at 20! due to a u64 accumulator while the\n     symbolic path computed bignums. Now accumulates in f64, cap 170 (171!\n     overflows f64). 21! .. 170! now evaluate numerically.\n\n  #3 mod (%)   — was truncated (sign of dividend, -7%3 = -1). Now Euclidean\n     (result in [0,|b|), -7%3 = 2) in BOTH numeric and symbolic paths — the\n     number-theory convention expected of a math tool. New Rational::rem_euclid.\n\n  #4 neg roots — (-2)^0.5, (-8)^(1/3) leaked raw NaN to the display. Now return\n     undefined (None). Real cbrt(-8) = -2 is unaffected.\n\n  #1 round     — verified consistent (half-away in both paths); no change.\n\nEach fix frozen in math-core/tests/oracle_regressions.rs (9 tests). Full suite\n493 + 7 prop + 9 regression green. difftest harness conventions synced; re-run\n(seed 7, 5k expr) → 0 confirmed engine bugs.\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["61507385bbf00868486db42af6d13a844720cbc1"],"add":163,"del":19,"cadd":163,"cdel":19,"files":7},{"repo":"forms","hash":"4cd5cd564e24f59a9553a9885ddc721d9f7eb467","ts":1781361162,"wall":"2026-06-13T10:32","msg":"feat(math-core): adopt astro-float arbitrary-precision backend (Razor B0)","body":"First step of the razor-accuracy initiative: add the bigfloat backend that will\ncarry transcendental values exactly to N digits (replacing f64 on the answer path).\n\n- ADR docs/decisions/0001 — astro-float =0.9.5 chosen over dashu (no trig), rug\n  (C deps, no wasm), and a hand-rolled Taylor backend (parsimony).\n- Pin astro-float =0.9.5 with default-features off + [\"std\",\"serde\"]. The default\n  \"random\" feature pulls rand->getrandom 0.2, which fails on wasm32-unknown-unknown;\n  dropping it lets math-core cross-compile to wasm32 clean.\n- Spike tests (math-core/tests/astro_float_spike.rs): sin(1), pi, exp(1)=e all match\n  known references to <1e-48. Verified against external values, not self-asserted.\n\nGate passed: native suite 493 + 9 regressions + 7 prop + 3 spike green; wasm32 build\nclean. True linked wasm size delta deferred to B2 (tree-shaking determines real cost;\npre-shake astro-float-num rlib ~1.6 MB vs 2.14 MB baseline bundle).\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["ae7e2e95beea59f01eba7424db09e2f6d435caf2"],"add":253,"del":6,"cadd":181,"cdel":0,"files":4},{"repo":"forms","hash":"3ad1fe2724996b99d99099761a3ff6a50e9cb944","ts":1781361536,"wall":"2026-06-13T10:38","msg":"feat(math-core): exact BigInt fib/nCr/nPr on the answer path (Razor A)","body":"The symbolic answer path routed fib/nCr/nPr through i64 math_fns, so results were\ncapped (fib n<=92) or overflowed to None (nCr/nPr beyond i64) — lossy for a tool\nthat already carries exact rationals. gcd/lcm were already exact via BigRational.\n\n- math_fns: add fibonacci_big (fast doubling), combinations_big, permutations_big —\n  exact BigInt, arbitrary-magnitude result, compute-capped at 1e6 multiplications.\n- apply_number_theory: fib/nCr/nPr now produce Term::Num(from_big_integer(..)).\n  nCr/nPr read numer_big() so n,k may exceed i64 (e.g. nCr(2^100, 2) now computes).\n- The fast f64 plotting path (eval_numeric) is unchanged.\n\nFrozen regressions (oracle_regressions.rs, all values independently verified):\nfib(100), fib(200), nCr(50,25), nPr(20,10), nCr(2^100,2), gcd/lcm large coprimes.\nUpdated the internal large-nCr test to assert the exact value (was no-panic only).\n\nSuite 493 + 15 regressions + 7 prop + 3 spike green; wasm32 clean.\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["4cd5cd564e24f59a9553a9885ddc721d9f7eb467"],"add":138,"del":22,"cadd":138,"cdel":22,"files":4},{"repo":"plenum","hash":"cd9f79835ef97c70ad080c1c6e10c25326b18535","ts":1781409492,"wall":"2026-06-13T23:58","msg":"feat: Plenum — raymarched quantum field engine","body":"A WebGL2/Three.js engine that renders a quantum field as a raymarched 3D\nvolume, evolved by its real equation of motion, obeying the measured\nimperatives of precision physics.\n\n- Tier 1: real scalar Klein-Gordon/phi^4 on a lattice (leapfrog, 7-point stencil)\n- Tier 2: mode-sampled free-field quantum vacuum (spectral FFT sampling)\n- Tier 3: complex scalar, domain coloring, emergent quantized vortices\n- Multi-cube: independent field sims in separate cubes (variations / split / zoo)\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":[],"add":2432,"del":0,"cadd":1317,"cdel":0,"files":23},{"repo":"plenum","hash":"cd5806dba5a61cdcafbe3bebdb5fa528536254dc","ts":1781472246,"wall":"2026-06-14T17:24","msg":"docs: handoff — flense redesign, 25-field roster, gravity-as-time-bend, quantization direction","body":"","parents":["cd9f79835ef97c70ad080c1c6e10c25326b18535"],"add":42,"del":32,"cadd":42,"cdel":32,"files":1},{"repo":"operations","hash":"d6b10bb559e4cd0bbb108e898c526f2d3ba33470","ts":1781998320,"wall":"2026-06-20T19:32","msg":"research: Plenum — design corpus (axioms, law, ISA, interface)","body":"Plenum: a WebGPU cosmic sandbox. One informatic field (the plenum) whose\nexcitations are programmable cells. Matter is condensed meaning; life is\nmetabolism by law. Constrained by the GPU, not by physics.\n\n- plenum-axioms.md: one substance; cells as excitations; meaning/energy\n  as bound/free; conservation (1st law) + dissipative arrow (2nd law);\n  life as metabolism\n- plenum-propagation-law.md: split-step law on a complex field at N=1\n  (Schrodinger transport + Gross-Pitaevskii coupling + magnitude-\n  preserving phase decoherence); energy conserved, coherence dissipated\n- plenum-genome-isa.md: Sense-Map-Actuate cell; soft-gene genome;\n  IMPRINT as the inverse of decoherence; Landauer-accounted metabolism\n- plenum-interface.md: Praxis Operis only; navigable cosmos with code in\n  pinnable panels; two-tier scrub/recompile boundary\n\nHandoff updated with the first-heartbeat build spec for next session.","parents":["a1cb19882c63b9fe086c7526d0ce5add2d99c5d1"],"add":997,"del":3,"cadd":997,"cdel":3,"files":5},{"repo":"symbiont.systems","hash":"ac0ff816cdcb5804ab6874c3a0b40cf951816334","ts":1782271031,"wall":"2026-06-23T23:17","msg":"feat(mobile): photorealistic gold-filament card background","body":"Rebuild the mobile.symbiont.systems business card with a full-bleed\nWebGL2 background: domain-warped gold filaments on aubergine with\nanisotropic-GGX specular, stochastic star-twinkle, quarter-res Gaussian\nbloom, and ACES tone mapping. Full dark inversion (near-black copy, gold\nframe over the field); QR kept on a light tile for scannability.\nTagline changed to \"The eyes are useless when the mind is blind...\"","parents":["ae81429106cb0713f390e1724beb08d8570eea4d"],"add":477,"del":19,"cadd":477,"cdel":19,"files":1},{"repo":"symbiont.systems","hash":"c6270dd1d121da2f02c4642126c5e9827419f42f","ts":1782274034,"wall":"2026-06-24T00:07","msg":"feat(mobile): aubergine mauve veins; revert dynamic experiments","body":"The aubergine ground now carries its own mauve filament veins interleaved\nwith the gold (the \"aubergine as filament\" request). Reverts the dynamic\nexperiments tried this session — curl turbulence, parallax layers, aurora\ndrift, and gyro/touch reactivity — back to the calm field. Matches what is\nlive at mobile.symbiont.systems.","parents":["ac0ff816cdcb5804ab6874c3a0b40cf951816334"],"add":8,"del":2,"cadd":8,"cdel":2,"files":1},{"repo":"symbiont.systems","hash":"b444a79d64e7893cecf47dbaa2249686ee6b6ffd","ts":1782673754,"wall":"2026-06-28T15:09","msg":"feat(mission-control): mirror live site on load","body":"Mission Control now hydrates from the deployed page on every load instead\nof localStorage/defaults, so the editor reflects what symbiont.systems is\nactually serving (\"Live always wins\").\n\n- deploy.js: generateProductionHTML() embeds a lossless CONFIG snapshot as\n  a <script id=\"mc-config\"> JSON island in the deployed page.\n- config.js: loadFromLive() fetches '/', reads the island, deep-merges into\n  CONFIG and re-migrates rings; throws if unreachable/un-seeded.\n- main.js: startup calls loadFromLive() first, falling back to loadSaved()\n  only when live is unreachable — no regression before the seeding publish.\n\nActivation requires one seeding publish so the live page carries the island.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c6270dd1d121da2f02c4642126c5e9827419f42f"],"add":45,"del":2,"cadd":45,"cdel":2,"files":3},{"repo":"symbiont.systems","hash":"3c7f4ecc996b40d93c92c1de81aed347baac3781","ts":1782700352,"wall":"2026-06-28T22:32","msg":"refactor(mission-control): live-only load, drop draft/preset","body":"Mission Control now mirrors the live site and nothing else. The previous\nfallback loaded the localStorage draft when live was unavailable, which\ncontradicted \"live always wins\" and let a stale draft override live.\n\n- config.js: remove loadSaved(); neuter scheduleSave() to a no-op so no\n  localStorage draft is ever written or read.\n- main.js: boot loads live config only — panels/scene build after live\n  arrives; on failure an error overlay is shown instead of a draft/preset.\n\nThe live portal index.html was seeded with the #mc-config island so the\ndashboard has a live source to read.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["b444a79d64e7893cecf47dbaa2249686ee6b6ffd"],"add":28,"del":51,"cadd":28,"cdel":51,"files":2},{"repo":"major-tims-ground-control","hash":"3e6cb94e9b1284d40c0e206f57d3e42f0629d201","ts":1782702486,"wall":"2026-06-28T23:08","msg":"Initial scaffold: Major Tim's Ground Control website","body":"Astro 7 + Tailwind 4 static site for a veteran-owned lawn and property\nmaintenance business in East Tennessee.\n\n- Data-driven content collections: services, service areas, testimonials\n- SEO foundation: per-page meta, OpenGraph, canonical, LocalBusiness JSON-LD,\n  sitemap\n- Responsive core pages: home, services, about, gallery, contact + per-town\n  service-area landing pages\n- Services hand off to a pre-filled quote form; sticky mobile call/text bar\n- All customer-facing copy is Tim's own words (verbatim from existing site)\n  or clearly-marked placeholders; no invented narrative\n\nForm backend (Cloudflare Function + Turnstile + Resend), real photos, logo,\nand deploy still pending.\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":[],"add":5100,"del":0,"cadd":4013,"cdel":0,"files":37},{"repo":"symbiont.systems","hash":"8b7f2b9a5e3ffd4c28e4b590dc357258192a5797","ts":1782703852,"wall":"2026-06-28T23:30","msg":"docs(handoff): session 3 — Mission Control live mirror","body":"Record the live-only refactor: #mc-config island, loadFromLive, seed +\ndeploy facts, verification, and open follow-ups. Prior valis bio-surface\nhandoff retained as carryover.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["3c7f4ecc996b40d93c92c1de81aed347baac3781"],"add":55,"del":3,"cadd":55,"cdel":3,"files":1},{"repo":"major-tims-ground-control","hash":"c15883303cdab32bc054c0826154805eb46d22e8","ts":1782704061,"wall":"2026-06-28T23:34","msg":"Add 404 page, self-hosted fonts, robots.txt; enable sharp","body":"- 404: Major Tom-themed transmission page (Ground Control hailing the lost\n  page) with a CSS starfield and a drifting \"404\", reduced-motion respected.\n  Original wording only — no song lyrics. noindex + no business schema.\n- Fonts: self-host Barlow + Inter via @fontsource (pinned 5.2.8), only the\n  weights used; no Google Fonts network call.\n- SEO: add public/robots.txt pointing at the sitemap.\n- Build: enable sharp's native build (pnpm onlyBuiltDependencies) so Astro\n  image optimization works for the gallery.\n- Layout: optional noindex prop for utility pages.\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["3e6cb94e9b1284d40c0e206f57d3e42f0629d201"],"add":142,"del":0,"cadd":16,"cdel":0,"files":5},{"repo":"major-tims-ground-control","hash":"710235e5e912867df42c4b75e552ed61a205cbe1","ts":1782706121,"wall":"2026-06-29T00:08","msg":"Add quote form backend: Cloudflare Function + Turnstile + Resend","body":"- functions/api/quote.js: Pages Function for POST /api/quote — honeypot +\n  Turnstile spam checks, field validation, sends the lead to Tim via Resend,\n  then 302-redirects (/thank-you on success, /contact?error=... on failure).\n  Email HTML is escaped against injection. All secrets via env; degrades\n  gracefully before keys exist.\n- contact.astro: real Turnstile widget (rendered only when the public site key\n  is set, so the build never breaks without it) + an error banner that surfaces\n  ?error= messages.\n- thank-you.astro: confirmation page (noindex), Tim's voice + call/text.\n- .gitignore: ignore .dev.vars (local wrangler secrets).\n\nLive sending is gated on Cloudflare + Resend accounts and Tim's DNS (deploy\nrunbook). Email round-trip verified at deploy; redirect logic tested locally.\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["c15883303cdab32bc054c0826154805eb46d22e8"],"add":215,"del":5,"cadd":129,"cdel":0,"files":4},{"repo":"operations","hash":"31ebfcf61d3333570b36aaba60f2d8f71f9eb534","ts":1782711078,"wall":"2026-06-29T01:31","msg":"docs: Major Tim's Ground Control — project plan, checklist, handoff","body":"Client engagement docs for the MTGC website rebuild:\n- project-plan.md: audit, target architecture, stack/hosting decisions,\n  pricing research, Bowie-nod ideas, phasing\n- tim-asset-checklist.md: forwardable asset/access checklist for the client\n- handoff.md: session handoff (state, blockers, next steps)","parents":["d6b10bb559e4cd0bbb108e898c526f2d3ba33470"],"add":493,"del":0,"cadd":493,"cdel":0,"files":3},{"repo":"major-tims-ground-control","hash":"3dafe981fc97fc76d0cc45457db674224a8f8009","ts":1782777938,"wall":"2026-06-29T20:05","msg":"Add Tim's logo and curated job photos to assets","body":"Land client-delivered images under src/assets for astro:assets/sharp\noptimization (no markup changes yet — wired in following commits):\n\n- logo.png (transparent) + logo-full.jpg (full \"Leaf It To Us\" lockup)\n- 10 curated before/after job photos covering mowing, trimming, pressure\n  washing, mulch/rock beds, and a commercial reference (Ziptron Energy)\n- 4 HEIC/HEIF sources converted to JPEG with EXIF orientation applied\n- dropped 3 duplicate variants of the rubber-mulch before/after\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["710235e5e912867df42c4b75e552ed61a205cbe1"],"add":0,"del":0,"cadd":0,"cdel":0,"files":12},{"repo":"major-tims-ground-control","hash":"eabf47d6577350926db99bf02260a5e84a67c6f7","ts":1782779052,"wall":"2026-06-29T20:24","msg":"Put the logo in the header and ship a real favicon","body":"- Header: replace the generic leaf glyph with Tim's mascot mark\n  (logo-mark.png, cropped from the transparent logo above the name badge);\n  keep the legible text wordmark beside it.\n- Favicons: generate favicon.ico (16/32/48), favicon-16/32.png, and\n  apple-touch-icon.png from the mascot on a near-black square (matches the\n  official dark logo); update the <head> links; remove the placeholder\n  favicon.svg.\n- Add sharp@0.34.5 as an explicit pinned dependency. It was already in the\n  pnpm store but unlinked, so the first astro:assets <Image> failed the build\n  with \"Could not find Sharp.\" This completes what c158833 (\"enable sharp\")\n  started.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["3dafe981fc97fc76d0cc45457db674224a8f8009"],"add":16,"del":16,"cadd":4,"cdel":3,"files":10},{"repo":"operations","hash":"ecb503d0c56a8131cfe8d20248ac6a8aadbde214","ts":1782782154,"wall":"2026-06-29T21:15","msg":"finances: first revenue — Major Tim's Ground Control Phase 1 deposit","body":"- Receipt 2026-001 ($500, Cash App) for the 50% Phase 1 deposit; $500\n  balance due on completion. Markdown record + branded PDF to send the client.\n- Ledger: +$500 income (running balance -435.63 -> +64.37).\n- Tax: $0 sales tax (NV doesn't tax services; TN below remote-seller nexus);\n  no sales tax claimed beyond \"none collected.\" IRS income/SE tax is the\n  seller's liability, kept off the client receipt.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["31ebfcf61d3333570b36aaba60f2d8f71f9eb534"],"add":41,"del":0,"cadd":40,"cdel":0,"files":3},{"repo":"major-tims-ground-control","hash":"2b9c6a0c332f016e67687b0e22b45074d751df47","ts":1782782504,"wall":"2026-06-29T21:21","msg":"Make the full logo the hero","body":"Tim's paid lockup is now the centerpiece, spotlit on dark green:\n\n- Key the black out of logo-full.jpg via corner flood-fill (not a luminance\n  key, which would punch holes in the badge/tires) -> logo-full-transparent.png,\n  a clean transparent master also reusable for footer/OG later.\n- Rebuild the hero centered + logo-forward: layered radial green-glow + vignette\n  give the mark depth so it sits in the space, not floating. Astro <Image priority>\n  makes it the LCP element (eager/sync/fetchpriority=high), optimized 1494kB->128kB.\n- Drop the redundant brand name/tagline from hero text (the logo carries them);\n  keep a veteran-owned eyebrow + a service/location <h1> for SEO, one bright CTA\n  + tap-to-call. Tuned padding/logo cap so the whole hero clears the fold on\n  desktop; mobile fits with room.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["eabf47d6577350926db99bf02260a5e84a67c6f7"],"add":27,"del":23,"cadd":0,"cdel":0,"files":2},{"repo":"major-tims-ground-control","hash":"f538913581c10215514bb1a99d381e3c6fd082da","ts":1782783147,"wall":"2026-06-29T21:32","msg":"Put the logo in the footer","body":"Swap the footer's text wordmark for the transparent full-logo master on the\ndark-green footer (its natural home). Lazy-loaded (below the fold), not priority\n— the hero remains the only LCP image. Tagline + Facebook + the bottom copyright\nbrand name are unchanged.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["2b9c6a0c332f016e67687b0e22b45074d751df47"],"add":3,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"major-tims-ground-control","hash":"6bca0e93c9f45995dcf3e84a06ae93f136e58868","ts":1782784022,"wall":"2026-06-29T21:47","msg":"Build the gallery from Tim's real before/afters","body":"- New src/data/gallery.ts: single source for both the gallery page and the\n  homepage teaser (8 square before/after photos with captions + specific,\n  local-SEO alt text; 3 flagged featured).\n- Gallery page: real responsive grid (sm:2 / lg:3), astro:assets <Image> with\n  widths/sizes, square tiles + captions. Lazy-loaded; no JS lightbox in Phase 1.\n- Homepage \"Before & After\" teaser: three featured tiles replace the placeholders.\n- Dropped the two 640x283 retaining-wall shots (too low-res); files remain in\n  the repo, unused, ready to swap if Tim sends better versions.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["f538913581c10215514bb1a99d381e3c6fd082da"],"add":107,"del":12,"cadd":74,"cdel":0,"files":3},{"repo":"major-tims-ground-control","hash":"189c33191f2b0181c61f652030d8ae495d8cdc35","ts":1782784913,"wall":"2026-06-29T22:01","msg":"Center the gallery's short last row","body":"Switch the gallery grid from CSS grid to flex-wrap + justify-center so the\nfinal row (8 tiles => 3/3/2) centers instead of leaving a left-aligned orphan.\nTile widths set per breakpoint (full / 50% / 33%) to preserve the 3-up layout.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["6bca0e93c9f45995dcf3e84a06ae93f136e58868"],"add":3,"del":2,"cadd":0,"cdel":0,"files":1},{"repo":"operations","hash":"27a3572fcb20a883a8cb208047d1d596defeab35","ts":1782784939,"wall":"2026-06-29T22:02","msg":"docs: ask Tim to re-send the retaining-wall job at full res","body":"That job came through as a small low-res collage, so it's excluded from the\ngallery for now. Added a scoped request (in Rowan's voice, forwardable) for a\nclean single before/after at full resolution to swap in later.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["ecb503d0c56a8131cfe8d20248ac6a8aadbde214"],"add":4,"del":0,"cadd":4,"cdel":0,"files":1},{"repo":"operations","hash":"e5f00b32ecbc85d9593ef753ccf0cc9793d41fe1","ts":1782791049,"wall":"2026-06-29T23:44","msg":"docs: MTGC session handoff + forwardable nameserver guide","body":"- Refresh handoff to current state: 6 site commits (logo everywhere, hero,\n  gallery), first revenue, Cloudflare zone connected (pending; nameservers\n  bailey/lamar), and the morning deploy resume sequence.\n- Add tim-nameserver-guide.md (forwardable, filled with the two nameservers;\n  marked do-not-send until Pages deploy + domain attach are verified).\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["27a3572fcb20a883a8cb208047d1d596defeab35"],"add":122,"del":81,"cadd":122,"cdel":81,"files":2},{"repo":"eureka-co-nevada","hash":"02aa02fb4a47b18c981d03ba5945d67f773ee9a8","ts":1782823474,"wall":"2026-06-30T08:44","msg":"chore: NAIP source reclaim — manifest, re-fetch guide, reclaim script","body":"Raw NAIP 2022 imagery (138.5 GB) + derived EPSG:3857 clip (72 GB) + tiler\nintermediate (11 GB) deleted locally; 221 GB reclaimed. The deployed\nnaip-basemap.pmtiles is the product and is kept. Raw is re-fetchable from\ns3://naip-analytic via STAC discovery (bbox + 2022, requester-pays).\n\n- sources/naip-2022-manifest.csv: 434 tiles, filename+bytes (recovery key)\n- sources/naip-2022-refetch.md: provenance, re-fetch, rebuild, cost notes\n- scripts/reclaim-naip-disk.sh: guarded reclaim (dry-run default, --execute)\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["33327c6bc7d2b3b9500d9b5888cd35f8959a5630"],"add":589,"del":0,"cadd":154,"cdel":0,"files":3},{"repo":"major-tims-ground-control","hash":"7396ed999ab69cf867dc66b4969b890cced43796","ts":1782832094,"wall":"2026-06-30T11:08","msg":"Add \"Created by Symbiont Systems\" footer credit","body":"Subtle attribution in the footer's bottom bar (right-aligned on desktop,\nstacked on mobile), linking to https://symbiont.systems (new tab, rel=noopener).\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["189c33191f2b0181c61f652030d8ae495d8cdc35"],"add":12,"del":3,"cadd":0,"cdel":0,"files":1},{"repo":"operations","hash":"c36ec333131fe6e239c09e10406bd18ec296e15a","ts":1782832205,"wall":"2026-06-30T11:10","msg":"strategy: rate card + MRR model; refresh MTGC handoff","body":"- strategy/pricing-and-rate-card.md: outcome-over-hours pricing (MESO), rate\n  card (site $3k, managed presence $500/mo, custom $10k+ value-based, advisory\n  day rates), build/retainer structure, \"minor edits\" guardrail, managed-presence\n  bundle, MRR model ($5k/mo = 10 retainers). Draft.\n- MTGC handoff: footer credit commit (7396ed9), deploy resume sequence, adjacent\n  strategy work.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["e5f00b32ecbc85d9593ef753ccf0cc9793d41fe1"],"add":198,"del":36,"cadd":198,"cdel":36,"files":2},{"repo":"operations","hash":"ce4050096c5c3b86d192c75a1052af15fec71374","ts":1782835881,"wall":"2026-06-30T12:11","msg":"docs: finalize Tim nameserver guide + handoff to \"deploy staged\"","body":"- tim-nameserver-guide.md: nameservers (bailey/lamar) inlined at the entry step;\n  \"site is ready\" opener; cleared to send (gating met).\n- handoff: DEPLOY section → STAGED — Pages deployed (major-tims-ground-control.pages.dev,\n  Function bundled), custom domains attached, DNS wired (apex+www → Pages, proxied;\n  stale records cleaned), zone pending NS. Only step left: Tim's flip. Token-scope\n  note (wrangler lacks dns_records).\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["c36ec333131fe6e239c09e10406bd18ec296e15a"],"add":73,"del":75,"cadd":73,"cdel":75,"files":2},{"repo":"major-tims-ground-control","hash":"7be02232fedf385cfa8a464915cbd42e667c9028","ts":1782838671,"wall":"2026-06-30T12:57","msg":"Finalize Phase 1 content: About copy, +2 reviews, tagline, OG image","body":"- About: add Tim's missing verbatim paragraphs (the \"nod to a great song /\n  every property is its own mission\" line + the \"Veteran-owned. Family-driven.\n  Rooted in hard work and real trust.\" close).\n- Testimonials: add the two Google reviews (Deborah E., Buddy U.) → 5 total.\n  Make `town` optional in the schema; TestimonialCard renders name-only when a\n  review has no stated town (no fabricated locations).\n- Tagline: adopt \"Leaf It To Us\" in business.tagline; move the longer veteran/\n  local descriptor into the footer as literal copy (the footer logo already\n  shows \"Leaf It To Us\", so the field would have been redundant there).\n- Add og-default.jpg (1200x630) — full logo on the brand glow + service/location\n  caption; Layout already references /og-default.jpg.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["7396ed999ab69cf867dc66b4969b890cced43796"],"add":37,"del":5,"cadd":21,"cdel":2,"files":7},{"repo":"major-tims-ground-control","hash":"55b4650447333e6f6431b58891a3f30d75883760","ts":1782857822,"wall":"2026-06-30T18:17","msg":"feat: add Tim's four new before/after photos to gallery","body":"Adds a wide-format row below the square grid for landscape collages that\nwould be cropped by the square tiles. New 640x283 before/afters: hedge\nrestoration (before+after pair), overgrown-yard reclaim, and a driveway\npressure-wash. Rendered 2-up at native ratio so the panels stay legible.\n\ngallery.ts gains a `wide` flag and squareItems/wideItems selectors; the\ngallery page renders the two families separately. Verified: astro check\n0/0/0, build clean (11 pages), all 12 tiles load (naturalWidth>0).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["7be02232fedf385cfa8a464915cbd42e667c9028"],"add":67,"del":6,"cadd":39,"cdel":3,"files":6},{"repo":"major-tims-ground-control","hash":"24fc42357b4d885ad245251dcb1e0024b42d7b34","ts":1782869913,"wall":"2026-06-30T21:38","msg":"fix: drop redundant \"More before & after\" gallery subheading","body":"The page is already titled \"Before & After\"; the wide row needs no second\nheading. Wide collages now flow directly under the square grid with matching\ngap-5 spacing as one continuous gallery.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["55b4650447333e6f6431b58891a3f30d75883760"],"add":16,"del":19,"cadd":0,"cdel":0,"files":1},{"repo":"operations","hash":"e71b23193542bf131d2654edd5532f70e13df4a4","ts":1782870652,"wall":"2026-06-30T21:50","msg":"docs: refresh MTGC handoff — content #2 + new photos shipped & deployed","body":"HEAD 24fc423. Logs the Phase 1 content commit (7be0223) and this session's\ngallery work (55b4650 wide-row photos, 24fc423 heading removal). Deploy state\nupdated: Tim flipped nameservers (propagated), zone pending CF activation\nrecheck; pages.dev fully live. Blocked-on rewritten to current reality.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ce4050096c5c3b86d192c75a1052af15fec71374"],"add":33,"del":21,"cadd":33,"cdel":21,"files":1},{"repo":"major-tims-ground-control","hash":"7f7ec311391069b676f7cb9a71d1a93c268e1d93","ts":1782942754,"wall":"2026-07-01T17:52","msg":"feat: add privacy policy for invisible Turnstile","body":"The quote form runs Cloudflare Turnstile in invisible mode for spam\nprotection. Invisible mode requires disclosing it in a privacy policy\nthat links Cloudflare's Turnstile Privacy Addendum, so add a privacy\npage (contact fields, processors: Turnstile + Resend) and a footer\n\"Privacy\" link. NAP pulled from business.ts.","parents":["24fc42357b4d885ad245251dcb1e0024b42d7b34"],"add":91,"del":1,"cadd":0,"cdel":0,"files":2},{"repo":"operations","hash":"bfc5d259600f1d4866c4d62a18dd6678680e68b6","ts":1782943971,"wall":"2026-07-01T18:12","msg":"docs: MTGC handoff — quote form fixed & live, GBP dropped","body":"Quote form works end-to-end: invisible Turnstile (400020 resolved) +\nhoneypot, Resend delivering to Tim's inbox (verified POST /emails 200),\nprivacy policy shipped. Domain live on custom domain. Google Business\nProfile removed from scope — Tim already has one and self-manages.","parents":["e71b23193542bf131d2654edd5532f70e13df4a4"],"add":64,"del":71,"cadd":64,"cdel":71,"files":1},{"repo":"operations","hash":"625834a0333c2d9d9a2fc405639b3305ef738c4b","ts":1782962584,"wall":"2026-07-01T23:23","msg":"docs: add Crescent Valley off-grid shelter build tracker","body":"","parents":["bfc5d259600f1d4866c4d62a18dd6678680e68b6"],"add":239,"del":0,"cadd":239,"cdel":0,"files":1},{"repo":"eureka-co-nevada","hash":"404fc3f8481a767e2a8679a917d805538f5d7381","ts":1783000594,"wall":"2026-07-02T09:56","msg":"fix: harden well-enrichment caching and PLSS fraction decoder","body":"- enrich_wells.py: stop caching failed NWIS fetches. An empty cached\n  response permanently masked a ~100-site batch on every subsequent\n  run. Both the site-metadata and groundwater-level loops now skip a\n  failed batch and let it retry on the next run.\n- parse_mining.py: correct the BLM township/range fraction decoder to\n  use CadNSDI quarter codes (0=whole, 1=quarter, 2=half, 3=three-quarter).\n  Prior logic mis-decoded quarter and dropped three-quarter; unknown\n  codes now surface a marker instead of silent junk. Output is unchanged\n  for all current data (only codes 0 and 2 occur).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["02aa02fb4a47b18c981d03ba5945d67f773ee9a8"],"add":30,"del":17,"cadd":30,"cdel":17,"files":2},{"repo":"eureka-co-nevada","hash":"2a2d605a075de47b826ca2a5a2756db381885181","ts":1783000983,"wall":"2026-07-02T10:03","msg":"fix: guard index-keyed well cache + DOM-build summit popup","body":"- enrich_wells.py: the NWIS cache filename is keyed by batch index, so a\n  reordered or changed site list could return another batch's cached\n  response. Both loops now reject any cache holding a site outside the\n  current batch and re-fetch, while still reusing valid committed\n  snapshots (empty gwlevels caches remain legitimate).\n- map/index.html: the summit navigation popup was the sole setHTML with\n  interpolated field data. Rebuilt it with createElement/textContent and\n  setDOMContent, matching the feature inspector — no HTML-injection path\n  even if NAV_DATA ever becomes data-driven.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["404fc3f8481a767e2a8679a917d805538f5d7381"],"add":39,"del":8,"cadd":39,"cdel":8,"files":2},{"repo":"eureka-co-nevada","hash":"50af7266319663e9acc456600306c7cb603e22b7","ts":1783001295,"wall":"2026-07-02T10:08","msg":"feat: NAIP basemap PMTiles build script","body":"Standalone pipeline turning the EPSG:3857 NAIP GeoTIFF into a PMTiles\nbasemap: gdal_translate to MBTiles (JPEG), overview generation, and\nPMTiles conversion, with interrupt cleanup and progress monitoring.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["2a2d605a075de47b826ca2a5a2756db381885181"],"add":571,"del":0,"cadd":571,"cdel":0,"files":1},{"repo":"eureka-co-nevada","hash":"2fb3d34f50459cddfcd8310d1a7250d77d111489","ts":1783007038,"wall":"2026-07-02T11:43","msg":"feat(map): Phase 0 — port map rendering to Vite + TypeScript","body":"Rebuild the Eureka viewer's foundation as a modular Vite+TS app that mirrors\nDynamic. The 3084-line monolith is preserved verbatim as index.legacy.html\n(rollback + parity oracle).\n\n- Config as file-as-truth: LAYERS, sources, render modes, palette, and places\n  migrated into src/config/*.ts.\n- Rendering separated from UI: core/map.ts (map singleton + base style),\n  layers/addLayers.ts (catalogue renderer, one builder per geometry type),\n  basemap + baseCartography, pure expressions, and a single core/state.ts\n  surface. Per-directory READMEs seed the hackability charter.\n- Minimal full-bleed index.html mounts the app; the sidebar is retired and\n  returns as sheets/docks in Phase 1-2.\n\nVerified: tsc clean, vite build succeeds, dev server serves all modules (200)\nand pmtiles (206 range), 8 unit tests pass (state, expressions). In-browser\n24-layer visual parity vs the legacy is the remaining check.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["50af7266319663e9acc456600306c7cb603e22b7"],"add":5958,"del":3093,"cadd":4314,"cdel":3093,"files":30},{"repo":"eureka-co-nevada","hash":"a6c1f16b7cd63d1aaff85919809b907e596edc8e","ts":1783027671,"wall":"2026-07-02T17:27","msg":"feat(map): Phase 1 — responsive shell (sheet + dock + FAB)","body":"Retire the fixed sidebar for on-demand chrome that renders one panel two ways:\na mobile bottom sheet, desktop edge docks. The map is full-bleed behind it.\n\n- core/viewport.ts: visualViewport-driven sizing + keyboard inset, so\n  bottom-pinned chrome never trusts 100vh.\n- ui/sheet.ts: three explicit detents (peek/half/full) via a translateY offset\n  — grabber drags with pointer capture and tap-cycles; state is a plain\n  variable, not buried in scrollTop. touch-action scoped so the grabber owns\n  drags and the body scrolls.\n- ui/dock.ts: desktop edge-docked non-modal <dialog>.show() (Dynamic\n  inspectPanel pattern) — map stays live behind it.\n- ui/panelHost.ts + registry.ts: one Panel, two renderings; (max-width:768px)\n  switches sheet vs dock. Adding a panel is one registerPanel() call.\n- ui/fab.ts: the `/` FAB (and physical `/`) emit eureka:slash; Phase 3's\n  palette will listen. Placeholder panels make the shell exercisable now.\n- styles/tokens.css: synthwave palette + safe-area vars — the seam the future\n  aesthetic plugs into. index.html drops inline CSS (no second source).\n\nVerified: tsc clean, vite build succeeds, dev server transforms all modules\n(200) with clean HMR. Sheet drag / dock / FAB interaction needs a browser.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["2fb3d34f50459cddfcd8310d1a7250d77d111489"],"add":642,"del":11,"cadd":642,"cdel":11,"files":17},{"repo":"eureka-co-nevada","hash":"5dd48c5cdcb6e111907e8b0076da00f70e406e9e","ts":1783028914,"wall":"2026-07-02T17:48","msg":"feat(map): Phase 2 — real panels (layers, search, inspector)","body":"Replace the Phase-1 placeholders with the ported sidebar behaviour, now\nrendered as sheet (mobile) or dock (desktop) content through the panel host.\n\n- Config: fields/nav/search config migrated (SKIP_FIELDS, FIELD_ALIASES,\n  formatters, FIELD_ORDER, NAV_DATA point lists, SEARCH_FIELDS, LAYER_NAMES).\n- layers panel: basemap toggles + six group accordions; per-layer toggle,\n  opacity, sublayer legend (per-sublayer + Other + additive All), render-mode\n  radios + legend, and NAV_DATA fly-to lists. Map verbs live in layerActions.ts\n  so the Phase-3 palette reuses them.\n- search panel: NAV_DATA (full extent) + rendered features (viewport), grouped\n  and deduped. Logic in a map-free searchProvider — 5 unit tests.\n- inspector: click queries all features under the point (stacked-feature\n  disambiguation), shows ordered attributes; the sheet detents are the\n  progressive disclosure; camera pads so the feature clears the sheet.\n\nDeferred (noted, not dropped): timeline year-range filter; flexsearch fuzzy\nranking (lands in the Phase-3 palette, where a static index fits).\n\nFixed the legacy isNaN(Date) — now isNaN(d.getTime()), identical behaviour.\n\nVerified: tsc clean, vite build succeeds, dev server transforms all modules\n(200), 13 unit tests pass. In-browser interaction parity is the open check.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["a6c1f16b7cd63d1aaff85919809b907e596edc8e"],"add":1138,"del":27,"cadd":1138,"cdel":27,"files":19},{"repo":"eureka-co-nevada","hash":"4c2bbe710325f2c5ff85f0d77b4922932585b1f9","ts":1783029576,"wall":"2026-07-02T17:59","msg":"feat(map): Phase 3 — / command palette + Option-C hybrid","body":"The `/` FAB and physical `/` now open a fuzzy command palette — Praxis's one\npersistent affordance, made real. Plus the two Option-C accelerators.\n\n- commands/registry.ts: the single action surface. flexsearch Document index\n  (Dynamic's config); commandsByGroup backs the browse state.\n- commands/mapCommands.ts: open-panel, view (reset / screenshot / zen), and one\n  toggle per catalogue layer — layer toggles reuse layerActions, so `/toggle`\n  and a panel checkbox are the same code.\n- ui/palette.ts (+ css): recents (localStorage) + browse-by-group empty state\n  (the touch quick-action grid), fuzzy filter, keyboard nav, DOM-built rows,\n  visualViewport-pinned bottom sheet on mobile / centered box on desktop.\n- ui/contextMenu.ts: long-press / right-click on a feature → object-scoped\n  action sheet (inspect / center / copy coords) via MapLibre 'contextmenu'.\n- ui/voice.ts: feature-detected Web Speech mic in the palette — progressive\n  enhancement, off by default.\n- Screenshot needs canvas readback: canvasContextAttributes.preserveDrawingBuffer\n  (MapLibre 5 nesting).\n\nVerified: tsc clean, vite build succeeds, dev server transforms all modules\n(200), 18 unit tests pass (+5 command-registry). Interaction is the open check.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["5dd48c5cdcb6e111907e8b0076da00f70e406e9e"],"add":621,"del":4,"cadd":621,"cdel":4,"files":12},{"repo":"eureka-co-nevada","hash":"361934924af1a7eab24e59185922658448dc2f2e","ts":1783030933,"wall":"2026-07-02T18:22","msg":"feat(map): Phase 4 — direct-manip widgets, composable panels, persistence","body":"Give every tuned value a touch-first direct-manipulation widget, make the panel\nset a file-as-truth manifest, and persist the map's state.\n\n- widgets/: scrubber (pointer-capture, vertical-offset precision, stepper\n  fallback, touch-action:none), swatch (native input=color), toggle (switch),\n  reorder (SortableJS via handle). All 44/48 targets, motion gated on\n  prefers-reduced-motion.\n- Wired: opacity → scrubber, single-colour layers → swatch (recolour). Both\n  flow through state and persist. (toggle-swap is cosmetic; reorder needs\n  z-order infra — widgets built + documented, wiring deferred.)\n- state↔panel sync closed: rows subscribe to state, so a `/toggle` command\n  updates the checkbox. layers panel cached (build-once) to avoid subscription\n  leaks; rows read initial values from state, not config defaults.\n- config/panels.config.ts: the \"lego\" manifest — enable/order/dock panels by\n  editing data; registry.buildPanels honours it.\n- persist/store.ts: layer state (visible/opacity/renderMode/colour) →\n  localStorage, debounced autosave, restore on boot, JSON export/import (the\n  iOS-safe stand-in for File System Access). 3 round-trip tests.\n- perf: fadeDuration:0 + raster-fade-duration:0 (NAIP) for idle-static repaint.\n  pixelRatio / maxTileCacheSize caps and camera-easing reduced-motion relocated\n  to Phase 5 on-device tuning (verified against MapLibre 5 types, not assumed).\n\nVerified: tsc clean, vite build succeeds, 21 unit tests pass. Widget touch\ninteraction is the open in-browser check.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["4c2bbe710325f2c5ff85f0d77b4922932585b1f9"],"add":487,"del":17,"cadd":487,"cdel":17,"files":22},{"repo":"eureka-co-nevada","hash":"68d9b579faa5dc425680d1de2cbb2393c43b2e6c","ts":1783035928,"wall":"2026-07-02T19:45","msg":"docs: COP atom/card/fusion design model","body":"The design conversation redefined the map's goal: a Metabolic Common Operating\nPicture (spatial awareness + management dashboard) over four coupled strata,\nsolo-operator for now. Captures the CoT-shaped atom model (validated against\nonX + ATAK research), fusion as a careful legible power-tool, and the spine to\nbuild. This is the model the atom/card/fusion arc implements.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["361934924af1a7eab24e59185922658448dc2f2e"],"add":149,"del":0,"cadd":149,"cdel":0,"files":1},{"repo":"eureka-co-nevada","hash":"c1267e065617b1854c1b0bd4302e974456606276","ts":1783035943,"wall":"2026-07-02T19:45","msg":"fix(map): Chunk 0 — stabilize the chrome","body":"Three stabilization fixes so the card work has a working host to build on.\n\n- FAB / palette survive a map-load throw: mount the shell at top level, not\n  inside map.on('load'). A `.value` TypeError deep in the load path was aborting\n  the handler before the FAB mounted, taking the `/` down. Restore is now\n  guarded too.\n- Dock scroll: .dock-body gets min-height:0 (flex item can shrink → scroll), and\n  .dock overrides the <dialog> UA height:fit-content/max-height so top+bottom\n  size it. Long panels now scroll instead of overflowing.\n- Mobile sheet: replace the translate-based detents (which pushed a full-height\n  card's lower portion below the viewport, making the bottom of long content\n  unreachable) with HEIGHT-based detents — the card's height is the detent's\n  visible height, bottom-anchored, never translated off-screen; the body scrolls\n  within. Drag changes height; release snaps to nearest detent.\n\nVerified: tsc clean, vite build, 21 tests pass, dev server hot-reloaded clean.\nIn-browser confirmation (desktop + narrow viewport) is the operator gate.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["68d9b579faa5dc425680d1de2cbb2393c43b2e6c"],"add":65,"del":53,"cadd":65,"cdel":53,"files":4},{"repo":"eureka-co-nevada","hash":"3508fc97bbf8e8ca29d59f4fbd97674523fbadc3","ts":1783036365,"wall":"2026-07-02T19:52","msg":"feat(map): Chunk 1 — atom core (CoT model)","body":"The foundation of the COP arc: every map thing reduces to one uniform,\naddressable atom.\n\n- core/atom.ts: the CoT-shaped atom {uid, type, source, predicate, position,\n  state, links[], stale, provenance} + a store (create/get/patch/remove/\n  subscribe, link/unlink/linkedFrom, atomsByType prefix match). Model only —\n  identity + domain state + graph, no presentation (state.ts keeps that for now).\n- core/catalogueAtoms.ts: pure LAYERS → atoms — each layer is a source atom with\n  no predicate; each sublayer is the same source + a filter, linked to its parent\n  (the {source, predicate} specificity tiers). No map dependency → unit-testable.\n- main.ts registers the catalogue atoms on load. Additive and non-breaking: the\n  existing panels still read state.ts; nothing else changed.\n\nVerified: tsc clean, vite build, 29 tests pass (+8: atom store + catalogue→atoms,\nincl. all 43 layer atoms registering with correct source/predicate/links).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c1267e065617b1854c1b0bd4302e974456606276"],"add":263,"del":4,"cadd":263,"cdel":4,"files":6},{"repo":"eureka-co-nevada","hash":"817f4a6bb1dd374d9d77ec72b1e4143cfff946a6","ts":1783039703,"wall":"2026-07-02T20:48","msg":"feat(map): Chunk 2 — cards in a tray (ownership slice)","body":"The card surface shift, on the first slice (geography/ownership). Each layer is\na card you toggle independently; cards live in a bottom rail you pull from.\n\n- ui/card.ts: one atom → a tray chip (tap = independent toggle, the core ask)\n  that expands into its controls (opacity scrubber, colour swatch, sublayer\n  toggles). Reuses the widget factories + layerActions verbs — no new map logic;\n  subscribes to state so a /toggle command reflects on the chip.\n- ui/tray.ts: a bottom rail, identical desktop + mobile (thumb zone), horizontally\n  scrollable, left of the FAB. Populated from the Ownership slice (5 cards).\n  Expanded card panels float above the chip so the rail scrolls cleanly.\n- Mounts in main's load handler (needs the catalogue's sublayer map); shell now\n  exposes its root.\n\nScope/coexistence (deliberate for the slice): the old Layers panel stays for the\nother strata; the tray covers only ownership. Generalizing to all strata + the\ndeck/browser + retiring the old panel comes with Chunk 7. Drag-to-fuse is Chunk 6.\n\nVerified: tsc clean, vite build, 29 tests pass, modules transform. The tray's\nlook/feel is the operator's in-browser gate — this chunk is pure UX.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["3508fc97bbf8e8ca29d59f4fbd97674523fbadc3"],"add":285,"del":3,"cadd":285,"cdel":3,"files":7},{"repo":"eureka-co-nevada","hash":"47272536f1b84aae896ff45a828a1a6ea4b02732","ts":1783041293,"wall":"2026-07-02T21:14","msg":"docs: handoff — COP rebuild arc + Chunk 2 card model rejected","body":"Lead the handoff with the active mobile→COP rebuild (branch mobile-praxis-rebuild):\nwhat shipped (Phases 0-4 + Chunks 0-2), the CoT atom model, the chunk plan, and\nthe working agreement (consult always, gated chunks). Flags the critical state:\nChunk 2's tray-of-toggle-chips was rejected — cards must contain the entity + its\nparameters + notes; four questions open, no code until answered. Spatial-half\nhandoff preserved below as prior context.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["817f4a6bb1dd374d9d77ec72b1e4143cfff946a6"],"add":58,"del":1,"cadd":58,"cdel":1,"files":1},{"repo":"mesnada","hash":"79731be79da674e2b347cc0f01a207963ac912e2","ts":1783102036,"wall":"2026-07-03T14:07","msg":"docs: vast-world design memo + phased plan","body":"North-star design for the pivot to a vast, explorable world: fog-limited\nterrain serialization + viewport culling as the scale unlock, the\nFort→Settlement merge as the frontier expansion loop, a field-driven\ngeography rewrite, and traversal/content. Four-phase implementation plan\nwith the test suite as the safety net.","parents":["e037473d96802e1a62b5257b9fdb24aa49ea25fc"],"add":468,"del":0,"cadd":468,"cdel":0,"files":2},{"repo":"mesnada","hash":"8aa70eb953cc1290d4ea881d1ec0bf8cf4ac3755","ts":1783102651,"wall":"2026-07-03T14:17","msg":"feat: fog-limit terrain serialization (Phase 1A)","body":"Terrain now serializes only the viewer's revealed hexes, matching the fog\nrule settlements already used. Per-move payload scales with exploration\nrather than map size — the unlock for continental boards. viewer=None\nstill returns the full map for tests/AI/debug.\n\nAdds 3 fog tests (terrain limited to revealed, terrain memory for\nrevealed-not-visible, full map without viewer). 354 tests passing.","parents":["79731be79da674e2b347cc0f01a207963ac912e2"],"add":79,"del":4,"cadd":79,"cdel":4,"files":2},{"repo":"mesnada","hash":"562c4654c399dd5872b8b3e545c15422a5cd35e1","ts":1783105831,"wall":"2026-07-03T15:10","msg":"feat: viewport culling + large default map (Phase 1B/1C)","body":"Viewport culling (1B): the hex layer now builds only hexes within the\ncamera window plus a margin, and rebuilds as the camera pans/zooms past\nthat margin (coalesced to one rebuild per animation frame). New cull.ts\nholds the bounds math; renderHexes skips out-of-view hexes in every draw\nloop; GameBoard drives re-cull from the pan/zoom handlers. With no bounds\nsupplied it draws everything, so headless/other callers are unaffected.\n\nLarge default map (1C start): games always start at radius 40 (~4,900\nhexes); the size picker is removed for now. Fog-limited serialization\nkeeps the per-player payload ~4 KB regardless of map size.\n\nCamera now centers on the human player's forces on game load — on a large\nmap the starting area is far from the origin, which is unexplored and no\nlonger drawn, so an origin-centered camera showed only empty fog.\n\nFrontend typecheck + build clean.","parents":["8aa70eb953cc1290d4ea881d1ec0bf8cf4ac3755"],"add":136,"del":39,"cadd":136,"cdel":39,"files":4},{"repo":"mesnada","hash":"304c4cb6abc367c572ae2a340aa8511fa12d4afd","ts":1783108401,"wall":"2026-07-03T15:53","msg":"feat: extend Settlement with fortification model (Phase 2A)","body":"Settlement gains hp, max_hp, fortified, and an occupancy_limit property\nbacked by OCCUPANCY_BY_TIER (Homestead 3 -> Capital 20) — one pool for\nfield + garrison, per the Fort→Settlement merge design. Serialized in\nto_dict. Pure addition: defaults (0/0/False) preserve current behavior.\n\n357 tests passing.","parents":["562c4654c399dd5872b8b3e545c15422a5cd35e1"],"add":60,"del":0,"cadd":60,"cdel":0,"files":3},{"repo":"mesnada","hash":"da3b591a6e99ecbcd5a7885ee7537cd5ea9645d6","ts":1783110368,"wall":"2026-07-03T16:26","msg":"feat: two-mode fortify + sparse 10-town gen (Phase 2B)","body":"fortify is now two-mode: found a fortified Homestead on frontier\nwilderness (>= MIN_FOUND_SPACING=10 hexes from any settlement), or\nreinforce an owned settlement's walls (hp -> FORT_MAX_HP, fortified).\nNo longer creates a fort Structure.\n\nMap gen seeds STARTING_SETTLEMENTS=10 sparse towns on large maps\n(spread out), leaving ~2,500 hexes of foundable wilderness — a real\nfrontier. Small maps keep their area-scaled low count.\n\nAdds found/reinforce/spacing/enemy-settlement tests. 362 passing.","parents":["304c4cb6abc367c572ae2a340aa8511fa12d4afd"],"add":152,"del":13,"cadd":152,"cdel":13,"files":4},{"repo":"mesnada","hash":"9163e3c422c2f524bbb91bb28bf08ca70bdaa467","ts":1783111050,"wall":"2026-07-03T16:37","msg":"feat: combat reads settlement.fortified (Phase 2C)","body":"Fortification defense bonus now derives from a fortified settlement on\nthe hex (owner + fortified) instead of a fort Structure, in both attack\nand preview_combat. Adds shared settlement_at(state, hex) helper.\n\nMigrates test_fortification_boosts_defense to a fortified settlement with\na strict assert (the old <= passed hollow once structures stopped\nconferring the bonus); drops the obsolete incomplete-fort defense test\n(construction no longer affects combat). 361 passing.","parents":["da3b591a6e99ecbcd5a7885ee7537cd5ea9645d6"],"add":28,"del":43,"cadd":28,"cdel":43,"files":3},{"repo":"mesnada","hash":"2f1afeea85a371e542249856781555d9c493e68c","ts":1783113623,"wall":"2026-07-03T17:20","msg":"feat: fold garrison into settlement occupancy (Phase 2D)","body":"Removes state.garrison entirely — units on a settlement hex ARE the\ngarrison, capped by occupancy_limit (get_stack_limit). NPC neutral\ndefenders now spawn as units on the settlement hex, so a defended\nsettlement must be fought for (movement blocks enemy-occupied hexes),\nnot walked into.\n\nMigrated readers: settlement hexes cap at occupancy_limit; combat garrison\nbonus + counter come from co-located allied occupants; defender death\nauto-yields to the next in the stack (promote deleted); healing heals all\noccupants of an owned settlement; visibility/territory/AP-cap drop their\nredundant garrison loops (occupants are field units). Removed ungarrison\naction + dispatch; sap/siege keep their (now-dead) structure path for 2E.\n\nRewrites test_garrison.py against the occupancy model; migrates\nsettlement-ownership + ap-cap tests. 351 passing.","parents":["9163e3c422c2f524bbb91bb28bf08ca70bdaa467"],"add":193,"del":670,"cadd":193,"cdel":670,"files":13},{"repo":"mesnada","hash":"c3a160f426277068e75f133b9e9ddb88718c4b62","ts":1783114306,"wall":"2026-07-03T17:31","msg":"feat: siege breaches settlement walls, never deletes (Phase 2E)","body":"armor_pierce combat and the sap ability now target a fortified enemy\nsettlement on the hex (was the dead fort Structure path): reduce hp by\nFORT_SIEGE_DAMAGE / SAP_SIEGE_DAMAGE, and at hp <= 0 drop the fortified\nflag (walls breached) — the settlement itself is never removed, so it\nbecomes capturable by normal occupation/combat. Neutral fortified\nsettlements (owner None) are siegeable too.\n\nAdds non-arbalest/arbalest/breach/sap tests. 354 passing.","parents":["2f1afeea85a371e542249856781555d9c493e68c"],"add":110,"del":18,"cadd":110,"cdel":18,"files":3},{"repo":"mesnada","hash":"54a813840710c940b57184a2f23c2717a7891070","ts":1783114782,"wall":"2026-07-03T17:39","msg":"feat: treasury is a settlement building (Phase 2F)","body":"Adds a `treasury` BuildingDef. upgrade_treasury now constructs it in an\nowned settlement with a free slot (was: upgrade a fort Structure, which\ncan no longer exist). get_ap_cap adds TREASURY_AP_BONUS (50) per owned\nsettlement with a treasury — wiring the \"+50 AP cap\" that was only ever\nin the ability's description text. Un-parks the dormant ability.\n\nRewrites treasury tests for the building model (build raises cap, enemy/\nno-settlement/second-treasury rejections). 356 passing.","parents":["c3a160f426277068e75f133b9e9ddb88718c4b62"],"add":76,"del":22,"cadd":76,"cdel":22,"files":5},{"repo":"mesnada","hash":"712a84c52cf5945ddb8a9d601971b3253016f6d2","ts":1783115397,"wall":"2026-07-03T17:49","msg":"feat: neutral settlement flavors at map-gen (Phase 2G)","body":"Each neutral settlement is now assigned a flavor at generation, weighted\nby tier (NEUTRAL_FLAVOR_WEIGHTS): undefended (no occupants, walk in to\ncapture), defended (NPC occupants, no walls), or fortified (NPC occupants\n+ walls, must be breached then captured). Small frontier towns lean open;\ncapitals/cities lean fortified strongholds.\n\nAdds flavor-invariant and all-flavors-occur tests. 358 passing.","parents":["54a813840710c940b57184a2f23c2717a7891070"],"add":56,"del":3,"cadd":56,"cdel":3,"files":3},{"repo":"mesnada","hash":"120c031ec7393eb18c6417ed78a29506194fbf49","ts":1783115615,"wall":"2026-07-03T17:53","msg":"feat: right-click action pill (Praxis-aligned context menu)","body":"Right-clicking a hex opens a compact pill of that hex's contextual verbs\nat the cursor (Defend, skill abilities, Gather, Gear, Enter settlement,\nDeploy), matching the Elemental/Dynamic pattern. Left-click stays\ninspection (HexTooltip, hidden while the pill is open). Browser context\nmenu suppressed; right-click no longer selects or pans (left button only).\n\nAdds contextMenu state + openContextMenu/closeContextMenu to the game\nhook; Pixi rightclick per hex; new HexContextMenu component.","parents":["712a84c52cf5945ddb8a9d601971b3253016f6d2"],"add":285,"del":8,"cadd":285,"cdel":8,"files":6},{"repo":"mesnada","hash":"3919aec622301e7837eff7a384d73c2f6080b625","ts":1783118113,"wall":"2026-07-03T18:35","msg":"feat: remove Structure; frontend renders fortified settlements (Phase 2H)","body":"Backend: deletes the Structure dataclass, state.structures, and its\nserialization. Removes the now-dead fort paths — construction advancement,\nincomplete-fort abandonment on move, structure capture-on-move, the\nmounted-can't-defend-in-fort check — and redirects sap AI targeting to\nfortified enemy settlements. Sweeps dead constants (FORT_BUILD_TURNS_\nREQUIRED, AP_UNGARRISON, GARRISON_MAX_CAPACITY, SETTLEMENT_STACK_LIMIT)\nand drops obsolete structure tests. 355 passing.\n\nFrontend: the merge finally shows on screen. hexRenderer draws a wall ring\n+ wall-HP bar for fortified settlements (fort/treasury markers removed);\nHexTooltip shows settlement occupancy + fortification; the unit badge now\nshows the stack count (×N occupants). Removes all state.structures /\nstate.garrison / ungarrison code from the tooltip, pill, hook, and types;\nmove stacking respects occupancy_limit. Typecheck + build clean.\n\nCompletes the Fort→Settlement merge (Phase 2).","parents":["120c031ec7393eb18c6417ed78a29506194fbf49"],"add":82,"del":352,"cadd":82,"cdel":352,"files":19},{"repo":"mesnada","hash":"2fc4d96f577296fbd1d718a29bb91a92744c0b70","ts":1783120863,"wall":"2026-07-03T19:21","msg":"feat: label fortify as Found settlement / Reinforce walls","body":"The engineer's kit's fortify action now reads contextually in both the\nright-click pill and the tooltip: \"🏗️ Found settlement\" on open ground,\n\"🧱 Reinforce walls\" on your own settlement, and hidden on another\nplayer's settlement. Makes founding discoverable instead of buried behind\na generic \"Fortify\" label.","parents":["3919aec622301e7837eff7a384d73c2f6080b625"],"add":16,"del":2,"cadd":16,"cdel":2,"files":2},{"repo":"mesnada","hash":"ea7e469125a52c85ca224d8943f3fad76f546389","ts":1783121688,"wall":"2026-07-03T19:34","msg":"feat: field-driven world generation (Phase 3 — geography rewrite)","body":"Replaces the adjacency random-walk with elevation + moisture noise fields\nmapped to biomes, so the map has coherent continents, coastlines, mountain\nranges, and climate bands instead of mottled noise. Order-independent and\ndeterministic from the seeded rng; the 6 terrain types are preserved so the\nfrontend renders it unchanged.\n\n- noise.py: seeded 2D value noise + fBm (no dependency).\n- worldgen.py: generate_world() samples elevation/moisture per hex, applies a\n  radial continent falloff (ramped in by map size so small maps stay land-heavy),\n  maps (elevation, moisture) -> TerrainType. Tunable WORLDGEN_* config.\n- board_setup: uses generate_world; settlement eligibility widened to any\n  traversable land (not just plains/hills) so N players always spawn and\n  settlements vary. Deletes terrain_gen.py.\n- Tests: new test_worldgen.py (determinism, biome invariants, water/land balance,\n  land coherence, enough eligible hexes); migrates test_terrain/test_board_setup.\n\nradius-40 gen ~130ms (full game 326ms); 359 tests passing.","parents":["2fc4d96f577296fbd1d718a29bb91a92744c0b70"],"add":205,"del":130,"cadd":205,"cdel":130,"files":8},{"repo":"mesnada","hash":"164fb8fc92b119cdaff26345117b1a20cdc8b974","ts":1783126024,"wall":"2026-07-03T20:47","msg":"chore: dead-code sweep after Fort→Settlement merge","body":"Removes garrison/fort-construction leftovers the merge orphaned:\n- backend: 8 never-emitted EventType members (GARRISON_ENTER/UNGARRISON/\n  PROMOTE/EXPELLED, FORT_COMPLETED/CONSTRUCTION_PROGRESS/ABANDONED,\n  STRUCTURE_CAPTURED) + their main.py payload-map entries.\n- frontend: selectedGarrisonIndex / selectGarrisonUnit / SELECT_GARRISON_UNIT\n  state, the unused \"deploying\" Mode and its dead reducer branch, and the\n  matching dead EventLog cases + events.ts union members.\n\nAlso corrects now-misleading copy: siege \"destroyed\"/\"fort took dmg\" ->\n\"walls breached\"/\"walls took siege dmg\" (siege breaches, never deletes).\n\n359 tests passing; frontend typecheck + build clean.","parents":["ea7e469125a52c85ca224d8943f3fad76f546389"],"add":7,"del":62,"cadd":7,"cdel":62,"files":6},{"repo":"mesnada","hash":"d86091af070139fc9977acf2a1c2365b89e076d8","ts":1783127306,"wall":"2026-07-03T21:08","msg":"fix: audit follow-ups — dead code, territory stacking, gold, combat preview","body":"- Dead code: remove never-emitted events SPAWN/FORTIFY/SAP (backend enum +\n  main.py payload map + FE union + EventLog cases + animation branches),\n  repoint the founding animation to FORT_CONSTRUCTION_STARTED, and drop the\n  unused GATHER_YIELD config constant.\n- Territory: compute_territory now scales a hex's projection with its stack\n  (capped by TERRITORY_MAX_HEX_INFLUENCE) onto itself and each neighbor — a\n  full fort dominates its borders, a lone unit projects as before.\n- Gold: buy/recruit deduct via state.gold.get(player, 0) - cost, so a missing\n  player key can't KeyError.\n- Combat preview: the counter's minimum is 0 when the max incoming hit could\n  kill the defender (no counter if it dies) — the preview no longer over-\n  promises a guaranteed counter.\n\nAdds territory-stacking and preview-counter tests. 362 passing.","parents":["164fb8fc92b119cdaff26345117b1a20cdc8b974"],"add":75,"del":51,"cadd":75,"cdel":51,"files":11},{"repo":"mesnada","hash":"01e99313b9f94f40edb682889279d6b6d5f36a78","ts":1783127578,"wall":"2026-07-03T21:12","msg":"feat: keyboard board navigation — recenter, cycle units, pan","body":"GameBoard exposes an imperative camera API (centerOn/panBy) via a ref.\nApp wires it to keys:\n- Tab / Shift+Tab: cycle to next/prev friendly unit AND center the camera\n  on it (fixes the old cycle that selected off-screen units you couldn't see).\n- C: recenter the camera on the centroid of your forces.\n- Arrow keys: pan the board.\n\nMakes a vast map navigable without hunting with the mouse.","parents":["d86091af070139fc9977acf2a1c2365b89e076d8"],"add":83,"del":21,"cadd":83,"cdel":21,"files":2},{"repo":"mesnada","hash":"331033d8e38e38feb548d88578d4819e79ec737e","ts":1783128372,"wall":"2026-07-03T21:26","msg":"feat: shop prices + stay-in-shop after purchase","body":"- Bodega now shows prices: Buy (Ng) with the item's cost (grayed when\n  unaffordable) and Sell (N/2 g); items display their proper name, not the\n  raw id. SettlementModal takes itemDefs.\n- Purchases no longer kick you back to the map — UPDATE_STATE preserves the\n  settlement shop (mode/activeSettlement/selection) across buy/sell/recruit,\n  so you keep trading until you close it. Every other action still returns\n  to the map.\n- Recruit \"full\" check uses the settlement's real occupancy_limit instead of\n  a hardcoded 10.","parents":["01e99313b9f94f40edb682889279d6b6d5f36a78"],"add":28,"del":13,"cadd":28,"cdel":13,"files":3},{"repo":"mesnada","hash":"2940b1eadd0307fc65697f34ee99a863b2701e62","ts":1783128914,"wall":"2026-07-03T21:35","msg":"fix: SET_GAME wiped itemDefs, zeroing shop prices","body":"startNewGame loads item defs (SET_ITEM_DEFS) then dispatches SET_GAME,\nwhich reset to INITIAL carrying only `abilities` — dropping the just-loaded\nitemDefs back to {}. Prices resolved to 0g (masked before, since the shop\ndidn't show prices). SET_GAME now preserves itemDefs like it does abilities.","parents":["331033d8e38e38feb548d88578d4819e79ec737e"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"mesnada","hash":"69b35c728ae2706e904b942b649ae1f7ab502a44","ts":1783131321,"wall":"2026-07-03T22:15","msg":"fix: assassin's kit renders as the concealed assassin","body":"An assassin's kit now resolves to the hooded-assassin sprite (like a cloak),\nhiding all other gear — assassins conceal their loadout. Reuses the existing\nAssasinationCloakKit.png; no new art, and drops the assassin's-kit sprite from\nthe outstanding list.","parents":["2940b1eadd0307fc65697f34ee99a863b2701e62"],"add":4,"del":4,"cadd":4,"cdel":4,"files":1},{"repo":"mesnada","hash":"e3856883c06e4d6c4f448c9939bee3a59e38a902","ts":1783131744,"wall":"2026-07-03T22:22","msg":"art: leather rifleman sprite (leather+rifle)","body":"Adds LeatherRifleman.png (white bg flood-filled to transparent) and its\nSPRITE_MAP entry. First of the 4 outstanding foot-soldier avatars.","parents":["69b35c728ae2706e904b942b649ae1f7ab502a44"],"add":1,"del":0,"cadd":1,"cdel":0,"files":2},{"repo":"mesnada","hash":"3cc9926bec2423c8d6bad51264cb8c5f821af0c1","ts":1783131791,"wall":"2026-07-03T22:23","msg":"art: plate shieldbearer sprite (full_plate+wooden_shield)","body":"Adds FullPlateWoodShield.png (bg flood-filled to transparent) + SPRITE_MAP\nentry. Second of the 4 outstanding foot-soldier avatars.","parents":["e3856883c06e4d6c4f448c9939bee3a59e38a902"],"add":1,"del":0,"cadd":1,"cdel":0,"files":2},{"repo":"mesnada","hash":"0f81ad5d94c49662c0b4fed657b9ef70384ee804","ts":1783132056,"wall":"2026-07-03T22:27","msg":"art: iron shieldbearer sprite (iron_shield)","body":"Adds IronShield.png (bg flood-filled to transparent) + SPRITE_MAP entry.\nThird of the 4 outstanding foot-soldier avatars.","parents":["3cc9926bec2423c8d6bad51264cb8c5f821af0c1"],"add":1,"del":0,"cadd":1,"cdel":0,"files":2},{"repo":"mesnada","hash":"2a46fe13a0d72a26cfdc0baafc89ced443c8e748","ts":1783132260,"wall":"2026-07-03T22:31","msg":"art: chainmail iron shieldbearer sprite (chainmail+iron_shield)","body":"Adds ChainIronShield.png (bg flood-filled to transparent) + SPRITE_MAP entry.\nCompletes the 4 outstanding foot-soldier avatars — foot roster fully drawn.","parents":["0f81ad5d94c49662c0b4fed657b9ef70384ee804"],"add":1,"del":0,"cadd":1,"cdel":0,"files":2},{"repo":"mesnada","hash":"0d0bd5b8423d0228d830e74f49c01965c06eb6e0","ts":1783133197,"wall":"2026-07-03T22:46","msg":"feat: activate dormant abilities via gear (ambush + magic tree)","body":"Rank-up skill-learning is not implemented -- learn_sources metadata is\ninert, so the only working skill-acquisition path in game is gear grants.\nThat left four coded abilities unreachable. Grant them via gear:\n\n- assassins_kit -> grants ambush (turns on the stealth-crit + plunder-on-kill\n  passive already coded in combat_actions.py; kit previously granted nothing).\n- New grimoire item -> grants confuse. All three magic abilities\n  (confuse, terrorize, mind_sight) gate on required_special \"confuse\", so one\n  item unlocks the whole arcane tree. Support/arcane, 6g, corporal-gated.\n\nTests: assassins_kit->ambush, grimoire->confuse, and the invariant that the\nconfuse special unlocks exactly {confuse, terrorize, mind_sight}. 364 passed.","parents":["2a46fe13a0d72a26cfdc0baafc89ced443c8e748"],"add":43,"del":5,"cadd":23,"cdel":4,"files":3},{"repo":"mesnada","hash":"e0e4136ae8d6bb547642e8ce63a7456b05824c04","ts":1783133744,"wall":"2026-07-03T22:55","msg":"feat: named recruit archetypes in the plaza (loadouts)","body":"The plaza used to roll a random rank + 0-2 random items per recruit, so the\nshop read as \"sergeant + full_plate, longsword\". Replace that with 17 named\narchetypes authored as data/loadouts/*.json (Swordsman, Man-at-Arms, Knight,\nCrossbowman, Halberdier, Longbowman, Rifleman, Assassin, Mage, Engineer,\nMedic, ...). generate_plaza_roster now draws eligible archetypes: an archetype\nis offered at a tier when its rank fits the tier's rank cap and every piece of\nits gear is within the tier's item-cost cap. Each archetype's rank is set so it\ncan legally equip its own gear; a test enforces that invariant.\n\nRecruits carry {loadout_id, name} through the RECRUIT event; the settlement\nmodal shows the archetype name with rank + gear as readable subtext. Skills\nstill derive from gear, so the Assassin gains ambush and the Mage gains the\nconfuse tree with no extra wiring. Knight is Capital-only; Mage is Metropolis+.\n\n369 passed; frontend typecheck + build clean.","parents":["0d0bd5b8423d0228d830e74f49c01965c06eb6e0"],"add":334,"del":42,"cadd":133,"cdel":42,"files":23},{"repo":"mesnada","hash":"c6786527ca7ec746e8381e1e42b7f162faf76c30","ts":1783134171,"wall":"2026-07-03T23:02","msg":"feat: two Tier-1 combat passives -- shield_wall and duelist","body":"Add depth to gear that previously granted no skill:\n\n- shield_wall (wooden_shield, iron_shield): +20% defense when the bearer is\n  adjacent to >=1 friendly unit. Computed in _effective_defense via the same\n  lazy count_adjacent_allies pattern the adjacent_ally crit already uses; the\n  defender defense and the counter-attack defense both pass state + coord, and\n  the preview caller passes them too, so preview and resolution stay in sync.\n- duelist (shortsword, longsword): +25% attack in melee (distance 1). One-line\n  hook in _effective_attack, mirroring the weak_melee penalty.\n\nA sword-and-board unit picks up both, which rewards fighting in formation.\nSkills authored as data/skills/*.json (passive, gear-learned). marksman/zealot\ndeferred -- they need a ranged-identity and a morale-system decision.\n\n375 passed.","parents":["e0e4136ae8d6bb547642e8ce63a7456b05824c04"],"add":143,"del":16,"cadd":99,"cdel":6,"files":9},{"repo":"mesnada","hash":"227f3c97c047ec9e051a7b945474524eea111184","ts":1783135266,"wall":"2026-07-03T23:21","msg":"feat: skill books -- learn specialist skills from tomes bought at the Bodega","body":"Adds a book economy so the hard-to-get specialist skills (which had no working\nacquisition path -- rank-up learning is unimplemented) can be learned:\n\n- ItemDef gains an optional teaches_skill field (backward-compatible; loader +\n  /api/items serializer updated). Eight books authored under data/items/:\n  Codex of Confusion (confuse), Manual of Ambush, Treatise on Command,\n  Ranger's Field Guide (scout), The Shadow Manual (stealth), Engineer's\n  Handbook (fortify), Meditations on the Last Stand, Ledger of Statecraft\n  (upgrade_treasury). Equipment-inherent skills (shield_wall, duelist,\n  armor_pierce, heal) stay gear-only per design.\n- New learn_from_book action (mirrors equip): reading a book permanently\n  appends the skill to unit.skills, is gated by the skill's min_rank, rejects a\n  skill the pawn already has, and CONSUMES the book. New LEARN event, registered\n  in the fog filter. API dispatch case \"learn\".\n- Bodega always stocks the tier-affordable tomes (reserved slots, so inventory\n  size bounds hold): scout from Homestead, all eight from Town up.\n- Frontend: PawnPanel splits inventory into equippable gear (Equip) and Tomes\n  (Read), shows the pawn's known skills; the Bodega gets a Tomes shelf. A book\n  teaching confuse lights up the whole magic tree, as with the grimoire.\n\n382 passed; frontend typecheck + build clean.","parents":["c6786527ca7ec746e8381e1e42b7f162faf76c30"],"add":413,"del":17,"cadd":237,"cdel":17,"files":21},{"repo":"mesnada","hash":"7e991547038ed3c422b900a0034bce841cfa6175","ts":1783135771,"wall":"2026-07-03T23:29","msg":"refactor: remove the grimoire (and the Mage archetype it powered)","body":"The grimoire granted confuse as gear; the Codex of Confusion book now teaches\nconfuse permanently, making the grimoire redundant. Remove it, and with it the\nMage recruit archetype (which was defined as gear: [grimoire] and would\notherwise reference a dead item). Magic is now acquired one way: recruit any\ncorporal+ unit, buy the Codex of Confusion at the Bodega, and read it.\n\nDrops the grimoire item, the mage loadout, and their two tests; de-references\nthem in the remaining tests and the roster docstring. 380 passed; frontend\ntypecheck clean.","parents":["227f3c97c047ec9e051a7b945474524eea111184"],"add":5,"del":53,"cadd":5,"cdel":23,"files":6},{"repo":"mesnada","hash":"35589053cc19276d2fdefb8af8243b1829176af5","ts":1783136307,"wall":"2026-07-03T23:38","msg":"feat: one book per magic ability -- split confuse/terrorize/mind_sight","body":"Previously terrorize and mind_sight both gated on the confuse special, so a\nsingle book unlocked all three. Give each its own special and its own book:\n\n- terrorize ability now requires_special \"terrorize\"; mind_sight requires\n  \"mind_sight\" (both were \"confuse\").\n- MAGICAL_SPECIALS gains terrorize + mind_sight so they still incur magical\n  burnout.\n- New tomes: Book of Terror (terrorize) and Codex of Second Sight (mind_sight),\n  corporal-gated, stocked at the Bodega alongside the Codex of Confusion.\n\nThe Codex of Confusion now teaches confuse only. Updated the garrison-abilities\nand magic-book tests accordingly, and de-brittled test_all_neutral_flavors_occur\n(it was seed-locked; the two new items perturbed the RNG stream -- now it\naggregates over several maps, since 'fortified' is rare on any single one).\n\n381 passed; frontend typecheck clean.","parents":["7e991547038ed3c422b900a0034bce841cfa6175"],"add":81,"del":21,"cadd":37,"cdel":21,"files":8},{"repo":"mesnada","hash":"268033ebda65290d62f8b749b6137cb6fb3d28b7","ts":1783137811,"wall":"2026-07-04T00:03","msg":"feat: gear trading -- hand equipped gear to an adjacent friendly unit","body":"Adds a direct unit-to-unit handoff (the \"direct adjacent handoff\" model): a\ngiver passes an equipped item straight to a friendly unit one hex away, gated by\nthe receiver's rank (same gate as equipping). Coexists with the existing shared\nplayer inventory; does not alter it.\n\n- New give_gear action: friendly giver + friendly receiver (unit 0 at to_hex),\n  distance <= 1, item held, receiver meets item min_rank -> transfer. New GIVE\n  event (from/to coords), registered in the fog filter; API dispatch case \"give\".\n- Frontend: the pawn panel lists adjacent friendly units under each equipped\n  item as \"Give to <unit>\" buttons (disabled + reasoned when the target's rank\n  is too low). Adjacency computed from hex neighbors in App.\n\n386 passed; frontend typecheck + build clean.","parents":["35589053cc19276d2fdefb8af8243b1829176af5"],"add":223,"del":16,"cadd":223,"cdel":16,"files":9},{"repo":"mesnada","hash":"e4c9a48cd9bcfbf5cd1238fe640e5945e160d973","ts":1783177656,"wall":"2026-07-04T11:07","msg":"docs: regenerate handoff from current state (was ~50 commits stale)","body":"","parents":["268033ebda65290d62f8b749b6137cb6fb3d28b7"],"add":114,"del":87,"cadd":114,"cdel":87,"files":1},{"repo":"mesnada","hash":"e1bf9b41333d81e19fdaad816773795d54e75626","ts":1783200356,"wall":"2026-07-04T17:25","msg":"docs: settlement metabolism design memo","body":"Living settlement economy to replace the one-way gold funnel: population as\nmetabolism (consumes food/fuel/medicine, produces labour+soldiers, emits\npollution), units as circulatory system, carrying capacity, land-use ring,\npollution diffusion field, ecological succession + ruins-as-memory. Includes\nimplementation fit against existing seams and v1/v2/v3 staging.","parents":["e4c9a48cd9bcfbf5cd1238fe640e5945e160d973"],"add":355,"del":0,"cadd":355,"cdel":0,"files":1},{"repo":"mesnada","hash":"6dcf8a3e168c0f36fd83dcd014b074126b0b47bf","ts":1783203645,"wall":"2026-07-04T18:20","msg":"feat: construction economy (Phase A) — materials build buildings","body":"Settlements gain a material stockpile and a general construction action,\nturning the one-way gather->sell-for-gold loop into a real economy.\n\n- Data-driven building defs (data/buildings/*.json + building_loader);\n  BuildingDef gains cost/ap_cost/store_capacity.\n- Settlement.stores + store_capacity (gated behind a warehouse), serialized.\n- deposit_resource action: unit bag -> settlement stockpile, capacity-clamped.\n- construct action generalizes the treasury; bootstrap rule — storage\n  buildings paid from the acting pawn's bag, others from stores.\n- Treasury deprecated as an ability; now a constructed building (stone+ore).\n- Wall-repair sink: reinforce costs REINFORCE_COST from stores; founding free.\n- Frontend: /api/buildings catalog, construct/deposit actions, SettlementModal\n  Construct panel + Stores display + Deposit control.\n- Tests: test_construction.py (14) + building-def/reinforce tests; treasury\n  tests rewritten to construct. 403 pass / 3 skip; frontend typecheck+build clean.\n\nDesign: research/mesnada-settlement-metabolism-design.md (Phase A of v1).","parents":["e1bf9b41333d81e19fdaad816773795d54e75626"],"add":908,"del":108,"cadd":876,"cdel":108,"files":29},{"repo":"mesnada","hash":"b77e7f7428df454a0939b40a8aeba71e76633e4d","ts":1783209806,"wall":"2026-07-04T20:03","msg":"feat: Phase B population/demographics + book-kit ability rework","body":"Two settlement-economy features landed together — they intermingle in\nsettlement.py and test_settlement_actions.py, so they can't be split without\ninteractive hunk staging.\n\nPopulation & Demographics (Phase B):\n- Settlement.population (float) + tier-based carrying capacity K and subsistence floor\n- Per-turn _process_population in end_turn: logistic growth when fed, starvation\n  toward the floor when not; owner-filtered so neutral settlements stay static\n- Hard food upkeep from grain/fish in stores; below-floor population regrows free\n- Recruiting drains population (1); plaza roster size scales with population\n- Emergent auto tier-promotion (population threshold + next tier's buildings)\n- Map-gen seeds towns at ~0.6*K; SettlementModal shows Population X/K + hint\n- Events STARVATION, TIER_PROMOTED; new test_population.py (13 tests)\n\nBook/kit ability rework:\n- Only magical abilities are book-learned (grimoires); learn_from_book now guards\n  on MAGICAL_SPECIALS\n- Removed 7 redundant/orphaned books (fortify/ambush/stealth/command/scout/\n  last_stand/statecraft) — their gear (kit/cloak/field_radio/spyglass) or rank\n  already grants the skill\n- Renamed the 3 remaining magic books to \"Grimoire of ...\"\n\n418 tests pass; frontend typecheck + build clean.","parents":["6dcf8a3e168c0f36fd83dcd014b074126b0b47bf"],"add":582,"del":183,"cadd":579,"cdel":26,"files":24},{"repo":"mesnada","hash":"56a8dd36b935b661666d699c2f060574df0abf5d","ts":1783216416,"wall":"2026-07-04T21:53","msg":"feat: auto-gather workers, per-pawn order targeting, construct shortfall UI","body":"Three features landed together — they intermingle across gathering.py, main.py,\nuseGameActions, HexContextMenu, and App.tsx, so they can't be split without\ninteractive hunk staging.\n\nAuto-gather workers (deterministic haul shuttle):\n- Toggle a pawn on a resource hex to a work stance (units.py gathering/gather_site/\n  home_base); the engine shuttles it between dig site and its warehouse-settlement\n  each turn — gather until loaded, walk home, deposit, return — on its own movement\n  budget (no shared AP). _process_workers in end_turn; greedy step-toward pathing.\n- set_gathering action + dispatch; ⛏ pill toggle + worker badge; test_workers.py.\n\nPer-pawn order targeting fix:\n- Orders were defaulting to stack index 0. Thread unit_index through gather,\n  set_gathering, deposit, sell, construct, and the ability acting-unit path\n  (backend + main.py dispatch + frontend action creators).\n- Right-click pill now acts on the selected stacked pawn and shows a per-pawn\n  picker when >1 pawn shares the hex. test_targeting.py.\n\nConstruct panel shortfall UI:\n- Unaffordable buildings show exactly what you're short (per resource + AP);\n  affordability now accounts for AP, not just materials.\n\n435 tests pass; frontend typecheck + build clean.","parents":["b77e7f7428df454a0939b40a8aeba71e76633e4d"],"add":565,"del":22,"cadd":565,"cdel":22,"files":16},{"repo":"mesnada","hash":"c022129dbc0c7e52123f2b4431d6c21a7a4ba36b","ts":1783217375,"wall":"2026-07-04T22:09","msg":"feat: gather v2 — resource weight, pick-a-resource, no warehouse needed","body":"Makes auto-gather loads physical and more flexible.\n\n- Resources carry weight (stone/ore 3, timber/peat 2, grain/fish/fiber/herbs 1);\n  bag weight counts toward encumbrance so a laden pawn is overencumbered and moves\n  slower (down to 1 hex/turn). Combat units with empty bags are unaffected.\n- Fixed the legacy stats path (pawn.py) which hardcoded capacity=0/no-encumbrance,\n  so bare worker pawns now actually feel weight.\n- Workers choose which resource to harvest (set_gathering takes resource_type;\n  per-resource \"Auto-gather X\" buttons in the pill).\n- No warehouse required: with an owned warehouse a worker shuttles + deposits;\n  without one it fills its own bag and idles for manual pickup. Losing the base\n  demotes to bag-only rather than cancelling.\n- \"Loaded\" is weight-based (overencumbered), replacing the flat haul limit.\n\n439 tests pass (16 worker tests); frontend typecheck + build clean.","parents":["56a8dd36b935b661666d699c2f060574df0abf5d"],"add":181,"del":59,"cadd":181,"cdel":59,"files":12},{"repo":"mesnada","hash":"be174d38d292e45ead690125c6e4ec40f7b76626","ts":1783217470,"wall":"2026-07-04T22:11","msg":"docs: refresh handoff — settlement metabolism arc (Phase A/B, workers, gather-v2)","body":"","parents":["c022129dbc0c7e52123f2b4431d6c21a7a4ba36b"],"add":77,"del":126,"cadd":77,"cdel":126,"files":1},{"repo":"mesnada","hash":"f8743d88dc67672cd410733669e3e197c2945e65","ts":1783225457,"wall":"2026-07-05T00:24","msg":"fix: remove units by identity, not stack index or value equality","body":"remove_unit_at() fell back to stack.pop(0) when called without a unit,\nand used list.remove (value equality) otherwise. On a stacked hex this\ndeleted the wrong unit and, where the caller re-places the intended unit\n(movement, rout-flee), duplicated it as a single object aliased into two\nhexes. Because Unit is a value-comparing dataclass, two freshly-recruited\npawns compare equal, so even passing the unit removed the wrong one.\n\n- unit_access.remove_unit_at: match the exact object by identity, not equality\n- thread the intended unit through every wrong-unit-hazardous caller:\n  movement, DOT death (turn), rout/shatter/flee (morale), attacker death\n  (combat x2), ability burnout; pass defender/target explicitly elsewhere\n\nAdds tests/test_stack_removal.py (4 regression tests). Suite: 443 passed.\n\nFixes audit findings C-1 (unit duplication) and C-2 (DOT wrong-unit).","parents":["be174d38d292e45ead690125c6e4ec40f7b76626"],"add":149,"del":17,"cadd":149,"cdel":17,"files":8},{"repo":"mesnada","hash":"fa9078a67193659b745bc43d9a07aad2c943439d","ts":1783226167,"wall":"2026-07-05T00:36","msg":"fix: worker crash on full target + resource regen player-count scaling","body":"Two independent turn-engine defects:\n\nC-3: _worker_step_toward exempted the target hex from the stack-limit\ncheck, then place_unit() raised ValueError on a full target — crashing\nend_turn (and losing the worker, since it was removed before placement).\nDrop the exemption so the worker's check matches place_unit's guard; a\nworker facing a full target now holds instead of crashing.\n\nH-10: resource regeneration ran on every player's end_turn, so an\nN-player game regenerated N times per round (regen_rate is a per-round\nrate). Gate regen on rotation wrap so it fires once per full round,\nindependent of player count.\n\nTests: adds a worker-holds-at-full-target regression; replaces\ntest_regen_on_end_turn (which encoded the per-player-turn cadence) with\ntest_regen_after_full_round + test_no_regen_mid_round. Suite: 441 passed.\n\nFixes audit findings C-3 (end_turn crash) and H-10 (regen scaling).","parents":["f8743d88dc67672cd410733669e3e197c2945e65"],"add":58,"del":15,"cadd":58,"cdel":15,"files":3},{"repo":"mesnada","hash":"813707a629d97a318e59b613339d59d6369a45e1","ts":1783260548,"wall":"2026-07-05T10:09","msg":"fix: combat burnout orphan, mutual-elimination draw, AI-loop hang","body":"Three termination/resolution defects:\n\nC-4: a magical attacker that killed its target and then burned out from\nattack fatigue hit an early-return that skipped defender removal, capture,\nand the win check — leaving the dead defender on the board. Remove the\nearly-return; the unified attacker-death handling below already removes a\nburned-out attacker (hp == 0), so the attack's effects still resolve.\n\nM-10: a mutual last-unit kill left no winner but marked everyone\neliminated — a soft-lock. Add GameState.game_over (serialized) and, in the\nshared _check_win_condition, treat an empty survivor set as a draw\n(GAME_OVER, winner=None) and set game_over on wins. Route the duplicate DOT\nwin-check through the shared function; surrender sets game_over.\n\nC-5: the AI auto-play loop (both routes) spun `while ...ai_players and not\nwinner` with no bound, so an all-AI game that never resolves hung the\nrequest worker. Extract one _autoplay_ai(state) helper that stops on\ngame_over and caps at MAX_AI_TURNS_PER_REQUEST.\n\nTests: adds test_termination.py (draw, single-survivor win, burnout-orphan\nvia forced roll, bounded stalemate). Suite: 443 passed.\n\nFixes audit findings C-4, C-5, M-10.","parents":["fa9078a67193659b745bc43d9a07aad2c943439d"],"add":141,"del":27,"cadd":141,"cdel":27,"files":6},{"repo":"mesnada","hash":"462436aa12bdf09278d8736baba292cddf41263b","ts":1783261209,"wall":"2026-07-05T10:20","msg":"fix: movement pathfinding — no leaping over impassable terrain","body":"move_unit accepted any hex within straight-line movement range, checking\nonly the destination's terrain and charging terrain cost for the\ndestination alone. A unit could therefore leap straight over an impassable\nmountain or water hex, and difficult terrain en route was free. The AI's\nmove enumeration shared the same flaw — and because a rejected move aborts\nthe AI's whole turn, fixing only move_unit would have made the AI stall.\n\nAdd one shared reachable_costs() helper (bounded BFS over traversable\nhexes; per-hex AP = terrain move_cost) used by BOTH move_unit and the AI:\n\n- a move now requires a real traversable path (no leaps); units detour\n  around a single obstacle when an alternate path fits within range\n- terrain cost is charged for every hex entered, not just the destination\n- the heavy-terrain restriction that the leap voided is restored\n- move_unit and the AI agree on reachability, so the AI never proposes a\n  move move_unit would reject\n\nTests: adds test_pathfinding.py (no-leap, detour-in-range, per-hex cost,\nplains-unchanged, AI-no-leap). Suite: 444 passed.\n\nFixes audit finding H-1.","parents":["813707a629d97a318e59b613339d59d6369a45e1"],"add":148,"del":30,"cadd":148,"cdel":30,"files":3},{"repo":"mesnada","hash":"d09858e93d7fc0054b9a46805c9587de54cf664e","ts":1783263156,"wall":"2026-07-05T10:52","msg":"fix: garrison counter, XP->AP refund, and high-ground bonus","body":"Three combat mechanic corrections:\n\nH-2: the garrison counter-attack summed every co-defender's RAW attack,\nunmitigated and unbounded, so a large settlement's garrison one-shot any\nattacker regardless of armor. Now only the strongest GARRISON_COUNTER_MAX_UNITS\nco-defenders contribute, and their summed throw is reduced by the attacker's\neffective defense — a lone weak defender is absorbed; only a collectively\nstrong garrison lands a counter.\n\nH-6: the XP->AP refund (xp // 2) could meet or exceed an attack's AP cost,\nletting a unit at its AP cap attack indefinitely within a turn. Cap the\nrefund at AP_ATTACK - 1 so every attack nets at least 1 AP spent.\n\nH-9: \"high ground\" was a dead gear-gated crit condition that merely checked\nwhether the attacker stood on hills. It is a TERRAIN advantage available to\nany unit: striking from higher terrain than the target now grants\n+HIGH_GROUND_ATTACK_BONUS attack (elevation: mountain>hills>plains/forest>\nswamp/water), applied in combat resolution and preview. Removed from the\ngear-crit path.\n\nTests: adds test_combat_mechanics.py (refund cap, high-ground damage,\ngarrison cap + defense). Updates one garrison test that encoded the old\nunmitigated counter. Suite: 459 passed.\n\nFixes audit findings H-2, H-6, H-9.","parents":["462436aa12bdf09278d8736baba292cddf41263b"],"add":169,"del":26,"cadd":169,"cdel":26,"files":5},{"repo":"mesnada","hash":"e74afa198b553c14834fabd97e1c1ad423fffdcb","ts":1783263918,"wall":"2026-07-05T11:05","msg":"fix: gather minting, gear-action targeting, malformed-payload 500","body":"Three economy/dispatch point fixes:\n\nH-5: the gather specialist bonus OVERWROTE the yield after drawing one unit\nfrom the node, so the bag gained 2 while the deposit lost only 1 —\nduplicating finite (regen-0) stone/ore. gather_resource and _worker_gather\nnow extract each unit from the node (repeated draws), so the node loses\nexactly what the bag gains and a specialist can't exceed what remains.\n\nH-7: equip_item / unequip_item / learn_from_book always acted on stack\nindex 0, so on a multi-pawn hex the item/skill landed on the wrong pawn\nwhile the UI showed another. Thread unit_index through the three actions\nand the dispatch (mirroring give_gear).\n\nH-11: a malformed hex string (e.g. from_hex=\"abc\") raised an unhandled\nValueError/IndexError out of Hex.from_str, returning a 500. submit_action\nnow catches it and returns 400 (client error).\n\nTests: adds test_economy_dispatch.py (gather conservation, selected-pawn\nequip, malformed hex -> 400). Suite: 458 passed.\n\nFixes audit findings H-5, H-7, H-11.","parents":["d09858e93d7fc0054b9a46805c9587de54cf664e"],"add":126,"del":15,"cadd":126,"cdel":15,"files":5},{"repo":"mesnada","hash":"93966e74513361be11002ef3537435b0d737c356","ts":1783265685,"wall":"2026-07-05T11:34","msg":"feat: buy buildings with gold as an either/or alternative to materials","body":"A building can now be paid for EITHER with its gathered materials (the\nexisting path) OR with a gold price — the player's choice each build. AP is\nstill the labour cost either way; buying with gold consumes no materials and\nthe material path is unchanged.\n\n- data: gold_cost on each building (warehouse/bodega 60, plaza 80,\n  treasury 100), loaded into BuildingDef and served by /api/buildings\n- backend: construct(pay_with_gold) validates and deducts gold_cost;\n  ActionPayload.pay_with_gold threaded through the dispatch\n- frontend: the Construct panel shows the gold price and a \"Buy Ng\" button\n  beside \"Build\", disabled unless you have the gold and AP\n\nTests: test_buy_buildings.py (buy success + gold debit, insufficient gold,\nno materials consumed, material path unchanged, AP still required).\nVerified end-to-end over HTTP. Suite: 463 passed; tsc + vite build clean.","parents":["e74afa198b553c14834fabd97e1c1ad423fffdcb"],"add":155,"del":36,"cadd":147,"cdel":32,"files":12},{"repo":"mesnada","hash":"42aa4d08d315687e6e418b9b6f4ec8d43b57f59d","ts":1783265843,"wall":"2026-07-05T11:37","msg":"docs: session handoff + defect audit + remediation roadmap","body":"Persist the full defect audit (48 findings) and the 10-chunk remediation\nroadmap, and refresh the handoff to reflect Chunks 1-6 + buy-with-gold\nshipped this session. Chunk 7 (dual stat-path) is next, decision-gated.\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["93966e74513361be11002ef3537435b0d737c356"],"add":610,"del":84,"cadd":610,"cdel":84,"files":3},{"repo":"mesnada","hash":"f12cd0012cc5dbe7539efc5076a4e20e25dd0582","ts":1783268219,"wall":"2026-07-05T12:16","msg":"feat: withdraw resources from a warehouse into a pawn's bag","body":"The reverse of deposit: pull the whole stored amount of a resource type from\na settlement's stores back onto the acting pawn. WITHDRAW event (registered in\nthe fog filter); a Withdraw button on each Stores line in the settlement modal.\n\nTests: test_withdraw.py (stores->bag, stacking, empty-store + non-owner errors).\nVerified end-to-end over HTTP. Suite: 472 passed.\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["42aa4d08d315687e6e418b9b6f4ec8d43b57f59d"],"add":145,"del":4,"cadd":145,"cdel":4,"files":10},{"repo":"mesnada","hash":"ccfc64cee679073d84bcae892a352d2c4663d455","ts":1783268402,"wall":"2026-07-05T12:20","msg":"fix: load bodega/building prices on mount, not only on New Game","body":"The item and building catalogs were fetched only inside startNewGame, so a\ngame created while those requests hadn't resolved (e.g. during a backend\nreload) left itemDefs empty and every bodega price rendered as '0g'. Extract\nloadCatalogs() and also run it once on app mount, so prices are always present.\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["f12cd0012cc5dbe7539efc5076a4e20e25dd0582"],"add":22,"del":3,"cadd":22,"cdel":3,"files":2},{"repo":"mesnada","hash":"6389afeb09c49029cd9e8d636a6ae32e478e50d8","ts":1783269584,"wall":"2026-07-05T12:39","msg":"refactor: unify stat model; rank scales only via percentages","body":"Chunk 7 (keystone). get_effective_stats had two divergent paths (a legacy\nUnitType path for bare units, a rank+gear path for the rest) that units flipped\nbetween. Collapse to ONE model: base stats from the rank table, class tags +\nspawn_cost + innate special/crit from the unit type, gear layered on top.\n\nRank model (operator decision): percentage-only. Flatten attack/defense/movement\nin ranks.json so they are constant across ranks; rank scales those solely through\nthe RANK_*_BONUS percentages applied in combat/movement. HP, carry capacity and\nskill slots still climb with rank.\n\nFixes audit findings:\n- H-3: rank no longer double-scales (table climb + percentage).\n- H-4: infantry/melee class tags now present on geared units, so the tag triangle fires.\n- H-8: learning a skill no longer flips a bare pawn's HP (60->50) or drops its tags.\n- M-6: spawn_cost populated for geared units (AI values them correctly).\n\nTests: adds test_stat_unification.py; updates two rank tests that encoded the old\nbase-stat climb. Suite: 476 passed.\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["ccfc64cee679073d84bcae892a352d2c4663d455"],"add":93,"del":65,"cadd":85,"cdel":57,"files":4},{"repo":"mesnada","hash":"0e9994f91c16f73b8f611295b1b1c9ce45488bfb","ts":1783272920,"wall":"2026-07-05T13:35","msg":"feat: naval + air units — sailing crosses water, flying crosses all","body":"Adds a 'sailing' skill (naval units traverse water hexes that block land units)\nand two recruitable loadouts: Sea Ship (grants sailing) and Airship (grants the\nexisting flying skill, which crosses any terrain). Both appear in the plaza like\nother archetypes. Sea Ship sprite wired (downscaled to 512x512); airship art pending.\n\nAlso hardens get_effective_stats: a unit whose type_id is a loadout id (not a\nregistered unit type) falls back to the base pawn type instead of raising.\n\nTests: test_naval_air.py (skills granted, water/mountain traversal, boat sails).\nSuite: 480 passed; tsc + vite build clean.\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["6389afeb09c49029cd9e8d636a6ae32e478e50d8"],"add":136,"del":2,"cadd":70,"cdel":2,"files":10},{"repo":"mesnada","hash":"22d967f1eae1a57ab0424f701584e65d96fcc894","ts":1783273466,"wall":"2026-07-05T13:44","msg":"art: airship sprite (transparent, 512x512)","body":"Authored by Rowan Valle; Executed by Claude Code.","parents":["0e9994f91c16f73b8f611295b1b1c9ce45488bfb"],"add":1,"del":1,"cadd":1,"cdel":1,"files":2},{"repo":"mesnada","hash":"8419bf3d39f5f12818798c134d430cd43c9d289b","ts":1783273579,"wall":"2026-07-05T13:46","msg":"docs: session handoff — Chunks 1-7 + naval/air; Port/Airfield spec next","body":"Authored by Rowan Valle; Executed by Claude Code.","parents":["22d967f1eae1a57ab0424f701584e65d96fcc894"],"add":73,"del":83,"cadd":73,"cdel":83,"files":1},{"repo":"mesnada","hash":"73a6bf1c1c73f63154c2b6019c899c2d12237008","ts":1783284386,"wall":"2026-07-05T16:46","msg":"feat: data-driven settlement building system + 14 buildings (P1)","body":"BuildingDef becomes a data effect-bundle (population, occupancy, AP, fog,\nmorale, heal, fort-hp, rank-cap, unlocks_loadouts, build-gates, upgrades_to);\na Settlement resolver sums them, retiring the hardcoded def_id dispatch\n(Treasury still grants +50 AP, now from data). construct gains\ntier/prerequisite/terrain gating, in-place upgrades, and wall-hp that coexists\nwith the fortify ability. The recruit roster gates any loadout named by a\nbuilding's unlocks_loadouts. Adds 14 buildings behind the existing four: Homes,\nWell/Aqueduct, Shrine/Temple/Cathedral, Palisade/Walls/Citadel, Watchtower,\nSchool/University, Healer's House, Arena. 492 backend tests pass.","parents":["8bd3e8b19476084bd56222d040f88e83acdfd662"],"add":638,"del":34,"cadd":479,"cdel":33,"files":24},{"repo":"mesnada","hash":"8bd3e8b19476084bd56222d040f88e83acdfd662","ts":1783284386,"wall":"2026-07-05T16:46","msg":"docs: settlement building-system prior-art research + naming ballot","body":"Four-family game-design survey (tactical+settlement hybrids, production chains,\npops & needs, district/adjacency) synthesized into a Mesnada design direction.\nNaming layer ratified by operator ballot. Ingested into unicursal RAG.","parents":["8419bf3d39f5f12818798c134d430cd43c9d289b"],"add":443,"del":0,"cadd":443,"cdel":0,"files":1},{"repo":"mesnada","hash":"4aedad83e2e43ee948bf51db63dcb1a1d90cf584","ts":1783284837,"wall":"2026-07-05T16:53","msg":"feat: Port and Airfield buildings — gate Sea Ship and Airship","body":"A Port (must be built beside water) unlocks the Sea Ship; an Airfield unlocks\nthe Airship. A building-unlocked archetype now bypasses the roster's item-cost\ncap, so the building is the real gate rather than the tier's budget — ships and\nairships are no longer the old Capital-only cost-cap loophole. 495 backend\ntests pass.","parents":["73a6bf1c1c73f63154c2b6019c899c2d12237008"],"add":79,"del":38,"cadd":58,"cdel":38,"files":5},{"repo":"mesnada","hash":"012d6f79eb44f1a3305edb745e1318f787f8876c","ts":1783297483,"wall":"2026-07-05T20:24","msg":"docs: pawn & command redesign, UI/UX backlog, project CLAUDE.md","body":"- mesnada-pawn-command-model.md: two-axis redesign (competence = 9 stats +\n  0-100 skills; command = rank as echelon span), faction leadership office,\n  mesnada retinue, decapitation/succession, government-forms seam. Chunked A-H.\n- mesnada-chunk-a-stat-block.md: approved plan for the data-first stat block.\n- mesnada-ui-ux-backlog.md: 6-phase remediation plan from the frontend audit.\n- CLAUDE.md: new project-context doc (repo had none).\n- master-roadmap: added the redesign arc; marked skill-learning and commander\n  designation open decisions resolved.\n- handoff: fixed stale header; recorded the redesign + Chunk A; M-5 superseded.","parents":["4aedad83e2e43ee948bf51db63dcb1a1d90cf584"],"add":569,"del":5,"cadd":569,"cdel":5,"files":6},{"repo":"mesnada","hash":"6b037184d07fdeecd295be140088b59d90745d90","ts":1783297493,"wall":"2026-07-05T20:24","msg":"fix(ui): Phase 1 UI/UX feedback & safety","body":"Root-cause feedback fixes plus reliability crashes from the frontend audit\n(.claude/plans/mesnada-ui-ux-backlog.md, Phase 1).\n\n- R1 error visibility: global error toast rendered above every overlay with a\n  dismiss button and auto-expire; friendly mapping for network/5xx; surfaced in\n  GameSetup (silent New-Game failure) and on catalog-load failure. Removed the\n  HUD error that hid behind the fullscreen settlement modal.\n- R2 loading + no double-submit: pending flag with a re-entrancy guard around\n  every server round-trip (doAction, startNewGame); working indicators in the\n  HUD, a global pill, and the Start button; action buttons disable while pending.\n- M-8: clamp selectedUnitIndex in the shop UPDATE_STATE branch so AI kills\n  mid-turn cannot leave it past a shrunk stack.\n- M-9: guarded playerColor/playerColorNum helpers; replaced every unguarded\n  PLAYER_COLORS lookup so a neutral/out-of-range player id no longer blanks the\n  board (found an extra crash site the audit missed at hexRenderer selection).\n- M-11: cancel the event-animation timer on cleanup and guard animation\n  callbacks against destroyed containers.\n- M-12: guard async Pixi init against unmount; defer app.destroy until init\n  settles (Pixi v8 throws on mid-init destroy).\n\nVerified: tsc --noEmit and vite build both clean.","parents":["012d6f79eb44f1a3305edb745e1318f787f8876c"],"add":200,"del":40,"cadd":200,"cdel":40,"files":11},{"repo":"mesnada","hash":"35ef25052bed3a7b353502f94c9d158c61ef1584","ts":1783300476,"wall":"2026-07-05T21:14","msg":"feat(ui): Phase 2+3 — gameplay legibility + wire additions","body":"UI/UX backlog Phases 2 and 3 (.claude/plans/mesnada-ui-ux-backlog.md). The core\nloop is now legible: you can see where a unit moves and what it can hit, the\ncombat preview says who's fighting and whether the blow lands, and draws end\ncleanly.\n\nPhase 2 — backend serialization (additive, no behavior change):\n- Expose per-unit effective `range` in _unit_to_dict (reusing the existing\n  get_effective_stats call) and on mounted units.\n- Expose `is_draw` alongside the already-shipped `game_over`.\n- Mirror on the client GameState/UnitData types. Test: test_serialization.py.\n\nPhase 3a — move & attack highlighting:\n- New read-only POST /api/game/{id}/reachable + selection_info() helper\n  (actions/query.py): reachable move hexes (with AP cost) via reachable_costs,\n  filtered by AP/fatigue/legal-destination; attackable enemy hexes by range +\n  LOS, excluding hidden enemies. Tests: test_query.py (incl. forest-LOS).\n- Client fetches it on selecting a friendly unit (stale-guarded), threaded to the\n  board; hexRenderer tints reachable hexes cyan and rings attackable enemies red.\n- HexTooltip shows a matching move/attack hint (the discoverability fix).\n\nPhase 3b — combat preview rework:\n- Extract resolveUnitName + gear-name map to lib/units.ts (shared).\n- CombatPreview shows attacker/defender names, a Guaranteed-kill / May-kill flag\n  (and a counter-death warning), and the attack AP cost (added to /preview).\n\nPhase 3c — draw game-over UI:\n- GameOverOverlay gains a draw (\"Stalemate\") variant; the overlay now gates on\n  game_over, and the stale !winner action guards (HUD, context menu, tooltip)\n  move to !game_over so a draw disables play.\n\nVerified: backend 502 pass / 3 skip; frontend tsc --noEmit and vite build clean.","parents":["6b037184d07fdeecd295be140088b59d90745d90"],"add":438,"del":62,"cadd":438,"cdel":62,"files":19},{"repo":"mesnada","hash":"31f2a19a8a3477d79140dbbaea34ad582801c105","ts":1783302876,"wall":"2026-07-05T21:54","msg":"feat: vehicles as boardable transport units","body":"Airships and sea ships become transport units that land units board, instead of\nsolo movement items. Design: .claude/plans/mesnada-vehicles-transport.md.\n\n- Unit gains `capacity` + `passengers`; vehicle loadouts carry capacity (airship\n  3, sea ship 6), set at create_unit and roster recruitment. Passengers live on\n  the vehicle Unit, so they ride along whenever it moves — no movement changes.\n- actions/transport.py: board_vehicle (one adjacent friendly land unit at a time,\n  free slot, AP), disembark_vehicle (drop the last passenger to an adjacent hex),\n  release_passengers (on destruction each passenger has a 15% survival roll,\n  ejected like release_mount, else lost). Wired into both combat death paths.\n- New board/disembark action types; BOARD/DISEMBARK events + visibility keys;\n  capacity + passenger roster serialized to the client.\n- Frontend: capacity/passengers on UnitData, an \"anchor N/M\" passenger badge on\n  vehicles, Board/Disembark verbs in the context menu, and event-log text.\n\nRecruitment gating was already enforced (the settlement-building unlocks_loadouts\nseam: Port unlocks sea_ship, Airfield unlocks airship) — locked with a new\nregression test.\n\nStat-coupling note: combat stats come from rank+gear, so vehicles keep their hull\nitem as the internal stat source until the Chunk B stat redesign; they are\nrecruit-only (cost far above the bodega cap) and location-gated to Ports/Airfields.\n\nTests: test_transport.py, test_vehicle_recruitment.py. Backend 510 pass / 3 skip;\nfrontend tsc + vite build clean.","parents":["35ef25052bed3a7b353502f94c9d158c61ef1584"],"add":482,"del":3,"cadd":478,"cdel":1,"files":23},{"repo":"mesnada","hash":"2ae59647e6b2b3a162f99d82b660cc7261cf57a6","ts":1783302957,"wall":"2026-07-05T21:55","msg":"docs: refresh handoff — UI/UX phases 1-3 + vehicle transport shipped","body":"","parents":["31f2a19a8a3477d79140dbbaea34ad582801c105"],"add":18,"del":9,"cadd":18,"cdel":9,"files":1},{"repo":"mesnada","hash":"1fbc942752339c1143b67510a868a96140f35315","ts":1783304561,"wall":"2026-07-05T22:22","msg":"feat: scouts can auto-explore","body":"A scout-only autonomous stance mirroring the auto-gather worker: an exploring\nscout walks toward unexplored terrain on its own each turn, revealing fog.\n\n- Unit gains `exploring`; set_exploring action gated to units with the `scout`\n  skill and mutually exclusive with auto-gather.\n- turn._process_scouts (run in end_turn beside _process_workers): each exploring\n  scout walks its full movement budget one hex at a time toward the nearest\n  unrevealed hex, revealing fog after each step so the frontier recedes. Uses the\n  scout's own movement (no AP) and reuses _worker_step_toward, so it never walks\n  into enemies; idles once the map is fully explored.\n- New set_exploring action type; `exploring` serialized.\n- Frontend: exploring on UnitData, a 🧭 Auto-explore / Stop-exploring context-menu\n  toggle (scout-skilled units only), and a 🧭 badge on exploring scouts.\n\nTests: test_explore.py (scout-gating, disable, walk-and-reveal). Backend 513 pass\n/ 3 skip; frontend tsc + vite build clean.","parents":["2ae59647e6b2b3a162f99d82b660cc7261cf57a6"],"add":175,"del":2,"cadd":175,"cdel":2,"files":12},{"repo":"mesnada","hash":"b1caa7df519b9d993bd13ca44447ae4bf46131a1","ts":1783304612,"wall":"2026-07-05T22:23","msg":"docs: handoff — scouts auto-explore shipped","body":"","parents":["1fbc942752339c1143b67510a868a96140f35315"],"add":2,"del":1,"cadd":2,"cdel":1,"files":1},{"repo":"eureka-co-nevada","hash":"e277026aaa4452abbce634ccf6bc0a50ad37baf7","ts":1783345635,"wall":"2026-07-06T09:47","msg":"docs: lock the card model — four dossier decisions resolved","body":"Chunk 2 card questions answered by the operator (2026-07-06): one uniform\nsummoned card per atom; all parameters sectioned in one card; notes as\npersisted CoT remarks; card replaces the inspector. Cards live in\nsheet/dock via panelHost with a back-stack; the tray dies. Execution:\nrevert 817f4a6, rebuild as Chunk 2' on the ownership slice, test-first.\n\nChunk plan renamed to ~/.claude/plans/eureka-cop-atom-card-arc.md and\nupdated to match.","parents":["47272536f1b84aae896ff45a828a1a6ea4b02732"],"add":15,"del":15,"cadd":15,"cdel":15,"files":1},{"repo":"eureka-co-nevada","hash":"72125a8f5a7463e82c27a3d340067a64fcc04695","ts":1783346339,"wall":"2026-07-06T09:58","msg":"Revert \"feat(map): Chunk 2 — cards in a tray (ownership slice)\"","body":"This reverts commit 817f4a6bb1dd374d9d77ec72b1e4143cfff946a6.","parents":["e277026aaa4452abbce634ccf6bc0a50ad37baf7"],"add":3,"del":285,"cadd":3,"cdel":285,"files":7},{"repo":"operations","hash":"e9562c854a993b44e01473016c17fb993dc09907","ts":1783447661,"wall":"2026-07-07T14:07","msg":"docs: MTGC Mission Control dashboard build plan (approved)","body":"","parents":["625834a0333c2d9d9a2fc405639b3305ef738c4b"],"add":201,"del":0,"cadd":201,"cdel":0,"files":1},{"repo":"major-tims-ground-control","hash":"8a42723e9dfefe9de47be8a238258be65217499e","ts":1783447854,"wall":"2026-07-07T14:10","msg":"feat: D1 database (ground-control-db) + wrangler.toml with DB binding","body":"Mission Control chunk 1. Schema: leads (status pipeline + value_won_cents +\nemail_sent recovery flag) and spam_events (kind + timestamp only). Migrations\napplied local + remote. wrangler.toml becomes Pages config source of truth on\nnext deploy — secrets unaffected.","parents":["7f7ec311391069b676f7cb9a71d1a93c268e1d93"],"add":47,"del":0,"cadd":44,"cdel":0,"files":3},{"repo":"major-tims-ground-control","hash":"fc4bdabc9392c0a57daa8b86a1b9a73ba4bcdf9b","ts":1783448096,"wall":"2026-07-07T14:14","msg":"feat: dual-write leads to D1 + count blocked spam","body":"Mission Control chunk 2. recordLead/recordSpam are fire-and-forget via\nwaitUntil - the Resend email path is never blocked or slowed by D1. Leads\nare recorded on every real-lead exit (no key, send fail, success) with an\nemail_sent flag, so a Resend outage becomes recoverable instead of lossy.\nHoneypot and Turnstile blocks store kind + timestamp only, never content.\nVerified via wrangler pages dev: happy path + honeypot rows land, redirects\nunchanged.","parents":["8a42723e9dfefe9de47be8a238258be65217499e"],"add":54,"del":1,"cadd":54,"cdel":1,"files":1},{"repo":"major-tims-ground-control","hash":"ab53b8f560b62b4ca1c1c3b78c3180cd093af258","ts":1783448481,"wall":"2026-07-07T14:21","msg":"feat: Access JWT verification middleware for /api/dashboard/*","body":"Mission Control chunk 4. Defense in depth behind the edge Access gate:\nRS256 WebCrypto verification against the team JWKS (6h per-isolate cache,\nkid-miss refetch), aud/iss/exp/nbf claim checks with 60s leeway. Fails\nclosed - including when CF_ACCESS_* env is unset - except the dev-only\nDEV_BYPASS_ACCESS flag in .dev.vars. All dashboard responses no-store.\nZero dependencies. Verified: 401 with no token and garbage token when\nbypass off; handlers reachable with bypass on.","parents":["fc4bdabc9392c0a57daa8b86a1b9a73ba4bcdf9b"],"add":145,"del":0,"cadd":145,"cdel":0,"files":3},{"repo":"major-tims-ground-control","hash":"7ba6d393209739a1281206c6678215d54e60daec","ts":1783448495,"wall":"2026-07-07T14:21","msg":"feat: leads API - GET log + metrics, PATCH status/value","body":"Mission Control chunk 5. GET /api/dashboard/leads returns the lead log\n(newest first, limit<=500) plus headline metrics (total/new/won/$ won).\nPATCH /api/dashboard/leads/:id advances status through the pipeline and\nsets value_won_cents; leaving 'won' clears the value so the money metric\nonly counts actual wins. Validated enum + integer-cents inputs; 400/404/405\nerror contract. Verified via curl against local D1.","parents":["ab53b8f560b62b4ca1c1c3b78c3180cd093af258"],"add":171,"del":0,"cadd":171,"cdel":0,"files":2},{"repo":"major-tims-ground-control","hash":"c4576ad6b6837dd4c0f5545b309d7eafbc528b7f","ts":1783448504,"wall":"2026-07-07T14:21","msg":"feat: spam shield API - blocked-attempt counters","body":"Mission Control chunk 6. GET /api/dashboard/spam returns total blocked,\nlast-30-days, and the honeypot/turnstile split from spam_events. Verified\ncounts against seeded local events.","parents":["7ba6d393209739a1281206c6678215d54e60daec"],"add":39,"del":0,"cadd":39,"cdel":0,"files":1},{"repo":"major-tims-ground-control","hash":"54a38028e16572b06ca7373645b9bf83b68dcdc0","ts":1783448980,"wall":"2026-07-07T14:29","msg":"feat: Mission Control dashboard - shell, leads panel, spam shield","body":"Mission Control chunk 7. Self-contained /mission-control page (no marketing\nlayout), dark console aesthetic on the brand greens, GROUND CONTROL TO MAJOR\nTIM. Status strip aggregates per-panel health (nominal/partial/offline) and\nmaps auth failures to a reload prompt. Leads panel: headline metrics\n(total/won/$ won), tap-to-cycle status pills with optimistic UI + revert on\nerror, dollars-won input on won leads, tel:/mailto: links, email-delivery\nfailure flag. All user-submitted content rendered via textContent - never\ninnerHTML. Spam shield panel with 30-day + kind split. Excluded from sitemap;\nnoindex,nofollow; robots.txt deliberately untouched.\n\nVerified: astro check 0/0/0, 13 pages built, headless-browser render against\nlocal D1 shows populated panels and persisted status changes.","parents":["c4576ad6b6837dd4c0f5545b309d7eafbc528b7f"],"add":422,"del":1,"cadd":8,"cdel":1,"files":2},{"repo":"major-tims-ground-control","hash":"49fbb644657fa7a472a3fab90cdf95896470a67c","ts":1783449159,"wall":"2026-07-07T14:32","msg":"feat: Launch Conditions panel - NWS forecast + mowing verdicts","body":"Mission Control chunk 9. weather.js chains api.weather.gov points->forecast\nfor the Talbott base (grid MRX/88,62), required User-Agent, null precip\ntreated as 0. Mowing heuristic: >=60% rain or >20mph wind = NO-GO; >=40% /\n>15mph / <=40F = MARGINAL; day after >=70% rain capped at MARGINAL. Edge\nCache API: 30min fresh + 24h stale fallback so an NWS outage serves the\nlast forecast instead of an empty panel. Coordinates added to business.ts\nbaseLocation (duplicated in the Function by design - never client-supplied).\n\nVerified: real NWS data end-to-end, headless render shows five day rows\nwith correct verdict chips, astro check 0/0/0.","parents":["54a38028e16572b06ca7373645b9bf83b68dcdc0"],"add":224,"del":2,"cadd":140,"cdel":2,"files":3},{"repo":"major-tims-ground-control","hash":"d4ec71b4087e4ff67d96e2fe745203dcc4cb1456","ts":1783449379,"wall":"2026-07-07T14:36","msg":"feat: traffic panel - Cloudflare GraphQL analytics telemetry","body":"Mission Control chunk 8. traffic.js queries httpRequests1dGroups (30-day\ndaily sparkline, authoritative) + httpRequestsAdaptiveGroups (top pages and\nreferrers; sampled trends). Free-plan adaptive retention is undocumented, so\nthe window is discovered from the settings node at runtime and clamped.\nQueries built from server-derived values only; asset/internal paths filtered;\nreferrers reduced to hostnames minus self. 10-min edge cache. Degraded\ncontract: missing CF_ANALYTICS_TOKEN/CF_ZONE_TAG or upstream failure returns\ndegraded:true - the panel dims to offline copy and the strip drops to\nPARTIAL TELEMETRY, never a broken page.\n\nVerified: degraded path end-to-end in headless render (amber strip, offline\npanel, other panels unaffected). Live-data verification pending the scoped\nZone Analytics:Read token (operator step).","parents":["49fbb644657fa7a472a3fab90cdf95896470a67c"],"add":334,"del":0,"cadd":196,"cdel":0,"files":2},{"repo":"major-tims-ground-control","hash":"d3b8011c73e49a293d405c599224339bb05da24e","ts":1783449499,"wall":"2026-07-07T14:38","msg":"docs: privacy policy - disclose D1 storage, retention, deletion","body":"Mission Control chunk 10. Cloudflare D1 added to services; retention section\nnow covers database storage with delete-on-request; spam blocks disclosed as\nkind + timestamp only. Keeps the policy truthful now that leads persist in D1.","parents":["d4ec71b4087e4ff67d96e2fe745203dcc4cb1456"],"add":22,"del":3,"cadd":0,"cdel":0,"files":1},{"repo":"operations","hash":"31266bfccb92e10f3e90942bfca9da0bcedac71a","ts":1783449626,"wall":"2026-07-07T14:40","msg":"docs: MTGC Mission Control - Tim's guide + handoff refresh","body":"Dashboard built through chunk 10 (9 commits on MTGC master, local).\nHandoff now carries the commit table, verification state, and the\nblocked-on-operator rollout list (Zero Trust setup, secrets, deploy\ncheckpoints A-D). Guide is forwardable to Tim after checkpoint C.","parents":["e9562c854a993b44e01473016c17fb993dc09907"],"add":100,"del":4,"cadd":100,"cdel":4,"files":2},{"repo":"operations","hash":"a2fd1bc46a4860b18e692bd714a4ea3029f32fc2","ts":1783450692,"wall":"2026-07-07T14:58","msg":"docs: MTGC Mission Control v2 plan - research findings + execution chunks","body":"Operator redirect: pipeline dead; v2 = traffic + R2 media uplink + weather +\nread-only leads + Tim-editable copy via root-middleware HTMLRewriter. All\nload-bearing mechanisms verified against live CF docs (root middleware fronts\nstatic assets, _routes.json invocation scoping, setInnerContent escapes by\ndefault, 100MB body / 10ms-CPU-excl-IO free limits, R2 stream-length gotcha).\nKey catch: transformed HTML must drop ETag or browsers 304 back to stale copy.","parents":["31266bfccb92e10f3e90942bfca9da0bcedac71a"],"add":165,"del":0,"cadd":165,"cdel":0,"files":1},{"repo":"major-tims-ground-control","hash":"09a2b2b60953aeebd6281c11843f3173664e46ab","ts":1783451508,"wall":"2026-07-07T15:11","msg":"refactor: v2 dashboard - traffic first, read-only leads, drop pipeline + spam panel","body":"Mission Control V2.1 (operator redirect: attribution pipeline killed).\nTraffic panel takes the top slot; leads become a read-only log (cards with\ntap-to-call, delivery-failure flag, count in the header) - status pills,\ndollar tracking, and metrics removed along with the PATCH endpoint; spam\npanel + endpoint removed (quote.js keeps counting; data accrues for later).\nVerified: astro check 0/0/0, headless render, deleted endpoints 404/405.","parents":["d3b8011c73e49a293d405c599224339bb05da24e"],"add":28,"del":367,"cadd":5,"cdel":159,"files":4},{"repo":"major-tims-ground-control","hash":"a52092f6af52ff66a0dc7d59dea1d2ff56fdf558","ts":1783452482,"wall":"2026-07-07T15:28","msg":"feat: photo uplink - R2 media transmit from Mission Control","body":"Mission Control V2.2. TRANSMIT PHOTOS panel on the dashboard: multi-select\nfrom camera roll or desktop, per-file progress, optional note, client-side\n400px JPEG thumbnails (originals stored untouched), recent-uploads strip.\nPOST /api/dashboard/media stores to R2 (sanitized keys uploads/YYYY-MM/...,\nnote as customMetadata, batch-end email ping to the operator via Resend);\nGET lists newest-first; file endpoint serves objects with traversal guards.\nAll behind the existing Access+JWT gate.\n\nR2 must be enabled on the account (one-time dashboard action) + bucket\ncreated before the first deploy with this binding - local dev simulates it.\n\nVerified: upload round-trip via curl (store, list w/ note, thumb 200 valid\nJPEG), traversal probes rejected, astro check 0/0/0, headless renders.","parents":["09a2b2b60953aeebd6281c11843f3173664e46ab"],"add":348,"del":0,"cadd":174,"cdel":0,"files":4},{"repo":"mesnada","hash":"a35d235bde870b94958079ce9ff530570b47bdc6","ts":1783453532,"wall":"2026-07-07T15:45","msg":"docs: master plan — single ordered roadmap; handoff/roadmap pointers","body":"","parents":["b1caa7df519b9d993bd13ca44447ae4bf46131a1"],"add":108,"del":2,"cadd":108,"cdel":2,"files":3},{"repo":"mesnada","hash":"bd1dad9fb0697a2927c40a693353b741bc781084","ts":1783453662,"wall":"2026-07-07T15:47","msg":"docs: handoff — M0 merge to main complete, approved order queued","body":"","parents":["a35d235bde870b94958079ce9ff530570b47bdc6"],"add":5,"del":3,"cadd":5,"cdel":3,"files":1},{"repo":"major-tims-ground-control","hash":"f8adcab0752b21110c0c2c88096ff8459edcdd9c","ts":1783453692,"wall":"2026-07-07T15:48","msg":"feat: Tim-editable site copy - registry, edge rewrite, EDIT SITE COPY panel","body":"Mission Control V2.3. Seventeen text regions become editable from the\ndashboard, self-service with no rebuild or deploy:\n\n- Registry (functions/_lib/editable-copy.js) is the single source of truth:\n  templates render its originals inside data-edit-attributed elements\n  (src/data/editable-copy.ts re-exports for Astro), the copy API uses it as\n  the allowlist, the middleware only rewrites its keys. Service card\n  summaries moved from collection frontmatter into the registry (schema\n  field dropped) so cards on home, /services, and service-area pages all\n  rewrite from one key.\n- Root functions/_middleware.js rewrites successful HTML GETs via streaming\n  HTMLRewriter; setInnerContent escapes by default so edits can change words\n  but never inject markup; try/catch falls back to the untouched response.\n  Overrides come from D1 copy_overrides (migration 0002, applied local +\n  remote) with a 60s per-isolate memo (COPY_MEMO_TTL_S=0 in .dev.vars).\n- Cache correctness: rewritten HTML drops ETag/Last-Modified and goes\n  no-cache, AND incoming If-None-Match/If-Modified-Since are stripped before\n  the asset layer - otherwise revalidating browsers get 304 and keep stale\n  pre-edit copy forever. Both directions verified.\n- public/_routes.json keeps Functions off real static assets (explicit root\n  filenames - extension wildcards would have swallowed /api/ media URLs).\n- /api/dashboard/copy GET/PUT/DELETE with allowlist + 2000-char validation;\n  EDIT SITE COPY panel with per-region textarea, dirty-tracked Save,\n  confirm-guarded Reset, ORIGINAL/EDITED state chips.\n\nVerified end-to-end locally (memo TTL 0): override PUT rewrites BOTH render\nsites of the shared about-intro key; DELETE restores originals; asset ETags\nuntouched; quote form 302 unaffected; unknown-key and oversize PUTs 400;\nastro check 0/0/0; headless render of the full board.","parents":["a52092f6af52ff66a0dc7d59dea1d2ff56fdf558"],"add":515,"del":61,"cadd":320,"cdel":7,"files":20},{"repo":"operations","hash":"37ffa70fd227e1cc07abda9d1a993f3b759eb647","ts":1783453823,"wall":"2026-07-07T15:50","msg":"docs: MTGC Mission Control v2 - guide rewrite, handoff refresh, plan executed","body":"V2.4. Tim's guide now covers the photo uplink and copy editing (pipeline\nsections dropped). Handoff carries the full v2 commit table, the cache-trap\nand _routes.json lessons, and the ordered blocked-on-operator list (Zero\nTrust, R2 enablement, secrets, checkpoints A-D). v2 plan status -> executed.\nAll three re-ingested into unicursal RAG.","parents":["a2fd1bc46a4860b18e692bd714a4ea3029f32fc2"],"add":53,"del":52,"cadd":53,"cdel":52,"files":3},{"repo":"mesnada","hash":"383358f1db6ec4dad9a556414df67eccb34d0d52","ts":1783455293,"wall":"2026-07-07T16:14","msg":"feat: seed one rng on GameState — reproducible games","body":"GameState carries state.rng (seeded) + state.seed (recorded). create_new_game\ngenerates and records a seed when none is given; POST /api/game/new accepts an\noptional seed. All in-game randomness now defaults to state.rng: dice, combat\nresolution, morale rout/rally, fatigue burnout, vehicle-passenger survival,\nAI turns, settlement inventory refresh and construct opening stock. Same seed\n= same world, same rolls. Seed/rng never serialized to clients (a known seed\nis a combat-variance oracle). Stateless helpers (resolve_combat, add_fatigue,\nroster generation) keep their explicit rng parameter; callers thread state.rng.\n\nChunk A plan amended: stat variance draws from state.rng, not a local\nunseeded Random.\n\nTests: tests/test_rng_determinism.py (8) — world/dice determinism, seed\nrecording, wire-shape non-leak. 521 pass / 3 skip.","parents":["bd1dad9fb0697a2927c40a693353b741bc781084"],"add":124,"del":17,"cadd":124,"cdel":17,"files":15},{"repo":"major-tims-ground-control","hash":"1f698f49811c68a99aa60dda58b04484c036737e","ts":1783546736,"wall":"2026-07-08T17:38","msg":"feat: Tim's portrait on the About page","body":"Replace the About-page placeholder with Tim's headshot, served as\nresponsive WebP through astro:assets. The photo is already live in\nproduction on the custom domain; this commits its source.","parents":["f8adcab0752b21110c0c2c88096ff8459edcdd9c"],"add":9,"del":4,"cadd":0,"cdel":0,"files":2},{"repo":"major-tims-ground-control","hash":"3c6e910808cae1ca349cf14e998eb7cf59523a9d","ts":1783546736,"wall":"2026-07-08T17:38","msg":"refactor: descope Mission Control to traffic + leads + copy","body":"Strip the photo uplink and weather panels per operator direction —\nkeep site traffic, the read-only leads log, and the site-copy editor.\n\nRemoves the R2 MEDIA binding and its media Functions, so the deploy no\nlonger needs R2 enabled or a card on file. Deletes the weather API.\nThe only remaining gate to ship Mission Control is the Cloudflare\nAccess app.","parents":["1f698f49811c68a99aa60dda58b04484c036737e"],"add":6,"del":567,"cadd":0,"cdel":304,"files":5},{"repo":"operations","hash":"b4ad28c5956fb08c02b7a9e751a825ebc71d5ea7","ts":1783547255,"wall":"2026-07-08T17:47","msg":"docs: MTGC Mission Control descope — 3 panels, R2 removed","body":"Reconcile the client docs with the 2026-07-08 descope: the dashboard is\nnow traffic + read-only leads + Tim-editable copy. Photos, weather, and\nthe R2 MEDIA binding were cut, so the deploy no longer needs R2 or a\ncard on file.\n\n- handoff.md: rewrite the Mission Control section; only gate left is the\n  Cloudflare Access app; note Tim's portrait is live.\n- tim-mission-control-guide.md: drop the photo-uplink and weather panels\n  (\"send photos — just text me\"); keep traffic, leads, copy.\n- mission-control-v2-plan.md: banner it as descoped; the editable-copy\n  research stands, the media/weather chunks are historical.","parents":["37ffa70fd227e1cc07abda9d1a993f3b759eb647"],"add":68,"del":40,"cadd":68,"cdel":40,"files":3},{"repo":"major-tims-ground-control","hash":"1c36a2a947ea0ce0cd605229998aeed9134152a0","ts":1783548679,"wall":"2026-07-08T18:11","msg":"feat: password gate for Mission Control (replaces Cloudflare Access)","body":"Card-free auth: a branded login page + HMAC-signed session cookie gate the\ndashboard page and /api/dashboard/* APIs, replacing the Cloudflare Access JWT\nmachinery (no Zero Trust, no card on file).\n\n- _lib/session.js: HMAC-SHA256 signed token mint/verify, cookie helpers, and a\n  constant-time password compare. WebCrypto only, fail closed.\n- mission-control/login.js: branded login form; constant-time password check\n  against MC_PASSWORD, then a 30-day signed session cookie and redirect.\n- api/dashboard/_middleware.js: verify the session cookie (was Access JWT).\n- root _middleware.js: redirect /mission-control to the login page when there\n  is no valid session cookie.\n- delete _lib/access.js; .dev.vars swapped to MC_PASSWORD / MC_SESSION_SECRET.\n\nVerified: 23-case session unit test; full curl flow (unauth 302 to login,\nwrong password 401, correct password sets cookie, API 401 without and 200 with\nthe cookie, dashboard gated).","parents":["3c6e910808cae1ca349cf14e998eb7cf59523a9d"],"add":253,"del":130,"cadd":253,"cdel":130,"files":5},{"repo":"operations","hash":"80f51cf8b54e8543ab601b4d08e35ea3e342d3f1","ts":1783549190,"wall":"2026-07-08T18:19","msg":"docs: MTGC Mission Control — password gate replaces Cloudflare Access","body":"Reconcile the client docs with the card-free password gate (commit\n1c36a2a in the site repo): a branded login page + HMAC-signed session\ncookie, no Cloudflare Access, no Zero Trust, no card.\n\n- handoff.md: rewrite the Mission Control section for the password gate;\n  commit table through 1c36a2a; \"left to ship\" is now just two secrets\n  (MC_PASSWORD, MC_SESSION_SECRET) plus the deploy.\n- tim-mission-control-guide.md: sign-in is now \"type the password I gave\n  you\" instead of an emailed code.\n- mission-control-v2-plan.md: banner notes the auth swap.","parents":["b4ad28c5956fb08c02b7a9e751a825ebc71d5ea7"],"add":64,"del":57,"cadd":64,"cdel":57,"files":3},{"repo":"major-tims-ground-control","hash":"e4cf90b097b3fdb133f4ca74089a32e2ba91076e","ts":1783550522,"wall":"2026-07-08T18:42","msg":"feat: magic-link entry for Mission Control (replaces password login)","body":"Access is now a signed link Rowan texts Tim — no password to choose,\nremember, or transmit. Tapping the link exchanges a long-lived token for\na 30-day session cookie; everything is our own HMAC (MC_SESSION_SECRET),\nno Cloudflare Access, no card.\n\n- mission-control/enter.js: verify the ?t=<token> magic link, mint a\n  30-day session cookie, redirect to the dashboard; branded \"link\n  expired\" notice on failure.\n- _lib/mc-notice.js: shared branded gate pages (\"use your link\" wall +\n  expired-link notice), inline CSS, no user input reflected.\n- root _middleware.js: unauthenticated /mission-control now shows the\n  \"use your link\" wall instead of a password form.\n- scripts/make-magic-link.mjs: operator's local link generator (signs\n  with MC_SESSION_SECRET, prints the URL).\n- _lib/session.js: drop the now-unused constant-time password compare.\n- delete mission-control/login.js; .dev.vars drops MC_PASSWORD.\n- mission-control.astro: session-expired copy points at the link.\n\nVerified: 20-case session unit test; full curl flow (no cookie 403 wall,\nmagic link sets cookie and 302s to dashboard, bad token 403 expired, API\n401 without / 200 with cookie, old /login 404).","parents":["1c36a2a947ea0ce0cd605229998aeed9134152a0"],"add":163,"del":144,"cadd":162,"cdel":143,"files":7},{"repo":"major-tims-ground-control","hash":"b365de931ca6f65b8d3e6887daa7ce757c40521f","ts":1783552945,"wall":"2026-07-08T19:22","msg":"chore: pin LEAD_FROM/LEAD_TO in wrangler.toml for the Pages deploy","body":"The first wrangler.toml deploy becomes the source of truth for plaintext\nenv vars and drops any not listed on the project — which would have\nbroken the live quote form (it reads LEAD_FROM/LEAD_TO). Pin the sender\nand recipient so they survive the takeover. Verified against the deployed\nproject: both present with correct values. Live as production deploy\n2b2a3734 (branch master).","parents":["e4cf90b097b3fdb133f4ca74089a32e2ba91076e"],"add":12,"del":4,"cadd":12,"cdel":4,"files":1},{"repo":"operations","hash":"447583b5930355a31f66c3d01b9ee636bde0d982","ts":1783553249,"wall":"2026-07-08T19:27","msg":"docs: MTGC Mission Control LIVE — magic-link gate deployed","body":"Mission Control deployed 2026-07-08 (Cloudflare Pages 2b2a3734, branch\nmaster) behind the card-free magic-link gate; MTGC repo pushed to Forgejo\nthrough b365de9. Quote form verified intact (LEAD_FROM/LEAD_TO survived\nthe wrangler.toml takeover).\n\n- handoff.md: status → LIVE IN PRODUCTION; \"left to ship\" → \"shipped\"\n  with live smoke results; only remaining is texting Tim his link.\n- tim-mission-control-guide.md + mission-control-v2-plan.md: magic-link\n  wording (folded in from the pre-deploy refresh).","parents":["80f51cf8b54e8543ab601b4d08e35ea3e342d3f1"],"add":57,"del":50,"cadd":57,"cdel":50,"files":3},{"repo":"major-tims-ground-control","hash":"f75de5b4a04dc150cfee6cde5319288c1795e15a","ts":1783554026,"wall":"2026-07-08T19:40","msg":"chore: pin CF_ZONE_TAG for the traffic panel","body":"Zone id for majortimsgroundcontrol.com, read by the Mission Control\ntraffic Function alongside the CF_ANALYTICS_TOKEN secret for its GraphQL\nAnalytics query. Not secret — lives in [vars].","parents":["b365de931ca6f65b8d3e6887daa7ce757c40521f"],"add":3,"del":0,"cadd":3,"cdel":0,"files":1},{"repo":"major-tims-ground-control","hash":"9f5508f2838d77e6e915115d3f242c76a957de42","ts":1783554510,"wall":"2026-07-08T19:48","msg":"fix: clamp traffic panel's adaptive query to the free-plan 1-day cap","body":"httpRequestsAdaptiveGroups rejects any single query spanning more than\n1 day on the free plan (a limit separate from retention). The panel asked\nfor a 7-day window for top pages/referrers, so that query errored and the\nwhole panel fell back to \"offline\". Clamp the adaptive window to just under\n24h; the 30-day sparkline (httpRequests1dGroups) has no span cap and is\nunaffected.\n\nConfirmed against the live zone: the 7d query errors (\"time range wider\nthan 1d\"), the 23h query returns rows.","parents":["f75de5b4a04dc150cfee6cde5319288c1795e15a"],"add":10,"del":4,"cadd":10,"cdel":4,"files":1},{"repo":"operations","hash":"38dbed09ffb24186d3e4b69f1cd2f7fdb636338e","ts":1783554802,"wall":"2026-07-08T19:53","msg":"docs: MTGC handoff — analytics live + traffic 1-day-cap fix","body":"Final rollout state: CF_ANALYTICS_TOKEN + CF_ZONE_TAG set, traffic panel\nconfigured; the free-plan httpRequestsAdaptiveGroups 1-day query-span cap\nthat dimmed the panel to \"offline\" is fixed (site-repo commit 9f5508f).\nLatest production deploy 6e9f7f0a; MTGC pushed to Forgejo through 9f5508f.","parents":["447583b5930355a31f66c3d01b9ee636bde0d982"],"add":21,"del":14,"cadd":21,"cdel":14,"files":1},{"repo":"major-tims-ground-control","hash":"4b3e2bfc11162bcf9147ae8d95bb17fa49c1f866","ts":1783555412,"wall":"2026-07-08T20:03","msg":"fix: traffic panel — drop referrers (free plan can't serve it), harden","body":"The adaptive dataset's clientRequestReferer field 403s on the free plan\n(\"zone does not have access to the field\"), which errored the whole query\nand dimmed the panel to offline. Fetch top pages only (clientRequestPath\nworks), and isolate BOTH best-effort queries — retention settings and top\npages — in their own try/catch, so only the authoritative daily dataset\n(httpRequests1dGroups, the sparkline/totals) failing can dim the panel.\nRemove the now-unused toHostname helper.\n\nFollow-up to 9f5508f (1-day span cap). Verified: daily + settings +\ntop-paths queries all return live data for the zone.","parents":["9f5508f2838d77e6e915115d3f242c76a957de42"],"add":49,"del":61,"cadd":49,"cdel":61,"files":1},{"repo":"major-tims-ground-control","hash":"aaef6515f3d016256c142a89fdbe78894c28ed22","ts":1783555906,"wall":"2026-07-08T20:11","msg":"refactor: remove referrers column from traffic panel","body":"The free plan can't serve referrer data (clientRequestReferer 403s), so\nthe \"Visitors came from\" column was permanently empty and misleading.\nRemove it from the panel (top pages goes full-width) and drop the now-dead\nreferrers field from the traffic payload.","parents":["4b3e2bfc11162bcf9147ae8d95bb17fa49c1f866"],"add":10,"del":30,"cadd":5,"cdel":8,"files":2},{"repo":"operations","hash":"d66fd3d2abba2a8fcf974a049455d60931140af2","ts":1783556125,"wall":"2026-07-08T20:15","msg":"docs: MTGC handoff — traffic referrers removed, panel final","body":"The free plan can't serve clientRequestReferer (authz 403), so the\nreferrers query was dropped and the \"Visitors came from\" column removed;\nthe traffic panel is now visitors + 30-day sparkline + top pages, hardened\nso only the authoritative daily dataset can dim it. Latest production\ndeploy 1b7539ce; MTGC pushed to Forgejo through aaef651.","parents":["38dbed09ffb24186d3e4b69f1cd2f7fdb636338e"],"add":20,"del":14,"cadd":20,"cdel":14,"files":1},{"repo":"operations","hash":"5a775353c8e8291b431491fa96d7d9e5b9fb62d4","ts":1783556345,"wall":"2026-07-08T20:19","msg":"docs: MTGC Mission Control rollout COMPLETE — Tim's link sent","body":"Tim's magic link was generated and sent 2026-07-08. Nothing outstanding;\nthe dashboard is live and delivered. Handoff \"Remaining\" cleared.","parents":["d66fd3d2abba2a8fcf974a049455d60931140af2"],"add":7,"del":7,"cadd":7,"cdel":7,"files":1},{"repo":"mesnada","hash":"efbf737799756c38d25b99ee1b6e547709bdfe26","ts":1783800832,"wall":"2026-07-11T16:13","msg":"feat: chunk A — innate 9-stat block on every unit (data-first)","body":"Foundation of the pawn & command redesign's competence axis. Each unit is now\nborn with a 9-stat block (strength, dexterity, speed, perception, endurance,\nintelligence, will, charisma, luck; 0-100, 50 = trained-adult baseline), rolled\nat birth from a per-archetype template (±10, clamped) via the seeded state.rng so\nrolls replay from the game seed. Deliberately zero behavior change: stats are\nstored and serialized to the client but consumed by no game logic yet — combat\nbegins reading stats x skills in chunk B.\n\n- StatBlock lives in units.py (not pawn.py as first planned) to avoid a circular\n  import, re-exported through pawn.py so loader import paths are unchanged.\n- create_unit gains an optional rng: rolled variance when given (live spawns pass\n  state.rng), deterministic template floor when omitted (test call sites), so the\n  never-null stats invariant holds everywhere.\n- roll_stats(loadout_id, rng); LoadoutPreset/loader carry the template; recruit,\n  starting pawns, and neutral garrisons all roll from their archetype.\n- Serialized in _unit_to_dict + the mounts block; mirrored on frontend UnitData.\n- 19 loadout templates authored; +9 tests (530 pass / 3 skip), tsc + build clean.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["383358f1db6ec4dad9a556414df67eccb34d0d52"],"add":446,"del":28,"cadd":212,"cdel":7,"files":28},{"repo":"mesnada","hash":"e72abc1a2aec790fd6c2e5fc6ed3bbee275e51ce","ts":1783807054,"wall":"2026-07-11T17:57","msg":"feat: chunk B1 — graded-skill data model (data-first, no behavior change)","body":"First half of the competence-axis rework. Skills stop being a binary list and\nbecome graded proficiencies, exposed but not yet consumed — the combat\nre-derivation and rank-scaling retirement land in B2.\n\n- Unit.skills: list[str] -> dict[str, int] (skill_id -> trained_points, 0-100).\n  Binary abilities and traversal tags ride along as presence keys, so every\n  `\"x\" in skills` membership check keeps working on dict keys unchanged.\n- SKILL_GOVERNING (the 12 skills -> 1-2 governing stats each) + aptitude factor\n  in config.py. effective_skill(stats, id, trained) = clamp(gov_avg*0.5 +\n  trained, 0, 100): a stat-derived aptitude floor plus an earned training delta.\n- EffectiveStats gains skill_levels: 12 effective proficiencies computed for\n  every unit (Pawn-safe). Serialized as skill_levels; mirrored on UnitData.\n- Absorbed old skills (ambush, sneak<-stealth, medicine<-heal, labour<-\n  gather_bonus) are graded; conditional abilities stay binary, per plan.\n\n538 pass / 3 skip (+8 new; all prior tests pass unchanged = no behavior change).\ntsc + build clean. Plan: .claude/plans/mesnada-chunk-b-graded-skills.md.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["efbf737799756c38d25b99ee1b6e547709bdfe26"],"add":201,"del":10,"cadd":201,"cdel":10,"files":12},{"repo":"mesnada","hash":"ef96b69a41019eb15ac3a765e093e4de00bf5284","ts":1783810265,"wall":"2026-07-11T18:51","msg":"feat: chunk B2 — combat derives from stats x skills; retire rank scaling","body":"The competence axis goes live. Combat power now comes from the stat block x\ngraded skills (+ gear), not rank. Verified in a live playtest before commit.\n\n- Derivation (get_effective_stats): melee attack from Smash/Blade, ranged from\n  Aim (new EffectiveStats.ranged_attack; combat picks by distance); defense from\n  Brace/Evade/Toughness; HP from Endurance; movement from Speed; carry from\n  Strength; vision from Perception. Gear bonuses scale x3 (GEAR_STAT_SCALE) so\n  equipment is a real pillar, not flavor.\n- Damage model: multiplicative mitigation, dmg = atk * C/(C+eff_def), replacing\n  subtractive atk - def. No armor walls; armor_pierce (halves eff_def in the\n  denominator) and fortification/terrain (multiply def) both keep working. Luck\n  tilts the damage variance center.\n- Retired: RANK_ATTACK/DEFENSE/MOVE_BONUS personal multipliers (rank contributes\n  nothing to combat now but a small institutional HP bump) and skill_cap. Max HP\n  derives at create/recruit from END + rank institutional.\n- Calibration (live engine, 400 seeds): recruit fight ~7 hits (was ~24), geared\n  knight -> pawn ~3, pawn -> armored knight ~21. Matches the approved harness.\n\nDeferred to follow-ups: Luck crit roll; vehicle hull-item divorce (must re-home\nflying/sailing + tags + movement, needs its own tuning under gear x3).\n\n547 pass / 3 skip (7 old-behavior tests rewritten; +9 B2 tests). tsc + build clean.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["e72abc1a2aec790fd6c2e5fc6ed3bbee275e51ce"],"add":351,"del":169,"cadd":271,"cdel":161,"files":15},{"repo":"mesnada","hash":"7c25154137131e2ffb3e9f36cf57b581e0854ca9","ts":1783812125,"wall":"2026-07-11T19:22","msg":"feat: luck crit — random critical hits scaled by the Luck stat","body":"First B follow-up. Each strike (and counter) rolls a critical hit whose chance\ncomes from the attacker's Luck: clamp(CRIT_CHANCE_BASE + (LCK-50)*LUCK_CRIT_PER_\nPOINT, 0, CRIT_CHANCE_MAX) -> 5% at LCK 50, up to 50%, floored at 0. A crit deals\nLUCK_CRIT_MULTIPLIER (1.5x) the rolled damage. Makes Luck matter offensively, not\njust as the variance tilt from B2.\n\n- combat.py: _luck_crit_chance(); crit rolled after damage in resolve_combat for\n  both the strike and the counter; CombatResult carries attacker_crit/defender_crit;\n  CombatPreview exposes attacker/defender crit_chance.\n- Surfaced: COMBAT event carries the crit flags; preview endpoint returns the\n  chances. Frontend shows \"✦ N% crit\" in the combat preview and \"✦CRIT\" in\n  the event log.\n\n553 pass / 3 skip (+6 crit tests: formula/clamp, higher-luck-crits-more, ~1.5x\ndamage, preview exposes chance). tsc + build clean.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["ef96b69a41019eb15ac3a765e093e4de00bf5284"],"add":139,"del":5,"cadd":139,"cdel":5,"files":9},{"repo":"mesnada","hash":"1077e8b8a03ccfb1128c9d6ecc91435f733d7953","ts":1783812926,"wall":"2026-07-11T19:35","msg":"refactor: divorce vehicles from the hull item — stat-block units","body":"Second B follow-up. Airships and sea-ships were pawns holding a magic \"hull item\"\nthat granted their combat stats, the flying/sailing skill, tags, and movement. With\nthe Chunk A stat block + B2 stat-derived combat, that item double-counted. Vehicles\nare now plain stat-block units, consistent with the one-model design.\n\n- Deleted data/items/{airship,sea_ship}.json (also stops a tier-5/6 bodega from\n  selling a hull item).\n- Loadouts: gear -> [] (no hull item); flying/sailing moved into loadout skills\n  (traversal read from stats.skills in movement/transport, unchanged). Dead\n  air/naval/vehicle tags dropped (no mechanic read them). Vehicle identity stays\n  capacity > 0.\n- Retuned stat templates to cover the lost item bonuses: HP up (higher END), armor\n  down (stat-derived defense caps at 30 — vehicles carry no gear def x3, so they're\n  tanky via HP, not plate). Attack and movement preserved.\n  airship 82->93 HP / def 32->25; sea_ship 87->97 HP / def 36->24.\n\n553 pass / 3 skip (no regressions; +1 divorce test). tsc + build clean.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["7c25154137131e2ffb3e9f36cf57b581e0854ca9"],"add":33,"del":54,"cadd":19,"cdel":2,"files":6},{"repo":"mesnada","hash":"586612c28cb836680956878c54409c677c30dc04","ts":1783813119,"wall":"2026-07-11T19:38","msg":"docs: session handoff — M1 (pawn foundation) complete","body":"Handoff for the stats x skills combat rework: Chunk A (stat block), B1 (graded\nskills), B2 (combat re-derivation + rank retirement), plus Luck crit and the\nvehicle hull-item divorce. 553 pass / 3 skip. Master-plan status line updated;\nM2 (Competence / skill acquisition) is next. 5 commits ahead of origin, unpushed.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["1077e8b8a03ccfb1128c9d6ecc91435f733d7953"],"add":76,"del":136,"cadd":76,"cdel":136,"files":2},{"repo":"mesnada","hash":"b48aab39bbc995e55ade5b772ac39ef7927d51bf","ts":1783828971,"wall":"2026-07-12T00:02","msg":"feat: chunk M2a — use-based skill growth (skills grow from doing)","body":"The graded skills from B1/B2 now climb from the aptitude floor through use. First\nhalf of M2 (Competence); M2b (Academia training) is next.\n\n- grow_skill(unit, skill, opponent_level): difficulty-scaled (a tougher opponent\n  trains you fast, a weakling trains nothing), diminishing near mastery, INT scales\n  the learning *speed*. trained_points accumulate as FLOAT so small/INT-driven gains\n  compound and the plateau is a real mechanic, not a rounding artifact; the effective\n  level shown to the client stays int. EASY_FLOOR=0.9 -> you rise to your competition\n  and must fight tougher foes to climb further.\n- Combat (resolve_combat): the strike trains the attacker's weapon skill (Smash/\n  Blade/Aim) vs the defender's best defense; taking a hit trains Toughness; the\n  counter mirrors it. CombatResult.skill_events -> SKILL_UP events (fog-filtered).\n- Non-combat: gather->Labour, heal->Medicine, construct->Engineering via\n  train_from_task (flat difficulty). SKILL_UP surfaced in the event log.\n- Calibrated by harness (steady/visible pacing): ~+23 skill over 20 veteran fights,\n  weaklings train nothing, mastery needs elite opposition.\n\nRemaining growth sites (noted follow-up): Ambush/Sneak (stealth), Engineering on\nfortify/sap/bridge.\n\n566 pass / 3 skip (+12). tsc + build clean.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["586612c28cb836680956878c54409c677c30dc04"],"add":361,"del":26,"cadd":361,"cdel":26,"files":14},{"repo":"mesnada","hash":"32ee26253ee805704bcd0c21afc47241ab545029","ts":1783829751,"wall":"2026-07-12T00:15","msg":"docs: session handoff — M2a (use-based skill growth) shipped","body":"Updates the handoff and master-plan status: M1 complete + M2a shipped (b48aab3).\nSkills now grow from use. M2b (Academia training-dummy path) is next, planned in\nmesnada-chunk-c-skill-acquisition.md. 566 pass / 3 skip. 7 commits ahead of origin.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["b48aab39bbc995e55ade5b772ac39ef7927d51bf"],"add":36,"del":22,"cadd":36,"cdel":22,"files":2},{"repo":"mesnada","hash":"41d8c82d70dc6f033692a4d5d4c552d0a14d6210","ts":1784239111,"wall":"2026-07-16T17:58","msg":"docs: M2b Academia — resolve tuition (flat per-turn gold, pause on can't-pay)","body":"Academia charges a flat ACADEMY_TUITION each training turn, charged before the\nskill tick. Insufficient gold pauses training (no charge, no gain, stance\nretained), resuming when gold returns. Resolves the OPEN tuition question in the\nM2b plan; adds the decision, per-turn mechanics, and test coverage.","parents":["32ee26253ee805704bcd0c21afc47241ab545029"],"add":5,"del":3,"cadd":5,"cdel":3,"files":1},{"repo":"mesnada","hash":"9b67912ef16412c67e9dea3a36f7ee97c6a59dad","ts":1784243164,"wall":"2026-07-16T19:06","msg":"feat: M2b backend — Academia skill training (occupancy + flat tuition)","body":"Rename University -> Academia and add a skill-training path: a unit occupying an\nowned settlement with an Academia trains one skill each turn for a flat gold\ntuition, INT-paced and headroom-slowed, until it caps or leaves.\n\n- BuildingDef.skill_train flag + settlement resolver property + serialization;\n  School keeps rank_train (M3-D), Academia gains skill_train.\n- Unit.training / training_skill stance (mirrors gather/explore); set_training\n  action gates on owner + Academia-occupant + graded skill; dispatch + skill_id\n  payload; TRAINING_STARTED / TRAINING_STOPPED events.\n- end_turn _process_training: charge ACADEMY_TUITION before the tick; can't-pay\n  pauses (no charge, no gain, stance kept); pawn.academy_train does the flat\n  growth; ends on mastery or leaving the settlement.\n- config: ACADEMY_RATE, ACADEMY_TUITION (starting values, calibrate in harness).\n- game.ts wire-type mirror (training fields, settlement skill_train, skill_id).\n\ntest_academia.py (16 tests): gating, per-turn growth + tuition, pause/resume,\nleaving/losing the settlement, INT scaling, mastery clamp, end_turn wiring.\nFull suite 582 pass / 3 skip; frontend tsc clean.","parents":["41d8c82d70dc6f033692a4d5d4c552d0a14d6210"],"add":418,"del":17,"cadd":405,"cdel":4,"files":17},{"repo":"mesnada","hash":"554ba79deff92d0ddf0a5fe8a95e53f5588c63a0","ts":1784244890,"wall":"2026-07-16T19:34","msg":"feat: M2b — serialize trainee progress + ETA for the Academia panel","body":"Add pawn.academy_progress(unit, skill) → (progress 0..1 toward the next level,\nest_turns to reach it at the flat rate; None once mastered). Serialize\ntraining_progress / training_est_turns in _unit_to_dict when a unit is training\n(neutral 0.0/None otherwise), so the frontend can render a progress bar with a\nturns-to-next estimate without holding the growth formula. Also persists the\napproved frontend plan (panel-only, all 12 skills, progress+ETA).\n\ntest_academia.py: progress is a fraction and ETA shrinks with training; mastery\nyields (1.0, None); fields serialize only while training. game.ts mirrors both.","parents":["9b67912ef16412c67e9dea3a36f7ee97c6a59dad"],"add":142,"del":2,"cadd":142,"cdel":2,"files":5},{"repo":"mesnada","hash":"8e4c92050d58893ccbf95baaaf2fb064941ee594","ts":1784249306,"wall":"2026-07-16T20:48","msg":"feat: M2b frontend — Academia training panel, badge, and skill display","body":"Give the Academia skill-training feature its UI, grounded in strategy-game\nconventions (centralized panel, surfaced cost, visible progress + ETA, glanceable\nstatus):\n\n- SettlementModal: \"Academia\" panel (owned + skill_train) — per occupant, a\n  12-skill grid to start training (mastered greyed), or a live progress bar with\n  L→L+1 and ~N-turns ETA and a Stop button; header shows tuition + an\n  insufficient-gold pause warning.\n- lib/skills.ts: SKILL_META for the 12 graded skills (names + emoji) — the first\n  frontend skill-label source.\n- unitRenderer: 🎓 badge on trainees (bottom-right, clear of gather/scout).\n- PawnPanel: split into Proficiencies (all 12 graded levels, previously invisible)\n  + Abilities (binary), with a training line.\n- EventLog/events: TRAINING_STARTED / TRAINING_STOPPED; SKILL_UP uses skill names.\n- useGameActions.setTraining; App threads settlement occupants + onSetTraining.\n- settlement.to_dict exposes academy_tuition so the panel shows the real cost.\n\ntsc + vite build clean; backend suite green (585/3).","parents":["554ba79deff92d0ddf0a5fe8a95e53f5588c63a0"],"add":224,"del":6,"cadd":224,"cdel":6,"files":10},{"repo":"mesnada","hash":"634d657ee97dcc2da98dc29c1e307b1b1562ef46","ts":1784249560,"wall":"2026-07-16T20:52","msg":"feat: economy foundation — needs/happiness constants + settlement resolvers","body":"Data-layer groundwork for production chains + population needs (no behavior change\nyet):\n\n- config.py: PROD_MIN_HAPPINESS; the NEEDS_BY_TIER demand ladder (cumulative\n  per-tier processed-good rates) + NEEDS_GOODS; the settlement happiness/unrest\n  constants (start/targets/inertia, growth response, emigration, unrest/revolt\n  thresholds, promotion gate). Growth multiplier is 1.0 at happiness 50 (==START)\n  and the promotion gate is < 50, so legacy population math/tests are unchanged.\n- settlement.py: Settlement.happiness (0-100, default 50) + unrest_turns fields;\n  `needs` and `production_recipes` resolver properties (mirror subsistence/\n  max_population); to_dict exposes happiness/needs/production_recipes for the later\n  frontend.\n- test_buildings.py: needs resolver + empty production_recipes tests.\n\n33 building/serialization/population tests green.","parents":["8e4c92050d58893ccbf95baaaf2fb064941ee594"],"add":98,"del":0,"cadd":98,"cdel":0,"files":3},{"repo":"mesnada","hash":"dce0e018618ae5f4666355d24da14f6d0418aaa4","ts":1784249692,"wall":"2026-07-16T20:54","msg":"feat: economy — nine production buildings (transform recipes)","body":"Author the wide production slate as data (building_loader already maps transform,\nso zero engine code): sawmill (timber->planks), mill (grain->flour), bakery\n(flour->bread), kiln (peat->charcoal), smelter (ore+charcoal->ingots), smithy\n(ingots->tools), weaver (fiber->cloth), brewery (grain->ale), apothecary\n(herbs->medicine). Five chains, two 3-stage. Intermediates: planks, flour,\ncharcoal, ingots. Consumer goods for the needs ladder: bread, ale, cloth, tools,\nmedicine. Recipes are inert until the production turn-step lands next.\n\ntest_production_data.py: all nine load with valid recipes; populated\nproduction_recipes resolver.","parents":["634d657ee97dcc2da98dc29c1e307b1b1562ef46"],"add":124,"del":0,"cadd":34,"cdel":0,"files":10},{"repo":"mesnada","hash":"78276f46be5742119769b8704856506e550a12a6","ts":1784249940,"wall":"2026-07-16T20:59","msg":"feat: economy — production turn-step (buildings transform stored goods)","body":"_process_production runs each owned settlement's recipes once per turn, before\n_process_population. Input availability is checked against a snapshot of stores\ntaken at the start of the settlement's pass, so an intermediate produced this turn\nisn't consumed downstream until next turn -- multi-stage chains advance exactly one\nstage/turn, independent of build order. Net-positive output respects store_capacity\n(like _worker_deposit); rock-bottom happiness halts production; owner-filtered.\n\n- events.py: PRODUCE; registered in the main.py fog-of-war coord filter.\n- test_production.py (9): consume->produce, missing input no-op, one-stage/turn\n  pipeline, multi-input, capacity gate on net-positive, net-negative runs when full,\n  happiness halt, owner filter, emits PRODUCE.\n\nFull suite 606 pass / 3 skip.","parents":["dce0e018618ae5f4666355d24da14f6d0418aaa4"],"add":152,"del":0,"cadd":152,"cdel":0,"files":4},{"repo":"mesnada","hash":"03860611ade3495bfef22077721a265817015b75","ts":1784250240,"wall":"2026-07-16T21:04","msg":"feat: economy — population needs + settlement happiness/unrest","body":"_process_needs_happiness (end_turn, after _process_population) consumes each tier's\nprocessed-good needs from stores, then eases settlement happiness toward a target set\nby need satisfaction (minus a penalty on a starving turn). Happiness, carried to next\nturn, scales logistic growth (1.0 at 50 == HAPPINESS_START, 0 at the stall point) and,\nbelow the stall point, drives emigration; tier promotion is gated on happiness >= 40.\nSustained rock-bottom happiness WHILE starving secedes the settlement to neutral\n(owner=None) with a partial pop loss -- so a merely needs-short settlement stagnates\n(chronic unrest), only a starving one revolts. Needs never starve population; food\nremains the only survival constraint. Distinct from unit morale.\n\n- events.py: SHORTAGE, UNREST, REVOLT (registered in the main.py fog filter).\n- turn.py: _happiness_growth_mult; _process_needs_happiness; growth/emigration in\n  _process_population; happiness gate in _check_tier_promotion; wired after population\n  with an order-coupling comment (starvation detection reads its events).\n- test_happiness.py (9). Full suite 607 pass / 3 skip; legacy population tests\n  unaffected (default happiness 50).","parents":["78276f46be5742119769b8704856506e550a12a6"],"add":227,"del":5,"cadd":227,"cdel":5,"files":4},{"repo":"mesnada","hash":"4d6e3ab91e1083dfc9b10e65ccb3862427fc4468","ts":1784250416,"wall":"2026-07-16T21:06","msg":"docs: living-economy research + production/needs/happiness shipped notes; handoff","body":"- mesnada-living-economy-research.md: the four researched pillars (Cook value\n  chains, Doran-Parberry emergent pricing, trader fun, Hanseatic merchant guild),\n  the proposed Mesnada architecture, and the dependency-ordered roadmap.\n- mesnada-production-needs-happiness.md: shipped notes + the happiness model +\n  tuning constants for the chunk that just landed.\n- handoff.md: rewritten for this session (M2b end-to-end + the economy substrate).","parents":["03860611ade3495bfef22077721a265817015b75"],"add":221,"del":72,"cadd":221,"cdel":72,"files":3},{"repo":"mesnada","hash":"647193ed18fd2729e804f1c6e5b28c9d43cd4b9c","ts":1784251656,"wall":"2026-07-16T21:27","msg":"feat: economy frontend — settlement welfare as a Chernoff face (modal + tooltip + log)","body":"Encode a settlement's economy/welfare state as a Chernoff face (Chernoff 1973) so it\nreads at a glance, with the specifics in text. Feature mapping: mouth←happiness,\neyes←needs satisfaction, brows←unrest, pallor←food security, size←population, a gold\nring when producing.\n\n- lib/chernoff.ts: settlementFace/settlementMood/faceDecode + needs/production/food\n  helpers (pure; demand = rate×pop vs stores; mood bands aligned to backend\n  UNREST/REVOLT/promotion thresholds).\n- ChernoffFace.tsx: SVG face from FaceParams.\n- SettlementModal: a Welfare card (face + mood + itemized needs met/short +\n  production running/idle); mood shown in the header too.\n- HexTooltip: a one-line mood + needs readout for owned settlements.\n- EventLog: UNREST/REVOLT lines; PRODUCE/SHORTAGE filtered out (per-turn ticks shown\n  in the Welfare panel, not the log).\n- types: SettlementData happiness/needs/production_recipes; events union.\n\ntsc + vite build clean. (Board face is the next commit.)","parents":["4d6e3ab91e1083dfc9b10e65ccb3862427fc4468"],"add":271,"del":4,"cadd":271,"cdel":4,"files":7},{"repo":"mesnada","hash":"307b743b47a7864cf311469036e7e3e9837a30dd","ts":1784251833,"wall":"2026-07-16T21:30","msg":"feat: economy frontend — Chernoff welfare face on the board map","body":"Owned settlements now draw their Chernoff welfare face (mood/needs/food/population)\nin place of the tier emoji, so off-screen discontent is visible on the map — a\nfrowning town is visibly in unrest without opening it. Neutral settlements (no\nrunning economy) keep the tier emoji; the owner ring and name are unchanged.\n\n- rendering/chernoffFace.ts: a Pixi Graphics draw fn, geometrically identical to the\n  SVG face (same 100-unit face space → target radius), sharing settlementFace from\n  lib/chernoff. Face.size (population) scales it.\n- hexRenderer: owned+visible settlements render the face; else the tier emoji.\n\ntsc + vite build clean.","parents":["647193ed18fd2729e804f1c6e5b28c9d43cd4b9c"],"add":74,"del":10,"cadd":74,"cdel":10,"files":2},{"repo":"mesnada","hash":"2100f57f71bd6b873b4473ef1c039dfdeb19d270","ts":1784324550,"wall":"2026-07-17T17:42","msg":"feat: living market economy — bodega market-maker, commodity trade, tax faucet","body":"Each bodega becomes a per-settlement market-maker pricing all 17 commodities via a two-pool constant-product reserve (spot = kappa/(stores+g0)). Every commodity is now buyable and sellable; prices move with local supply/demand and a slow belief reverts them toward production-cost anchors each round (game/market.py, _process_markets).\n\nKills the static-price gold faucet: selling pays from a bodega's finite treasury and goods enter settlement stores. Adds the real gold source — a tax faucet: each owned settlement pays its owner per turn (population tax scaled by happiness, plus bodega commerce) via _process_tax. Bodega gains a small 30-slot storage buffer so gatherers can deposit.\n\nConfig note (config.py also carries the adversary-AI constants used by the next commit). 705 tests pass.","parents":["307b743b47a7864cf311469036e7e3e9837a30dd"],"add":1128,"del":82,"cadd":1123,"cdel":79,"files":21},{"repo":"mesnada","hash":"fa012552fd24126924ea71bd78fbbadc30dac69d","ts":1784324566,"wall":"2026-07-17T17:42","msg":"feat: adversary AI — utility spine + economic self-sufficiency + military mind (M1-M4)","body":"Turns the greedy combat bot into a strategic adversary on one utility spine (game/ai/utility.py): amortized present value (the fix for greedy myopia — economic investments score their discounted future yield), one 0-150 want scale with a >100 emergency band, response curves, compensation-factor combine, +25% momentum. Economic self-sufficiency (game/ai/economy.py): it builds its economy and gathers, funded by taxes.\n\nMilitary mind: M1 recruitment scaled by force ratio (game/ai/military.py); M2 two-axis posture — butter/guns and preserve/conquer (game/ai/posture.py); M3 strangulation — capture enemy/neutral settlements to cut their recruitment; M4 preservation — refuse suicidal trades, retreat endangered units, and an emergency override that drops everything to save the last units (the only lose condition).\n\n705 tests pass; ruff clean.","parents":["2100f57f71bd6b873b4473ef1c039dfdeb19d270"],"add":1305,"del":34,"cadd":1305,"cdel":34,"files":14},{"repo":"mesnada","hash":"e4d43652470494471e81115035043aad41c133cd","ts":1784324625,"wall":"2026-07-17T17:43","msg":"docs: adversary-AI research + military-mind plan + session handoff","body":"Prior-art research for the economic/strategic AI (utility theory, Freeciv amortize/want, Wesnoth guns-vs-butter, two-axis doctrine) and the M1-M4 military-mind plan, plus the session handoff (living economy + adversary AI, 705 tests).","parents":["fa012552fd24126924ea71bd78fbbadc30dac69d"],"add":373,"del":65,"cadd":373,"cdel":65,"files":3},{"repo":"mesnada","hash":"fb0265f4af62056fa39c9a1ac4aee029674d38e0","ts":1784325196,"wall":"2026-07-17T17:53","msg":"feat: market panel — settlement UI for live commodity trade","body":"SettlementModal Market panel: every commodity's live buy/sell price + local stock + carried amount, wired to buy_commodity/sell_commodity. Surfaces the bodega treasury and each settlement's tax income; removes the superseded Sell Resources subsection. Types/events/dispatchers wired; tsc --noEmit and vite build clean.","parents":["e4d43652470494471e81115035043aad41c133cd"],"add":94,"del":14,"cadd":94,"cdel":14,"files":5},{"repo":"mesnada","hash":"91ac3f40a01144d827f2fce4dc5678374706efd1","ts":1784325638,"wall":"2026-07-17T18:00","msg":"feat: economy sim harness + AI perf (enemy-position cache)","body":"Adds a full-loop economy sim harness (test_economy_sim.py): runs production->needs->tax->markets over many turns and asserts the economy stays healthy — prices clamped to [anchor, anchor*CEIL], stores non-negative, tax accrues, shocks heal. Doubles as a tuning rig.\n\nPerf: cache enemy positions per greedy-loop iteration so move scoring stops rebuilding the enemy list per candidate (with a state-scan fallback for standalone scoring) — 60 AI turns 43s->16s (~2.7x), behaviour unchanged. 710 tests pass; ruff clean.","parents":["fb0265f4af62056fa39c9a1ac4aee029674d38e0"],"add":134,"del":14,"cadd":134,"cdel":14,"files":4},{"repo":"mesnada","hash":"563dcc98102e5e8c58bb82e109ac2c8843c5ad9b","ts":1784325830,"wall":"2026-07-17T18:03","msg":"docs: thorough session handoff — full arc, architecture, force-concentration next","body":"Comprehensive handoff a fresh session can resume from: market/tax/AI architecture, the M1-M4 doctrine, files, config tuning reference, and force-concentration breakthrough noted as the one remaining optional item (with a design sketch).","parents":["91ac3f40a01144d827f2fce4dc5678374706efd1"],"add":134,"del":60,"cadd":134,"cdel":60,"files":1},{"repo":"mesnada","hash":"93c4ef6d4998f16326eae7b0722960014120e45e","ts":1784326459,"wall":"2026-07-17T18:14","msg":"perf: memoize reachability, stats, and unit danger across the AI greedy loop","body":"The greedy loop re-enumerates every unit's actions after each action, recomputing reachable_costs, get_effective_stats, and per-unit danger ~50x/turn. All three are stable per (unit, position) within a turn (reachable_costs ignores en-route occupancy), so they're now memoized in per-turn caches cleared by play_ai_turn. A mid-game 6v6 AI turn: ~0.33s -> ~0.14s (with the earlier enemy-position cache, ~2.4x this round). Behaviour unchanged; 710 tests pass, ruff clean.","parents":["563dcc98102e5e8c58bb82e109ac2c8843c5ad9b"],"add":63,"del":10,"cadd":63,"cdel":10,"files":4},{"repo":"mesnada","hash":"a986b1592f0dd06e89180d156bd9fa7ff88405ce","ts":1784566749,"wall":"2026-07-20T12:59","msg":"docs: consolidated state-of-the-game — single source of truth + plan of record","body":"One canonical doc reconciling every Mesnada planning artifact against the\nground-truth code (verified 2026-07-20): full development arc, how the game\nfunctions now (12 subsystems), current build state, the 48-finding defect\naudit reconciled (all CRITICAL + HIGH fixed), and the forward roadmap (§6,\nled by the unbuilt M3 command-and-faction layer).\n\nSupersedes handoff.md, mesnada-remediation-roadmap.md, and mesnada-defect-audit.md\nas status docs; the .claude/plans sub-plans remain authoritative for design detail.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["93c4ef6d4998f16326eae7b0722960014120e45e"],"add":407,"del":0,"cadd":407,"cdel":0,"files":1},{"repo":"mesnada","hash":"eb9d6bc8d59a5bb12934f8eaaee0f1c44a1496b7","ts":1784567163,"wall":"2026-07-20T13:06","msg":"chore: clear ruff unused-import backlog (23 F401 across 12 modules)","body":"Removes dead imports flagged by ruff; no logic changed. `ruff check game/`\nnow clean; backend 710 pass / 3 skip unchanged.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["a986b1592f0dd06e89180d156bd9fa7ff88405ce"],"add":10,"del":20,"cadd":10,"cdel":20,"files":12},{"repo":"mesnada","hash":"72827f2f8df658cc7bb308e7ec57e85746f99e63","ts":1784567563,"wall":"2026-07-20T13:12","msg":"docs: state-of-the-game — ruff clean; RNG determinism confirmed already-resolved","body":"Lint backlog cleared (eb9d6bc), so §4/§6.6/§8 updated to \"clean\". RNG\ndeterminism re-investigated against ground truth: create_new_game seeds one\nrandom.Random(seed) and threads it through worldgen/placement/inventories/\nresources into state.rng, so every production path is deterministic — the\n07-04 audit concern was closed by the 07-07 seeded-rng work. The settlement.py\nrandom.Random() fallbacks are test-only conveniences. §5 corrected.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["eb9d6bc8d59a5bb12934f8eaaee0f1c44a1496b7"],"add":16,"del":11,"cadd":16,"cdel":11,"files":1},{"repo":"mesnada","hash":"4042815cd69069f1676d2c2d1d11fbdf76334578","ts":1784569435,"wall":"2026-07-20T13:43","msg":"docs: correct the combat damage formula (multiplicative, not subtractive)","body":"The Chunk-B2 rework switched combat to multiplicative mitigation\n(dmg = atk * C/(C + eff_def), C=10) with stats-derived attack/defense and no\nrank scaling, but two docs still described the old subtractive max(0, atk-def)\nformula: combat.py's module docstring and the state-of-the-game §3.3. Both now\nmatch the actual _calculate_damage. Docstring/prose only — no behavior change.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["72827f2f8df658cc7bb308e7ec57e85746f99e63"],"add":30,"del":17,"cadd":30,"cdel":17,"files":2},{"repo":"mesnada","hash":"0b55e3475491c67d3526a3084c6e5c2693c69857","ts":1784569529,"wall":"2026-07-20T13:45","msg":"feat: EventLog labels for the 5 unlabelled events + GIVE/LEARN","body":"Adds SETTLEMENT_CAPTURED, TERRORIZE, MIND_SIGHT, BURNOUT_DAMAGE, and\nBURNOUT_DEATH to the GameEventType union and gives all five — plus the\npreviously-unhandled GIVE and LEARN — human-readable format cases in the event\nlog, so they no longer render as raw uppercase tokens. Field mappings verified\nagainst the backend event payloads; tsc + vite build clean.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["4042815cd69069f1676d2c2d1d11fbdf76334578"],"add":20,"del":1,"cadd":20,"cdel":1,"files":2},{"repo":"mesnada","hash":"4a623f66c23f40f53e97427688e789ea6e8cd4a8","ts":1784570013,"wall":"2026-07-20T13:53","msg":"fix: render the chainmailed-arbalestier sprite (dead asset wired)","body":"ArbelistChained.png existed but no SPRITE_MAP key pointed at it, so a chainmail +\narbalest unit fell back to plain chainmail art. Add the chainmail+arbalest_weapon\nmapping — the combo is reachable by equipping both.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["ded18eb807c9beb95ee03aa038d0011b9e0a54e5"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"mesnada","hash":"ded18eb807c9beb95ee03aa038d0011b9e0a54e5","ts":1784570013,"wall":"2026-07-20T13:53","msg":"fix: close the settlement shop when the town is captured mid-turn (M-7)","body":"UPDATE_STATE kept the player in the shop across their own actions, but never\nre-checked ownership — so if an AI captured the settlement during auto-play, the\nplayer stayed in a now-enemy store whose buy/recruit calls would fail server-side.\nKeep the shop open only while the settlement is still owned by the human player.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["0b55e3475491c67d3526a3084c6e5c2693c69857"],"add":5,"del":31,"cadd":5,"cdel":1,"files":4},{"repo":"mesnada","hash":"1332b67e6afd2d7dc570c707757a1daa930ef6f3","ts":1784571311,"wall":"2026-07-20T14:15","msg":"docs: design directions (factions, governments, trade caravans) + parked RTS/Command mode","body":"Captures a design session: four threads finish the turn-based core (trade\ncaravans, factions, government types, the M3 command layer), then a real-time\nRTS/Command mode ships as a separate version sharing the domain logic — AP\nbecomes a regenerating Command pool modelled on VATS-era Fallout (Mesnada already\nhas the stat-derived cap + kill-refunds; only continuous regen is new; keep the\npool player-wide; drop the 2d6 for multiplayer). New plan doc + state-of-the-game\n§6.7; §6.2/§6.6 updated to mark this session's shipped fixes (M-7, EventLog\nlabels, combat-formula docs, orphan skills, arbalest sprite).\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["4a623f66c23f40f53e97427688e789ea6e8cd4a8"],"add":187,"del":6,"cadd":187,"cdel":6,"files":2},{"repo":"mesnada","hash":"3a8102818e5c911d942cb09bc131b70623794aef","ts":1784574028,"wall":"2026-07-20T15:00","msg":"chore: launch.sh — one-shot dev launcher (venv + servers + open browser)","body":"Activates the backend venv, runs start.sh (backend :8000 + frontend :5173), and\nopens the browser once Vite answers. Backs the KDE desktop button (mesnada.desktop,\nwhich lives in ~/.local and is machine-specific, not committed).\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["fd4dc422b91c5d2ca6f34b63e9d191668f0bef17"],"add":25,"del":0,"cadd":25,"cdel":0,"files":1},{"repo":"mesnada","hash":"c04224666f39cebb8a7481cabdb5276a54c88aa9","ts":1784574028,"wall":"2026-07-20T15:00","msg":"feat: AP-gate autonomous movement — workers + scouts spend from leftover AP (caravan Phase 0)","body":"Auto-gather workers and auto-explore scouts moved for free off a private movement\nbudget; now their movement draws from the player's leftover AP at end_turn, at the\nmanual-movement per-hex rate, and stalls when the pool is dry. AP becomes the\nuniversal action gate (no off-AP carve-out), making guns-vs-butter literal — spend\nevery AP fighting and you get no auto-hauling/scouting that turn. `_worker_step_toward`\ngains optional player/stats params (AP-gated when supplied; the movement-geometry\nprimitive still steps freely for direct callers). The gather/deposit/reveal ticks stay\nfree (movement-only per the decision). Prerequisite for trade caravans, which share\nthis model. 714 pass / 3 skip; ruff clean.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["1332b67e6afd2d7dc570c707757a1daa930ef6f3"],"add":97,"del":16,"cadd":97,"cdel":16,"files":3},{"repo":"mesnada","hash":"fd4dc422b91c5d2ca6f34b63e9d191668f0bef17","ts":1784574028,"wall":"2026-07-20T15:00","msg":"docs: trade-caravans plan (D1-D6 + Phase 0 AP-gating retrofit)","body":"The full caravan design: a worker that trades instead of gathers, composing the\nworker shuttle + AMM market; player and neutral tiers; economics (self-converging,\nfinite treasuries, no minted money); raidability; and D6 — all movement is AP-gated\n(spend-from-leftover), which is now Phase 0 (shipped separately).\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["c04224666f39cebb8a7481cabdb5276a54c88aa9"],"add":206,"del":0,"cadd":206,"cdel":0,"files":1},{"repo":"mesnada","hash":"db1018b39ca54749d66f8b36baec7140a2a5d08f","ts":1784574295,"wall":"2026-07-20T15:04","msg":"docs: session handoff — full-read + reconciliation + hygiene + design + caravan Phase 0","body":"11-commit session: canonical state-of-the-game doc from a full-codebase read; defect\naudit reconciled; hygiene (ruff, EventLog labels, M-7, arbalest, orphan skills, combat\ndocs); design directions (factions/governments/caravans/RTS); trade-caravans plan; and\nPhase 0 (AP-gate autonomous movement) shipped. Handoff points at the state doc as the\nplan of record; resume at caravans Phase 1 pending the D1-D5 confirm.\n\nAuthored by Rowan Valle; executed by Claude Code.","parents":["3a8102818e5c911d942cb09bc131b70623794aef"],"add":85,"del":155,"cadd":85,"cdel":155,"files":1},{"repo":"mesnada","hash":"8ace34a3c2744e1977b8de0d4907a0ae68435c1b","ts":1784669509,"wall":"2026-07-21T17:31","msg":"docs: living-economy spec — geology, tech ladder, population strata","body":"Plan of record for the economy/population arc: an extractive geology feeds a\nreach-not-research tech ladder (stone to electronics), gated by a four-stratum\npopulation pyramid and a per-turn labor flow, with autarky and trade as two\nviable metabolisms and money as the eventual capstone. Seven open design\nquestions closed by a prior-art pass (Anno, Victoria 3, Dwarf Fortress,\nFactorio, the demographic transition model). Every live claim verified against\nthe current engine.","parents":["db1018b39ca54749d66f8b36baec7140a2a5d08f"],"add":486,"del":0,"cadd":486,"cdel":0,"files":1},{"repo":"mesnada","hash":"8f294b23e9432bbd0f399dc7f6017693e72a3dc8","ts":1784669509,"wall":"2026-07-21T17:31","msg":"feat: recipe-graph query layer","body":"The reach-not-research ladder as queryable data — one module reused across the\neconomy arc. producible() answers what a hinterland can make given its raws and\nshops; requirements_for() gives the minimal missing shops/raws to unlock a target\n(bottleneck diagnostic + AI climb); frontier() reports tech level;\nstrangulation_targets() ranks each raw/shop by how much of the ladder collapses\nif denied; min_cut_for() finds the smallest denial set to break a target (the\neconomic-warfare tools). Reuses the recipe-collection pattern from\nmarket.commodity_anchors; built to absorb substitution when it arrives. 14 tests.","parents":["c87d67e626fa9d65f40ba7c4240852517edc8a62"],"add":385,"del":0,"cadd":385,"cdel":0,"files":2},{"repo":"mesnada","hash":"c87d67e626fa9d65f40ba7c4240852517edc8a62","ts":1784669509,"wall":"2026-07-21T17:31","msg":"feat: populate the world by default (P1.1)","body":"New games defaulted to a bare radius, spawning only two settlements with no\nneutrals — a degenerate map with no trade network, the reason the economy read\nas dead. Default map_size to \"medium\" (about eight towns incl. neutral market\npartners) and thread map_size through GameSetup, the API, and the client, with a\nWorld-size selector restoring the parked map-size options. The low-level\ncreate_new_game(radius=...) test idiom is untouched. New test_new_game_defaults\nlocks the populated default (neutral bodegas present).","parents":["8ace34a3c2744e1977b8de0d4907a0ae68435c1b"],"add":71,"del":10,"cadd":71,"cdel":10,"files":6},{"repo":"mesnada","hash":"fc6e9f5645379848840422a54fe96b41026835b8","ts":1784670322,"wall":"2026-07-21T17:45","msg":"feat: geological deposit layer (P1.2)","body":"Terrain is too coarse to specialize an economy — a town near plains/forest/hills\ngathers most of the palette, so processed prices stay flat. The deposit layer\npartitions the map into ~6-12 Voronoi geological provinces, each bearing one or\ntwo deposit classes (copper/tin/iron/coal/flux/precious/clay/rare-earth), and\ngates deposit-keyed resources on the class borne at their hex — clustering metals\ninto regions. Keystone deposits (tin/flux/rare-earth) never spawn in a player's\nstart province, so the chokepoints must be reached for; deposit yields scale with\nremoteness from the nearest start. Wired via an RNG snapshot so existing placement\nstreams stay byte-identical (all prior tests unchanged). Inert until P1.3 keys the\nmetal raws to deposits. 9 tests.","parents":["8f294b23e9432bbd0f399dc7f6017693e72a3dc8"],"add":258,"del":4,"cadd":258,"cdel":4,"files":4},{"repo":"mesnada","hash":"8e3c02819d281d823fca32984d1f369ab22e617e","ts":1784670446,"wall":"2026-07-21T17:47","msg":"docs: session handoff — P1.1, recipe-graph layer, deposit layer (P1.2)","body":"This session: shipped the living-economy spec (plan of record), populated the\nworld by default (P1.1), the recipe-graph query layer, and the geological\ndeposit layer (P1.2, inert until P1.3). Next is P1.3 — the metal raws and alloy\nrecipes that key to the deposit layer and finally move the price-spread meter.","parents":["fc6e9f5645379848840422a54fe96b41026835b8"],"add":97,"del":96,"cadd":97,"cdel":96,"files":1},{"repo":"mesnada","hash":"180e2fb91addf3e0202657f277d21b29e7079fc3","ts":1784682317,"wall":"2026-07-21T21:05","msg":"feat: metallurgy spine — metals + alloy chains (P1.3)","body":"Makes the deposit layer live. Adds 8 finite, deposit-keyed metal raws\n(iron/copper/tin/coal/limestone/fire_clay/silver/gold) — so games now differ in\nwhat they can make (a seed with no iron cannot smelt steel locally). Adds the\nalloy chain as data: crucible_maker, blast_furnace (iron+coal+limestone->steel),\nfoundry (copper+tin->bronze), weaponsmith, bronzeworks, armorer — with weapons\nproducible from steel OR bronze (substitution, an escape hatch for the iron-less\ntown) and the furnaces gated on a crucible to build (the reach-not-research\nrecursion). Fixes a latent anchor bug substitution exposed: a good with multiple\nrecipes now anchors to its CHEAPEST path, not whichever resolved first. 741 pass.","parents":["8e3c02819d281d823fca32984d1f369ab22e617e"],"add":157,"del":16,"cadd":97,"cdel":16,"files":13},{"repo":"mesnada","hash":"7cb7193e2d685a499e4f1202983d0abe5bc02a55","ts":1784682317,"wall":"2026-07-21T21:05","msg":"feat: economic-aliveness meter (backend/tools/measure_spreads.py)","body":"Promotes the price-spread harness from scratchpad to a kept tool — the fitness\nfunction for the living-economy arc. Drives AI-vs-AI games on a populated map and\nreports, per commodity, the peak cross-town price gap and its dwell, split raw vs\nprocessed, plus a census of which production buildings the AI actually built. That\ncensus is what diagnosed the real blocker: the AI builds zero production, so\nprocessed goods stay flat regardless of commodity content.","parents":["180e2fb91addf3e0202657f277d21b29e7079fc3"],"add":126,"del":0,"cadd":126,"cdel":0,"files":1},{"repo":"mesnada","hash":"c5bc3cb6caa12b083a97cc15591066f44c21067b","ts":1784684756,"wall":"2026-07-21T21:45","msg":"chore: meter tests a real multi-town economy (>= 6 developed towns)","body":"Bumps the map to large and seeds each player with several staffed, owned towns\n(seed_multitown_economy) instead of one lone capital — so the fitness function\nmeasures production at scale, never a two-town toy. Adds a building census that\ndiagnoses incomplete chains (a shop built with nothing to feed it).","parents":["dfe102bfa782952bd1d375faf8ef43cf62d17f3d"],"add":26,"del":1,"cadd":26,"cdel":1,"files":1},{"repo":"mesnada","hash":"dfe102bfa782952bd1d375faf8ef43cf62d17f3d","ts":1784684756,"wall":"2026-07-21T21:45","msg":"feat: AI builds a real economy — material pay, seek resources, all pawns gather (P1.4a)","body":"The economic AI built nothing but its starting bodega/plaza because it only\nproposed buildings it could pay for entirely in gold (it starts at 10, buildings\ncost 40-90). Three fixes that close the gather -> stockpile -> build loop:\n\n- Material payment: also propose construct actions paid from the settlement's own\n  stockpile (construct already supported it; the AI never used it), scored on\n  material affordability.\n- Seek resources: set_gathering gains a remote target hex; the AI dispatches idle\n  pawns to WALK to the nearest deposit of the resource its economy most lacks,\n  self-balancing across types (stone/timber first, then food, then metals).\n- All pawns gather: raise the gather-saturation ceiling (4 -> 30) so every idle\n  pawn works as a field hand, soldiers included.\n\nThe AI now gathers a spread and builds production (sawmills, bakeries, a first\nmetal shop). Not yet sufficient alone — it builds shops in no dependency order, so\nchains stay incomplete; the recipe-graph reach-scoring is the finish. 740 pass.","parents":["7cb7193e2d685a499e4f1202983d0abe5bc02a55"],"add":66,"del":22,"cadd":66,"cdel":22,"files":3},{"repo":"mesnada","hash":"299436780c9395ea677d924ca2e59a99b2f0a559","ts":1784686212,"wall":"2026-07-21T22:10","msg":"chore: launcher waits for backend before opening the browser","body":"Open the browser only once BOTH :5173 (Vite) and :8000 (API) answer, so the setup\nscreen can start a new game immediately instead of racing a not-yet-ready backend.","parents":["da6348935d18d454a363d9ad90350837972389c1"],"add":6,"del":3,"cadd":6,"cdel":3,"files":1},{"repo":"mesnada","hash":"da6348935d18d454a363d9ad90350837972389c1","ts":1784686212,"wall":"2026-07-21T22:10","msg":"feat: reach-based construct scoring (recipe-graph bottleneck-unblock)","body":"Score a building by how many downstream goods it unlocks given the settlement's\ninputs (recipe_graph.producible over its stockpile + what the player gathers), so\nthe AI builds chains in dependency order — mill before bakery, crucible before\nfurnace. Correct but latent: currently the AI can only afford cheap homes, so\nthere is nothing for reach to reorder until material throughput is fixed.","parents":["c5bc3cb6caa12b083a97cc15591066f44c21067b"],"add":26,"del":0,"cadd":26,"cdel":0,"files":1},{"repo":"mesnada","hash":"ff38966be5483240b631d040ca82888f0c4a33ed","ts":1784686212,"wall":"2026-07-21T22:10","msg":"docs: session handoff — economy arc through P1.4; throughput is the next constraint","body":"Substrate built and proven (deposit layer, metallurgy spine, recipe-graph, AI\nmaterial-pay/seek/all-pawns-gather, reach-scoring). Meter still 0/14 processed:\nthe AI gathers with every pawn but materials trickle (spread across 12 types,\nAP-gated remote hauls), so production buildings are never affordable. Next step is\neconomy throughput — concentrate gathering + raise yields.","parents":["299436780c9395ea677d924ca2e59a99b2f0a559"],"add":86,"del":73,"cadd":86,"cdel":73,"files":1},{"repo":"mesnada","hash":"e6ac94382c7e41c7816d0187c238b9fca2fb25f9","ts":1784755332,"wall":"2026-07-22T17:22","msg":"feat: hover tooltips describing gear, items, and buildings","body":"Reusable portal Tooltip primitive (dark-glass, viewport-clamped) wired\nonto pawn gear/inventory/tomes and settlement construct/shop names,\nsurfacing the catalog descriptions on hover.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ff38966be5483240b631d040ca82888f0c4a33ed"],"add":114,"del":23,"cadd":114,"cdel":23,"files":3},{"repo":"holocene","hash":"7db45eba3b90d3f4ffc13677606c98afb4e751eb","ts":1784758104,"wall":"2026-07-22T18:08","msg":"feat: Holocene timeline — TypeScript + Vite modular refactor (Phase A)","body":"Port the single-file HTML timeline into a typed, modular Vite + TS project\nmirroring the house dynamic archetype. Behavior-preserving.\n\n- 14 modules across types/data/core/util/render/ui/interaction\n- core/state owns view state and the single year<->pixel scale\n  (the inverse is dedup'd out of zoom/pinch/wheel)\n- render/canvas owns the hit-region list; renderer wired via callback\n  so core/state needs no import of the renderer (no cycles)\n- dead thematic eras branch removed (no track used it)\n- 18 Vitest unit tests: format, layout packing, scale round-trip\n- reference/holocene-original.html kept as the parity baseline\n\nAuthored by Rowan Valle; Executed by Claude Code\n\nBy Symbiont Systems LLC","parents":[],"add":4592,"del":0,"cadd":3251,"cdel":0,"files":27},{"repo":"holocene","hash":"488f542394565db00dc5832f28f47c87c4e27c6c","ts":1784758369,"wall":"2026-07-22T18:12","msg":"fix: Phase B — a11y, pinch/pan dead-spot, tooltip offset","body":"Audit fixes on top of the Phase A port. Behavior-additive.\n\n- animateTo snaps instantly under prefers-reduced-motion (covers fit,\n  keyboard nav, and year-jump, which all route through it)\n- canvas gets role=img; its aria-label points AT users to the live\n  section panel as the text equivalent (no aria-live: rebuilds per pan)\n- pointer onUp re-arms panning when one finger remains after a pinch,\n  with moved=true so the following lift does not fire a phantom tap\n- placeTip adds the canvas offset within .wrap so the card lands on the\n  pointer instead of ~14px off\n\nAuthored by Rowan Valle; Executed by Claude Code\n\nBy Symbiont Systems LLC","parents":["7db45eba3b90d3f4ffc13677606c98afb4e751eb"],"add":24,"del":4,"cadd":24,"cdel":4,"files":4},{"repo":"holocene","hash":"f0e529abe3976dc96bc1ee3a13912793c04e7d7f","ts":1784758599,"wall":"2026-07-22T18:16","msg":"chore: add deploy.sh and project CLAUDE.md","body":"- deploy.sh: build, rsync dist/ to /var/www/holocene on the box, reload caddy\n  (no secrets; uses the symbiont-vps SSH alias and the box's own env token)\n- CLAUDE.md: project context in house style\n\nAuthored by Rowan Valle; Executed by Claude Code\n\nBy Symbiont Systems LLC","parents":["488f542394565db00dc5832f28f47c87c4e27c6c"],"add":74,"del":0,"cadd":74,"cdel":0,"files":2},{"repo":"mesnada","hash":"7a029fc0c842c5366cf027d0b01b4c58e83b7cf4","ts":1784758640,"wall":"2026-07-22T18:17","msg":"feat: supply-pull needs — survival/toll/luxury split (town-redesign chunk 1)","body":"Restructures population needs into the supply-pull grammar (spec §13.4) so a\nsettlement is never handed a debt on promotion — the bootstrap bug that kept the\nprocessed-goods meter at zero. Adds survival_needs (derived from the tolls a tier\nalready paid, so it can't drift), toll_good (gates the next promotion, buildable\nat this tier — Fork A), and luxury_needs (happiness bonus only). Happiness now\nrides on survival + a luxury lift; the toll no longer craters a fresh Village,\nwhich owes nothing and stays content.\n\nAlso folds this session's design into the spec: §13.4 supply-pull/demote town\nprogression, §13.5 troop feeding + two-tier rations + foraging-with-depletion.\n\n740 pass / 3 skip, ruff clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["e6ac94382c7e41c7816d0187c238b9fca2fb25f9"],"add":222,"del":45,"cadd":222,"cdel":45,"files":6},{"repo":"operations","hash":"b14c451d7fc2d46d6d0877f2da06e2625e515940","ts":1784758891,"wall":"2026-07-22T18:21","msg":"docs: register holocene in the atlas","body":"New project holocene — interactive Holocene-scale timeline viz\n(Vite/TS, Canvas 2D), deployed live at holocene.symbiont.systems.\n\n- projects/index.md: Active/Creative row\n- status/dashboard.md: Infrastructure (Live) + Active Development rows\n- projects/relationships.md: Creative chain\n- projects/links/holocene: symlink to code/holocene\n\nAuthored by Rowan Valle; Executed by Claude Code\n\nBy Symbiont Systems LLC","parents":["5a775353c8e8291b431491fa96d7d9e5b9fb62d4"],"add":5,"del":0,"cadd":4,"cdel":0,"files":4},{"repo":"holocene","hash":"1a9e304c6dbfd832eb670055365258cb3fe4db9a","ts":1784759011,"wall":"2026-07-22T18:23","msg":"style: fill the window width dynamically","body":"The content column was capped at 700px, leaving large empty margins on\nwide displays. Route all five caps through a single --content-max var\n(1800px) so the timeline fills typical windows and caps on ultra-wide.\nCanvas already re-renders on resize; no JS change.\n\nAuthored by Rowan Valle; Executed by Claude Code\n\nBy Symbiont Systems LLC","parents":["f0e529abe3976dc96bc1ee3a13912793c04e7d7f"],"add":11,"del":5,"cadd":11,"cdel":5,"files":1},{"repo":"mesnada","hash":"e439b32864889faf527e3bcffc6b92883c3e557a","ts":1784759362,"wall":"2026-07-22T18:29","msg":"feat: supply-pull promotion — sustain the toll to rise (town-redesign chunk 2)","body":"A settlement now promotes only after meeting its toll good (the next tier's entry\ngood) for PROMOTE_TOLL_TURNS consecutive turns, on top of population, happiness,\nand guaranteed buildings. toll_streak tracks it; the toll is consumed like a need\neach turn but never touches happiness. A tier with no toll (Homestead) still\npromotes on population alone.\n\nYou rise by already producing what the next tier consumes — so a Town always\narrives with its bread chain running, never into the debt that craters it (§13.4).\n\n741 pass / 3 skip, ruff clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["7a029fc0c842c5366cf027d0b01b4c58e83b7cf4"],"add":50,"del":4,"cadd":50,"cdel":4,"files":5},{"repo":"mesnada","hash":"15fae6c7f4a1a7f25704da6bc9e3442f97d3b26c","ts":1784760270,"wall":"2026-07-22T18:44","msg":"feat: graceful demotion — fall down the ladder, don't revolt (town-redesign chunk 3)","body":"A settlement that loses a survival good (a toll it once climbed on) for\nDEMOTE_UNMET_TURNS consecutive turns now falls one tier instead of festering\ntoward revolt — the reverse of supply-pull (§13.4). survival_deficit_turns\ntracks the shortfall; on demotion the tier drops, streaks reset, and population\nover the lower tier's cap emigrates. The Homestead (tier 1) is the\nun-collapsible floor. New TIER_DEMOTED event, wired into the fog filter.\n\nVerified on the probe: the seeded tier-2/3 towns that used to rot at happiness 20\n(no bread chain) now demote to sustainable Villages and sit content at 79-84 —\nthe death spiral is gone, tiers settle at {1:4, 2:4}, everyone fed. Towns\nfunction. (The processed-goods meter still needs the AI to build the bread chain\nso towns can climb — the next course.)\n\n743 pass / 3 skip, ruff clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["e439b32864889faf527e3bcffc6b92883c3e557a"],"add":64,"del":0,"cadd":64,"cdel":0,"files":6},{"repo":"holocene","hash":"85c1aef89ce844ef589ecfca21ae7cd099afc281","ts":1784760837,"wall":"2026-07-22T18:53","msg":"feat: arrange mode Phase 1 — grab-handle track reorder","body":"Direct manipulation replacing the ▲▼ chips (chips kept as the keyboard\npath). Each track gets a ⠿ grip handle; grab it and drag vertically to\nreorder the continental stack. View-only, vertical-only.\n\n- types: HitRegion gains kind/trackIndex/rowIndex; new Grab type\n- state: grab + hover fields\n- layout: trackBands() (pointer-Y → drop slot) and pure trackInsertIndex()\n- render/canvas: drawGrip(), track handle + hit, ghost + insertion line,\n  polity hits tagged with track/row (forward-compat for Phase 2)\n- interaction/arrange (new): beginGrab/updateTarget/commitGrab/clearGrab\n- interaction/pointer: handle grab takes priority over pan/tap; grab\n  suppresses pan/tap; setPointerCapture for the drag\n- 5 unit tests for the track-move index math\n\nTouch caveat: canvas is touch-action:pan-y; vertical grab relies on\nsetPointerCapture suppressing scroll — needs phone verification.\n\nAuthored by Rowan Valle; Executed by Claude Code\n\nBy Symbiont Systems LLC","parents":["1a9e304c6dbfd832eb670055365258cb3fe4db9a"],"add":230,"del":8,"cadd":230,"cdel":8,"files":8},{"repo":"holocene","hash":"6b4e501ac95d5b7df82b4da407967b83e51d7af8","ts":1784761180,"wall":"2026-07-22T18:59","msg":"data: re-anchor three dates to consistent criteria","body":"- Zoroastrianism -550 → -1200: Gathic Avestan linguistic horizon\n  (~Rigvedic), not Achaemenid adoption. Was appearing younger than\n  Judaism (-1208) only because the two were anchored differently.\n- Rapa Nui 400 → 1200: radiocarbon short chronology (now agrees with\n  its own moai event at 1200).\n- Chamorro (Marianas) 400 → -1500: initial Austronesian settlement.\n\nAuthored by Rowan Valle; Executed by Claude Code\n\nBy Symbiont Systems LLC","parents":["85c1aef89ce844ef589ecfca21ae7cd099afc281"],"add":3,"del":3,"cadd":3,"cdel":3,"files":1},{"repo":"holocene","hash":"c2e1fade8bdb9ef49888268775421b7171827e33","ts":1784761533,"wall":"2026-07-22T19:05","msg":"feat: arrange mode Phase 2 — grab-handle polity reorder","body":"Grab a polity/religion by its ⠿ handle (shown on the hovered/selected\nbar) and drag it to another packed row within its own track. View-only,\nvertical-only; horizontal (dates) and track (geography) stay locked.\n\n- render/canvas: polity handle on hover/select (zone extends past thin\n  slivers so they stay grabbable); polity ghost + insertion overlay\n- state.hover holds the bar under the cursor (redraw only on change)\n- layout: pure spansOverlap() + rowAccepts() overlap guard\n- arrange: polity grab/target(row)/commit — move between rows, reject on\n  time-collision (snap back), new row when dropped below all, prune empties\n- pointer: onDown accepts polity handles; hover sets state.hover\n- 3 unit tests for the overlap guard\n\nAuthored by Rowan Valle; Executed by Claude Code\n\nBy Symbiont Systems LLC","parents":["6b4e501ac95d5b7df82b4da407967b83e51d7af8"],"add":127,"del":21,"cadd":127,"cdel":21,"files":7},{"repo":"holocene","hash":"c2bba104802aac02be63aa3489d55f204919be8a","ts":1784762408,"wall":"2026-07-22T19:20","msg":"style: thicker tracks — bump lane/row/gap and fonts","body":"Everything read too small. Scaled the per-track geometry up ~40-50%\nso it reads bigger, not just taller with tiny text.\n\n- LANE_H 44→60, ROW_H 15→22, TRACK_GAP 8→12\n- polity labels 9→11px, track name 11→13px, event dot r 4→5\n- label baselines nudged for the taller rows\n\nAuthored by Rowan Valle; Executed by Claude Code\n\nBy Symbiont Systems LLC","parents":["c2e1fade8bdb9ef49888268775421b7171827e33"],"add":11,"del":11,"cadd":11,"cdel":11,"files":2},{"repo":"mesnada","hash":"35c5d0f1c82c2359b54b1568842f887eda1af6b2","ts":1784762664,"wall":"2026-07-22T19:24","msg":"feat: AI climbs the ladder — bread chain bootstraps (town-redesign AI course)","body":"The economy AI now values a shop by the promotion it unlocks: _toll_progress\nscores any building on the critical path to the settlement's toll good (via\nrecipe_graph.requirements_for), weighted TOLL_WEIGHT — a bakery is worth the\ntier-jump, not just its bread. The scoring was correct but affordability gated\nit to zero (towns are materially destitute), so two balance levers open the\nfirst industrial rung: tier-2 workshop costs (mill/bakery/weaver/sawmill/kiln)\nhalved, and WORKER_GATHER_YIELD 1 -> 2 so materials concentrate faster.\n\nAlso fixes a latent crash: _award_combat_ap KeyError'd on a neutral (player 0)\ndefender, which has no AP pool — now guarded.\n\nMeter, before -> after: no mill/bakery ever built -> mill 13, bakery 6, sawmill\n5, kiln 3; flour/bread/planks climb off flat zero. The production ladder now\nbootstraps unsupervised at tier 2. (Metal chain still needs tier-3 towns — the\nnext push.)\n\n743 pass / 3 skip, ruff clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["15fae6c7f4a1a7f25704da6bc9e3442f97d3b26c"],"add":112,"del":16,"cadd":102,"cdel":6,"files":10},{"repo":"mesnada","hash":"165f5df7bcd7c1c31454c0d5a17c375402cae108","ts":1784836746,"wall":"2026-07-23T15:59","msg":"feat: resource improvements — developed sites yield and regen more","body":"Add the Improvement model so a wild resource hex can become a cultivated\nsite (farm/lumber_yard/fishing_village/flax_field/herb_garden) that\npermanently out-yields and out-regens a raw patch. Worked land can now\nfeed a town's growth instead of being stripped and left dead (§13.4).\n\n- Improvement frozen dataclass + IMPROVEMENTS table (grain/fish/timber/\n  fiber/herbs → their developed forms; finite metals excluded for now)\n- HexResource gains improvement field + yield_mult, effective_regen,\n  can_improve properties and improve() (raises pool ceiling, fills it);\n  regen now uses effective_regen\n- worker auto-gather path multiplies its draw by the site's yield_mult\n- probe_tiers diagnostics for the tier-climb investigation\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["35c5d0f1c82c2359b54b1568842f887eda1af6b2"],"add":103,"del":7,"cadd":103,"cdel":7,"files":4},{"repo":"mesnada","hash":"93ff38d83142f825fe5fecf714e98d8185884b42","ts":1784836767,"wall":"2026-07-23T15:59","msg":"feat: develop action — a pawn cultivates a resource hex into its improvement","body":"A pawn standing on a wild grain/fish/timber/fiber/herbs hex can spend AP\nto develop it (farm/fishing_village/lumber_yard/flax_field/herb_garden),\na one-time investment that permanently multiplies the site's yield, regen\nand pool ceiling. Manual gather now reaps the developed yield too.\n\n- develop_resource(): validates turn/unit/routing/resource-present/\n  can_improve/AP, calls improve(), emits DEVELOP, trains Labour\n- AP_DEVELOP config constant; EventType.DEVELOP + fog-filter coord entry\n- gather_resource multiplies its draw by the site's yield_mult\n- TestDevelopResource (success, event, insufficient-AP, already-improved,\n  non-improvable, no-resource, routing, wrong-player)\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["165f5df7bcd7c1c31454c0d5a17c375402cae108"],"add":147,"del":4,"cadd":147,"cdel":4,"files":5},{"repo":"mesnada","hash":"f60af1037990ada0b52c19555085efe3096186ed","ts":1784837964,"wall":"2026-07-23T16:19","msg":"feat: AI cultivates its food — develops resource sites, food-first (§13.4)","body":"The economic AI now develops the wild resource hexes its pawns stand on,\nturning them into farms/fishing villages/lumber yards. Food sites are\nvalued highest (population growth, hence tier promotion, is bottlenecked\non food) and scaled by proximity to an owned settlement — a field only\nfeeds a town it can reach. A developed food hex near a town out-ranks a\nplain gather, so the AI cultivates once and reaps the tripled harvest\nevery turn after, breaking the subsistence trap that pinned towns below\nthe tier-3 population threshold.\n\n- generate_economic_actions enumerates develop for a pawn on an improvable\n  hex; _score_develop weights food > other, scales by settlement distance,\n  gates on AP; develop dispatched through the AI executor and score match\n- develop_resource exported through game.actions\n- food-first gather priority (grain/fish before construction/metal raws)\n- tests: enumeration, valuation, AP gate, want-band ceiling, and an\n  end-to-end play_ai_turn that cultivates a grain hex into a farm\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["93ff38d83142f825fe5fecf714e98d8185884b42"],"add":120,"del":5,"cadd":120,"cdel":5,"files":6},{"repo":"mesnada","hash":"e15ab5da22e82262e341098af400de33cd755f49","ts":1784846150,"wall":"2026-07-23T18:35","msg":"feat: nutrition-weighted food + civilizational tolls (§13.6)","body":"Raw grain and flour are no longer edible — food must be processed (grain ->\nflour -> bread) or eaten as fish. Each edible good yields nutrition points\n(fish 1, bread 4; game meats land in the next commit); population above\nsubsistence eats nutrition, not unit count, draining perishable raw food\nbefore the dense bread reserve. This ends the grain tug-of-war: grain is now\na pure industrial input, so the mill and the dinner table never contend, and\nthe feed-first turn-order hack is reverted (production before population again\n— bread baked this turn feeds people the same turn).\n\nPromotion tolls become CIVILIZATIONAL goods, never food, so no good is drawn\ntwice (once as food, once as toll): 2->3 cloth, 3->4 ale, 4->5 tools,\n5->6 medicine — each buildable within its tier's slots. Growth = feed people;\npromotion = make finer goods. Village slot budget 4 -> 5 for headroom.\n\n- config: FOOD_NUTRITION table; POP_FOODS derived from it (grain out);\n  TIER_TOLL/NEED_RATE/NEEDS_GOODS -> cloth/ale/tools/medicine\n- turn.py: nutrition-weighted _process_population + _consume_food (raw first);\n  revert feed-first reorder\n- ai/economy.py: FOOD_RESOURCES derived from the nutrition table (grain out);\n  gather priority puts real food first, grain mid-list as an industrial raw\n- settlement.py: Village building_slots 4 -> 5\n- tests: grain no longer feeds (test_grain_is_not_food); bread is dense food\n  (test_bread_is_dense_food); toll/needs/slot tests updated to the new ladder\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["f60af1037990ada0b52c19555085efe3096186ed"],"add":110,"del":50,"cadd":110,"cdel":50,"files":9},{"repo":"mesnada","hash":"4d81c5c4b290a36f5db3667c77d068dc53b49b33","ts":1784847906,"wall":"2026-07-23T19:05","msg":"feat: game meats + the hunting skill (§13.6)","body":"Add a roster of huntable wild meat and make hunting a skill check that\nmisses some of the time. Six game types: big game (venison/boar/elk,\nnutrition 2, big herds pool 10-14, slow to recover) and small game\n(hare/fowl/grouse, nutrition 1, thin pool 4-6, quick to bounce back),\nplaced on their biomes by the existing terrain-driven loop and tradeable\nlike any raw (market anchors derive from sell_price).\n\nHunting is a graded skill (perception + dexterity) that trains with use.\nA hunt succeeds with probability base(0.45) + skill/100 * span(0.45) minus\nthe quarry's wariness (big game harder), clamped to [0.05, 0.95] and rolled\noff the reproducible state.rng. A miss yields no meat and leaves the herd\nintact (the game flees); the skill trains on every attempt, hit or miss.\nThis gives towns an abundant-but-exhaustible early larder — overhunting\nstrips a forest of game for a long while.\n\nThe AI hunts with no special-casing: a worker dispatched to a game hex is\nrouted by _worker_harvest to the hunt roll instead of a deterministic\ngather, so it hunts, misses, and learns like anyone.\n\n- hex_resource: 6 game ResourceTypes + configs (renewable, not developable)\n- config: RAW_COMMODITIES + COMMODITY_DEPTH_GROUP + FOOD_NUTRITION meats;\n  hunting constants; \"hunting\" in SKILL_GOVERNING\n- gathering: hunt_success_prob, resolve_hunt, hunt_resource action\n- turn: _worker_harvest routes game -> hunt, else gather\n- events/main: HUNT event + fog-filter coord key; frontend meat dot colors\n- tests: hit/miss/deplete/AP/skill-training/non-game/difficulty; game\n  configs; biome placement; commodity counts\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["e15ab5da22e82262e341098af400de33cd755f49"],"add":311,"del":15,"cadd":311,"cdel":15,"files":12},{"repo":"mesnada","hash":"df9d59a1a05948984e1e46c0a575cf56bf8ac91f","ts":1784847919,"wall":"2026-07-23T19:05","msg":"tools: probe/trace diagnostics for the nutrition + game model","body":"Update the economy probes to the §13.6 model so they read the real gates:\nfood NUTRITION on hand vs need (not raw unit counts), the actual toll good\nand its stock/streak, the toll input (fiber), plus a game census (huntable\nmeat left on the map). trace_village follows one settlement turn by turn to\nshow the food flow (fish / game / bread) and the toll chain — the tool that\npinpointed the two remaining AI-logistics blockers.\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["4d81c5c4b290a36f5db3667c77d068dc53b49b33"],"add":93,"del":6,"cadd":93,"cdel":6,"files":2},{"repo":"mesnada","hash":"762664013ecbd96f7a9b375b4ecae89a131f7554","ts":1784848082,"wall":"2026-07-23T19:08","msg":"docs: session handoff — food model works, AI logistics is the next front","body":"Nutrition food + game/hunting shipped and proven: a town now feeds itself\noff fish + hunted game and climbs to pop 10.7 (was pinned at subsistence).\nMeter still 0/14 — blocked on town promotions, blocked on an AI-logistics\ngap (gather toll/food inputs, build a food buffer), deferred as tuning.\n\nAuthored by Rowan Valle; Executed by Claude Code.","parents":["df9d59a1a05948984e1e46c0a575cf56bf8ac91f"],"add":110,"del":87,"cadd":110,"cdel":87,"files":1},{"repo":"hexa","hash":"9a8d02b9e0c4bdcbd6707729df67424c672ad8fb","ts":1785374169,"wall":"2026-07-29T21:16","msg":"docs: Hexa M0 spec, README, start script","body":"Persistent hex world on the Mesnada engine lineage. Python policy over\nRust mechanism (PyO3 seam). Plan of record in .claude/hexa-m0-spec.md.","parents":[],"add":196,"del":0,"cadd":180,"cdel":0,"files":4},{"repo":"hexa","hash":"63f81e098bddea0b41295082e027135b45a0a555","ts":1785374185,"wall":"2026-07-29T21:16","msg":"feat: hexpath Rust crate (PyO3 A*) + WebSocket shard server","body":"Rust mechanism under Python policy: A* over the hex cost grid, parity-tested\nagainst the pure-Python reference (equal cost, legal steps). Shard: asyncio\nwebsockets, name+token sessions (alpha only, not auth), server-side pathing\nof move intents, per-player visible-set broadcast each tick, snapshot on\ninterval and SIGTERM/SIGINT.","parents":["f899fe86b043875a901db034e99379f6451c4c18"],"add":529,"del":0,"cadd":357,"cdel":0,"files":7},{"repo":"hexa","hash":"f151718029b89b1039e81f3eccefc81b83e9471a","ts":1785374185,"wall":"2026-07-29T21:16","msg":"feat: PixiJS client — Mesnada's visual language","body":"Pointy-top hexes (HEX_SIZE 64), Mesnada terrain palette and cloakedPawn\nsprite, owner tints, click-to-move with drag-pan/wheel-zoom camera, pawn\nHUD, smooth walk easing. vite 6.4.3 (esbuild dev-server advisory cleared).","parents":["63f81e098bddea0b41295082e027135b45a0a555"],"add":1692,"del":0,"cadd":464,"cdel":0,"files":9},{"repo":"hexa","hash":"f899fe86b043875a901db034e99379f6451c4c18","ts":1785374185,"wall":"2026-07-29T21:16","msg":"feat: world domain — hexes, terrain, worldgen, pawns, tick, persistence","body":"Pure deterministic domain: cube-coord hex math matching Mesnada, terrain\ncosts inherited verbatim, seeded worldgen behind a swappable seam, per-pawn\naction-timer movement (travel time before arrival), atomic JSON snapshots,\nvision-radius visibility. 27 tests, test-first.","parents":["9a8d02b9e0c4bdcbd6707729df67424c672ad8fb"],"add":912,"del":0,"cadd":912,"cdel":0,"files":20},{"repo":"hexa","hash":"e993f3537ba0dd3a5349585cd5215850299c1c36","ts":1785374211,"wall":"2026-07-29T21:16","msg":"docs: session handoff — M0 complete, visual check pending","body":"","parents":["f151718029b89b1039e81f3eccefc81b83e9471a"],"add":31,"del":0,"cadd":31,"cdel":0,"files":1},{"repo":"hexa","hash":"209aa5f3bfaac5e1b336302be378b982621e3bc0","ts":1785374683,"wall":"2026-07-29T21:24","msg":"feat: textured hex terrain — Mesnada's tile art","body":"Six terrain textures copied from Mesnada, each baked once into a\nhex-clipped tile (mask applied at bake, not per hex), so 1,801 terrain\nsprites share six textures and batch. Flat palette remains the fallback.","parents":["e993f3537ba0dd3a5349585cd5215850299c1c36"],"add":54,"del":8,"cadd":54,"cdel":8,"files":7},{"repo":"hexa","hash":"8f5d3036f1765f40088048bb1fb1b7eb055b2200","ts":1785445490,"wall":"2026-07-30T17:04","msg":"feat: gear live — starter kits, walk speed, vision, equip over the wire","body":"Pawns spawn as Mesnada archetypes (swordsman/archer/man-at-arms/skirmisher),\nstats rolled deterministically from (seed, pawn id). Walk time scales with\neffective movement (encumbrance slows, speed strides); gear terrain overrides\nconsulted per step. Vision radius is per-pawn (Perception + spy glass).\nProtocol: everyone sees worn gear, only the owner sees bag + stat sheet;\nequip/unequip messages. E2E smoke moved into the repo and extended.","parents":["f5825333aded4386f198b849cb1f3557d9ff17ab"],"add":269,"del":21,"cadd":269,"cdel":21,"files":8},{"repo":"hexa","hash":"f5825333aded4386f198b849cb1f3557d9ff17ab","ts":1785445490,"wall":"2026-07-30T17:04","msg":"feat: gear domain — Mesnada's armour/weapons/gear system ported","body":"StatBlock (9 innate stats, birth-rolled), effective_skill (SKILL_GOVERNING +\naptitude floor), and the get_effective_stats resolver: attack from\nSmash/Blade/Aim, defense from Brace/Evade/Toughness, HP from Endurance,\nmovement from Speed, vision from Perception, gear layered x GEAR_STAT_SCALE,\nweight/encumbrance, gear-granted skills, terrain overrides, crit selection.\n35 item + 17 loadout JSONs shared verbatim from Mesnada. Pawn bag/gear with\nequip/unequip (no slot limits — Mesnada rule). Deviations documented:\nmin_rank dormant, pawn-carried bag, vision on VISION_RADIUS base. 17 new\ntests, parity values hand-derived from Mesnada constants.","parents":["209aa5f3bfaac5e1b336302be378b982621e3bc0"],"add":1603,"del":4,"cadd":533,"cdel":4,"files":59},{"repo":"hexa","hash":"a67ca2b6f85387268b30a9ce9070752a9dccbcd1","ts":1785445492,"wall":"2026-07-30T17:04","msg":"feat: gear on the board — 110-sprite mapping + gear HUD","body":"spriteMap ported from Mesnada (SPRITE_MAP + resolveGearKey verbatim,\nfilename-based fallback chain); unit textures lazy-loaded and swapped when\nkit changes. Art untinted — ownership reads from label color. HUD: selected\npawn's stat sheet, worn list (doff), bag (don). Spec ladder updated.","parents":["8f5d3036f1765f40088048bb1fb1b7eb055b2200"],"add":324,"del":20,"cadd":324,"cdel":20,"files":116},{"repo":"hexa","hash":"50a8c80f422b3586f88382c3e36f604a03965172","ts":1785445532,"wall":"2026-07-30T17:05","msg":"docs: handoff — gear system shipped","body":"","parents":["a67ca2b6f85387268b30a9ce9070752a9dccbcd1"],"add":10,"del":5,"cadd":10,"cdel":5,"files":1},{"repo":"hexa","hash":"f65d303d228d3b1e6f3ff09a9dee7a6674cf3d08","ts":1785446046,"wall":"2026-07-30T17:14","msg":"feat: lasso multi-select — left-drag draws a loop, catches your pawns","body":"Freeform lasso (true lasso, not a marquee): left-drag traces a gold loop in\nworld space; on release, your pawns inside the polygon (ray-cast test)\nbecome the selection. Left tap still single-selects or marches the whole\nselected group to the tapped hex; camera pan moves to right-drag, wheel\nzoom unchanged. HUD shows the group count; gear sheet appears for a single\nselection only.","parents":["50a8c80f422b3586f88382c3e36f604a03965172"],"add":120,"del":34,"cadd":120,"cdel":34,"files":2},{"repo":"hexa","hash":"ba32418c860b9571104f0f262c73fd0299d82412","ts":1785446138,"wall":"2026-07-30T17:15","msg":"fix: drag-select is a marquee box, not a freeform lasso","body":"Standard RTS behavior (Kenshi-style): left-drag draws a gold selection\nrectangle; your pawns inside its bounds become the group. Same tap/march,\nright-drag pan, and wheel zoom as before.","parents":["f65d303d228d3b1e6f3ff09a9dee7a6674cf3d08"],"add":34,"del":40,"cadd":34,"cdel":40,"files":2},{"repo":"hexa","hash":"6fcac4f53a21469c11ebf7f373941e03b6c28788","ts":1785446829,"wall":"2026-07-30T17:27","msg":"fix: new orders preserve the stride in flight — spam-click freeze killed","body":"Pawn.order() no longer cancels the pending step; the pawn finishes the\nstride it's in, then follows the new route. Routes are pathed from\nroute_origin() (pending or hex) so re-orders never rubber-band. Regression\ntest proves a pawn re-clicked every half-second arrives in exactly the same\ntick count as an undisturbed one (previously it never moved at all).\nTargeting the origin yields an empty route: the de facto stop command.","parents":["ba32418c860b9571104f0f262c73fd0299d82412"],"add":51,"del":8,"cadd":51,"cdel":8,"files":3},{"repo":"hexa","hash":"952461e5c754a8219afd8bb94254a99ddb2d2451","ts":1785446899,"wall":"2026-07-30T17:28","msg":"fix: path cache identity + per-pawn terrain cost overrides in routing","body":"_grid_for keyed the native grid on a bare id(terrain) — a recycled address\ncould serve a stale grid; it now holds a strong reference and compares\nidentity, which a live object makes sound. find_path/a_star_python accept\ncost_overrides (terrain type -> per-pawn cost, 0 = impassable), so routing\nagrees with the tick's gear terrain overrides; overridden pawns take the\nPython reference path, default pawns keep the Rust grid. The move handler\npasses effective_stats(pawn).terrain_move_cost.","parents":["6fcac4f53a21469c11ebf7f373941e03b6c28788"],"add":95,"del":15,"cadd":95,"cdel":15,"files":3},{"repo":"hexa","hash":"7622801ad898f77d1d5c09f84dd0121c37b3ab8b","ts":1785447282,"wall":"2026-07-30T17:34","msg":"fix: true walk interpolation; selection clearing sticks","body":"Pawns now carry step_ticks (serialized, on the wire): the client estimates\nthe shard tick between state messages and places walking sprites linearly\nbetween hex centers by actual step progress — continuous walking replaces\nthe ease-to-destination hop-and-wait. One-time auto-select moved from\nonState (which resurrected cleared selections every 250 ms) to onWelcome.\nE2E smoke: mid-walk redirect scenario added; teardown hardened so a phase\nfailure is never masked by shutdown timeout. Plan of record persisted at\n.claude/plans/hexa-pathfinding-fixes.md.","parents":["952461e5c754a8219afd8bb94254a99ddb2d2451"],"add":174,"del":16,"cadd":173,"cdel":16,"files":10},{"repo":"hexa","hash":"84944af405697b0fdc6822724df552c852b3c854","ts":1785447317,"wall":"2026-07-30T17:35","msg":"docs: handoff — pathfinding B1-B5 fixed","body":"","parents":["7622801ad898f77d1d5c09f84dd0121c37b3ab8b"],"add":14,"del":3,"cadd":14,"cdel":3,"files":1},{"repo":"hexa","hash":"4bcbc311936aec2703fdbba695689dc817d80bb0","ts":1785447690,"wall":"2026-07-30T17:41","msg":"feat: unreachable clicks walk to closest approach (both A* twins)","body":"An impassable or unreachable goal no longer dead-ends: A* returns the path\nto the reachable hex nearest the goal (RTS walk-toward-the-click), chosen\nat pop time by (heuristic, cost) with first-found ties — pop order is\nFIFO-deterministic in both implementations, so Python and Rust settle on\nthe identical endpoint (parity-tested over passable AND impassable goals).\nFully-boxed-in returns [start]: the pawn stays put, no error spam.","parents":["84944af405697b0fdc6822724df552c852b3c854"],"add":68,"del":24,"cadd":68,"cdel":24,"files":3},{"repo":"hexa","hash":"341bd8aca2da7e21af9d5a8f227735c795a03ca2","ts":1785447982,"wall":"2026-07-30T17:46","msg":"feat: formation spread on group moves","body":"world/formation.py: passable slots spiral out from the click (target first),\ngreedy nearest-first assignment, deterministic ties — the group settles on\ndistinct hexes with minimal crossing instead of stacking on one. The move\nmessage accepts pawns[] for groups (single-pawn form unchanged); the client\nsends one group order. Composes with closest-approach: an impassable click\nseats the squad on its ring. A* and smoke phase1 refactored under the\ncomplexity gate (helpers, no suppressions). 6 formation tests; smoke gains\nthe formation scenario and persists the settled position across restart.","parents":["4bcbc311936aec2703fdbba695689dc817d80bb0"],"add":318,"del":106,"cadd":318,"cdel":106,"files":8},{"repo":"hexa","hash":"cd82da953223ad08bc634e4091856ee855175a57","ts":1785448001,"wall":"2026-07-30T17:46","msg":"docs: handoff — pathfinding enhancements shipped","body":"","parents":["341bd8aca2da7e21af9d5a8f227735c795a03ca2"],"add":12,"del":4,"cadd":12,"cdel":4,"files":1},{"repo":"hexa","hash":"4d744f37523e9ef50d28bb87f8071fabdb3c9f4c","ts":1785448441,"wall":"2026-07-30T17:54","msg":"feat: one pawn per hex — occupancy, reservation, wait/detour/give-up","body":"The world invariant: a hex holds one pawn. A walking pawn reserves both its\nhex and the hex it is entering, so arrivals never collide. A pawn whose\nnext step is occupied waits BLOCKED_WAIT_TICKS (2 s), then detours around\nthe blocker via blocked-aware A* (Python path — the native grid is\nimmutable, occupancy isn't), or stands down when the blocker squats its\nfinal destination or no detour exists. Face-to-face swaps refuse cleanly;\ncontention resolves in deterministic pawn-id order. Spawning refuses a full\nworld (join gets 'world is full') instead of stacking the center. Five\noccupancy tests, incl. a four-way charge asserting the invariant holds\nevery tick.","parents":["cd82da953223ad08bc634e4091856ee855175a57"],"add":170,"del":19,"cadd":170,"cdel":19,"files":7},{"repo":"hexa","hash":"9a9d2ec7c813da1c70225d51b835e3f5831ea032","ts":1785448529,"wall":"2026-07-30T17:55","msg":"feat: snapshot migration — co-located pawns nudged to free hexes on load","body":"Pre-invariant worlds may hold stacked pawns; on load the shard relocates\ncollisions to the nearest free passable hex (deterministic, pawn-id order)\nand cancels colliding reservations. Clean worlds load untouched — walkers\nkeep walking.","parents":["4d744f37523e9ef50d28bb87f8071fabdb3c9f4c"],"add":57,"del":0,"cadd":57,"cdel":0,"files":3},{"repo":"hexa","hash":"1ae8ac74e4f5a55b2c2ce3adbd9c54f32032ca1f","ts":1785448818,"wall":"2026-07-30T18:00","msg":"fix: forest tile noise — proper minification (box downscale + mipmaps)","body":"Root cause: 1024px art squeezed to a 141px baked tile in one bilinear pass\n(~4 of every 53 texels sampled), then minified again by the camera —\nhigh-frequency textures (forest canopy) turned to static; low-frequency\nwashes survived, which is why only forest read as broken. Fix at both\nstages: assets box-downscaled 2:1 to 512 (exact pixel-art average, 4x\nsmaller files), sources mipmapped before the bake, and the baked tiles\nmipmapped for far zoom (textureSourceOptions verified against pixi 8.6.6\nd.ts).","parents":["9a9d2ec7c813da1c70225d51b835e3f5831ea032"],"add":12,"del":1,"cadd":12,"cdel":1,"files":7},{"repo":"hexa","hash":"97837e876b28adec7797350f56188fd2b9e8bf7b","ts":1785449147,"wall":"2026-07-30T18:05","msg":"fix: terrain went black — drop GPU mipmap flags, downscale stepwise","body":"The mipmap attempt allocated mip levels on the one-shot baked render\ntexture that nothing ever filled; the minifying sampler read empty black\nlevels and every tile vanished (operator screenshot). Boring fix instead:\nhalve the source texture stepwise (512 -> 256) so the final bake reduction\nis <= 2x — plain textures, no sampler flags, intermediates destroyed. The\n512 box-downscaled assets from the prior commit stand.","parents":["1ae8ac74e4f5a55b2c2ce3adbd9c54f32032ca1f"],"add":26,"del":13,"cadd":26,"cdel":13,"files":1},{"repo":"hexa","hash":"c59ffdc04640c34d68aa7b5d72dc1bca687e1d24","ts":1785449331,"wall":"2026-07-30T18:08","msg":"fix: page freeze — generateTexture ignores the target's own transform","body":"halve() passed a bare sprite scaled 0.5; generateTexture renders its target\nas a root and ignores the target's own transform, so the 'halved' texture\ncame back full-size and the downscale loop spun forever on the main thread.\nWrapped in a Container (child transforms are honored) with an explicit\nframe, plus a 4-iteration hard cap so any future bug here degrades quality\ninstead of hanging the page.","parents":["97837e876b28adec7797350f56188fd2b9e8bf7b"],"add":15,"del":4,"cadd":15,"cdel":4,"files":1},{"repo":"hexa","hash":"ae4cc8e1395d13884c590c39bfeb8f7b2916b840","ts":1785450221,"wall":"2026-07-30T18:23","msg":"feat: formations — spread/file/wedge/line, gear-aware ranks, squad memory","body":"Shapes are rank-ordered offset generators (dispatch table) rotated exactly\nto the six hex facings; facing snaps from the squad-centroid march vector.\nTerrain-fit slides blocked slots to the nearest free passable hex, so\nshapes degrade toward a blob on broken ground and reform in the open.\nAssignment is gear-aware: melee-tagged pawns claim the front ranks (wedge\napex, head of file), ranged the rear; single-rank shapes fall back to pure\nproximity. The squad remembers its formation (Player.formation, persisted,\nset_formation message, echoed in state). Client: glyph picker when multiple\npawns are selected. Protocol gains 'moving' (route-in-progress) — the HUD\nidle label was lying about pawns between steps, and the smoke settle check\nwas racing it. 12 formation tests; smoke marches a wedge.","parents":["c59ffdc04640c34d68aa7b5d72dc1bca687e1d24"],"add":351,"del":109,"cadd":351,"cdel":109,"files":11},{"repo":"hexa","hash":"0b7e584535dbf13c0faa2611fe31c858efc48563","ts":1785450250,"wall":"2026-07-30T18:24","msg":"docs: handoff — formations shipped","body":"","parents":["ae4cc8e1395d13884c590c39bfeb8f7b2916b840"],"add":10,"del":0,"cadd":10,"cdel":0,"files":1},{"repo":"hexa","hash":"802f5319ab5866c2b91175bbc130897afb8239fb","ts":1785450325,"wall":"2026-07-30T18:25","msg":"feat: arrow-key camera panning","body":"Held arrows pan continuously, frame-rate independent (scaled by ticker\ndelta), page scroll suppressed, ignored while typing in the join field,\npressed-set cleared on window blur so alt-tab can't wedge a key.","parents":["0b7e584535dbf13c0faa2611fe31c858efc48563"],"add":22,"del":0,"cadd":22,"cdel":0,"files":1},{"repo":"hexa","hash":"9558c0a732ac0623ec0314537e74c193372bde20","ts":1785450523,"wall":"2026-07-30T18:28","msg":"feat: roster-number selection — digit selects a pawn, Shift/Ctrl+digit toggles","body":"Pawns carry 1-based roster numbers (join order), shown in the HUD rows and\non their board labels. Plain digit selects that pawn alone; Shift or Ctrl\n(or Meta) + digit toggles it in and out of the multi-selection. e.code is\nused instead of e.key so Shift+1 doesn't arrive as '!'; Shift is the\nreliable modifier since browsers reserve some Ctrl+digit combos for tab\nswitching. Ignored while typing in the join field.","parents":["802f5319ab5866c2b91175bbc130897afb8239fb"],"add":25,"del":3,"cadd":25,"cdel":3,"files":2},{"repo":"hexa","hash":"edcc117545a73a5f8162e076057661f69fe503b7","ts":1785450670,"wall":"2026-07-30T18:31","msg":"fix: multi-select is Shift+digit only — Ctrl/Meta/Alt combos left to the browser","body":"","parents":["9558c0a732ac0623ec0314537e74c193372bde20"],"add":4,"del":4,"cadd":4,"cdel":4,"files":1},{"repo":"hexa","hash":"c9b9522d2d5c954a808f3b2b2681839f788af570","ts":1785451250,"wall":"2026-07-30T18:40","msg":"feat: combat domain — Kenshi stances over Mesnada damage math","body":"Stances: passive (never fights), alert (default; stands ground, swings at\nadversaries in weapon range), bellicose (hunts the nearest adversary inside\nits perception bubble — effective vision — chasing via the full pathfinding\nstack). Manual orders always override seeking (auto_route flag). Damage is\nMesnada Chunk B2: melee/ranged by distance, atk*C/(C+def) mitigation,\ndeterministic seed/tick/id variance — replayable, no RNG state. At 0 hp a\npawn is DOWNED, not dead: collapses in place (hex stays held), attackers\ndisengage, passive regen stands it up at 25% max. Swings measure from where\nthe pawn stands — the tests caught mid-stride reach. Tick pipeline:\nstances -> movement -> combat -> recovery, one effective-stats resolve per\npawn per tick shared across systems. 10 combat tests.","parents":["edcc117545a73a5f8162e076057661f69fe503b7"],"add":368,"del":9,"cadd":368,"cdel":9,"files":7},{"repo":"hexa","hash":"5c0bbe1b02b1e6c8c9b0b91bb8924c23b6e5dfc0","ts":1785451547,"wall":"2026-07-30T18:45","msg":"feat: combat on the wire — stances, HP bars, spawn separation","body":"set_stance message (per-pawn, ownership-checked; leaving bellicose calls\noff the chase). Pawn views carry hp/max_hp/stance/downed publicly — wounds\nare visible on the body, Kenshi-style. Client: stance glyph row (passive/\nalert/bellicose) for any selection, health bars above wounded pawns\n(Mesnada's colors, hidden at full), downed pawns ghost at 45% alpha, HUD\nrows show stance + DOWN. New players now spawn SPAWN_SEPARATION hexes from\nstrangers — alert-by-default plus adjacent spawns meant every world opened\nwith a brawl. Smoke: a bellicose archer hunts a passive bob pawn over the\nwire, draws blood, and stands down.","parents":["c9b9522d2d5c954a808f3b2b2681839f788af570"],"add":162,"del":18,"cadd":162,"cdel":18,"files":9},{"repo":"hexa","hash":"533319b5fdab4b430319109a45fa613d0c4ca89f","ts":1785451636,"wall":"2026-07-30T18:47","msg":"feat: SVG icons for formation and stance pickers","body":"Unicode glyphs rendered as font-roulette; replaced with inline SVG on\ncurrentColor. Formation icons draw the actual slot pattern (spread ring,\nfile column, wedge triangle, line rank); stances read as open circle /\nshield / crossed blades. Row status uses the same stance icon.","parents":["5c0bbe1b02b1e6c8c9b0b91bb8924c23b6e5dfc0"],"add":18,"del":7,"cadd":18,"cdel":7,"files":2},{"repo":"hexa","hash":"d3b6b44ea5fb65f5b73dfcf746c20d0c23ae26cc","ts":1785451656,"wall":"2026-07-30T18:47","msg":"docs: handoff — combat stances shipped","body":"","parents":["533319b5fdab4b430319109a45fa613d0c4ca89f"],"add":11,"del":0,"cadd":11,"cdel":0,"files":1},{"repo":"hexa","hash":"7623f519a94cbbd31702a7999cac39b9bab2f79d","ts":1785454042,"wall":"2026-07-30T19:27","msg":"feat!: the 3D pivot, phase 1 — continuous meters replace the hex grid","body":"The world is real space now: float (x,z) positions + headings, waypoint\nroutes walked at m/s from stats x biome speed, radius separation with\nconvoy rules (moving blockers are followed patiently; stationary ones get\na deterministic sidestep, then surrender). The nav lattice survives\ninvisibly: A* over 4m cells, string-pulled to smooth waypoints (Kenshi\nnavmesh pattern; pure Python — Rust returns when profiling says so).\nWorldgen produces biome + ELEVATION per cell (128x128, 512m square).\nRanges and vision are meters (melee 2.5m, longbow 45m, vision 55m+).\nFormations are vector offsets with continuous facing. Snapshot v2 —\nhex-era snapshots archived, not loaded. hexes.py and the hex tests are\ndeleted; 63 tests rewritten green on first full run.\n\nHardening from the smoke's honest findings: the tick loop schedules\nabsolutely, survives (and loudly logs) tick exceptions, and slow consumers\nare EVICTED on send timeout — one stalled client used to freeze the whole\nshard. Name canon per operator: Hexa is the sixth body in the cosmic\nsystem of the in-game universe.\n\nThe 2D hex client is now protocol-incompatible (sanctioned: playability\nduring the rework waived).","parents":["d3b6b44ea5fb65f5b73dfcf746c20d0c23ae26cc"],"add":1316,"del":1449,"cadd":1316,"cdel":1449,"files":30},{"repo":"hexa","hash":"ba16a979e24a9a764b5c0e6d6e90a9803e2677ae","ts":1785454071,"wall":"2026-07-30T19:27","msg":"docs: handoff — 3D pivot phase 1 shipped, engine choice open","body":"","parents":["7623f519a94cbbd31702a7999cac39b9bab2f79d"],"add":14,"del":0,"cadd":14,"cdel":0,"files":1},{"repo":"hexa","hash":"26fff12830abbab96349f4284d77771e40ddaa8a","ts":1785519742,"wall":"2026-07-31T13:42","msg":"docs: handoff — Hexa Classic worktree on the classic branch","body":"","parents":["ba16a979e24a9a764b5c0e6d6e90a9803e2677ae"],"add":11,"del":0,"cadd":11,"cdel":0,"files":1},{"repo":"hexa","hash":"7851626ab706dff41c54d1d0d673c252ae5a8bc6","ts":1785613330,"wall":"2026-08-01T15:42","msg":"feat: client3d skeleton — Three.js ground, camera rig, capsule pawns (3D Phase 2)","body":"","parents":["26fff12830abbab96349f4284d77771e40ddaa8a"],"add":2374,"del":3,"cadd":1135,"cdel":3,"files":12},{"repo":"hexa","hash":"62e6d2ca3506cde9f22298120668b8d3946964e1","ts":1785613385,"wall":"2026-08-01T15:43","msg":"docs: handoff + pivot plan — Three.js chosen, Phase 2 client3d built","body":"","parents":["7851626ab706dff41c54d1d0d673c252ae5a8bc6"],"add":32,"del":5,"cadd":32,"cdel":5,"files":2},{"repo":"hexa","hash":"5acfb66a6c59212031221e7d2318f4c413ef56d2","ts":1785614316,"wall":"2026-08-01T15:58","msg":"fix: float-and-wade — no pawn is ever stranded on impassable ground","body":"Two compounding defects drowned a pawn permanently: the body-block sidestep\ninserted its dodge waypoint with no passability check (stepping pawns into\nwater), and zero biome speed wiped the waypoints of any pawn standing on\nimpassable ground, discarding every escape order.\n\nSidestep now validates the dodge against terrain and world bounds (tries\nthe far side, else skips). Standing on impassable ground now yields\nIMPASSABLE_ESCAPE_FACTOR wade speed instead of paralysis — routes still\nnever lead into water; pawns just float and crawl back out. A learned swim\nskill scaling this factor is future design (skills milestone).","parents":["62e6d2ca3506cde9f22298120668b8d3946964e1"],"add":90,"del":15,"cadd":90,"cdel":15,"files":3},{"repo":"hexa","hash":"3530f335c1bd61acbf82f83eec0a8367d4ce583d","ts":1785615053,"wall":"2026-08-01T16:10","msg":"feat: KayKit rigged characters — gear-driven bodies, props, animations (3D Phase 3)","body":"Five CC0 Adventurers rigs (Kay Lousberg) vendored with license. The body\nmodel is chosen from gear (arcana -> Mage, ranged -> Rogues, armor class ->\nKnight/Barbarian, shield bumps the fallback to Knight); weapons are the\nrigs' own hand-slot meshes toggled by item family; the attack clip follows\nthe main hand. Motion from the wire: downed lies, fighting swings, speed\npicks walk or run. Every node and clip name verified against the GLB\ninventories; all 35 items resolve (CHARACTER-PARITY-OK).","parents":["7b422efabc1190619bac7cfeb889cdf464b20f7f"],"add":395,"del":88,"cadd":362,"cdel":88,"files":10},{"repo":"hexa","hash":"7b422efabc1190619bac7cfeb889cdf464b20f7f","ts":1785615053,"wall":"2026-08-01T16:10","msg":"feat: 'fighting' flag on the pawn view — swung within ATTACK_TICKS (attack-animation cue)","body":"","parents":["5acfb66a6c59212031221e7d2318f4c413ef56d2"],"add":30,"del":2,"cadd":30,"cdel":2,"files":2},{"repo":"hexa","hash":"4d0f997f58ff833cc7bf912bb4f91c4f88fc12b4","ts":1785615261,"wall":"2026-08-01T16:14","msg":"docs: handoff — float-and-wade fix + Phase 3 characters","body":"","parents":["3530f335c1bd61acbf82f83eec0a8367d4ce583d"],"add":19,"del":1,"cadd":19,"cdel":1,"files":1},{"repo":"hexa","hash":"47eef2ffc3c5dbc4b48f6635ebd2847d16de8e06","ts":1785617180,"wall":"2026-08-01T16:46","msg":"feat: worldgen v2 — a landscape descended from process, not scattered","body":"v1 rolled a weighted die per cell and smoothed it: biomes had no causal\ntie to elevation, water sat wherever the die said, and there was no\ndrainage, coastline, or watershed. v2 runs the pipeline the literature\nconverges on (research/procedural-worldgen-terrain-synthesis.md):\n\n  fractal surface -> erosion -> hydrology -> climate classification\n\n- world/noise.py: seeded Perlin gradient noise, fBm, ridged multifractal,\n  domain warping. Pure Python, no new dependency.\n- Elevation: warped fBm with ridges biting only above an onset, pow\n  redistribution for flat valleys, square-bump island shaping so the map's\n  rim is coastline instead of an invisible wall, plus a gentle continental\n  lift over the middle.\n- Erosion: droplet/snowball method (Beyer, Talle) — sediment exchanged\n  behind the droplet, brush-weighted, interior-clamped.\n- Hydrology: one-pass flow accumulation carves a connected river network.\n- Climate: moisture diffused from open water, biomes read off a Whittaker\n  elevation x slope x moisture table.\n\nThree findings the tests forced, each a defect caught before shipping:\nsea level must be CALIBRATED by percentile (a fixed waterline drowned the\nworld at 72% ocean); relief must be walkable (88 m over 512 m made every\nslope alpine and erased plains); and connectivity must be VERIFIED, not\nhoped for (seed 42 spawned onto a 32-cell islet) — worlds now carve passes\nand causeways until the spawn reaches most walkable ground.\n\nThe six-biome vocabulary is unchanged: it is load-bearing across server\nwalk speeds, Mesnada item terrain overrides, and client vertex colors.\nThe waterline now travels on the wire so the client stops assuming it.\n\n83 server tests green (10 noise, 11 worldgen incl. the connectivity gate);\n12 seeds verified 100% spawn connectivity with a stable biome mix.","parents":["4d0f997f58ff833cc7bf912bb4f91c4f88fc12b4"],"add":1198,"del":82,"cadd":1198,"cdel":82,"files":9},{"repo":"hexa","hash":"77ed8e3a848729552711ca1a63e5e98e4220dec2","ts":1785618029,"wall":"2026-08-01T17:00","msg":"feat: dressing — ground detail, vegetation, day/night (3D Phase 4)","body":"- terrain: slope-driven bedrock blending so cliffs read as cliffs, a\n  runtime-drawn grain texture (no asset to ship, no CDN to reach), and\n  per-vertex color jitter to break flat-shaded uniformity.\n- vegetation.ts: instanced conifers, swamp trees, rocks, and grass tufts\n  scattered from a seeded PRNG by biome and slope — one draw call per prop\n  type, identical every session. Geometry is procedural rather than\n  vendored: no CC0 nature pack was reachable through a trustworthy mirror,\n  and the chunky low-poly silhouettes sit naturally beside the KayKit\n  characters. Real GLTF props drop in at the makeX() factories.\n- sky.ts: a 20-minute day driven by the SHARD tick, not the browser clock,\n  so every player under the same sky sees the same sun. Sky, sun, ambient,\n  and fog colors interpolate around a keyframe table; night stays moonlit\n  rather than black — unplayable dark is worse than unrealistic light.\n- persist: loaded pawns are rehomed off impassable ground. A saved position\n  is a claim about a world that may no longer exist; worldgen v2 would\n  otherwise have dropped the existing player's pawns into open ocean.\n\n85 server tests green. Client verified headless: tsc, vite build, terrain\ncoordinate parity, character mapping parity, and a dressing harness\n(sky continuity around the clock incl. the midnight seam, no sub-horizon\nsun, night stays lit, scatter deterministic, no prop in water or floating).","parents":["47eef2ffc3c5dbc4b48f6635ebd2847d16de8e06"],"add":578,"del":14,"cadd":578,"cdel":14,"files":6},{"repo":"hexa","hash":"ee46c23cc503d6509e6785f8f73cb9cd0e63c331","ts":1785618103,"wall":"2026-08-01T17:01","msg":"docs: handoff — worldgen v2 + Phase 4 dressing; world-size question open","body":"","parents":["77ed8e3a848729552711ca1a63e5e98e4220dec2"],"add":47,"del":7,"cadd":47,"cdel":7,"files":1},{"repo":"hexa","hash":"57f2bbc31d67ef3e459dacc0aea048d66ef0061a","ts":1785619165,"wall":"2026-08-01T17:19","msg":"feat: the globe — cube-sphere foundation (sphere phase 1)","body":"Operator's order: Hexa becomes a true 20 km-radius body — the sixth body of\nthe cosmic system, made literal. One permanent world, generated once and\nthereafter loaded. Plan of record: .claude/plans/hexa-spherical-world.md\n\nworld/sphere.py — two representations, each where it belongs. Entities are a\nunit direction plus altitude (great-circle distance, tangent-plane heading,\nno seams, every range still in meters); terrain is a cube-sphere grid of six\n512-cell faces (~57 m each, 1.57 M total).\n\nCross-face adjacency is computed GEOMETRICALLY rather than from hand-written\nedge-rotation tables: step past a face's edge in that face's own continuous\n(u, v), build the direction, re-project it. The cube face's plane extends\npast its square, so the ray genuinely strikes the neighbouring face. Correct\nby construction — and verified, not assumed.\n\nworld/noise.py gains 3D Perlin/fBm/ridged/warp. A field sampled per-face in\n2D cracks where faces meet; sampled from the 3D point it cannot.\n\nVerification (24 sphere + 7 noise tests, 116 green overall):\n- flooding through neighbours from ONE cell reaches all 1,572,864 — the\n  globe is provably closed, with no seam and no leak\n- adjacency is symmetric; the 24 cube-corner cells correctly have 7\n  neighbours, everything else 8\n- walking the circumference returns to the start\n- small distances (1 cm to 10 m) stay accurate — acos(dot) would lose them\n- the tangent frame survives standing exactly on a pole\n- cross-seam field steps are no larger than within-face steps\n\nPerf finding for phase 2: neighbors8 does trig, ~47 s per full sweep, so\nworldgen must precompute the neighbour table rather than call it in loops.","parents":["ee46c23cc503d6509e6785f8f73cb9cd0e63c331"],"add":870,"del":1,"cadd":870,"cdel":1,"files":6},{"repo":"hexa","hash":"5af0b66fb4bd3630a274c0745e1bdb3efb5c5b5a","ts":1785620883,"wall":"2026-08-01T17:48","msg":"feat: global worldgen on the sphere (sphere phase 2)","body":"world/globe.py runs worldgen v2's pipeline over the cube-sphere and writes\nthe result to data/planet.bin. One permanent world: generated once (3.5\nminutes), loaded thereafter in 32 ms.\n\nThe sphere deleted three things the flat world needed:\n- Island shaping and the continental lift. A sphere has no rim to drown and\n  no middle to raise; continents fall out of the noise.\n- Connectivity repair. The flat world CARVED land bridges because spawn was\n  pinned to the origin. Nothing is special about any point on a globe, so\n  the world is left alone and spawn is placed on the largest continent.\n  Islands become somewhere to sail to rather than a defect to bulldoze.\n- Beyer's edge-ravine artifact, which cannot arise with no off-map drain.\n\nErosion steps cell-to-cell through the adjacency table rather than flowing\ncontinuously: a continuous droplet would have to change cube faces\nmid-flight, and grid stepping is seam-safe by construction. The table (8\nslots per cell, -1 padding for the 24 corner cells with 7 neighbours) is\nbuilt once so no inner loop pays for trigonometry.\n\nThresholds are MEASURED, not guessed — the first full run produced 0.0%\nhills because the flat world's numbers assumed 4 m cells and 42 m of relief.\nSampled the generated fields, then set each threshold to a percentile of\nwhat the planet actually contains.\n\nHEXA, seed 1077 — 5,027 km2, 1,572,864 cells at 56.5 m:\n  water 59.5% (2,990 km2)   plains 16.2% (816 km2)\n  forest 8.4% (421)         hills 8.3% (416)\n  swamp 4.5% (226)          mountain 3.1% (157)\n  WALKABLE 1,880 km2 — elevation -255 m to +669 m, land median 113 m\n  spawn: forest at 19 m, latitude +56.6 deg, on the largest continent\n\n16 globe tests: adjacency table matches live geometry, determinism, water at\nthe bottom, no statistical difference between face-seam and interior cells,\nspawn provably on the largest continent, and the file format rejects\nforeign, truncated, and wrong-radius planets.","parents":["57f2bbc31d67ef3e459dacc0aea048d66ef0061a"],"add":826,"del":27,"cadd":826,"cdel":27,"files":5},{"repo":"hexa","hash":"3b35e651c42a9ef9befae7a23747dca35b9571b9","ts":1785621020,"wall":"2026-08-01T17:50","msg":"docs: handoff — Hexa is a planet (sphere phases 1-2)","body":"","parents":["5af0b66fb4bd3630a274c0745e1bdb3efb5c5b5a"],"add":47,"del":0,"cadd":47,"cdel":0,"files":1},{"repo":"hexa","hash":"7e3f69dd0cbc0ec9698932d445fb2f9844166b41","ts":1785621108,"wall":"2026-08-01T17:51","msg":"feat: the world itself — data/planet.bin (seed 1077)","body":"The one permanent world, in version control because it is a designed\nartifact, not a build product. Reproducible from seed today; irreplaceable\nthe moment it is hand-edited, which is the point of keeping it here.\n\nHEXA — 20 km radius, 5,027 km2, 1,572,864 coarse cells at 56.5 m:\n  water 59.5% (2,990 km2)   plains 16.2% (816 km2)\n  forest 8.4% (421)         hills 8.3% (416)\n  swamp 4.5% (226)          mountain 3.1% (157)\n  1,880 km2 walkable, elevation -255 m to +669 m, land median 113 m\n  spawn: forest at 19 m, latitude +56.6 deg, on the largest continent","parents":["3b35e651c42a9ef9befae7a23747dca35b9571b9"],"add":0,"del":0,"cadd":0,"cdel":0,"files":1},{"repo":"hexa","hash":"3f63b9a674c050d8928f88bbb62ecede574628f6","ts":1785621132,"wall":"2026-08-01T17:52","msg":"docs: handoff — planet.bin committed","body":"","parents":["7e3f69dd0cbc0ec9698932d445fb2f9844166b41"],"add":3,"del":4,"cadd":3,"cdel":4,"files":1},{"repo":"hexa","hash":"1be8e62f35fb6270eca11da2a5ae568cd4a8cec0","ts":1785622995,"wall":"2026-08-01T18:23","msg":"feat: the server lives on the planet (sphere phase 3)","body":"The flat square is gone from the simulation. A position is now a point on\nthe sphere — a unit direction from the planet's centre — and every distance\nis a great-circle arc in metres.\n\nThe swap was made cheap by rewriting world/space.py in place: `dist`,\n`heading_to`, and `step_toward` kept their names because their MEANING never\nchanged (metres between two places, bearing from one to another, walk toward\na place). Only the geometry underneath moved from a plane to a sphere, so\ncombat, visibility, and stance-seeking needed no edits at all.\n\n- pawn: (x, z) -> a unit direction; heading is a bearing, 0 = north\n- state: holds the Planet, spawns on a spiral out from its spawn point\n- path: A* over the cube-sphere cell graph, great-circle costs, arc-clear\n  string pulling; nearest_walkable for rescuing bad positions\n- formation: slots laid into the local tangent plane and rotated by bearing;\n  a blocked slot slides by searching bearings, since a globe has no axes\n- tick: great-circle movement; sidesteps step out on a bearing and are still\n  terrain-checked (float-and-wade survives intact)\n- persist: positions are directions; the planet is injectable, never stored\n- protocol: the welcome carries planet METADATA, not terrain — 1.57 M cells\n  is 7.6 MB, so the client fetches planet.bin and both sides read one file\n- deleted: world/worldgen.py (the flat generator), in_world, clamp_to_world,\n  HALF_WORLD_M, and the flat nav lattice\n\nTwo real bugs the tests forced out:\n- Cells are ~57 m across, so ANY order shorter than one cell produced an\n  empty route and the pawn never moved — which is most tactical movement.\n  find_route now walks the direct arc when it is clear, which is what\n  string-pulling would collapse to anyway.\n- PLANET_FILE was CWD-relative; the shard runs from server/ and would have\n  looked for the world in the wrong place. It now resolves from the repo.\n\n121 tests green, ruff clean. Live probe: the shard boots on the real planet\n(1,572,864 cells), spawns a squad in forest, and pawns walk at forest speed.\nThe E2E smoke script is marked stale — it speaks the old wire and will be\nrewritten with the phase 4 client rather than twice.","parents":["3f63b9a674c050d8928f88bbb62ecede574628f6"],"add":835,"del":1407,"cadd":835,"cdel":1407,"files":25},{"repo":"hexa","hash":"3e52220c83c57c9787a613e7a9193109dfc5ab31","ts":1785623070,"wall":"2026-08-01T18:24","msg":"docs: handoff + plan — sphere phase 3 complete","body":"","parents":["1be8e62f35fb6270eca11da2a5ae568cd4a8cec0"],"add":27,"del":6,"cadd":27,"cdel":6,"files":2},{"repo":"hexa","hash":"e13f53b03c104233129470b0f93a526271db72a0","ts":1785624393,"wall":"2026-08-01T18:46","msg":"feat: the client stands on the planet (sphere phase 4)","body":"The world renders as the body it is. Everything is drawn in metres from the\nplanet's centre — at a 20 km radius float32 resolves 2.4 mm, so the floating\norigin the plan warned about turned out to be unnecessary.\n\n- sphere.ts: the server's cube-sphere math, ported. Verified against values\n  emitted by world/sphere.py itself — 424 cases, exact agreement. A cell of\n  disagreement would put every pawn on the wrong ground.\n- planet.ts: parses the same planet.bin the server wrote (public/planet.bin\n  is a SYMLINK, so there is still exactly one planet), and refuses to run if\n  the shard reports a different world than the file holds.\n- globe.ts: two LOD tiers, chosen by the horizon. On a 20 km body the ground\n  curves away 283 m from a standing eye and 4 km from the highest peak, so a\n  far shell (whole globe, every 8th cell, ~25 k verts) plus a handful of\n  full-resolution near tiles is all anyone can see. Tiles overlap by a row\n  and their edge vertices are computed past the face boundary, so they meet\n  across cube seams. The ocean is a sphere at the waterline — coastlines\n  emerge where it meets the land rather than being drawn.\n- camera.ts: focus is a PLACE and up is whatever that place points, so\n  panning walks the surface. Zooming out becomes an orbit: the same control\n  runs from a pawn's shoulder to the whole body.\n- pawns.ts: bodies interpolate along great circles and are oriented by an\n  explicit basis (feet to the centre, face along the bearing) — Euler angles\n  are meaningless when every pawn stands on a different plane.\n- vegetation.ts: scattered over cells near the camera, seeded by CELL INDEX\n  so a tree is in the same spot every time you walk back to it.\n- terrain.ts deleted (the flat mesh); mulberry32 moved to random.ts.\n\nVerified headlessly: tsc, vite build, SPHERE-PARITY-OK, PLANET-PARSE-OK\n(1,572,864 cells, seed 1077, spawn on forest), and GLOBE-OK — far shell and\ntile vertices sit on the real terrain, and tiles built at a cube seam\ncorrectly straddle two faces. Live: shard on the planet, client serving\nplanet.bin (7,864,376 bytes).","parents":["3e52220c83c57c9787a613e7a9193109dfc5ab31"],"add":987,"del":492,"cadd":986,"cdel":492,"files":11},{"repo":"hexa","hash":"f9690612078b65a5c04b8b26bc49f1da9efbe809","ts":1785624712,"wall":"2026-08-01T18:51","msg":"feat: a local day, and a moon with real phases","body":"Two things a globe changes about the sky, and one the operator asked for.\n\nDAY IS LOCAL. The sun is a direction in space now; a directional light aimed\nat the planet's centre lights exactly the hemisphere facing it, so day and\nnight fall out of the geometry. Sky colour is read from LOCAL SOLAR TIME —\nthe sun's altitude in your own sky, with its east/west component breaking\nthe tie between dawn and dusk, which altitude alone cannot. Walk far enough\neast and you walk into the morning.\n\nThe check caught the bug that made this necessary: mapping altitude straight\nto time of day only ever produced daylight (the night keyframes were\nunreachable), and opposite sides of the world differed by 0.19 of a lamp.\nThey now differ by 1.60, and the sun runs 0.10 to 1.70 across a full day.\n\nTHE MOON is a real body, not a billboard: a sphere out at eight planet radii,\nlit by the same sun that lights the world, so its phases are geometry rather\nthan artwork. It rides its own tilted orbit on a period of 5.3 days — a\ndeliberately fractional number, so the phase drifts from night to night\ninstead of repeating with the sun. Moonlight is a second dim, cool\ndirectional light scaled by the lit fraction, so a full moon overhead really\ndoes lighten the ground.\n\nVerified headlessly (DRESSING-OK): the moon never intersects the planet over\ntwo full orbits, goes new (0.00) to full (1.00), subtends 4.3 degrees — some\neight times our own moon, because one you cannot find is not worth having —\nand sheds light up to 0.35.","parents":["e13f53b03c104233129470b0f93a526271db72a0"],"add":114,"del":22,"cadd":114,"cdel":22,"files":2},{"repo":"hexa","hash":"fa67b7f5fac6c4ebd7a77dbe36ba9045d4ffb36e","ts":1785624747,"wall":"2026-08-01T18:52","msg":"docs: handoff + plan — sphere phase 4 complete","body":"","parents":["f9690612078b65a5c04b8b26bc49f1da9efbe809"],"add":34,"del":8,"cadd":34,"cdel":8,"files":2},{"repo":"hexa","hash":"cb2fd7b6198d7ce7be1e4371221be1ceb9675dd2","ts":1785625101,"wall":"2026-08-01T18:58","msg":"fix: the planet was inside out — every triangle faced inward","body":"Operator's screenshot: nothing but ocean, with trees floating in it. The\nterrain was being built correctly the whole time (the trees stood on it),\nbut EVERY face of the globe was wound the wrong way, so the ground was\nbackface-culled and the camera looked straight through it to the ocean\nsphere behind. Inverted winding also inverted the normals, so the lighting\nhad been wrong too.\n\nThe winding is no longer hand-derived. The six cube faces do not all share\nhandedness, so a fixed index order cannot be right for all of them by\nconstruction. Each patch now MEASURES one of its own triangles against the\ndirection it should face — every vertex is on the surface, so \"outward\" is\njust the triangle's own centroid — and flips itself if it points inward.\nVerified per face: 205/205 triangles outward on all six, 0/9 tiles inside\nout.\n\nAlso tightened the ocean. Its segment count is not cosmetic: a flat facet\nspanning chord c on a sphere of radius R sags (c/2)^2 / 2R below the true\nsurface. At 96 segments that is a 1.3 km chord and a TEN METRE error — it\nwould have drowned or exposed whole coastlines. At 512 segments it is 0.4 m.","parents":["fa67b7f5fac6c4ebd7a77dbe36ba9045d4ffb36e"],"add":47,"del":1,"cadd":47,"cdel":1,"files":1},{"repo":"hexa","hash":"0cea2003fc7e686301c4c91f67d82754e5c5a374","ts":1785625335,"wall":"2026-08-01T19:02","msg":"feat: double-click a roster name to ride that pawn","body":"Double-clicking a name in the roster puts the camera on that pawn at 22 m\nand KEEPS it there. Following rather than a one-shot centring, because a\npawn worth looking at is usually one that is walking — a snap would lose it\nwithin seconds.\n\nThe camera is handed back the moment you pan. Rotating and zooming do not\nrelease it: you are still looking at the same pawn, from another angle or\nrange, which is the whole point of having gone there.\n\nfocusOn deliberately leaves yaw and pitch alone, so it keeps the angle the\noperator chose instead of snapping to some canonical view. Following stops\nby itself if the pawn goes out of sight, rather than chasing a ghost.\n\nVerified (FOCUS-OK): the camera lands on the pawn, closes to 22 m without\nending up inside it or underground, keeps the operator's chosen angle, holds\nthe pawn framed over a 1 km walk, and does not let the stand-off creep.","parents":["cb2fd7b6198d7ce7be1e4371221be1ceb9675dd2"],"add":50,"del":1,"cadd":50,"cdel":1,"files":3},{"repo":"hexa","hash":"714b4a36bcea0a2fdbf40f1cdd4176f3021d7a11","ts":1785625509,"wall":"2026-08-01T19:05","msg":"fix: the follow camera was moving at 4 Hz while the pawn moved at 60","body":"The skip had a single cause: the camera was updated from the SERVER's\nposition, once per tick, while the body it was following was drawn sixty\ntimes a second gliding between those ticks. So the pawn slid around inside\nthe frame four times a second.\n\nThe camera now tracks where the pawn was actually DRAWN — PawnManager\nremembers each body's interpolated place — and it is updated every frame,\nafter animate() rather than on the state message. On top of that it eases\ntoward its subject with an exponential approach on dt, which absorbs tick\njitter and behaves identically at any frame rate.\n\nMeasured rather than eyeballed. Simulating a pawn walking 3 m/s while the\nserver speaks at 4 Hz:\n  per-tick following: worst frame 2.34x the average step  <- the skip\n  per-frame following: worst frame 1.00x                  <- even\n  tracked speed 2.75 m/s at 30, 60 and 144 fps (frame-rate independent)\n  steady-state lag 0.31 m — glued, not trailing","parents":["0cea2003fc7e686301c4c91f67d82754e5c5a374"],"add":39,"del":9,"cadd":39,"cdel":9,"files":2},{"repo":"hexa","hash":"3136cf2c33d2714867004ef7f9c44b076c9e8e6b","ts":1785626124,"wall":"2026-08-01T19:15","msg":"feat: torch, flashlight, and a moon that glows when it fills","body":"Night was unplayably dark without something to carry into it.\n\nTWO LAMPS, deliberately different. A torch is a wide warm glow, 9 m, bright\nclose and gone by its edge — it shows you your feet and gives you away. A\nflashlight throws a hard cold beam 34 m along the way the pawn is facing —\nit reaches, but shows nothing to the sides. Carrying both does not make a\nbrighter one: the better lamp wins.\n\nItemDef gained light_radius_m / light_color / light_beam, all additive with\ndefaults, so every item written before lamps existed loads unchanged. The\nlamp is resolved into EffectiveStats like any other gear property, and it\nrides on the wire as PUBLIC data — a light in the dark is the one thing\neveryone can see, whether or not the bearer wanted to be seen. The bag stays\nprivate beside it.\n\nEvery pawn now spawns with a torch stowed in its bag and the point pawn also\ncarries the flashlight. That lives in Hexa's spawn code, NOT in the loadout\nfiles, which are Mesnada's data shared verbatim — the test now names that\nboundary instead of asserting a bare item count.\n\nRendering splits the cost honestly. The FLAME is a cheap emissive speck that\nevery bearer gets, so a distant torch still reads as a point of fire. The\nLIGHT it casts is expensive, so only the six nearest bearers get a real one,\nnearest first — a lamp across the valley matters less than the one at your\nfeet.\n\nTHE MOON now has a halo that swells as it fills: zero at new, 0.85 at full,\n2.6x the disc, riding exactly with it. Squared against phase so it stays\nsubtle through the crescents and only blooms near full. Its light already\nscaled with phase; now you can see why.\n\nVerified: 126 server tests, and LIGHTS-OK — the glow tracks the moon across\ntwo orbits without drifting, a new moon does not glow, the torch is\nmeasurably warm and the flashlight measurably cold, and the flashlight\nreaches further. All six client harnesses still green.","parents":["714b4a36bcea0a2fdbf40f1cdd4176f3021d7a11"],"add":325,"del":2,"cadd":281,"cdel":2,"files":13},{"repo":"hexa","hash":"8e54dc926556685008f55fbd463612de9867d1c1","ts":1785627009,"wall":"2026-08-01T19:30","msg":"feat: lamps authored in real lumens — crappy keychains to floodlights","body":"Operator: \"different levels of lumens on these flashlights. Some will have\ncrappy lumens while others will light up vast areas.\"\n\nLights are now written in LUMENS, the unit lamps are actually sold in, and\neverything else is derived from the photometry (world/light.py):\n\n    isotropic:  I = lumens / 4pi                  (candela)\n    cone:       I = lumens / (2pi (1 - cos a/2))\n    reach:      r = sqrt(I / MIN_USEFUL_LUX)      (inverse square)\n\nAdding a lamp now means picking a bulb, not guessing a radius. The family:\n\n    torch            15 lm   flame        8 m    warm, and gives you away\n    camp_lantern     90 lm   flame       19 m    lights the camp, throws nothing\n    pocket_light     12 lm   30 deg      53 m    a keychain LED\n    flashlight      180 lm   24 deg     256 m    the standard\n    tactical_light  900 lm   16 deg     400 m    capped at the horizon\n    floodlight     3000 lm   70 deg     363 m    night into a grey afternoon\n\nThe physics earns its keep immediately: the 12-lumen keychain OUT-THROWS the\n15-lumen torch, because the same light poured into a narrow cone raises the\nintensity enormously. Anyone who has held both knows it; now the model does\ntoo. Carrying two lamps picks the one that lights the most ground, not the\none that burns the most fuel.\n\nReach is capped at 400 m. A tight beam is physically good for the better\npart of a kilometre, but this planet's horizon is 283 m from a standing eye\n— past the cap there is nothing left to light.\n\nthree.js takes light.power in LUMENS directly (verified in its source:\nPointLight lm = cd x 4pi, SpotLight lm = cd x pi), so the authored value\nreaches the renderer untouched, with decay 2 for real inverse-square\nfalloff. No invented intensity numbers anywhere in the chain.\n\n130 server tests. LAMP-RENDER-OK proves the renderer carries the authored\nlumens, the beam's half-angle is right, stowing a lamp removes both flame\nand light, downed pawns drop theirs, and the six-light cap holds under\ntwenty bearers while every one of them still shows a flame.","parents":["3136cf2c33d2714867004ef7f9c44b076c9e8e6b"],"add":302,"del":51,"cadd":188,"cdel":43,"files":15},{"repo":"hexa","hash":"6584ff70e55bbb37bf0bc5d82fb32e700446d2db","ts":1785627527,"wall":"2026-08-01T19:38","msg":"feat: headlamps — a lamp on the brow, aimed where the pawn looks","body":"Two of them: a plain headlamp (90 lm, wide 45-degree spill, 97 m) and a\ntactical one (450 lm, tight 26 degrees, 374 m — within a whisker of the\nhand-held flashlight's reach, so hands-free costs you nothing).\n\nLamps now declare a MOUNT. A head mount rides at the brow rather than the\nfist, and its beam is aimed slightly down — you walk looking at the ground\nahead of you, not at the horizon. Hand-held lamps say so explicitly too, so\nthe field is never absent by accident.\n\nThe squad now spawns with a torch AND a headlamp each, and the point pawn\ncarries the tactical one.\n\nHonest limit: hand OCCUPANCY is not modelled yet — nothing today stops a\npawn swinging a two-hander while holding a torch — so \"hands free\" is\npresently about where the light rides and how it aims, not a mechanical\nadvantage. Making a held lamp cost you a hand is a separate mechanic, worth\ndoing, and worth deciding on its own.\n\n134 server tests.","parents":["8e54dc926556685008f55fbd463612de9867d1c1"],"add":155,"del":18,"cadd":89,"cdel":12,"files":17},{"repo":"hexa","hash":"45c3f9f839dd31c9cfeda751b38f40dd862af41a","ts":1785630425,"wall":"2026-08-01T20:27","msg":"feat: factions — hostility must exist before anyone swings","body":"Two bugs with one root: the world assumed war.\n\nIDENTITY IS THE TOKEN, not the typed name. The client keyed its token by\nname (`hexa-token-${name}`), so typing your own name with one letter out of\nplace found no token and made you a SECOND PERSON — with four pawns who\npromptly fought the squad you already had. It is now one token per browser;\nthe server checks it first, recognises you whatever you typed, and treats a\ndifferent name as a rename. A rename carries the token, the pawns and the\nfaction across: only the label moves.\n\nHOSTILITY IS DECLARED. An adversary used to be any pawn of another owner, so\ntwo strangers meeting on 5,027 km2 of planet fought on sight. Now:\n\n- Every player holds a faction of their own; NPC factions will share the\n  registry when there are any.\n- Relations default to NEUTRAL. Neutral pawns ignore each other completely —\n  they walk past, camp beside, and never trade a blow.\n- Hostility is declared (`set_relation`), and one-sided until answered.\n- Being struck answers it: a faction that takes damage turns on whoever\n  dealt it, so nobody can be farmed by an enemy they may not fight back\n  against.\n- Allies are never targets.\n- A faction is never hostile to itself, which is what stops your own squad\n  brawling however you spell your name.\n\nStances survive unchanged — they say what a pawn does about the enemies it\nhas, not who those enemies are.\n\nThe client shows standing rather than identity: a thin ring under everyone\nwho is not yours, red for hostile, green for allied, grey for neutral. On a\nworld anyone can drop into, whether the figure on the ridge is a threat is\nthe one thing worth reading at a glance.\n\nA subtle test hazard, handled: with strangers neutral, every old \"these two\ndo NOT fight\" test would now pass whether or not the thing it claimed to\ntest still worked. tests/helpers.at_war() makes the war explicit, and every\ncombat test declares one first.\n\n148 server tests (14 new), 11 client harnesses green. Worlds saved before\nfactions load with each player in their own, at peace with all.","parents":["6584ff70e55bbb37bf0bc5d82fb32e700446d2db"],"add":911,"del":23,"cadd":911,"cdel":23,"files":17},{"repo":"hexa","hash":"ba2bb79bc1592046977c33f203ca38e198aab899","ts":1785637132,"wall":"2026-08-01T22:18","msg":"fix: the token migration locked existing players out of their own world","body":"Making the token one-per-browser broke everyone who already had one. Older\nbuilds stored it under `hexa-token-${name}`; the new code read `hexa-token`,\nfound nothing, sent no token, and the server correctly refused the name as\nalready claimed. The operator could not enter his own world.\n\nThe client now adopts a token left under the old per-name key (trying both\nthe typed name and the last name it remembers) and rewrites it under the new\none. The migration can be deleted once no such browser is left.\n\nAnd the reason this took a report rather than a glance: thirty-seven\nconnections were refused without a single line in the log. A refusal is an\nevent and is now recorded, with a message that says what to do about it\ninstead of \"name taken (bad token)\".\n\nVerified against a SCRATCH shard on another port — never the one being\nplayed on:\n  1. first join                          -> welcome\n  2. rejoin with the token               -> same identity\n  3. the TYPO carrying the token         -> renamed; ONE player, four pawns\n  4. someone else's name, wrong token    -> refused, and logged\n  5. a genuine stranger                  -> joins, and is neutral","parents":["45c3f9f839dd31c9cfeda751b38f40dd862af41a"],"add":34,"del":7,"cadd":34,"cdel":7,"files":2},{"repo":"hexa","hash":"d9bced83f0817d267c6ca375afad364031c98734","ts":1785638932,"wall":"2026-08-01T22:48","msg":"fix: the world looked tiled from above, and panning up there thrashed","body":"Operator's screenshot from altitude: rectangular patches of forest, a haze\nover everything, and lag while panning. Three separate causes.\n\nCOLOUR WAS NEVER INTERPOLATED. Phase 5 made height bilinear and left colour\nas a nearest-cell lookup, so the terrain's shape was smooth while its colour\nwas a 56.5 m checkerboard with axis-aligned edges. Those rectangular forests\nwere not forests, they were pixels.\n\nInterpolating the lookup turned out NOT to be enough on its own, and finding\nout why was the useful part: a coarse tile's vertices sit exactly at cell\ncentres, where a bilinear blend returns that cell's own colour and softens\nnothing — which is precisely the view from altitude. So the finished vertex\ncolours are also blurred against their neighbours, which turns a biome\nboundary into a gradient several vertices wide on every tier without adding\na single vertex. The biome sample is additionally nudged by a little noise,\nso shores and treelines wander across their cells instead of following the\ngrid. Hard biome edges: 5.7% -> 3.2%, measured against what the old code\nproduced on the same tile rather than against a threshold picked out of\nthe air.\n\nTHE LAG WAS INVISIBLE GEOMETRY. `updateDetail` floored its reach at 1, so\nNINE 4-metre patches were built even from orbit — about 114 k vertices\nregenerated whenever the focus moved 450 m, which panning at altitude does\nevery frame. Detail is now dropped entirely above the height where 4 m\nspacing cannot be seen, vegetation with it, and what remains is built two\npatches per frame instead of all at once (2 -> 4 -> 6 across frames).\n\nTHE HAZE was fog pinned at 1,500-14,000 m regardless of altitude, so the\nwhole planet sat inside it from above. Fog now recedes as the camera climbs.\n\nPlan of record for the rest of the operator's list — sprint on stamina,\nright-click context menu, prospecting and mining, crafting at stations, and\nHUD targets that can actually be hit — is in\n.claude/plans/hexa-work-and-world.md, with the design decisions he made.","parents":["ba2bb79bc1592046977c33f203ca38e198aab899"],"add":266,"del":7,"cadd":266,"cdel":7,"files":6},{"repo":"hexa","hash":"b0d608358651d2d59e27fe6edb6c357c96bf7c2c","ts":1785640849,"wall":"2026-08-01T23:20","msg":"feat: sprinting that trains itself, and terrain bounded at every zoom","body":"RUNNING. Walking is free; sprinting draws on a pool of wind that refills when\nyou slow down, so a long march becomes a decision and Endurance stops being a\nnumber that only sets hit points.\n\nOperator: \"the more you run, the faster and easier it gets to do.\" So running\nTRAINS, through the graded-skill system Mesnada already gave us rather than a\nparallel one — `athletics` joins SKILL_GOVERNING under speed and endurance,\nand every second at a sprint feeds it. The skill then buys back every cost:\n\n    a bigger pool      more ground between breathers\n    a slower drain     up to 45% cheaper to sprint\n    a faster recovery  up to 80% quicker to catch your breath\n    a longer stride    up to 28% faster at a run\n\nMeasured end to end: a pawn with 60 trained points covers more than 1.5x the\nground of a novice on one lungful. The first crossing of a valley is a\nlabour; the hundredth is a jog.\n\nNothing here can strand a pawn. An empty pool drops it back to a WALK — no\nexhaustion penalty, no lost orders, no speed below walking. Overencumbered\npawns cannot start, and the downed do not run.\n\nZOOM. The operator asked whether zoom should be limited so regions load in\nsmaller chunks. Measuring first found a real bug: the LOD early-out keyed on\nPOSITION only, so zooming without panning never reached the altitude gate and\nnine 4-metre patches stayed resident from orbit — the exact waste the gate\nexists to prevent. Range now counts as movement.\n\nRather than forbidding a zoom level, the fine ground is CAPPED at nine\npatches and the nearest win it. Zooming out no longer enlarges the detailed\nregion; it moves the camera away from a region of fixed size until the gate\ndrops it. Resident geometry, measured across the whole range:\n\n    view   300 m   9 detail patches  (114 k verts)\n    view   900 m   9 detail patches\n    view  2000 m   none — coarse tiles only (27 k)\n    view 90000 m   none — the whole planet in 53 k\n\n162 server tests (14 new), 6 client harnesses green.","parents":["d9bced83f0817d267c6ca375afad364031c98734"],"add":451,"del":11,"cadd":451,"cdel":11,"files":10},{"repo":"hexa","hash":"c9456067da15fed06f315a8522eef3e9b7496d14","ts":1785641239,"wall":"2026-08-01T23:27","msg":"fix: I stripped the world bare — the LOD gate measured the wrong thing","body":"Operator: \"what did you do with the vegetation and stones etc?\" I deleted\nthem, at every zoom level, including standing on the ground.\n\nThe altitude gate I added to stop detail being rebuilt from orbit tested\n`viewRangeM()` — how far the camera can SEE. On a 20 km planet the horizon\nfrom a normal 120 m play camera is already 2,250 m, so a gate at 900 m was\ntrue from the very first click. Trees, rocks, grass and the entire fine\nterrain layer were switched off permanently.\n\nThe gate now tests STAND-OFF: how far the eye actually is from the ground,\nwhich is the thing that decides whether a 4 m tree is worth drawing. Measured\nacross the zoom range the wheel produces:\n\n    stand-off  120 m   9 detail patches   133 props\n    stand-off  532 m   9 detail patches   133 props\n    stand-off  741 m   none               none\n    stand-off 1437 m   none               none\n\nThe lesson is the one this project keeps teaching: I reached for a number\nthat sounded like altitude instead of measuring what it returned. A probe\nwould have shown 2,250 m at the default camera in one line.","parents":["b0d608358651d2d59e27fe6edb6c357c96bf7c2c"],"add":35,"del":15,"cadd":35,"cdel":15,"files":2},{"repo":"hexa","hash":"f36a7ef3907b339f40361f98c3d70835d39f803e","ts":1785642557,"wall":"2026-08-01T23:49","msg":"docs: research the resource economy instead of inventing it","body":"Operator, twice and rightly: do some research on prior art; and this world is\na CLOSED SYSTEM — living things come back, metal and stone do not, like the\nreal world.\n\nBoth corrections landed. Read the prior art, then the mass budget, then wrote\nthe design:\n\nKENSHI — prospecting is a survey OVERLAY (percentage efficiency for iron,\ncopper, water, fertility before you settle), and mining rate is driven by the\nLabouring SKILL. Both port directly; Hexa already trains skills by use.\n\nRIMWORLD — surface ore finite, deep drilling effectively infinite. They\nCHANGED it to infinite on purpose, because a permanent colony that runs dry\nis a dead colony. The lesson is not \"make it infinite\" but \"make the frontier\nrecede rather than end\".\n\nVALHEIM — stations have a RADIUS and upgrade IN PLACE. Better than the flat\nfield-vs-station split I had proposed: a camp becomes a gradient of\ncapability, improved incrementally.\n\nMESNADA (ours) — already has ResourceConfig with pools and regen, a Deposit\nenum with geological provinces, the full metallurgy spine with tin kept out\nof starting provinces as the bronze bottleneck, and recipe_graph answering\n\"what can this settlement actually make\". The data ports; the mechanism does\nnot, because it is turn-based shops and Hexa is a pawn working a deposit.\n\nTHE CLOSED SYSTEM. Metal is not destroyed by use — ore becomes an ingot\nbecomes a blade becomes scrap becomes an ingot, with a small loss at each\nmelt. What is finite is ORE IN THE GROUND: the concentrated, shallow, cheap\nform. That is how Earth works; we have never run out of iron, only of cheap\niron.\n\nAnd the arithmetic says the fear was misplaced: the top 5 m of this planet's\ncrust holds ~3,800 Mt of iron, while four pawns hauling 20 kg six times an\nhour move 11.5 t/day — one rich CELL is 37 days of work for a squad. The\nworld cannot be hand-stripped. What is scarce is ore near where you are\nstanding, which is exactly the pressure worth having.\n\nResearch doc ingested to unicursal (8 fragments, 13 axes).","parents":["c9456067da15fed06f315a8522eef3e9b7496d14"],"add":199,"del":11,"cadd":199,"cdel":11,"files":2},{"repo":"hexa","hash":"978b99e2306406f9fc295e2fa8d8494c12d23ee9","ts":1785645113,"wall":"2026-08-02T00:31","msg":"feat: geology, resources, prospecting and mining on a closed world","body":"The ground is made of something now, and it differs by where you stand.\n\nGEOLOGY. The planet is partitioned into 14 provinces — Voronoi cells by\ngreat-circle distance — each bearing one or two deposit classes, so metals\nCLUSTER into regions instead of scattering evenly. Ported from Mesnada's\nhex-board version; three ideas carry over because they are the good ones:\nkeystones (tin, flux, precious) never spawn within 6 km of a start, so the\nbronze bottleneck must be reached for; richness grows with remoteness, so\nexpansion pays for itself; and the whole thing is derived from the planet's\nown seed, so it costs nothing to store and can never drift from the world it\ndescribes.\n\nRESOURCES follow the operator's rule and the real world's: living things come\nback, metal and stone do not. Timber, fibre, game and fish thin out and\nreturn. Iron, copper, tin, coal, stone, limestone and clay do not, because\nnothing on this planet is making iron.\n\nDeposits have DEPTH. The surface band is quick; the same vein below costs\n2.2x and then 4.5x per unit, which is what makes better tools and eventually\na real mine worth building. Running dry near home is a prompt, not a wall.\n\nWORK. A pawn walks to a deposit and works it tick by tick — the part that\ndoes NOT port from Mesnada, where a shop produces once per turn. Prospecting\nreveals what the ground bears (Kenshi's overlay, earned: a trained\nprospector reads further). Harvesting is faster with skill and slower with\ndepth, and both TRAIN the skill that speeds them. Ore in the satchel weighs\nwhat ore weighs, so a pawn hauling stone walks slower and cannot run.\n\nTWO BUGS THE TESTS FOUND:\n\nPools were sized by feel, not by mass. 320 units at 5 kg is 1.6 tonnes — a\nwheelbarrow — where a 57 m cell with a 3 m vein holds ~3,900 t. That put the\nplanet's entire iron supply at TWO YEARS of one squad's labour, which is not\na world, it is a level. Sized from the ground instead: a rich iron cell is\n~1,550 t (about 2 days of squad work) and the planet is ~527 years. Scarce\nlocally, inexhaustible globally — which was the whole design.\n\nSurveying rejected any cell whose CENTRE was out of range, so a prospector\nstanding near a cell boundary learned nothing about the ground under its own\nboots. A cell now counts if any part of it is in reach.\n\n183 tests (21 new). Crafting and the recycling loop next — the ladder now has\nsomething to stand on.","parents":["f36a7ef3907b339f40361f98c3d70835d39f803e"],"add":1238,"del":3,"cadd":1238,"cdel":3,"files":14},{"repo":"hexa","hash":"7578fbd3682d8a690239f2375324dee3abd7e00d","ts":1785645737,"wall":"2026-08-02T00:42","msg":"feat: crafting — the cycle that lets a closed world stay playable","body":"19 recipes and 6 stations, shaped by the two rules the closed system implies.\n\nMATTER IS CONSERVED. Ore becomes an ingot becomes a blade becomes scrap\nbecomes an ingot, and the iron is still on the planet at every step. Melting\nscrap loses 8% to slag — the only place metal actually leaves the world, kept\nsmall on purpose so the planet does not bleed out, and kept non-zero so fresh\nore stays worth digging. Reclaiming is cheaper and quicker per ingot than\nsmelting ore, which is what stops a permanent world filling up with dead\nswords.\n\nCAPABILITY HAS A PLACE. Rough work anywhere — rope, planks, a charcoal pit\ntended by hand. Real work at a station, and a station projects a RADIUS\nrather than gating a tier, so a camp becomes a gradient of capability worth\ndefending. A station never removes what your hands could already do.\n\nThe ladder walks recipes to a fixpoint, so ore → ingot → blade needs nobody\nto list the chain. It also answers the useful question: what is missing?\n\nA BUG THE TESTS FOUND, and a good one: asking which SINGLE station unlocks a\nthing reports that NOTHING blocks a longsword — because it needs a smelter\nfor the steel and a forge to beat it, and neither alone is enough. The query\nnow adds stations greedily until the target is reachable, so it answers\n{smelter, forge, tannery} instead of {}.\n\nThe keystones bite exactly as intended: without tin ore, bronze is not slow,\nit is unreachable however much you build. Same for steel without flux. Those\nare the deposits the geology deliberately keeps away from spawn.\n\n198 tests (15 new).","parents":["978b99e2306406f9fc295e2fa8d8494c12d23ee9"],"add":487,"del":0,"cadd":487,"cdel":0,"files":2},{"repo":"hexa","hash":"02e7dc3d872e5e2323027801178327bc0d69317b","ts":1785646974,"wall":"2026-08-02T01:02","msg":"feat: right-click orders, and a shard that dispatches all of its verbs","body":"THE MENU. Right-DRAG still turns the camera; right-CLICK without dragging\nopens a menu of what can be done with whatever is under the cursor — ground\noffers move, run, prospect and work; your own pawn offers follow and select;\nanother faction offers declare hostile, make peace, offer alliance. Same\ndistinction left-click already makes between selecting and marqueeing, so\nthere is one rule rather than two.\n\nIt is also the answer to \"the buttons for formations and aggression stance\nsuck and are hard to actuate\". They were fourteen pixels of SVG in a cramped\nrow. Menu entries are full-width text with their shortcut shown — a real\ntarget, and a way to stop needing the target.\n\nGround the player has not surveyed reads \"unsurveyed\" and the work entry is\ndisabled with the reason, so prospecting is something you notice you need\nrather than something you are told about.\n\nA BUG THE END-TO-END PROBE FOUND, and the unit tests could not:\n\nThe shard silently ignored three of its own orders. `work`, `set_sprint` and\n`set_relation` had handlers, the client sent them, the tests exercised the\nhandlers directly — and nothing happened in a real session, because the\ndispatcher was an elif chain and my edits to it landed nowhere. Prospecting\nreturned zero cells and sprinting did not engage.\n\nThe chain is now a TABLE. A table cannot be half-edited: either a verb is in\nit or it plainly is not. Eight verbs, all reachable, checked by asking the\nclass what it answers.\n\nThe lesson is the one this project keeps re-teaching: unit tests that call a\nhandler directly cannot tell you the handler is unreachable. Only driving the\nreal socket does — against a SCRATCH shard on another port, never the world\nthe operator is standing in.\n\nVerified end to end: prospect surveyed 147 cells, harvest filled a satchel,\nsprint covered 28.9 m in 5 s and drew down the wind. 198 server tests, 4\nclient harnesses.","parents":["7578fbd3682d8a690239f2375324dee3abd7e00d"],"add":376,"del":20,"cadd":376,"cdel":20,"files":6},{"repo":"hexa","hash":"7e4322ee897c411651429ea759a342e69454e200","ts":1785935956,"wall":"2026-08-05T09:19","msg":"feat: a heliocentric sky, a moon that lights the night, and lamps that work","body":"The sun no longer orbits the planet. The planet spins on an axis held fixed\nin inertial space and orbits the sun, so seasons fall out of the geometry the\nway the moon's phases already did — the old tilt was on the SUN's orbit, which\nis constant relative to the sun and produced no seasons at all. The moon now\norbits in inertial space too and is carried into the body frame by the same\nspin, so it rises and sets instead of crawling round once every 5.3 days.\n\nNight ambient answers to the moon: phase AND altitude, because a new moon\nreflects nothing however high it rides and a moon below the horizon is\nlighting somebody else's night. The phase was already computed; it had only\never reached the halo.\n\nThree lighting faults, each real and each measured:\n\n  - three.js SpotLight.power converts as cd = lm/pi and discards the cone\n    angle, so the tactical light rendered at 286 cd against the 14,718 cd the\n    server derives its reach from. Setting intensity in candela ourselves\n    bypasses that. Client and server now agree on all eight lamps exactly.\n\n  - No tone curve at all, so everything over 1.0 clipped flat. Khronos\n    Neutral, which is identity below 0.76 and only compresses highlights.\n    NOT AgX: three ships it with the look transform commented out, which is\n    the flat variant nobody actually uses.\n\n  - Exposure targeted ILLUMINANCE when what reaches the screen is what a\n    surface reflects — BRDF_Lambert takes it through RECIPROCAL_PI and an\n    albedo below 1 on the way. Aiming illuminance at mid-grey put a mid-albedo\n    surface at 0.029. Daylight was six times too dark and no amount of tuning\n    was going to fix an arithmetic error.\n\nThe sky's night levels are authored rather than physical. Rendering the true\n1:400,000 ratio of moonlight to daylight is how you get a game nobody can\nplay; the prior art is unanimous that darkness is carried by colour, not by\nluminance. The lamps stay honestly photometric because the server derives\ntheir reach from the same numbers.\n\ncelestial.ts takes no three.js and no DOM import, so the orbital mechanics are\ncheckable without a browser. That caught two bugs reading never would have:\nboth orbits ran backwards relative to the spin (34 apparent solar circuits a\nyear in a 32-day year), and a sqrt skylight curve that dumped 380 lux across a\nhair's width of sun angle at sunset.\n\nVerified: 31 celestial oracles, photometric parity against the real server\nfunction over every lamp in data/items, tsc clean, vite build, 198 server\ntests unchanged.\n\nKnown gaps, not yet addressed: lamps need a gain constant now that the night\nfloor has risen, and the blue night grade the research calls for is not built.","parents":["02e7dc3d872e5e2323027801178327bc0d69317b"],"add":966,"del":115,"cadd":966,"cdel":115,"files":9},{"repo":"hexa","hash":"83e50e84d2fa3c8a540b8868a3f9c079e4813e6e","ts":1785940743,"wall":"2026-08-05T10:39","msg":"perf: load the planet in one memcpy, and stop shipping it uncompressed","body":"Four things on the loading path, from the render/load audit.\n\nPlanet.parse read all 1,572,864 heights one at a time through DataView. It\nnow takes a single Float32Array view over a sliced buffer. The alignment\nworry behind the old loop was real — the heights do not begin on a 4-byte\nboundary, so a view over the original buffer throws — but slice returns a\nfresh buffer aligned by construction, so the whole block moves as one copy.\nHonest about the size of this: the old loop measured 17 ms, not the hundreds\nI assumed. V8 optimises DataView well. The new parse is about 8 ms.\n\nThat trade reads in HOST byte order where the old code forced little-endian,\nwhich is safe on anything that runs a browser but is now load-bearing, so it\nis checked at parse time rather than trusted.\n\nplanet.bin was going out with no Content-Encoding at all. A dev-server\nmiddleware gzips it: 7,864,376 -> 5,927,888, a quarter off, using node:zlib\nso it costs no dependency. Measured before reaching for anything fancier —\nbrotli is NOT worth it here (5,930,357 vs 5,934,527 at q5). The 6.29 MB of\nfloat32 heights are high-entropy mantissa and do not compress; only the\nbiomes do, and gzip already takes those to almost nothing. The middleware is\ndev-only; production serving has to enable compression itself.\n\nThe load now reports progress into the join screen. Eight megabytes behind a\nblank screen is indistinguishable from a hang. Clamped, because\nContent-Length is the compressed size while the bytes counted are\ndecompressed.\n\nAlso: cellIndexAt carried two stacked doc comments, the first describing the\nprivate method below it, and the import block had a stray blank line.\n\nVerified: a new headless check parses the real data/planet.bin two independent\nways and compares EVERY height — 6,291,456 bytes byte-identical to the file,\nand all 1,572,864 values identical to the old DataView loop. Plus biome\nequality, biome range, no NaN, and relief within the world's stated bounds.\nLive: gzip confirmed on the wire and the decoded body byte-identical to disk.","parents":["7e4322ee897c411651429ea759a342e69454e200"],"add":273,"del":17,"cadd":273,"cdel":17,"files":4},{"repo":"hexa","hash":"e2d98749ba6fb51aec8473f4f9c679ad7cb1e5ea","ts":1785941215,"wall":"2026-08-05T10:46","msg":"perf: vegetation stops rebuilding itself from scratch every time you walk","body":"rebuild() called dispose(), which destroyed every geometry AND every material,\nand then reran makeConiferTree() and its siblings — a handful of Cylinder,\nCone and Sphere constructors plus a buffer merge — followed by four fresh\nmaterials and four fresh InstancedMesh allocations. All of that fired whenever\nthe camera wandered 35% of the dressed range, which walking does constantly.\nNone of it changes when you walk.\n\nPrototypes and materials are now module-level singletons, built lazily in the\nsame shape glow.ts uses for its shared texture. The instanced meshes persist\nand only their matrices and .count change; capacity grows in blocks of 256, so\nin practice it allocates once and then never again.\n\nOne subtlety that had to be handled rather than inherited: three computes an\nInstancedMesh's bounding sphere from its instance matrices and CACHES it. The\nold dispose-and-recreate got a fresh one by accident. Reusing the mesh means\ninvalidating it explicitly, or the props get frustum-culled against wherever\nthey used to be.\n\nslopeAt now asks coarseHeightAt rather than heightAt. It is deciding whether\nground is too steep to stand a tree on — a question about the shape of the\nterrain — and the fine layer is metre-scale noise laid over that shape. It was\ndragging a 4-octave fBm through four samples for every candidate cell in a\n23x23 sweep to answer something the stored world already knew. Where a prop\nactually STANDS still uses heightAt, so trees sit on the bumps you can see.\n\nAlso hoisted four Vector3 and two Matrix4 out of the per-instance loop.\n\nVerified: a new headless check drives two rebuilds and asserts the meshes,\ngeometries and materials are the same objects before and after, that counts\nrefresh and stay inside capacity, that the bounding sphere is invalidated,\nthat empty layers stop drawing, that a second Vegetation shares the same\nprototypes, and that disposing one does not destroy them for the other.","parents":["83e50e84d2fa3c8a540b8868a3f9c079e4813e6e"],"add":251,"del":43,"cadd":251,"cdel":43,"files":2},{"repo":"hexa","hash":"19243547304c758700189fd70dda8d960829da36","ts":1785941903,"wall":"2026-08-05T10:58","msg":"perf: globe internals — flat arrays, 16-bit indices, a shell built over frames","body":"buildPatch allocated a three-element JS array per vertex and held all of them\nuntil the patch finished: 12,769 live allocations for one detail patch. Now a\nsingle flat Float32Array, with one scratch tuple reused for the colour lookup.\n\nIndices were always Uint32Array. Every patch built here is well under the\n65,536 a Uint16 can address — the largest is 113x113 = 12,769 — so the wide\ntype was never once needed. Chosen by vertex count rather than hardcoded, so\nit stays correct if the constants move.\n\nThe far shell was built entirely in the constructor: six faces of 4,225\nvertices, each vertex costing a heightAt and a groundColor, before anything\ncould reach the screen. Only the face under the spawn is built now; the other\nfive are pumped one per frame from the render loop. Driven by the clock rather\nthan by input, because standing still must not leave the rest of the globe\nmissing.\n\nblurColors allocated a scratch buffer per call — reused now. Globe had no\ndispose() at all; far shell, ocean and the shared material were never\nreleased.\n\nVerified by a new headless check that measures the SCENE GRAPH rather than\nre-deriving the constants: the shell starts at one face and reaches six under\npumping, pumping past the end is harmless, every terrain index buffer is\n16-bit, no patch exceeds what Uint16 can address, every patch is wound\noutward (a patch facing inward is backface-culled and the planet goes\ninvisible), and dispose empties the shell.\n\nIt also puts a number on what comes next. At ground level the scene holds\n554,496 triangles across 25 meshes, and 261,120 of them — 47% — are the ocean\nsphere. That is the next commit.","parents":["e2d98749ba6fb51aec8473f4f9c679ad7cb1e5ea"],"add":220,"del":26,"cadd":220,"cdel":26,"files":3},{"repo":"hexa","hash":"a8f796ca78b6c1e6a5aafdd15879f1ad86bbe6cd","ts":1785943457,"wall":"2026-08-05T11:24","msg":"perf: tier the ocean — 554k triangles down to 298k","body":"The globe's tiering was never the problem. Far shell, near tiles, detail\npatches is the right architecture and it works. The ocean was the problem: one\nSphereGeometry(radius, 512, 256) covering the entire planet, always resident,\nalways drawn, and transparent, so it could not even early-Z. Measured against\nthe real scene graph it was 261,120 triangles — 47% of everything drawn.\n\nThe 512 was defended on sag, and the defence was sound: a flat facet spanning\nchord c on a sphere of radius R sits (c/2)^2/2R below the true surface, so at\n96 segments that is a 1.3 km chord and a ten metre error, which drowns and\nexposes whole coastlines. But it is an argument about water you are STANDING\nNEXT TO. Past the 283 m horizon nobody can measure it.\n\nSo the sea is tiered like the land. Near water is a flat grid at the waterline\nover each tile that contains any — no heightAt, no groundColor, no blur, since\nthe sea is level — stepping 2 cells, which is a 113 m chord and 8 cm of sag.\nFar water is one sphere at 256 segments, 1.5 m of sag, seen only from a\ndistance.\n\nExactly one of the two is ever drawn, switched on stand-off. They sit at the\nsame radius, so both would z-fight, and both being transparent they would\nblend twice and darken the sea where they overlapped. The threshold is chosen\nagainst tile reach: three tiles out is 6.3 km of coverage and the horizon from\n900 m is 6.0 km, so down low the near tiles genuinely cover the view.\n\nMeasured: ground level 554,496 -> 297,984 triangles, water 261,120 -> 4,608\n(1.5% of the frame, was 47%). From altitude the far sphere is 65,024 against\nthe old 262,144.\n\nAlso in this commit:\n\nThe far shell was six meshes, one per cube face, each with a planet-sized\nbounding sphere — so all six passed the frustum test whichever way you were\nfacing. Now 2x2 chunks per face, 24 meshes, and the far hemisphere can be\nrejected. Deliberately not 4x4: 96 draw calls costs more than the vertex\nshading it saves. Neighbouring chunks share their seam row and both compute it\nfrom the same (u, v), so there is no crack.\n\nPixel ratio walks 2 -> 1.5 -> 1 when frames run long, counted with a decay so\none unlucky frame during a patch build cannot trip it. One-way on purpose:\nstepping back up on a lucky stretch oscillates, and the step that CAUSED the\ngood stretch is the one you would be undoing.\n\nEvery knob that trades detail for frame time now lives in quality.ts. Not an\nauto-detecting quality system — a table you can read beats a heuristic you\nhave to trust.\n\nVerified: the globe check now measures only meshes that would actually be\nDRAWN, since an invisible one costs nothing, and asserts the budget, the water\nshare, that the far sphere is absent at ground level and alone at altitude,\n16-bit indices throughout, and outward winding. 198 server tests unchanged.","parents":["19243547304c758700189fd70dda8d960829da36"],"add":348,"del":101,"cadd":348,"cdel":101,"files":4},{"repo":"hexa","hash":"befad0cb8fc8814fab08b129cb8dcbb886b48363","ts":1785943587,"wall":"2026-08-05T11:26","msg":"feat: night is carried by colour, and lamps are worth carrying","body":"Researched rather than derived, after the physics-first version produced a\nnight nobody could play in. The prior art is unanimous and says the opposite\nof what was built: \"make it feel dark, but don't actually make it dark.\"\nDarkness on a screen is a COLOUR treatment, not a luminance level. Film has\nknown it for a century — shoot in daylight, underexpose a little, tint blue —\nand the reason it works is the Purkinje shift: below about 0.03 cd/m2 the rods\ntake over, and rods peak near 500 nm and are nearly blind to red. Real night\nvision is desaturated and blue-green. Reproduce those cues and the viewer\nreads \"night\" at any brightness.\n\nSo the night ambient is now a strongly blue, low-saturation hemisphere light,\nwhich IS that desaturation for free — a blue light on a red surface renders it\ngrey. No post pass, no render target. New moon is deep and near-monochrome,\nfull moon paler and more silver with some colour returning, so the moon drives\nthe grade as well as the level.\n\nThe lamps were drowned by that. Raising the night floor left a torch at\n1.19 cd sitting under an ambient of 1.0 — invisible. A single LAMP_GAIN lifts\nevery lamp together, so a tactical light stays exactly 12,000x a torch and the\nserver's reach ordering is untouched.\n\nThe bigger fix was the falloff. decay was 2 — pure inverse square, physically\nright and gameplay-wrong: a torch put 1.19 lux at a metre and 0.13 at three,\na bright spot with nothing around it. Games routinely do not use pure inverse\nsquare for this exact reason. At 1.4 the same torch holds 0.26 at three metres\nand 0.065 at eight. three's own falloff needed no help otherwise — it is\nFrostbite's windowed form, clamped near the source, converging at the cutoff.\n\nLamps also gained a glare sprite, sized by the LOG of intensity. A lamp's real\njob on screen is to look brighter than the screen can go, and the pixels run\nout long before the candela do. Linear sizing would make the tactical halo a\nhundred times the torch's; the eye does not read brightness that way. The moon\nalready used this trick, so its glow texture moved to a shared glow.ts. What\nthis cannot do is bloom the over-range ground UNDER a beam — that needs a real\nHDR pass, and is deliberately not in this commit.\n\nVerified: the photometry check now also asserts a torch meaningfully lifts the\nnight floor — that coupling lives in two files with no reason to be read\ntogether — and that the gain stays a uniform scalar so lamp ranks cannot drift\nfrom the server's reach ordering.","parents":["a8f796ca78b6c1e6a5aafdd15879f1ad86bbe6cd"],"add":175,"del":34,"cadd":175,"cdel":34,"files":5},{"repo":"hexa","hash":"e98a846bb49a86776ef9a2373fdfb78ac90cae31","ts":1785943632,"wall":"2026-08-05T11:27","msg":"docs: persist the sky/lighting and render-audit plans under semantic names","body":"","parents":["befad0cb8fc8814fab08b129cb8dcbb886b48363"],"add":291,"del":0,"cadd":291,"cdel":0,"files":2},{"repo":"hexa","hash":"f6c539437e6acea9284a6c19be0e47f3fbdee7b0","ts":1785944653,"wall":"2026-08-05T11:44","msg":"fix: selection rings went black by day and gold by dark","body":"My bug, from adding adaptive exposure. The rings were already unlit —\nMeshBasicMaterial — which is why this looked impossible at first. Unlit is not\nenough: toneMappingExposure multiplies EVERY material that does not opt out,\nand exposure now runs from 2.7e-5 at noon to 1.2 at night. Five orders of\nmagnitude through a fixed gold gives black in daylight and gold in the dark,\nwhich is precisely what the operator saw.\n\ntoneMapped: false on the things the player is meant to READ — selection ring,\nrelation ring, HP bar, order marker, and the lamp flame's own dot. The flame\nmatters for a different reason: it is opaque, so exposure rendered it as a\nblack dot rather than merely dimming it away.\n\nThe two additive glows are deliberately left exposed. Additive blending fades\ntoward nothing as the scene brightens, which is exactly what a torch's halo\nand the moon's halo should do in daylight — those are glows, not readouts.\n\nGuarded by a source scan rather than a scene walk: PawnManager needs GLTF rigs\nand a canvas and will not construct in Node, and toneMapped is a\nconstruction-time literal, so the source is the truth. Every MeshBasicMaterial\nand SpriteMaterial must now declare its intent — toneMapped: false for UI, or\nAdditiveBlending for a glow — and a new one that declares neither fails.","parents":["e98a846bb49a86776ef9a2373fdfb78ac90cae31"],"add":120,"del":5,"cadd":120,"cdel":5,"files":3},{"repo":"hexa","hash":"e2186c667952b2d6a03f3c844a08df493fd7e8ea","ts":1785948358,"wall":"2026-08-05T12:45","msg":"feat: drop and ground piles — a closed world gets no delete key","body":"A pawn could harvest itself into permanent overencumbrance with no way out.\nwork.py added to `carrying` and nothing ever took it away; there was no drop\nverb at all.\n\nThe fix could not be \"remove the units\". Everything else in the resource\ndesign rests on matter not vanishing — ore becomes ingot becomes blade becomes\nscrap becomes ingot, and only the furnace takes its cut — so drop has to mean\n\"put it there\", which means something has to hold it once it is there.\n\nworld/piles.py: a pile is a heap of raw units at a place, owned by nobody,\nvisible to everybody, lifted by whoever walks to it. Piles merge, because\nsetting a load down where a load already lies is what a person would do and it\nkeeps the count bounded. Dust below an epsilon is swept, since harvest yields\nare floats and subtraction leaves residue.\n\nTwo verbs. `drop` with no resource puts everything down, which is the order an\noverladen pawn actually needs. `take` lifts from a pile within reach, bounded\nby what the pawn can still bear.\n\nThose two deliberately disagree about encumbrance, and it is worth saying why:\ndigging is work that accumulates whether or not you are ready for it — that is\nhow a pawn gets overladen in the first place. Choosing to shoulder a heap you\nplainly cannot carry is not work, it is a mistake, and the shard declines to\nmake it for you.\n\nPiles persist in the snapshot. Losing them across a restart would quietly\ndelete matter, which is the one thing this world may not do. Old snapshots\nwithout the key load fine and start empty.\n\nOn the wire they are filtered to those near a player's own pawns — piles\naccumulate over the life of a world and you can only walk to what is in front\nof you. Client renders them as lit heaps coloured by whatever there is most\nof, sized by the cube root of the load, and the order menu grows a Load\nsection: put everything down, put down one named thing, or pick up.\n\nVerified 15 unit tests, and — because a handler can be correct, tested and\ncompletely unreachable, which has already happened in this shard — an\nend-to-end probe on a SCRATCH shard on 8702 that drives the real socket:\nharvest, drop, confirm the pile appears with the same mass that left the\npawn's hands, then take and confirm it comes back. 213 server tests green.","parents":["f6c539437e6acea9284a6c19be0e47f3fbdee7b0"],"add":976,"del":3,"cadd":976,"cdel":3,"files":13},{"repo":"hexa","hash":"f0ad99d6aa563700505998ee5caaeb676418cecb","ts":1785950251,"wall":"2026-08-05T13:17","msg":"feat: working and lifting build the back that does them","body":"Operator's call on the encumbrance numbers: leave the weights alone, bulk\nhauling belongs to carts and draft animals, but labour should slowly make a\npawn stronger. This is that, and it turned out to be two halves of which only\none existed.\n\nThe `labour` skill was already there, governed by strength and endurance, and\nalready trained by every swing of a pick and every felled tree — and it did\nabsolutely nothing for carrying. Capacity was bare strength/STR_PER_CARRY. A\npawn could spend a lifetime quarrying stone and be no better at carrying the\nquarry. Capacity now counts it.\n\nThe other half is that carrying itself trains, the way running trains\nathletics. Hauling was the one part of the work that paid nothing, which is\nbackwards — hauling is most of what the work actually IS. A loaded back is a\nback in training.\n\nBounded by a FULL load rather than the load carried, so an overladen pawn\ntrains at exactly the same rate as a fully laden one. Nothing to be farmed by\ndeliberately crippling a pawn, and a pawn already eating the encumbrance\npenalty at least earns something for it.\n\nWhat it buys, measured:\n\n  labour   0 -> 12 kg      full-load training is 0.012/s,\n  labour  50 -> 13 kg      about 21 minutes of hauling\n  labour 100 -> 16 kg      for the first fifteen points\n\nDeliberately modest, and there is a test pinning it: even a perfect labourer\ncannot shoulder one unit of stone. Training must never quietly become an\nalternative to the cart it is supposed to be waiting for.\n\nBaseline capacity moves 10 -> 12 as a side effect, because labour has an\naptitude floor of 25 from strength and endurance before a single point is\ntrained. test_gear's baseline was updated to say why rather than to a new\nmagic number.\n\n222 server tests green, 9 of them new.","parents":["e2186c667952b2d6a03f3c844a08df493fd7e8ea"],"add":201,"del":2,"cadd":201,"cdel":2,"files":5},{"repo":"hexa","hash":"fbaf02b5f831893e45a9529eafd03788f9d3c0f5","ts":1785951355,"wall":"2026-08-05T13:35","msg":"docs: research the biosphere instead of inventing it","body":"The operator's brief was ferns, gymnosperms, spore-bearers, lichens, insects\nand fungi, small gliding mammals, flightless raptor-analogues, and a composite\nfungal/arthropod organism — with the note \"primitive? But not really.\"\n\nThat instinct has a precise form, and it turns out to be a single axiom:\nFLOWERS NEVER HAPPENED. Every item on the list is downstream of removing one\nclade, which is the test of a good axiom — the world stops being a list of\nchosen features and becomes a consequence.\n\nNo angiosperms costs grass, fruit, nectar, hardwood, and the pollinator\neconomy. It keeps WOOD, because conifers are gymnosperms and gymnosperm timber\nis excellent — which matters more than any other line here, since charcoal and\nconstruction are load-bearing for the economy already shipped.\n\nIt also solves the fibre problem rather than creating one. Cotton, flax, hemp,\njute and ramie are every one of them angiosperms, so plant fibre essentially\ndoes not exist on this world and textiles MUST be animal and fungal. The\noperator's instinct to source fibre from silk was not a preference; his own\npremise had already required it.\n\nTwo anchors did real work:\n\nHarrison, Kaiser & VandenBrooks (2010) on hyperoxia and insect gigantism is\nthe obvious one. But Clapham & Karr (2012) is the better argument: insect size\ntracks oxygen through the Palaeozoic and then DECOUPLES after the Jurassic,\nonce birds radiate and aerial predation constrains size more than atmosphere\ndoes. Hexa's avian-analogues are flightless. The predator ceiling that shrank\nEarth's insects was never installed here — which justifies large arthropods\nwithout asking the renderer for any physics.\n\nAmadou gives the fibre ladder a bottom rung that is not invented at all:\nFomes fomentarius worked into felt, attested in Otzi's kit 5,300 years ago and\nstill made in Transylvania, with a documented process (boil, beat, dry, work by\nhand; nitrate it to take a spark). A complete production chain, already real.\n\nThe doc separates what is anchored from what is asserted from what is\ninvented, and says which is which. The composite organism is design, not\nbiology, and is labelled so rather than dressed as a finding.\n\nIngested to unicursal — 13 fragments, 11 axes.","parents":["f0ad99d6aa563700505998ee5caaeb676418cecb"],"add":250,"del":0,"cadd":250,"cdel":0,"files":1},{"repo":"hexa","hash":"2a0e61993401ad96e3614493bd296ad6752ab17f","ts":1785952273,"wall":"2026-08-05T13:51","msg":"docs: correct two errors in the biosphere doc, and gain a better world for it","body":"Operator caught both.\n\nFIBRE IS NOT SCARCE HERE. The doc claimed that because cotton, flax and hemp\nare angiosperms, plant fibre essentially could not exist. Wrong twice. Western\nred cedar is a conifer and Northwest Coast peoples made cordage, matting and\nclothing from its bark for millennia — a world of conifers is not a world\nwithout textiles, it is a world whose textiles are bark. And an absent clade\nconstrains HISTORY, not chemistry: bast-like fibre is a structural solution,\nnot an angiosperm invention, and nothing stops a gymnosperm or fern lineage\nconverging on it. `fibre` stays a plant product; fungal and animal fibres are\nadditions beside it rather than replacements for something missing.\n\nTHE AERIAL PREDATION CEILING IS NOT ABSENT. This is the sharper correction and\nthe argument was self-defeating as written. Clapham & Karr is right that insect\nsize decouples from oxygen once birds radiate and hunt on the wing — but the\ndoc removed birds and then put insectivorous flying mammals in the air, which\nis the same selective pressure wearing a different coat. It is what bats do.\n\nThe fix is not to dodge the pressure but to let it split the arthropods in two:\nsmall and numerous in the air where things hunt on the wing, large on the\nground where nothing airborne constrains a two-metre detritivore — and the\nground megafaunal roles are open anyway, since the grasslands that would feed\nlarge herbivores never existed. That is a better world than one where\neverything is uniformly big: two halves with different ecologies, different\nhunting mechanics, and different reasons to be afraid.\n\nIt also makes one vague thing load-bearing and therefore worth deciding:\nwhether the fliers glide or fly under power. Powered flight makes them real\naerial predators and pins flying arthropods small; gliding makes them\nopportunists and relaxes the ceiling.\n\nThe fibre ladder is now five rungs sorted by KIND OF WORK — harvest, harvest\nand process, hunt, cultivate, husband — rather than by scarcity.\n\nBoth corrections are recorded in the confidence section so they are not made\nagain. Re-ingested: 14 fragments.","parents":["fbaf02b5f831893e45a9529eafd03788f9d3c0f5"],"add":79,"del":23,"cadd":79,"cdel":23,"files":1},{"repo":"hexa","hash":"6bd3489168faca1aab08be489abef3e96afbfccb","ts":1785953312,"wall":"2026-08-05T14:08","msg":"docs: research L1 — the producers came back richer than three resources","body":"Building the biosphere one trophic level at a time, so L1 has to be right\nfirst: everything above it eats this and every material chain starts here.\nEight producer resources rather than the three originally guessed, and three\nof the findings change the design rather than decorating it.\n\nSPHAGNUM IS THE TANNING AGENT. Its cell-wall polysaccharide sphagnan tans\ncollagen — it is the mechanism that preserves bog bodies. That matters here\nspecifically because this world has no oak, oak being an angiosperm, so the\nobvious tanning route does not exist. The axiom forced a better answer than\nthe one it removed, and the answer is fully attested. Conifer bark tannin\n(hemlock and larch, an industry rather than a folk practice) is the second\nroute.\n\nBRACKEN POTASH IS SEASONAL. Roots run about 20% potash in early summer and 5%\nby autumn, and fern ash was a real raw material for Bohemian potassium-calcium\nglass. This world now HAS seasons — the heliocentric sky was built for the look\nof it, but the sub-solar latitude genuinely migrates over a 32-day year. A\nresource whose yield depends on the time of year turns that from scenery into\neconomics, and it is the only mechanic on the list that could not have existed\na week ago.\n\nPEAT IS A THIRD RESOURCE CLASS. The economy divides cleanly into renewable\n(living, comes back) and finite (geological, does not). Peat is neither:\nbiotic in origin, accumulating at about a millimetre a year, so finite across\nany timescale a player inhabits. It is the bridge between the two halves of a\nworld built on the claim that living things return and minerals do not — and\nit is a FUEL, which is where that ambiguity bites hardest. It also splits the\nfuel chain: timber is currently lumber, charcoal and firewood at once, so\nforests bottleneck the moment anyone smelts seriously. A swamp becomes a fuel\nprovince and the choice between burning wood and cutting turf acquires\ngeography.\n\nAlso found: lichen dyes (orchil purple, in use by the Phoenicians ~3000 BC)\nand LITMUS, which is the first chemical instrument anyone on this planet could\nown; sphagnum as a wound dressing from the Bronze Age through 1914-18;\nlycopodium flash powder; Equisetum silica; and naval stores — tar, pitch and\nturpentine tapped from living conifers, which is what preserves rope and\nwaterproofs a hull.\n\nSeven new citations. Re-ingested: 18 fragments.","parents":["2a0e61993401ad96e3614493bd296ad6752ab17f"],"add":106,"del":0,"cadd":106,"cdel":0,"files":1},{"repo":"hexa","hash":"9a7d25cda903ae322137b9208cbe65edd8412608","ts":1785954263,"wall":"2026-08-05T14:24","msg":"docs: L1 had no sea and no nitrogen — and peat's honest rate is not slow","body":"Two gaps in the producer list, both structural.\n\nTHE SEA. Sixty per cent of this planet is ocean and the list had no marine\nproducers in it whatsoever. Kelp burned in pits was one of the principal\nindustrial sources of SODA ASH before the Leblanc process — glass, soap,\nceramic glaze — plus iodine and alginate, at about twenty tons of wet weed per\nton of ash, cut chest-deep and dried before burning. That ratio is a feature:\nit makes a coast worth settling and gives shore work a character inland work\ndoes not have. Paired with bracken it also gives the world TWO ALKALIS FROM\nTWO BIOMES — potash from the ferns of the interior, soda ash from the kelp of\nthe shore — and since potash glass and soda-lime glass behave differently,\nglassmaking acquires a geography. The axiom also strips the water: seagrass\nand mangroves are angiosperms, so a shoreline here is bare rock, kelp and moss.\n\nNITROGEN, and this is the best find in the document. Legumes are angiosperms,\nso Earth's most important nitrogen-fixing partnership does not exist here — and\nthe replacement is BETTER and is itself a composite organism. The water fern\nAzolla carries an endosymbiotic cyanobacterium and fixes at roughly twice the\nlegume-rhizobium rate, doubling its biomass in as little as two days; it is a\nrice fertiliser worldwide today. Cyanobacteria also fix inside lichens, inside\nthe coralloid roots of every cycad examined, and with bryophytes and a marine\ndiatom. So the nitrogen economy of this world runs almost entirely through\ncyanobacterial partnerships: its soil fertility IS its symbiosis. Same\nstructural move as sphagnum replacing oak, and it lands on the project's own\nthesis rather than beside it.\n\nPEAT, HONESTLY. Operator asked for the real number rather than a convenient\nzero, and the arithmetic is counterintuitive. Peat accumulates about a\nmillimetre a year; on a 3,196 m2 cell at 150 kg/m3 that is 479 kg or 32 units\na year. But a game year is 10.7 real hours — an 822x compression — so the\nhonest regrow_per_second is 0.000832, FASTER than timber (0.00025) and fibre\n(0.0006). A millimetre a year is not slow when the year is ten hours long.\n\nWhat makes peat geological is the DEPTH, not the rate. A two-metre bog holds\nabout 64,000 units, the same order as an iron cell's 62,000, so cutting one\nout and waiting for it back is 2,000 game-years. Honest pool, honest rate, and\nthe behaviour that falls out is the one wanted: a cut bank heals within a\nsession and the bog is finite on any timescale anyone will play. It earns its\nplace between the living and the mineral by being genuinely both, not by being\na renewable with its regrowth switched off.\n\nTen producers now, against three. Four new citations. Still unresearched and\nlisted as such: diatomaceous earth, stoneworts, hornworts, liverworts, and\nwhether cycad sago earns a food chain given it needs detoxifying first.\nRe-ingested: 21 fragments.","parents":["6bd3489168faca1aab08be489abef3e96afbfccb"],"add":99,"del":3,"cadd":99,"cdel":3,"files":1},{"repo":"hexa","hash":"cc9c334aa1cf357c0cfb43fa3d76def2622aef89","ts":1785954935,"wall":"2026-08-05T14:35","msg":"docs: close the L1 gaps — diatomite is the best item on the list","body":"DIATOMITE. Diatoms are algae in glass houses; their fossil shells make a rock\nthe Greeks used as abrasive and lightweight brick, that filters water and beer,\nand that Nobel used to absorb and stabilise nitroglycerine. But the reason it\nmatters HERE is the insecticide mechanism: it kills arthropods PHYSICALLY, the\nfine powder absorbing lipids out of the waxy cuticle until the animal dies of\ndehydration. No toxin, no receptor, nothing to evolve resistance to.\n\nOn a planet whose dominant animals are arthropods that is not a footnote. It\nis the answer to how a settlement holds a perimeter against something with an\nexoskeleton — a dusted threshold, a powdered store-room, a line across a\ntunnel mouth — and it should be ordinary, unglamorous, and work every time.\n\nIt also confirms the third resource class is a category rather than a special\ncase pleaded for peat. Sphagnum makes peat; diatoms make diatomite. Both are\nfossil deposits of L1 producers, biotic in origin and geological in practice.\nOne is a fuel and one is a weapon. Diatoms are L1 and living; diatomite is a\ndeposit and belongs with the ore.\n\nCYCAD SAGO. Cycasin and BMAA are neurotoxins implicated in the Guam\nParkinson-ALS complex, and the pith is a starch staple anyway, because cycasin\nis water-soluble and leaches: the Chamorro preparation soaks for about three\nweeks with water changes every two or three days, and even 24 hours removes\nroughly 90% of the BMAA. Food that is poison until you know the process, where\nthe process is mostly patience — time-gated rather than skill-gated, which\nsuits a world where real days pass.\n\nAN HONEST NEGATIVE. Hornworts, liverworts and freshwater stoneworts were\nresearched and do not earn resources. They are ground cover and ecological\ntexture, the things that make a bog look like a bog. Not every clade has to\npay rent. Stoneworts encrusting themselves in calcium carbonate to form marl\nis the one lead worth remembering, but it is unverified and the world already\nhas limestone, so it stays a note.\n\nEleven living producers plus one deposit. Four new citations.\nRe-ingested: 22 fragments.","parents":["9a7d25cda903ae322137b9208cbe65edd8412608"],"add":72,"del":6,"cadd":72,"cdel":6,"files":1},{"repo":"hexa","hash":"473c9185d68eb7bc24d81a305bbe8f61ee80937e","ts":1785961257,"wall":"2026-08-05T16:20","msg":"fix: a permanent world stops being re-derived from its seed every boot","body":"The operator named this one. generate_geology() ran at startup and drew from\nrandom.Random(seed ^ 0x0DEB05), so the world's mineral geography was a dice\nroll repeated on every restart rather than a property of the world. Measured:\nappending ONE class to DEPOSITS moves nine of fourteen provinces — tin leaves\ntwo of them and appears in a third — and every survey anyone had made would\nhave gone on pointing at ore that had quietly left.\n\nThe module's own docstring already promised the right thing: \"generated once\nand lives forever; its geology is part of it, not a roll made at load.\" The\ncode only achieved that by accident, and only for as long as nobody edited it.\n\nAn earlier draft of the fix used a second RNG stream so the existing draw\nstayed undisturbed. That preserves the world by arithmetic luck and would\nbreak again the moment province count or seed scattering changed. Rejected in\nfavour of the obvious thing: the world is authored, so its geology is a file.\n\nRNG only ever touched two things — the 14 province seed points and each\nprovince's deposit set. Everything else is geometry. So data/geology.json\ncarries 2,472 bytes of seeds and deposits, hand-editable, and the rest is\nrebuilt. Deciding a province should bear tin is now done by opening a file and\nsaying so, which is what an authored world deserves.\n\nVerified the refactor did not move the world: regenerating with the new code\nproduces seeds and deposits identical to the committed file.\n\nWHILE IN THERE, two things measurement made obvious.\n\nBoot was spending 64 SECONDS assigning 1.57 M cells to their nearest province,\nagainst 0.03 s to read planet.bin — effectively the whole cost of starting a\nshard, paid every restart. That is baked now to a binary cache keyed by a hash\nof its inputs: source asset in JSON, build artifact in binary, gitignored,\nregenerated automatically whenever the source changes so a hand-edit can never\nleave a stale partition behind. Cold 42.4 s, warm 0.006 s — 7,179x.\n\nAnd `richness` was a 6.3 MB float array built by walking every cell at boot to\nanswer a question that is O(1) whenever anyone asks it, which is a few times a\ntick while somebody is digging. It is computed on demand now and the array is\ngone.\n\n232 tests green, 10 new: the file round-trips, a future format is refused, a\ntypo'd deposit name is refused rather than silently bearing nothing, the cache\nis believed when inputs match and ignored when they do not, a corrupt cache is\nignored rather than trusted, and the committed world still bears every class\nworth bearing. Tests keep generating their own geology over their own small\nplanets — the one place a fresh roll is the right answer.","parents":["cc9c334aa1cf357c0cfb43fa3d76def2622aef89"],"add":621,"del":45,"cadd":466,"cdel":45,"files":8},{"repo":"hexa","hash":"9d7c97738db74cf383204a257145812ce8ed3270","ts":1785966634,"wall":"2026-08-05T17:50","msg":"feat: trophic level 1 — the producers of a world without flowers","body":"Thirteen living resources, built one trophic level at a time as the operator\nasked. Everything above eats this and every material chain starts here.\n\nSee research/biosphere-without-flowers.md. No angiosperms, so no grass, no\nfruit and no nectar — but conifers, ferns, clubmosses, horsetails, lichens,\nkelp and a great deal of fungus. Pools are sized from BIOMASS the way the ore\npools were sized from mass in the ground: cell area, a plausible standing crop\nper square metre, and the weight of one unit. None of them chosen by feel.\n\nNOWHERE IS BARREN NOW. Water bore nothing but fish on a planet that is 60%\nocean; it has kelp and azolla. Mountains bear lichen and only lichen, which is\nthe correct amount of life for bare rock.\n\nPEAT CARRIES THE HONEST NUMBERS rather than a convenient zero. It accumulates\nabout a millimetre a year — 479 kg, 32 units, over a 3,196 m2 cell — but a\ngame year is 10.7 real hours, an 822x compression, so the true rate is FASTER\nthan timber's. What makes peat geological is the DEPTH: two metres of bog is\n64,000 units, so cutting one out and waiting for it back is 2,003 game-years.\nA cut bank heals within a session and the bog never does. Both facts are\nasserted in tests rather than left in a comment.\n\nFIBRE COMES OUT OF WOOD, per the operator's correction. ret_bark takes conifer\nbark to fibre, and a test proves a forest alone can reach rope without ever\nfinding a fibre plant. Cedar bark clothed the Northwest Coast for millennia —\na world of conifers is not a world without textiles, it is a world whose\ntextiles are bark.\n\nTOOLS GATE THE GROUND. The draft had no tool_tag on anything, which would have\nleft eleven things harvestable barehanded while a log needs an axe. Peat gets\nits own tag: a turf spade is not a pick and not an axe, because peat is cut in\nbricks with a long one-sided blade, so the world's second fuel is gated behind\na tool that had to be invented for it. New item, new forge recipe.\n\nAND best_resource_at NEEDED REWORKING, or one-click \"work this ground\" would\nhave answered wrongly in a wood. Two simpler rules were tried and both failed:\n\"rarest\" gives a forest resin (pool 150) over timber, and \"largest pool\" gives\nit bracken (2,100 against timber's 1,200) — ferns really are denser ground\ncover than trees are trees, but nobody clicking on a wood means the ferns.\nMass throughput settles it, and is a physical way of asking what ground is\nFOR: timber moves 8.25 kg/s against bracken's 2.1, and the same rule puts kelp\nahead of fish at sea without being told to. Ore still wins by scarcity, since\na cell with tin under it should offer the tin.\n\n248 tests green, 16 new. Two of the new ones caught my own bad premises: tin\nis only offered where its BIOME allows as well as its deposit class, so a\nplains cell over a tin province has no tin to give.","parents":["473c9185d68eb7bc24d81a305bbe8f61ee80937e"],"add":400,"del":5,"cadd":381,"cdel":5,"files":6},{"repo":"hexa","hash":"877526afefe9605eb275ac753a39685f36df99f6","ts":1785972152,"wall":"2026-08-05T19:22","msg":"docs: the sere, arborescence as a form, and an organelle that stayed outside","body":"THE SERE. A sere is the whole sequence of communities that replace one another\non a piece of ground, pioneer to climax; each step is a seral stage. Named for\nwhat they start from — lithosere on bare rock, hydrosere in open water,\npsammosere on sand, halosere in salt marsh. Worth noting that the PEAT\nresource is a hydrosere caught in the act: a bog is not a place, it is a\nprocess several thousand years in.\n\nEarth's canonical ladder is rock, lichen, moss, GRASS, shrub, trees, climax —\nand grass is the only angiosperm rung in it. Remove that one and the hole is\nfilled by exactly the plants that are aggressive pioneers on Earth anyway:\nbracken takes burned ground and Equisetum takes volcanic ash and mine spoil.\nSeven stages, mm to 50 m. Degraded ground stops being \"empty terrain\" and\nbecomes stage 0 on its way somewhere.\n\nTREE IS A FORM, NOT A CLADE — the operator's correction, and load-bearing.\nArborescence is a strategy that enough lineages found independently that the\nword says nothing about ancestry. Lycopsids made Lepidodendron at 30-50 m with\ntrunks 1-2 m across. Horsetails made Calamites at 10-15 m, spreading clonally\ninto thickets. Ferns made tree ferns and still do. Gymnosperms made the\nconifers this world already has.\n\nThree fossil facts each do work. The giants were bare poles crowning only at\nthe top, which is trivial as a growth rule and unmistakable as a silhouette.\nThe canopy was OPEN, not closed, so the understorey is never shaded out and\nall seven seral stages can stand in one view — a forest legible in depth\nrather than a green ceiling. And they were structurally HERBS, load borne by\nwater-laden parenchyma, so a forty-metre lycopsid trunk is soft, fibrous and\nwet. A lycopsid trunk is not timber, and pretending they are one resource\nwould waste the most interesting material fact on the planet.\n\nPROTOTAXITES, and this is the best idea in the document, both halves of it the\noperator's.\n\nFirst: it is its own eukaryote. Not plant, fungus, animal or lichen but a\nfourth lineage — which is not a liberty with the science but the current\nreading of it, the 2026 work finding it structurally and chemically distinct\nfrom every known fungus and proposing exactly an extinct eukaryotic lineage.\nThis world declines to let it go extinct.\n\nSecond, and better: it is an EXOSYMBIONT. Mitochondria and chloroplasts are\nthe same story told twice — engulfed, kept, and the host gains something it\ncould never evolve alone. Prototaxites is that story with the topology\ninverted. It was never swallowed. It stayed outside, got enormous, and\neverything else plugs into IT.\n\nWhat it supplies is nitrogen, which is not arbitrary: this document already\nestablished that legumes are angiosperms, that the nitrogen economy therefore\nruns through cyanobacterial partnerships, and that this world's soil fertility\nIS its symbiosis. This gives that fact a body. The planet fixes nitrogen at\ntwo scales — endo, inside azolla and lichens and cycad roots; exo, in one\norganism spanning the world, of which the 8 m columns are only what surfaces.\n\nIt feeds by taking a cut of what it moves. A toll, not a harvest — so it is\nneither producer nor decomposer but a third thing running transverse to the\ntrophic ladder. Ground becomes fertile because it is CONNECTED. Cutting a\ncolumn costs everything plugged in through that node. It is planetary\nstructure that is neither biome nor province: a graph laid across the world,\nand the first thing in this design that is a map rather than a field. And for\na player who intends to run a gestalt, an organism that is already a\ndistributed body with everything joined to it is not scenery — it is the thing\nto join.\n\nPALETTE. Ochre, blue-green and grey-purple, per the operator, and it is more\nfaithful than the green we currently draw, because green dominance IS the\nangiosperm palette. Sphagnum is rust and ochre as often as green, azolla turns\ndeep red in strong light, many cycads are genuinely glaucous blue, lichens run\norange through orchil purple, horsetail is dull grey-green from its silica,\nand bracken turns rust dying back — which is the year model asking to be used.\n\nAlso recorded: the operator intends to play as a hive intelligence and to\nbuild composite bodies for that mind to inhabit. That makes the composite\norganism not merely fauna to encounter but a template for what a player can\nbecome, and anything designed for it should be designed with a player inside.\n\nSix new citations. Re-ingested: 32 fragments.","parents":["9d7c97738db74cf383204a257145812ce8ed3270"],"add":248,"del":7,"cadd":248,"cdel":7,"files":1},{"repo":"hexa","hash":"7aa9f14e7286221bd3bc691f3611b6540e8a2c0d","ts":1785973554,"wall":"2026-08-05T19:45","msg":"feat: diatomite — the defence an exoskeleton cannot adapt to","body":"Fossil diatoms: algae in glass houses, piled up in a dead lake bed. The Greeks\ncut it for abrasive and lightweight brick, it filters water and beer, and\nNobel used it to make nitroglycerine safe to carry.\n\nOn this planet it is a weapon, and an unanswerable one. The powder absorbs the\nlipids out of an arthropod's waxy cuticle and the animal dies of dehydration.\nNo toxin, no receptor, no metabolism to adapt — there is nothing to evolve\nresistance TO. On a world whose dominant animals wear their skeletons outside,\na dusted threshold is how a settlement holds a perimeter, and it should be\nordinary, unglamorous and work every time.\n\nSibling to limestone: both are fossil plankton, one silica and one carbonate.\nBiotic in origin and geological in practice — the same third class peat\nbelongs to, reached from the other direction. And it settles out of standing\nwater, so it is hills and plains, never mountain. A lakebed is not a\nmountaintop.\n\nTHIS IS THE CHANGE THAT WAS UNSAFE A COMMIT AGO. Appending a class to DEPOSITS\nused to reshuffle rng.sample for every province after it — nine of fourteen\nmoved when that was measured. Now geology is a file, so which provinces bear\nit is an EDITORIAL act rather than a dice roll, and it was made as one:\nprovinces 3 and 8, which bore nothing but stone and were the two dullest in\nthe world. Diatomite is a lacustrine sediment, so it keeps sedimentary company\nrather than sitting with the metals, and the two dull provinces become worth\nthe journey. Under 14.9% of the planet — scarce enough that a defence must be\nsought, common enough that it can be found. Not a keystone: tin is a\nbottleneck and belongs away from spawn, but being cornered near home without a\ndefence is a worse game than finding one on the doorstep.\n\nThe cache design earned itself here without being asked to. Editing which\ndeposits a province bears did NOT invalidate the province-assignment cache,\nbecause the key hashes the seed points and the face count and nothing else —\nprovince membership does not depend on what is buried in it. Geology still\nloads in 0.006 s after the edit.\n\nAlso pinned the permanent world's geology province-for-province in a test.\nDeliberately brittle: changing what a province bears is an editorial act on a\nworld meant to be kept, so it should be impossible to do by accident and\nimpossible to do without saying so. If that test fails, either something\nreshuffled the world — the thing the previous commit exists to prevent — or\nsomebody made a decision and owes the list an update.\n\n253 tests green, 5 new.","parents":["877526afefe9605eb275ac753a39685f36df99f6"],"add":97,"del":1,"cadd":95,"cdel":1,"files":5},{"repo":"hexa","hash":"2f5d051077758a4e8db3a643128ac149222c9e63","ts":1785975629,"wall":"2026-08-05T20:20","msg":"feat: the year reaches the server, and bracken knows what month it is","body":"Seasonal yield is the only mechanic on this planet that could not have existed\na week ago. Bracken roots run about 20% potash in early summer and 5% by\nautumn, and until the sky became heliocentric and the sub-solar latitude\nactually migrated, there was no early summer to run it in.\n\nworld/calendar.py is NOT a port of the whole sky. The shard needs one number —\nhow far north or south the sun stands — and it is unusually cheap, because the\nspin cannot touch it: rotating about +Y leaves the Y component alone, so\n\n    sub-solar latitude = asin( -cos(orbit) * sin(obliquity) )\n\nand everything the seasons need follows from that line.\n\nSEASONS ARE PER HEMISPHERE, not global. North and south are opposite and\npretending otherwise would have the whole planet flower on the same day.\nDerived from how high the sun gets at noon where you are: agreeing in sign\nwith your own latitude is summer, disagreeing is winter. The equator sits at\n0.5 all year and never leaves, which is correct rather than degenerate — the\ntropics do not have a growing season, they have weather. Two squads working\nbracken in opposite hemispheres are having opposite luck on the same tick.\n\nResourceDef gains ONE field, season_low: the yield multiplier at the worst\ntime of year. One number covers both real behaviours. Bracken is 0.25, a\ncontinuous fourfold swing. Fiddleheads are 0.05, because croziers appear\nbriefly and are then simply gone — a window rather than a slope, so a forest\nthat fed you in spring will not in autumn.\n\nDRIFT was the risk, since the orbital constants now exist in two languages,\nand two transcriptions agreeing with each other prove nothing. Guarded the way\nlamp photometry is: the test writes a probe, runs the REAL celestial.ts under\nnode, and compares. Worst disagreement across the year: 9.0e-17 radians. Year\nlength and axial tilt are asserted equal too, so a change to one side without\nthe other fails loudly rather than quietly desynchronising the sky from the\nharvest.\n\nTwo of my own test premises were wrong and the failures were worth having. A\ntick advances the ORBIT as well as the spin, so \"time of day cannot move the\nsun\" is untestable through this API — the honest version is that a day is\nsmall against a year, and it is. And the test planet's HOME sits exactly on\nthe equator, where there is no season at all; the REAL world's spawn is at\n+56.6 degrees and swings the full 0 to 1 across the year, so the mechanic is\nvisible where players actually stand. That now has a test of its own, because\na seasonal mechanic nobody can see is not a mechanic.\n\n269 tests green, 16 new.","parents":["7aa9f14e7286221bd3bc691f3611b6540e8a2c0d"],"add":332,"del":10,"cadd":332,"cdel":10,"files":4},{"repo":"hexa","hash":"510237fdd25a9f86d43d78d9ab3d6a8c9d4aa8ac","ts":1785979847,"wall":"2026-08-05T21:30","msg":"feat: repalette the world — green dominance was the angiosperm palette","body":"The ground and its dressing were coloured for a world with FLOWERS in it:\nyellow-green prairie, bright leaf-green woods, marsh grass. Hexa has no\nangiosperms, so it has no grass and no broadleaf canopy, and Earth-green was\nquietly the least faithful thing in the renderer.\n\nThis is not a stylistic override of realism. It is the correction of one.\nEvery colour below is what the organism actually is, from\nresearch/biosphere-without-flowers.md:\n\n  sphagnum   rust-red and ochre as often as green\n  cycads     many are genuinely glaucous blue\n  conifers   blue-green, pulled there by their own wax bloom\n  lichens    orange (Xanthoria) through grey-green to orchil purple\n  horsetail  dull grey-green — the silica gives it a sheen\n  bracken    green in season, rust and ochre dying back\n\nSo plains becomes lichen heath and moss barren instead of prairie, forest\nbecomes glaucous conifer instead of broadleaf, swamp becomes the rust and\nochre of sphagnum over peat, and mountain takes a purple cast from the crust\ngrowing on it. One of the three rock tints now carries the orange Xanthoria\nputs on exposed stone.\n\nThe ocean goes teal rather than sky-blue, and for a reason rather than a mood:\nthis seabed's relief is 260 m, so by Earth's standards (mean depth 3,700 m)\nthe entire ocean is continental shelf — shallow, lit to the bottom, and full of\nkelp. It should not read as deep water, because it is not.\n\nAlso renamed the grass. There is no grass on this planet — Poaceae are\nangiosperms — and the client was drawing grass tufts anyway. What carpets open\nground here is clubmoss, horsetail and lichen, so GRASS_DENSITY, GRASS_COLOR\nand makeGrassTuft are COVER_DENSITY, COVER_COLOR and makeCoverTuft. A grep for\n\"grass\" in the client now returns exactly one line: the comment explaining why\nthere isn't any.\n\ntsc clean, build green, six client suites pass.","parents":["2f5d051077758a4e8db3a643128ac149222c9e63"],"add":61,"del":21,"cadd":61,"cdel":21,"files":2},{"repo":"hexa","hash":"7366f7d45ef1848feb0245f6c3ed260b519da791","ts":1785981348,"wall":"2026-08-05T21:55","msg":"fix: the terrain tiers were fighting over the same ground, and burying pawns","body":"Near tiles and detail patches were drawn at IDENTICAL radius over exactly the\nsame ground. Only the far shell had ever been given an offset. So the two\nz-fought, and which one you saw was down to depth-buffer precision.\n\nThat is not a shimmer. Everything that stands on this world — pawns, trees,\npiles — is placed at heightAt, the finest answer there is. A coarse tile\ninterpolates between samples 56.5 m apart, and measured over the real planet\nit rides up to 2.5 m ABOVE that on broken ground:\n\n  detail patch (4 m)     p95 0.05-0.36 m   worst 0.58 m\n  coarse tile (56.5 m)   p95 0.35-2.47 m   worst 4.37 m\n\nWherever the coarse surface won the depth test, anything standing there was\nburied to the waist in ground that was not really there.\n\nThe three tiers now sit at three depths — detail on top at true radius, tiles\n0.6 m under it, shell 2.0 m under that — with the numbers named in quality.ts\nbeside the rest of the render knobs rather than as a bare literal in the middle\nof a mesh builder. A test pins the ordering and checks the gap actually clears\nthe worst coarse error, because \"these two must not be level\" is exactly the\nkind of invariant that gets undone by someone tidying a scale call.\n\nHONESTY ABOUT WHETHER THIS IS THE BUG THE OPERATOR SAW: it is a real defect\nand it produces exactly this symptom, but I have not proven it is the one in\nhis screenshot. Two hypotheses were tested and eliminated first — terrain\ninterpolation error at detail range is under 0.4 m and cannot bury anything,\nand the ground cover is nowhere near dense or tall enough. This is the third,\nand unlike those two it is a genuine mistake in the code regardless.","parents":["510237fdd25a9f86d43d78d9ab3d6a8c9d4aa8ac"],"add":54,"del":2,"cadd":54,"cdel":2,"files":3},{"repo":"hexa","hash":"f721043b9969bd940485b9aebc22960b8ba07124","ts":1785982595,"wall":"2026-08-05T22:16","msg":"docs: session handoff — L1 shipped, sinking pawns still open","body":"Replaces a handoff three weeks stale (2026-07-30, hex era). Sixteen commits\nthis session across geology, L1, the calendar and the renderer.\n\nThe section that matters most is the open one. Pawns appear sunk into the\nground, it is POSITION-dependent, and three hypotheses are already eliminated\nwith evidence so a fresh session does not re-run them: terrain interpolation\n(measured, under 0.4 m at detail range), the character rig (ruled out by the\nsymptom being position-dependent), and terrain tier z-fighting (a real defect,\nfixed, but the four live pawns measure within 5 cm of their mesh either way).\n\nThe live hypothesis is the operator's own — a pawn standing inside a\nvegetation prop — and the exact probe to settle it is written down.\n\nAlso persists the L1 plan under its semantic name.","parents":["7366f7d45ef1848feb0245f6c3ed260b519da791"],"add":313,"del":211,"cadd":313,"cdel":211,"files":2},{"repo":"hexa","hash":"08713347cf25d80ebf205343ac3b48abfa7d71f7","ts":1786023409,"wall":"2026-08-06T09:36","msg":"test: the ground you see is not the ground you stand on, and now it says so","body":"Trees were found sunk, which killed both standing hypotheses at once: a tree\ncannot stand inside another prop, and it has no character rig. What pawns,\ntrees and piles share is that all three are placed at heightAt() — so the\nsuspect had to be the drawn surface itself.\n\nIt is. Raycasting the real scene graph along the local vertical, over the real\nplanet, at four places chosen to cover the biomes spawn does not have:\n\n  exactly one land surface per patch    414 of 414 samples hit THREE\n  nothing buried past 0.5 m             161 of 414 buried, worst 64.5 m\n\nThe far shell is the culprit. It samples every 8th cell — 452 m between\nvertices — and stretches flat between them, so on broken ground it rides tens\nof metres above the surface everything is standing on. It is sunk by\nSHELL_DEPTH_M = 2.0, a bare literal that predates the tiering work and was\nnever measured against anything. Two metres of defence against an 84 m error.\n\nNo constant fixes that; the disagreement is geometric, not a depth bias. The\nanswer is the one every terrain LOD paper states — Losasso and Hoppe put it\nplainest, that only the finest level is drawn as a complete sheet and every\ncoarser one omits the region already covered — and it is what\n.claude/plans/hexa-quadtree-terrain-lod.md builds.\n\nWHY THIS IS A TEST AND NOT A FIX: globe-check.ts already asserts the tiers'\ndepth offsets and their triangle counts, and it passed the whole time the\nshell was floating 84 m over the ground. A test that checks the knobs cannot\ncatch a knob set wrong. This one measures the drawn surface against heightAt\nand knows nothing about tiers, so it will survive them being replaced — which\nis the next commit. It is committed FAILING on purpose: it is the gate.\n\nPassing already, and worth keeping honest: no gaps, correct winding, and\n293,376 triangles against a 400,000 ceiling.","parents":["f721043b9969bd940485b9aebc22960b8ba07124"],"add":447,"del":0,"cadd":447,"cdel":0,"files":2},{"repo":"hexa","hash":"e3b55740ef77e776078e92a965330e7c1d872c83","ts":1786026444,"wall":"2026-08-06T10:27","msg":"feat: one terrain hierarchy — the coarse ground stops being drawn over the fine","body":"Three complete sheets covered the same ground, ordered by sinking each a\nconstant distance toward the planet's centre. That is replaced by six\nquadtrees, one per cube face, where exactly one level is drawn over any patch\n— the rule Losasso and Hoppe state plainly and every terrain LOD paper since\nrepeats. A node is a square of a face's cell space meshed as a 33x33 grid over\nits own extent, so spacing halves each level and every node costs the same.\n\nMeasured by tests/ground-truth-check.ts, standing in four biomes:\n\n  one surface per patch    414 of 414 samples hit THREE  ->  0 hit more than one\n  nothing buried           161 of 414, worst 64.48 m     ->  0, worst 0.48 m\n\nVertices are laid EDGE to edge rather than centre to centre, so siblings share\ntheir boundary exactly, four children tile their parent exactly, and a root\ncovers its cube face exactly. The old centre-to-centre convention left half-cell\nslivers at every seam.\n\nTHREE THINGS THE MEASUREMENT TAUGHT, none of which were in the plan:\n\nA planet breaks the assumption the literature is written under. On a flat world\ndistance grows without bound, so a range of a few node extents picks a small\nneighbourhood; this body is 126 km around and a root is 29 km, so \"within 1.6\nextents\" is most of the globe INCLUDING the half facing away. Horizon culling\nis not an optimisation here — it is what makes the range rule mean the same\nthing on a sphere as on a plane. It cut 627k triangles to 467k.\n\nCost is quadratic in the range factor: a level subdivides across ~pi*F^2 nodes,\neach into four, so the whole tree is ~6*pi*F^2*(G-1)^2 per level. 2.5 drew 387\nnodes; 1.6 draws 228.\n\nAnd a tree that is still descending must not be measured. At one point the same\ncode read 1.98 m of burial mid-descent and 0.48 m settled — the ancestor\nstand-in doing exactly its job, covering ground with a parent until the child\nlands, and being reported as a defect for it. The test now runs to convergence.\n\nSTILL OVER BUDGET, and the reason is worth naming rather than tuning away:\n466,944 triangles against a 400,000 ceiling. F is the only real lever, and F is\ncurrently pinned from below by the burial tolerance — because props are placed\nat heightAt, the ideal surface, which coarse ground cannot follow. Two\nconstraints fighting over one constant is the same coupling that caused the\noriginal bug. It breaks properly when props stand on the surface actually\nDRAWN, which is the next work; then F drops and both pass.\n\nAlso here: coverage is no longer budgeted (an unbuilt node is covered by its\nparent, so the cap and the per-update patch budget are gone), the ocean is\nper-node and inherits the same guarantee (far sphere and its stand-off switch\ndeleted), vegetation range is DERIVED from where the LOD carries detail instead\nof being a second constant that had to agree with it, and every node carries\nits parent's surface ready for the morph.\n\nheightAt gains withDetail: a node coarser than the fine layer's Nyquist limit\nasking for detail does not get roughness, it gets aliasing — most of why the\nold far shell was 84 m from the truth.\n\nglobe-check.ts rewritten: its tier-depth and scale-ordering assertions no\nlonger mean anything, and what replaces them is the structure that keeps the\nground honest while the tree moves — roots resident, never a hole mid-descent,\nand every node's parent surface sampled along its own rays.\n\nClient only; server untouched. tsc clean, vite build green, six client suites\npass, ground-truth-check fails on the budget alone.","parents":["08713347cf25d80ebf205343ac3b48abfa7d71f7"],"add":801,"del":757,"cadd":801,"cdel":757,"files":6},{"repo":"hexa","hash":"4e5c5b683ee840aa7abc72a5b6193d65c9f3f830","ts":1786028983,"wall":"2026-08-06T11:09","msg":"fix: things stand on the ground that is drawn, not the ground that is meant","body":"Two fixes, and between them the last of the sinking and the whole triangle\noverage.\n\nPROPS STOOD ON A SURFACE NO MESH REPRODUCES. planet.heightAt is the ideal\nground: bilinear over the stored cells plus a fine layer synthesised at metre\nscale. A mesh is triangles between samples. Those two disagree by however much\nthe terrain moved in between, and the coarser the ground the worse it gets — so\na pawn placed on the ideal one floats or sinks against the one you can see.\n\nGlobe.surfaceHeightAt walks the tree to the node actually being drawn at that\nplace and interpolates over the same triangle the GPU does, choosing the same\nside of the same diagonal. Vegetation, pawns, piles and the order marker all\nask it instead.\n\n  worst burial    0.48 m  ->  0.001 m\n\nStructurally zero rather than merely small, and zero at ANY level of detail —\nwhich is the part that matters, because it takes the LOD out of the correctness\nargument entirely. The range factor was pinned from below by the burial\ntolerance and from above by the triangle budget: two constraints fighting over\none constant, which is exactly the shape of the bug this whole rework is about.\nUnpinned, it drops from 1.6 to 1.3 and the ground gets cheaper without getting\nworse.\n\nThe distance between the drawn surface and the ideal one does not go away — it\nis what a level of detail IS — so the test now reports it as fidelity (p50\n0.04 m, worst 0.96 m) rather than pretending it is a defect. It only ever\nbecame a burial because something was standing on the wrong one.\n\nTHE SEA WAS DRAWN OVER DRY LAND. Any node with a single wet vertex got a full\n33x33 sheet of transparent water, most of it over ground that is above the\nwaterline and hides it — the same sin the whole-globe ocean sphere was retired\nfor, at node scale. Only quads with a wet corner are meshed now, so the\nshoreline still closes and the inland nine-tenths is not drawn.\n\n  sea    149,504  ->  60,422 triangles\n\nTOGETHER, measured over the real planet standing in four biomes:\n\n  one surface per patch    0 of 414 samples overlap\n  nothing buried           0 of 414, worst 0.001 m\n  triangles                616,448  ->  398,342  against a 400,000 ceiling\n\nThe ceiling did not move. It was worth not moving: 400,000 was never a hardware\nmeasurement, only \"what we achieved, plus headroom\", and raising a threshold to\nadmit one's own work is how SHELL_DEPTH_M came to be 2 m against an 84 m error.\nThe number came down to meet it instead.\n\nClient only; server untouched. tsc clean, vite build green, all seven client\nsuites pass — ground-truth-check now among them.","parents":["e3b55740ef77e776078e92a965330e7c1d872c83"],"add":223,"del":57,"cadd":223,"cdel":57,"files":7},{"repo":"hexa","hash":"9db01b580e435ba500b25fdd46e190c34f2ef12f","ts":1786030371,"wall":"2026-08-06T11:32","msg":"feat: adjacent levels of detail share their edge exactly, and swap without a pop","body":"The last visible defect in the terrain, and the reason skirts were rejected:\na skirt hides a tear, it does not stop one. Geomorphing means there is no tear.\n\nEvery vertex already carried its own level's surface and its parent's. The\nvertex program now slides between them by how far that vertex is from the eye,\nand two properties fall out:\n\n  - At a node's outer edge the distance IS the level's whole range, so the\n    morph is complete and those vertices sit exactly on the parent's surface —\n    which is the coarser neighbour's surface. The seam is shared rather than\n    covered. No skirts, no stitching, no depth to tune.\n  - A node is already wearing its parent's shape at the moment the parent\n    replaces it, so the swap changes nothing on screen.\n\nPosition, normal and colour all morph together. Normals alone would have left\nlighting sliding over stationary ground; colour alone would have left cliffs\nflickering as the rock-on-slope term changed with the level under it.\n\nTHE BAND IS COMPILED IN, NOT PASSED AS A UNIFORM. Uniforms added in\nonBeforeCompile follow the PROGRAM, and all nine levels would have shared one\nprogram and therefore one band — every level morphing over the range of\nwhichever compiled first. Literals plus a per-level customProgramCacheKey give\neach level its own, for the price of nine tiny shaders. A test pins it: six\ndistinct bands across six drawn levels, each matching its own extent.\n\nonBeforeCompile FAILS SILENTLY. If three renames a chunk or edits its body the\nreplacement stops matching, the injection vanishes, and what you get is the old\ncracked terrain with nothing in the console. So the chunk order and the exact\nbodies were read out of the installed three rather than remembered — the colour\nchunk turned out to be vColor.rgb on a vec4, not the vec3 assumed — and\nglobe-check now compiles every level's shader and asserts no #include survived.\n\nAnything STANDING on the ground morphs with it. Globe.surfaceHeightAt applies\nthe same factor from the same distance, so a pawn does not walk out of the\nhillside it is on while the hillside is changing shape underneath it.\n\nAnd the oracle had to learn about it too: three's raycaster reads the position\nattribute and knows nothing about a vertex shader, so measuring the mesh\ndirectly stopped meaning \"what is drawn\" the moment this landed. The test now\nbakes the morph in before raycasting — a second, independent transcription of\nthe same arithmetic, which is only worth anything because globe-check\nseparately proves the shader carries it.\n\n  worst burial   0.001 m -> 0.009 m, the two transcriptions agreeing to a\n                 centimetre; still four thousand times under tolerance\n\nAll seven client suites pass, tsc clean, vite build green, 398,342 triangles\nagainst the 400,000 ceiling. Client only; server untouched.","parents":["4e5c5b683ee840aa7abc72a5b6193d65c9f3f830"],"add":191,"del":15,"cadd":191,"cdel":15,"files":3},{"repo":"hexa","hash":"f6016756416f786e899b0e7704f4970321d8c3e2","ts":1786031799,"wall":"2026-08-06T11:56","msg":"test: pin what we borrow from three, not just what we do to it","body":"Two guards against the two ways the geomorph can rot without anyone hearing.\n\nPIN THE ASSUMPTION, NOT THE OUTCOME. The existing checks prove the string\nsurgery applied. They cannot prove the result is valid GLSL — that only happens\nwhen a driver compiles it, and there is no GPU in a test runner. So the gap was\nthree keeping a chunk's NAME while editing its BODY: the patch still matches,\nthe test still passes, and the shader breaks on the player's machine.\n\nThe exact lines the replacements are written against are now asserted directly\nagainst three's own source, along with the chunk ORDER the morph factor depends\non (it is computed in the colour chunk because that is the earliest one running\nbefore both the normal and the position; reorder them and it is read before it\nis written).\n\nVerified these bite rather than merely being present, by mutating the real\nchunk source and confirming the pin notices:\n\n  vColor goes back to a vec3        CAUGHT\n  the colour attribute becomes vec4 CAUGHT\n  objectNormal renamed              CAUGHT\n  transformed renamed               CAUGHT\n\nThe first negative control was wrong before it was right, and worth recording:\n\"vColor *= color;\" looked like a plausible variant to test against and is in\nfact ALREADY in the chunk, in the USE_COLOR_ALPHA branch. A pin can be exact\nand still fail a badly chosen control.\n\nNO LEVEL MAY ADD A UNIFORM. The band is a compiled-in literal because uniforms\nadded in onBeforeCompile follow the PROGRAM, so all nine levels would share one\nand morph over whichever band compiled first. That is written down in a comment,\nand a comment does not stop anybody — adding a uniform is the obvious move and\nthe one three's docs show. Now it fails at the moment the mistake is made\ninstead of the moment somebody notices the horizon sliding.\n\nWhat stays uncovered, deliberately: whether the assembled GLSL actually\ncompiles. That needs headless-gl or a browser in the loop, which is a large\ndependency for one assertion — and unlike SHELL_DEPTH_M, which was silent for\nas long as nobody measured, a bad shader is loud and immediate: three logs the\ncompile error and the ground does not draw.\n\nAll seven client suites pass, tsc clean, vite build green.","parents":["9db01b580e435ba500b25fdd46e190c34f2ef12f"],"add":45,"del":0,"cadd":45,"cdel":0,"files":1},{"repo":"hexa","hash":"3b8cc7e5f34476e97d598b8dbe8d0468cd796035","ts":1786033241,"wall":"2026-08-06T12:20","msg":"docs: retire the description of a game this stopped being","body":"The sweep after the terrain rework, and most of what it found was not the\nrework's leavings but old skin nobody had shed.\n\nREADME described a hex world served to a PixiJS client, with a Rust A* crate\ncarrying the pathfinding and a status section reading \"M0 walking skeleton — no\ncombat, economy, building, or factions yet\". Every clause of that is false. The\nworld has been a 20 km globe since 2026-08-01, the client has been three.js\nsince the pivot, native/hexpath has been imported by nothing since the grid\ndied, and there is combat, gear, work, piles, factions, seasons and a trophic\nlevel. A front door that lies is worse than no front door: it is the first\nthing a new session believes.\n\nRewritten against what the code actually does, including how the terrain now\nworks and where its plan and its oracle live.\n\nHandoff was worse, and worse in the way that matters — it still listed the\nsinking pawns as open and mid-investigation, with two eliminated hypotheses and\na live one, all of it overtaken. A stale handoff does not merely go unread, it\nsends the next session down a road that has already ended.\n\nAlso swept:\n  - every dead tier constant confirmed gone (DECIMATION, SHELL_CHUNKS, all\n    three *_DEPTH_M, DETAIL_*, MAX_DETAIL_PATCHES, the water stand-off pair);\n    every remaining export in quality.ts is referenced\n  - one unused import (closeMenu in main.ts), found by running tsc with\n    --noUnusedLocals, which is not on by default\n\nDELIBERATELY NOT DELETED, and now written down where the next session will see\nit rather than rediscovering it: client/ (the retired PixiJS client),\nnative/hexpath/ (hex-era Rust A*), and server/world-2026-07-29.bak.json (a\ncommitted v1 snapshot). Nothing references any of them. All are recoverable\nfrom git. Removing a directory is an explicit order, not a tidy-up.\n\nVerified rather than asserted: 98 commits, 269 server tests green, ruff clean,\ntsc clean, vite build green, and the README's own verify command produces\nexactly the seven client suites it claims.","parents":["f6016756416f786e899b0e7704f4970321d8c3e2"],"add":162,"del":134,"cadd":162,"cdel":134,"files":3},{"repo":"hexa","hash":"06cc48297deffb3ba32d847fb7aa1c00b93f5de1","ts":1786037096,"wall":"2026-08-06T13:24","msg":"docs: research the arthropod body instead of inventing it","body":"Stage 1 of the arthropod pawn. Written before any code, for the same reason the\nbiosphere doc was: that one changed the L1 design materially — sphagnum replaced\noak as this world's tanning agent because the axiom forced it, and peat's honest\nnumbers turned out to be more interesting than the convenient zero.\n\nThe finding that makes a grown body tractable is not a graphics finding:\n\n  An arthropod segment's identity is a LABEL, not a structure. Hox genes assign\n  it, and changing the label turns an antenna into a leg.\n\nHomeotic transformation is the proof — removing homothorax or extradenticle\ntransforms antenna to leg, and knocking down Ultrabithorax in Parhyale\ntransforms whole segments. Antennal cells already carry everything needed to be\nleg cells. So the genome does not have to encode a body. It encodes a short list\nof names and magnitudes, which is small enough to author by hand, inherit, and\nmutate meaningfully — which is what \"the genome is gameplay, always and forever\"\nactually requires.\n\nThree things carry mechanical weight, and none were invented for the game:\n\nGAIT IS EMERGENT. Legs are coupled phase oscillators; the gait is what they\nsettle into. Contralateral legs alternate anti-phase, protraction waves run\nposterior to anterior, and swing duration stays CONSTANT while stance shrinks\nwith speed — duty cycle above 50% is metachronal, at 50% the tripod appears.\nOne input, and the gait falls out. It also gives a headless test the thing that\nactually looks wrong when it is wrong: a foot in stance must be stationary\nagainst the ground. Sliding feet are measurable without rendering.\n\nDAMAGE SHOULD BE LOCAL. Per-segment ganglia with weakly-coupled CPGs mean a body\nlike this does not die the way one with everything in its head does. A wound\nshould degrade a segment, not subtract from a pool.\n\nGROWTH COSTS VULNERABILITY. The cuticle is inflexible, so size is set while\nsoft: the animal expands, THEN hardens. It cannot grow without becoming\ndefenceless. And sclerotization is where both stiffness and colour come from, so\na soft pawn is a pale pawn — the vulnerability advertises itself with no UI.\n\nSerial homology gives the last piece: every appendage is a chain of podomeres,\nso antenna, mandible, walking leg and manipulator are one grower with five\nparameter sets rather than a catalogue.\n\nReuses the operator's own prior research rather than re-deriving it — the Zooid\nBoneGraph's attractor model, voxel-genetics' gene structure with wobble\ndegeneracy and methylation, and the ganglion architecture's reading of insect\nCPGs, which turned out to contain the gait solution already.\n\nMarked honestly, as the biosphere doc was: what is anchored in the literature,\nwhat is carried over, what is extrapolated (the morphology-to-stats mapping —\ndirections defensible, coefficients are design), and what is invented (ganglion\ndensity governing how well a body fights wounded; the moult as a scheduled\nsession-scale event). Both of the last two are game design wearing biology's\nclothes and are labelled as such.\n\n11 fragments in unicursal, all 13 axes populated. Plan of record alongside at\n.claude/plans/hexa-arthropod-body-and-genome.md.","parents":["3b8cc7e5f34476e97d598b8dbe8d0468cd796035"],"add":474,"del":0,"cadd":474,"cdel":0,"files":2},{"repo":"hexa","hash":"784ca82ffb345afc22531831ba26546f4610ff57","ts":1786041394,"wall":"2026-08-06T14:36","msg":"feat: pawns stop being rolled and start being grown","body":"Stats were a loadout template jittered by plus or minus ten at birth. They are\nnow EXPRESSED from a genome, which means the nine attributes and the animal you\ncan see have one cause instead of two — a pawn's sheet becomes a consequence of\nits body rather than a number beside it.\n\nWhat the genome carries is small, and that is the whole finding from the\nresearch: an arthropod segment's identity is a LABEL, not a structure. So a\ngenome does not encode a body, it encodes twelve names and magnitudes. 283 bytes,\nreadable, hand-editable, heritable.\n\n  data/genetics.json    AUTHORED, like geology.json beside it. Which loci exist,\n                        which codons each carries, what each expresses, and the\n                        stock founders are drawn from. Read, never rolled.\n  server/genomes.json   LIVE, and deliberately NOT in world.json — the\n                        operator's call, and the right one: heredity is its own\n                        kind of state and mixing it in would make both harder to\n                        read and harder to edit.\n\nTwo files that must agree is a real hazard, so it is designed out rather than\nhoped away. A founder genome is DERIVED from (seed, pawn id), so delete\ngenomes.json entirely and every pawn gets its own body back — verified, not\nasserted. Same posture rehome_stranded takes toward a saved position: a loaded\nfact is a claim to be checked.\n\nWOBBLE, AND THE BUG IT CAUSED. Several codons express one value, so variation\ncan be silent — without it a lineage cannot carry anything it is not already\nwearing. Founders were first drawn over CODONS, which looks right and is wrong:\na value written three ways comes up three times as often. Measured, four\nfounders gave THREE IDENTICAL BODIES. Founders are drawn over VALUES now and\nthen given one of the several spellings, which is also the honest reading —\nredundancy exists so a lineage can drift, not so a population can be uniform.\nTwelve founders now give at least six distinct bodies; two hundred give seventy.\n\nThe body plan describes more than animals on purpose. All technology here is\nbiological — you do not forge a blade, you grow one — so a tool is a body too:\none segment, no ganglia, no moult. Making that general now cost nothing.\nDiscovering later that it had to be would have cost a second system.\n\nFive stats are derived from morphology and four are not. Intelligence, will,\ncharisma and luck stay allelic, because a segment count does not imply a\ntemperament and pretending otherwise would be the kind of tidy lie this project\nrefuses elsewhere. The exponents are named in one table rather than scattered\nthrough the arithmetic: directions argued from the research, magnitudes are\ndesign and expect to want tuning against play.\n\nCORRECTED IN THE PLAN, rather than quietly dropped: the plan promised a test\nthat a founder genome reproduces the old roll_stats output. That is not\nachievable and should not be — a jitter is not recoverable from morphology, and\nif it were, the genome would not be deciding anything. The property that\nactually holds is stronger: Pawn.stats was already persisted, so existing pawns\nare untouched BY CONSTRUCTION. Expression is how stats come into existence, at\nbirth; storage never changed.\n\nOne existing test updated rather than worked around: test_atomic_write_leaves_no_tmp\nasserted the directory held exactly one file, which was a proxy for \"no .tmp\nsurvived\" and stopped being true when heredity got a file of its own. It now\nasserts the intent directly, so the next file to arrive beside the world does not\nfail a test about atomicity.\n\n290 tests green (269 + 21), ruff clean. Client untouched.","parents":["06cc48297deffb3ba32d847fb7aa1c00b93f5de1"],"add":1105,"del":11,"cadd":938,"cdel":11,"files":10},{"repo":"hexa","hash":"89fc1323738f1ec590e32f262c1e52fae32714f5","ts":1786042570,"wall":"2026-08-06T14:56","msg":"docs: session handoff — the terrain rework, and half the arthropod","body":"A full handoff rather than a delta, because this session changed two things a\nfresh reader would otherwise have to reconstruct: what the terrain renderer IS\nnow, and what a pawn is made of.\n\nRecords, in Part Zero and deliberately first, the five canon decisions the\noperator made this session — pawns become arthropods with the humanoid rigs\nkept, the genome is gameplay \"always and forever\", genetics gets its own file,\nall technology is biological FOR THE GESTALT with the existing forge chain\nstaying for humanoid use, and the terrain confirmed good by eye. Those are\ndirectives, not inferences, and losing them would cost more than losing any of\nthe code.\n\nThe crafting resolution is written into the plan of record as well, so it is not\nonly in a conversation: crafting.py is not demolished, biotech is a second\nbranch gated on which body you wear, and that is why BodyPlan already describes\na grown artifact and has a test for it.\n\nThe plan's stages are REORDERED in place: 4 and 5 before 3, because the operator\nasked for a body and seeing it will inform the mechanics rather than the other\nway round. Also notes the one thing the plan did not list — the body plan has to\nreach the wire before any of it can be drawn.\n\nPart Five keeps the lessons, each of which cost real time: measure the thing and\nnot the knob; a planet breaks the assumption the LOD literature is written\nunder; never measure a tree that is still descending; two constraints fighting\nover one constant is the shape of this whole bug class; do not raise a threshold\nto admit your own work; onBeforeCompile fails silently and three's chunk bodies\nare not what memory says; a pin can be exact and still fail a badly chosen\ncontrol; wobble makes founders uniform if you draw over codons; and fix a test's\nassertion to its intent rather than around the change.\n\nFlags two things a fresh session would otherwise trip on. The RUNNING SHARD IS\nSTALE — pid 37600 predates the genome work, has never written genomes.json, and\nneeds a restart. And when it restarts, the twelve legacy pawns keep the stats\nstored in world.json while their newly derived genomes express different ones;\nharmless until stage 3 reads the body plan for gear slots, and it wants a\ndecision that has not been asked for.\n\n101 commits, still nothing pushed. 290 server tests green, ruff clean, seven\nclient suites green, tsc and vite build clean, working tree clean.","parents":["784ca82ffb345afc22531831ba26546f4610ff57"],"add":408,"del":100,"cadd":408,"cdel":100,"files":2},{"repo":"hexa","hash":"8755f67e1cec44ea649555be3438a0d1c458d4a4","ts":1786051890,"wall":"2026-08-06T17:31","msg":"feat: identity stops being a name","body":"A name is a label a player can retype, and this world was keyed by one. Retype\nit with a letter out of place and the shard, following its own rules perfectly,\nhanded back a second identity with four more bodies. One person accumulated four\nrecords that way. Cleaning it up destroyed eight pawns and their gear, because a\npruned body's kit has nowhere in this model to fall — and the last surviving\nrecord still carried a faction reading player:Rodney WilkernutsF, fossilised from\na spelling nobody had used in weeks.\n\nSo identity moves onto an id that nothing can retype. world/registry.py is the\nsource of truth for players and factions, in players.json beside the snapshot\nand gitignored like it — it holds session tokens.\n\n  - Pawn.owner holds the id. A rename used to rewrite every body a player\n    owned; it now touches one field and the squad does not notice.\n  - A faction derives from the id, so it can never fossilise a name again.\n    Free to migrate today only because the relations table was empty.\n  - Tokens are a LIST. A second browser joins the person who already exists\n    instead of minting a stranger, which is the failure this file exists for.\n  - Surveys and the shard's socket map re-key from name to id. Both silently\n    lost everything a player had, on a rename.\n\nAuthoritative, and therefore rebuildable: the snapshot still carries\npawn.owner, so a lost registry is reconstructed rather than reinvented. Ids,\npawn lists and factions come back; the name and tokens do not, and a recovered\nplayer is honestly nameless until somebody claims it. Proven by deleting the\nfile in a test, not by assertion.\n\nfaction_for_player(name) is deleted, with a note where it stood. It is the\nfunction this whole mess came out of.\n\nSnapshot goes v2 -> v3; players leave world.json. 318 tests (was 290), ruff\nclean, tsc clean, seven client suites green.","parents":["89fc1323738f1ec590e32f262c1e52fae32714f5"],"add":1004,"del":233,"cadd":1000,"cdel":233,"files":18},{"repo":"hexa","hash":"86bf6dddfd5d0617832a92a43283334cd835c515","ts":1786051908,"wall":"2026-08-06T17:31","msg":"feat: the tools that move a world onto the registry, and prune one","body":"Three, and only one of them is routine.\n\ntools/migrate_players.py takes a v2 snapshot to v3, once and one way. Players\nleave world.json for players.json and gain an id; pawn.owner stops being a name\nand becomes that id; surveys are re-keyed, or a rename would discard everything\na prospector ever learned; and relations are rewritten onto the new faction\nstrings, with any pair naming a faction that no longer exists dropped rather\nthan carried as a war against nobody. Every token a record held is carried\nacross, so nobody is locked out of a world they were playing an hour ago. It\nrefuses a snapshot that is not v2 and refuses to overwrite a registry that\nalready exists, so running it twice cannot hurt anything.\n\ntools/prune_players.py DESTROYS things and says so plainly rather than quietly.\nA pruned pawn's gear does not fall to the ground: piles hold raw resource units\nand nothing in this model can receive a worn chainmail, so the kit goes with the\nbody. That is a real exception to the closed world's rule that nothing is ever\ndeleted. It is taken deliberately, which is why the default is a dry run and why\nthe operator is shown what is about to be burned. Neither next_pawn_id nor\nnext_player_id is ever lowered: a recycled pawn id would grow a new animal into\na dead one's body, and a recycled player id would inherit a dead faction's wars.\n\ntools/live.py holds the guard both of them need. The tick loop snapshots every\nSNAPSHOT_EVERY_TICKS and again on shutdown, so an edit made underneath a running\nshard is overwritten within the minute, silently and with no error to notice.\nOne home for that rule rather than a copy per tool, because a rule with two\ncopies is a rule that drifts. The liveness check is a bare TCP connect and never\na join — a diagnostic join on a live shard creates a REAL player with real pawns\nin the operator's world.\n\nBoth write tmp-then-rename, and both verify by reloading through the real\nload_snapshot rather than trusting their own arithmetic.","parents":["8755f67e1cec44ea649555be3438a0d1c458d4a4"],"add":417,"del":0,"cadd":417,"cdel":0,"files":3},{"repo":"hexa","hash":"00ed5ec149d66d3fb3d159600f8d3b9143eb891c","ts":1786052831,"wall":"2026-08-06T17:47","msg":"feat: a pawn's body reaches the wire","body":"The client cannot draw an arthropod off an asset file. Leg count varies per\nindividual — this squad walks on six, six, eight and eight — so no rig on a\nshelf is right, and the body plan has to travel.\n\nSix numbers per pawn: segments, legs, manipulators, podomeres, size and\ncuticle. Not the segment chain with every appendage hanging off it, because\nthat would be sending the grower's OUTPUT instead of its input. The client runs\nthe same rule from the same numbers and arrives at the same animal, which is\nthe whole reason a genome encodes a short list of names and magnitudes rather\nthan a mesh.\n\nPublic, like gear and unlike the bag. How many legs a thing has is the most\nvisible fact about it, and a stranger the client could not draw would be worse\nthan one it draws wrongly.\n\nPodomeres were not in the original wire list and are here anyway: a grower\ncannot build an appendage without knowing how long its chain is, and leaving it\nout would mean touching this message a second time.\n\nExpression is cached on the WorldState, keyed by the genome's IDENTITY rather\nthan by a flag somebody has to remember to clear. A body does not change while\nthe animal is alive, so re-growing one for every visible pawn on every tick is\nwork with a known answer; Genome is frozen, so the only way one can change is\nby being replaced, and a replacement invalidates the entry by itself. Moulting\nwill lean on that.\n\nNothing renders from this yet. character.ts is still the only body there is —\nmaking it one implementation behind an interface is the next step.\n\n324 tests, ruff clean, tsc clean, vite build green.","parents":["86bf6dddfd5d0617832a92a43283334cd835c515"],"add":204,"del":4,"cadd":204,"cdel":4,"files":4},{"repo":"hexa","hash":"e43ca8d2850f9750a8b391656f3d24dcd523fdf2","ts":1786054198,"wall":"2026-08-06T18:09","msg":"feat: the pawns are arthropods, and the walk is not animated","body":"Stage 4 and 5 together: the seam that lets more than one kind of body exist,\nand the first body that could not have been a file.\n\nTHE SEAM. pawns.ts called library.spawn(chooseModel(gear)) inline, which is why\nthere could only ever be one kind of body — the decision was welded to the thing\nthat made it. It now asks growBody() for something with a root, a height and a\nmotion, and does not know whether it got 41 authored joints or a chain of\nsegments walked by oscillators. The KayKit rigs are one implementation of that\ninterface rather than the only one, which is what the operator's canon requires:\nhumanoids stay for players who want to be humanoid.\n\nTHE GROWER. Six numbers off the wire become an animal. Head is six fused\nsegments, thorax is whatever bears legs, the rest is abdomen; every appendage is\none grower with different parameters, because serial homology is not a\nconvenience but the reason an antenna and a leg are the same organ wearing\ndifferent labels. Two InstancedMeshes, so an entire animal is two draw calls\nhowever many legs it turned out to have.\n\nTHE GAIT IS EMERGENT. One phase oscillator per leg. Contralateral legs\nanti-phase, the protraction wave running posterior to anterior, swing duration\nheld constant while stance shrinks with speed. Nobody chooses the tripod — it is\nwhat those phase relations do at duty 0.5. No clip could have served this\nanyway: this squad walks on six, six, eight and eight.\n\nTwo oracles, and both earned their place by failing first.\n\ngait-check found that a duty factor of 0.45 leaves a hexapod on two feet. That\nis real biology — fast cockroaches do it — but it is only survivable because the\nanimal is DYNAMICALLY stable, falling forward and catching itself. We simulate\nno dynamics, so ours would not be falling, it would be floating. The tripod is\nnow the floor, which is exactly where the literature puts it.\n\narthropod-check found limbs stretching up to 18% to reach a foot the leg could\nnot span: at 3 m/s the gait wanted a 0.91 m stride from an 0.8 m leg. The fix is\nthe one a real animal uses — it does not grow its leg and it does not slide its\nfoot, it takes more steps. Stride is now capped by measured reach and cadence\ncarries the rest, which leaves the no-slide property untouched because stride is\nstill speed x duty x period.\n\nGear does nothing on an arthropod, deliberately. Operator canon: \"if I want a\nweapon, I will just use claws or acid or fire — gear is part of an arthropodic\nbody.\" It grows its armament; hanging a longsword mesh off a chela in the\nmeantime would be precisely the wrong placeholder.\n\n324 server tests, 9 client suites, ruff clean, tsc clean, vite build green.","parents":["00ed5ec149d66d3fb3d159600f8d3b9143eb891c"],"add":1286,"del":30,"cadd":1286,"cdel":30,"files":8},{"repo":"hexa","hash":"4d02cc77b0aeeaf75275ead3976646f86eaa4457","ts":1786055597,"wall":"2026-08-06T18:33","msg":"fix: the gait ran on a clock, and the body did not","body":"The operator reported the arthropods sliding toward the end of their gait, and\nthe oracle that exists to catch exactly that said the feet were planted. The\noracle was right about what it measured and wrong about what the client does.\n\nIt assumed the body advances at the speed the gait was handed. It does not.\npawns.ts interpolates between server states 250 ms apart and CLAMPS at the end\nof each, so a state arriving even slightly late parks the body while the frames\nkeep coming and the clock keeps running. Measured, driving the body the way\npawns.ts actually drives it:\n\n  states on time    parked  0% of frames    0.0 mm slip\n  states  8 ms late parked  6% of frames    3.1 mm/frame  =  67 cm per second\n  states 33 ms late parked 12% of frames    5.8 mm/frame  = 125 cm per second\n\nEight milliseconds of lateness is not an unusual network, it is a normal one.\n\nTHE FIX IS STRUCTURAL, not a tolerance. The walk now runs on ground actually\ncovered rather than on time x assumed speed, and a planted foot is ANCHORED: it\nremembers where it was set down and how far the body had gone at the time, and\nevery frame after that reports the difference. Its world position is therefore\na constant by construction, and stays one through parking, catch-up, a speed\nchange mid-step, or stopping dead — none of which the old formula survived.\n\nThe stride still cannot outrun the leg, so cadence still carries the speed.\n\nThe oracle now stalls the body on purpose, the way the real one stalls, and the\nguard was checked for teeth rather than assumed to have them: the old\ntime-driven model slips 50 mm/frame under that harness and the new one 0.00.\n\nAlso fixed: the detector itself, which read the last frame of swing as a\nplanted foot and reported its travel as a slide. Stance returns a lift of\nexactly zero, so anything above float noise is a foot still in the air. That\ncost an hour and is now a comment.\n\nPAWNS_PER_PLAYER goes 4 -> 10, per the operator: sales are not the constraint\nright now. Ten fit the spawn ring at 1.75 m apart, which clears SEPARATION_M;\npast about twelve they would spawn already body-blocking and _squad_ring wants\na second ring.\n\n324 server tests, 9 client suites, ruff clean, tsc clean, vite build green.","parents":["e43ca8d2850f9750a8b391656f3d24dcd523fdf2"],"add":299,"del":92,"cadd":299,"cdel":92,"files":9},{"repo":"hexa","hash":"8d7767135f31dff5711534da9939161e5c15426d","ts":1786056272,"wall":"2026-08-06T18:44","msg":"feat: the world grows what it actually bears","body":"The client dressed the ground with four props called tree, swampTree, rock and\ncover, against thirteen real organisms — and skipped water entirely, which is\n59.5% of this planet. A swamp and a plain were the same greenery at different\ndensities, and clicking either answered with a resource nothing on screen had\nsuggested was there.\n\nTHE FACT THAT MADE THIS FREE: every L1 producer has deposit = None on the\nserver, so what a cell bears depends on its BIOME and nothing else, and the\nclient already holds the biome of all 1.57 M cells in planet.bin. Placement can\ntherefore agree with resources_at() by construction rather than by coincidence,\nwith no extra wire traffic and nothing to keep in sync by hand.\n\nSo the flora is now the flora:\n\n  swamp     sphagnum hummocks, horsetail, cycads, fiddleheads, cut peat banks\n  plains    lichen crust, clubmoss, bracken, horsetail\n  forest    conifers, cycads, bracken, clubmoss, fiddleheads\n  hills     bracken, clubmoss, lichen\n  mountain  lichen, and nothing else — it is the only thing that lives on rock\n  water     kelp rising off the bed, azolla matted on the surface\n\nPalettes are the honest ones rather than the expected ones. Green dominance IS\nthe angiosperm palette and this world has no angiosperms: sphagnum is rust and\nochre as often as green, cycads are genuinely glaucous blue, lichen runs from\nXanthoria orange through grey-green to orchil purple, kelp is olive to amber,\nand azolla goes deep red in strong light. The strange palette is the accurate\none.\n\nflora.ts holds what a thing IS; vegetation.ts holds where it goes. The same\nsplit celestial.ts and sky.ts have, for the same reason: the first question is\ndesign and the second is engineering.\n\nThe test now asks the REAL server function over subprocess and checks parity\nboth ways — nothing is drawn where the server would not hand it over, and\nnothing a biome bears is invisible. A player should never be asked to prospect\nfor something there is no sign of.\n\n12 species, one draw call each, 617 instances in a dressed 600 m. 9 client\nsuites green, tsc clean, vite build green. Server untouched.","parents":["4d02cc77b0aeeaf75275ead3976646f86eaa4457"],"add":689,"del":283,"cadd":689,"cdel":283,"files":3},{"repo":"hexa","hash":"79869a431f684f3ece2fde0cdfca1857987ba20f","ts":1786056970,"wall":"2026-08-06T18:56","msg":"fix: the world was dressed at one plant every sixty metres","body":"The operator looked at it and said the wildlife was sparse. It was, by about\nfive hundred times, and the reason is embarrassing: density was written per\nCELL, a cell is 3,196 m2, and 0.85 looked like a lot. It is one conifer per\n3,760 m2 — a tree every 61 metres. That is not a forest, it is a car park.\n\nMeasured, and then fixed against the measurement:\n\n  conifer   0.85/cell -> 26/cell     one per 3,760 m2 -> one per 123 m2\n  sphagnum  0.90      -> 26 CLUSTERS of five mounds\n  lichen    0.70      -> 40 on bare rock, where it is the only living thing\n  kelp      0.55      -> 38, because a kelp bed is a forest\n\nThree things beyond the numbers, all of them found by measuring rather than by\nlooking:\n\nSTEEP WAS SET TO 0.5, and the server calls ground `hills` at a slope of 0.67.\nSo every hill and mountain on the planet was classified too steep to grow on,\nand bracken and clubmoss were refused on exactly the ground resources_at()\nsays bears them — three props within ten metres against fifteen on plains. The\nthreshold is now 1.2, above the mountain line, so only true cliffs are bare.\n\nHORSETAIL COST 480 TRIANGLES, ten times everything around it, for a plant meant\nto carpet a swamp. Rebuilt at 140. A carpet you cannot afford to draw is the\nreason the world gets dressed sparse in the first place.\n\nGROUND COVER IS CLUMPED. Five mounds in one instance costs a third of five\ninstances, and the ground layer is where density is actually read. Drawing one\nplant per prop is why it still looked scattered after the densities were raised.\n\nDensity now falls with distance — full under the camera, a fifteenth at 600 m —\nbecause the cost is dominated by far cells nobody can resolve, and the horizon\nat standing eye height is 283 m anyway.\n\nResult: 617 props to about 8,000, worst case 396,000 triangles across 12\ninstanced draw calls, against a terrain that draws 398,000. The test now\nasserts BOTH — at least 30 props within 25 m in every biome, and under 500,000\ntriangles — because \"sparse\" and \"too expensive\" are the two ways this goes\nwrong and neither is visible in a total.\n\n9 client suites green, tsc clean, vite build green. Server untouched.","parents":["8d7767135f31dff5711534da9939161e5c15426d"],"add":220,"del":82,"cadd":220,"cdel":82,"files":3},{"repo":"hexa","hash":"15ae39a9627ebc9817b0470eb8b658d3c99cae08","ts":1786057934,"wall":"2026-08-06T19:12","msg":"fix: mats lie on the soil, and lichen sheets its biome","body":"Three reports in one, all of them things measurement had been asked the wrong\nquestion about.\n\nMATS FLOATED, and pawns walked underneath them. A mat was one prop, so it took\nONE ground sample — its centre's — and an eighteen-metre crust then hovered over\nevery dip inside its own footprint. That is the sunk-trees bug wearing the other\nsign, and it has the same answer: a sheet cannot be rigid on terrain that is not.\n\nA mat is now a scatter of small lobes, each placed separately, each sampling the\nground it actually lies on. It drapes. Worst lobe now sits 0.1 cm above the\nterrain, and the test measures every one of them.\n\nLICHEN SHEETS rather than speckles. It is the only living thing on bare rock, so\na mountain is now vast overlapping crust — Xanthoria orange, grey-green, orchil\npurple — with stone showing through where the crusts have not met. Same\ntreatment for azolla on the water and sphagnum in the bog, whose lobe is a low\ndome so the carpet and the hummocks are one geometry.\n\nMat outlines are stretched unevenly per instance and their lobes fray smaller\ntoward the edge, so no two are the same shape and none of them ends in a circle.\n\nAZOLLA IS THE RED, not kelp — and the operator settled what that means. On Earth\nazolla is strictly freshwater and has no business in an ocean. Here the ocean is\nnot that salty and azolla adapted, which sits well with a seabed 260 m at its\ndeepest: this sea is effectively all continental shelf. Recorded in flora.ts.\n\nCoverage is now the measure rather than a prop count, because the count started\nlying the moment mats arrived: trading forty small lichen patches for twenty-two\nlarge crusts halves the count and doubles the ground covered. Every biome now\nhas at least a fifth of the ground within 25 m under something.\n\nTwo plants were eating the budget: clubmoss cost 120 triangles a patch for caps\nnobody can see — 274,000 on a plain, more than half the frame — and horsetail\n140 for a second whorl. Cones and open-ended shafts instead. And conifers were\nsaplings with a one-metre canopy, which is most of why a forest floor measured\n8% covered.\n\nWorst case 389,000 triangles across 12 instanced draw calls, against a terrain\nthat draws 398,000.","parents":["79869a431f684f3ece2fde0cdfca1857987ba20f"],"add":227,"del":97,"cadd":227,"cdel":97,"files":3},{"repo":"hexa","hash":"6053c2f4800d0253a4706afe54c7f5e8fbe49d8d","ts":1786058644,"wall":"2026-08-06T19:24","msg":"docs: research what prospecting is actually for","body":"The operator asked for a way to cancel prospecting, or better, for prospecting\nto become the thing that gets you more stats on what you right-click. Both\nhalves point at one defect, and the prior art names it exactly.\n\nSince the client started drawing the real thirteen producers, a swamp visibly\ncontains sphagnum and horsetail and cycads — and the game still demands a\nsix-second job before it will admit any of it, then reports \"swamp —\nunsurveyed\" over ground the player is looking straight at. That is the failure\nthe roguelike identification literature has complained about for thirty years,\nreached by a different road.\n\nSix sources, and the most useful one argues AGAINST the obvious design. Golden\nKrone Hotel names four failure modes of identification systems — burden of\nknowledge, hoarding, learned helplessness, and solved-yet-tedious — and every\none is a live risk here. Their fix is not to delete the mystery but to BOUND it.\n\nMetroid Prime supplies the frame: the Scan Visor turns the player into a\nbiologist, and its strength is that the game supplies observations while the\nplayer supplies the theory. Subnautica supplies the entry schema — behaviour,\nanatomy, niche, reproduction, evolution — and the stance that knowledge is a\nbest-fit theory rather than a lookup. Vintage Story's propick supplies the split\nthat Hexa is missing: a coarse read that tells you what to EXPECT in a region,\nand a precise one that finds the seam. EVE supplies resolution as a number that\nskill improves. Wingspan supplies the principle this world already runs on and\nhad not noticed — the field guide entry IS the rule sheet.\n\nThe approach that falls out: sight is free, study is work, and prospecting is\nfor what is buried. The boundary is not difficulty, it is whether an eye could\nhave got there. Geology is genuinely invisible; a fern is not.\n\nThree things make it fit this world rather than any world. The client cannot\nlie about the flora, because every producer is chosen by biome and the client\nholds every biome — so hiding the name is a fiction maintained against the\nplayer's own eyes. The examining organ exists and is genomic, so study depth\nscales with the antennae and ganglia of the body doing it. And knowledge belongs\nto the gestalt, because surveys are already keyed by player rather than pawn.\n\nWritten, ingested to unicursal (14 fragments, all 13 axes), committed.","parents":["15ae39a9627ebc9817b0470eb8b658d3c99cae08"],"add":307,"del":0,"cadd":307,"cdel":0,"files":1},{"repo":"hexa","hash":"53cc7adbe063dc781e7651c2f8668eadd56f8857","ts":1786059718,"wall":"2026-08-06T19:41","msg":"feat: the fourth lineage and the tinder fungus, and a rate that was never real","body":"Two organisms the biosphere research authored in detail and the code had never\nheard of, plus the reason to go looking: an audit of what is designed against\nwhat is implemented.\n\nPROTOTAXITE. Not a plant, not a fungus, not an animal — the 2026 work found the\nreal thing structurally and chemically distinct from every known fungus living\nor extinct and proposed an entirely extinct eukaryotic lineage; this world\ndeclines to let it go extinct. An eight metre column over a metre wide, and the\ntallest thing here. It stands on the BARREN ground, solitary, kilometres from\nany forest, because it does not need the soil a forest needs — it is making the\nsoil a forest will need. Cut it and the section is a mat rather than a grain.\n\nDrawn as a bare vertical, which is the only one on the planet: everything else\nis a cone, a spray or a mat, and being the sole exception is what makes it read\nas a landmark from a kilometre off. The most striking thing in this world is now\nfound in the emptiest part of it.\n\nAMADOU. Bracket fungus, the second rung of the fibre ladder, and a complete\nproduction chain needing no animals at all — which matters on a planet whose\nupper rungs all wait on fauna that does not exist. Otzi carried some 5,300 years\nago. Drawn on a stub of dead wood, because a shelf growing out of bare ground\nreads as a rock.\n\nMountains are no longer lichen and nothing else. They are lichen and, rarely, a\ncolumn belonging to a kingdom that has no other members. The test that asserted\notherwise was right until this landed and now says so.\n\nAND THE RATE, WHICH IS THE REAL FINDING. Deposits.regrow reads\nregrow_per_second as a FRACTION OF POOL per second. Every document, comment and\ntest reads it as UNITS per second. Measured end to end rather than read: an\nemptied peat bog refills in 1,201 seconds — twenty real minutes — against the\ntwo thousand game-years the L1 research states. Sixty-four thousand times, and\nthe same defect on every renewable here.\n\nThe peat test passes because it does its own arithmetic instead of driving the\nfunction, which is precisely the failure the terrain oracle was built to end: a\ntest that checks the knob cannot catch a knob wired to nothing.\n\nNeither reading is simply right. Under units the slow things land correctly and\nazolla takes 27.8 years to recolonise a pond it doubles across in two days;\nunder fractions azolla is close and peat loses the depth argument its entire\ndesign rests on. The rates were authored under mixed intent and want\nre-deriving under one — and the FIA data suggests which: refill time in\ngame-years equal to real recovery time in world years, since a game year IS a\nworld year and no compression is needed.\n\nThat is a balance change across nineteen resources, so it is measured, recorded\nin Deposits.regrow's own docstring and in the research, and left for the\noperator rather than quietly applied. The two new rates are set to be correctly\nordered under EITHER reading, so nothing here depends on the answer.\n\n324 server tests, 9 client suites, ruff clean, tsc clean, vite build green.","parents":["6053c2f4800d0253a4706afe54c7f5e8fbe49d8d"],"add":308,"del":17,"cadd":308,"cdel":17,"files":5},{"repo":"hexa","hash":"1bb331b3870774d03e0e03ecac719135dcaa3487","ts":1786060393,"wall":"2026-08-06T19:53","msg":"fix: every renewable regrew sixty-four thousand times too fast","body":"Deposits.regrow read regrow_per_second as a FRACTION OF POOL per second. Every\ndocument, comment and test read it as UNITS per second. Measured end to end\nrather than read, an emptied peat bog refilled in 1,201 seconds — twenty real\nminutes — against the two thousand game-years its own design states.\n\nThe operator's call: units per second, and re-derive all nineteen.\n\nTHE DERIVATION. Refill time in game-years equals real recovery time in WORLD\nyears, because a game year is a world year here — the calendar is compressed\nagainst real time, not against the world's own clock, so an ecological figure\nmaps straight across with no conversion factor to get wrong. That is the same\nmove the pools already made when they were sized from standing biomass instead\nof from feel.\n\nEvery rate is now written as refills_in(pool, world_years) rather than as a\nfloat, so what a reader sees is the fact — a conifer forest takes a century, a\nwater fern takes seven weeks — and what the computer sees is the arithmetic.\nFour orders of magnitude, from azolla at 0.15 years to peat at 2,000.\n\nPeat is the only number that did not move. It was the one resource whose rate\nhad been derived honestly in the first place, which is exactly why the\ndiscrepancy was visible from it.\n\nFLAT UNITS HAS A CONSEQUENCE, and it is the right one: a richer cell takes\nproportionally longer to refill, because a deeper bog is not laid down any\nfaster than a shallow one. Stripping the best ground now costs more time to\nundo than stripping poor ground. It has its own test.\n\nAND THE TESTS NOW DRIVE THE FUNCTION. The old peat test computed\npool / (rate x year) itself and asserted the answer — a restatement of the\nintended arithmetic, which is why it passed for months over a knob wired to\nnothing. The new ones strip a cell bare, run the real regrowth, and measure how\nlong it takes to come back. That failure mode has now happened twice; the\nterrain oracle was built to end it and this is the second place it was hiding.\n\n`geology` is gone from regrow's signature, since a flat rate does not consult it.\n\n329 server tests, ruff clean.","parents":["53cc7adbe063dc781e7651c2f8668eadd56f8857"],"add":232,"del":64,"cadd":232,"cdel":64,"files":6},{"repo":"hexa","hash":"ddf31c2249406c623417cd3e322c192aa3320981","ts":1786062790,"wall":"2026-08-06T20:33","msg":"fix: the planet wore a grid, and drew itself one LOD level coarser","body":"Two defects in the terrain, found by measuring the drawn surface rather than\nreading the code that produces it.\n\nTHE GRID OF SEAMS was shading, not geometry. computeVertexNormals sees only one\nnode's own triangles, so a vertex on a node's boundary got a normal accumulated\nfrom three of the six triangles that actually surround it — tilted inward, and\ntilted a different way in each of the two nodes holding it. Positions matched to\nthe last bit; only the light disagreed, which is why it survived so long. On the\nsurface actually drawn, 9,207 shared-vertex pairs disagreed, the worst by 40\ndegrees. Every node edge at every level drew itself as a line.\n\nThe same one-sided arithmetic ran through the slope that decides how much\nbedrock shows, and the colour blur simply refused to touch the boundary ring —\nthe one ring two nodes SHARE was the one ring neither smoothed.\n\nThe fix is a BORDER of samples taken beyond the node and thrown away before\nanything reaches the GPU. Two neighbours then derive a shared vertex from an\nidentical triangle fan, so they agree because they computed the same thing and\nnot because a tolerance was tuned. Within a cube face the disagreement is now\nexactly zero. Costs 26% more height samples per node and not one triangle or\nbyte on the GPU.\n\nTHE GEOMORPH WAS PINNED AT 1. select() hands a node to its children while the\neye is nearer than F extents, so a node is only ever DRAWN from F outward — and\nthe morph band ran from 0.66F to F, entirely inside the region where the level\nis not on screen at all. Every drawn vertex sat past the far end and clamped:\n97.5% of the visible planet was rendering its PARENT's shape. The finest level\nwas sampled, meshed, uploaded and discarded every frame, and the two properties\nthe morph exists for were vacuous rather than true. The band now spans [F, 2F] —\nthe range a level is actually drawn over, ending exactly where its parent takes\nover. Detail roughly doubles at no triangle cost.\n\nFalling out of that: surfaceHeightAt morphed ONCE at the prop, while the GPU\nmorphs per vertex and interpolates across the result. Identical while the factor\nwas stuck at 1; three samples buried by 68 cm the moment it started varying. It\nnow does what the hardware does, and burial went from 0.01 m to 0.001 m.\n\nparentHeights also interpolated the parent BILINEARLY where the parent mesh\ndraws triangles — so the surface a child morphed onto was not quite the one its\nparent draws. Now the triangle, matching surfaceHeightAt's own reasoning.\n\nAND THE TESTS AGREED WITH BOTH BUGS. globe-check asserted\nmorphFar === RANGE * extent(level) — the renderer's own formula, copied — and\nthat formula IS the defect, so the check passed. ground-truth-check baked the\nmorph with the same copied band, so it too saw nothing. Two transcriptions of\none mistake read as a passing test. The assertions are now properties: the band\nmust end where the parent takes over and must not begin before the level is\ndrawn, neighbours must shade a shared edge identically, and the planet must not\nbe drawing itself one level coarser. All four fail on the old code.\n\nLeft standing and now bounded rather than hidden: the twelve cube edges, where\ntwo faces do not parameterise into each other and a border sample cannot land on\nthe neighbour's grid. 165 of 8,969 shared vertices, twelve arcs rather than a\ngrid. And cracks at LEVEL boundaries, worst 28.5 m, down from 700 vertices to\n154 — a coarse node can be morphing toward its own parent while a finer\nneighbour has already morphed onto it. Both measured, both asserted against\ngrowth.\n\n169 client checks, tsc and build clean.","parents":["1bb331b3870774d03e0e03ecac719135dcaa3487"],"add":431,"del":108,"cadd":431,"cdel":108,"files":3},{"repo":"hexa","hash":"2c70c09c4dc0b0e063c13ede14516c2bde464cf3","ts":1786063262,"wall":"2026-08-06T20:41","msg":"fix: the sea was still drawing the grid after the land stopped","body":"The seam fix covered the land and left the ocean accumulating its normals the\nsame broken way — which is why the grid was still showing up occasionally, over\nwater.\n\nIt was worse there. Only WET quads are meshed, so a vertex on a shoreline\ncarries a single triangle in one node and a full fan in the next, and the two\nnormals disagreed by up to a RIGHT ANGLE across 8,512 shared pairs. A border of\nextra samples cannot help: the missing triangles are not outside the node, they\nare dry.\n\nThe sea is level. Its normal is the up direction, exactly, everywhere — so it is\nnow written rather than accumulated. Zero disagreement, and cheaper than the\naccumulation it replaces.\n\nAsserted in globe-check beside the land seam; it fails on the old code.\n\n169 client checks, tsc and build clean.","parents":["ddf31c2249406c623417cd3e322c192aa3320981"],"add":60,"del":1,"cadd":60,"cdel":1,"files":2},{"repo":"hexa","hash":"bb95390542f636451ed8f6f83ccac67032a6c7b6","ts":1786064021,"wall":"2026-08-06T20:53","msg":"feat: a pawn is born carrying nothing, because it is an arthropod","body":"Every pawn was issued a Mesnada starter kit at birth — leather and a shortsword,\nleather and a shortbow, chainmail and a longsword, leather and a sling — plus a\ntorch and a headlamp each, and a tactical headlamp for the point pawn. All of it\nassumes a torso to strap armour to and a fist to close around a hilt or a lamp.\nThis animal has neither.\n\nWhat it fights with, it grows: claws, acid, fire. What it sees by, it will grow\n— one caste is to carry a bioluminescent organ throwing light in every direction\nat once, which is not something a held torch can do. Until that organ exists the\ndark is simply dark, and that is the honest state rather than a torch standing\nin for it.\n\nTwo halves, because a snapshot does not re-derive itself:\n\n- add_player_with_pawns now spawns with an empty body and an empty bag, which\n  fixes every pawn born from here on and nothing already standing in the world.\n- tools/strip_gear.py takes the equipment off the pawns in an existing world.\n  Idempotent, refuses to run while the shard is listening, tmp+rename, and\n  verifies by reading the file back rather than trusting its own dict. Applied\n  to the live world: 17 items off 4 pawns at tick 361,628.\n\nTHE GEAR SUBSYSTEM IS KEPT AND IS NOT DEAD CODE. Every rule in world/gear.py is\ncorrect for anything humanoid — bonuses scaled onto the 0-100 sheet, the best\nlamp winning by REACH rather than lumens, encumbrance over gear plus bag plus\nhaul — and this world is not promised to stay arthropod-only. What changed is\nwho is issued equipment at birth, which was never that file's decision. Items,\nloadouts and equip/unequip all still work for whatever turns up with hands.\nNoted at the top of gear.py so the next reader does not mistake it for rot.\n\nThe kit is NOT dropped on the ground. It was never lawfully theirs — it is an\nartefact of this world having been seeded by another game's code — and leaving\nfour swords in the dirt of a planet with no smith and no hands would be\ninventing history rather than correcting it.\n\nThree tests asserted the old canon and now assert the new one, including that a\nstripped pawn's light radius is zero — so the day a light source exists again,\nthat is the test that says so.\n\n329 server tests, ruff clean.","parents":["2c70c09c4dc0b0e063c13ede14516c2bde464cf3"],"add":188,"del":28,"cadd":188,"cdel":28,"files":5},{"repo":"hexa","hash":"5873413ce9ad251f40a1948b489c32e171f76cc4","ts":1786064815,"wall":"2026-08-06T21:06","msg":"feat: right-click an organism and the world tells you what it is","body":"The operator asked for this before the regrowth rates, the terrain seams and\nthe gear, and it kept losing. It is the first tier of the three the research\nsettled on: SIGHT IS FREE, STUDY IS WORK, PROSPECTING IS FOR WHAT IS BURIED.\nThis is sight.\n\nNothing was pickable before. The context menu already handled pawns and ground,\nbut every plant on the planet is drawn as an InstancedMesh and no ray was ever\ncast at one, so the most conspicuous thing on screen was the one thing the game\nwould not talk about.\n\nWHY IT COSTS NOTHING. Every L1 producer is chosen by BIOME alone and the client\nholds every cell's biome, so what is drawn is already exactly what the server\nwill hand over. Charging a survey to learn that a bracken thicket is bracken is\na fiction maintained against the player's own eyes — the toll booth the\nroguelike literature warns about, performed before the real game starts. What\nstays earned is the state of a particular stand and what lies under it, and\nneither is in the catalogue.\n\n- Every resource carries a `note`: one line, the thing worth knowing. Twenty\n  seven of them, authored rather than generated — sphagnum is antiseptic and was\n  field dressing before anyone knew why; clubmoss spores are a sheet of fire in\n  air; a ring cut round a conifer kills it and a panel does not.\n- The catalogue rides the WELCOME, once. Thirteen fields, no per-place data, no\n  second copy to drift.\n- `Vegetation.pick` returns what is under the cursor. Which SPECIES, not which\n  individual: the server has no notion of a particular plant, only of what a\n  cell holds, and a stand of bracken is worked as a stand.\n- The menu grows a heading, the field-guide line, and what the thing yields —\n  with the tool it needs and how long it takes to come back, phrased as a person\n  would say it rather than as a float. Azolla reads \"back in 8 weeks\"; peat\n  reads \"back in 2000 years\".\n- A conifer is FIVE harvests off one tree — timber, resin, bark, cones, and the\n  bast under the bark that can be taken without killing it — so a species may\n  declare what it yields where its name is not itself a resource.\n\nClient and server are checked against each other rather than against a copy:\nfield-guide-check reads the server's own resource table off disk and asserts\nthat every organism the client draws is a resource the server defines and has\nsomething to say about. A copy would agree with itself forever.\n\nStill to come, and named so it is not mistaken for done: STUDY as a job,\nPROSPECT narrowing to what is actually buried, and a cancel verb — there is\nstill no way to clear a pawn's job once given.\n\n330 server tests, 10 client suites, tsc and build clean.","parents":["bb95390542f636451ed8f6f83ccac67032a6c7b6"],"add":437,"del":2,"cadd":437,"cdel":2,"files":10},{"repo":"hexa","hash":"a73907670101e60ab3909f5f37b80e36d4f9fb72","ts":1786065847,"wall":"2026-08-06T21:24","msg":"fix: harvesting was impossible for half the planet, and said nothing","body":"Asked whether the world could be harvested yet, the honest answer was: fourteen\nof twenty-seven resources yes, thirteen no — and the thirteen were unreachable\nby ANY sequence of actions a player could take.\n\nTHE TOOL CHAIN WAS A CLOSED LOOP. A pickaxe needs iron ingots and a plank. The\nore needs a pick to mine; the timber needs an axe to fell. No starting kit ever\nheld either — the founders were issued swords and armour — and crafting has no\nnetwork verb, so nothing could be made even with the materials. Every metal,\nevery stone, all the timber, coal, limestone, diatomite, resin, bark, cycad pith\nand the prototaxites sat behind a door with no key anywhere in the world. This\npredates the gear being taken off anybody; removing the swords changed nothing\nabout it.\n\nAND IT FAILED SILENTLY. `_do_harvest` dropped the job and returned. Four pawns\nordered to fell timber walked over, stopped, and stood there — no message, no\nmarker, nothing in the log to tell a player from a bug. A refusal nobody can see\nis indistinguishable from a broken game.\n\nThree fixes, all following canon already set:\n\n- THE BODY IS THE TOOL. Mandibles are a shearing pair driven by the largest\n  muscles the animal has; chelae are a lever with a fulcrum, which is the entire\n  mechanism of a pick. A beetle larva in heartwood is not waiting on a forester's\n  axe. So the body satisfies `axe` and `pick` directly, and carried tools still\n  satisfy everything they always did — a humanoid with a pickaxe is unaffected.\n- A SPADE IS STILL A MADE THING. Peat is cut in bricks with a long one-sided\n  blade and neither mandible nor claw will do it. That was the original intent\n  and it is now reachable rather than impossible: claws get the ore, the ore\n  becomes iron, and a swamp becomes a fuel province the moment somebody forges\n  the blade for it.\n- REFUSALS ARE VISIBLE. Pawns carry a `refusal`, sent to the OWNER only — a\n  rival sees your pawn stop, not why — cleared by the next order, and shown once\n  per reason rather than every 250 ms.\n\nSeparately, the client greyed out \"work this ground\" until the ground had been\nprospected. Never gate an action behind knowing a name: a pawn can cut bracken\nit was never told is bracken. Study should make you BETTER at working a stand,\nnot be what makes working it possible — otherwise the first thing a new player\ndoes is an errand performed before the game will let them play. The menu now\noffers \"Harvest Amadou\" against whatever is under the cursor, and names it.\n\nStill not wired: crafting has no verb at all, so the forge recipes remain data\nnobody can reach. That is the next hole and it is bigger than this one.\n\n332 server tests, 10 client suites, tsc and build clean.","parents":["5873413ce9ad251f40a1948b489c32e171f76cc4"],"add":175,"del":8,"cadd":175,"cdel":8,"files":8},{"repo":"hexa","hash":"257fcac6086232aa5d332709596289ed25433609","ts":1786077456,"wall":"2026-08-07T00:37","msg":"docs: the body as industry — metabolism, castes and material science","body":"The hive should not be given crafting with insect skins on. The organism is the\nrefinery: matter goes in as something common, and what comes out is decided by\nwhat went in and by which body did the processing.\n\nCRAFTING STAYS, and this document says so at the top. Many inhabitants of this\nplanet will be humanoid or human and they must craft; the hive grows a caste for\nthe problem instead. Neither can perform the other's trick, and the economy\nworth having is the trade between two technologies that cannot copy each other.\n\nThree real mechanisms, and they stack:\n\n- DIET DECIDES THE CASTE. Honeybee queens and workers are the same genome\n  separated by larval diet, through DNA methylation. Kucharski 2008 silenced one\n  methyltransferase and got queens with no royal jelly at all. So you do not\n  engineer a caste, you feed one — and caste must stop being something express()\n  returns.\n- GUT FLORA DECIDES THE CAPABILITY, AND MOULTING TAKES IT AWAY. A termite cannot\n  digest wood; the hindgut protists do, and they are DISCARDED AT EVERY MOULT and\n  re-acquired from nestmates by trophallaxis. A termite that moults alone starves\n  in a forest. So the hive's industry lives in living bodies rather than a tech\n  tree: losable, transmissible, and therefore tradeable — you can sell a humanoid\n  town a culture and they cannot manufacture one.\n- A BIOELECTRIC LAYER DECIDES WHAT GETS BUILT. Levin's planaria regrow a second\n  head after a brief channel block, and the two-headed form persists through\n  later cuts with the genome untouched. A rewritable template of what to build,\n  editable in hours.\n\nMOULTING IS THE HINGE, and BodyPlan already carries moult_interval_ticks with\nnothing consuming it. One timer we already ship gives chitin (Nausicaa's Ohmu\nshell is cut from a SHED carapace, not a corpse), voids the gut, and opens the\nonly window in which caste can be re-expressed.\n\nThe fiction was read for its material science rather than its plot. Miéville's\nkhepri eat colourberries and sculpt with what comes out the other end — the diet\nIS the material, which is the mechanic stated as cleanly as it can be.\nVanderMeer's gray caps make technology that reads as a parody of ours, which is\nthe standard hive goods must meet or trade is a reskin.\n\nOn Rupert Sheldrake, fairly: morphic resonance has not been demonstrated and\nthis document does not claim it has, but the question he pressed — if form is\nnot fully in the genes, where is it kept — is the question Levin found a\nmechanism for. A world is entitled to its own physics. What matters is knowing\nwhich layer we are standing on.\n\nMerlin Sheldrake's networks turn out not to be a new layer at all: the\nPrototaxites exosymbiont in biosphere-without-flowers already IS this body. What\nthe research adds is a motive — a node is subsidised \"not to save the tree for\nthe sake of the tree, but to prevent the loss of a useful node\" — and therefore\nthat regrowth should scale with connectivity, multiplying the recovery times\nalready derived rather than replacing them.\n\nAlso names two gaps found while writing: there is no drinkable water resource\nanywhere in a world about to have thirst kill people, and the cancel verb\nbecomes load-bearing the moment work is automated.\n\nIngested to unicursal, 15 fragments across all 13 axes.","parents":["a73907670101e60ab3909f5f37b80e36d4f9fb72"],"add":283,"del":0,"cadd":283,"cdel":0,"files":1},{"repo":"hexa","hash":"c34ac90971cd96e3aafa2b0af53fd81f65a3fb62","ts":1786078201,"wall":"2026-08-07T00:50","msg":"docs: the excretion economy — piss and shit are the chemical industry","body":"Operator's ruling: eating, drinking, pissing and shitting are all real and all\nfour are USEFUL. No game makes you do them because no game makes them worth\nanything. Here they are where the chemistry comes from. Researched rather than\nwaved at, and it turned out to be the most historically literal part of the\nwhole design.\n\nAN ARTHROPOD DOES NOT PISS. Insects are uricotelic: nitrogen leaves as uric\nacid, a near-dry paste, because that is how you excrete without spending water.\nMammals are ureotelic and pay in water. That is a strategic asymmetry rather\nthan a detail — a humanoid settlement needs water simply to excrete and a hive\nbarely does, so THE DRY COUNTRY BELONGS TO THE HIVE, for a reason that can be\ntold in one sentence.\n\nURATE IS A BATTERY, NOT A WASTE. Cockroaches do not excrete their urate, they\nbank it in dedicated urocytes in the fat body, beside mycetocytes housing\nBlattabacterium. The symbiont cannot break urate down itself but recycles the\nurea and ammonia coming off it into glutamate, and from there makes every\nessential amino acid and vitamin from a very short list of inputs. So nitrogen\nwaste is a bank and the symbiont is the only thing that can withdraw from it.\n\nTHAT IS THE REPLETE, and it is better than the honeypot ant that suggested it: a\nfat body full of banked nitrogen plus a resident bacterial factory. Feed it and\nit charges; what it can pay out is decided by which symbiont it carries.\n\nTWO CLASSES OF SYMBIONT, TWO ECONOMIES. Gut flora sits in the hindgut, is lost\nat every moult and is re-acquired socially — it circulates, it can be taught,\nit can be sold. A fat-body endosymbiont is inherited through the egg and never\nlost — it belongs to a lineage and must be bred. Some trades you spread by\nfeeding; others you can only get by breeding.\n\nWHAT THE HUMANOIDS WILL PAY FOR, and none of this is invented: guano, nitrogen\nand phosphate, was Peru's dominant export from about 1840 until Haber-Bosch\nkilled it in 1909, and nations fought over the islands. Saltpetre is niter beds\nof straw and manure wetted with urine and privy-liquor, left months while\nbacteria turn urea to nitrate — that is gunpowder, and Napoleonic France\ncollected its soldiers' urine for it. Phosphorus is Hennig Brand boiling fifteen\nhundred gallons of urine in 1669 looking for gold and getting a white solid that\nGLOWED, which he named the light-bearer.\n\nThat last one closes a loop the operator opened earlier: the promised\nbioluminescent caste and the phosphorus in the excreta are the same chemistry.\n\nAnd the trade asymmetry is the good part. The hive cannot forge and does not\nwant to; the humanoids cannot grow a caste. But humanoid gunpowder, fertiliser\nand chemistry all begin in something the hive produces without trying. The\ntechnologically primitive party sells the industrial one the input to its\nindustry, and the guano wars are the precedent.\n\nTHROUGHPUT SETTLED: a ferry chain, and crop capacity scales with connectivity to\nPrototaxites. The nitrogen exosymbiont literally distends its repletes — one\nproperty of the ground now explains both how fast it recovers and how much can\nbe carried across it.\n\nRe-ingested, 21 fragments.","parents":["257fcac6086232aa5d332709596289ed25433609"],"add":116,"del":7,"cadd":116,"cdel":7,"files":1},{"repo":"hexa","hash":"e6ff03c8eb548e257bff5f9c51fb9f0dbc9f6e5a","ts":1786078311,"wall":"2026-08-07T00:51","msg":"docs: it runs both ways, and the price depends on the diet","body":"The operator's follow-up — humanoid excreta count too — closes the loop rather\nthan adding to it. A humanoid is ureotelic: watery, nitrogen-rich waste in\nvolume, which is exactly what a niter bed wants and exactly what a replete wants\nto bank. So the hive does not only sell. It buys a town's latrines, and a\nwell-fed town is a nitrogen mine.\n\nEdo ran this as a real market for three hundred years. Night soil was collected,\npriced and shipped; farmers sent boats into the city loaded with vegetables and\ntook the city's waste back out. Waste from wealthy households and feudal estates\ncommanded a PREMIUM because the servants there ate well and it showed in the\nnutrient content, and by law the privy's output belonged to the landlord — who\ncould make roughly twice a carpenter's annual income from it.\n\nWhich means the khepri rule is not just a crafting mechanic, it is an economy\nthat has already existed: the value of what comes out is a function of what went\nin. The same sentence governs a replete's yield, a builder's wall, and the\nmarket price of a town's latrine.\n\nConsequences that need no further invention: a prosperous humanoid city is worth\nmore to a hive alive than sacked; besieging a town degrades its output before\nits walls; feeding your own repletes well is quality control rather than\nsentiment; and somebody owns the privy, which was a property right worth real\nmoney and is a better source of conflict than most invented ones.","parents":["c34ac90971cd96e3aafa2b0af53fd81f65a3fb62"],"add":36,"del":0,"cadd":36,"cdel":0,"files":1},{"repo":"hexa","hash":"0bf17ce4d9133fc5475810ed7f51957c94d00fdb","ts":1786082826,"wall":"2026-08-07T02:07","msg":"feat: cancel — the one verb that was missing","body":"Nothing in this shard could clear a pawn's job. An order, once given, ran until\nthe ground was worked out or the pawn found it could not do the work, and\nwalking away only paused it. That was survivable while every job ended by\nitself. It stops being survivable the moment work repeats: a job that renews\nwith no way to stop it is not a busy pawn, it is a pawn you have lost.\n\nClears the three things that together mean \"still trying\" — the job, the route,\nand any refusal left from the last attempt.\n\nWHAT IT DOES NOT TOUCH IS THE LOAD. Cancelling an order is not throwing away\nwhat a pawn is carrying, and in a world that cannot destroy matter the\ndifference is not a nicety. Putting things down already has its own verb and its\nown pile. Asserted, because it is exactly the sort of thing a later refactor\nwould quietly fold together.\n\nBound to C rather than Escape. Escape already hands the camera back, and\noverloading it would mean the reflex for \"get me out of this view\" silently\nabandons whatever the squad was doing.\n\nFirst step of the metabolism plan (.claude/plans/hexa-metabolism-and-castes.md,\nrenamed off the auto-generated name plan mode insisted on). Mortality and\nlifespan are next, and they are the ones that make the reproducer caste\nnecessary rather than decorative.\n\n333 server tests, 10 client suites, tsc and build clean.","parents":["e6ff03c8eb548e257bff5f9c51fb9f0dbc9f6e5a"],"add":97,"del":0,"cadd":97,"cdel":0,"files":4},{"repo":"hexa","hash":"0f57cbeac63ad4d1cf1bbb965955c05f3d574dfb","ts":1786085365,"wall":"2026-08-07T02:49","msg":"feat: things die, and the world remembers them","body":"Nothing in Hexa could die. `is_downed` marked a body down and process_recovery\nstood it back up; no pawn was ever removed and no pawn had an age. That is not\njust a missing feature — a hive whose members do not die never needs to\nreproduce, so the reproducer caste asked for on the first day had nothing to\nanswer.\n\nA LIFESPAN IS A COUNT OF MOULTS. Determinate growth is the arthropod condition:\nan animal moults a fixed number of times, stops, and stopping is the end of it.\nSo `instars` joins the genome beside moult_interval, and lifespan is teneral\nplus instars x interval. One clock drives growth, the loss of gut flora (Phase\n4) and death, with no second timer to keep in step by hand. A body that does not\nmoult is not on a clock at all, which is what keeps grown artifacts and test\nfixtures from dying on their first tick.\n\nNOTHING IS DESTROYED. A death is a TRANSFER: the carried load and the cuticle\nthe body was wearing are set down where it fell, through the same\n`piles.drop` that `drop_load` uses. Chitin is a resource now — in no biome, so\nnothing digs it out of the ground; it exists because bodies do. Nausicaa's\npeople cut their armour out of a MOULTED carapace, which is the calm route to\nthe same substance; this is the other one. An old hive is a materials supply.\n\nPAWN RECORDS, per the operator's call. A pawn existed only as an integer in a\nplayer's list, which was fine while nothing could die and stops being fine the\nmoment something can — `kill` removes the body, and the world would have kept no\nmemory that it was ever there. So a death CLOSES a record rather than erasing\none, and `died_tick` is the whole difference between a roster and a history.\nNames, owners, birth, death, cause and parents, ready for the generation that\nasks who its mother was. Registry format 1 -> 2, and a v1 file still loads: its\nplayers list what they command, so the living reconstruct exactly, and nothing\nthat died is lost because nothing could die.\n\nTWO TRAPS FOUND AND DISARMED.\n\n`Registry.forget` takes a PLAYER id. Handing it a pawn id — which is what the\nfirst draft of kill() did — would have deleted a player the first time anything\ndied.\n\nAnd `born_tick` defaults to 0, which is a default masquerading as a fact. The\nlive world is at tick 408,915: it would have read those zeroes as \"born at the\nbeginning of time\" and reaped all four founders on the first tick after the\nupdate, mass death caused entirely by a field that had not existed yet. The\ntruthful answer is that their age is unknown, so `start_the_clock` starts it at\nload. Same reasoning `rehome_stranded` uses on positions and `genome_of` uses on\nmissing genomes: an absent fact must not be filled in with a lie that parses.\n\nIMMORTALITY, blunt and on purpose. `tools/immortal.py` raises or lowers a\nper-pawn override; the four founders of the live world are protected while the\nmechanics meant to feed them are still being built. It suppresses only the\nending — hunger and thirst, when they arrive, will still climb and still show.\n\nThe roster is now sent every tick instead of once at join, because a body can\nstop existing while the player is looking at it, and the client was still\nlisting it, offering it, and selecting it with a digit.\n\n342 server tests (10 new), 10 client suites, tsc and build clean.","parents":["0bf17ce4d9133fc5475810ed7f51957c94d00fdb"],"add":1156,"del":59,"cadd":680,"cdel":2,"files":14},{"repo":"hexa","hash":"99ca1a61eeafc8d58cd1c935282de701ba4647c5","ts":1786085692,"wall":"2026-08-07T02:54","msg":"fix: giving a body its first record is not a disagreement to report","body":"`reconcile` returns the notes the boot log prints, and those notes are for\nDISAGREEMENTS between the registry and the pawns — ownership that had to be\nrepaired. Backfilling a pawn record for a body that predates pawn records is not\nthat; it is filling in a field that did not used to exist. Reporting it meant\nevery world older than the feature booted complaining about a world that was\nfine, and it broke the test that says a world already in agreement changes\nnothing.\n\nCaught by that test, and it was right.\n\nAlso worth recording how it reached master: the previous commit ran as\n`pytest | tail -3 && git commit`, and a pipeline's exit status is the LAST\ncommand's — tail always succeeds. So the chain committed over a red suite that\nwas printed on screen at the time. The gate has to read pytest's own status, not\nthe status of whatever formatted its output.\n\n343 server tests.","parents":["0f57cbeac63ad4d1cf1bbb965955c05f3d574dfb"],"add":6,"del":1,"cadd":6,"cdel":1,"files":1},{"repo":"hexa","hash":"13546eece1abe2cf7fcbbd592c2b7765ee0cc437","ts":1786088437,"wall":"2026-08-07T03:40","msg":"fix: an organism owes its age to nothing outside itself","body":"The first version of ageing computed it as `state.tick - born_tick`, tying every\nbody's life to the planet's absolute clock. That is backwards, and it generated\nall of its own problems: every body needed a timestamp in world time, anything\nthat predated the field needed a migration to invent one, and a zero could not\nbe told apart from \"born at the dawn of time\" — so the live world at tick\n408,915 would have reaped all four founders on the spot.\n\nThe patch for that was a None sentinel plus a `start_the_clock` pass at load,\nwhich was scaffolding holding up a bad frame. Both are deleted.\n\nA BODY COUNTS ITS OWN YEARS. `Pawn.age_ticks` goes up while it lives and refers\nto nothing else. There is then nothing to disambiguate: a default of zero is\nhonest, because it means this body has not lived long. An old snapshot loads as\nnewborn, which is a reading rather than a repair. Drop a pawn into a world five\nmillion ticks old and it is still newborn, because how long the planet has been\nturning is not a fact about the animal.\n\n`PawnRecord.born_tick` keeps world time deliberately — a CHRONICLE may ask \"when\ndid that happen\", which is a question about the world and fairly asked in the\nworld's units. Nothing reads it to decide anything.\n\nEverything ages, including what cannot die of it: immortality suppresses the\nending, not the clock, or lowering the flag later would hand a body back every\nyear it lived through.\n\nTWO OTHER TRAPS, disarmed rather than patched.\n\n`Registry.forget(player_id)` was `players.pop(id, None)`, so handing it a PAWN\nid returned None and did nothing whatever — which is how the first draft of\nkill() would have shipped, silently failing to detach anything. It is\n`forget_player` now, and an integer raises TypeError. Forgetting an absent\nplayer stays a legal no-op, because that genuinely is one.\n\nAnd check.sh, because a commit went out over a red suite gated on\n`pytest -q | tail -3 && git commit` — a pipeline's status is the LAST command's,\nand tail always succeeds. Thirteen gates in one place, every status read\ndirectly, nothing piped into anything that could swallow one. Verified by\nbreaking a test on purpose: exits 1 broken, 0 clean, 0 restored.\n\nNothing is committed without ./check.sh green. This commit is the first that was.","parents":["99ca1a61eeafc8d58cd1c935282de701ba4647c5"],"add":204,"del":82,"cadd":204,"cdel":82,"files":9},{"repo":"hexa","hash":"2db4447584713bab11bfe52eff25c99d9fe63ab9","ts":1786109975,"wall":"2026-08-07T09:39","msg":"feat: hunger, thirst, and a system of measurement to state them in","body":"Phase 2 of the metabolism plan, plus the units question it exposed.\n\nWHAT NEARLY SHIPPED. Food was quoted as \"a share of a reference body's daily\nneed\" — a ratio wearing the coat of a measurement. It composes with nothing, it\ncannot be checked against the world, and it silently makes one particular body\nthe yardstick for the universe. world/units.py is now the single registry: SI as\nthe spine, every quantity's unit in its name, and every derived constant naming\nthe real measurement it came from.\n\nKLEIBER'S LAW, which fixes an actual error. I had scaled food need by mass — the\ncube of length. Metabolic rate goes as mass to the three-quarters, which is why\nan elephant eats far less per kilogram than a mouse. Under the wrong version big\nbodies are punished linearly; under the right one a large body is CHEAPER to run\nper kilo and a small one is always hungry, which is a strategic texture that was\nbeing thrown away. A 70 kg body now costs 6,273 kJ/day and an 800 kg one 48.7\nkJ/kg against the small body's 308.\n\nURICOTELY IS THE DESERT ASYMMETRY. Insects void nitrogen as a near-dry paste\nprecisely so they need not spend water flushing it. A 70 kg body here drinks\n0.50 L/day where the ureotelic humanoid line is 2.50. One number, and it is why\nthe dry country belongs to the hive.\n\nAnd `xeric` joins the genome: how much of the water in food a body wrings out\nand keeps. At the low end an animal must find standing water; near the top it\ndrinks its dinner and crosses ground that would kill something else. A lineage\nworth breeding rather than a line of flavour.\n\nFORCE AND STRESS, which turns two booleans into a mechanic. `cuts()` and\n`breaks()` answered whether a body HAD mandibles or chelae. Now muscle pulls\n300 kPa of its own cross-section — real, and about the same in every animal\nanybody has measured — cross-section goes as the square of length while mass\ngoes as the cube, and that is why a small animal is relatively strong without\nanybody tuning it. A founder brings 1,633 N of bite through a 20 mm2 edge, which\nis 82 MPa; a chela brings 2,654 N bluntly but levers against the tensile\nweakness of brittle rock and reaches 66 MPa equivalent.\n\nMaterials answer in the same units: green conifer shears at 9 MPa, limestone and\nore fail near 9-15, prototaxite at 15. So `tool_tag` for axe and pick work is\ngone, replaced by a threshold that says what the tag could not — WHICH bodies\ncan do it and how close to the edge of their strength they are working. A shape\ntool is still a made thing: peat is cut in bricks with a long one-sided blade\nand no amount of strength substitutes for the blade.\n\nEating and drinking ship WITH this rather than in Phase 3, because thirst that\nkills without a way to drink is not a phase, it is a bug. Water is a resource in\nthe ground like any other and drinking is a harvest that goes into the body\ninstead of into the load — only as much as there is room for, so a closed world\nnever has to hand back what nobody swallowed. Sphagnum is not food; it is water\nyou can chew, and the model says so.\n\nTWO THINGS THE GATE CAUGHT, both real. A geometry test walked a pawn 128 km and\nit died of thirst on day three — the helper had been driving a body that no\nlonger existed and reported it as a failure of the planet's shape. It raises\nnow. And `vegetation-check` refused water as an invisible resource, correctly by\nits own rule: the exemption is that the terrain draws the sea itself.\n\nReserves are in DAYS, on the wire and in the menu, because a day is the unit a\nplayer can act on. -1 is uninitialised as with stamina and hp, so a body that\npredates hunger wakes up fed rather than starving — the same mistake the birth\ndate made once already, and it does not get to happen twice.\n\n353 server tests, 10 client suites, ./check.sh green.","parents":["13546eece1abe2cf7fcbbd592c2b7765ee0cc437"],"add":982,"del":75,"cadd":938,"cdel":75,"files":20},{"repo":"hexa","hash":"4c424b5c59dda2ce62442ba8c03bc8a191edaf8c","ts":1786114643,"wall":"2026-08-07T10:57","msg":"refactor: delete thirty-one constants nothing was using","body":"First pass of the modularity work, and the cheapest: config.py carried a whole\nretired limb. The flat-square world was replaced by the sphere and its constants\nwere never removed — WORLD_CELLS, CELL_M, the erosion knobs, the old biome\nthresholds, the land-bridge repair budget. Alongside them, constants orphaned by\nlater work: STARTER_LOADOUTS died when the gear came off the pawns, PLANET_SEED\ndied when the planet became an asset loaded from disk, DEFAULT_STANCE was\nshadowed by a literal on Pawn.\n\nFound mechanically rather than by eye — every name defined in config.py, grepped\nacross the whole server for a use outside it. Thirty-one had none. 307 lines down\nto 253.\n\nAlso adds tools/modularity.py, which measures the shape of the server rather than\ntrusting anybody's memory of it: fan-in, fan-out, and import cycles by Tarjan.\nZero cycles across 38 modules is the expensive property this codebase has and it\nwas found by accident during an audit; a property nobody checks is one you have\nuntil the day you do not. `--strict` exits non-zero on a cycle, so the rest of\nthis refactor is guarded rather than hoped for.\n\nWorth recording a failure on the way: the first attempt at moving constants used\na regex import-rewriter that collapsed every multi-line `from world.config\nimport (...)` in fifteen files, including files where nothing had moved, and\nleft the definitions duplicated in their new home. Reverted whole. A refactor\nthat touches files it has no business touching is not a refactor.\n\n355 server tests, ./check.sh green.","parents":["2db4447584713bab11bfe52eff25c99d9fe63ab9"],"add":153,"del":54,"cadd":153,"cdel":54,"files":2},{"repo":"hexa","hash":"312c9b097845661ae12b0040b9db80363cad5533","ts":1786116689,"wall":"2026-08-07T11:31","msg":"refactor: constants live with the system that owns them","body":"config.py was 307 lines imported by twenty modules, and I edited it four times\nin one afternoon for four unrelated reasons — gear, chitin, metabolism, drinking.\nA file changed for many reasons belongs to none of them, and every module in the\nserver carried a dependency on constants it never used.\n\nIt is 53 lines now, fan-in 20 down to 7, and no longer the most depended-on\nmodule in the codebase.\n\nWind went to stamina, the planet's shape to globe and the grid's to sphere,\nforce and materials to units, hunger to metabolism, what a body is worth dead to\nmortality, damage to combat, pile reach to piles, snapshot format to persist.\nWhat is left is what is genuinely global: the tick, where the assets are, the\nshard's defaults, and the socket.\n\nTHE RULE THAT FELL OUT, and it earned itself twice: if a number is only\nmeaningful inside one system, it goes there; if two systems that do not import\neach other need it, it goes to the layer BENEATH them both, never to a shared\nbag.\n\nBoth violations were caught by tools/modularity.py rather than by a person.\nCARRY_SKILL_BONUS went to work and made combat <-> gear <-> state <-> work,\nbecause work already imports gear — carry capacity is an effective stat and is\ncomputed in gear, so that is where it belongs. FACE_CELLS and PLANET_RADIUS_M\nwent to globe and made globe <-> sphere, because a planet is built ON a\ncube-sphere rather than the other way around; they describe the shape of the\ngrid, so they went down to sphere. Zero cycles before, zero after, and this time\nthe property was measured instead of remembered.\n\nThe mover is deliberately surgical: a file is rewritten only if it actually\nimports a name being moved, multi-line imports stay multi-line, and constants\nland under a module's imports rather than bolted to the end of it. The first\nversion flattened every config import in fifteen files including ones where\nnothing had moved, and was reverted whole.\n\n355 server tests, ./check.sh green.","parents":["4c424b5c59dda2ce62442ba8c03bc8a191edaf8c"],"add":366,"del":340,"cadd":366,"cdel":340,"files":37},{"repo":"hexa","hash":"ff01bd3d530ea72b30ed1e212bc9e97a4b9aee5f","ts":1786118451,"wall":"2026-08-07T12:00","msg":"refactor: the rules stop living behind a socket","body":"net/server.py was 567 lines with fan-out 17, the highest in the server, because\nparsing a message, checking who was asking, and deciding what a claw can do all\nhappened in the same function. It is 417 now and no longer appears at the top of\nthe coupling table at all; the verbs are in world/orders.py, callable from a\nhandler, a tool, or a test with nothing stubbed.\n\nTWO PIECES OF EVIDENCE THAT IT WAS WRONG, both already in the repository:\n\nThe cancel test constructed `Shard.__new__(Shard)` with a stubbed send in order\nto reach a verb. It calls the verb now. No test builds a fake shard.\n\nAnd tools/strip_gear.py and tools/immortal.py edited the JSON snapshot by hand —\nreaching into world[\"pawns\"][id][\"gear\"] and writing it back — because there was\nnothing else to call. So the rule about what a body may carry existed twice, in\nPython and in dict-poking, and only one copy had tests. Both tools now load the\nworld through the shard's own loader, call `gear.strip` and\n`mortality.set_immortal`, and save through the shard's own saver.\n\nRuff removed nineteen imports from the transport once the verbs left, which is\nthe coupling dissolving rather than a tidy-up.\n\nAuthorisation stays in transport deliberately: who is asking is a fact about the\nconnection, not about the world. Verbs take already-resolved pawns and return a\nLIST of reasons they could not comply — not exceptions, because one order\ncommonly goes to four bodies and three of them manage it.\n\nAND THE TOOLS HAD NO COVERAGE AT ALL, which is how SNAPSHOT_PATH moving from\nconfig to persist in the last commit broke both of them while ruff reported all\nchecks passed and 355 tests went green. A lint pass does not resolve symbols\nacross modules and an unimported module cannot fail. tests/test_tools.py now\nimports every tool — the cheapest possible guard, and it would have caught it.\n\n363 server tests, zero import cycles, ./check.sh green.","parents":["312c9b097845661ae12b0040b9db80363cad5533"],"add":512,"del":363,"cadd":512,"cdel":363,"files":9},{"repo":"hexa","hash":"c9aa86a0d13c8fc8d3f539e11cc52e20f6d70b73","ts":1786119708,"wall":"2026-08-07T12:21","msg":"refactor: guard the body against accretion instead of renaming its fields","body":"Pass 3 was to group Pawn's thirty fields into pawn.life, pawn.meta and\npawn.work. I measured it before starting and declined: 165 references across 18\nfiles, and THE DEPENDENCY GRAPH IDENTICAL BEFORE AND AFTER. Nine modules import\nPawn; renaming its attributes changes none of them. That is organisation, not\ndecoupling, and it does not prevent the accretion it was meant to prevent — it\nonly tidies it as it happens.\n\nThe risk it was aimed at is real. The metabolism plan alone adds a crop, banked\nurate, frass, gut flora, a fat-body endosymbiont and a caste: six more fields on\none dataclass, each written by a different system, and the thing stops being a\nbody and becomes a bag that every module reaches into.\n\nTHE FIX THAT WORKS WAS ALREADY IN THE CODEBASE. state.genomes, state.deposits,\nstate.piles, state.surveys and state._phenotypes are side tables keyed by pawn\nid and owned by the system that cares. A system holding its own state that way\ndoes not import Pawn at all — a real edge removed, rather than a name moved.\n\nSo this pass ships the two things that hold that line, for a fraction of the\ndiff:\n\n- tests/test_pawn_shape.py caps Pawn's field count and fires at the moment\n  somebody is about to add the thirty-first, with the reasoning in the failure\n  message rather than in a commit nobody will find. It also asserts that no\n  field on a body is named after a SYSTEM — `pawn.metabolism` would mean the\n  body had started carrying a module's luggage.\n- The convention is written into WorldState's own docstring, which is where\n  Phase 3 will hit it.\n\nAn honest note on process: the plan for this pass was approved and I did not\nfollow it. Measuring first is the reason, and the measurement is in the plan\nfile beside the original so the decision can be argued with later.\n\n366 server tests, ./check.sh green.","parents":["ff01bd3d530ea72b30ed1e212bc9e97a4b9aee5f"],"add":80,"del":0,"cadd":80,"cdel":0,"files":2},{"repo":"hexa","hash":"bdcd1e1d3c93249fee0150ed89eeb3291750537f","ts":1786125959,"wall":"2026-08-07T14:05","msg":"fix: wire Kleiber into the game it was only ever described in","body":"I reported that a 70 kg body \"now costs 6,273 kJ/day\" and that big bodies are\ncheaper per kilogram. Both figures came from units.daily_kj, and NOTHING CALLED\nIT. The tick loop drained a flat rate that ignored the body entirely, so body\nmass had no effect on food or water at all. The law was true of a function, had\ntests beside it, and was absent from the simulation. That is a false report as\nmuch as a defect, and it is the first thing fixed here.\n\nFOOD AND WATER ARE ABSOLUTE NOW. pawn.food_kj and pawn.water_l hold kilojoules\nand litres; capacity and drain come from the body's own metabolic rate, which\nfollows mass^0.75. Days were the first model and hid exactly the thing that\nmatters — a day of reserve is a day for any body, so size could never show.\nDays remain what the PLAYER sees, computed at the wire, because \"half a day of\nwater\" is an instruction and \"412 kJ\" is not.\n\nTHE RESOURCE TABLE STOPPED LYING ABOUT ITS UNITS. `nutrition` and `moisture`\nwere quoted as \"a share of a reference body's daily need\" — the exact ratio\nwearing the coat of a measurement that units.py was written to abolish, left\nsitting in the table beside it. They are kj_per_kg and water_l_per_kg now, read\noff a food table: lean flesh 6,000, pine kernels 20,000 because they are mostly\nfat, a spring green 1,400, sphagnum 200. A unit has a mass, so per-unit is a\nmultiplication rather than a fudge.\n\nCellulose is the interesting entry. Bast is 17,000 kJ/kg gross and almost none\nof it is reachable without gut flora, so fibre is quoted at what a body can\nactually get. Phase 4 is what raises it.\n\nTwo assertions I wrote were sloppy and the model was right: three units of\nsphagnum is nine kilograms of wet moss, and four units of azolla carries 3.8 L\nof water into a body that holds 1.5. Wet food out-supplies the gut that has to\nhold it, which is worth knowing and is now a comment.\n\nTHE CYCLE CHECK IS IN THE GATE. tools/modularity.py was built so the zero-cycles\nproperty would be measured instead of remembered, and then it was only run when\nI remembered. check.sh runs it.\n\nORDERS SPLIT BEFORE IT BECAME THE NEXT CONFIG.PY. Feeding went to metabolism,\nworking the ground to work, and orders keeps motion — go, stop, run. A verb that\nIS the logic belongs with the logic; one file accumulating a verb per mechanic\nwas the same shape I had just finished dismantling, one layer down.\n\nAnd the Pawn field ceiling now points at a paved path: state.Table is a side\ntable that persists itself, so adding one costs a line rather than a pair of\nhand-written serialisers. A guard that nudges toward work nobody has made easy\nis a guard people step over.\n\n368 server tests, 10 client suites, zero import cycles, ./check.sh green.","parents":["c9aa86a0d13c8fc8d3f539e11cc52e20f6d70b73"],"add":438,"del":290,"cadd":438,"cdel":290,"files":11},{"repo":"hexa","hash":"cd86df6459af79f0725887c92bf4c3634fed75f9","ts":1786127164,"wall":"2026-08-07T14:26","msg":"fix: the shard would not start, and every test was green","body":"`main.py` read `config.SNAPSHOT_PATH`. That constant moved to `persist` two\ncommits ago, and the tool that moved it only rewrote `from world.config import\nX` — an ATTRIBUTE access is invisible to it. So the entry point broke, ruff\nreported all checks passed, 368 tests passed, and the game could not boot. Three\nmore in net/server.py were broken the same way and never reached, because\nstartup died first.\n\nThis is the third time the same shape has bitten: a symbol moves, and the thing\nthat would have noticed is not run. The tools were caught by importing them. The\nentry point was not, because IMPORTING A MODULE DOES NOT RUN ITS FUNCTIONS —\n`config.SNAPSHOT_PATH` sat in an argparse default, evaluated when main() builds\nits parser, which no test ever did.\n\nTwo guards, and the second is the one that matters:\n\n- every first-party module is imported by a test — main, transport, systems,\n  tools. Cheap, and covers the class rather than the instance.\n- and the entry point is RUN, with --help, which constructs the parser and so\n  evaluates every default before exiting. Verified by reintroducing the exact\n  break: the import guard stayed green and this one failed.\n\nThe shard is back up on the live world, and Kleiber is visible in it: Tapia\nholds 2.09 L and 52,797 kJ where its smaller squadmates hold 1.13 L and 28,634.\nA bigger body carries more, spends more, and is cheaper to run per kilogram —\nwhich is what the last commit claimed and what, until now, nothing in the\nrunning game did.\n\n369 server tests, ./check.sh green.","parents":["bdcd1e1d3c93249fee0150ed89eeb3291750537f"],"add":69,"del":6,"cadd":69,"cdel":6,"files":3},{"repo":"hexa","hash":"99214adb56501f4de1bd418bcfed5898c6fef901","ts":1786131442,"wall":"2026-08-07T15:37","msg":"feat: bodies that make their own light","body":"The promised bioluminescent caste, and it turned out to be mostly wiring. The\nentire photometric pipeline survived the gear removal with nothing left feeding\nit: EffectiveStats carries lumens, beam and mount; light.py converts lumens to a\nuseful radius through the real solid-angle maths; the wire sends a light block;\nthe client builds a PointLight or a SpotLight with a flame and a halo. All of it\nwas reachable only by CARRYING a lamp, and nothing here has a hand.\n\nSo `glow` joins the genome and BodyPlan, expressed in lumens, and a body that\nhas it lights its own ground.\n\nBEAM ZERO, NOT 360, and that is the whole reason this needed no new rendering.\nThe photometry already reads a zero beam as lumens spread over the entire sphere\n— `lumens / 4pi`, which is exactly what an organ throwing light in every\ndirection is — and the client already reads a zero beam as a point source rather\nthan a cone. Sending 360 would have built a SpotLight with a 180-degree half\nangle, which three.js clamps. The two ends already agreed; they just had to be\nasked the same question.\n\nRanked against a carried lamp by REACH, not by being an organ. That is the rule\ngear.py already uses to choose between two lamps — whichever lights the most\nground wins, because that is what a light is for — and it means a humanoid with\na good headlamp still out-throws a dim glow.\n\nThe colour is foxfire green. Most bioluminescence on Earth is blue-green because\nthat carries through water; a fungoid world glows the colour of rotting wood,\nand it is the same phosphorus Hennig Brand boiled out of urine in 1669 and named\nthe light-bearer — so a hive that banks its own nitrogen can afford to burn a\nlittle of it as light.\n\nAND A GENE BENCH, because adding a locus deliberately cannot move a genome that\nwas already written down. `express` reads a missing allele as the locus default,\nwhich is the property that keeps heredity honest and also leaves no way to switch\na new trait on for a body already standing. tools/gene.py writes an ALLELE, not a\nphenotype: it picks a codon expressing the wanted value, so the change is\nheritable, visible in genomes.json, and expresses through the same path every\nother body uses. Worth having well beyond glow — xeric when a lineage has to\ncross dry country, instars when one has to outlive the others, caste when there\nis caste.\n\nTwo tests broke and both were the feature working: a fixture body happened to\nglow. Fixing them exposed that I had made the organ outrank a carried lamp for\nno reason, which is where the reach rule came from. The dark-body fixture\nsilences the locus by METHYLATION — the mechanism the genome already had for\nforcing a locus to its default, and the same one the honeybee result runs on.\n\nThe four founders are lit: glow=AGA, 60 lm, about 15 m of ground each.\n\n370 server tests, 10 client suites, ./check.sh green.","parents":["cd86df6459af79f0725887c92bf4c3634fed75f9"],"add":299,"del":6,"cadd":253,"cdel":6,"files":7},{"repo":"hexa","hash":"de9259c7032e1fcc35c5860cb2ce6948e0b7ca8b","ts":1786133156,"wall":"2026-08-07T16:05","msg":"fix: the glow is an organ on the animal, not a ball in front of it","body":"The first pass reused the torch renderer, which hangs a single emissive sphere\nat a fixed height in front of the pawn. For a carried lamp that is exactly\nright; for a body that makes its own light it read as a floating ball, because\nthat is precisely what it was.\n\nAn organ belongs ON the animal, so the body now says where its organs are.\n`ArthropodBody` keeps the head and abdomen-tip positions off its own segment\nlayout — not guessed at a height — and reports the radius from the segment the\norgan sits on, so a big animal glows in proportion. Two emitters, at either end,\nthe way a firefly keeps its lantern at the tail.\n\nThey are parented to `body.root` rather than to the pawn's group, which means\nthey inherit every bit of the animal's motion for free: the gait, the turning,\nthe bob. A thing welded to the group would have slid around on top of a body\nthat was walking underneath it.\n\n`Body` gained an optional `glowAt` — optional because a humanoid CARRIES lamps\nand does not grow them, and the interface should say which kind of thing it is\ndescribing rather than making every body pretend it might glow.\n\nOne ownership mistake caught on the way: I had the organ builder call\n`setLampLit(actor, true)` directly, which fights the camera's light budget —\na frame spends `MAX_LIVE_LIGHTS` on the nearest bearers and turns the rest off.\nThe organs are drawn regardless and only the light is budgeted, which is the\nbetter behaviour anyway: a distant hive is a line of green sparks in the dark\nlong before any of it is close enough to cast.\n\n370 server tests, 10 client suites, ./check.sh green.","parents":["99214adb56501f4de1bd418bcfed5898c6fef901"],"add":96,"del":4,"cadd":96,"cdel":4,"files":3},{"repo":"hexa","hash":"73f5c1a07760ad34e8d784892371b8c70dd75423","ts":1786134024,"wall":"2026-08-07T16:20","msg":"fix: the body glows. Nothing hangs off it.","body":"Two wrong attempts, same mistake both times. First the torch renderer's single\nemissive sphere hung in front of the pawn; then a pair of them parented at the\nhead and abdomen tip. The second was anatomically defensible — that is where a\nfirefly keeps its lantern — and it still looked like the pawn was escorting\nballoons, because AN EMITTER YOU CAN POINT AT IS A LAMP however it is parented.\n\nThe cuticle emits. `MeshLambertMaterial.emissive` adds light that owes nothing\nto any lamp in the scene, so a glowing body reads as lit from within at any hour\nand in any shadow — which is what bioluminescence is. Every segment and every\nlimb already shares one material per body, so the whole animal comes up at once\nfor the cost of two numbers and no extra geometry, no extra draw call, and\nnothing to attach, track, or dispose.\n\n`Body` now declares `setGlow?()` — a capability rather than a set of fittings.\nThe previous shape had the interface publishing `glowAt` and `glowRadius`, which\nis the body telling the renderer where to bolt things on. Asking the body to\nlight itself is the same information without the assembly instructions.\n\nEmission is deliberately separate from the photometry: lumens decide what the\nGROUND sees and are already derived from the genome, while GLOW_EMISSION decides\nwhat the ANIMAL looks like. Tying them would make the brightest allele a white\nsilhouette.\n\n370 server tests, 10 client suites, ./check.sh green.","parents":["de9259c7032e1fcc35c5860cb2ce6948e0b7ca8b"],"add":37,"del":91,"cadd":37,"cdel":91,"files":3},{"repo":"hexa","hash":"f113e451e5c51356483fcae7c167c928e94d641e","ts":1786134621,"wall":"2026-08-07T16:30","msg":"feat: turn the glow up, and give it a dial","body":"Three times too dim, and no way to find the right number without editing a\nconstant and rebuilding.\n\nBRIGHTER, AND SCALED BY THE ALLELE. Emission was a flat 0.85 for every glowing\nbody, so the 25 lm gene and the 140 lm gene looked identical — the genome was\ndoing work the eye could not see. It is now quoted against a reference allele,\nso a brighter gene reads brighter, and the default is 2.6.\n\nTHE DIAL: `[` dims, `]` brightens, multiplicative because brightness is read\nlogarithmically and a fixed step is coarse at the bottom and imperceptible at\nthe top. It re-lights every glowing body immediately and prints the value, so a\nlook found by feel can be written back into the constant it came from. That is\nPraxis axiom 4 — dial it in rather than guess, test, guess — and the printed\nnumber is what keeps the file the truth rather than the dial.\n\nEmission stays deliberately separate from the photometry. The lumens on the wire\ndecide what the GROUND sees and come from the genome; this decides what the\nANIMAL looks like. They are different questions — a firefly is blinding to look\nat and lights almost nothing — and welding them would mean no body could read\nbright without also flooding the terrain.\n\n370 server tests, 10 client suites, ./check.sh green.","parents":["73f5c1a07760ad34e8d784892371b8c70dd75423"],"add":56,"del":6,"cadd":56,"cdel":6,"files":2},{"repo":"hexa","hash":"8fdf0d6a53ce698bcee130b8745d70c2fef6a5d4","ts":1786139960,"wall":"2026-08-07T17:59","msg":"feat: the glow dial turns what is selected, not everything","body":"`[` and `]` moved one number that every glowing body read, so brightening one\nscout washed out the whole squad standing behind it. Emission is per pawn now,\nand the dial only reaches the selection.\n\nAnything never dialled sits at the default, and the default is still quoted\nagainst the reference allele — so a brighter gene opens brighter rather than\nevery body starting identical and only diverging once somebody touches it.\n\nWith nothing selected the keys say so instead of feeling dead, and a selection\nof bodies that do not glow says that instead. A key that silently does nothing\nis indistinguishable from a key that is broken, which is the same\nno-hidden-state argument as the refusals.\n\nThis is a LOOK knob and lives only in the client — it is not on the wire, not in\nthe snapshot, and gone at reload. What a body actually emits into the world is\nthe `glow` locus, and that is changed with tools/gene.py, which writes an allele\nand is heritable. Worth keeping the two apart: one is how bright it looks to\nyou, the other is how much light there is.\n\n370 server tests, 10 client suites, ./check.sh green.","parents":["f113e451e5c51356483fcae7c167c928e94d641e"],"add":49,"del":30,"cadd":49,"cdel":30,"files":2},{"repo":"hexa","hash":"259de08b63866ee307ab734603d97c98ee4e51fe","ts":1786143203,"wall":"2026-08-07T18:53","msg":"docs: session handoff — the board, the canon, and the traps","body":"Thirty commits in a day and two machine crashes, so this is written to be read\ncold by a session that remembers none of it.\n\nWhat it carries that the code cannot:\n\nTHE CANON. Rulings that are not derivable from any file — the hive grows castes\nwhile humanoids craft and BOTH stay; weapons and tools are grown rather than\nheld; a pawn is born carrying nothing; repletes are people and there are two\nkinds; storage is built from mud and fibre; excreta are the chemical industry;\nsight is free and study is earned; a closed world has no delete key.\n\nTHE STATE OF THE LIVE WORLD, including the thing a fresh session would otherwise\nfind the hard way: all four founders sit at 0.00 L and 0 kJ, alive only because\nimmortality is raised on them. Lowering that flag kills the squad. Nothing feeds\nthem yet.\n\nTHE THREE TRAPS that have actually bitten, each with the guard that now catches\nit: a pipeline's exit status is the last command's, and it put a red suite on\nmaster; a default is not a fact, and `born_tick = 0` would have reaped every\nfounder; importing a module does not run its functions, and the shard would not\nstart while 372 tests were green.\n\nTHE BOARD, ordered simplest to hardest, with what each item unblocks — and the\nnote that moulting is the highest-leverage thing on it and cheaper than its\nposition suggests, because the timer already exists and does nothing.\n\nAND THE OPEN DECISION. The operator wants every organism to be a pawn. The\narithmetic says 1.57 M cells at 40-60 plants each is about 70 million organisms\nagainst a budget of 10-50k, so the question is whether a clonal stand counts as\none organism — which is what bracken, lichen and azolla actually are — or whether\nindividuals are wanted with a simulated radius. Everything in L2 waits on that\nanswer, and it is written down rather than left in a chat log.\n\nAlso parks the gene-editing plan under a semantic name, since the operator set it\naside and the design should not rot in a file called swirling-herding-nest.","parents":["8fdf0d6a53ce698bcee130b8745d70c2fef6a5d4"],"add":223,"del":455,"cadd":223,"cdel":455,"files":1},{"repo":"azura-website","hash":"5dfb627c01166fe7545ad018b6a97c40ac85850a","ts":1786414401,"wall":"2026-08-10T22:13","msg":"docs: guest-facing intro copy for the Azura ecotourism site","body":"","parents":[],"add":7,"del":0,"cadd":7,"cdel":0,"files":1},{"repo":"operations","hash":"cb11bab6288f58ef905a4ba17effa18072024549","ts":1786414881,"wall":"2026-08-10T22:21","msg":"docs: register azura-website in the atlas","body":"","parents":["b14c451d7fc2d46d6d0877f2da06e2625e515940"],"add":2,"del":0,"cadd":1,"cdel":0,"files":2},{"repo":"azura-website","hash":"29b242954d53ffa8d9627233ba986ede0430bea3","ts":1786420532,"wall":"2026-08-10T23:55","msg":"feat: sky-engine mockup — live sky, scroll-to-tonight, moon, weather hooks","body":"Design doc + working mockup of the approved concept: sun-altitude-driven\nsky gradient (6 keyframes), scroll scrubs time from now to tonight's darkest\npoint, star field with twinkle and Milky Way, phased moon disc, horizon\nsilhouettes with hour-keyed fauna, Tonight-at-Azura card, weather.json hook.\nSolar math verified against USNO (sunset within 1 min).","parents":["5dfb627c01166fe7545ad018b6a97c40ac85850a"],"add":885,"del":0,"cadd":885,"cdel":0,"files":4},{"repo":"azura-website","hash":"c62ffbf7699bc6c31af69ea2c554a37e99ddd052","ts":1786423115,"wall":"2026-08-11T00:38","msg":"feat: Book a stay section — platform cards for Hipcamp, Airbnb, The Dyrt","body":"Pending state until listings go live; set href and drop class=pending to\nactivate a card. Direct booking on azura.camp noted as coming.","parents":["29b242954d53ffa8d9627233ba986ede0430bea3"],"add":91,"del":0,"cadd":91,"cdel":0,"files":2},{"repo":"operations","hash":"8ee55188ae3680b0e7a611688c4079a182f46625","ts":1786456118,"wall":"2026-08-11T09:48","msg":"docs: research — campsite listing platform inventory for Azura","body":"","parents":["cb11bab6288f58ef905a4ba17effa18072024549"],"add":95,"del":0,"cadd":95,"cdel":0,"files":1},{"repo":"operations","hash":"dc56258eaaaddeeca7917c926c626d773b91ee1b","ts":1786457990,"wall":"2026-08-11T10:19","msg":"docs: platform research — existing Hipcamp history, free-stay networks excluded, listing info marked outdated","body":"","parents":["8ee55188ae3680b0e7a611688c4079a182f46625"],"add":21,"del":15,"cadd":21,"cdel":15,"files":1},{"repo":"azura-website","hash":"8cfe1027e21dc03c444c05cbe4224bb71bbf86fd","ts":1786458899,"wall":"2026-08-11T10:34","msg":"feat: researched twilight palette — banded dramatic dusk/dawn (10 keyframes x 5 stops)","body":"Colors keyed to real atmospheric phenomena: twilight arch, purple light\n(peak -4 deg), Belt-of-Venus rose, blue hour, per atoptics.co.uk et al.\nFull research in design/twilight-palette.md. Adds ?alt=<deg> inspection\nparam; theme flips at -3 deg for contrast over civil-dusk purples.","parents":["c62ffbf7699bc6c31af69ea2c554a37e99ddd052"],"add":119,"del":24,"cadd":119,"cdel":24,"files":3},{"repo":"azura-website","hash":"07d1f436ad82a924b64cf007b23bd7f18c8f7a89","ts":1786459459,"wall":"2026-08-11T10:44","msg":"refactor: remove fauna silhouettes; twilight palette approved","body":"Fauna read as twee — low-poly animal redesign planned as its own\nresearch/design pass. Hour-keyed data-phase mechanism retained. Sagebrush\nfringe and range silhouette stay.","parents":["8cfe1027e21dc03c444c05cbe4224bb71bbf86fd"],"add":11,"del":33,"cadd":11,"cdel":33,"files":3},{"repo":"azura-website","hash":"bac1cf98acaa4ed96c2f6ab0bff00d3b8abe8e86","ts":1786459840,"wall":"2026-08-11T10:50","msg":"refactor: remove sagebrush flora from horizon — clean range + ground only","body":"","parents":["07d1f436ad82a924b64cf007b23bd7f18c8f7a89"],"add":7,"del":13,"cadd":7,"cdel":13,"files":2},{"repo":"azura-website","hash":"546162387a761c7c9b9c51efd7907c9dcaac8cde","ts":1786462032,"wall":"2026-08-11T11:27","msg":"feat: copy lives in content/*.md — runtime markdown-lite renderer","body":"One file per section (hero, sky, quote, visit); page fetches and renders\nat load; everything escaped so copy files cannot break the page. Kills the\nintro.md/index.html duplication (intro.md superseded and removed). README\ndocuments the no-tooling editing workflow incl. Forgejo web editor.","parents":["bac1cf98acaa4ed96c2f6ab0bff00d3b8abe8e86"],"add":107,"del":15,"cadd":107,"cdel":9,"files":8},{"repo":"azura-website","hash":"b27af85962dabe6b4399c5faf821109be918df32","ts":1786462315,"wall":"2026-08-11T11:31","msg":"fix: restore purpose paragraph — pull quote gets its full context","body":"","parents":["546162387a761c7c9b9c51efd7907c9dcaac8cde"],"add":2,"del":0,"cadd":2,"cdel":0,"files":1},{"repo":"azura-website","hash":"d17e4f27091aad29a510b6b48c1a4667c3289d22","ts":1786471084,"wall":"2026-08-11T13:58","msg":"feat: gallery — 27 photos recovered from Hipcamp listing","body":"The Land section: lazy-loaded thumb grid + dialog lightbox with full-size\nimages. Photos recovered via Wayback snapshot of the 2021 listing page ->\nHipcamp Cloudinary CDN (originals lost). Three withheld: guest faces (2),\nanimal remains (1). manifest.json drives the grid; README documents adding\nphotos.","parents":["b27af85962dabe6b4399c5faf821109be918df32"],"add":218,"del":2,"cadd":133,"cdel":2,"files":60},{"repo":"azura-website","hash":"425f04a166e9fc21fec15dfd943aad16775ed4a0","ts":1786474059,"wall":"2026-08-11T14:47","msg":"feat: filmstrip gallery — center-focused coverflow replaces grid","body":"Native CSS scroll-snap does the physics; JS scales items by distance from\ncenter. Wheel flips one frame, arrows/keyboard advance, click centers or\nopens lightbox, counter shows position. Full-bleed strip, starts on photo 2\nso both edges peek. ?eager=1 debug param disables lazy-loading.","parents":["d17e4f27091aad29a510b6b48c1a4667c3289d22"],"add":151,"del":37,"cadd":151,"cdel":37,"files":3},{"repo":"azura-website","hash":"2c50e21dc99422378302b60cd259af477cf5ac63","ts":1786474395,"wall":"2026-08-11T14:53","msg":"style: bare arrow glyphs on the filmstrip — orbs removed","body":"","parents":["425f04a166e9fc21fec15dfd943aad16775ed4a0"],"add":8,"del":8,"cadd":8,"cdel":8,"files":1},{"repo":"azura-website","hash":"6ad0f12c871cc9f97f200653c9d8da2f541fe800","ts":1786474673,"wall":"2026-08-11T14:57","msg":"style: center the Azura masthead","body":"","parents":["2c50e21dc99422378302b60cd259af477cf5ac63"],"add":2,"del":0,"cadd":2,"cdel":0,"files":1},{"repo":"azura-website","hash":"c83eb79a50cb5c894661f48b2c0a03a53c931ffa","ts":1786476358,"wall":"2026-08-11T15:25","msg":"feat: Expedition Mark masthead + self-hosted Fraunces","body":"Tracked gold eyebrow over hairline, wide-tracked uppercase AZURA, italic\ndescriptor. Fraunces variable (regular+italic woff2, 149KB, OFL) self-\nhosted, no CDN — the open-source Canela-class serif. Site-wide serif var\nnow resolves to Fraunces.","parents":["6ad0f12c871cc9f97f200653c9d8da2f541fe800"],"add":69,"del":13,"cadd":69,"cdel":13,"files":5},{"repo":"azura-terraforming","hash":"9b26f18f1b7c7c052b2ed9be8ec7c1f30eb926dc","ts":1786500564,"wall":"2026-08-11T22:09","msg":"docs: outdoor shower build spec + shopping list (Camplux BW158 kit)","body":"","parents":["fe92d62b7d8a0bcc0064b3b81ea03c81669f0ef7"],"add":88,"del":0,"cadd":88,"cdel":0,"files":1},{"repo":"azura-terraforming","hash":"490fe5b9d8d7ebe9c329ddc91ea7acd8858688a1","ts":1786500889,"wall":"2026-08-11T22:14","msg":"docs: add tool checklist to shower build spec","body":"","parents":["9b26f18f1b7c7c052b2ed9be8ec7c1f30eb926dc"],"add":25,"del":3,"cadd":25,"cdel":3,"files":1},{"repo":"azura-website","hash":"eee1469c1696d9d95edd17f8daa7ce98d62d555d","ts":1786544555,"wall":"2026-08-12T10:22","msg":"docs: calendar-sync design — verified platform iCal support + feed rules","body":"","parents":["c83eb79a50cb5c894661f48b2c0a03a53c931ffa"],"add":75,"del":0,"cadd":75,"cdel":0,"files":1},{"repo":"operations","hash":"02609d8fe706dc833fcda02f34bd31e22cb5a006","ts":1786545448,"wall":"2026-08-12T10:37","msg":"docs: LandTrust deep-dive — insurance included, no iCal by design (hunting-lease lineage)","body":"","parents":["dc56258eaaaddeeca7917c926c626d773b91ee1b"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"operations","hash":"46cf9c50be163f9a7905d9463064a3a9661a3313","ts":1786545908,"wall":"2026-08-12T10:45","msg":"docs: LandTrust excluded — hunter audience conflicts with wildlife mission","body":"","parents":["02609d8fe706dc833fcda02f34bd31e22cb5a006"],"add":6,"del":4,"cadd":6,"cdel":4,"files":1},{"repo":"azura-website","hash":"ace1a37fd8e6549a5a41388225881243822e905b","ts":1786545912,"wall":"2026-08-12T10:45","msg":"docs: drop LandTrust from calendar sync — all remaining channels iCal-capable","body":"","parents":["eee1469c1696d9d95edd17f8daa7ce98d62d555d"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"azura-website","hash":"35e1b623f06bd7ffc407fcc1a5ed2e3ee358716f","ts":1786548140,"wall":"2026-08-12T11:22","msg":"feat: iCal feed generator + availability merge (test-first, 24 tests)","body":"bookings/blocks.txt is the operator-editable source of truth. make_ics.py\nemits the RFC 5545 outbound feed (deterministic UIDs/DTSTAMP, checkout-\nexclusive DTEND, no label leakage). merge_availability.py polls platform\nfeeds (failure-tolerant, injected fetcher for tests) and unions ranges\ninto availability.json for the site calendar. Stdlib only.","parents":["ace1a37fd8e6549a5a41388225881243822e905b"],"add":449,"del":0,"cadd":398,"cdel":0,"files":11},{"repo":"azura-website","hash":"bb939af3e742f5001db540fff1a43e6b204e1839","ts":1786548215,"wall":"2026-08-12T11:23","msg":"chore: gitignore Python bytecode, untrack pycache","body":"","parents":["35e1b623f06bd7ffc407fcc1a5ed2e3ee358716f"],"add":2,"del":0,"cadd":0,"cdel":0,"files":5},{"repo":"azura-website","hash":"86bbf80c7ac30c070c3bc01f1696e54c42a8f3e0","ts":1786550627,"wall":"2026-08-12T12:03","msg":"feat: availability calendar — 3-month moon-phase grid in Book section","body":"drawMoonShape factored out of the sky moon (pixel-regression verified);\neach day cell carries its true moon phase, busy dates dim from\navailability.json, today ringed, Pacific-time day boundaries. Verified by\nDOM-stub harness (tools/test_calendar_dom.mjs) after headless screenshots\nproved unreliable for async content. Docs updated.","parents":["bb939af3e742f5001db540fff1a43e6b204e1839"],"add":350,"del":19,"cadd":350,"cdel":19,"files":6},{"repo":"azura-website","hash":"205306eccb76730e51b2e726c5048f3399d5de4d","ts":1786557025,"wall":"2026-08-12T13:50","msg":"feat: 2026 layout refinement — rhythm, nav, containers, WCAG 2.2, structured data","body":"Sections content-height on clamp spacing tokens (page 5173->2695px);\ntwo-tier width (72rem grids / 65ch prose); Sky+Tonight card paired via\ncontainer query; fixed anchor nav mirroring the HUD (stacks below it on\nnarrow screens); skip link + :focus-visible + contrast bumps; theme-color,\nSVG crescent favicon, OG tags + og.jpg, Campground JSON-LD with geo.\nAll tests green; JSON-LD validated.","parents":["86bbf80c7ac30c070c3bc01f1696e54c42a8f3e0"],"add":152,"del":36,"cadd":152,"cdel":36,"files":4},{"repo":"azura-website","hash":"a2a4e7c6222a53a5d08463590140b3be45e27afe","ts":1786557967,"wall":"2026-08-12T14:06","msg":"style: centered spine — columns and headings center, running text stays left","body":"Prose blocks center under the centered masthead (margin-inline auto,\n65ch); section h2s and footer center; pull quote and calendar legend get\ntrue text-centering (display material); sky-pair centers as a unit.\nRunning paragraphs remain left-aligned — centered body text is a\nreadability tax.","parents":["205306eccb76730e51b2e726c5048f3399d5de4d"],"add":15,"del":1,"cadd":15,"cdel":1,"files":1},{"repo":"azura-website","hash":"a1904e1ad8319ebe350535296c2dd647874a7330","ts":1786558924,"wall":"2026-08-12T14:22","msg":"copy: The Sky section — dark-sky pitch in house voice","body":"","parents":["a2a4e7c6222a53a5d08463590140b3be45e27afe"],"add":5,"del":1,"cadd":5,"cdel":1,"files":1},{"repo":"azura-website","hash":"7d3df0b47ce3ba7e1255979eb7b8eedd064d93ec","ts":1786586453,"wall":"2026-08-12T22:00","msg":"feat: Visit section — stay copy, bring list, coords, schematic map, operator directions","body":"Gate + camp coordinates in an instrument block with Google/Apple Maps\nlinks (plain URLs, no embeds); hand-drawn SVG route schematic in site\npalette (I-80 / Exit 261 / NV-306 / power-line towers / gate / camp);\noperator's written directions verbatim in content/directions.md; renderer\nlearns '- ' lists for the bring list. Engine + JSON-LD corrected to true\ncamp pin 40.5224,-116.4989 (operator atlas).","parents":["a1904e1ad8319ebe350535296c2dd647874a7330"],"add":170,"del":5,"cadd":170,"cdel":5,"files":6},{"repo":"azura-website","hash":"c514341b6f68c22610f9439bcd46773d9e660f17","ts":1786587515,"wall":"2026-08-12T22:18","msg":"fix: map corrections per operator — Beowawe midway, tower 1 over gate, drop elevation, water line generous","body":"","parents":["7d3df0b47ce3ba7e1255979eb7b8eedd064d93ec"],"add":13,"del":13,"cadd":13,"cdel":13,"files":2},{"repo":"azura-website","hash":"4c8af4d02befa952a5806abb53230fbc86892c0b","ts":1786598291,"wall":"2026-08-13T01:18","msg":"docs: Hipcamp listing renamed to Azura Abode of Peace — both names in schema","body":"","parents":["c514341b6f68c22610f9439bcd46773d9e660f17"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"azura-website","hash":"8d952f954a4a844e6a80df8e6c365ddca90d5c77","ts":1786729345,"wall":"2026-08-14T13:42","msg":"docs: weather cron cut by operator decision — absent weather.json is the shipping behavior","body":"","parents":["4c8af4d02befa952a5806abb53230fbc86892c0b"],"add":9,"del":9,"cadd":9,"cdel":9,"files":1},{"repo":"wheel-of-the-heavens","hash":"a6ef352a1c1fd791ce7beb210eb15da4d336d3ac","ts":1786730245,"wall":"2026-08-14T13:57","msg":"feat(core): azura_moon example — daily moonrise/set almanac as JSON","body":"Transit-anchored moon_events + phase() over a date range for a fixed\nobserver, one row per local calendar day (mean solar time). Meeus ch. 7\ncalendar conversion, self-tested. Rise/set verified against USNO\nrstt/oneday for Crescent Valley NV (2026-11-01, 2027-03-05) to under\n4 minutes. Built for azura.camp's Tonight card; works for any site.","parents":["da51bac27cb6771e08245c73b4e7c8c23068a332"],"add":206,"del":0,"cadd":206,"cdel":0,"files":2},{"repo":"azura-website","hash":"ea06ea0c8f059059e8c2f06c9433bee58a70cf30","ts":1786732022,"wall":"2026-08-14T14:27","msg":"feat: moonrise/set on the Tonight card — precomputed Cycles ephemeris","body":"moon.json: 730 daily rows (through 2028-08-12) for the camp pin from the\nazura_moon example in wheel-of-the-heavens; USNO-verified to <4 min.\nDeterministic data as a committed static file — no cron, no WASM.\n\nsky.js loads it same-origin like weather.json; card gains Moonrise and\nMoonset rows in Pacific time; illumination prefers the ephemeris row\n(epoch: tonight's solar midnight) with the synodic approximation as\nfallback. DOM test extended to cover the wiring.","parents":["8d952f954a4a844e6a80df8e6c365ddca90d5c77"],"add":829,"del":12,"cadd":93,"cdel":12,"files":6},{"repo":"azura-website","hash":"8844c487f1278f6a69e500969d84473e20d80394","ts":1786732512,"wall":"2026-08-14T14:35","msg":"feat: live weather on the Tonight card — client-side NWS fetch","body":"The browser GETs the LKN 95,121 hourly forecast (keyless, CORS-open) and\ntakes the current hour: temperature + shortForecast to the card, cloud\nfraction from an ordered lookup on the NWS's own condition words — coarse\non purpose, derived from the string on the card so the page can't\ncontradict itself. Failure path unchanged: ideal sky, em-dash. Replaces\nthe cut weather.json cron; reversal recorded in the design doc.","parents":["ea06ea0c8f059059e8c2f06c9433bee58a70cf30"],"add":72,"del":15,"cadd":72,"cdel":15,"files":3},{"repo":"operations","hash":"6e675216b98d125784d243257edb8b6858aa045c","ts":1786734748,"wall":"2026-08-14T15:12","msg":"finance: azura.camp + azura.land registered — ledger entry + 2027 Cloudflare transfer deadline","body":"","parents":["46cf9c50be163f9a7905d9463064a3a9661a3313"],"add":2,"del":0,"cadd":1,"cdel":0,"files":2},{"repo":"operations","hash":"8b2df5894f4c24b5792003fedd580dcc8fee483b","ts":1786734940,"wall":"2026-08-14T15:15","msg":"fix: domain purchase went on personal card, not business","body":"","parents":["6e675216b98d125784d243257edb8b6858aa045c"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"azura-website","hash":"70e217c35f571727f298fcdbe1bf8b8b0abaef4a","ts":1786736887,"wall":"2026-08-14T15:48","msg":"docs: site is live — azura.camp deployed on Hetzner, DNS at Porkbun","body":"","parents":["8844c487f1278f6a69e500969d84473e20d80394"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"azura-website","hash":"9051ad89072e2ba9495dd7d8ae48cce3e6007590","ts":1786737928,"wall":"2026-08-14T16:05","msg":"feat: move iCal feed to unguessable path (feed rule 6) — paste-day for Hipcamp","body":"","parents":["70e217c35f571727f298fcdbe1bf8b8b0abaef4a"],"add":2,"del":2,"cadd":2,"cdel":2,"files":3},{"repo":"azura-website","hash":"94697d9d415395f3a104bb70e11b7df834fddf0a","ts":1786738612,"wall":"2026-08-14T16:16","msg":"feat: Hipcamp two-way calendar link — export URL in feeds.txt (Phase B, Hipcamp)","body":"","parents":["9051ad89072e2ba9495dd7d8ae48cce3e6007590"],"add":11,"del":6,"cadd":7,"cdel":4,"files":3},{"repo":"azura-website","hash":"dcef73ac77fd8c854e76ddf5a8a702244277fb49","ts":1786740287,"wall":"2026-08-14T16:44","msg":"feat: grid shows operator blocks only — all platform feeds pulled (operator ruling)","body":"30 Hipcamp sites broke the one-site inbound model: any single booking\nwould dim the whole grid. Platform bookings live on platforms.","parents":["94697d9d415395f3a104bb70e11b7df834fddf0a"],"add":17,"del":10,"cadd":15,"cdel":6,"files":3},{"repo":"azura-website","hash":"70b9e9a39637fb285d66bc99d2bfc6147689228b","ts":1786740459,"wall":"2026-08-14T16:47","msg":"docs: operator removed the Hipcamp import — zero calendar coupling either direction","body":"","parents":["dcef73ac77fd8c854e76ddf5a8a702244277fb49"],"add":6,"del":5,"cadd":6,"cdel":5,"files":1},{"repo":"azura-website","hash":"3bcf45c3bf25ef692d6eeaafc0344d921baf61eb","ts":1786740713,"wall":"2026-08-14T16:51","msg":"fix: purge example blocks — calendar showed fake unavailability Aug 20-23 + Sep 2-4","body":"","parents":["70b9e9a39637fb285d66bc99d2bfc6147689228b"],"add":2,"del":29,"cadd":0,"cdel":0,"files":3},{"repo":"azura-website","hash":"3458e7ace0f13926c2314b80a9de8ca4186e1286","ts":1786742796,"wall":"2026-08-14T17:26","msg":"block: closed through Aug 22 — opening prep (grinder, IBC cage, shower)","body":"","parents":["3bcf45c3bf25ef692d6eeaafc0344d921baf61eb"],"add":16,"del":2,"cadd":0,"cdel":0,"files":3},{"repo":"operations","hash":"ec78112dd1e74e4e38ec61381d0528d78ce97eaa","ts":1786745610,"wall":"2026-08-14T18:13","msg":"docs: research — azura.camp discoverability, tiered plan (indexing, maps, dark-sky ecology)","body":"","parents":["8b2df5894f4c24b5792003fedd580dcc8fee483b"],"add":94,"del":0,"cadd":94,"cdel":0,"files":1},{"repo":"azura-land","hash":"d01849f81394140e61247cd283fe1e64e40298d0","ts":1786845528,"wall":"2026-08-15T21:58","msg":"feat: azura.land estate site — landing page, journal + diary generators, station stub","body":"Estate face of the property: homestead placeholder (operator's words\npending), research-station copy, camp door to azura.camp. In-house\nstdlib journal generator (markdown subset, RSS, sitemap) and\nPillow-based photo diary generator (thumbs, captions, day notes),\n26 tests, ruff + mypy clean. Generated output gitignored; server\npull cron will rebuild on deploy. Not deployed.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":1216,"del":0,"cadd":1207,"cdel":0,"files":14},{"repo":"operations","hash":"57de7e8ec878ad343b3db56b557bdbee2b03e525","ts":1786845565,"wall":"2026-08-15T21:59","msg":"atlas: register azura-land — estate site repo created (journal + diary + station)","body":"","parents":["ec78112dd1e74e4e38ec61381d0528d78ce97eaa"],"add":2,"del":0,"cadd":1,"cdel":0,"files":2},{"repo":"azura-land","hash":"7445bb00eeefe5f82c1e1f52a92aa62b7a5df250","ts":1786845658,"wall":"2026-08-15T22:00","msg":"docs: session handoff — repo created, built, not deployed","body":"","parents":["d01849f81394140e61247cd283fe1e64e40298d0"],"add":51,"del":0,"cadd":51,"cdel":0,"files":1},{"repo":"azura-land","hash":"474a7814f44385f47e759a2e73435a47229d0934","ts":1786891638,"wall":"2026-08-16T10:47","msg":"copy: refer to the playa as the playa — Hispanic names favored over old English","body":"","parents":["7445bb00eeefe5f82c1e1f52a92aa62b7a5df250"],"add":6,"del":6,"cadd":6,"cdel":6,"files":2},{"repo":"azura-land","hash":"3ecdee7f83d3053ee0ae6a8795133426782641f2","ts":1786891899,"wall":"2026-08-16T10:51","msg":"style: azure ground — Azura is blue","body":"Jet/indigo night register replaced by azure (#0a3a6b → #1565b3\ngradient). Gold accent and playa-dust whites (bone, alkali) stay.\nTheme-color + favicon ground follow.","parents":["474a7814f44385f47e759a2e73435a47229d0934"],"add":16,"del":14,"cadd":16,"cdel":14,"files":4},{"repo":"azura-land","hash":"7c5ac13b645a656a778f93cc9371915130196fe1","ts":1786892073,"wall":"2026-08-16T10:54","msg":"design: palette study — the color wheel from azure, harmonies + measured contrast","body":"","parents":["3ecdee7f83d3053ee0ae6a8795133426782641f2"],"add":163,"del":0,"cadd":163,"cdel":0,"files":1},{"repo":"azura-land","hash":"e1743aa0fd15c75f8373d2feef0a2041054e9dae","ts":1786892286,"wall":"2026-08-16T10:58","msg":"style: rust #a85b38 joins as third accent — edges only","body":"Blockquote + code-block left borders, diary photo hover/focus rings.\n2.9:1 on azure, so surfaces and borders, never text. Palette study\nupdated: rust solid on the wheel, straw stays the reserve.","parents":["7c5ac13b645a656a778f93cc9371915130196fe1"],"add":12,"del":6,"cadd":12,"cdel":6,"files":2},{"repo":"azura-land","hash":"3d42a58d096888a5eeb0344930e699d19c787703","ts":1786892503,"wall":"2026-08-16T11:01","msg":"style: full wheel adopted as named tokens — roles reserved","body":"straw/teal/indigo/sage/rose defined in :root with documented jobs\n(straw reserve accent, teal/indigo depth, sage/rose future station\ndata series). Visible chrome unchanged: azure/gold/bone+alkali/rust.","parents":["e1743aa0fd15c75f8373d2feef0a2041054e9dae"],"add":16,"del":3,"cadd":16,"cdel":3,"files":2},{"repo":"azura-land","hash":"96cfe2e46322f58b1e74f28e9c9cafab713c7316","ts":1786892984,"wall":"2026-08-16T11:09","msg":"copy: homestead section — operator's words in (mechanical fixes flagged for veto)","body":"","parents":["3d42a58d096888a5eeb0344930e699d19c787703"],"add":8,"del":6,"cadd":8,"cdel":6,"files":1},{"repo":"azura-land","hash":"14d97d523140435b91845ff887c0e16fc6e8fad8","ts":1786895012,"wall":"2026-08-16T11:43","msg":"copy: homestead — em-dash out, sentence runs straight per operator","body":"","parents":["96cfe2e46322f58b1e74f28e9c9cafab713c7316"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"symbiont.systems","hash":"e97104f8b497e88712c2e99fe24ab96f44515603","ts":1786895251,"wall":"2026-08-16T11:47","msg":"feat: Azura Camp + Azura Land rings — the two new sites join the orbit","body":"azura.camp (gold #d9973f, r8.5) and azura.land (azure #2b7fd4, r9)\nas outer URL rings with hover preview cards. Oasis of Azura ring\nleft untouched (still points at the Hipcamp listing).","parents":["8b7f2b9a5e3ffd4c28e4b590dc357258192a5797"],"add":28,"del":0,"cadd":28,"cdel":0,"files":1},{"repo":"symbiont.systems","hash":"4e9bb1f36ac574709cef00a2c798ff0911c8c2b1","ts":1786896786,"wall":"2026-08-16T12:13","msg":"feat: retire Oasis of Azura ring — Hipcamp link superseded by Azura Camp ring","body":"","parents":["e97104f8b497e88712c2e99fe24ab96f44515603"],"add":0,"del":18,"cadd":0,"cdel":18,"files":1},{"repo":"symbiont.systems","hash":"2045ecc998c6053ff706a03e9053474e37ec6235","ts":1786896924,"wall":"2026-08-16T12:15","msg":"fix: restore #mc-config island lost from repo — live-only since June 29","body":"The Mission Control live-mirror island existed only in the deployed\nHTML, never in the repo; today's ring deploy dropped it. Rebuilt from\nthe live backup with the ring changes applied (Oasis of Azura out,\nAzura Camp + Azura Land in) and committed so repo = live from now on.","parents":["4e9bb1f36ac574709cef00a2c798ff0911c8c2b1"],"add":1,"del":0,"cadd":1,"cdel":0,"files":1},{"repo":"code-forge","hash":"47aacb538e10ba33a2c92b265408c830c12592c3","ts":1786900864,"wall":"2026-08-16T13:21","msg":"feat: code-forge becomes a real repo — garden repatriated, Organum Operis designed","body":"P0 of the Organum Operis plan: garden.js, puppet.js, home.tmpl, and\nbake-garden-data.sh recovered from the server (previously live-only,\nper lesson-portal-live-drift). Design doc for the instrument that\nsucceeds the garden at git.symbiont.systems; garden retires to an\nemeritus URL per operator ruling.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":4102,"del":0,"cadd":4102,"cdel":0,"files":6},{"repo":"code-forge","hash":"8f278e8476d839e3aecd413d832774334038e84b","ts":1786901882,"wall":"2026-08-16T13:38","msg":"feat: P1 — bake_record.py, the Organum's record baker","body":"Walks every git repo under a root (bare or worktree) → record.json:\nall commits (hash/ts/wall/msg/body/parents/diffstat), 7x24 rhythm\nmatrix from author wall-clock, per-repo blame strata binned by\nquarter, repo language. Incremental cache keyed on full ref\nsignature; deterministic output; tolerant of non-UTF8 history\n(found by the real corpus, regression-tested).\n\nSmoke-baked the real record: 49 repos, 1,589 commits — every count\nverified against git rev-list. 3.48M living lines across 47 blamed\nrepos; first full bake 4m, incremental re-run instant.\n\n12 tests, ruff + mypy clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["47aacb538e10ba33a2c92b265408c830c12592c3"],"add":435,"del":0,"cadd":432,"cdel":0,"files":3},{"repo":"code-forge","hash":"f9df9a536cc0116e30a5d36ebb03893825dbb451","ts":1786902666,"wall":"2026-08-16T13:51","msg":"feat: P2 — the static panes: DAG braid, ledger, churn, rhythm, needle at NOW","body":"organum/: no-framework instrument shell (grid, chromatic-black P2\nground), pure DOM/canvas. model.js is DOM-free and node-tested (7\ntests); panes.js renders DAG lanes (log-magnitude nodes, merge\nrings, month ticks), weekly churn (+gold/−rust), rhythm punchcard,\nand the gold needle. Ledger: 1,589 real DOM rows, weight by diff\nsize. Verified against the real record: lanes/churn/ledger all\nreconcile to 1,589 commits; strata + inspector are P4 placeholders.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["8f278e8476d839e3aecd413d832774334038e84b"],"add":616,"del":0,"cadd":616,"cdel":0,"files":5},{"repo":"code-forge","hash":"93dc74f29d2e8305c641d4b9eebe74f4a7b0102c","ts":1786902974,"wall":"2026-08-16T13:56","msg":"feat: P3 — the needle lives: scrub, lock-step, the Replay","body":"Needle model (pure, node-tested): binary-search needleState,\nwall-clock rhythmUpTo (reconciles exactly with the Python-baked\nmatrix over all 1,589 real commits), index-paced replayT with cubic\neasing — every commit gets an equal share of the sweep, so dormant\nmonths flash and hot weeks stretch. Panes render as-of-needle:\nfuture commits/bins ghost at 10%. Drag-to-scrub on record and churn\ncanvases; ledger scroll-follows by row arithmetic; statline shows\nthe needle date and count while off NOW. Replay: 90 s default,\n?replay=N override, ?replay=0 or prefers-reduced-motion skips,\nclick/key to skip. 12 node tests + 12 py tests green.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["f9df9a536cc0116e30a5d36ebb03893825dbb451"],"add":230,"del":17,"cadd":230,"cdel":17,"files":4},{"repo":"code-forge","hash":"40f2fef46199b36f3832a904a3d338bffdd7327a","ts":1786903647,"wall":"2026-08-16T14:07","msg":"fix: replay died on frame one; record pane label pile-up","body":"Root cause (probe-log evidence from headless Firefox): the first rAF\ntimestamp can precede the performance.now() start mark, sending\nprogress negative — replayT floored to commits[-1] and the thrown\nTypeError killed the animation chain silently. Clamped in both the\ncaller and replayT (regression test added), and errors now surface on\nthe statline instead of dying quiet.\n\nScrunch: 47 repo labels drew at the lanes' left edge, over the data.\nAll time panes now share a 130px gutter (labels live there; axis\nspans the rest; scrub mapping matches). Verified live headless:\nreplay-frame-1 → frame-60 → replay-done at the exact configured\nduration. ?debug keeps the stage probes available.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["93dc74f29d2e8305c641d4b9eebe74f4a7b0102c"],"add":51,"del":16,"cadd":51,"cdel":16,"files":4},{"repo":"code-forge","hash":"0611a3919d523e228e740fb5b33aae423e2e54ab","ts":1786904490,"wall":"2026-08-16T14:21","msg":"feat: replay re-paced — 18 s ease-out, ignition not throat-clearing","body":"90 s ease-in-out spent its first ten seconds nearly motionless —\noperator veto. Now ease-out: the record detonates from genesis and\ndecelerates into NOW. Design doc amended.","parents":["40f2fef46199b36f3832a904a3d338bffdd7327a"],"add":12,"del":5,"cadd":12,"cdel":5,"files":3},{"repo":"code-forge","hash":"1a4d73a858e3306fafa6a72e21f59e19becbb6b4","ts":1786904868,"wall":"2026-08-16T14:27","msg":"feat: P4 — strata wall, inspector, command grammar, URL state","body":"Strata: blame barcode per repo (largest first, log-scaled bars),\nsegments age-ramped umber→gold across the record's quarters; HEAD-\nonly by nature, so needle-independent; /repo filter dims the rest.\nInspector shares the strata slot: click a commit in the record\n(hit-test mirrors renderer geometry — roundtrip-verified on real\ndata) or a ledger row → full message, diffstat, hash, and the\nclick-through to its Forgejo commit page. Command line on '/':\n/repo (prefix-matched), /YYYY-MM[-DD] needle jump, /find text\n(latest match selected), /all clears. URL carries ?repo=&t=&q= —\napplied on load (skips replay), updated on scrub/filter/find.\n17 node tests; headless boot verified with full URL state.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["0611a3919d523e228e740fb5b33aae423e2e54ab"],"add":449,"del":27,"cadd":449,"cdel":27,"files":5},{"repo":"code-forge","hash":"ce484276097b94f031590d250d71a528fc7257e3","ts":1786907518,"wall":"2026-08-16T15:11","msg":"feat: P5 — the nigredo ground","body":"WebGL2 single-pass oil under the instrument: domain-warped fbm (the\nmobile card's ink-in-water fold), four chromatic blacks orbiting the\nhouse aubergine — hue drifts, value stays pinned dark — with the\ncauda pavonis sheen riding a narrow band of the field at 3%, and\ninterleaved-gradient-noise dither against banding. The oil's\nagitation follows local commit density at the needle: it stirs where\nthe record burns, stills where it sleeps. Guards: half-res render,\n30 fps cap, pause when hidden, reduced-motion still frame, ?ground=0\nkill switch, no-WebGL2 → CSS ground. Verified live headless\n(ground-live probe: compile+link+loop clean).\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["1a4d73a858e3306fafa6a72e21f59e19becbb6b4"],"add":208,"del":0,"cadd":208,"cdel":0,"files":3},{"repo":"code-forge","hash":"6e9e258877b34526295e9b6a8a3ec6c453c18f64","ts":1786909112,"wall":"2026-08-16T15:38","msg":"style: the plate — Organum's own engraved grammar (Swiss discipline, no costume)","body":"Rule-work frames replace the dark-dashboard cards: no radii, no glass,\nline not fill — the nigredo breathes through every pane. Labels are\ncartouches cut into the top rule; gold corner ticks register the\nplates; Fraunces (house serif) carries labels, numerals, and the\nengraved wordmark between rule flourishes. The time-rule replaces\nbare gridlines: double rail, week ticks between, months cut through,\nquarters heavier with numerals. Rhythm rebuilt as the Organum's polar\nfigure — 24 hours around (midnight up), seven day-bands out, and at\ncenter the rose: an engraved figure turned from the hourly totals,\nornament computed from the record itself. The needle is a drawn hand\n(bearing eye, hairline shaft, lozenge counterpoise). One ruby on the\nplate: the selected commit. 17 tests; headless boot + ground clean.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["ce484276097b94f031590d250d71a528fc7257e3"],"add":270,"del":72,"cadd":270,"cdel":72,"files":4},{"repo":"code-forge","hash":"e9e2badb21a46ba5a2f88f96f96d21eceee0b740","ts":1786909718,"wall":"2026-08-16T15:48","msg":"style: churn re-engraved — the tide, not the bar chart","body":"Weekly bars replaced by mirrored stepped areas: written mass rises,\nremoved mass hangs, both filled with 45° engraver's hatching and\noutlined in their metal; the future is a ghost outline ahead of the\nneedle. A graduated log scale (100 · 1k · 10k · 100k · 1M) is cut\ninto the gutter with decade ticks in each metal. Weekly steps stay\nhonest — the hatching does the craft.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["6e9e258877b34526295e9b6a8a3ec6c453c18f64"],"add":102,"del":15,"cadd":102,"cdel":15,"files":1},{"repo":"code-forge","hash":"f2aa81dc60481ae71b773b02ea83a89f1ef7683c","ts":1786910121,"wall":"2026-08-16T15:55","msg":"fix: ledger cartouche was clipped — scroll containment moved from pane to list","body":"","parents":["e9e2badb21a46ba5a2f88f96f96d21eceee0b740"],"add":3,"del":2,"cadd":3,"cdel":2,"files":1},{"repo":"code-forge","hash":"4b5e97f9cfc3b344ccb348500121be8d2298812b","ts":1786911546,"wall":"2026-08-16T16:19","msg":"feat: the instrument is named GIT — operator ruling","body":"Programming-native, domain-identical, zero costume. organum/ stays\nas the internal module path (a directory named git/ would be asking\nfor trouble).","parents":["f2aa81dc60481ae71b773b02ea83a89f1ef7683c"],"add":9,"del":7,"cadd":9,"cdel":7,"files":2},{"repo":"code-forge","hash":"3662d7975b7e7267e2a4de9793bd7299c91783bd","ts":1786922528,"wall":"2026-08-16T19:22","msg":"fix: the honesty pass — dedupe forks, binary-clean strata, wall clocks, honest labels","body":"Cross-repo hash dedupe: shared history counts once, in the elder\nrepo (program-x19 proves to be a pure snapshot of margin — zero\ndivergent commits; the record drops from 1,589 to 1,422 unique).\nStrata blames only files git itself considers text (empty-tree\nnumstat) — Ptolemy's PDFs no longer count as anyone's lines; living\ntotal falls 3.48M → 1.52M. All displayed dates/times are the author\nwall clock exactly as git recorded it wherever the operator sat (RI\nEastern, Nevada Pacific) — UTC conversion removed from ledger,\ninspector, statline; rhythm already used wall. Weekly bins align to\nMonday, not the Unix epoch's Thursday. Statline counts repos that\nhold commits. Churn says 'committed', claiming no more than the\ntruth. Cache entries record strata inclusion, so a no-strata bake\ncan no longer poison a strata bake. 16 py + 17 js tests.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["4b5e97f9cfc3b344ccb348500121be8d2298812b"],"add":96,"del":11,"cadd":96,"cdel":11,"files":6},{"repo":"code-forge","hash":"59b8cfc52227bb6e42effec59aae799d6100ed20","ts":1786924334,"wall":"2026-08-16T19:52","msg":"feat: the record's repo names are handles — click filters, ctrl-click opens Forgejo","body":"Gutter names hit-test on their own row math (tested); click toggles\nthe /repo isolation across all panes, ctrl/cmd-click opens the repo\non the forge, the active filter's name renders in gold, and the\ncursor knows the difference between handle and track. Scrubs no\nlonger start from the gutter (a press there used to slam the needle\nto the record's origin).","parents":["3662d7975b7e7267e2a4de9793bd7299c91783bd"],"add":51,"del":5,"cadd":51,"cdel":5,"files":3},{"repo":"code-forge","hash":"2d87bafc565a9c0dcdd5d79d22c2a481773edb8d","ts":1786924591,"wall":"2026-08-16T19:56","msg":"feat: the / palette suggests — recency-ranked repos, months, live find counts","body":"Pure suggestion engine (tested): empty input offers the five most\nrecently worked repos, the latest month, /find, and /all when a\nfilter is active; typed prefixes narrow repos (then substring\nmatches), digits complete months from the record's extent, and\n'/find x' shows its live match count as the hint. Arrow keys move,\nTab completes, Enter runs the selection, click runs a row. Plate\ngrammar: gold-edged selection, italic serif hints.","parents":["59b8cfc52227bb6e42effec59aae799d6100ed20"],"add":177,"del":12,"cadd":177,"cdel":12,"files":4},{"repo":"code-forge","hash":"f2fde13344a3580a82b831d631b180bdf1dc96b2","ts":1786925247,"wall":"2026-08-16T20:07","msg":"feat: P6 — the live tail: the record grows while you watch","body":"live.js polls the forge each minute: one cheap updated-repos search,\ncommits fetched only for repos that changed, arrivals filtered past\nthe record's edge. Pure and tested: apiToCommit transcribes the\nauthor wall clock verbatim (Pacific stays Pacific), mergeLiveCommits\ndedupes by hash and keeps time order. An arrival rebuilds scale,\nlanes, churn and ledger, follows NOW if the needle was resting\nthere, and blooms a gold ring off its node — the one moment the\nplate may flash. Dev cross-origin fails quietly and gives up after\nfour misses; ?live=0 disables. 21 node + 16 py tests.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["2d87bafc565a9c0dcdd5d79d22c2a481773edb8d"],"add":198,"del":1,"cadd":198,"cdel":1,"files":5},{"repo":"azura-land","hash":"c12306333b2d5c27567aec634f47b20ae928220d","ts":1786925304,"wall":"2026-08-16T20:08","msg":"docs: handoff refresh — palette, naming ruling, homestead copy state","body":"","parents":["14d97d523140435b91845ff887c0e16fc6e8fad8"],"add":13,"del":2,"cadd":13,"cdel":2,"files":1},{"repo":"code-forge","hash":"09f789d9e78ebf76f38ab7361415b2f993023d98","ts":1786925304,"wall":"2026-08-16T20:08","msg":"docs: session handoff — P0–P6 complete, deploy awaits order","body":"","parents":["f2fde13344a3580a82b831d631b180bdf1dc96b2"],"add":68,"del":0,"cadd":68,"cdel":0,"files":1},{"repo":"code-forge","hash":"cef2c33116e7e1da00ee59585aa9bdef2a97e44c","ts":1786925668,"wall":"2026-08-16T20:14","msg":"feat: P7 artifacts — GIT home.tmpl (standalone, forge links) + garden emeritus page","body":"home.tmpl is generated from organum/index.html: assets at\n/assets/organum/, record at /record.json (same-origin via Caddy),\nexplore/garden/sign-in links in the title row. The garden's old\ntemplate becomes garden/emeritus.html, served at /garden.","parents":["09f789d9e78ebf76f38ab7361415b2f993023d98"],"add":443,"del":107,"cadd":443,"cdel":107,"files":2},{"repo":"code-forge","hash":"c02076932aae79e6e409fd3dc14edba1a35ac4f6","ts":1786926825,"wall":"2026-08-16T20:33","msg":"feat: year paging — the record becomes a codex, one year per page","body":"The register: 2015–2026 tabs in the title row (Fraunces numerals,\nactive gold, fallow 2022/2024 present but dimmed — a record that\nkeeps its silences is the honest one). Fixed Jan→Dec axis so months\nalign across flips; lanes, churn, ledger, and rhythm scope to the\npage; strata stays whole-history. The needle roams the full record\nand the page turns under it — the Replay now flips eleven years like\nan odometer: one lane in 2015, the fallow years passing as held\nbreaths, then the page turns to 2026 and the braid explodes. Flip by\nclick, ←/→, /2019, or ?y=2019. home.tmpl generation scripted\n(tools/build_home_tmpl.py) so dev page and front door cannot drift.\n22 node + 16 py tests; full replay verified headless over the real\n11-year record.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["cef2c33116e7e1da00ee59585aa9bdef2a97e44c"],"add":269,"del":42,"cadd":269,"cdel":42,"files":6},{"repo":"code-forge","hash":"b0fbb48f4c30b47bfadb4f65a25a2049efdaa8d2","ts":1786931688,"wall":"2026-08-16T21:54","msg":"feat: the nigredo is the loading screen; month labels fixed to UTC","body":"The oil starts on the first frame — full-bleed with the GIT mark\nfloating on it while the record downloads and parses — then the\nplates fade in over it (900ms) and the replay fires. Layering fix\nfrom the mobile card's own lesson: ground on html, body transparent\n(an opaque body paints over a z-index:-1 canvas). record.json now\npreloaded from the head. And the screenshot caught a timezone bug in\nthis of all houses: month labels formatted in browser-local time\nwhile ticks sat at UTC midnights — a Pacific browser read JAN as\nDEC. Labels now format in UTC; tick and name agree.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["c02076932aae79e6e409fd3dc14edba1a35ac4f6"],"add":118,"del":18,"cadd":118,"cdel":18,"files":5},{"repo":"code-forge","hash":"b7560eb8710b467323e5e8c26fbe98104015da07","ts":1786932303,"wall":"2026-08-16T22:05","msg":"fix: the nigredo is the load screen, and nothing else — operator ruling","body":"The oil runs hot (rgb ~41,37,66 at center, framebuffer-verified) from\nthe first frame while the record loads, GIT mark floating on it; when\nthe plates rise it fades out over 1s and the shader stops and the\ncanvas is removed. No oil under the instrument. Asset paths are now\ncontent-versioned (/assets/organum/<build>/) — Forgejo caches assets\nfor six hours, which is why every fix today was invisible to a\nbrowser that had cached the first build.","parents":["b0fbb48f4c30b47bfadb4f65a25a2049efdaa8d2"],"add":56,"del":17,"cadd":55,"cdel":17,"files":6},{"repo":"code-forge","hash":"c9cc251730494b53d30942df82148b1e22710864","ts":1786932607,"wall":"2026-08-16T22:10","msg":"fix: nigredo instant and re-graded — inline shader, black base, glowing veins","body":"The oil waited on the module graph to download; now it's inline in\nthe page and runs the instant the HTML parses. Re-graded per\noperator: the wash of uniform brightening is gone — near-black\nground (center px rgb 10,9,17) with two phase-offset chromatic vein\nsets (violet + umber) folding through it and the peacock sheen only\non the sharpest folds. Contrast, not brightness. Faster clock: a\nload screen lives seconds, the oil must move. ground.js retired;\nindex.html carries the load screen whole.","parents":["b7560eb8710b467323e5e8c26fbe98104015da07"],"add":203,"del":218,"cadd":202,"cdel":217,"files":5},{"repo":"code-forge","hash":"e0cb2eeed040f9a311d5b6fa24a97681accd1f63","ts":1786932875,"wall":"2026-08-16T22:14","msg":"style: the oil goes slick — pitch floor, thin-film iridescence, specular streaks","body":"Ground drops to true pitch (center px rgb 4,3,8); slickness is\ndynamic range. Broad thin-film rainbow banding follows the oil's\nthickness contours; veins sharpen and heat up; tight specular\nstreaks give the wet glint; the peacock saturates the sharpest\nfolds at 2x.","parents":["c9cc251730494b53d30942df82148b1e22710864"],"add":36,"del":24,"cadd":35,"cdel":23,"files":3},{"repo":"code-forge","hash":"b044c466408282b752b0eac0bcc026c74b76041b","ts":1786933055,"wall":"2026-08-16T22:17","msg":"style: the whole slick lights — flow floor, full-field film, filigree","body":"Only one region ignited: every layer was gated by a flow mask that\nsat near zero across most of the field. Flow gets a .35 floor, the\nthin-film rainbow covers the surface, a high-frequency iridescent\nfiligree layer joins the coarse folds, everything else warms.","parents":["e0cb2eeed040f9a311d5b6fa24a97681accd1f63"],"add":36,"del":26,"cadd":35,"cdel":25,"files":3},{"repo":"code-forge","hash":"32a35adc057ac03cad2b1abdc7c0bd078840d2ee","ts":1786933770,"wall":"2026-08-16T22:29","msg":"feat: the instrument is named — La Obra Raudhanica","body":"The Raudhanic Work: the record of the work of Rowan Del Valle De\nAzura y Carminati. Spanish per the house naming doctrine; obra is\nthe living descendant of opus/operis, blood family to Sphaera and\nPraxis Operis. Supersedes the interim GIT. Wordmark and loading\nmark re-set for the full name.","parents":["b044c466408282b752b0eac0bcc026c74b76041b"],"add":30,"del":27,"cadd":29,"cdel":26,"files":4},{"repo":"code-forge","hash":"11e49c53658bc92877579b26398b11d385ad69ac","ts":1786934812,"wall":"2026-08-16T22:46","msg":"feat: smartphone fallback — the Ledger alone","body":"Under 760px the instrument becomes the honest single-pane logbook\n(design §7): wordmark, year register, statline, and the full ledger,\nlive-tailing; a tapped row opens the inspector full-screen. No\nreplay on phones — the logbook, not the cinema. Record, rhythm,\nchurn, strata canvases and the / palette stay desktop. Plus a vw-\nprobe: headless firefox ignores --window-size without --screenshot\n(viewport 1366), which is why the phone path can't be proven\nheadless — real hardware is the oracle.","parents":["32a35adc057ac03cad2b1abdc7c0bd078840d2ee"],"add":88,"del":5,"cadd":87,"cdel":4,"files":4},{"repo":"symbiont.systems","hash":"ed68bf57d0d57b46c14b29b071ec431ddcacad19","ts":1786935593,"wall":"2026-08-16T22:59","msg":"fix: rings answer the finger — fresh tap raycast, fat hit-tori, near-miss forgiveness","body":"Mobile ring taps were nondeterministic: click resolved against a\nhover cache that only updates in the animation frame after a\npointermove — a mouse streams moves, a tap races the frame and loses\nhalf the time. Taps now raycast the scene at the tap point directly.\nEach ring gains an invisible companion torus 3.5x fatter (child of\nthe ring mesh, inherits every transform) as the true hit target —\nhover uses it too. If even that misses, the rings' circles are\nprojected to screen space and the nearest within 28px takes the tap.\nDesktop interaction unchanged in feel; the needle just got an eye.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["2045ecc998c6053ff706a03e9053474e37ec6235"],"add":52,"del":4,"cadd":52,"cdel":4,"files":1},{"repo":"symbiont.systems","hash":"939c3b2ff394c2a546127db956bd80ba25b75d67","ts":1786935803,"wall":"2026-08-16T23:03","msg":"feat: every ring gets its preview card — generated from RING_CONFIG","body":"The three hand-written cards (four rings never got theirs) are\nreplaced by a builder that emits a preview card per ring from\nconfig: one source, no drift. Forms, Elemental, Eureka County, and\nForgejo now preview on hover like the rest.","parents":["ed68bf57d0d57b46c14b29b071ec431ddcacad19"],"add":22,"del":14,"cadd":22,"cdel":14,"files":1},{"repo":"symbiont.systems","hash":"263b000c65398c89cfbcb8e02039f80ad0eda55f","ts":1786935913,"wall":"2026-08-16T23:05","msg":"fix: fat hit-tori out, nearest-centerline in — adjacent rings sit 0.5 apart","body":"The 0.55 hit tubes of neighboring rings physically intersected, so\nthe raycast returned whichever surface faced the camera — often the\nwrong ring. Hit-testing (tap AND hover) is now purely the projected\nnearest-centerline test: the thread you see nearest your finger is\nthe one you get, 30px reach for taps, 26px for hover, 72 samples per\nring. Deterministic; no 3D geometry to argue with.","parents":["939c3b2ff394c2a546127db956bd80ba25b75d67"],"add":7,"del":19,"cadd":7,"cdel":19,"files":1},{"repo":"azura-website","hash":"7f98b1cdb1f00b8623c3777ffc35abda2d8f3277","ts":1786937024,"wall":"2026-08-16T23:23","msg":"feat: discoverability tier 1 — robots, sitemap, canonical, IndexNow key","body":"robots.txt keeps the tokened calendar feed out of crawlers and\ndeclares the sitemap; single-URL sitemap.xml; rel=canonical on the\npage; IndexNow key file for instant Bing/Yandex indexing (submission\nfollows once the cron publishes).","parents":["3458e7ace0f13926c2314b80a9de8ca4186e1286"],"add":17,"del":0,"cadd":1,"cdel":0,"files":5},{"repo":"azura-website","hash":"17b8f1b0e0382a11dc5a5de52293fb4a8e5c39ac","ts":1786937895,"wall":"2026-08-16T23:38","msg":"feat: coordinates gated — the land is silent, the booking speaks","body":"Gate/camp coordinates, maps links, the route schematic, and the\ndirections leave the public page without a trace — no replacement\ncopy, per operator: silence, not signage. All of it relocates to an\nunguessable /visit/<token>/ page (noindex, robots-excluded, the\ncalendar-feed pattern) to be handed out in booking confirmations.\nJSON-LD keeps the locality, loses the pin. The sky engine now runs\non Crescent Valley town center — seconds of difference, says\nnothing about the gate. directions.md removed from the public\ncontent tree; the operator's words moved whole.","parents":["7f98b1cdb1f00b8623c3777ffc35abda2d8f3277"],"add":87,"del":58,"cadd":85,"cdel":58,"files":6},{"repo":"azura-land","hash":"4e5b3aa2c25d951f6bb9e45629438788aae602c5","ts":1786937916,"wall":"2026-08-16T23:38","msg":"fix: precise coordinates out of the Place markup — locality only (coords gated)","body":"","parents":["c12306333b2d5c27567aec634f47b20ae928220d"],"add":0,"del":1,"cadd":0,"cdel":1,"files":1},{"repo":"azura-land","hash":"e7327a9ac0b3f25b3e18b6012406aaa65eba38e1","ts":1786939655,"wall":"2026-08-17T00:07","msg":"feat: served diary copies are EXIF-stripped — GPS never reaches the public site","body":"Location policy made mandatory: pages link /diary/full/, a generated\ntree of losslessly stripped copies (JPEG APP1 removed, pixels\nbyte-identical — tested); /photos/ is robots-excluded and the future\nvhost must deny it outright. 28 tests.","parents":["4e5b3aa2c25d951f6bb9e45629438788aae602c5"],"add":83,"del":4,"cadd":82,"cdel":4,"files":4},{"repo":"code-forge","hash":"08a85a864d52912335ae87989e1a56dd9f1fbd4e","ts":1786939730,"wall":"2026-08-17T00:08","msg":"docs: handoff — deployed state, final name","body":"","parents":["11e49c53658bc92877579b26398b11d385ad69ac"],"add":10,"del":6,"cadd":10,"cdel":6,"files":1},{"repo":"code-forge","hash":"982c08e82c176f28bda815316584254d37343686","ts":1786939750,"wall":"2026-08-17T00:09","msg":"docs: handoff current-state matches deployed reality","body":"","parents":["08a85a864d52912335ae87989e1a56dd9f1fbd4e"],"add":5,"del":4,"cadd":5,"cdel":4,"files":1},{"repo":"operations","hash":"e5a86d527d2949659a0c3b6c895a614afa5a7236","ts":1786939820,"wall":"2026-08-17T00:10","msg":"docs: session log + atlas + AAR — La Obra Raudhanica sprint, Azura gating","body":"code-forge registered in the atlas; SESSION-LOG entry for the\n2026-08-16/17 marathon; AAR with the reusable lessons (probe-log\noracle, cache drift, honesty pass, silence-not-signage) ingested in\nunicursal alongside the re-ingested design doc.","parents":["57de7e8ec878ad343b3db56b557bdbee2b03e525"],"add":147,"del":0,"cadd":146,"cdel":0,"files":4},{"repo":"infra","hash":"c5b98643bcb45d82721eef2ff721d3c8b95a5c39","ts":1786975553,"wall":"2026-08-17T10:05","msg":"feat: the server as found + deploy discipline","body":"Baseline import of symbiont-vps config (Caddyfile, cron.d incl. the\ngarden bake migrated out of root's crontab, BIND minus its key,\n/usr/local/bin scripts), deploys.toml surface registry, per-target\ndeploy scripts (backup + atomic move + verify), check-drift.sh, and\nthe restore runbook. Server-side edits are henceforth violations.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":[],"add":967,"del":0,"cadd":553,"cdel":0,"files":23},{"repo":"operations","hash":"6281a9550477580fd4e762d9e668cca0ed8e2b17","ts":1786975835,"wall":"2026-08-17T10:10","msg":"atlas: register infra — the server as code","body":"","parents":["e5a86d527d2949659a0c3b6c895a614afa5a7236"],"add":5,"del":0,"cadd":1,"cdel":0,"files":5},{"repo":"infra","hash":"81120aedfcc06e34382a539843e3f36d784e1eb5","ts":1786976984,"wall":"2026-08-17T10:29","msg":"feat: Phase C — the ntfy spine: silent failure ends","body":"ntfy v2.27.0 (pinned binary) at ntfy.symbiont.systems behind Caddy\n(vhost deployed via deploy/caddy.sh — the pipeline dogfooded on its\nfirst real change). Auth deny-all: valis admin (phone app), cron\nwrite-only to symbiont-alerts via token. notify-fail.sh wraps every\ncron — azura-pull (bash -c so the && chain survives), organum-bake\n(as forgejo; token group-readable), garden-bake, vps-backup —\npublishing to localhost so alerts outlive vhost trouble. Weekly\ndrift check on simutron pushes on drift. Backup set now carries\n/etc/ntfy + /var/lib/ntfy. Found+fixed: bash if-without-else eats\nthe failing exit code (RC after fi is 0).","parents":["c5b98643bcb45d82721eef2ff721d3c8b95a5c39"],"add":31,"del":4,"cadd":20,"cdel":0,"files":7},{"repo":"infra","hash":"767ba5bdc3c21e6471ff8ac124750ee1bb9af955","ts":1786978688,"wall":"2026-08-17T10:58","msg":"fix: alert topic renamed to symbiontx — operator's chosen name","body":"","parents":["81120aedfcc06e34382a539843e3f36d784e1eb5"],"add":2,"del":2,"cadd":2,"cdel":2,"files":1},{"repo":"code-forge","hash":"dc3442c3bef84720973c174ca74ce91324913b57","ts":1786979992,"wall":"2026-08-17T11:19","msg":"feat: /lens code — the hand-written view, opt-in and openly declared","body":"Baker v2 (cache versioned): every commit carries cadd/cdel — adds and\ndeletes in the hand-written suffix class (source, markup, config,\nprose; data formats fall outside; suffix class ONLY, never curated\npaths, per the honesty ruling) — and strata_code bins the living\nlines the same way, in the same blame pass. '/lens code' in the\npalette re-counts churn, node sizes, ledger weights, strata, and the\nstatline through the lens — with the statline openly declaring\n'lens: code'; '/lens off' restores the whole truth; ?lens=code makes\nit shareable. First reading: 11.3M committed / 3.9M hand-class;\n1.52M living / 645k living code. 18 py + 23 node tests.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["982c08e82c176f28bda815316584254d37343686"],"add":173,"del":29,"cadd":173,"cdel":29,"files":6},{"repo":"infra","hash":"f404707159824da1411e6310cdd55c444b2d244b","ts":1786979996,"wall":"2026-08-17T11:19","msg":"sync: bake_record.py v2 from code-forge (cadd/cdel + strata_code)","body":"","parents":["767ba5bdc3c21e6471ff8ac124750ee1bb9af955"],"add":49,"del":13,"cadd":49,"cdel":13,"files":1},{"repo":"code-forge","hash":"759e47555ec26db695fa60ba1b0fe6f190e19e8b","ts":1786980163,"wall":"2026-08-17T11:22","msg":"chore: build id for lens deploy","body":"","parents":["dc3442c3bef84720973c174ca74ce91324913b57"],"add":4,"del":4,"cadd":3,"cdel":3,"files":2},{"repo":"operations","hash":"500b0cfb3ef253e9715f729952b60995adf9bbb4","ts":1786980635,"wall":"2026-08-17T11:30","msg":"docs: the Estate Manual — every surface, instrument, pipeline, and quirk","body":"The operator's tutorial and general review in one: La Obra's palette\ngrammar and gauges, the portal's rings, Azura's publish-and-gate\npatterns, the infra repo rules, backups, the spine, the storage box,\nthe tokened-URL pattern, the eight-line doctrine, and the cron map.\nIngested in unicursal.","parents":["6281a9550477580fd4e762d9e668cca0ed8e2b17"],"add":233,"del":0,"cadd":233,"cdel":0,"files":1},{"repo":"code-forge","hash":"473d271d8054679d9047dd567d8a60796c4aae15","ts":1786981013,"wall":"2026-08-17T11:36","msg":"feat: the tutorial — game grammar, do it to advance","body":"First visit (desktop), La Obra teaches itself: six steps, each\nwaiting for the real action — the replay, a scrub, a page flip, a\ncommit opened, the palette summoned, the lens flipped — coach\ncartouche in the plate grammar, gold pulse on the target pane, Esc\nskips, localStorage remembers, /help (and ?tutorial=1) replays.\nmain.js dispatches obra:* events at the true moments; the no-replay\nand URL-state boot paths satisfy step one too.\n\nAuthored by Rowan Valle; Executed by Claude Code","parents":["759e47555ec26db695fa60ba1b0fe6f190e19e8b"],"add":259,"del":5,"cadd":258,"cdel":4,"files":6},{"repo":"symbiont.systems","hash":"014470a71af6c5ff4acd134ee421d41eade5d16d","ts":1786981017,"wall":"2026-08-17T11:36","msg":"feat: first-visit hint on touch devices — 'touch a ring', retiring at first touch","body":"","parents":["263b000c65398c89cfbcb8e02039f80ad0eda55f"],"add":34,"del":0,"cadd":34,"cdel":0,"files":1},{"repo":"code-forge","hash":"3563125148804346e3bbb77ce1478470f6cd08d5","ts":1786981363,"wall":"2026-08-17T11:42","msg":"copy: tutorial stripped to dry imperatives — operator veto on the flourish","body":"","parents":["473d271d8054679d9047dd567d8a60796c4aae15"],"add":13,"del":19,"cadd":12,"cdel":18,"files":3},{"repo":"code-forge","hash":"ee1fe5aac9f078b682ff7405f3bff4341ca3b27d","ts":1786984415,"wall":"2026-08-17T12:33","msg":"copy: tutorial in plain sentences — informative and nothing else","body":"","parents":["3563125148804346e3bbb77ce1478470f6cd08d5"],"add":13,"del":13,"cadd":12,"cdel":12,"files":3},{"repo":"operations","hash":"fbfe5ae70db18df33d19b291eca3a8d5d945428a","ts":1786988945,"wall":"2026-08-17T13:49","msg":"strategy: openly for hire — the service menu (Recon/Survey/Build/Atlas/Doctrine/Retainer)","body":"Posture ruled, menu named and priced against researched comps\n(fixed-price only, K floor, speed clocks as the axis), ESA\nqualification path documented as dormant option.","parents":["500b0cfb3ef253e9715f729952b60995adf9bbb4"],"add":39,"del":1,"cadd":39,"cdel":1,"files":1},{"repo":"operations","hash":"d5cf47fbde1b573f2676e3352a94b77b6a993874","ts":1786989012,"wall":"2026-08-17T13:50","msg":"strategy: sixth offer named Standby","body":"","parents":["fbfe5ae70db18df33d19b291eca3a8d5d945428a"],"add":1,"del":1,"cadd":1,"cdel":1,"files":1},{"repo":"operations","hash":"5646459158ee22f7af7bb200873b7f6c19dd3f5f","ts":1786990041,"wall":"2026-08-17T14:07","msg":"strategy: final service names (operator) — descriptive; Eco-Agronomy program replaces Survey at $5K+","body":"","parents":["d5cf47fbde1b573f2676e3352a94b77b6a993874"],"add":7,"del":7,"cadd":7,"cdel":7,"files":1},{"repo":"operations","hash":"63f80d2b692fdffea6a7eb9f3e9eab40dd5feeb3","ts":1786990244,"wall":"2026-08-17T14:10","msg":"strategy: billing is hourly at $150/hr — operator ruling; menu ranges = typical totals","body":"","parents":["5646459158ee22f7af7bb200873b7f6c19dd3f5f"],"add":4,"del":3,"cadd":4,"cdel":3,"files":1},{"repo":"operations","hash":"2bb95654953a9e8011444dbdf2cbe3ec16a52c73","ts":1786990583,"wall":"2026-08-17T14:16","msg":"strategy: add Consultation at $150/hr — the sole hourly item, on-ramp under the $1K floor; engagements stay fixed-price","body":"","parents":["63f80d2b692fdffea6a7eb9f3e9eab40dd5feeb3"],"add":2,"del":1,"cadd":2,"cdel":1,"files":1},{"repo":"operations","hash":"479ee582e42de60992da450302a3bf4eb5269005","ts":1786990724,"wall":"2026-08-17T14:18","msg":"strategy: correct billing doctrine — fixed-price engagements; Consultation is the sole hourly item","body":"","parents":["2bb95654953a9e8011444dbdf2cbe3ec16a52c73"],"add":5,"del":4,"cadd":5,"cdel":4,"files":1},{"repo":"operations","hash":"4ed9a9a194c736f91cab5038467d9ef2d35f35c3","ts":1786990883,"wall":"2026-08-17T14:21","msg":"handoff: estate sprint + final services menu (2026-08-15..17)","body":"","parents":["479ee582e42de60992da450302a3bf4eb5269005"],"add":73,"del":0,"cadd":73,"cdel":0,"files":1},{"repo":"infra","hash":"3cf321c791ba302abe3cabc6ac6e4a2387fe7bc8","ts":1786990887,"wall":"2026-08-17T14:21","msg":"handoff: infra trio live and verified","body":"","parents":["f404707159824da1411e6310cdd55c444b2d244b"],"add":46,"del":0,"cadd":46,"cdel":0,"files":1},{"repo":"symbiont.systems","hash":"6a868e46b14a55e3086a4314f342a1836a15e0d9","ts":1786990891,"wall":"2026-08-17T14:21","msg":"handoff: session 4 — ring roster + touch UX","body":"","parents":["014470a71af6c5ff4acd134ee421d41eade5d16d"],"add":47,"del":0,"cadd":47,"cdel":0,"files":1},{"repo":"azura-website","hash":"99b4a89f1bab20cb3d57edccf84adf438a31d179","ts":1786990895,"wall":"2026-08-17T14:21","msg":"handoff: gating + discoverability tier 1","body":"","parents":["17b8f1b0e0382a11dc5a5de52293fb4a8e5c39ac"],"add":42,"del":0,"cadd":42,"cdel":0,"files":1},{"repo":"infra","hash":"99942d302d3cbb745bec5d8adb02303aaff37375","ts":1786991061,"wall":"2026-08-17T14:24","msg":"security: azura.camp hides .git/.claude/.gitignore/.indexnow-key — webroot is a live checkout; .git was publicly readable","body":"","parents":["3cf321c791ba302abe3cabc6ac6e4a2387fe7bc8"],"add":5,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"operations","hash":"6c268e3c9c1f4a13631d4448210002b833db8ca1","ts":1786991353,"wall":"2026-08-17T14:29","msg":"docs: estate manual doctrine 9 — checkout webroots hide .git (azura.camp exposure sealed + audited clean)","body":"","parents":["4ed9a9a194c736f91cab5038467d9ef2d35f35c3"],"add":6,"del":0,"cadd":6,"cdel":0,"files":1},{"repo":"eureka-co-nevada","hash":"9ddaf24266b8477bbc07225a4bdca9c57001b77f","ts":1787169254,"wall":"2026-08-19T15:54","msg":"docs: mobile field-instrument architecture — offline storage, packs, prior art","body":"Research for carrying the county twin into the county it models. Two products\nagreed: A (reading surface, phone with signal) and B (field instrument, no bars).\n\nFindings that shape the build:\n- The vector twin minus closed claims is 232 MB across eight archives, every one\n  inside the 10-100 MB band OPFS handles well. The county is carryable whole.\n  Only imagery needs geographic scoping.\n- Tiles must never pass through a service worker: Cache Storage forbids storing\n  a 206. Three stores, three roles - OPFS for archives, SW cache for shell and\n  glyphs and sprites, IndexedDB for atoms.\n- pmtiles extract works against a remote archive, so packs bake from the 10.2 GB\n  NAIP file without moving it. Prior art (Esri, onX) says preplanned beats\n  on-demand, which removes an extraction service from the design.\n- Chrome on Android has no showOpenFilePicker, so sideload means pick once and\n  stream into OPFS. Packs can arrive by USB instead of over rural LTE.\n\nIngested to unicursal (13 fragments, 10 axes); topology graphed.","parents":["72125a8f5a7463e82c27a3d340067a64fcc04695"],"add":197,"del":0,"cadd":197,"cdel":0,"files":1},{"repo":"eureka-co-nevada","hash":"52ac963fd4267eff6d96c935ad12312ec9f24c48","ts":1787169269,"wall":"2026-08-19T15:54","msg":"fix(map): self-host glyphs — three of four font stacks rendered no labels","body":"Root cause of the long-standing \"Unimplemented type: 4\" throw, which was\nrecorded as cosmetic and was not. fonts.openmaptiles.org answers an unknown\nfontstack with HTTP 200 and its marketing HTML; MapLibre protobuf-decodes that\npage and fails. Verified by request:\n\n  Metropolis Medium                      200 application/octet-stream  68470\n  Open Sans Bold                         200 application/octet-stream  80025\n  Noto Sans Bold                         200 text/html                  2725\n  Arial Unicode MS Bold                  200 text/html                  2725\n  Open Sans Bold,Arial Unicode MS Bold   200 text/html                  2725\n\nSo contour labels, place labels, summit labels and POI labels were all silently\nabsent - the composite stack is unresolvable because the fallback name is\nproprietary and exists on no open glyph server.\n\n- Glyphs now served from /fonts, adjacent to /sprites and /pmtiles, from the\n  openmaptiles fonts v2.0 release. 2.8 MB: Metropolis Medium and Open Sans Bold\n  complete, Noto Sans Bold Latin-only since it labels contour elevations.\n- Arial Unicode MS Bold dropped from all four stacks.\n- New test asserts every text-font a layer declares has glyphs on disk and that\n  the payload is a protobuf rather than an HTML error page. It fails red on the\n  Arial stack, so this class of silent breakage cannot return.\n\nAlso removes a third-party runtime dependency and is a precondition for offline.\n\n36 tests pass, typecheck clean.","parents":["9ddaf24266b8477bbc07225a4bdca9c57001b77f"],"add":1556,"del":5,"cadd":71,"cdel":5,"files":520},{"repo":"eureka-co-nevada","hash":"8e17b301816ad16eb61e4b3bbbe47af6a2fe36a9","ts":1787169389,"wall":"2026-08-19T15:56","msg":"feat(map): geolocate control with field defaults, not browser defaults","body":"A county map on a phone must answer where-am-I first. Neither the deployed\nmonolith nor this rebuild had any geolocation at all - no GeolocateControl, no\nnavigator.geolocation anywhere in the tree.\n\nSettings live in config/geolocate.config.ts because they are field decisions,\nnot implementation detail:\n\n- enableHighAccuracy true. MapLibre defaults to false, which asks the OS for a\n  coarse network estimate - fine in a city, useless where the nearest tower is a\n  valley away and GNSS is the only real source.\n- timeout 20 s. The 6 s default gives up before a cold GNSS lock under cover.\n- maximumAge 0. In a moving truck a cached position is a lie.\n- trackUserLocation true, so the control follows instead of acting as a one-shot\n  desktop button.\n- showAccuracyCircle true. A bare dot claims precision the fix does not have,\n  and out here that difference is the width of a section line.\n- fitBoundsOptions maxZoom 15, to keep enough country in frame to stay oriented.\n\nFive tests guard these against reverting to the browser defaults. The control\ndisables its own button when a fix is refused, so failure is already visible\nwithout a notification surface.\n\nNoted in the source: geolocation needs a secure context, so reaching the dev\nserver from a phone by LAN IP silently kills it. Use adb reverse and localhost.\n\n41 tests pass, typecheck clean, build 1250 kB / 332 kB gzip.","parents":["52ac963fd4267eff6d96c935ad12312ec9f24c48"],"add":75,"del":0,"cadd":75,"cdel":0,"files":3},{"repo":"eureka-co-nevada","hash":"cad0a5acb2c7665340343acff063680f0e7dba2c","ts":1787169558,"wall":"2026-08-19T15:59","msg":"chore(map): pmtiles 3.0.6 to 4.5.0, maplibre 5.21.1 to 5.24.0, patch dev audit","body":"pmtiles 4 is required, not optional: the offline plugin we will use for the\nfield instrument depends on pmtiles ^4.4.0, and shipping two copies in one\nbundle is not acceptable. The API we touch is unchanged - new Protocol().tile\nwith addProtocol - and 4.x additionally exposes Protocol.add/get and a\nFileSource, which are exactly the seams the offline path needs.\n\nMapLibre stays on the 5 line, deliberately. v6.4.1 is current and its bundle and\nWebGL2 gains are real, but @makina-corpus/maplibre-offline-pmtiles declares\npeer maplibre-gl ^3 || ^4 || ^5 and was last released in March, before v6\nshipped in July. Upgrading now would put the field instrument outside its\nsupported range on a guess. 5.24.0 is the head of the 5 line. Revisit v6 when\nthe plugin declares support or when we verify it ourselves.\n\nAlso ran npm audit fix: nanoid and postcss, both transitive under Vite and\nbuild-time only, both now clean. Production dependencies were already clean.\n\nPins stay exact. 41 tests pass, typecheck clean, 0 vulnerabilities.\nBundle 1253 kB / 333 kB gzip, unchanged within noise.","parents":["8e17b301816ad16eb61e4b3bbbe47af6a2fe36a9"],"add":21,"del":31,"cadd":0,"cdel":0,"files":2},{"repo":"eureka-co-nevada","hash":"079d910da5fd982b9b0a647ddfe24f8364da1fc0","ts":1787169783,"wall":"2026-08-19T16:03","msg":"test(map): mechanical style-spec oracle — disproves the malformed-expression theory","body":"The handoff records a TypeError on .value in the map load path, guessed to be\n\"likely a malformed paint expression\" and never root-caused. Guessing is not a\ndiagnosis, so this asks the MapLibre style-spec validator instead.\n\nThe map singleton is mocked, so the oracle runs with no DOM and no WebGL - the\nfake only records what addLayer was asked to add. It captures the real load\norder from main.ts (contours, catalogue, towns), 150 layers in total, and\nvalidates:\n\n  - the base style alone\n  - every added layer\n  - the whole composed style, base plus catalogue, which is the runtime shape\n\nAll clean. The malformed-expression hypothesis is therefore wrong, and the throw\nlives somewhere the style spec cannot see. Root-causing it needs the error\nobserved in a browser; noted for the device gate rather than guessed at again.\n\nTo make the base style testable it moved out of map.ts into core/baseStyle.ts as\na pure function of the web-root origin. map.ts builds a real Map at import time\nand can never run in a test; this can. That also removed the `as any` cast on\nthe style object, so StyleSpecification now type-checks the thing it describes.\n\n45 tests pass, typecheck clean, build unchanged.","parents":["cad0a5acb2c7665340343acff063680f0e7dba2c"],"add":132,"del":25,"cadd":132,"cdel":25,"files":3},{"repo":"eureka-co-nevada","hash":"984ce33930970cf0be984c0ea60d5081db3e357c","ts":1787169989,"wall":"2026-08-19T16:06","msg":"feat(scripts): field pack builder — the whole county travels for 362 MB","body":"The research doc estimated township imagery at ~90 MB from arithmetic and said\nthe figure had to be measured before anything was designed against it. Measured,\nwith pmtiles extract against the local 10.2 GB archive:\n\n  whole county   z13    8.1 MB      township   z16    7.0 MB\n                 z14   32.3 MB      (6x6 mi)   z17   25.6 MB\n                 z15  130.8 MB                 z18  103.9 MB\n                 z16  553.0 MB\n                 z18   10.2 GB\n\nEvery extract finished in under a second. The arithmetic was close on townships\nand wrong about the shape of the problem: the county does not need scoping.\n\nCapping imagery at z15 puts the entire county - all eight vector archives whole,\nplus countywide imagery - in 362.0 MB, verified end to end. At z15 roads, fields,\nfence lines and structures are legible, which is enough to navigate by. That is\none download with nothing to choose in advance and nothing to get wrong in the\nfield, which is the failure mode Esri warns about with on-demand areas.\n\nTownship packs survive as an opt-in second tier for full resolution where work is\nactually happening. Two tiers is onX's low/medium/high, reached from the\nmeasurements rather than from the prior art.\n\nClosed claims stay out: 285 MB of 106K historic claims is over the OPFS band and\nof little use standing in a wash.\n\nBoth tiers pass pmtiles verify. Outputs gitignored.","parents":["079d910da5fd982b9b0a647ddfe24f8364da1fc0"],"add":135,"del":9,"cadd":134,"cdel":9,"files":3},{"repo":"eureka-co-nevada","hash":"c93e08ca07017e0d37629be2bc27d789780b6132","ts":1787170039,"wall":"2026-08-19T16:07","msg":"docs: handoff — mobile arc, six commits, device gate blocking","body":"Records what landed, the two findings that change the picture (silent label\nfailure, and the county not needing scoping), the reasons behind the version\ndecisions, and what is explicitly still open. Notes that the .value throw is not\na malformed expression so it is not re-theorised a third time.\n\nAlso records that the plan file the COP section references no longer exists in\n~/.claude/plans/, and that plans belong in the repo so they cannot vanish again.","parents":["984ce33930970cf0be984c0ea60d5081db3e357c"],"add":82,"del":2,"cadd":82,"cdel":2,"files":1},{"repo":"eureka-co-nevada","hash":"c1fd81a3d9ece24fda42e1718c2e89f06de13231","ts":1787174515,"wall":"2026-08-19T17:21","msg":"feat(map): the lip is the mobile affordance; the / palette is desktop only","body":"Operator: on mobile there must be a lip you pull up and down like every other\napp, not a / palette. Correct - the palette is a keyboard affordance and was\nstanding in as the only way into the app on a phone.\n\nThe sheet mechanics already existed - three detents, drag, fling, snap - but the\nbody stayed empty until the palette put a panel in it, so a phone showed a bare\n96 px strip with no way in except the very thing that does not belong there.\n\n- A tab strip now lives in the peek lip, one tab per registered panel in\n  manifest order, so the closed sheet already says what it holds. The Panel type\n  has documented a \"sheet tab\" since it was written; it was never built.\n- The whole lip is a drag handle, not just the grabber. Tap-to-cycle stays\n  scoped to the grabber, so tapping a tab selects that tab and nothing else.\n- Tapping the active tab shuts the sheet; tapping another switches and opens.\n- The FAB is hidden under 768 px. The physical / key still works wherever there\n  is a keyboard.\n- Peek is 88 px: grabber 26 plus tab strip 44 plus margin, so the lip cannot\n  hide its own tabs. Tabs are 36 px tall inside 8 px padding, keeping the touch\n  target at the 44 px minimum.\n\nThe default panel renders from main.ts after setCatalogue, not at mount. The\nlayers panel needs subLayerIdsById to wire its toggles, so rendering it at shell\nmount would have produced a panel of dead switches. Tabs appear immediately\neither way, so the chrome stays independent of map load as intended.\n\nKnown gap: Reset View, Screenshot and Zen were palette-only and are now\nunreachable on a phone. Open Layers/Search/Inspector are replaced by the tabs.\nThose three want a home on mobile - a design call, not a silent drop.\n\nDeployed to /test/. 45 tests pass, typecheck clean.","parents":["c93e08ca07017e0d37629be2bc27d789780b6132"],"add":118,"del":5,"cadd":118,"cdel":5,"files":5},{"repo":"eureka-co-nevada","hash":"b4bba597a7306648e95a7efe803fa4bab635f880","ts":1787175132,"wall":"2026-08-19T17:32","msg":"fix(map): drop Carlin — it is in Elko county","body":"Carlin sat in the hardcoded TOWNS list and the map drew and labelled it as one\nof ours. A twin that marks places it does not contain is lying about its own\nextent.\n\nVerified rather than assumed, against the Census county boundary already in the\nrepo (GEOID 32011), by point-in-polygon:\n\n  Eureka           -115.9605  39.5126   inside\n  Crescent Valley  -116.5731  40.4172   inside\n  Beowawe          -116.4736  40.5897   inside\n  Carlin           -116.1035  40.7143   OUTSIDE\n\nOnly Carlin. Crescent Valley and Beowawe are genuinely in the county, so the\nobvious \"clean up the northern ones too\" instinct would have deleted real data.\n\nplaces.config.test.ts now point-in-polygons every town against that boundary, so\na stray town fails the suite instead of shipping. Confirmed it bites: red with\nCarlin restored, green without. Deployed - the town's latitude no longer appears\nanywhere in the served bundle.\n\nNote for the reader: \"Carlin Peaks\" stays. It is named for the town but sits at\n40.7414, inside the line - which is why this was checked by geometry and not by\nmatching on the name.\n\n50 tests pass.","parents":["c1fd81a3d9ece24fda42e1718c2e89f06de13231"],"add":68,"del":1,"cadd":68,"cdel":1,"files":2},{"repo":"eureka-co-nevada","hash":"86c4d3a54cc4bfc9764f6a398719a689d1386575","ts":1787175469,"wall":"2026-08-19T17:37","msg":"fix(map): peek must clear the first body line, not just the tabs","body":"Adding the tab strip to the lip at 88 px left the body zero visible height at\npeek, which silently broke the inspector's whole design. inspect.ts states it:\n\"peek shows the identity line, dragging up reveals the table.\" With tabs in the\nway there was no identity line to see - you would tap a feature and the sheet\nwould look empty until you dragged it.\n\nborder-box throughout: grabber 26 + tabs (36 + 8 strip padding) + identity line\n(18 + 12 padding) = 100. Peek is now 112, so the body reads as continuing below\nthe fold rather than ending.\n\nFound by reading the panel I had just changed the container of.","parents":["b4bba597a7306648e95a7efe803fa4bab635f880"],"add":6,"del":1,"cadd":6,"cdel":1,"files":1},{"repo":"eureka-co-nevada","hash":"2bae7a83fb33d28ebfa4ea4239b55078e8d95230","ts":1787176035,"wall":"2026-08-19T17:47","msg":"feat(map): identity, position readout, and an overflow for the stranded actions","body":"Three gaps, two of them regressions the rebuild introduced against the legacy.\n\n1. The map did not say what it was. The legacy carried a title card; the rebuild\n   dropped it and opened as an anonymous viewer. Restored as a tap-to-expand card\n   top left, driven by config/identity.config.ts so the statewide map swaps one\n   object.\n\n   Its numbers are derived, not copied. The legacy claimed 10,786 km2 - which\n   matches neither the land nor the land-plus-water figure in the Census boundary\n   sitting in this repo - and a feature count of 186,548 that went stale the day\n   the catalogue changed. Area now comes from GEOID 32011 (AREALAND +\n   AREAWATER = 10,826 km2, 4,180 sq mi), the high point from the summits file\n   (Diamond Peak, 3,234 m), and the layer count is counted at runtime.\n\n2. Nothing ever showed you where you are. The legacy printed coordinates on\n   mousemove, which never fires on a phone - so the one device you would be\n   standing in the county with showed nothing. Long-press Copy coordinates\n   existed but is undiscoverable and copies the pressed point, not your position.\n\n   The readout shows your GPS fix with its accuracy while the geolocate control\n   is tracking, the map centre otherwise, and says which. Tap to copy decimal\n   degrees. On tracking end it drops back to the centre rather than leaving a\n   stale fix on screen still pretending to be you.\n\n   MapLibre fires new Event('geolocate', position) and its extend() copies with\n   for...in, which walks the prototype chain, so the GeolocationPosition\n   accessors do land on the event. Checked against the bundled source rather than\n   trusted, and guarded loudly regardless.\n\n3. Reset View, Screenshot and Zen were palette-only and the palette is now\n   desktop-only, so they were unreachable on a phone. A \"...\" button in the lip\n   lists every non-panel command - read at click time, so commands registered\n   during map load are picked up. It reuses the existing context-menu renderer,\n   which already becomes a bottom sheet under 768 px, rather than growing a\n   second menu.\n\n50 tests pass, typecheck clean. Deployed to /test/.","parents":["86c4d3a54cc4bfc9764f6a398719a689d1386575"],"add":318,"del":5,"cadd":318,"cdel":5,"files":8},{"repo":"eureka-co-nevada","hash":"e3cac420e6df951a2e2e4273bc276f5a80d02b78","ts":1787176555,"wall":"2026-08-19T17:55","msg":"docs: preset design research — QGIS themes, the clutter budget, revised set","body":"Researched before building, and it corrected my own proposal in three places.\n\nThe model to copy is QGIS map themes, not onX. Themes capture layer visibility,\nsublayer/category visibility, and style BY REFERENCE rather than inline, and\napply exclusively. Two of those are load-bearing here: our catalogue is full of\nsublayers (flowlines by regime, buildings by 20 types, claims by operator), and\ngrazing alone carries 7 render modes - a preset must name a mode id, never embed\npaint values, or every palette change breaks every preset. Exclusive-vs-additive\nis settled by prior art rather than taste.\n\nWorth stating plainly: onX and Gaia ship basemap switching and individual\ntoggles, not saved layer sets. They are the right reference for the offline packs\nand the wrong one here.\n\nThe finding that changed the design: 21 of the 43 layers are area fills and\nEcology alone holds 10, so the \"Wildlife\" preset I proposed would have stacked\nten translucent polygons - exactly the clutter failure mode the cartographic\nliterature names. But the refinement matters more than the count: ownership fills\nPARTITION space and read as one choropleth, while habitat fills NEST and read as\nmud. The budget is on overlapping fills, not fills.\n\nConsequent changes: Wildlife splits into \"Big Game\" (route lines across all three\nherds) plus per-herd presets, which also matches the USGS atlas convention of\nmapping herds individually. PLSS leaves Ownership for its own Survey preset - it\nis a reference frame, not an ownership class. Closed claims leaves Mining; 106K\nfeatures and 285 MB is history, not current activity, and should be a deliberate\nact over cellular.\n\nIngested to unicursal (8 fragments, 9 axes). No code yet.","parents":["2bae7a83fb33d28ebfa4ea4239b55078e8d95230"],"add":151,"del":0,"cadd":151,"cdel":0,"files":1},{"repo":"eureka-co-nevada","hash":"85b5e6732beb3ec8e4b9d0b8fa38741ff6c37533","ts":1787177335,"wall":"2026-08-19T18:08","msg":"fix(map): gitignore rule for field-packs was anchored and therefore dead","body":"I wrote \"map/field-packs/\" into map/.gitignore. A pattern containing a slash is\nanchored to the directory holding the .gitignore, so that matched\nmap/map/field-packs/ - a path that does not exist. Confirmed with\ngit check-ignore: map/field-packs/manifest.json was NOT ignored.\n\nThe 362 MB county pack was safe only by accident, caught by the root *.pmtiles\nrule. Anything else the pack builder emits - a manifest, a checksum file - would\nhave been staged by a git add of the directory.\n\nNow \"field-packs/\", verified with git check-ignore against both a .pmtiles and a\n.json path.\n\nFound by the repo audit.","parents":["e3cac420e6df951a2e2e4273bc276f5a80d02b78"],"add":1,"del":1,"cadd":0,"cdel":0,"files":1},{"repo":"eureka-co-nevada","hash":"c6670ca48061255938a6a082c2d10fe8c51bdd19","ts":1787177738,"wall":"2026-08-19T18:15","msg":"docs: five-lane parallel audit — ~20 confirmed defects, .value throw root-caused","body":"Five read-only auditors over map/ and the repo: correctness, architecture and\ndead code, tests, performance and mobile, repository state. Nothing was modified.\n\nThe .value TypeError is root-caused after months. opacityProp() in\nui/panels/layerActions.ts has no circle branch and falls through to\nfill-opacity. Style.setPaintProperty runs deepEqual(layer.getPaintProperty(name),\nvalue) BEFORE delegating to the validating setter, so getPaintProperty reaches\nTransitionable.getValue and dereferences this._values['fill-opacity'].value on a\ncircle layer, which is undefined. It fires only on a second visit, once state has\nbeen saved, which is why it looked intermittent. The cascade matters more than\nthe throw: main.ts wraps the restore loop and autoSave() in one try/catch, so ~30\nlayers never restore and persistence is permanently dead thereafter.\n\nThe earlier \"malformed paint expression\" hypothesis was wrong, and the style-spec\noracle written to test it could not have seen this - its fake's setPaintProperty\nis a no-op.\n\nPerformance headline, verified by hand: every vector archive stores tiles\nuncompressed. build-pmtiles.sh passes --no-tile-compression under a comment\nreading \"no compression (PMTiles handles it)\" - the comment is the bug. PMTiles\nrecords a compression type, it does not apply one, and Range addressing means the\nserver cannot gzip either. Measured ownership z8 at 2.31x, closed-claims z8 at\n5.35x. Rebuild-only fix, no code change - and it must precede baking offline\nfield packs or the waste is baked in permanently.\n\nAlso: no minzoom on any of 148 layers, so one tap on Closed Claims at the default\nview starts a measured 23.6 MB download; preserveDrawingBuffer is global for one\ncommand; mouseenter/mouseleave run two unfiltered queryRenderedFeatures per\npointer move over all 148 layers.\n\nSeveral of the worst findings were introduced by the mobile session that\ncommissioned this audit, including the ... overflow being 45 items tall and\nunscrollable, Zen being a one-way door on mobile, and a circular import surviving\nonly on import-type erasure.\n\nRepo: 15 commits unpushed; live is four commits behind master and missing an\nHTML-injection hardening; merging to master without changing the deploy step\nserves a blank page.\n\nIngested to unicursal (10 fragments, 8 axes).","parents":["85b5e6732beb3ec8e4b9d0b8fa38741ff6c37533"],"add":228,"del":0,"cadd":228,"cdel":0,"files":1},{"repo":"eureka-co-nevada","hash":"687cf8db63ede543d80b3f29147c96f6cc8eabc9","ts":1787180171,"wall":"2026-08-19T18:56","msg":"fix(map): root-cause the .value TypeError — one paint-property table","body":"The throw that has been open for months. opacityProp() in layerActions.ts had no\ncircle branch and fell through to 'fill-opacity'. Style.setPaintProperty runs\ndeepEqual(layer.getPaintProperty(name), value) BEFORE delegating to the\nvalidating setter, so getPaintProperty reached Transitionable.getValue and\ndereferenced this._values['fill-opacity'].value on a circle layer, which is\nundefined.\n\nIt only fired on a second visit, once state had been saved, which is why it read\nas intermittent. Walking persisted state in registration order reaches springs\n13th - type circle, no sublayers - and throws.\n\nThe cause underneath the bug: the same knowledge was encoded twice in two\ndifferent vocabularies. One ladder keyed on the CONFIG type\n(fill/line/circle/well/range-label), another twenty lines below keyed on the\nMAPLIBRE type (fill/line/circle/symbol), each with its own silent fallback. Four\nconfig types translate to a different MapLibre type than their name suggests -\nwell builds a circle, range-label builds a symbol - so the config-keyed ladder\nwas wrong for 12 of 43 layers.\n\nlayers/paintProps.ts now holds it once, as data, with the translation explicit\nand NO fallback: an unknown type returns nothing and the caller does nothing,\nrather than guessing 'fill-' and throwing inside the library.\n\nThe test is a real oracle, not a table asserted against itself: it runs the\nactual builders against a fake map, records what they really emitted, and checks\nthe table against that. Verified it bites - encoding the old assumption\n(well is a fill) fails with \"wells: config 'well' -> table says 'fill', builder\nemitted 'circle'\".\n\nTwo things fixed for free by having the table:\n- Opacity now reaches the -heatmap sibling, which neither branch touched. The\n  control did nothing at all while a layer was in heatmap render mode; the\n  legacy fanned out to it and the rebuild dropped that.\n- setLayerColor had the same defect and would have set fill-color on a symbol.\n\nmain.ts now guards the restore PER LAYER. One bad entry used to abort the whole\nloop and - because autoSave() sat inside the same try - stop the map ever saving\nagain. A single throw on the 13th layer left ~30 unrestored and persistence dead\nfrom that session onward.\n\n71 tests pass, typecheck clean.","parents":["c6670ca48061255938a6a082c2d10fe8c51bdd19"],"add":229,"del":33,"cadd":229,"cdel":33,"files":4},{"repo":"eureka-co-nevada","hash":"87e3d67c4dab3bcbbb7b43c27e77f871357c8e62","ts":1787180192,"wall":"2026-08-19T18:56","msg":"fix(map): put the smoke detector back — map errors were going unheard","body":"The rebuild dropped map.on('error'), which the legacy had at index.legacy.html\n:2791. MapLibre failures do not throw to the page; they arrive on that handler or\nnowhere. With it gone, every one of them was silent - the glyph server answering\nHTTP 200 with an HTML page, a paint property set on the wrong layer type, a\nmissing sprite. That is why the missing-label bug survived months of use.\n\nAlso de-silenced two swallowed failures:\n- baseCartography's county-mask fetch had .catch(() => {}), so a failed mask\n  looked identical to a working one.\n- basemap fell back from NAIP to USGS topo without ever saying why, which hides\n  precisely the case that matters in the field: the local PMTiles being\n  unreachable.\n\nNothing here changes behaviour. It changes whether we find out.","parents":["687cf8db63ede543d80b3f29147c96f6cc8eabc9"],"add":20,"del":6,"cadd":20,"cdel":6,"files":3},{"repo":"eureka-co-nevada","hash":"c3685335d77895e6647cfa0aebcace179a0e6ac9","ts":1787180192,"wall":"2026-08-19T18:56","msg":"fix(map): three mobile regressions from the session that shipped the sheet","body":"All three were mine, all three found by the audit.\n\n1. The \"...\" overflow listed 45 commands, not 3. It filtered out the Panels\n   group and kept everything else - including 42 per-layer toggle commands\n   registered in a loop, which is why source-grepping for group: 'Layers' showed\n   one occurrence and I read it as one command. At 44px each the menu rendered\n   ~1,980px tall with overflow: hidden, putting Reset View, Screenshot and Zen\n   about 1,300px above the viewport. The control built to reach those three was\n   the one place they could not be reached. Now excludes groups that already have\n   their own surface, and .ctx-menu is capped and scrollable so no future menu\n   can do this again.\n\n2. Zen was a one-way door on a phone. toggleChrome hid #chrome, and every\n   re-entry affordance lives inside it - the / FAB, which is display:none under\n   768px anyway, and a phone has no / key. The only recovery was a page reload.\n   Zen is now a body class, with one exit button mounted as a SIBLING of #chrome\n   so it survives the hide.\n\n3. The peek height existed in three places and two disagreed: an unread\n   --sheet-peek token at 96px, the real PEEK_PX at 112px, and a hardcoded 122px\n   in readout.css silently encoding \"peek + 10\". sheet.ts owns the number and\n   publishes it as the CSS var; the others consume it.","parents":["87e3d67c4dab3bcbbb7b43c27e77f871357c8e62"],"add":82,"del":6,"cadd":82,"cdel":6,"files":8},{"repo":"eureka-co-nevada","hash":"5e94ff82ad7062f2f0320166ac2f69ec5793bf7b","ts":1787180209,"wall":"2026-08-19T18:56","msg":"fix(map): every claim filing date displayed one day early in Nevada","body":"fields.config.ts produces every value the operator reads in the inspector and had\nno tests. Two real defects, both now red-then-green:\n\n- new Date('2026-08-19') parses as UTC midnight, and toLocaleDateString then\n  formatted it in local time - so anywhere west of Greenwich the previous day was\n  displayed. A New Year's Day filing rendered as \"Dec 31, 2025\". These are\n  calendar dates with no time component, so they are now formatted with\n  timeZone: 'UTC', and a test pins the output across four timezones.\n\n- The absent-value guard checked null, '' and the string 'null' but not\n  undefined. PMTiles features routinely omit fields, so the attribute table\n  rendered the literal word \"undefined\". NaN printed as \"NaN\" for the same\n  reason; both are now absent. Zero and false still render - they are data.\n\nAlso typed the three exported functions, which were implicit-any and only\ncompiled because tsconfig disables noImplicitAny. That is three fewer errors to\nclear when strictness goes on.","parents":["c3685335d77895e6647cfa0aebcace179a0e6ac9"],"add":110,"del":6,"cadd":110,"cdel":6,"files":2},{"repo":"eureka-co-nevada","hash":"c69dfcdc27e3d6196cb9c0cdc238be66608f7513","ts":1787180893,"wall":"2026-08-19T19:08","msg":"test(map): browser spike — reproduces the .value throw verbatim in real Chromium","body":"The Phase 2a gate, answering three questions before any suite is built on it.\n\n1. Headless Chromium gives MapLibre a usable WebGL2 context:\n   ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero)), SwiftShader\n   driver) / WebGL 2.0 (OpenGL ES 3.0 Chromium). Software rasteriser, adequate.\n\n2. The map draws real pixels - 154 layers, 1081x2202 canvas, a 2.2 MB PNG data\n   URL. That also settles an open question from Phase 1: reading the canvas\n   inside a 'render' event works with preserveDrawingBuffer OFF, so dropping that\n   flag did not break /screenshot.\n\n3. Console errors reach the runner. Deliberately setting fill-opacity on a circle\n   layer - exactly what persisted-state restore used to do - reproduces the\n   historical defect verbatim:\n\n     Cannot read properties of undefined (reading 'value')\n\n   That is the .value TypeError from the handoff, on demand, in a browser. It was\n   root-caused by reading MapLibre's source; this confirms it by observation.\n\n4. A clean load now produces ZERO console errors, which is the assertion the\n   whole approach exists to make. Every Phase 1 fix holds in a real browser.\n\nTwo runners, two directories: vitest owns src/ (node, no DOM), playwright owns\ne2e/. vite.config.ts excludes e2e/ from vitest, which was otherwise collecting\nthe Playwright specs and failing on their imports.\n\n@playwright/test pinned exact at 1.62.1. 71 unit tests + 4 browser tests pass.","parents":["5e94ff82ad7062f2f0320166ac2f69ec5793bf7b"],"add":213,"del":2,"cadd":143,"cdel":0,"files":6},{"repo":"eureka-co-nevada","hash":"833a8496c83f0275aa3f4dfbaa1cb0993041107d","ts":1787181480,"wall":"2026-08-19T19:18","msg":"test(map): full strict, the build gates on tests, and a browser suite that bites","body":"Phase 2. Phase 1 fixed bugs; this stops them coming back.\n\nTHE SUITE. e2e/smoke.spec.ts exercises the app the way a person does — every tab\nin the sheet lip, a layer toggle, the overflow menu, Zen and back out, and a\nreload that replays persisted state — asserting the console stays clean\nthroughout. Plus two harness proofs, so a failure says whether the app broke or\nthe harness did. Verified it bites: reverting the paintProps fix turns the\nrestore test red, and restoring it turns it green.\n\nSTRICTNESS. tsconfig claimed strictness had to be ratcheted up gradually with\nstrictNullChecks \"last\" as the hard step. Measured: strictNullChecks was 2 errors\nand full strict was 26 — and 24 of those were one shape, TS7053, config lookup\ntables typed as bare object literals being indexed by a dynamic string key. They\nneeded a Record<> annotation, not type surgery. strict, noUnusedLocals and\nnoUnusedParameters are all on now, at zero errors. noUnusedParameters found one\ndead argument in buildNavList.\n\nTHE GATE. `npm run build` was `tsc --noEmit && vite build` — it never ran the\ntests. It now runs vitest between them, and I confirmed a regression exits 1\nrather than shipping.\n\nA TEST THAT DID NOT BITE, CAUGHT BY TRYING. Proving the build gate, I mutated\nOPACITY_PROPS.circle to 'fill-opacity' — the original defect — and all 71 unit\ntests stayed green. My own paintProps test only checked config->MapLibre type\nmapping, never that a circle layer's opacity property is a CIRCLE property. That\nis precisely the \"test that cannot fail\" the audit criticised, written by the\nperson who criticised it.\n\nFixed with an independent oracle: MapLibre's style spec publishes, for every\nlayer type, the paint properties that type actually has. The table is now checked\nagainst that rather than against itself. The same mutation now fails with\n\"opacity: 'fill-opacity' is not a paint property of a 'circle' layer\".\n\n72 unit tests, 7 browser tests, typecheck clean under full strict.","parents":["c69dfcdc27e3d6196cb9c0cdc238be66608f7513"],"add":230,"del":119,"cadd":221,"cdel":112,"files":12}],"strata":{"alchemo-sigilism":[],"azura-land":[["2026-Q3",1542]],"azura-terraforming":[["2026-Q1",277924],["2026-Q3",110]],"azura-website":[["2026-Q3",3650]],"azurak-language":[["2026-Q1",215]],"azuran-knowledge-ark":[["2026-Q1",11055]],"bioflash":[["2023-Q3",176]],"cell":[["2026-Q1",5748]],"code-forge":[["2026-Q3",8079]],"composite-organism":[["2026-Q1",116]],"deck-of-cards":[["2015-Q3",4423],["2015-Q4",102],["2016-Q1",4],["2017-Q1",4],["2017-Q2",410],["2017-Q3",148],["2019-Q2",17],["2019-Q3",41],["2020-Q1",6]],"dying-earth":[["2026-Q1",1263]],"dynamic":[["2026-Q2",9207]],"elemental":[["2026-Q2",180327]],"emoji_wall":[["2023-Q3",674]],"eureka-co-nevada":[["2026-Q1",52824],["2026-Q2",1120],["2026-Q3",640]],"external-organelle-project":[["2026-Q1",3796]],"facedancer":[["2026-Q2",1087]],"form-template":[["2021-Q4",169]],"forms":[["2026-Q2",365726]],"gerald-herald":[["2026-Q1",95]],"glyph3d":[["2026-Q1",1689]],"glyphic":[["2026-Q1",1197]],"goat_management_app":[["2023-Q3",1]],"good-news":[["2023-Q3",8680]],"groundwork":[["2026-Q1",167249]],"heloo-wald":[["2021-Q3",3]],"hex-tessellation":[["2026-Q1",3097]],"hexa":[["2026-Q3",35691]],"hexquest":[],"holocene":[["2026-Q3",5020]],"infra":[["2026-Q3",1080]],"iris":[["2026-Q1",2920]],"learning-area":[["2016-Q1",4065],["2016-Q2",10277],["2016-Q3",4262],["2016-Q4",13904],["2017-Q1",5284],["2017-Q2",3596],["2017-Q3",834],["2017-Q4",68],["2018-Q1",1028],["2018-Q2",1305],["2018-Q3",764],["2018-Q4",1161],["2019-Q1",696],["2019-Q2",235],["2019-Q3",46],["2019-Q4",3450],["2020-Q1",6929],["2020-Q2",2679],["2020-Q3",1663],["2020-Q4",71],["2021-Q1",64],["2021-Q2",120],["2021-Q3",6]],"major-tims-ground-control":[["2026-Q2",5567],["2026-Q3",1661]],"margin":[["2026-Q1",139125]],"mesnada":[["2026-Q1",20568],["2026-Q3",20687]],"meso-cli":[["2026-Q1",2966]],"metabolic":[["2026-Q2",9578]],"musico":[["2026-Q1",9699]],"mycelial-network":[["2026-Q1",1639]],"new-belen-game":[["2023-Q3",6],["2026-Q1",13941]],"new-church-game":[["2023-Q3",8962]],"operations":[["2026-Q1",29542],["2026-Q2",5733],["2026-Q3",1538]],"ops26-04p2a":[["2026-Q1",363]],"opsin":[["2026-Q2",2999]],"persian-gulf-theater":[["2026-Q1",4949]],"plenum":[["2026-Q2",2442]],"program-x19":[["2026-Q1",134133]],"publications":[["2026-Q1",503]],"puppet":[["2026-Q2",3047]],"reflex":[["2026-Q1",16208]],"researcher-graph":[["2026-Q1",1557]],"robotics":[],"rowbots":[["2026-Q1",146]],"seandruh":[["2023-Q3",23709]],"soma":[["2026-Q1",2786]],"somaphore":[["2026-Q1",21909]],"symbiont-gis":[["2026-Q1",163100]],"symbiont-systems":[["2026-Q1",6895]],"symbiont.systems":[["2026-Q1",14558],["2026-Q2",8883],["2026-Q3",165]],"symbiontic-dialogues":[["2026-Q1",898]],"synthpen":[["2023-Q3",315]],"techbiont-framework":[["2026-Q1",27093]],"the-azuran":[["2026-Q1",1]],"the-azuran.github.io":[["2021-Q4",383]],"trishsays":[["2026-Q1",3935]],"unified-ai":[["2026-Q1",9502]],"web-scrapper":[["2021-Q4",2]],"wheel-of-the-heavens":[["2026-Q2",187911],["2026-Q3",206]],"world":[["2026-Q2",3692]]},"strata_code":{"alchemo-sigilism":[],"azura-land":[["2026-Q3",1532]],"azura-terraforming":[["2026-Q1",11053],["2026-Q3",110]],"azura-website":[["2026-Q3",2771]],"azurak-language":[["2026-Q1",215]],"azuran-knowledge-ark":[["2026-Q1",10389]],"bioflash":[["2023-Q3",173]],"cell":[["2026-Q1",5409]],"code-forge":[["2026-Q3",8075]],"composite-organism":[["2026-Q1",116]],"deck-of-cards":[["2015-Q3",2712],["2015-Q4",70],["2016-Q1",4],["2017-Q1",3],["2017-Q2",407],["2017-Q3",148],["2019-Q2",17],["2019-Q3",31],["2020-Q1",6]],"dying-earth":[["2026-Q1",1263]],"dynamic":[["2026-Q2",9048]],"elemental":[["2026-Q2",19856]],"emoji_wall":[],"eureka-co-nevada":[["2026-Q1",14646],["2026-Q2",685],["2026-Q3",640]],"external-organelle-project":[["2026-Q1",3770]],"facedancer":[["2026-Q2",343]],"form-template":[["2021-Q4",169]],"forms":[["2026-Q2",40183]],"gerald-herald":[["2026-Q1",95]],"glyph3d":[["2026-Q1",1684]],"glyphic":[["2026-Q1",1197]],"goat_management_app":[],"good-news":[["2023-Q3",7503]],"groundwork":[["2026-Q1",28590]],"heloo-wald":[["2021-Q3",3]],"hex-tessellation":[["2026-Q1",3088]],"hexa":[["2026-Q3",30865]],"hexquest":[],"holocene":[["2026-Q3",3679]],"infra":[["2026-Q3",655]],"iris":[["2026-Q1",1764]],"learning-area":[["2016-Q1",3400],["2016-Q2",8645],["2016-Q3",4190],["2016-Q4",13776],["2017-Q1",5048],["2017-Q2",3596],["2017-Q3",834],["2017-Q4",68],["2018-Q1",1023],["2018-Q2",1304],["2018-Q3",762],["2018-Q4",1152],["2019-Q1",694],["2019-Q2",234],["2019-Q3",46],["2019-Q4",3427],["2020-Q1",6874],["2020-Q2",2678],["2020-Q3",1663],["2020-Q4",71],["2021-Q1",64],["2021-Q2",120],["2021-Q3",6]],"major-tims-ground-control":[["2026-Q2",4277],["2026-Q3",977]],"margin":[["2026-Q1",126008]],"mesnada":[["2026-Q1",17894],["2026-Q3",19695]],"meso-cli":[["2026-Q1",2966]],"metabolic":[["2026-Q2",9571]],"musico":[["2026-Q1",4999]],"mycelial-network":[["2026-Q1",1085]],"new-belen-game":[["2023-Q3",4],["2026-Q1",13797]],"new-church-game":[["2023-Q3",7761]],"operations":[["2026-Q1",25429],["2026-Q2",5732],["2026-Q3",1529]],"ops26-04p2a":[["2026-Q1",363]],"opsin":[["2026-Q2",2499]],"persian-gulf-theater":[["2026-Q1",4949]],"plenum":[["2026-Q2",1327]],"program-x19":[["2026-Q1",121341]],"publications":[["2026-Q1",447]],"puppet":[["2026-Q2",2052]],"reflex":[["2026-Q1",15515]],"researcher-graph":[["2026-Q1",1548]],"robotics":[],"rowbots":[["2026-Q1",146]],"seandruh":[["2023-Q3",7634]],"soma":[["2026-Q1",2786]],"somaphore":[["2026-Q1",14984]],"symbiont-gis":[["2026-Q1",24441]],"symbiont-systems":[["2026-Q1",3976]],"symbiont.systems":[["2026-Q1",14531],["2026-Q2",7671],["2026-Q3",165]],"symbiontic-dialogues":[["2026-Q1",898]],"synthpen":[["2023-Q3",188]],"techbiont-framework":[["2026-Q1",26783]],"the-azuran":[["2026-Q1",1]],"the-azuran.github.io":[["2021-Q4",383]],"trishsays":[["2026-Q1",2198]],"unified-ai":[["2026-Q1",8566]],"web-scrapper":[],"wheel-of-the-heavens":[["2026-Q2",15070],["2026-Q3",206]],"world":[["2026-Q2",2697]]},"rhythm":[[16,8,6,2,3,3,0,2,1,3,10,22,14,13,16,27,24,24,10,16,39,22,35,22],[16,4,2,0,0,2,7,4,18,17,23,41,18,32,21,18,16,12,21,16,18,24,23,8],[12,4,0,4,4,0,3,10,13,14,26,32,15,13,47,13,34,25,13,14,25,23,18,15],[11,4,3,1,0,1,1,6,12,11,24,29,32,34,32,17,24,42,40,39,32,30,30,20],[16,17,5,1,1,0,5,4,30,18,17,32,25,33,26,23,21,42,38,33,23,37,23,22],[7,5,5,2,7,1,1,0,11,10,11,13,24,38,23,29,35,36,34,23,17,16,20,15],[11,11,9,6,2,3,4,5,12,12,21,17,21,17,5,23,22,27,17,11,7,15,24,15]]}