|
6501
|
That one macropad by @NotJaxon76 | Stardance
|
NotJaxon76
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: That one macropad by @NotJaxon76 | Stardanc Title: That one macropad by @NotJaxon76 | Stardance...
|
1793253050.6276047
|
1793857850.6276047
|
|
6502
|
My awesome macropad! by @Bekir | Stardance
|
Bekir
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @Bekir | Stardance
|
1793156091.8141823
|
1793760891.8141823
|
|
6503
|
amu by @Amu | Stardance
|
Amu
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: amu by @Amu | Stardance
|
1793198994.5943267
|
1793803794.5943267
|
|
6504
|
Spesia.it by @gianluca_morello | Stardance
|
gianluca_morello
|
0
|
1.55
|
0
|
[]
|
[{"post_id": 2093, "ts": "2026 [{"post_id": 2093, "ts": "2026-06-04T12:51:28Z", "hours": 1.55, "text": "Created Spesia monorepo and scaffolded the backend (Express + Prisma/Postgres), configured Redis cache and reverse proxy on my Proxmox host, and implemented basic auth + health/profile endpoints. Performed smoke tests to verify the API is reachable and responding."}]...
|
Title: Spesia.it by @gianluca_morello | Stardance
Title: Spesia.it by @gianluca_morello | Stardance
Devlogs:
Created Spesia monorepo and scaffolded the backend (Express + Prisma/Postgres), configured Redis cache and reverse proxy on my Proxmox host, and implemented basic auth + health/profile endpoints. Performed smoke tests to verify the API is reachable and responding....
|
1793170461.4666672
|
1793775261.4666672
|
|
6505
|
System dev logs, drafts by @SamTheArchitect | Star System dev logs, drafts by @SamTheArchitect | Stardance...
|
SamTheArchitect
|
0
|
107.05
|
0
|
[]
|
[{"post_id": 34618, "ts": "202 [{"post_id": 34618, "ts": "2026-07-25T14:27:31Z", "hours": 12.6883, "text": "Workflow Closure & Collapse orchestrator This feature ensures the git commit history remains clean from wips, and the closure when the development of a requirement is finished remains frictionless by automating git operations such as path finding, worktree and branch deletion. Leaving the workspace clean and ready to restart the workflow again for a new update or extra feature. How this engine works Once the builder has complete the implementation, perform a final commit with all changes implemented and staged When the builder runs the command collapse within the worktree to finish the workflow, Then the engine should: Merge the final commit to the main branch The implementation of the requirement wips are preserved in the final commit squash. The history has only one commit with the wip changes The merge is complete successfully Delete the worktree & branch once the commit is present in the main branch to ensure no data is lost and the req name is availability for future implementations Unlink the symlink connection of the markdown editor for the specific docs folder and link to the main docs tree The engine in action"}, {"post_id": 29472, "ts": "2026-07-16T13:23:05Z", "hours": 11.5917, "text": "Git Wortree Set Up & Spawn Orchestrator New functionalities The spawn command is now connected to the orchestrator in the package.json so that it can later be publish in npm and make it fully global accessible in the developer system by using the -g flag Config changes memory: Every time the system changes the system-config.json the changes are automatically staged and commit so that they are present in the new worktree Testing Created two integration automated test using jest that stress test the spawn engine under different scenarios and flags, implement a cool ghost typist so that no questions arise why testing, since those are handle by the ghost typist and test itself. Performed an e2e test in an isolated enviroment within my computer, finding some bugs and fixing them properly. (The video shows the e2e test in action) Fixes The system faced a config path mismatch when the command was trigger when the worktree was outside of a prefix folder and then moved to it, making the config file ENOENT . e2e test e2e spawn engine in action Create a folder with the prefix if not previously created and move the main worktree dir and other worktrees present there Handle the config-system.json presence if not handle its creation Create a new worktree with the artifact in lowercase as name and branch to work within the folder with the project identifier prefix Connect the docs of the new worktree to the folder in the markdown editor Open a VS code instance"}, {"post_id": 27206, "ts": "2026-07-12T15:48:41Z", "hours": 10.3403, "text": "Git Wortree Set Up & Spawn Orchestrator I develop the initial part of the system requirement of a workflow orchestrator that interacts with git and the system files to create a frictionless, fast and intuitive experience when bringing ideas to live. Creating and isolated environment that ensures the change log remains pristine and connected to a specific Requirement artifact and its context and market value. Command and flags The command that triggers the first part of the orchestrator is spawn with a string argument that will be the name of the requirement to implement e.g: req023 . It can be called with different flags to modify the behavior of the orchestrator and achieve different functionalities: --symlink or -s --code or -c Flag Combinations and what it achieves Scenario A: Git Tree Workflow & Symlink Connection To The Markdown Editor Update Only trigger the command with the -s flag: Creates a folder with the prefix if not previously created and move the main worktree dir and other worktrees present there Create a new worktree with the artifact in lowercase as name and branch to work within the folder with the project identifier prefix Connect the docs of the new worktree to the folder in the markdown editor Scenario B: Git Tree Workflow Intialization enhance functionality for VSCode instance & Symlink Connection To The Markdown Editor Update Trigger the command with the -s & -c flag: Create a folder with the prefix if not previously created and move the main worktree dir and other worktrees present there Create a new worktree with the artifact in lowercase as name and branch to work within the folder with the project identifier prefix Connect the docs of the new worktree to the folder in the markdown editor Open a VS code instance Scenario C: Git Tree Workflow Initialization enhance functionality for VSCode instance Only trigger the command with the -c flag: Create a folder with the prefix if not previously created and move the main worktree dir and other worktrees present there Create a new worktree with the artifact in lowercase as name and branch to work within the folder with the project identifier prefix Open a VS code instance Scenario D: Default only worktree creation folder set up Trigger the command without flags: Create a folder with the prefix if not previously created and move the main worktree dir and other worktrees present there Create a new worktree with the artifact in lowercase as name and branch to work within the folder with the project identifier prefix Challenges To handle the underlying mechanism of git such as the way it manages the links from the main worktree to its linked ones, how to move them without breaking the linkage and how to heal the systme once the main woerktree is moved represent a challenge that involve some hours of debugging, logs, investigation and testing to make it properly set up the initial state of the system and continue with the worktree creation."}, {"post_id": 25089, "ts": "2026-07-09T02:19:03Z", "hours": 20.9244, "text": "Git staging workflow & pristine version control engineering Context of the problem Now that the system is getting to its final shape one of the most important tools it should integrate is git, but how to do it properly to ensure a pristine commit history to understand the project, its progression, what has been implemented and how the project as evolved over time. Also easily look backwards for quickly identification of the implementation details we are looking for. Nor in a messy uncontextualized way but rather having clear context on what are those changes related to, which requisite is being implemented, refactor or updated Managing docs and code within the same repository carries the risk of “micro commit bloat” only small work and temporary struggle that doesn’t carry a significant weight when backward looking in the future fill the commit history. When reviewing you don’t what to see hundreds of micro commits that doesn’t actually inform of a complete feature. I’ve analize the possible architectural decision including: Workspace squashing and isolated staging of wip commits Git worktrees Clean commit guidelines Clean Room Extraction: 2 branches one for the workspace, containing all the wip messy commits. Edge cases But the one that must be picked is the one that adresses the edge cases: Probable cross device synchronization commits that should not be part of the final commit history. Another key edge case is the synchronization of the cloud repository and the conflict it might cause with the overall sync and the atomic commit history. Handling two REQs that modify the same file in different lines Complete vision of the doc files from the markdown renderer The decision The final decision combines some of the previously mention alternatives and discards others but to make it short the solution is to use worktrees, one per requirement implementation and then clean it out, but this also comes with the frictions of having to update the symlink connection to the markdown editor of preference. Visually explained the architecture is in a digrama below Benefits Semantic commits The repository becomes self-documenting. Generating >“release notes”, “architectural change log” or revising >the project evolution becomes a mathematical query: git log --grep=\"^type\" Structural Bracket Identifier This makes it possible to audit the overall evolution of a >specific requirement implementation or architectural >decision over the project life by using git log --grep=\"[ID]\" . Ease the debugging process and version control >navigation. Git-Tree Concurrent file work history collapse solution: by using >the git-tree the edge case of losing track of multi line >edits that belong to different REQs in the same file is >handled gracefully by the work tree capabilities Dashboard blindness solution: Eliminates dashboard >blindness by using the symlink connection Workflow & the custom Script Finding paths to create symlinks, moving trees to a parent folder so the development can began, the squashing of the commits for a clean history and the merge of wortrees to the main branch migth represent minutes of administrative friction. So the implementation of a script that ease the friction parts of the workflow to ensure the developer never gets out of flow due to administrative stuff is a foundational add on to the system."}, {"post_id": 19990, "ts": "2026-07-01T13:49:00Z", "hours": 41.9653, "text": "Automatic Link Connections Refactor Engine This engine ensures there is no need for manually refactoring of links that connect the related files across the project. Simply imagining updating hundreds of broken links when a name or folder is change, that is not acceptable. Also helps reducing the friction when creating connections like thinking the relative path to the file. This way is avoid the debt of having broken links across the traceability system and friction of connecting files is reduce to 0. Implementation Details File mapping Engineer FileSelectionHelper.js which uses a recursive algorithm that serves as a helper method for data collection using node for file path extraction that works as follows: Extracts the root folder directories and all files paths and names storing them in a data structure. Stores them separately creating a distinction between files and folders. Recursively calls itself to scan the directories stored but before deletes the previously scan directory to ensure the algorithm doesn’t fall in an infinite loop. Stops once there are no more directories to scan. Connections Mapping Implement a helper function PathExtractionHelper.js that will take the found files by FileSelectionHelper.js build a map of the artifacts and the files that mention a connection to them. Algorithm behavior: Loop over all the files of the project Reads the file data an check for a connection mention @trace REQ-001 @ If that artifact exist as a key in the data structure it will append the file, and ensure the already stored connections are not lost Otherwise it will append the first file and create the key Traceability Pipeline Class To ensure clean code, concern separation and functionality encapsulation I develop a class that contains methods that make possible the traceability engine. Methods capabilities: Find artifact path in the project folder Classify artifact connections in different areas Build a markdown table with those connections classification and its relative path to the current artifact ready to navigate by a click from any markdown rendering engine (this ensures the builder can easily open and navigate through the artifact related files, probably implementing what the artifact states) Write the markdown table to a specific artifact.md file Engine execution Once the separated functionalities are encapsulated in its methods and helpers the engine must be orchestrated to provided the expected behavior for this the AutoLinkRefactorExecutionThread.js ensures the execution works as intended leveraging the tools available to ensure the acceptance criteria expected outcome is fulfilled. Testing To ensure system integrity this implementation includes 2 test suits: 6 unit tests for the standalone methods and helpers 1 integration test that ensures that the orchestration of the standalone pieces provide the expected output."}, {"post_id": 11268, "ts": "2026-06-18T13:00:02Z", "hours": 9.5367, "text": "CORE FEATURES Engineer the requirements structure & artifacts including: Kanban Board: How data can be accessed from the requisite Kanban board to increase productivity and maintain a wip (work in progress) of one at the time while visualizing the status and priority of each requisite. Artifacts: Create templates for each of the requisite note artifacts: User Stories, acceptance criteria, Analytical breakdown (Operational procedure to guide problem solving ). Traceability properties: Define the yaml properties for the REQ artifact to ensure traceability form the kanban and the Maps of content dashboard. Define a symlink connection usage from the markdown editor to the project folder with the git system Engineer the architectural decision records structure and artifacts including: Kanban Board: How data can be accessed from the ADRs Kanban board visualize decisions that are pending, approved or depracated Artifacts: Create templates for each of the requisite note artifacts Traceability properties: Define the yaml properties for the ADR artifact to ensure traceability from the kanban and the Maps of content dashboard. Created a central MOC dashboard that maps automatically ADRs, REQs and Vertical slicing diagrams. Includes also an architectural diagram that gives a big picture of how the system behaves."}]...
|
Title: System dev logs, drafts by @SamTheArchitect Title: System dev logs, drafts by @SamTheArchitect | Stardance
Devlogs:
CORE FEATURES Engineer the requirements structure & artifacts including: Kanban Board: How data can be accessed from the requisite Kanban board to increase productivity and maintain a wip (work in progress) of one at the time while visualizing the status and priority of each requisite. Artifacts: Create templates for each of the requisite note artifacts: User Stories, acceptance criteria, Analytical breakdown (Operational procedure to guide problem solving ). Traceability properties: Define the yaml properties for the REQ artifact to ensure traceability form the kanban and the Maps of content dashboard. Define a symlink connection usage from the markdown editor to the project folder with the git system Engineer the architectural decision records structure and artifacts including: Kanban Board: How data can be accessed from the ADRs Kanban board visualize decisions that are pending, approved or depracated Artifacts: Create templates for each of the requisite note artifacts Traceability properties: Define the yaml properties for the ADR artifact to ensure traceability from the kanban and the Maps of content dashboard. Created a central MOC dashboard that maps automatically ADRs, REQs and Vertical slicing diagrams. Includes also an architectural diagram that gives a big picture of how the system behaves.
Automatic Link Connections Refactor Engine This engine ensures there is no need for manually refactoring of links that connect the related files across the project. Simply imagining updating hundreds of broken links when a name or folder is change, that is not acceptable. Also helps reducing the friction when creating connections like thinking the relative path to the file. This way is avoid the debt of having broken links across the traceability system and friction of connecting files is reduce to 0. Implementation Details File mapping Engineer FileSelectionHelper.js which uses a recursive algorithm that serves as a helper method for data collection using node for file path extraction that works as follows: Extracts the root folder directories and all files paths and names storing them in a data structure. Stores them separately creating a distinction between files and folders. Recursively calls itself to scan the directories stored but before deletes the previously scan directory to ensure the algorithm doesn’t fall in an infinite loop. Stops once there are no more directories to scan. Connections Mapping Implement a helper function PathExtractionHelper.js that will take the found files by FileSelectionHelper.js build a map of the artifacts and the files that mention a connection to them. Algorithm behavior: Loop over all the files of the project Reads the file data an check for a connection mention @trace REQ-001 @ If that artifact exist as a key in the data structure it will append the file, and ensure the already stored connections are not lost Otherwise it will append the first file and create the key Traceability Pipeline Class To ensure clean code, concern separation and functionality encapsulation I develop a class that contains methods that make possible the traceability engine. Methods capabilities: Find artifact path in the project folder Classify artifact connections in different areas Build a markdown table with those connections classification and its relative path to the current artifact ready to navigate by a click from any markdown rendering engine (this ensures the builder can easily open and navigate through the artifact related files, probably implementing what the artifact states) Write the markdown table to a specific artifact.md file Engine execution Once the separated functionalities are encapsulated in its methods and helpers the engine must be orchestrated to provided the expected behavior for this the AutoLinkRefactorExecutionThread.js ensures the execution works as intended leveraging the tools available to ensure the acceptance criteria expected outcome is fulfilled. Testing To ensure system integrity this implementation includes 2 test suits: 6 unit tests for the standalone methods and helpers 1 integration test that ensures that the orchestration of the standalone pieces provide the expected output.
Git staging workflow & pristine version control engineering Context of the problem Now that the system is getting to its final shape one of the most important tools it should integrate is git, but how to do it properly to ensure a pristine commit history to understand the project, its progression, what has been implemented and how the project as evolved over time. Also easily look backwards for quickly identification of the implementation details we are looking for. Nor in a messy uncontextualized way but rather having clear context on what are those changes related to, which requisite is being implemented, refactor or updated Managing docs and code within the same repository carries the risk of “micro commit bloat” only small work and temporary struggle that doesn’t carry a significant weight when backward looking in the future fill the commit history. When reviewing you don’t what to see hundreds of micro commits that doesn’t actually inform of a complete feature. I’ve analize the possible architectural decision including: Workspace squashing and isolated staging of wip commits Git worktrees Clean commit guidelines Clean Room Extraction: 2 branches one for the workspace, containing all the wip messy commits. Edge cases But the one that must be picked is the one that adresses the edge cases: Probable cross device synchronization commits that should not be part of the final commit history. Another key edge case is the synchronization of the cloud repository and the conflict it might cause with the overall sync and the atomic commit history. Handling two REQs that modify the same file in different lines Complete vision of the doc files from the markdown renderer The decision The final decision combines some of the previously mention alternatives and discards others but to make it short the solution is to use worktrees, one per requirement implementation and then clean it out, but this also comes with the frictions of having to update the symlink connection to the markdown editor of preference. Visually explained the architecture is in a digrama below Benefits Semantic commits The repository becomes self-documenting. Generating >“release notes”, “architectural change log” or revising >the project evolution becomes a mathematical query: git log --grep="^type" Structural Bracket Identifier This makes it possible to audit the overall evolution of a >specific requirement implementation or architectural >decision over the project life by using git log --grep="[ID]" . Ease the debugging process and version control >navigation. Git-Tree Concurrent file work history collapse solution: by using >the git-tree the edge case of losing track of multi line >edits that belong to different REQs in the same file is >handled gracefully by the work tree capabilities Dashboard blindness solution: Eliminates dashboard >blindness by using the symlink connection Workflow & the custom Script Finding paths to create symlinks, moving trees to a parent folder so the development can began, the squashing of the commits for a clean history and the merge of wortrees to the main branch migth represent minutes of administrative friction. So the implementation of a script that ease the friction parts of the workflow to ensure the developer never gets out of flow due to administrative stuff is a foundational add on to the system.
Git Wortree Set Up & Spawn Orchestrator I develop the initial part of the system requirement of a workflow orchestrator that interacts with git and the system files to create a frictionless, fast and intuitive experience when bringing ideas to live. Creating and isolated environment that ensures the change log remains pristine and connected to a specific Requirement artifact and its context and market value. Command and flags The command that triggers the first part of the orchestrator is spawn with a string argument that will be the name of the requirement to implement e.g: req023 . It can be called with different flags to modify the behavior of the orchestrator and achieve different functionalities: --symlink or -s --code or -c Flag Combinations and what it achieves Scenario A: Git Tree Workflow & Symlink Connection To The Markdown Editor Update Only trigger the command with the -s flag: Creates a folder with the prefix if not previously created and move the main worktree dir and other worktrees present there Create a new worktree with the artifact in lowercase as name and branch to work within the folder with the project identifier prefix Connect the docs of the new worktree to the folder in the markdown editor Scenario B: Git Tree Workflow Intialization enhance functionality for VSCode instance & Symlink Connection To The Markdown Editor Update Trigger the command with the -s & -c flag: Create a folder with the prefix if not previously created and move the main worktree dir and other worktrees present there Create a new worktree with the artifact in lowercase as name and branch to work within the folder with the project identifier prefix Connect the docs of the new worktree to the folder in the markdown editor Open a VS code instance Scenario C: Git Tree Workflow Initialization enhance functionality for VSCode instance Only trigger the command with the -c flag: Create a folder with the prefix if not previously created and move the main worktree dir and other worktrees present there Create a new worktree with the artifact in lowercase as name and branch to work within the folder with the project identifier prefix Open a VS code instance Scenario D: Default only worktree creation folder set up Trigger the command without flags: Create a folder with the prefix if not previously created and move the main worktree dir and other worktrees present there Create a new worktree with the artifact in lowercase as name and branch to work within the folder with the project identifier prefix Challenges To handle the underlying mechanism of git such as the way it manages the links from the main worktree to its linked ones, how to move them without breaking the linkage and how to heal the systme once the main woerktree is moved represent a challenge that involve some hours of debugging, logs, investigation and testing to make it properly set up the initial state of the system and continue with the worktree creation.
Git Wortree Set Up & Spawn Orchestrator New functionalities The spawn command is now connected to the orchestrator in the package.json so that it can later be publish in npm and make it fully global accessible in the developer system by using the -g flag Config changes memory: Every time the system changes the system-config.json the changes are automatically staged and commit so that they are present in the new worktree Testing Created two integration automated test using jest that stress test the spawn engine under different scenarios and flags, implement a cool ghost typist so that no questions arise why testing, since those are handle by the ghost typist and test itself. Performed an e2e test in an isolated enviroment within my computer, finding some bugs and fixing them properly. (The video shows the e2e test in action) Fixes The system faced a config path mismatch when the command was trigger when the worktree was outside of a prefix folder and then moved to it, making the config file ENOENT . e2e test e2e spawn engine in action Create a folder with the prefix if not previously created and move the main worktree dir and other worktrees present there Handle the config-system.json presence if not handle its creation Create a new worktree with the artifact in lowercase as name and branch to work within the folder with the project identifier prefix Connect the docs of the new worktree to the folder in the markdown editor Open a VS code instance
Workflow Closure & Collapse orchestrator This feature ensures the git commit history remains clean from wips, and the closure when the development of a requirement is finished remains frictionless by automating git operations such as path finding, worktree and branch deletion. Leaving the workspace clean and ready to restart the workflow again for a new update or extra feature. How this engine works Once the builder has complete the implementation, perform a final commit with all changes implemented and staged When the builder runs the command collapse within the worktree to finish the workflow, Then the engine should: Merge the final commit to the main branch The implementation of the requirement wips are preserved in the final commit squash. The history has only one commit with the wip changes The merge is complete successfully Delete the worktree & branch once the commit is present in the main branch to ensure no data is lost and the req name is availability for future implementations Unlink the symlink connection of the markdown editor for the specific docs folder and link to the main docs tree The engine in action...
|
1793256970.6733804
|
1793861770.6733804
|
|
6506
|
Playback Control MacroPad by @Landon | Stardance
|
Landon
|
0
|
3.49
|
0
|
[]
|
[{"post_id": 4587, "ts": "2026 [{"post_id": 4587, "ts": "2026-06-07T22:39:24Z", "hours": 2.3142, "text": "finalizing PCB and some basic cad did a lil bit or drawing, and a bit more routing. today just made some tlittle tweaks, added bolt holes, changed pcb size and rewired. started with some cad and making a case for my macro/hackpad"}, {"post_id": 1864, "ts": "2026-06-04T02:26:10Z", "hours": 1.1781, "text": "#Re learning kicad# today i spent way too long importing footprints, looking for footprints, and everything in between, im happy to have come up with a semi finished product that would work at the stage its in. next time im going to find a fitting rotary encoder and inegrate it! hopefully i can get a screen on this little guy too"}]...
|
Title: Playback Control MacroPad by @Landon | Star Title: Playback Control MacroPad by @Landon | Stardance
Devlogs:
#Re learning kicad# today i spent way too long importing footprints, looking for footprints, and everything in between, im happy to have come up with a semi finished product that would work at the stage its in. next time im going to find a fitting rotary encoder and inegrate it! hopefully i can get a screen on this little guy too
finalizing PCB and some basic cad did a lil bit or drawing, and a bit more routing. today just made some tlittle tweaks, added bolt holes, changed pcb size and rewired. started with some cad and making a case for my macro/hackpad...
|
1792691677.9818797
|
1793296477.9818797
|
|
6507
|
portfolio by @ok | Stardance
|
ok
|
1
|
27.0
|
219
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-28T01:12:34Z", "hours": 27.0, "multiplier": 8.19, "payout": 219, "blessing": "neutral", "text": "I made a personal website that shows both my coding and photography! the photos are loaded in with JSON, to make my future self happy (thats a first). The projects have actual pieces of code from my projects, with breadcrumbs (thats what bootstrap calls them), to what file they’re from, and tooltips by the breadcrumb from where they are used. for the about me and contact me section, I made sure to have it dynamically change based on where you are coming from, with shoutouts to organizations that I support, and also making sure to change the logo IF it requires being changed. contact me form has a list of hashed blocked emails (i.e [email protected] ). Also, made sure that omkanabar.com/contact redirects you to the contact section of my main page. made sure there’s a landing page, after you submit. thanks for reading this! -ok", "repo": "https://github.com/om-kanabar/om-kanabar.github.io", "demo": "https://omkanabar.com"}]...
|
[{"post_id": 17302, "ts": "202 [{"post_id": 17302, "ts": "2026-06-28T01:02:40Z", "hours": 4.5217, "text": "final devlog finished everything, finally contact form added contact form that dynamically changed colors, also contact.html redirects you to the contact form. Also, if there is a param that states from=randomPlace, if you submit my form, it will tell me which place you got to my website, (this is mainly used for ease of use for me). oh also added some blocked emails, try using [email protected] , and it’ll show a message that is fullscreen. i don’t like spammers. about me i made a simple about me section, that shows a bit about my interests, and it shout outs some organizations that i support. both contacte form and about me dynamically change colors depending on what side you clicked (the wbez logo also changes). 404 made 404 page more like the rest of my website and less like the first version of my site (i still included the same quote). thanks I added a landing page once you submitted my form. very simple. code made this project into v.3.0.0-stable photography added nothing thank you to everyone who has seen any of my devlogs, and has supported me! -ok btw i wish i could add more photos"}, {"post_id": 15751, "ts": "2026-06-25T17:00:06Z", "hours": 3.8819, "text": "Finished the code section! I finished the code section for my website, finally! Photography I rearranged the photos from the “scene” thing into just one continuous thing bcs the scene for me would’ve been too hard for me to design UX and UI around. Also added back scrolling using arrow keys! Code Finished everything including projects! This took alot of time and alot of debugging. The code backgrounds are actual text styles with CSS. EVERYTHING made the website more responsive! -ok"}, {"post_id": 14109, "ts": "2026-06-23T02:47:53Z", "hours": 6.05, "text": "this is the longest devlog that ill prob have on this project everything made the back btn a chameleon nav so it doesn’t get in the way while scrolling down photography made transitions between different scenes, also made it JSON based, so i don’t have to do repetitive html. (screenshot of json is there) btns for scrolling don’t work, ill fix that later code i finally started working on this after spending so much time on photography I added alot of things, words dont’ do it justice see pictures. so I made actual code from the projects the background for each section and its ACTUAL TEXT styled with css (it matches my vs code exactly), I also added links to the document in a breadcrumb at the top. i need to devlong more often trust ill do it -ok"}, {"post_id": 12933, "ts": "2026-06-21T05:17:04Z", "hours": 3.6736, "text": "Made it so that JSON controls the photos and JS inserts them dynaimically, this was quite a challange for me since i didn’t know JSON syntax and how to parse it at all."}, {"post_id": 4689, "ts": "2026-06-08T03:01:41Z", "hours": 1.7144, "text": "Made it so you can scroll with arrow keys, also added scroll buttons, obv clean and minimal to avoid taking attention from my photography. Also I removed the copyright notice, ill add it at the bottom of the page later. Also I cleaned up my repo and folder from a bunch of old files from my old website (ewww) git still has them but its now better. i also just went on a photography trip to downtown chicago, maybe ill add a photo? but now I kinda need to work on the code section because its feeling quite unloved right now."}, {"post_id": 3314, "ts": "2026-06-06T05:36:52Z", "hours": 0.6758, "text": "finished adding all my photos! finally! I rearranged some of the photos so it made more sense and also I made it so that lansdcape orientated photos instead of multiple lines of Shutter speed, apurture and ISO its one line so that everything fits better on the screen. Tommorow/today imma start working on the code section or work on an about me section which will lead to a contact section"}, {"post_id": 2589, "ts": "2026-06-05T05:43:23Z", "hours": 2.1675, "text": "Added more photos! Fixed the scrolling because the old one while it looked cool was WAAY too complex to be used at all on other computers. Also I made it so that when you hover over the photo details their opacity increases."}, {"post_id": 2467, "ts": "2026-06-04T23:43:43Z", "hours": 1.4242, "text": "Added the first photo in my portfolio to the website! I also made sure that a user could see it knowing to scroll down, Im going to add the other photos in my portfolio soon."}, {"post_id": 1895, "ts": "2026-06-04T03:38:54Z", "hours": 2.7667, "text": "I made the introduction section of the website, and finished the main animations. I also added a bit of filler text for the body of each one"}]...
|
Title: portfolio by @ok | Stardance
Devlogs:
I ma Title: portfolio by @ok | Stardance
Devlogs:
I made the introduction section of the website, and finished the main animations. I also added a bit of filler text for the body of each one
Added the first photo in my portfolio to the website! I also made sure that a user could see it knowing to scroll down, Im going to add the other photos in my portfolio soon.
Added more photos! Fixed the scrolling because the old one while it looked cool was WAAY too complex to be used at all on other computers. Also I made it so that when you hover over the photo details their opacity increases.
finished adding all my photos! finally! I rearranged some of the photos so it made more sense and also I made it so that lansdcape orientated photos instead of multiple lines of Shutter speed, apurture and ISO its one line so that everything fits better on the screen. Tommorow/today imma start working on the code section or work on an about me section which will lead to a contact section
Made it so you can scroll with arrow keys, also added scroll buttons, obv clean and minimal to avoid taking attention from my photography. Also I removed the copyright notice, ill add it at the bottom of the page later. Also I cleaned up my repo and folder from a bunch of old files from my old website (ewww) git still has them but its now better. i also just went on a photography trip to downtown chicago, maybe ill add a photo? but now I kinda need to work on the code section because its feeling quite unloved right now.
Made it so that JSON controls the photos and JS inserts them dynaimically, this was quite a challange for me since i didn’t know JSON syntax and how to parse it at all.
this is the longest devlog that ill prob have on this project everything made the back btn a chameleon nav so it doesn’t get in the way while scrolling down photography made transitions between different scenes, also made it JSON based, so i don’t have to do repetitive html. (screenshot of json is there) btns for scrolling don’t work, ill fix that later code i finally started working on this after spending so much time on photography I added alot of things, words dont’ do it justice see pictures. so I made actual code from the projects the background for each section and its ACTUAL TEXT styled with css (it matches my vs code exactly), I also added links to the document in a breadcrumb at the top. i need to devlong more often trust ill do it -ok
Finished the code section! I finished the code section for my website, finally! Photography I rearranged the photos from the “scene” thing into just one continuous thing bcs the scene for me would’ve been too hard for me to design UX and UI around. Also added back scrolling using arrow keys! Code Finished everything including projects! This took alot of time and alot of debugging. The code backgrounds are actual text styles with CSS. EVERYTHING made the website more responsive! -ok
final devlog finished everything, finally contact form added contact form that dynamically changed colors, also contact.html redirects you to the contact form. Also, if there is a param that states from=randomPlace, if you submit my form, it will tell me which place you got to my website, (this is mainly used for ease of use for me). oh also added some blocked emails, try using [email protected] , and it’ll show a message that is fullscreen. i don’t like spammers. about me i made a simple about me section, that shows a bit about my interests, and it shout outs some organizations that i support. both contacte form and about me dynamically change colors depending on what side you clicked (the wbez logo also changes). 404 made 404 page more like the rest of my website and less like the first version of my site (i still included the same quote). thanks I added a landing page once you submitted my form. very simple. code made this project into v.3.0.0-stable photography added nothing thank you to everyone who has seen any of my devlogs, and has supported me! -ok btw i wish i could add more photos
Ships:
I made a personal website that shows both my coding and photography! the photos are loaded in with JSON, to make my future self happy (thats a first). The projects have actual pieces of code from my projects, with breadcrumbs (thats what bootstrap calls them), to what file they’re from, and tooltips by the breadcrumb from where they are used. for the about me and contact me section, I made sure to have it dynamically change based on where you are coming from, with shoutouts to organizations that I support, and also making sure to change the logo IF it requires being changed. contact me form has a list of hashed blocked emails (i.e [email protected] ). Also, made sure that omkanabar.com/contact redirects you to the contact section of my main page. made sure there’s a landing page, after you submit. thanks for reading this! -ok...
|
1793289186.028454
|
1793375586.028454
|
|
6508
|
SkyAware by @andychenweizhao | Stardance
|
andychenweizhao
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: SkyAware by @andychenweizhao | Stardance
|
1793231726.7707505
|
1793836526.7707505
|
|
6509
|
Untitled project by @akaki | Stardance
|
akaki
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Untitled project by @akaki | Stardance
|
1792676914.8484957
|
1793281714.8484957
|
|
6510
|
My awesome macropad! by @HamzaEren | Stardance
|
HamzaEren
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @HamzaEren | Starda Title: My awesome macropad! by @HamzaEren | Stardance...
|
1792752878.1048586
|
1793357678.1048586
|
|
6511
|
My first slack bot! by @Sol75 | Stardance
|
Sol75
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @Sol75 | Stardance
|
1793238470.200646
|
1793843270.200646
|
|
6512
|
My awesome macropad! by @najil_kilayil | Stardance
|
najil_kilayil
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @najil_kilayil | St Title: My awesome macropad! by @najil_kilayil | Stardance...
|
1792939655.09829
|
1793803655.09829
|
|
6513
|
Untitled project by @kaabia_ahmed2009 | Stardance
|
kaabia_ahmed2009
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Untitled project by @kaabia_ahmed2009 | Sta Title: Untitled project by @kaabia_ahmed2009 | Stardance...
|
1793274780.448163
|
1793879580.448163
|
|
6514
|
My first slack bot! by @Lavender | Stardance
|
Lavender
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @Lavender | Stardanc Title: My first slack bot! by @Lavender | Stardance...
|
1792669849.1225653
|
1793274649.1225653
|
|
6515
|
Minecraft weapon mod by @CalebRivera | Stardance
|
CalebRivera
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Minecraft weapon mod by @CalebRivera | Star Title: Minecraft weapon mod by @CalebRivera | Stardance...
|
1792702069.9292827
|
1793306869.9292827
|
|
6516
|
My first slack bot! by @lucy_stiglitz | Stardance
|
lucy_stiglitz
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @lucy_stiglitz | Sta Title: My first slack bot! by @lucy_stiglitz | Stardance...
|
1793181283.0180004
|
1793786083.0180004
|
|
6517
|
swarmtrace by @raviiiibro | Stardance
|
raviiiibro
|
1
|
140.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-07T14:12:02Z", "hours": 140.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "the marketing was challenging and i think now it is ready and i get more suggestion if people will use it and i hope i ccan buy a domain by the star dust", "repo": "https://github.com/ravi3594444/swarmtrace", "demo": "https://swarmtrace.vercel.app/"}]...
|
[{"post_id": 57987, "ts": "202 [{"post_id": 57987, "ts": "2026-08-30T10:07:47Z", "hours": 3.3442, "text": "half work done"}, {"post_id": 45694, "ts": "2026-08-12T10:51:40Z", "hours": 14.5639, "text": "starting work"}, {"post_id": 38796, "ts": "2026-08-01T11:14:26Z", "hours": 10.8114, "text": "today i know there is so much work left on this project then i think i added a floating side bar added some more now features for backend optimization guys working on a i3 sucks please help me to buy an macbook byyy"}, {"post_id": 34749, "ts": "2026-07-25T18:41:00Z", "hours": 9.1911, "text": "adding agent graph this is mvp only i will polish it byee"}, {"post_id": 31855, "ts": "2026-07-20T15:58:43Z", "hours": 8.5708, "text": "added many features like day and night light take a tour and adjust icons sizes to a bit smaller and fixed some backend issues and run many real tests like rag agent and hermes agent and again applied for google search console ——————————————————————————————————— i need to buy a domain but i do not have money i will start marketing after buying domain byee guyss please like"}, {"post_id": 29572, "ts": "2026-07-16T16:32:50Z", "hours": 10.4061, "text": "does a full audit by ai agent found some production bugs working on prd section 1 because it is main it conation python package updtaes because the whole project is up to sdk byee meet in next vlog"}, {"post_id": 27112, "ts": "2026-07-12T11:44:54Z", "hours": 11.8228, "text": "all test are passing"}, {"post_id": 25197, "ts": "2026-07-09T08:46:20Z", "hours": 13.8544, "text": "added new features"}, {"post_id": 20965, "ts": "2026-07-02T18:13:39Z", "hours": 22.3356, "text": "Ahh infinite .tsx bug fixing"}, {"post_id": 12234, "ts": "2026-06-19T23:39:44Z", "hours": 9.5261, "text": "dev vlog#7today i worked on research on my project about similar projects because i cant get a .com domain hi have to buy a .ai domain and i worked on dashboard today because it was so simple then guys please suggest any improvement."}, {"post_id": 9898, "ts": "2026-06-16T11:58:18Z", "hours": 5.4533, "text": "Dev Vlog #6Finally, the landing page work is officially done! The platform is ready for users, and you can check it out here: swarmtrace.vercel.app.Right now, I don’t have the budget to buy a custom domain, so I have set it up on Google Search Console for now. I know that having a domain like swarmtrace.ai would help it perform much better in Google Search, since Google tends to rank subdomains poorly.That being said, the platform is still very much in the building phase. I am already working on adding some exciting new features.Stay tuned, and bye for now!"}, {"post_id": 7404, "ts": "2026-06-12T10:32:32Z", "hours": 8.6239, "text": "finally live on vercel but still in deployment you can check it guys go on swarmtrace.vercel.app"}, {"post_id": 5009, "ts": "2026-06-08T17:33:24Z", "hours": 0.6333, "text": "dev vlog #4 builders just finished the backend work for today / rest work tomorrow i will make the frontend connected to clerk for auth and neon for database . byee👍"}, {"post_id": 4889, "ts": "2026-06-08T13:38:09Z", "hours": 5.7483, "text": "dev vlog 3”What’s up, builders! Today we are fundamentally changing how SwarmTrace works. We’re tearing out the local SQLite restrictions and turning this project into a distributed, multi-tenant AI agent monitoring platform. The goal? Anyone can install our package, drop in an API key, and instantly view their agent’s execution traces on a sleek, hosted Next.js dashboard powered by Clerk and Supabase—without hosting a single thing themselves.” What We’re Solving Today: The “Localhost” Trap: Right now, the FastAPI backend expects to live on the same machine as the SQLite database. If a user runs an agent on their machine, they can’t easily see it on a globally hosted dashboard. Multi-Tenancy: We need to make sure User A never sees User B’s logs. Every single trace must be bound to an organization or user ID. Zero-Infra for the User: The developer using tracely should only have to pip-install it, provide a SWARMTRACE_API_KEY, and let our remote backend handle the rest. 📐 The SaaS Architecture Blueprint Here is how data will flow across the internet from your user’s local python script straight to your Vercel-hosted frontend dashboard: [ User’s Local Machine ] └── Running AI Agent (LangChain/CrewAI/AutoGen) └── Tracely SDK (Decorators) │ ▼ (Async Background HTTP POST /ingest) [ Vercel Serverless / API Gateway ] ─── (Validates SWARMTRACE_API_KEY) │ ▼ (Writes Log Payload) [ Hosted Database: Supabase / Postgres ] └── traces table (Schema: id, user_id, execution_time, trace_payload) ▲ │ (Fetches user-specific traces via Clerk JWT auth) [ Vercel Frontend: Next.js + Clerk ] └── Protected Dashboard View (Only shows rows matching user_id) 🗂️ The Technical Roadmap To pull this off, we have to transform four key elements of your repository: The SDK (tracely/scraper.py & tracer.py) Current: Writes to a local SQLite database via storage.py. SaaS Modification: Introduce a background background-worker thread or async pool. When a trace finishes, it sends an HTTP POST request to https://api.swarmtrace.dev/v1/ingest carrying the payload and an Authorization: Bearer st_live_… header. The Backend Engine (api.py) Current: Reads from local SQLite. SaaS Modification: Drop SQLite. Migrate to a hosted Postgres instance (Supabase is perfect here). Add an /ingest route for incoming agent metrics. Add middleware to validate incoming user requests from the frontend using Clerk JWT tokens. The Authentication Layer (Clerk) Wrap your frontend-next/ layout inside a . Set up a pipeline where a user logs in, generates an “Agent API Key” from their settings dashboard, and pastes that key into their Python .env file. also tracely is maded by me it is the part of swarm trace."}, {"post_id": 3574, "ts": "2026-06-06T15:55:13Z", "hours": 1.6264, "text": "🐝 SwarmTrace DevLog #3 — Wiring the Dashboard to Real Data June 6, 2026 /////////////////////////////////////////////////////// Today was all plumbing. No new features, no design work — just making the two halves of this project actually talk to each other. /////////////////////////////////////////////////////// Where Things Stood I had two things running independently. On one side, the FastAPI server — started it up this morning, it boots clean, the @observe decorator has been collecting real traces into SQLite every time an agent function runs. The data is there. It’s been there. On the other side, the dashboard UI — five pages, looks exactly like the design mockups, dark theme, all the charts and tables and drawers. Finished that yesterday. The problem is they had never spoken to each other. The UI was showing hardcoded numbers I typed in by hand. The API was sitting there with real data and nothing asking for it. The Work Spent today closing that gap. First thing I did was map out what each page actually needs from the backend. Overview needs health stats and an activity feed. Traces needs the full call list. Agents needs a registry of everything that’s been observed. Metrics needs cost and token breakdowns. Settings needs API key management and integration status. Then I went into the API and built those endpoints out one by one. The good news — all the underlying data was already in the database from the decorator. I wasn’t inventing anything, just exposing it in the right shape. The annoying part was that the frontend and backend had grown slightly different vocabularies. The UI expected fields named one way, the API had them named another. Duration in milliseconds vs latency in seconds. function_name vs function. Small things, but they all had to be aligned or every fetch would silently return nothing. CORS was the other thing that caught me — frontend on one port, backend on another, browser refuses to talk between them without the right middleware. Quick fix once I remembered that’s what was happening. The Moment it Clicked Started both servers. Opened the dashboard. Traces page loaded with real function names — execute_task, plan_steps, fetch_data — things I’d actually run this week. Real latencies. Real token counts. Real errors with the actual error messages. Turned on Live Mode. Ran an agent task in a separate terminal. Watched the row appear in the table a couple seconds later. That’s the thing you build toward. What’s Still Hardcoded A few things I haven’t gotten to yet. The Overview stat cards are still static numbers — need to write proper aggregation logic for those. The per-agent token sparklines are placeholder data because I’m storing traces, not time-bucketed token history per agent. Something to fix this week. Tomorrow Get the Overview cards pulling from real DB aggregations. Then figure out deployment — right now this whole thing requires running two local servers which isn’t great for a demo. Want a single public URL before the submission deadline. /////////////////////////////////////////////////////// SwarmTrace — open-source observability for multi-agent AI systems. Built for AMD Hackathon 2026."}, {"post_id": 3416, "ts": "2026-06-06T10:35:54Z", "hours": 3.8981, "text": "🐝 SwarmTrace — Developer Log 1 Project: SwarmTrace Version: 0.1.7 Built for: AMD Hackathon Author: Ravi Kumar What is it? SwarmTrace is a tracing and observability library for LLM-based multi-agent systems — essentially “pytest for AI agents.” The core idea: AI swarms are unpredictable, and existing tools give you no visibility into what happened, where it broke, or whether a prompt change caused a regression. SwarmTrace fixes that. What it does Tracing — wrap any Python function (sync or async) with @observe and every call is automatically recorded: inputs, outputs, latency, token usage, cost, errors, and parent–child relationships between nested agent calls. Token Budget — the @budget decorator tracks cumulative token usage across calls and warns you (or hard-stops) before an agent blows past its limit. Regression Detection — the compare() function runs two prompt versions against the same inputs and uses an LLM to score output similarity, flagging regressions automatically. Tool Attention (ISO Scoring) — implements the technique from arXiv:2604.21816. Instead of injecting all tool schemas into every prompt, it uses FAISS + sentence embeddings to select only the top-k relevant tools per query — reducing tool token overhead by up to 95%. Web Scraping Traces — scraper.scrape(url) wraps Scrapling with full trace recording so scrape calls show up in the call tree like any other agent action. CLI — swarmtrace prints a rich call tree with costs and statuses. swarmtrace-replay replays any individual trace. swarmtrace-export dumps everything to JSON or CSV. Frontend Dashboard A React + TanStack Router frontend visualises live traces from the FastAPI backend: Stat bar — total traces, cumulative tokens, total cost, error count at a glance Call Tree — hierarchical view of parent→child agent calls for a full run Waterfall — timeline view showing which agents ran in parallel vs sequentially Token Chart — per-trace token usage over time Failures page — isolated view of every errored trace with its call chain and error message Detail Drawer — click any trace to inspect its full args, output, latency, and lineage Live Mode — polls the backend every 2 seconds for real-time trace updates Storage All traces land in a local SQLite database (~/.tracely.db) with WAL mode enabled. Auto-purges oldest rows beyond 10,000 to stay bounded. Indexed on timestamp for fast ordered reads. Export to JSON/CSV available via CLI. Stack LayerTechnologyCore libraryPython 3.8+, SQLite, contextvarsRegression LLMClaude Haiku via litaiTool selectionFAISS + sentence-transformersAPIFastAPI + PydanticFrontendReact, TanStack Router/Start, Tailwind, RechartsCLI displayrichPackagingsetuptools, pip-installable Key design decisions contextvars for parent tracking — parent IDs propagate automatically through async and threaded code without any manual wiring. Nested @observe calls build the tree on their own. SQLite over a hosted DB — zero setup for the user; works offline; the auto-purge keeps it from growing unboundedly. Graceful degradation everywhere — if sentence-transformers/FAISS aren’t installed, Tool Attention falls back to returning the first k tools. If tiktoken isn’t installed, budget tracking falls back to len // 4. Storage errors never crash the agent being traced. Current limitations Failures page still uses static demo data instead of the live API swarm_module_0–4.py are five identical placeholder files (to be collapsed into one) No authentication on the API (development only) pyproject.toml is incomplete; setup.py not yet migrated. i have to complete ui first now then i will do other api work because it will be connected to ui because it was originally built a python frame work.byee"}]...
|
Title: swarmtrace by @raviiiibro | Stardance
Devl Title: swarmtrace by @raviiiibro | Stardance
Devlogs:
🐝 SwarmTrace — Developer Log 1 Project: SwarmTrace Version: 0.1.7 Built for: AMD Hackathon Author: Ravi Kumar What is it? SwarmTrace is a tracing and observability library for LLM-based multi-agent systems — essentially “pytest for AI agents.” The core idea: AI swarms are unpredictable, and existing tools give you no visibility into what happened, where it broke, or whether a prompt change caused a regression. SwarmTrace fixes that. What it does Tracing — wrap any Python function (sync or async) with @observe and every call is automatically recorded: inputs, outputs, latency, token usage, cost, errors, and parent–child relationships between nested agent calls. Token Budget — the @budget decorator tracks cumulative token usage across calls and warns you (or hard-stops) before an agent blows past its limit. Regression Detection — the compare() function runs two prompt versions against the same inputs and uses an LLM to score output similarity, flagging regressions automatically. Tool Attention (ISO Scoring) — implements the technique from arXiv:2604.21816. Instead of injecting all tool schemas into every prompt, it uses FAISS + sentence embeddings to select only the top-k relevant tools per query — reducing tool token overhead by up to 95%. Web Scraping Traces — scraper.scrape(url) wraps Scrapling with full trace recording so scrape calls show up in the call tree like any other agent action. CLI — swarmtrace prints a rich call tree with costs and statuses. swarmtrace-replay replays any individual trace. swarmtrace-export dumps everything to JSON or CSV. Frontend Dashboard A React + TanStack Router frontend visualises live traces from the FastAPI backend: Stat bar — total traces, cumulative tokens, total cost, error count at a glance Call Tree — hierarchical view of parent→child agent calls for a full run Waterfall — timeline view showing which agents ran in parallel vs sequentially Token Chart — per-trace token usage over time Failures page — isolated view of every errored trace with its call chain and error message Detail Drawer — click any trace to inspect its full args, output, latency, and lineage Live Mode — polls the backend every 2 seconds for real-time trace updates Storage All traces land in a local SQLite database (~/.tracely.db) with WAL mode enabled. Auto-purges oldest rows beyond 10,000 to stay bounded. Indexed on timestamp for fast ordered reads. Export to JSON/CSV available via CLI. Stack LayerTechnologyCore libraryPython 3.8+, SQLite, contextvarsRegression LLMClaude Haiku via litaiTool selectionFAISS + sentence-transformersAPIFastAPI + PydanticFrontendReact, TanStack Router/Start, Tailwind, RechartsCLI displayrichPackagingsetuptools, pip-installable Key design decisions contextvars for parent tracking — parent IDs propagate automatically through async and threaded code without any manual wiring. Nested @observe calls build the tree on their own. SQLite over a hosted DB — zero setup for the user; works offline; the auto-purge keeps it from growing unboundedly. Graceful degradation everywhere — if sentence-transformers/FAISS aren’t installed, Tool Attention falls back to returning the first k tools. If tiktoken isn’t installed, budget tracking falls back to len // 4. Storage errors never crash the agent being traced. Current limitations Failures page still uses static demo data instead of the live API swarm_module_0–4.py are five identical placeholder files (to be collapsed into one) No authentication on the API (development only) pyproject.toml is incomplete; setup.py not yet migrated. i have to complete ui first now then i will do other api work because it will be connected to ui because it was originally built a python frame work.byee
🐝 SwarmTrace DevLog #3 — Wiring the Dashboard to Real Data June 6, 2026 /////////////////////////////////////////////////////// Today was all plumbing. No new features, no design work — just making the two halves of this project actually talk to each other. /////////////////////////////////////////////////////// Where Things Stood I had two things running independently. On one side, the FastAPI server — started it up this morning, it boots clean, the @observe decorator has been collecting real traces into SQLite every time an agent function runs. The data is there. It’s been there. On the other side, the dashboard UI — five pages, looks exactly like the design mockups, dark theme, all the charts and tables and drawers. Finished that yesterday. The problem is they had never spoken to each other. The UI was showing hardcoded numbers I typed in by hand. The API was sitting there with real data and nothing asking for it. The Work Spent today closing that gap. First thing I did was map out what each page actually needs from the backend. Overview needs health stats and an activity feed. Traces needs the full call list. Agents needs a registry of everything that’s been observed. Metrics needs cost and token breakdowns. Settings needs API key management and integration status. Then I went into the API and built those endpoints out one by one. The good news — all the underlying data was already in the database from the decorator. I wasn’t inventing anything, just exposing it in the right shape. The annoying part was that the frontend and backend had grown slightly different vocabularies. The UI expected fields named one way, the API had them named another. Duration in milliseconds vs latency in seconds. function_name vs function. Small things, but they all had to be aligned or every fetch would silently return nothing. CORS was the other thing that caught me — frontend on one port, backend on another, browser refuses to talk between them without the right middleware. Quick fix once I remembered that’s what was happening. The Moment it Clicked Started both servers. Opened the dashboard. Traces page loaded with real function names — execute_task, plan_steps, fetch_data — things I’d actually run this week. Real latencies. Real token counts. Real errors with the actual error messages. Turned on Live Mode. Ran an agent task in a separate terminal. Watched the row appear in the table a couple seconds later. That’s the thing you build toward. What’s Still Hardcoded A few things I haven’t gotten to yet. The Overview stat cards are still static numbers — need to write proper aggregation logic for those. The per-agent token sparklines are placeholder data because I’m storing traces, not time-bucketed token history per agent. Something to fix this week. Tomorrow Get the Overview cards pulling from real DB aggregations. Then figure out deployment — right now this whole thing requires running two local servers which isn’t great for a demo. Want a single public URL before the submission deadline. /////////////////////////////////////////////////////// SwarmTrace — open-source observability for multi-agent AI systems. Built for AMD Hackathon 2026.
dev vlog 3”What’s up, builders! Today we are fundamentally changing how SwarmTrace works. We’re tearing out the local SQLite restrictions and turning this project into a distributed, multi-tenant AI agent monitoring platform. The goal? Anyone can install our package, drop in an API key, and instantly view their agent’s execution traces on a sleek, hosted Next.js dashboard powered by Clerk and Supabase—without hosting a single thing themselves.” What We’re Solving Today: The “Localhost” Trap: Right now, the FastAPI backend expects to live on the same machine as the SQLite database. If a user runs an agent on their machine, they can’t easily see it on a globally hosted dashboard. Multi-Tenancy: We need to make sure User A never sees User B’s logs. Every single trace must be bound to an organization or user ID. Zero-Infra for the User: The developer using tracely should only have to pip-install it, provide a SWARMTRACE_API_KEY, and let our remote backend handle the rest. 📐 The SaaS Architecture Blueprint Here is how data will flow across the internet from your user’s local python script straight to your Vercel-hosted frontend dashboard: [ User’s Local Machine ] └── Running AI Agent (LangChain/CrewAI/AutoGen) └── Tracely SDK (Decorators) │ ▼ (Async Background HTTP POST /ingest) [ Vercel Serverless / API Gateway ] ─── (Validates SWARMTRACE_API_KEY) │ ▼ (Writes Log Payload) [ Hosted Database: Supabase / Postgres ] └── traces table (Schema: id, user_id, execution_time, trace_payload) ▲ │ (Fetches user-specific traces via Clerk JWT auth) [ Vercel Frontend: Next.js + Clerk ] └── Protected Dashboard View (Only shows rows matching user_id) 🗂️ The Technical Roadmap To pull this off, we have to transform four key elements of your repository: The SDK (tracely/scraper.py & tracer.py) Current: Writes to a local SQLite database via storage.py. SaaS Modification: Introduce a background background-worker thread or async pool. When a trace finishes, it sends an HTTP POST request to https://api.swarmtrace.dev/v1/ingest carrying the payload and an Authorization: Bearer st_live_… header. The Backend Engine (api.py) Current: Reads from local SQLite. SaaS Modification: Drop SQLite. Migrate to a hosted Postgres instance (Supabase is perfect here). Add an /ingest route for incoming agent metrics. Add middleware to validate incoming user requests from the frontend using Clerk JWT tokens. The Authentication Layer (Clerk) Wrap your frontend-next/ layout inside a . Set up a pipeline where a user logs in, generates an “Agent API Key” from their settings dashboard, and pastes that key into their Python .env file. also tracely is maded by me it is the part of swarm trace.
dev vlog #4 builders just finished the backend work for today / rest work tomorrow i will make the frontend connected to clerk for auth and neon for database . byee👍
finally live on vercel but still in deployment you can check it guys go on swarmtrace.vercel.app
Dev Vlog #6Finally, the landing page work is officially done! The platform is ready for users, and you can check it out here: swarmtrace.vercel.app.Right now, I don’t have the budget to buy a custom domain, so I have set it up on Google Search Console for now. I know that having a domain like swarmtrace.ai would help it perform much better in Google Search, since Google tends to rank subdomains poorly.That being said, the platform is still very much in the building phase. I am already working on adding some exciting new features.Stay tuned, and bye for now!
dev vlog#7today i worked on research on my project about similar projects because i cant get a .com domain hi have to buy a .ai domain and i worked on dashboard today because it was so simple then guys please suggest any improvement.
Ahh infinite .tsx bug fixing
added new features
all test are passing
does a full audit by ai agent found some production bugs working on prd section 1 because it is main it conation python package updtaes because the whole project is up to sdk byee meet in next vlog
added many features like day and night light take a tour and adjust icons sizes to a bit smaller and fixed some backend issues and run many real tests like rag agent and hermes agent and again applied for google search console ——————————————————————————————————— i need to buy a domain but i do not have money i will start marketing after buying domain byee guyss please like
adding agent graph this is mvp only i will polish it byee
today i know there is so much work left on this project then i think i added a floating side bar added some more now features for backend optimization guys working on a i3 sucks please help me to buy an macbook byyy
starting work
half work done
Ships:
the marketing was challenging and i think now it is ready and i get more suggestion if people will use it and i hope i ccan buy a domain by the star dust...
|
1793285460.575129
|
1793371860.575129
|
|
6518
|
My first slack bot! by @lucy_stiglitz | Stardance
|
lucy_stiglitz
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @lucy_stiglitz | Sta Title: My first slack bot! by @lucy_stiglitz | Stardance...
|
1792655421.128719
|
1793260221.128719
|
|
6519
|
Personal OS by @PyroProtato | Stardance
|
PyroProtato
|
0
|
0.37
|
0
|
[]
|
[{"post_id": 5110, "ts": "2026 [{"post_id": 5110, "ts": "2026-06-08T19:56:26Z", "hours": 0.3683, "text": "Started basic HTML!"}]...
|
Title: Personal OS by @PyroProtato | Stardance
De Title: Personal OS by @PyroProtato | Stardance
Devlogs:
Started basic HTML!...
|
1793180871.9659262
|
1793785671.9659262
|
|
6520
|
Unus by @laurynas_lubauskas | Stardance
|
laurynas_lubauskas
|
0
|
10.23
|
0
|
[]
|
[{"post_id": 8640, "ts": "2026 [{"post_id": 8640, "ts": "2026-06-14T11:17:37Z", "hours": 1.2636, "text": "Day 6 I added this feature a few days ago, but I was too lazy to write a devlog, but I will now. So I added a reply button to in the AI assistant. It wasn’t so hard just I needed to search a lot and even went into the second page of google. It is a vital feature, because when I added the AI assistant it asked a question and I couldn’t answer, because there was no reply button. That is it for today/few days ago. Thanks for taking your assisted mind to read it :P"}, {"post_id": 6376, "ts": "2026-06-10T18:52:22Z", "hours": 2.6589, "text": "Day 5 Today I was sick so I had some time to add AI to my browser! It took me a while but I did it with no bugs/problems. I was deciding a long time between different AI models that I could use for my browser, but I choose grok. It wasn’t my first option, but it was the only free api that was available. I know it’s not the best AI model, but it will do for the moment. Right after adding AI I went to test it and I found that I can’t respond to grok when it asks questions. So now thats what I am trying to add. I hope I will do it tomorrow or in the next few days. I am really happy that I was able to add the AI. It took me a while to research everything. Thanks for taking your Intelligent time to read this ;o Get it?"}, {"post_id": 5137, "ts": "2026-06-08T20:29:15Z", "hours": 1.3672, "text": "Day 4 Today I kinda finished the ui even tho in the future I will add more. Today I was brainstorming ideas for the features that I could add. I decided on ai integration into the browser. I think ai is a great feature especially when you search something and you dont need to enter random sketchy websites. It shows what you searched for. I’m hoping on adding the feature tomorrow, or at least starting to add. This is all for today. I think the new ui looks way better and I hope to make it even better. Thanks for taking your sweetest time to read this :D"}, {"post_id": 4493, "ts": "2026-06-07T20:28:46Z", "hours": 1.9892, "text": "Unus Day 3 During the weekend I didn’t code just Sunday evening. I am updating the ui once again and I am changing a lot of the python code and it takes a lot of time and I still need to update the qss file. My idea after I finish the ui is adding the features to the browser. I think features is the main “selling point” of a browser. Since I am updating the python file you cant see the ui difference in the browser so I will just attach a screenshot of the code! Bye ;D"}, {"post_id": 2351, "ts": "2026-06-04T20:01:08Z", "hours": 1.7922, "text": "Unus Day 2 Today I worked on optimizing the code for the ui. My first code was not optimized for ui and I needed to do lots of changes before I could create a style.qss file. I worked a lot on optimizing the code today, so I didn’t have time to do some improvement on the ui, but there is a few minor differences. I don’t know if I will log a lot of hours during the weekend. This was all for today thanks for reading!"}, {"post_id": 1627, "ts": "2026-06-03T19:16:08Z", "hours": 1.1547, "text": "Unus Day 1 Hi, This is my first devlog and i took 1h 9m to create the “backbone/base” of the browser. The browser is based on chromium and I used python for the code. I still need to do lots of ui design and other features. I might try adding ai to the browser, but that’s a big question mark. By the end I hope to have a full nice browser with lots of features. I will try to make it so that people could download my browser. This is all for today. My summer holidays start in less than 3 weeks so during the summer holidays I want to absolutely perfect this browser. Thanks for taking your time to read this!"}]...
|
Title: Unus by @laurynas_lubauskas | Stardance
De Title: Unus by @laurynas_lubauskas | Stardance
Devlogs:
Unus Day 1 Hi, This is my first devlog and i took 1h 9m to create the “backbone/base” of the browser. The browser is based on chromium and I used python for the code. I still need to do lots of ui design and other features. I might try adding ai to the browser, but that’s a big question mark. By the end I hope to have a full nice browser with lots of features. I will try to make it so that people could download my browser. This is all for today. My summer holidays start in less than 3 weeks so during the summer holidays I want to absolutely perfect this browser. Thanks for taking your time to read this!
Unus Day 2 Today I worked on optimizing the code for the ui. My first code was not optimized for ui and I needed to do lots of changes before I could create a style.qss file. I worked a lot on optimizing the code today, so I didn’t have time to do some improvement on the ui, but there is a few minor differences. I don’t know if I will log a lot of hours during the weekend. This was all for today thanks for reading!
Unus Day 3 During the weekend I didn’t code just Sunday evening. I am updating the ui once again and I am changing a lot of the python code and it takes a lot of time and I still need to update the qss file. My idea after I finish the ui is adding the features to the browser. I think features is the main “selling point” of a browser. Since I am updating the python file you cant see the ui difference in the browser so I will just attach a screenshot of the code! Bye ;D
Day 4 Today I kinda finished the ui even tho in the future I will add more. Today I was brainstorming ideas for the features that I could add. I decided on ai integration into the browser. I think ai is a great feature especially when you search something and you dont need to enter random sketchy websites. It shows what you searched for. I’m hoping on adding the feature tomorrow, or at least starting to add. This is all for today. I think the new ui looks way better and I hope to make it even better. Thanks for taking your sweetest time to read this :D
Day 5 Today I was sick so I had some time to add AI to my browser! It took me a while but I did it with no bugs/problems. I was deciding a long time between different AI models that I could use for my browser, but I choose grok. It wasn’t my first option, but it was the only free api that was available. I know it’s not the best AI model, but it will do for the moment. Right after adding AI I went to test it and I found that I can’t respond to grok when it asks questions. So now thats what I am trying to add. I hope I will do it tomorrow or in the next few days. I am really happy that I was able to add the AI. It took me a while to research everything. Thanks for taking your Intelligent time to read this ;o Get it?
Day 6 I added this feature a few days ago, but I was too lazy to write a devlog, but I will now. So I added a reply button to in the AI assistant. It wasn’t so hard just I needed to search a lot and even went into the second page of google. It is a vital feature, because when I added the AI assistant it asked a question and I couldn’t answer, because there was no reply button. That is it for today/few days ago. Thanks for taking your assisted mind to read it :P...
|
1793195512.6469765
|
1793800312.6469765
|
|
6521
|
Rogue-Lite Top Down Shooter by @Orangeson76 | Star Rogue-Lite Top Down Shooter by @Orangeson76 | Stardance...
|
Orangeson76
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Rogue-Lite Top Down Shooter by @Orangeson76 Title: Rogue-Lite Top Down Shooter by @Orangeson76 | Stardance...
|
1793310693.6533628
|
1793915493.6533628
|
|
6522
|
Py-Watchdog: Smart Folder Automation Hub by @Greg_ Py-Watchdog: Smart Folder Automation Hub by @Greg_ios | Stardance...
|
Greg_ios
|
1
|
4.0
|
19
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-18T08:00:01Z", "hours": 4.0, "multiplier": 4.97, "payout": 19, "blessing": "neutral", "text": "Py-Watchdog: Smart Folder Automation Hub What did you make? I built Py-Watchdog, a smart, privacy-first open-source automation tool written in Python. It runs silently in the background and automatically keeps your cluttered Downloads and Desktop folders organized. It doesn’t just sort files by extension; it supports advanced custom rules (like startswith or contains matching) and features a real-time web dashboard built with Flask and Bootstrap to monitor your file-moving statistics dynamically. What was challenging? The biggest challenge was transitioning the tool from a simple command-line script into a robust background service that updates metrics on the fly. Implementing the asynchronous log tracking and making the backend expose a clean /api/count endpoint for the Flask dashboard—while keeping the background thread lightweight and stable—took a lot of troubleshooting and fine-tuning. What are you proud of? I’m incredibly proud of the customization and user autonomy this project offers. Users aren’t locked into generic folders; they can set up tailored rules for how their files should be managed. I am also proud of packing everything into a clean web dashboard UI and compiling the final script into a standalone .exe so that anyone can use it without needing a Python environment. What should people know so they can test your project? To test it out, you don’t need to write a single line of code! Head over to the GitHub repository and download the latest executable file (.exe) from the releases page. Run it, set up your custom organization rules, and open the web dashboard to see your files getting sorted in real-time. Check the automatically generated log files to see exactly what actions the watchdog performed.", "repo": "https://github.com/travletothefurureprogramming/smart_folder_automation", "demo": "https://github.com/travletothefurureprogramming/smart_folder_automation/releases/tag/SecondRelease"}]...
|
[{"post_id": 11162, "ts": "202 [{"post_id": 11162, "ts": "2026-06-18T07:53:42Z", "hours": 0.2583, "text": "Publish the second release(v2.0.0) https://github.com/travletothefurureprogramming/smart_folder_automation/releases/tag/SecondRelease"}, {"post_id": 10862, "ts": "2026-06-17T20:21:07Z", "hours": 1.0878, "text": "Added a Flask-based web dashboard to track the number of files moved in real time. The backend exposes a /api/count endpoint, and the frontend displays the metric using a clean Bootstrap UI."}, {"post_id": 3423, "ts": "2026-06-06T11:07:55Z", "hours": 0.4461, "text": "Make a .exe and github release"}, {"post_id": 3410, "ts": "2026-06-06T10:18:58Z", "hours": 0.8694, "text": "Add suppourt for custom rules and organization not only for extension, from now rules can also organize files if startwith or contains a word based on users custom rules"}, {"post_id": 3070, "ts": "2026-06-05T23:29:13Z", "hours": 0.4039, "text": "From now Py-Watchdog Smart Folder Automation Hub can track and organize downloads and desktop folders. Can also run in backhround. Finaly it write his actions in log file!!!"}, {"post_id": 3058, "ts": "2026-06-05T22:58:53Z", "hours": 0.5903, "text": "Suppourt for organazing desktop and notifications"}, {"post_id": 2989, "ts": "2026-06-05T22:20:01Z", "hours": 0.3431, "text": "Making a basic file tracking for Downloads folder"}]...
|
Title: Py-Watchdog: Smart Folder Automation Hub by Title: Py-Watchdog: Smart Folder Automation Hub by @Greg_ios | Stardance
Devlogs:
Making a basic file tracking for Downloads folder
Suppourt for organazing desktop and notifications
From now Py-Watchdog Smart Folder Automation Hub can track and organize downloads and desktop folders. Can also run in backhround. Finaly it write his actions in log file!!!
Add suppourt for custom rules and organization not only for extension, from now rules can also organize files if startwith or contains a word based on users custom rules
Make a .exe and github release
Added a Flask-based web dashboard to track the number of files moved in real time. The backend exposes a /api/count endpoint, and the frontend displays the metric using a clean Bootstrap UI.
Publish the second release(v2.0.0) https://github.com/travletothefurureprogramming/smart_folder_automation/releases/tag/SecondRelease
Ships:
Py-Watchdog: Smart Folder Automation Hub What did you make? I built Py-Watchdog, a smart, privacy-first open-source automation tool written in Python. It runs silently in the background and automatically keeps your cluttered Downloads and Desktop folders organized. It doesn’t just sort files by extension; it supports advanced custom rules (like startswith or contains matching) and features a real-time web dashboard built with Flask and Bootstrap to monitor your file-moving statistics dynamically. What was challenging? The biggest challenge was transitioning the tool from a simple command-line script into a robust background service that updates metrics on the fly. Implementing the asynchronous log tracking and making the backend expose a clean /api/count endpoint for the Flask dashboard—while keeping the background thread lightweight and stable—took a lot of troubleshooting and fine-tuning. What are you proud of? I’m incredibly proud of the customization and user autonomy this project offers. Users aren’t locked into generic folders; they can set up tailored rules for how their files should be managed. I am also proud of packing everything into a clean web dashboard UI and compiling the final script into a standalone .exe so that anyone can use it without needing a Python environment. What should people know so they can test your project? To test it out, you don’t need to write a single line of code! Head over to the GitHub repository and download the latest executable file (.exe) from the releases page. Run it, set up your custom organization rules, and open the web dashboard to see your files getting sorted in real-time. Check the automatically generated log files to see exactly what actions the watchdog performed....
|
1793332084.1143243
|
1793418484.1143243
|
|
6523
|
Pet Rock Web Page by @Aster_ | Stardance
|
Aster_
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Pet Rock Web Page by @Aster_ | Stardance
|
1792651978.123984
|
1793256778.123984
|
|
6524
|
My first slack bot! by @DheerajS | Stardance
|
DheerajS
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @DheerajS | Stardanc Title: My first slack bot! by @DheerajS | Stardance...
|
1792702196.2782474
|
1793306996.2782474
|
|
6525
|
Career.com by @Hannah | Stardance
|
Hannah
|
0
|
4.74
|
0
|
[]
|
[{"post_id": 78816, "ts": "202 [{"post_id": 78816, "ts": "2026-10-11T17:56:16Z", "hours": 2.3972, "text": "Worked on the sql connectivity todayy^^"}, {"post_id": 11258, "ts": "2026-06-18T12:41:09Z", "hours": 1.1633, "text": "Working on some evaluation questions today :)"}, {"post_id": 10590, "ts": "2026-06-17T12:29:48Z", "hours": 1.1794, "text": "started the project today^^"}]...
|
Title: Career.com by @Hannah | Stardance
Devlogs: Title: Career.com by @Hannah | Stardance
Devlogs:
started the project today^^
Working on some evaluation questions today :)
Worked on the sql connectivity todayy^^...
|
1792792098.9568172
|
1793396898.9568172
|
|
6526
|
Untitled by @Orangeson76 | Stardance
|
Orangeson76
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Untitled by @Orangeson76 | Stardance
|
1792666509.6501513
|
1793271309.6501513
|
|
6527
|
Untitled by @Liza | Stardance
|
Liza
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Untitled by @Liza | Stardance
|
1792723821.151422
|
1793328621.151422
|
|
6528
|
blockEm by @ondy | Stardance
|
ondy
|
1
|
16.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-30T17:02:16Z", "hours": 16.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "blockEm What did you make? Custom app blocker/limiter aimed specifically to stop prolongued doomscrolling. Its currently specifically build around maximum scroll amount/day instead of the usual maximum time/day which is better system in my opinion. Features: Daily Scroll Limit - set maximum amount of scrolls/day before scrolling(not whole app) gets blocked Set Cheat Hours - ability to set cheat hours independently for each day of the week(regular apps usually only allow set time for all days). Allowing apps/dms/homepages… - you can ignore friends reels, tiktok messages, instagram homepage posts or even whole apps Overview - see your progress through the whole month and discover scroll patterns What was challenging? The hardest was to make sure the scrolls are detected in each part of each app, the detection works by taking the number of likes(and comments) and when it changes trying to figure out if that was a scroll. You can probably imagine that each app section has completely different like and comment buttons… What are you proud of? The fact that i went into this with 0 android app development knowledge How to test the project everything is on the github page", "repo": "https://github.com/0ndyy/blockEm/", "demo": "https://github.com/0ndyy/blockEm/releases/tag/0.1"}]...
|
[{"post_id": 75612, "ts": "202 [{"post_id": 75612, "ts": "2026-09-30T15:40:34Z", "hours": 1.6392, "text": "blockEm: productivity blocker devlog 4: This devlog i developed something reallu useful = CHEAT HOURS, i know lot of apps have those but most of the time you can only set hours and days, blockem allows you to set specific hours for each day - this can be especially usefull if you want to scroll in school or comute but not home/other places and have different schedules for each day of the week. Id like to share my struggles but this was really straight forward and i havent ran into many issues, the only thing i might change in the future is the native android time selection which is really ugly for some reason…"}, {"post_id": 34301, "ts": "2026-07-24T21:46:54Z", "hours": 4.4869, "text": "blockEm: productivity blocker devlog 3: After last time completely overhauling the whole system i alsmot had to do it again😭🙏. The system had many glitches and was overcomplicated. The new system relies on change in likes(or comments for backup) count to detect a scroll. I added a debug menu showing things such as current app, app section, like/comment count… which turned out to be really helpful - now the system is working so i can say version 0.1 is finished. I will now focus on adding more features(version 0.2, you can preview the roadmap in one of the screenshots) and better design(version 0.3 - hopefully this could be first public relese yay)"}, {"post_id": 8878, "ts": "2026-06-14T19:52:37Z", "hours": 3.5933, "text": "blockEm: productivity blocker devlog 2: Started completely reworking the tracking system, since the old one used math sizes and ratios, which are different on some platforms, it was unreliable and become quickly a mess. * To make this devlog at least a little bit visually interesting😭🙏 i implemented a startup screen and a scroll history section * Once im finished with the new system i will finally start implementing other features from just scroll counting, such as: app blocker, app timer, app unlocks per hour…"}, {"post_id": 5870, "ts": "2026-06-09T20:30:47Z", "hours": 1.335, "text": "blockEm: productivity blocker devlog 1.1: Decided to take a little break from coding and made this banner in photoshop, it took around 50 minutes. The remaining 30m is some bugfixing after last devlog. Overall im quite happy with how it turned out especially considering that art is my weaker side."}, {"post_id": 5625, "ts": "2026-06-09T14:33:55Z", "hours": 2.6528, "text": "blockEm: productivity blocker devlog 1: In this session i made huge progress, i implemented some helpful toggles(see image) and most importantly finally a blocker - after reaching set amount of scrolls it blocks you from scrolling further, its still a bit janky and can be bypassed, but i will work on that later on. * Also implementing to work the scroll counter across all apps and different types was a huge headache, i switched to math based detection - basically detecting different elements(back button, sent button, navigation bar…) and their sizes. On ig for example we have regualr reel, dm reels, fyp in dms, suggested reels etc. and all have different sizes n stuff - so like allowing first reel in dms and not allowing scrolling further was quite a challenge. Hopefully instagram doesnt chagne it in their next update😭🙏"}, {"post_id": 4187, "ts": "2026-06-07T12:36:09Z", "hours": 2.2464, "text": "devlog 0: implemented basic android app in kotlin, currently just asks for permissions and count the amount of scrolls you do per day(on tiktok, instagram and youtube); next i will start making some app ui and implementing blocking(scroll limit, app blocking ect.); also i am planning to soon relese it to public for any feedback so stay tuned"}]...
|
Title: blockEm by @ondy | Stardance
Devlogs:
devl Title: blockEm by @ondy | Stardance
Devlogs:
devlog 0: implemented basic android app in kotlin, currently just asks for permissions and count the amount of scrolls you do per day(on tiktok, instagram and youtube); next i will start making some app ui and implementing blocking(scroll limit, app blocking ect.); also i am planning to soon relese it to public for any feedback so stay tuned
blockEm: productivity blocker devlog 1: In this session i made huge progress, i implemented some helpful toggles(see image) and most importantly finally a blocker - after reaching set amount of scrolls it blocks you from scrolling further, its still a bit janky and can be bypassed, but i will work on that later on. * Also implementing to work the scroll counter across all apps and different types was a huge headache, i switched to math based detection - basically detecting different elements(back button, sent button, navigation bar…) and their sizes. On ig for example we have regualr reel, dm reels, fyp in dms, suggested reels etc. and all have different sizes n stuff - so like allowing first reel in dms and not allowing scrolling further was quite a challenge. Hopefully instagram doesnt chagne it in their next update😭🙏
blockEm: productivity blocker devlog 1.1: Decided to take a little break from coding and made this banner in photoshop, it took around 50 minutes. The remaining 30m is some bugfixing after last devlog. Overall im quite happy with how it turned out especially considering that art is my weaker side.
blockEm: productivity blocker devlog 2: Started completely reworking the tracking system, since the old one used math sizes and ratios, which are different on some platforms, it was unreliable and become quickly a mess. * To make this devlog at least a little bit visually interesting😭🙏 i implemented a startup screen and a scroll history section * Once im finished with the new system i will finally start implementing other features from just scroll counting, such as: app blocker, app timer, app unlocks per hour…
blockEm: productivity blocker devlog 3: After last time completely overhauling the whole system i alsmot had to do it again😭🙏. The system had many glitches and was overcomplicated. The new system relies on change in likes(or comments for backup) count to detect a scroll. I added a debug menu showing things such as current app, app section, like/comment count… which turned out to be really helpful - now the system is working so i can say version 0.1 is finished. I will now focus on adding more features(version 0.2, you can preview the roadmap in one of the screenshots) and better design(version 0.3 - hopefully this could be first public relese yay)
blockEm: productivity blocker devlog 4: This devlog i developed something reallu useful = CHEAT HOURS, i know lot of apps have those but most of the time you can only set hours and days, blockem allows you to set specific hours for each day - this can be especially usefull if you want to scroll in school or comute but not home/other places and have different schedules for each day of the week. Id like to share my struggles but this was really straight forward and i havent ran into many issues, the only thing i might change in the future is the native android time selection which is really ugly for some reason…
Ships:
blockEm What did you make? Custom app blocker/limiter aimed specifically to stop prolongued doomscrolling. Its currently specifically build around maximum scroll amount/day instead of the usual maximum time/day which is better system in my opinion. Features: Daily Scroll Limit - set maximum amount of scrolls/day before scrolling(not whole app) gets blocked Set Cheat Hours - ability to set cheat hours independently for each day of the week(regular apps usually only allow set time for all days). Allowing apps/dms/homepages… - you can ignore friends reels, tiktok messages, instagram homepage posts or even whole apps Overview - see your progress through the whole month and discover scroll patterns What was challenging? The hardest was to make sure the scrolls are detected in each part of each app, the detection works by taking the number of likes(and comments) and when it changes trying to figure out if that was a scroll. You can probably imagine that each app section has completely different like and comment buttons… What are you proud of? The fact that i went into this with 0 android app development knowledge How to test the project everything is on the github page...
|
1793339765.7441447
|
1793426165.7441447
|
|
6529
|
My first slack bot! by @st4r21722 | Stardance
|
st4r21722
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @st4r21722 | Stardan Title: My first slack bot! by @st4r21722 | Stardance...
|
1792770580.4891202
|
1793375380.4891202
|
|
6530
|
My awesome macropad! by @SamBair | Stardance
|
SamBair
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @SamBair | Stardanc Title: My awesome macropad! by @SamBair | Stardance...
|
1792752531.6781406
|
1793357331.6781406
|
|
6531
|
My first slack bot! by @Lamparter | Stardance
|
Lamparter
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @Lamparter | Stardan Title: My first slack bot! by @Lamparter | Stardance...
|
1792914713.7778718
|
1793778713.7778718
|
|
6532
|
The Great Zoltar by @iabmulcahey | Stardance
|
iabmulcahey
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: The Great Zoltar by @iabmulcahey | Stardanc Title: The Great Zoltar by @iabmulcahey | Stardance...
|
1792745734.8347335
|
1793350534.8347335
|
|
6533
|
Automated Hydroponic System by @Lukie_pookie | Sta Automated Hydroponic System by @Lukie_pookie | Stardance...
|
Lukie_pookie
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Automated Hydroponic System by @Lukie_pooki Title: Automated Hydroponic System by @Lukie_pookie | Stardance...
|
1792695160.455571
|
1793299960.455571
|
|
6534
|
Math Suite by @R10 | Stardance
|
R10
|
0
|
105.42
|
0
|
[]
|
[{"post_id": 58033, "ts": "202 [{"post_id": 58033, "ts": "2026-08-30T11:44:29Z", "hours": 7.6675, "text": "DEVLOG #21 Completed the CLI tool and created binaries for windows and linux using pyinstaller. Also completed the full Guide page on the website with all the relevant rules, syntax and limitations listed cleanly."}, {"post_id": 54909, "ts": "2026-08-26T04:03:17Z", "hours": 1.2047, "text": "DEVLOG #20 Completed and wired Unparser TRY NEW UPDATE I completed the unparser now with the precedence based approach and I can’t believe how much simpler it is and how bad my initial approach was. The thing that makes it work is the new needs_paren function which basically does all the precedence based logic of telling if the child needs parenthesis or not. Basically if the child’s precedence is lower than the parent op then we need a parenthesis. For example: if the child is a + node and the parent is a * node then we would need parenthesis on the child. For example: (x+1) * 3 -> x+1 needed parenthesis. The main part that made me think a bit was the case when precedence of the child and parent is equal. There are basically 3 cases here: When op is + or * , the child never needs parenthesis. When op is - or / , the child only need parenthesis if it is on the right side. For example: precedence of + == - , a + b - c -> a+b is on the left side and hence does not needs parenthesis. Whereas, c - (a+b) -> a+b on the right side needs parenthesis because this basically means c - a - b and not c - a + b . Hence, parenthesis is required. When op is ^ , parenthesis is only required when the child is on the left and not when it is on the right. For example: a^b^c does not need parenthesis (even though it could be written as a^(b^c) ) but, (a^b)^c needs parenthesis because this means a^(b*c) as the powers multiply. I have also wired in the unparser function to derivative and simplify too so now the result is an expression instead of a tuple. Now I will update my README.md and explain the working of the unparser and then I will work on adding the guide page to my website."}, {"post_id": 54516, "ts": "2026-08-25T15:24:49Z", "hours": 3.9794, "text": "DEVLOG #19 Another Setback I was working on the unparse function today. Basically the idea was simply to recurse through the tree and form the expression as a string. Now, the hard part in this was to decide when to apply parenthesis. Basically, we have to apply parenthesis to any child of the function which has a lower precedence then the current parent op. I did not have this idea as well set in my mind when i was making this function and I just wasted 4 hours today trying to stack up elif cases with or conditions to try to cover every shape. Basically, I was thinking that for * / / , there are only 4 base cases: both children need parenthesis left needs parenthesis right needs parenthesis none need parenthesis I took that as a starting point and then i started to think of cases which would satisfy that and that caused me to build up this or-or-or jargon. I am really pissed. Now I will change my direction and move onto a precedence based approach which checks if the precedence of the child is lesser than the parent op, if yes then parenthesize it and if no then check if precedence is equal, if it is then check for associativity. That is the plan and I hope I don’t mess up this time."}, {"post_id": 53795, "ts": "2026-08-24T14:32:20Z", "hours": 4.6131, "text": "DEVLOG #18 LIVE PROJECT I have finally deployed the Version-1 of the project on vercel, check it out at the link above. I also completed the README for my repo explaining all the features and limitations of the project. Now I will be working on making an unparser to show the users a clean expressions as a result from the calculator instead of AST nodes and I will also add a guide page on the website for the syntax rules and general guide."}, {"post_id": 53022, "ts": "2026-08-23T12:29:17Z", "hours": 6.5536, "text": "DEVLOG #17 Completed Styling (would appreciate feedback) Features: AST generator AST visualizer (downloadable SVG trees) Domain calculator Range Calculator Derivative calculator Simplification Next steps: AST back to expression generator because right now all the calculators give the result in terms of AST nodes so i need a reverse-parser which I think would be easy. Making a simpler bare bones CLI tool for simpler People. adding a guide page to the website explaining all the limitations and syntax of the calculator. hosting on my own domain? That is all that I can think for now. Right now I have not hosted the website because I am thinking of adding a few more features like user changeable SVG node and line colors, etc."}, {"post_id": 51764, "ts": "2026-08-21T16:32:30Z", "hours": 7.3219, "text": "DEVLOG #16 More PROGRESS! completed range.py tested edge cases with some pretty nasty ones and have decided to leave some limitations like not supporting gif/frac/sec/tan… functions because of their nature. General Debugging created all the flask endpoints along with the basic HTML layout of the website and wiring in the JS. Website is tested and all endpoints are working Now, I will focus on adding some styling to the website and also making the user experience better."}, {"post_id": 50948, "ts": "2026-08-20T12:44:34Z", "hours": 7.7231, "text": "DEVLOG #15 Real PROGRESS! Completed the full differentiation pipeline which is working completely now with all edge cases (that I have tested) handled. converted simplify to a standalone file as I noticed that simplify could be used as a general simplification pipeline for ALL generated nodes in my maths suite. Created pow_to_div function in simplify to turn negative exponents into division nodes to make the simplification pipeline truly generalized because none of my other algorithms expect a negative exponent. A LOT of debugging in domain.py and testing some edge cases. Adding support for multiple exclusions instead of single in normalize_domain . Earlier: (-∞, -2) ∪ (-2, 2) ∪ (2, ∞) Now: R-{-2, 2} which is a much cleaner solution Now I am working on completing range.py and then finally making the website for the full maths suite. I am a bit confused. I am not able choose between flask and FastAPI. If you have read all this then would you also mind sharing your opinion on what should I use in the comments?"}, {"post_id": 48137, "ts": "2026-08-16T13:02:18Z", "hours": 7.85, "text": "DEVLOG #14 Completed the full simplify_initial pipeline. Handled cases with 0 and 1 and traced a full long recursion by hand to better understand the pattern and make iterative debugging faster. Also handled negative node by simplifying the ('*', '-1', right) node formed so that any coefficients collapse cleanly and the term can form correctly with a negative coefficient. EXAMPLE:- Earlier: x - 3x -> terms = [(1.0, 'x', 1.0), (-1.0, ('*', '3', 'x'), 1.0)] Now: x - 3x -> terms = [(1.0, 'x', 1.0), (-3.0, 'x', 1.0)] Therefore, now merging terms will result in ('*', '-2', 'x') I pasted my code into claude and asked it to generate me some test cases which it believes would fail and now I am working on debugging them with a mix of hand tracing recursion and simple fixes so the pipeline is almost at its end (I hope)."}, {"post_id": 45545, "ts": "2026-08-12T03:20:05Z", "hours": 7.77, "text": "DEVLOG #13 I have completed the basic simplification functions now but, it is not working perfectly and there are still some changes to be made. for example, handling cases where it is multiplied by 0, or when 0 is added, or it is multiplied by 1, etc. so I think it requires a bit more of iterative debugging to catch all of the edge cases. I have formalized the design of simplification into: Flatten -> form_term -> merge_terms -> form_node -> rebuild which is much better then the previous logic that I had where I was adding more edge cases for handling each case. Right now I will be testing the full recursion for a test case to check where it goes wrong right now in the pipeline to fix it."}, {"post_id": 42398, "ts": "2026-08-07T02:47:07Z", "hours": 8.9103, "text": "STUCK So basically, since my last devlog, the main feature of the new derivative calculator that I had proudly announced is now coming to bite me. The simplification is so tough. Let me explain you all the turn of events. (Simplification is still not complete) basically, my initial idea of simplification was just removing all the temporary zeros and ones that were generated by the derivative itself. Then I thought of increasing the initial scope to support some other simplifications like (‘ ’, ‘2’, (’ ’, ‘2’, ‘x’)) should be solved to (‘ ’, ‘4’, ‘x’). I managed to achieve this simplification too but, I found out there are a lot more simplification cases that I need to handle after we get the derivative. for example: x - 3x, which should be simplified to -2x. For that I had to build an approach which would take the coefficient and base then operate on the coefficients for the same bases according to the operator. Therefore, for x the coeff is 1 and then for 3x the coeff is 3 but that is incorrect. In the case of x-3x, the coefficients should be 1 and -3 so that when i add them i get -2 as the final coefficient for x. To do that, I had to switch all binary subtraction expression and turn them into additive unary negative for op = ‘+’ so that x - 3x turns into x + (-3x). Now, all this actually worked but the main problem was that now the flattened list looks like [‘x’, (’ ’, ‘-1’, (‘ ’, ‘3’, ‘x’))] which means I cannot reliably extract the coefficients now. I first have to handle the recursive case of flattening the node again, turning (’ ’, ‘-1’, (‘ ’, ‘3’, ‘x’)) to the flattened version [‘-1’, ‘3’, ‘x’] and then i would have to run it back through combine where it would be formed as calc = -3 and symbols = ‘x’ and then rebuild it as the node (’ ’, ‘-3’, ‘x’). Only after that can i actually extract the coefficients and compare the bases of the two expressions which would be 1 and -3 and calculate them according to the op => ‘+’ to finally give -2 as calc and ‘x’ as symbols and then rebuild that again into (‘ ’, ‘-2’, ‘x’) to solve it. Now this was just one case for one operator but i need to handle both ‘+’ and ’ ’ as the both have associativity and there are other cases for other ops too like x^2/x should just simplify to x. I have already added so much code that I myself feel like the approach is very wrong and the more I build the more edge cases I am adding because right now the amount of if-else handling for specific cases is crazy so I really think that I need to reconsider my approach for simplification. The derivative calculator is taking too much time considering it is an intermediate step but I think it would be worth it because this simplification step is something that I have never done before so I would be learning something anyway."}, {"post_id": 37427, "ts": "2026-07-30T04:49:03Z", "hours": 8.0483, "text": "Derivative For finding the range, I am opting for method of differentiation to check intervals. hence, I have made derivative.py for differentiation. This is my second derivative calculator. The first one that I built was made completely using string slicing and weird string manipulation and pretty biased logic where everything was stored in the form of a dictionary. To be honest, I was pretty proud of that calculator because I was able to make it just using the knowledge I had, and recursion is not innate (I think) and I was still able to do it so I am proud of it. But, it was no doubt pretty inefficient with a lot of edge cases. Therefore, this time i am making a better calculator using my new AST representation and A LOT more recursion. This calculator will process more functions and it will be able to simplify the derivative too, for example: derivative of 2x^2 will not be displayed as 2*2x, rather it will be correctly displayed as 4x."}, {"post_id": 33852, "ts": "2026-07-24T03:07:49Z", "hours": 6.1169, "text": "Devlog #10 Completed domain.py finished coding domain.py and tested about 20 test-cases on it. Completed debugging to finally finish domain calculation and start with Range. I do not know what else to tell you all as it has been a few days of coding and debugging with different bugs surfacing like incorrect handling of undefined functions, normalizing output, handling union cases correctly, etc."}, {"post_id": 32213, "ts": "2026-07-21T07:27:55Z", "hours": 5.6939, "text": "Union and Intersection of intervals I have made the intersection function which takes intervals and unions them together. I am now working on the union function. I initially used recursion to do the job but that was incorrect that the better method was just to sort the intervals list and then use a simple loop to evaluate the union. Here is the issue i was facing: [[A, B, C, D], E] AUE-> False, BUE-> False, CUE-> True => [F, A, B, D] union [F, A, B, D]-> FUA-> False => [[F,A], B, D] again [F,A], B => FUB-> False, BUA-> False => [F, A, B] => union this list now => FUA-> False => [[F,A], B] then again [F,A], B => FUB-> False, BUA-> False => [F, A, B] => FUA-> False => [[F,A], B] this goes on and on infinitely This is a problem of infinite recursion"}, {"post_id": 30591, "ts": "2026-07-18T09:17:11Z", "hours": 4.9469, "text": "It has been a tough journey If you read my previous devlog, it almost feels like i was foreshadowing what was about to happen to me. While making the solve_node function which would solve the inequality for x, i got lost in the mess of symbolic mathematics and started handling cases with fallbacks upon fallbacks. It has really a hot mess, I got to find out that there can be many types of questions and to solve every type of domain question, I would need fallback logic for every type of question which would mean I would have to encompass all the techniques in domain finding into the file and manage the interaction of the techniques and orchestrate them at a high level and basically making my own sympy (which took decades to build). I even thought of quitting a few times and the project was basically at a halt for 1-2 days. I then decided to solve a simple domain question by hand to check what really are the steps of finding the domain of a function. I found out that my logic up until making the constraints was fine. The next steps were finding critical points for example: (x-2)(x+3)>0 would have critical points 2 and -3 (they are just the points where the function is zero). Now, I also know that critical points also occur when the sign of the function changes or when its nature changes (going from defined to undefined and vice-versa) so instead of making a symbolic critical point finding function I thought of a more brute force method. If I have a number line (range of numbers) and i simply walk through them one by one, noting sign change between 2 numbers as a sign “there is a critical point here” and then use another function to basically go into each of those marked intervals and continuously half the interval (think of it as taking an interval and then zooming into the interval until you find the critical point) until about 9 decimal places (could be anything, it is just the amount of accuracy), you would get the critical point pretty accurately without having to solve anything using logic or symbolically, just substitute values of x. After finding the critical points, turning it into domain is as simple as just substituting points and see if the inequality holds."}, {"post_id": 28299, "ts": "2026-07-14T13:49:18Z", "hours": 2.7275, "text": "Domain Calculation Started the domain calculation file (domain.py) and made the function get_constraints() that recurses through the tree to look for domain restricting operators like /, sqrt, log, arcsin, etc. into a list. next steps are to solve each of the generated constraints (inequalities) and then combine them to get the domain for x (or any variable). Currently working on trying to solve the inequalities but it is proving to be pretty difficult so it could take longer than usual."}, {"post_id": 27119, "ts": "2026-07-12T12:03:05Z", "hours": 0.3206, "text": "AST Visualizer (continued) Case-2 If the node is not a leaf (i.e. not a string) we will again check for 2 cases. the node can either have 1 child or 2 children. If there are 2 children then we have to make 2 recursive calls but if we have a single child then only one and the other stuff is pretty similar so I will only explain the case when there are 2 children. first of all, we unpack the node to get op, left and right. Now we call assign_positions with depth+1 (to effectively track each level we go down), on left and right and extract: x-position of children, id of children and the parameters that get updated (id_count and leaf_count). next, we used children’s x-position, average it to get the op’s x-position. We make the tree: tree[op_id] = {'label': op, 'x': op_x, 'depth': depth, 'children': [l_id, r_id]} . Now we increase the id_count by 1 but not the leaf_count as we have not encountered a leaf (I had made a mistake here and increased leaf_count in the case where the node is not a leaf because I had named the variable as x_position earlier and thought that it must increment everywhere but forgot that we are averaging the children’s x-position to get op’s x-position so i do not need to increment it, which is why I have cleared this up). Now we return the same stuff: op_id, id_count, op_x, leaf_count, tree. Rendering Tree The actual tree generation is simply looping through the dictionary. The important function is converting x_position and depth values that are simple integers into actual pixel positions to actually position the circles in the correct spot which is done by pixel_x = margin+x*x_spacing and pixel_y = margin+depth*y_spacing where margin, x_spacing and y_spacing are all hyper-parameters. The next function is draw_nodes which simply loops though the values of tree dictionary gets the x and depth for each node, converts them to actual coordinated using get_pixel_coords and then creates the svg line: '<circle cx=\"{x}\" cy=\"{y}\" r=\"25\" fill=\"white\" stroke=\"black\" /> <text x=\"{x}\" y=\"{y}\" text-anchor=\"middle\" dominant-baseline=\"middle\">{i['label']}</text>' for each node and its text. The other is draw_lines. It takes all the parent nodes and gets their x and y value as pixel coordinates. Then, it gets the children of the node and for each child’s id, the function gets the child by its id, then gets the x and y coordinates of the child as pixel coordinates and then draws the line as per this syntax: f'<line x1=\"{x1}\" y1=\"{y1}\" x2=\"{x2}\" y2=\"{y2}\" stroke=\"white\" />' Finally we have the render_expression function which wraps everything into a single sequence of operations and creates the final svg code: f'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"850\" height=\"650\"> {lines} {nodes} </svg>' and created an svg file to view the final tree."}, {"post_id": 27067, "ts": "2026-07-12T09:05:33Z", "hours": 3.9078, "text": "AST Visualizer After completing my tokenizer and parser with a few fixes, I wanted to move straight onto building the actual domain and range logic and setting up all the constraints, but instead, I had another idea. Whenever I saw the output of my parser, it just seemed a bit meh . The output was just a nested tuple and it was not looking like what I had built was a tree. So, as a side quest, I built an SVG AST visualizer that takes the tuple and build its tree and it is SVG and not matplotlib so that if I ever decide to turn this program into a website, I can simply plug in this code and get the output straight in a web page. How it works: For the people curious as to how it works, I am sorry if my explanation does not make sense because even I do not understand it very well (I am pretty bad at recursion). basically, the main function that lets me plot these nodes in a 2D space is assign_positions. If we do not focus on recursion yet, the basic idea of this function is that there are 2 types of node: leaf nodes and internal nodes . Leaf nodes are the nodes which do not have any children and terminate the branch i.e. are terminal . whereas, internal nodes have children and branch out further to extend the tree i.e. are non-terminal . The basic hypothesis was that if there are two leaf nodes, and I assign them an x-position of 0 and 1, their parent node should be at a position which is the mid point (or average) of its children. Which means, the parent node of two leaf nodes (or internal nodes) at x-position 0 and 1 would lie at x-position 0.5 (avg of 0 and 1). now for the y-position, I have used depth as the name where the idea was simply that with every new node, the depth should increase by 1. Now we come to recursion and how I generalized this position idea to any possible tuple. The basic things that the assign_positions function takes are: node-> Current node depth-> Current depth/ y-position id_count-> The ID assigned to the node leaf_count-> Basically the x-position of the leaves tree-> Current tree dictionary There are 2 cases, the node can either be a leaf or an internal node. If the node is a leaf node, then we simple make the tree: tree[str_id] = {'label': node, 'x': str_x, 'depth': depth} . we increase leaf_count by 1 (because if the x-position assigned to this node was 0 then the next leaf node should have it as 1) and we increase id_count by 1. This case returns the x-position assigned to this node-> str_x, the id assigned to this node-> str_id, the current id_count, the current leaf_count and the current tree. These specific constraints are returned because If a parent had done a recursive call and the node was a leaf node then the parent would require: the child’s x position to average left and right positions to set its own position. the child’s id to keep track of it in its own dictionary. the current id_count and leaf_count so that an assigned number is not reassigned to another node by mistake in a recursive call. Case-2 and tree rendering covered in next devlog"}, {"post_id": 26425, "ts": "2026-07-11T06:35:09Z", "hours": 1.6078, "text": "Debugging Day fixed unary negative operation on a function like -sqrt in the tokenizer. added support for implicit multiplication in the tokenizer (right now only valid for alphabets after numbers like 3x, 25x, etc. and not for alphabet after alphabet like xsin(x), xlog(x), etc.) fixed the decimal point collection in the tokenizer due to the failed test case: -.5 Added support for exponents by adding parse_pow() . initially i had simply copied the structure of parse_add and parse_mul and ran the test case but i found out that the result was wrong. My current parsing algorithm has natural left associativity, which is required for other operators but, is wrong for power. Because, 2^3^2 should result in 2^(3^4) and not (2^3)^4, which means i needed right associativity. For getting right associativity, i had to make it such that the right term of the node was recursively calling parse_pow(), so that everything after it would get parsed first which would give us right associativity."}, {"post_id": 25763, "ts": "2026-07-10T06:37:12Z", "hours": 5.1942, "text": "Parser Testing I spent about 4 hours testing and debugging the recursive decent parsing algorithm, trying to understand the flow by writing each and every step. Here are my test cases. Test case-1 exp = 2+3*4 tokens = ['2', '+', '3', '*', '4'] expected result = ('+', 2, ('*', 3, 4)) This test case was used so that i can better understand parse_add and parse_mul along with the main parse_atom. Reached the correct answer. Found a bug in approach: I was not handling the case when pos was out of index ideally. Researched a bit on RDP and found out there is a basic template used in RDP which is while pos < len(tokens) ... and thus used this refined knowledge in my successive attempts. Test case-2 exp = 2+3+4+5 tokens = ['2', '+', '3', '+', '4', '+', '5'] expected result = ('+', ('+', ('+', 2, 3), 4), 5) This specific test case defines why a while loop is important as it includes accumulation of same operator. I wanted to work through this by hand as I was really confused why we need a while loop instead of a simple if-else check whether the pos is out of range or not but the answer became clean when i worked through it. Reached the correct answer. Test case-3 exp = (2+3)*4+1 tokens = ['(', '2', '+', '3', ')', '*', '4', '+', '1'] expected result = ('+', ('*', ('+', 2, 3), 4), 1) I used this test case as it introduces parenthesis into the parsing algorithm which is a fundamental feature. correctly worked through the parsing and reached the correct answer. Parser I also completed the v1 of the parser in just 20 minutes. It is pretty hilarious that it took me 4 hours just to understand RDP but 20 minutes to code it. But, I believe those were 4 hours well spend because earlier, I found RDP to be mind breaking, but now I understand it so well that I think I can teach it even to a 12 year old."}, {"post_id": 24691, "ts": "2026-07-08T13:28:05Z", "hours": 1.3383, "text": "Tokenizer progress: 1. Added decimal point support: Failed attempt : I initially tried to detect . from inside the .isdigit if-elif loop like detecting a continuation of digits but failed on case \"12.34\" → ['1234'] and then found the simpler solution. Added elif exp[i] == \".\": num.append(exp[i]) as its own top-level case, letting a decimal point unconditionally join whatever number is currently being built inside the num list. all test cases passed: \"0.3 + 1.5436* 245\" → ['0.3', '+', '1.5436', '*', '245'] . And, \"3.5\" , \".5\" , \"12.34\" all correctly maintained their decimal points. tested all of the previous test cases like multi-digit numbers, multi-letter function names, parentheses, mixed expressions and all passed . 2. Added Unary minus v/s binary subtraction distinction: While thinking of some more edge cases, I found a case \"2*-3\" → ['2', '*', '-', '3'] which was wrong and I found out that the tokenizer needs to make the distinction between a unary minus -3 , -x , etc. and a binary minus 2-3 , x-4 , etc. Added a special condition for - in the top level operator detecting if block and handling edge cases in the .isdigit and .isalpha elif blocks. All test cases passed:- \"3-2\" → ['3', '-', '2'] \"3*-2\" → ['3', '*', '-2'] \"-2+3\" → ['-2', '+', '3'] \"(-2)\" → ['(', '-2', ')'] \"3--2\" → ['3', '-', '-2'] 3. Added support for new operators and functions: Support for ^ operator by adding it to the top level operator detecting if block . Support for Absolute Value |x| by adding it to the top level operator detecting if block . Support for Fractional Part Function {x} by adding it to the top level operator detecting if block . Support for Greatest Integer Function [x] by adding it to the top level operator detecting if block . Also added these cases inside the unary minus handling if block thus passing all possible test cases. Status: The tokenizer part is complete for now. There are a few changes to be made, like adding support for implicit multiplication. Though, it is something that could be handled by the parser so I will handle it as time comes."}, {"post_id": 24112, "ts": "2026-07-07T14:03:11Z", "hours": 1.9192, "text": "This is the first devlog for my Domain and Range calculator. I have completed making the first part of my custom AST algorithm: the tokenizer. I have used simple string parsing to separate specific terms in the expression. The algorithm handles sequence of characters (like alphabets or digits) as a single term which opens up the world to more complex and some basic and necessary functions like sqrt(), log(), trigonometric and inverse trigonometric functions. I am now going to handle some edge cases and try to functionize or shorten the collection of characters part as I have noticed that The process is same for digit and alphabets so I could potentially shorten the code. I expect this program to fit cleanly into the larger mathematical suit that I am trying to build to support most of mathematics along with support for coordinate geometry but that is something for later."}]...
|
Title: Math Suite by @R10 | Stardance
Devlogs:
Th Title: Math Suite by @R10 | Stardance
Devlogs:
This is the first devlog for my Domain and Range calculator. I have completed making the first part of my custom AST algorithm: the tokenizer. I have used simple string parsing to separate specific terms in the expression. The algorithm handles sequence of characters (like alphabets or digits) as a single term which opens up the world to more complex and some basic and necessary functions like sqrt(), log(), trigonometric and inverse trigonometric functions. I am now going to handle some edge cases and try to functionize or shorten the collection of characters part as I have noticed that The process is same for digit and alphabets so I could potentially shorten the code. I expect this program to fit cleanly into the larger mathematical suit that I am trying to build to support most of mathematics along with support for coordinate geometry but that is something for later.
Tokenizer progress: 1. Added decimal point support: Failed attempt : I initially tried to detect . from inside the .isdigit if-elif loop like detecting a continuation of digits but failed on case "12.34" → ['1234'] and then found the simpler solution. Added elif exp[i] == ".": num.append(exp[i]) as its own top-level case, letting a decimal point unconditionally join whatever number is currently being built inside the num list. all test cases passed: "0.3 + 1.5436* 245" → ['0.3', '+', '1.5436', '*', '245'] . And, "3.5" , ".5" , "12.34" all correctly maintained their decimal points. tested all of the previous test cases like multi-digit numbers, multi-letter function names, parentheses, mixed expressions and all passed . 2. Added Unary minus v/s binary subtraction distinction: While thinking of some more edge cases, I found a case "2*-3" → ['2', '*', '-', '3'] which was wrong and I found out that the tokenizer needs to make the distinction between a unary minus -3 , -x , etc. and a binary minus 2-3 , x-4 , etc. Added a special condition for - in the top level operator detecting if block and handling edge cases in the .isdigit and .isalpha elif blocks. All test cases passed:- "3-2" → ['3', '-', '2'] "3*-2" → ['3', '*', '-2'] "-2+3" → ['-2', '+', '3'] "(-2)" → ['(', '-2', ')'] "3--2" → ['3', '-', '-2'] 3. Added support for new operators and functions: Support for ^ operator by adding it to the top level operator detecting if block . Support for Absolute Value |x| by adding it to the top level operator detecting if block . Support for Fractional Part Function {x} by adding it to the top level operator detecting if block . Support for Greatest Integer Function [x] by adding it to the top level operator detecting if block . Also added these cases inside the unary minus handling if block thus passing all possible test cases. Status: The tokenizer part is complete for now. There are a few changes to be made, like adding support for implicit multiplication. Though, it is something that could be handled by the parser so I will handle it as time comes.
Parser Testing I spent about 4 hours testing and debugging the recursive decent parsing algorithm, trying to understand the flow by writing each and every step. Here are my test cases. Test case-1 exp = 2+3*4 tokens = ['2', '+', '3', '*', '4'] expected result = ('+', 2, ('*', 3, 4)) This test case was used so that i can better understand parse_add and parse_mul along with the main parse_atom. Reached the correct answer. Found a bug in approach: I was not handling the case when pos was out of index ideally. Researched a bit on RDP and found out there is a basic template used in RDP which is while pos < len(tokens) ... and thus used this refined knowledge in my successive attempts. Test case-2 exp = 2+3+4+5 tokens = ['2', '+', '3', '+', '4', '+', '5'] expected result = ('+', ('+', ('+', 2, 3), 4), 5) This specific test case defines why a while loop is important as it includes accumulation of same operator. I wanted to work through this by hand as I was really confused why we need a while loop instead of a simple if-else check whether the pos is out of range or not but the answer became clean when i worked through it. Reached the correct answer. Test case-3 exp = (2+3)*4+1 tokens = ['(', '2', '+', '3', ')', '*', '4', '+', '1'] expected result = ('+', ('*', ('+', 2, 3), 4), 1) I used this test case as it introduces parenthesis into the parsing algorithm which is a fundamental feature. correctly worked through the parsing and reached the correct answer. Parser I also completed the v1 of the parser in just 20 minutes. It is pretty hilarious that it took me 4 hours just to understand RDP but 20 minutes to code it. But, I believe those were 4 hours well spend because earlier, I found RDP to be mind breaking, but now I understand it so well that I think I can teach it even to a 12 year old.
Debugging Day fixed unary negative operation on a function like -sqrt in the tokenizer. added support for implicit multiplication in the tokenizer (right now only valid for alphabets after numbers like 3x, 25x, etc. and not for alphabet after alphabet like xsin(x), xlog(x), etc.) fixed the decimal point collection in the tokenizer due to the failed test case: -.5 Added support for exponents by adding parse_pow() . initially i had simply copied the structure of parse_add and parse_mul and ran the test case but i found out that the result was wrong. My current parsing algorithm has natural left associativity, which is required for other operators but, is wrong for power. Because, 2^3^2 should result in 2^(3^4) and not (2^3)^4, which means i needed right associativity. For getting right associativity, i had to make it such that the right term of the node was recursively calling parse_pow(), so that everything after it would get parsed first which would give us right associativity.
AST Visualizer After completing my tokenizer and parser with a few fixes, I wanted to move straight onto building the actual domain and range logic and setting up all the constraints, but instead, I had another idea. Whenever I saw the output of my parser, it just seemed a bit meh . The output was just a nested tuple and it was not looking like what I had built was a tree. So, as a side quest, I built an SVG AST visualizer that takes the tuple and build its tree and it is SVG and not matplotlib so that if I ever decide to turn this program into a website, I can simply plug in this code and get the output straight in a web page. How it works: For the people curious as to how it works, I am sorry if my explanation does not make sense because even I do not understand it very well (I am pretty bad at recursion). basically, the main function that lets me plot these nodes in a 2D space is assign_positions. If we do not focus on recursion yet, the basic idea of this function is that there are 2 types of node: leaf nodes and internal nodes . Leaf nodes are the nodes which do not have any children and terminate the branch i.e. are terminal . whereas, internal nodes have children and branch out further to extend the tree i.e. are non-terminal . The basic hypothesis was that if there are two leaf nodes, and I assign them an x-position of 0 and 1, their parent node should be at a position which is the mid point (or average) of its children. Which means, the parent node of two leaf nodes (or internal nodes) at x-position 0 and 1 would lie at x-position 0.5 (avg of 0 and 1). now for the y-position, I have used depth as the name where the idea was simply that with every new node, the depth should increase by 1. Now we come to recursion and how I generalized this position idea to any possible tuple. The basic things that the assign_positions function takes are: node-> Current node depth-> Current depth/ y-position id_count-> The ID assigned to the node leaf_count-> Basically the x-position of the leaves tree-> Current tree dictionary There are 2 cases, the node can either be a leaf or an internal node. If the node is a leaf node, then we simple make the tree: tree[str_id] = {'label': node, 'x': str_x, 'depth': depth} . we increase leaf_count by 1 (because if the x-position assigned to this node was 0 then the next leaf node should have it as 1) and we increase id_count by 1. This case returns the x-position assigned to this node-> str_x, the id assigned to this node-> str_id, the current id_count, the current leaf_count and the current tree. These specific constraints are returned because If a parent had done a recursive call and the node was a leaf node then the parent would require: the child’s x position to average left and right positions to set its own position. the child’s id to keep track of it in its own dictionary. the current id_count and leaf_count so that an assigned number is not reassigned to another node by mistake in a recursive call. Case-2 and tree rendering covered in next devlog
AST Visualizer (continued) Case-2 If the node is not a leaf (i.e. not a string) we will again check for 2 cases. the node can either have 1 child or 2 children. If there are 2 children then we have to make 2 recursive calls but if we have a single child then only one and the other stuff is pretty similar so I will only explain the case when there are 2 children. first of all, we unpack the node to get op, left and right. Now we call assign_positions with depth+1 (to effectively track each level we go down), on left and right and extract: x-position of children, id of children and the parameters that get updated (id_count and leaf_count). next, we used children’s x-position, average it to get the op’s x-position. We make the tree: tree[op_id] = {'label': op, 'x': op_x, 'depth': depth, 'children': [l_id, r_id]} . Now we increase the id_count by 1 but not the leaf_count as we have not encountered a leaf (I had made a mistake here and increased leaf_count in the case where the node is not a leaf because I had named the variable as x_position earlier and thought that it must increment everywhere but forgot that we are averaging the children’s x-position to get op’s x-position so i do not need to increment it, which is why I have cleared this up). Now we return the same stuff: op_id, id_count, op_x, leaf_count, tree. Rendering Tree The actual tree generation is simply looping through the dictionary. The important function is converting x_position and depth values that are simple integers into actual pixel positions to actually position the circles in the correct spot which is done by pixel_x = margin+x*x_spacing and pixel_y = margin+depth*y_spacing where margin, x_spacing and y_spacing are all hyper-parameters. The next function is draw_nodes which simply loops though the values of tree dictionary gets the x and depth for each node, converts them to actual coordinated using get_pixel_coords and then creates the svg line: '<circle cx="{x}" cy="{y}" r="25" fill="white" stroke="black" /> <text x="{x}" y="{y}" text-anchor="middle" dominant-baseline="middle">{i['label']}</text>' for each node and its text. The other is draw_lines. It takes all the parent nodes and gets their x and y value as pixel coordinates. Then, it gets the children of the node and for each child’s id, the function gets the child by its id, then gets the x and y coordinates of the child as pixel coordinates and then draws the line as per this syntax: f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" stroke="white" />' Finally we have the render_expression function which wraps everything into a single sequence of operations and creates the final svg code: f'<svg xmlns="http://www.w3.org/2000/svg" width="850" height="650"> {lines} {nodes} </svg>' and created an svg file to view the final tree.
Domain Calculation Started the domain calculation file (domain.py) and made the function get_constraints() that recurses through the tree to look for domain restricting operators like /, sqrt, log, arcsin, etc. into a list. next steps are to solve each of the generated constraints (inequalities) and then combine them to get the domain for x (or any variable). Currently working on trying to solve the inequalities but it is proving to be pretty difficult so it could take longer than usual.
It has been a tough journey If you read my previous devlog, it almost feels like i was foreshadowing what was about to happen to me. While making the solve_node function which would solve the inequality for x, i got lost in the mess of symbolic mathematics and started handling cases with fallbacks upon fallbacks. It has really a hot mess, I got to find out that there can be many types of questions and to solve every type of domain question, I would need fallback logic for every type of question which would mean I would have to encompass all the techniques in domain finding into the file and manage the interaction of the techniques and orchestrate them at a high level and basically making my own sympy (which took decades to build). I even thought of quitting a few times and the project was basically at a halt for 1-2 days. I then decided to solve a simple domain question by hand to check what really are the steps of finding the domain of a function. I found out that my logic up until making the constraints was fine. The next steps were finding critical points for example: (x-2)(x+3)>0 would have critical points 2 and -3 (they are just the points where the function is zero). Now, I also know that critical points also occur when the sign of the function changes or when its nature changes (going from defined to undefined and vice-versa) so instead of making a symbolic critical point finding function I thought of a more brute force method. If I have a number line (range of numbers) and i simply walk through them one by one, noting sign change between 2 numbers as a sign “there is a critical point here” and then use another function to basically go into each of those marked intervals and continuously half the interval (think of it as taking an interval and then zooming into the interval until you find the critical point) until about 9 decimal places (could be anything, it is just the amount of accuracy), you would get the critical point pretty accurately without having to solve anything using logic or symbolically, just substitute values of x. After finding the critical points, turning it into domain is as simple as just substituting points and see if the inequality holds.
Union and Intersection of intervals I have made the intersection function which takes intervals and unions them together. I am now working on the union function. I initially used recursion to do the job but that was incorrect that the better method was just to sort the intervals list and then use a simple loop to evaluate the union. Here is the issue i was facing: [[A, B, C, D], E] AUE-> False, BUE-> False, CUE-> True => [F, A, B, D] union [F, A, B, D]-> FUA-> False => [[F,A], B, D] again [F,A], B => FUB-> False, BUA-> False => [F, A, B] => union this list now => FUA-> False => [[F,A], B] then again [F,A], B => FUB-> False, BUA-> False => [F, A, B] => FUA-> False => [[F,A], B] this goes on and on infinitely This is a problem of infinite recursion
Devlog #10 Completed domain.py finished coding domain.py and tested about 20 test-cases on it. Completed debugging to finally finish domain calculation and start with Range. I do not know what else to tell you all as it has been a few days of coding and debugging with different bugs surfacing like incorrect handling of undefined functions, normalizing output, handling union cases correctly, etc.
Derivative For finding the range, I am opting for method of differentiation to check intervals. hence, I have made derivative.py for differentiation. This is my second derivative calculator. The first one that I built was made completely using string slicing and weird string manipulation and pretty biased logic where everything was stored in the form of a dictionary. To be honest, I was pretty proud of that calculator because I was able to make it just using the knowledge I had, and recursion is not innate (I think) and I was still able to do it so I am proud of it. But, it was no doubt pretty inefficient with a lot of edge cases. Therefore, this time i am making a better calculator using my new AST representation and A LOT more recursion. This calculator will process more functions and it will be able to simplify the derivative too, for example: derivative of 2x^2 will not be displayed as 2*2x, rather it will be correctly displayed as 4x.
STUCK So basically, since my last devlog, the main feature of the new derivative calculator that I had proudly announced is now coming to bite me. The simplification is so tough. Let me explain you all the turn of events. (Simplification is still not complete) basically, my initial idea of simplification was just removing all the temporary zeros and ones that were generated by the derivative itself. Then I thought of increasing the initial scope to support some other simplifications like (‘ ’, ‘2’, (’ ’, ‘2’, ‘x’)) should be solved to (‘ ’, ‘4’, ‘x’). I managed to achieve this simplification too but, I found out there are a lot more simplification cases that I need to handle after we get the derivative. for example: x - 3x, which should be simplified to -2x. For that I had to build an approach which would take the coefficient and base then operate on the coefficients for the same bases according to the operator. Therefore, for x the coeff is 1 and then for 3x the coeff is 3 but that is incorrect. In the case of x-3x, the coefficients should be 1 and -3 so that when i add them i get -2 as the final coefficient for x. To do that, I had to switch all binary subtraction expression and turn them into additive unary negative for op = ‘+’ so that x - 3x turns into x + (-3x). Now, all this actually worked but the main problem was that now the flattened list looks like [‘x’, (’ ’, ‘-1’, (‘ ’, ‘3’, ‘x’))] which means I cannot reliably extract the coefficients now. I first have to handle the recursive case of flattening the node again, turning (’ ’, ‘-1’, (‘ ’, ‘3’, ‘x’)) to the flattened version [‘-1’, ‘3’, ‘x’] and then i would have to run it back through combine where it would be formed as calc = -3 and symbols = ‘x’ and then rebuild it as the node (’ ’, ‘-3’, ‘x’). Only after that can i actually extract the coefficients and compare the bases of the two expressions which would be 1 and -3 and calculate them according to the op => ‘+’ to finally give -2 as calc and ‘x’ as symbols and then rebuild that again into (‘ ’, ‘-2’, ‘x’) to solve it. Now this was just one case for one operator but i need to handle both ‘+’ and ’ ’ as the both have associativity and there are other cases for other ops too like x^2/x should just simplify to x. I have already added so much code that I myself feel like the approach is very wrong and the more I build the more edge cases I am adding because right now the amount of if-else handling for specific cases is crazy so I really think that I need to reconsider my approach for simplification. The derivative calculator is taking too much time considering it is an intermediate step but I think it would be worth it because this simplification step is something that I have never done before so I would be learning something anyway.
DEVLOG #13 I have completed the basic simplification functions now but, it is not working perfectly and there are still some changes to be made. for example, handling cases where it is multiplied by 0, or when 0 is added, or it is multiplied by 1, etc. so I think it requires a bit more of iterative debugging to catch all of the edge cases. I have formalized the design of simplification into: Flatten -> form_term -> merge_terms -> form_node -> rebuild which is much better then the previous logic that I had where I was adding more edge cases for handling each case. Right now I will be testing the full recursion for a test case to check where it goes wrong right now in the pipeline to fix it.
DEVLOG #14 Completed the full simplify_initial pipeline. Handled cases with 0 and 1 and traced a full long recursion by hand to better understand the pattern and make iterative debugging faster. Also handled negative node by simplifying the ('*', '-1', right) node formed so that any coefficients collapse cleanly and the term can form correctly with a negative coefficient. EXAMPLE:- Earlier: x - 3x -> terms = [(1.0, 'x', 1.0), (-1.0, ('*', '3', 'x'), 1.0)] Now: x - 3x -> terms = [(1.0, 'x', 1.0), (-3.0, 'x', 1.0)] Therefore, now merging terms will result in ('*', '-2', 'x') I pasted my code into claude and asked it to generate me some test cases which it believes would fail and now I am working on debugging them with a mix of hand tracing recursion and simple fixes so the pipeline is almost at its end (I hope).
DEVLOG #15 Real PROGRESS! Completed the full differentiation pipeline which is working completely now with all edge cases (that I have tested) handled. converted simplify to a standalone file as I noticed that simplify could be used as a general simplification pipeline for ALL generated nodes in my maths suite. Created pow_to_div function in simplify to turn negative exponents into division nodes to make the simplification pipeline truly generalized because none of my other algorithms expect a negative exponent. A LOT of debugging in domain.py and testing some edge cases. Adding support for multiple exclusions instead of single in normalize_domain . Earlier: (-∞, -2) ∪ (-2, 2) ∪ (2, ∞) Now: R-{-2, 2} which is a much cleaner solution Now I am working on completing range.py and then finally making the website for the full maths suite. I am a bit confused. I am not able choose between flask and FastAPI. If you have read all this then would you also mind sharing your opinion on what should I use in the comments?
DEVLOG #16 More PROGRESS! completed range.py tested edge cases with some pretty nasty ones and have decided to leave some limitations like not supporting gif/frac/sec/tan… functions because of their nature. General Debugging created all the flask endpoints along with the basic HTML layout of the website and wiring in the JS. Website is tested and all endpoints are working Now, I will focus on adding some styling to the website and also making the user experience better.
DEVLOG #17 Completed Styling (would appreciate feedback) Features: AST generator AST visualizer (downloadable SVG trees) Domain calculator Range Calculator Derivative calculator Simplification Next steps: AST back to expression generator because right now all the calculators give the result in terms of AST nodes so i need a reverse-parser which I think would be easy. Making a simpler bare bones CLI tool for simpler People. adding a guide page to the website explaining all the limitations and syntax of the calculator. hosting on my own domain? That is all that I can think for now. Right now I have not hosted the website because I am thinking of adding a few more features like user changeable SVG node and line colors, etc.
DEVLOG #18 LIVE PROJECT I have finally deployed the Version-1 of the project on vercel, check it out at the link above. I also completed the README for my repo explaining all the features and limitations of the project. Now I will be working on making an unparser to show the users a clean expressions as a result from the calculator instead of AST nodes and I will also add a guide page on the website for the syntax rules and general guide.
DEVLOG #19 Another Setback I was working on the unparse function today. Basically the idea was simply to recurse through the tree and form the expression as a string. Now, the hard part in this was to decide when to apply parenthesis. Basically, we have to apply parenthesis to any child of the function which has a lower precedence then the current parent op. I did not have this idea as well set in my mind when i was making this function and I just wasted 4 hours today trying to stack up elif cases with or conditions to try to cover every shape. Basically, I was thinking that for * / / , there are only 4 base cases: both children need parenthesis left needs parenthesis right needs parenthesis none need parenthesis I took that as a starting point and then i started to think of cases which would satisfy that and that caused me to build up this or-or-or jargon. I am really pissed. Now I will change my direction and move onto a precedence based approach which checks if the precedence of the child is lesser than the parent op, if yes then parenthesize it and if no then check if precedence is equal, if it is then check for associativity. That is the plan and I hope I don’t mess up this time.
DEVLOG #20 Completed and wired Unparser TRY NEW UPDATE I completed the unparser now with the precedence based approach and I can’t believe how much simpler it is and how bad my initial approach was. The thing that makes it work is the new needs_paren function which basically does all the precedence based logic of telling if the child needs parenthesis or not. Basically if the child’s precedence is lower than the parent op then we need a parenthesis. For example: if the child is a + node and the parent is a * node then we would need parenthesis on the child. For example: (x+1) * 3 -> x+1 needed parenthesis. The main part that made me think a bit was the case when precedence of the child and parent is equal. There are basically 3 cases here: When op is + or * , the child never needs parenthesis. When op is - or / , the child only need parenthesis if it is on the right side. For example: precedence of + == - , a + b - c -> a+b is on the left side and hence does not needs parenthesis. Whereas, c - (a+b) -> a+b on the right side needs parenthesis because this basically means c - a - b and not c - a + b . Hence, parenthesis is required. When op is ^ , parenthesis is only required when the child is on the left and not when it is on the right. For example: a^b^c does not need parenthesis (even though it could be written as a^(b^c) ) but, (a^b)^c needs parenthesis because this means a^(b*c) as the powers multiply. I have also wired in the unparser function to derivative and simplify too so now the result is an expression instead of a tuple. Now I will update my README.md and explain the working of the unparser and then I will work on adding the guide page to my website.
DEVLOG #21 Completed the CLI tool and created binaries for windows and linux using pyinstaller. Also completed the full Guide page on the website with all the relevant rules, syntax and limitations listed cleanly....
|
1793206203.400674
|
1793811003.400674
|
|
6535
|
My awesome macropad! by @nina | Stardance
|
nina
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @nina | Stardance
|
1792781265.2076168
|
1793386065.2076168
|
|
6536
|
jscraper by @project516 | Stardance
|
project516
|
0
|
3.0
|
0
|
[]
|
[{"post_id": 2756, "ts": "2026 [{"post_id": 2756, "ts": "2026-06-05T15:09:46Z", "hours": 3.0, "text": "simple gui"}]...
|
Title: jscraper by @project516 | Stardance
Devlog Title: jscraper by @project516 | Stardance
Devlogs:
simple gui...
|
1792925682.3764853
|
1793789682.3764853
|
|
6537
|
chess by @reyaanshrajmishra | Stardance
|
reyaanshrajmishra
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: chess by @reyaanshrajmishra | Stardance
|
1793173855.5895631
|
1793778655.5895631
|
|
6538
|
My first slack bot! by @valeOz-999 | Stardance
|
valeOz-999
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @valeOz-999 | Starda Title: My first slack bot! by @valeOz-999 | Stardance...
|
1793299980.1541555
|
1793904780.1541555
|
|
6539
|
My awesome macropad! by @shaunthepyro | Stardance
|
shaunthepyro
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @shaunthepyro | Sta Title: My awesome macropad! by @shaunthepyro | Stardance...
|
1793227760.8572607
|
1793832560.8572607
|
|
6540
|
My first slack bot! by @reyaanshrajmishra | Starda My first slack bot! by @reyaanshrajmishra | Stardance...
|
reyaanshrajmishra
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @reyaanshrajmishra | Title: My first slack bot! by @reyaanshrajmishra | Stardance...
|
1793256985.944424
|
1793861785.944424
|
|
6541
|
My awesome macropad! by @Flambi | Stardance
|
Flambi
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @Flambi | Stardance
|
1792687953.294094
|
1793292753.294094
|
|
6542
|
My awesome macropad! by @anikwhatnot | Stardance
|
anikwhatnot
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @anikwhatnot | Star Title: My awesome macropad! by @anikwhatnot | Stardance...
|
1792738520.6688406
|
1793343320.6688406
|
|
6543
|
My awesome macropad! by @Siyog | Stardance
|
Siyog
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @Siyog | Stardance
|
1792659021.0841246
|
1793263821.0841246
|
|
6544
|
Rubrics Cubes by @Lol123rl | Stardance
|
Lol123rl
|
1
|
1.0
|
12
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-15T22:10:41Z", "hours": 1.0, "multiplier": 10.72, "payout": 12, "blessing": "neutral", "text": "I made a Rubic Cube game where you can solve between a 2x2 - 10x10. It was a fun quick project with the auto scrambler. Have fun.", "repo": "https://github.com/Lol123rl/Cube", "demo": "https://stunning-starship-b67fed.netlify.app/"}]...
|
[{"post_id": 1564, "ts": "2026 [{"post_id": 1564, "ts": "2026-06-03T17:40:42Z", "hours": 1.0936, "text": "rubics cube"}]...
|
Title: Rubrics Cubes by @Lol123rl | Stardance
Dev Title: Rubrics Cubes by @Lol123rl | Stardance
Devlogs:
rubics cube
Ships:
I made a Rubic Cube game where you can solve between a 2x2 - 10x10. It was a fun quick project with the auto scrambler. Have fun....
|
1793310968.3201368
|
1793397368.3201368
|
|
6545
|
My awesome macropad! by @krishb | Stardance
|
krishb
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @krishb | Stardance
|
1793328478.0955935
|
1793933278.0955935
|
|
6546
|
no_title by @core_cryptic_io | Stardance
|
core_cryptic_io
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: no_title by @core_cryptic_io | Stardance
|
1793303237.3635662
|
1793908037.3635662
|
|
6547
|
My first slack bot! by @core_cryptic_io | Stardanc My first slack bot! by @core_cryptic_io | Stardance...
|
core_cryptic_io
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @core_cryptic_io | S Title: My first slack bot! by @core_cryptic_io | Stardance...
|
1792770594.5233254
|
1793375394.5233254
|
|
6548
|
My first slack bot! by @RakeshJai | Stardance
|
RakeshJai
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @RakeshJai | Stardan Title: My first slack bot! by @RakeshJai | Stardance...
|
1793288958.8337128
|
1793893758.8337128
|
|
6549
|
Hunter Games by @LoginlikeLogan | Stardance
|
LoginlikeLogan
|
2
|
18.0
|
22
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-07T14:24:03Z", "hours": 11.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "So I made a Games website to play some fun games. I went through many challenges of going through bugs and site issues. Hope you guys enjoy this site and support me!", "repo": "https://github.com/Logdegret/HunterGames", "demo": "https://logdegret.github.io/HunterGames/"}, {"ship_num": 2, "ts": "2026-06-04T00:12:29Z", "hours": 7.0, "multiplier": 15.05, "payout": 22, "blessing": "neutral", "text": "I made a game site called Hunter games that is on a github website. It is open sourced, fun, and highly addicting. I am currently still working out a few bugs but most of the games are fully playable. I did not create the games except bossbound which I used AI to make (sadly). Bossbound is still a work in progress but other than that enjoy!", "repo": "https://github.com/Logdegret/HunterGames", "demo": "https://logdegret.github.io/HunterGames/"}]...
|
[{"post_id": 21745, "ts": "202 [{"post_id": 21745, "ts": "2026-07-03T20:40:35Z", "hours": 0.7319, "text": "Site Back Up! 😁 Ive got the site back up! I think this was a github Issue but feel free to go and play some games now bc Ive added a few more new games that are pretty addicting! Btw these are NOT all of the games"}, {"post_id": 20928, "ts": "2026-07-02T17:31:09Z", "hours": 1.115, "text": "SOOOO many bugs! this is horrible! there is so many deployment bugs that need to be fixed which might be githubs fault since it might be down rn, so I might try agian tomorrow"}, {"post_id": 20262, "ts": "2026-07-01T20:11:48Z", "hours": 0.5294, "text": "Added two more games and will be done pretty soon! Check it out I added two more games, Google doodle baseball and 3 slices to the website!"}, {"post_id": 16037, "ts": "2026-06-26T01:35:52Z", "hours": 1.0981, "text": "Missing games fixed!"}, {"post_id": 14383, "ts": "2026-06-23T14:27:39Z", "hours": 0.6692, "text": "Fixing spacing issues and added OvO"}, {"post_id": 11954, "ts": "2026-06-19T14:47:19Z", "hours": 1.5383, "text": "I added a new logo and created a dev mode to add games, bugs though need to be fixed…"}, {"post_id": 5562, "ts": "2026-06-09T12:02:29Z", "hours": 5.205, "text": "Complete rework! Added friends list, and stats!😙"}, {"post_id": 1789, "ts": "2026-06-04T00:08:43Z", "hours": 0.4333, "text": "Added an opensourced golf game that was found on github. Kinda doesn’t work right now but it is a work in progress"}, {"post_id": 1770, "ts": "2026-06-03T23:21:50Z", "hours": 0.5283, "text": "Added Xp bar to home ui, There are still bugs though"}, {"post_id": 1751, "ts": "2026-06-03T22:49:43Z", "hours": 5.895, "text": "Fixing Hunter Games Bugs"}]...
|
Title: Hunter Games by @LoginlikeLogan | Stardance Title: Hunter Games by @LoginlikeLogan | Stardance
Devlogs:
Fixing Hunter Games Bugs
Added Xp bar to home ui, There are still bugs though
Added an opensourced golf game that was found on github. Kinda doesn’t work right now but it is a work in progress
Complete rework! Added friends list, and stats!😙
I added a new logo and created a dev mode to add games, bugs though need to be fixed…
Fixing spacing issues and added OvO
Missing games fixed!
Added two more games and will be done pretty soon! Check it out I added two more games, Google doodle baseball and 3 slices to the website!
SOOOO many bugs! this is horrible! there is so many deployment bugs that need to be fixed which might be githubs fault since it might be down rn, so I might try agian tomorrow
Site Back Up! 😁 Ive got the site back up! I think this was a github Issue but feel free to go and play some games now bc Ive added a few more new games that are pretty addicting! Btw these are NOT all of the games
Ships:
I made a game site called Hunter games that is on a github website. It is open sourced, fun, and highly addicting. I am currently still working out a few bugs but most of the games are fully playable. I did not create the games except bossbound which I used AI to make (sadly). Bossbound is still a work in progress but other than that enjoy!
So I made a Games website to play some fun games. I went through many challenges of going through bugs and site issues. Hope you guys enjoy this site and support me!...
|
1792875200.2760565
|
1793739200.2760565
|
|
6550
|
Leading Zeros Utility by @infinite_silly | Stardan Leading Zeros Utility by @infinite_silly | Stardance...
|
infinite_silly
|
2
|
23.0
|
304
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-07T21:43:33Z", "hours": 17.0, "multiplier": 17.27, "payout": 289, "blessing": "neutral", "text": "Hello everyone! I was working on some Project Euler problems, and I realised that my solutions weren’t sorting correctly because they didn’t have any leading zeros in the numeric portion of their filenames. The same issue happened for my Advent of Code solutions once I hit day 10. I realised I could automate this, and the leading-zero-util was born. It slowly grew from a little, mediocre script to a decently-ish written CLI tool with proper unit tests, a Homebrew tap, a man page, and completions. If you want a better look at the development process than just the devlogs, please check out my commits on GitHub. If you are going to install the LZU, I also recommend that you use the Homebrew tap rather than the crates.io release, the instructions for which are in the README.", "repo": "https://github.com/KaonQuantum/leading-zero-util", "demo": "https://crates.io/crates/leading-zero-util"}, {"ship_num": 2, "ts": "2026-06-10T15:04:30Z", "hours": 6.0, "multiplier": 2.57, "payout": 15, "blessing": "neutral", "text": "I made a utility to change the number of leading zeros in filenames! I was working on Project Euler and had to add a leading zero to all my filenames, which was tedious, so I made this!", "repo": "https://github.com/KaonQuantum/leading-zero-util", "demo": "https://crates.io/crates/leading-zero-util"}]...
|
[{"post_id": 42843, "ts": "202 [{"post_id": 42843, "ts": "2026-08-07T19:41:19Z", "hours": 0.9986, "text": "Drop it Like it’s Hot THIS IS THE FINAL DEVLOG!!!! We got a working release! After my last devlog, I added some unit tests for skip_rename(), and I added the Github default Rust workflow with some modifications to the repo to automatically test any new commits against the test suit, which is most of my codebase. Also added a test workflow to the homebrew tap so it’s easier to see that all is working."}, {"post_id": 42489, "ts": "2026-08-07T08:00:31Z", "hours": 1.3761, "text": "Refactor I’m going to keep this one quick because it just got deleted for being too long. The previously mentioned behaviour of overwriting filenames has been fixed and has it’s own unit test now. It was given an exception before the actual rename. All the rename logic was duplicated between dec and !dec, so I flattened that. I pulled out the pre-rename exception logic into a new helper: skip_rename(). It needs unit tests of its own. Byyyeeeeee!!!"}, {"post_id": 42432, "ts": "2026-08-07T04:14:30Z", "hours": 1.0014, "text": "I’m Smart but I’m Bad at Taking Tests Hello again! You know what they say, new commit, new devlog! “[Test] Torsion” We got MORE UNIT TESTS!!! The get_filenames() fn was formerly the only function in helpers.rs that had no unit tests, so I added 6 unit tests for it. They have about the same general structure as the unit tests for change_leading_zeros(). Beautification I was trying to make my code prettier, and I accidentally screwed up an ownership issue. My unit tests made use of tempdirs with the tempfile crate to test change_leading_zeros() and get_filenames. This is the original pattern for getting the temp dir’s path: let binding = tempdir () .unwrap (); let dir = binding .path (); // stuff can be done with dir now This is what I changed it to: let dir = tempdir () .unwrap () .path () .to_owned (); When the tempdir gets dropped, it also deletes the directory, which makes dir a path to a dir that doesn’t exist. Everything compiles fine, but the code panics because the tempdir doesn’t exist. Override Something I forgot to mention in my last devlog is that if there was the files file1.txt and file01.txt, it (c/w)ould rename over one of the files and silently delete the file written over. I still have to fix this issue. I’ve wanted to learn Zig, so I looked up Zig crash courses on Youtube, and this is from the one I was watching."}, {"post_id": 42339, "ts": "2026-08-07T00:40:04Z", "hours": 2.7222, "text": "Testing Tests Hello again! I can’t believe we’re on devlog #8, considering I have been doing pretty sparse devlogs! if true { allTestsPass } IT’S UNIT TEST TIIIIIME!!! I added 13 unit tests to my big change_leading_zeros() function. They cover most, if not all, possible edge cases. Rename file11 -> file11 I discovered that in change_leading_zeros(), if the resulting new filename was the same as the old, would still do the rename, and it would count as a renamed file, so that the actual number of renamed files would be too large. Hating on for loops as much as the functional bros. I realised that my get_filenames() fn, which still has no unit tests, could be swapped to an iterator structure. old: pub fn get_filenames ( path : & Path ) -> Vec < String > { let mut names = Vec :: new (); if let Ok ( read_dir ) = fs :: read_dir ( path ) { for file in read_dir .flatten () { names .push ( file .file_name () .into_string () .unwrap_or ( \"unknown name\" .into ()), ); } } names } pub fn get_filenames ( path : & Path ) -> Vec < String > { fs :: read_dir ( path ) .into_iter () .flatten () .flatten () .map (| f | f .file_name () .into_string () .unwrap_or ( \"unknown name\" .into ())) .collect () } The two functions behave in exactly the same way, no unnecesary unwrap()s that may cause panics See y’all next devlog!"}, {"post_id": 41806, "ts": "2026-08-06T07:38:58Z", "hours": 2.0653, "text": "Testing, Testing, 1 2 3 Here’s what I’ve been working on to try to get a good, stable release. I Need an Extension I discovered that when doing the normalising add, the one that’s like problem-1.txt, problem-11.rs (-n 1) -> problem-01.txt, problem-11.rs (keeps the same total length of the numeric portion), it actually counts the extension characters, so the result would actually be problem-01.txt, problem-011.rs because the extensions are different lengths. Previously, the find_target() function was like this: pub fn find_target ( filenames : & Vec < String > , count : usize ) -> usize { let mut minimum = usize :: MAX ; for file in filenames { let ( dot_index , cond ) = check_file ( file ); if cond { continue ; } let split_index = find_split_index ( file , dot_index ); minimum = minimum .min ( file [ split_index .. ] .len ()); } minimum + count } Now, it’s pub fn find_target ( filenames : & Vec < String > , count : usize ) -> usize { let mut minimum = usize :: MAX ; let mut is_numeric : bool = false ; for file in filenames { let ( dot_index , cond ) = check_file ( file ); if cond { continue ; } let split_index = find_split_index ( file , dot_index ); minimum = minimum .min ( file [ split_index .. dot_index ] .len ()); is_numeric = true ; } if is_numeric { minimum + count } else { 0 } } Now the target isn’t the shortest number of characters in the numeric portion plus the extension, it’s just the extension. The is_numeric variable is just there so that it doesn’t try to add count to usize::MAX, getting an overflow if there are no files with numeric suffixes. sleep(); sleep(); sleep(); allTestsPass(); The last step before 1.0.0 is UNIT TESTS!!!!!! The easiest unit tests to write are ones for my functions in helpers.rs, including find_target(), check_file(), find_split_index(), and get_filenames(). I wrote 15 unit tests for the first three, and I might write some for get_filenames after I write some for change_leading_zeros(). While writing the unit tests, I stumbled upon the edge case for find_target if there are no applicable files, which is why I added the is_numeric above. The next step is writing the aforementioned unit tests for change_leading_zeros()."}, {"post_id": 41550, "ts": "2026-08-05T20:43:11Z", "hours": 1.3689, "text": "Crack a Brewski with the Boys Much Abrew about Nothing, pt. 2 Got the homebrew tap working! Not much to say, except that it is a tad annoying to have to have a separate repo just for the tap. Compleated Because of the Homebrew tap, I decided to swap the non-nushell completions to a hidden flag, so you can run them with –generate-completions zsh/bash/fish/elvish/powershell to create the completions file, which the tap can do at install time for zsh, bash, and fish. Unfortunately, it can’t do it for elvish, powershell, or nushell, so you have to manually install completions for those three. Man(chester United) Because I now have a homebrew tap, installing man files is much easier. I brought back my old clap_mangen code for build.rs, and added a line to the formula, so now man generation works!"}, {"post_id": 41176, "ts": "2026-08-05T06:57:49Z", "hours": 0.9675, "text": "Much Abrew About Nothing Since the failure that was clap_mangen, I have been considering a homebrew release, because then I can more easily have the man files and completions be installed, and I would do homebrew specifically since it is the main package manager I use, and it kind of works on everything. I was using Claude Code to teach me how to create the tap, but I unfortunately ran through my limit and $100 of usage credits I got for free when Fable 5 dropped off my plan on a separate data entry task running with Claude Chrome, so I need to do some testing of the tap. See y’all next devlog!"}, {"post_id": 40506, "ts": "2026-08-04T02:47:49Z", "hours": 1.2161, "text": "Completionism A few days ago, I looked up clap on crates.io , and realised there were many crates built to add functionality to CLAP, like clap_mangen, clap-version-flag, and more. The two this devlog is about are clap_complete and clap_complete_nushell. These two allow for the generation of shell completions; clap_complete supports Bash, Zsh, Fish, Elvish, and PowerShell; clap_complete_nushell adds nushell support. The standard package has a new (in-development) feature that allows for the binary itself to be the completion script, allowing for more minimal user setup if downloading from crates.io†. The nushell version does not have this feature, so you have to run it with a special flag and save the output to a completions file in ~/.config/nushell/completions/leading-zero-util.nu. † crates.io doesn’t have an install step so it doesn’t look in the OUT_DIR at build time, so it doesn’t pick up files like the completion files. This same issue is why I chose not to use clap_mangen, since I only currently distribute through crates.io. If I later make a Homebrew tap, I’ll probably change the way the completions are done and re-add clap_mangen."}, {"post_id": 40305, "ts": "2026-08-03T18:53:22Z", "hours": 1.7167, "text": "Breaking it up Divide and Conquer When I was setting up my build.rs to use clap_mangen, I had to separate my CLI arg parser construct from the rest of my code and put it in a new file. I also realised that some of my code in my (basically) main function (change_leading_zeros()) was repetitive and could be extracted into functions. My change_leading_zeros() was extremely long and deserved its own file. Even after moving a ton of code into helpers.rs, it’s still 78 lines long, thoroughly violating Uncle Bob’s standards. (Granted, his standards are bad, and Uncle Bob could go trip on a log for all I care) I have never worked in a multi-file project before, not even for my Pong game, which is just 747 lines of code all in one file, and it could have easily been broken up into more files. I have a really fast scrolling speed on my laptop, to the point of it being almost unusable, so scrolling all the code in that project was annoying. Because I have never made a multi-file Rust project before, I had no idea what I was doing. I ran into a ton of errors, including my LSP stopping working, so I didn’t have autocomplete or clippy linting for one of my files for a bit, so I got even more confused. Now, fortunately, everything works now, and I even found some issues in my code (an if condition with an OR in which the first part of the OR was redundant; a for loop that instead could have been an iterator chain; a variable that stayed mutable after mutability was unnecessary), so it was an overall great success! Illiteracymaxxing Previously, I mentioned that the LZU operates off of a target length for file names, so having a schema like file01.txt project02.rs problem03.py wouldn’t work, but I was dead wrong. I haven’t worked on the project in a month and a half, and when reading over my code to see what it does, I mistook target as the target filename length, not the target length of the numeric portion. I thus removed the warnings associated with what I believed to be a behaviour of the LZU from the short help, long help, and README. The lesson is maybe to double-check with a friend or smth when you get confused by your own code."}, {"post_id": 39787, "ts": "2026-08-02T23:58:27Z", "hours": 1.5247, "text": "Google: “How to use leading-zero-util?” A couple things have happened since the last devlog, so let’s go through them! Flatten Until today, and we will get to why, all the code was in src/main.rs, which made it harder to deal with and harder to work with. I moved the Cli struct (the clap parser struct) to a new file, src/cli.rs, so it’s a little more readable now. Man Down! As I mentioned in my last devlog, I was going to use the clap_mangen crate to generate a man file for the leading-zero-util. I set it up and created a build.rs, but realised that crates.io wouldn’t do anything with the man files, so you can’t run man leading-zero-util. This was v0.4.0 (We are now on v0.5.0). The benefit of a man file is minuscule, and I can always add it back to my build.rs. It wasn’t worth the extra dependencies, so I dropped it. Reading the version message explains the version message. I was previously considering the clap-version-flag crate for a better version message, but realised it would add basically nothing, and it isn’t well maintained. I decided instead to use shadow-rs for a better long version. I had deleted my build.rs, so I made a new one and added shadow-rs to the code."}, {"post_id": 39347, "ts": "2026-08-02T08:21:29Z", "hours": 1.7653, "text": "Leading with Zeros, ending with .txt Hello everyone! Dusting off my leading zero utility after finishing up Pong, and there were some issues! The F in BSMRCDF I realised that my utility didn’t work for filenames with extensions (no problem-01.rs or mediocre-01.py), so that needed to be fixed. Look for the helpers The CLI uses a target length for non-basic additions, so it only works on filenames with nonnumeric sections of the same length (target-01.rs, project-11.rs), but not problem-11 & target-01. Consequently, the help sections need to warn about this. I also added some more examples at the bottom of the long help. Man the stall This isn’t as much of an issue as something I just found out about. There is a crate, clap_mangen , THAT LETS YOU GENERATE MAN DOCS, which I feel I feel way more excitement than it warrants. This is the next step for this project. See y’all next devlog!"}, {"post_id": 6262, "ts": "2026-06-10T14:57:57Z", "hours": 5.8289, "text": "Leading Zero Util 0.2.0 is complete!"}]...
|
Title: Leading Zeros Utility by @infinite_silly | Title: Leading Zeros Utility by @infinite_silly | Stardance
Devlogs:
Leading Zero Util 0.2.0 is complete!
Leading with Zeros, ending with .txt Hello everyone! Dusting off my leading zero utility after finishing up Pong, and there were some issues! The F in BSMRCDF I realised that my utility didn’t work for filenames with extensions (no problem-01.rs or mediocre-01.py), so that needed to be fixed. Look for the helpers The CLI uses a target length for non-basic additions, so it only works on filenames with nonnumeric sections of the same length (target-01.rs, project-11.rs), but not problem-11 & target-01. Consequently, the help sections need to warn about this. I also added some more examples at the bottom of the long help. Man the stall This isn’t as much of an issue as something I just found out about. There is a crate, clap_mangen , THAT LETS YOU GENERATE MAN DOCS, which I feel I feel way more excitement than it warrants. This is the next step for this project. See y’all next devlog!
Google: “How to use leading-zero-util?” A couple things have happened since the last devlog, so let’s go through them! Flatten Until today, and we will get to why, all the code was in src/main.rs, which made it harder to deal with and harder to work with. I moved the Cli struct (the clap parser struct) to a new file, src/cli.rs, so it’s a little more readable now. Man Down! As I mentioned in my last devlog, I was going to use the clap_mangen crate to generate a man file for the leading-zero-util. I set it up and created a build.rs, but realised that crates.io wouldn’t do anything with the man files, so you can’t run man leading-zero-util. This was v0.4.0 (We are now on v0.5.0). The benefit of a man file is minuscule, and I can always add it back to my build.rs. It wasn’t worth the extra dependencies, so I dropped it. Reading the version message explains the version message. I was previously considering the clap-version-flag crate for a better version message, but realised it would add basically nothing, and it isn’t well maintained. I decided instead to use shadow-rs for a better long version. I had deleted my build.rs, so I made a new one and added shadow-rs to the code.
Breaking it up Divide and Conquer When I was setting up my build.rs to use clap_mangen, I had to separate my CLI arg parser construct from the rest of my code and put it in a new file. I also realised that some of my code in my (basically) main function (change_leading_zeros()) was repetitive and could be extracted into functions. My change_leading_zeros() was extremely long and deserved its own file. Even after moving a ton of code into helpers.rs, it’s still 78 lines long, thoroughly violating Uncle Bob’s standards. (Granted, his standards are bad, and Uncle Bob could go trip on a log for all I care) I have never worked in a multi-file project before, not even for my Pong game, which is just 747 lines of code all in one file, and it could have easily been broken up into more files. I have a really fast scrolling speed on my laptop, to the point of it being almost unusable, so scrolling all the code in that project was annoying. Because I have never made a multi-file Rust project before, I had no idea what I was doing. I ran into a ton of errors, including my LSP stopping working, so I didn’t have autocomplete or clippy linting for one of my files for a bit, so I got even more confused. Now, fortunately, everything works now, and I even found some issues in my code (an if condition with an OR in which the first part of the OR was redundant; a for loop that instead could have been an iterator chain; a variable that stayed mutable after mutability was unnecessary), so it was an overall great success! Illiteracymaxxing Previously, I mentioned that the LZU operates off of a target length for file names, so having a schema like file01.txt project02.rs problem03.py wouldn’t work, but I was dead wrong. I haven’t worked on the project in a month and a half, and when reading over my code to see what it does, I mistook target as the target filename length, not the target length of the numeric portion. I thus removed the warnings associated with what I believed to be a behaviour of the LZU from the short help, long help, and README. The lesson is maybe to double-check with a friend or smth when you get confused by your own code.
Completionism A few days ago, I looked up clap on crates.io , and realised there were many crates built to add functionality to CLAP, like clap_mangen, clap-version-flag, and more. The two this devlog is about are clap_complete and clap_complete_nushell. These two allow for the generation of shell completions; clap_complete supports Bash, Zsh, Fish, Elvish, and PowerShell; clap_complete_nushell adds nushell support. The standard package has a new (in-development) feature that allows for the binary itself to be the completion script, allowing for more minimal user setup if downloading from crates.io†. The nushell version does not have this feature, so you have to run it with a special flag and save the output to a completions file in ~/.config/nushell/completions/leading-zero-util.nu. † crates.io doesn’t have an install step so it doesn’t look in the OUT_DIR at build time, so it doesn’t pick up files like the completion files. This same issue is why I chose not to use clap_mangen, since I only currently distribute through crates.io. If I later make a Homebrew tap, I’ll probably change the way the completions are done and re-add clap_mangen.
Much Abrew About Nothing Since the failure that was clap_mangen, I have been considering a homebrew release, because then I can more easily have the man files and completions be installed, and I would do homebrew specifically since it is the main package manager I use, and it kind of works on everything. I was using Claude Code to teach me how to create the tap, but I unfortunately ran through my limit and $100 of usage credits I got for free when Fable 5 dropped off my plan on a separate data entry task running with Claude Chrome, so I need to do some testing of the tap. See y’all next devlog!
Crack a Brewski with the Boys Much Abrew about Nothing, pt. 2 Got the homebrew tap working! Not much to say, except that it is a tad annoying to have to have a separate repo just for the tap. Compleated Because of the Homebrew tap, I decided to swap the non-nushell completions to a hidden flag, so you can run them with –generate-completions zsh/bash/fish/elvish/powershell to create the completions file, which the tap can do at install time for zsh, bash, and fish. Unfortunately, it can’t do it for elvish, powershell, or nushell, so you have to manually install completions for those three. Man(chester United) Because I now have a homebrew tap, installing man files is much easier. I brought back my old clap_mangen code for build.rs, and added a line to the formula, so now man generation works!
Testing, Testing, 1 2 3 Here’s what I’ve been working on to try to get a good, stable release. I Need an Extension I discovered that when doing the normalising add, the one that’s like problem-1.txt, problem-11.rs (-n 1) -> problem-01.txt, problem-11.rs (keeps the same total length of the numeric portion), it actually counts the extension characters, so the result would actually be problem-01.txt, problem-011.rs because the extensions are different lengths. Previously, the find_target() function was like this: pub fn find_target ( filenames : & Vec < String > , count : usize ) -> usize { let mut minimum = usize :: MAX ; for file in filenames { let ( dot_index , cond ) = check_file ( file ); if cond { continue ; } let split_index = find_split_index ( file , dot_index ); minimum = minimum .min ( file [ split_index .. ] .len ()); } minimum + count } Now, it’s pub fn find_target ( filenames : & Vec < String > , count : usize ) -> usize { let mut minimum = usize :: MAX ; let mut is_numeric : bool = false ; for file in filenames { let ( dot_index , cond ) = check_file ( file ); if cond { continue ; } let split_index = find_split_index ( file , dot_index ); minimum = minimum .min ( file [ split_index .. dot_index ] .len ()); is_numeric = true ; } if is_numeric { minimum + count } else { 0 } } Now the target isn’t the shortest number of characters in the numeric portion plus the extension, it’s just the extension. The is_numeric variable is just there so that it doesn’t try to add count to usize::MAX, getting an overflow if there are no files with numeric suffixes. sleep(); sleep(); sleep(); allTestsPass(); The last step before 1.0.0 is UNIT TESTS!!!!!! The easiest unit tests to write are ones for my functions in helpers.rs, including find_target(), check_file(), find_split_index(), and get_filenames(). I wrote 15 unit tests for the first three, and I might write some for get_filenames after I write some for change_leading_zeros(). While writing the unit tests, I stumbled upon the edge case for find_target if there are no applicable files, which is why I added the is_numeric above. The next step is writing the aforementioned unit tests for change_leading_zeros().
Testing Tests Hello again! I can’t believe we’re on devlog #8, considering I have been doing pretty sparse devlogs! if true { allTestsPass } IT’S UNIT TEST TIIIIIME!!! I added 13 unit tests to my big change_leading_zeros() function. They cover most, if not all, possible edge cases. Rename file11 -> file11 I discovered that in change_leading_zeros(), if the resulting new filename was the same as the old, would still do the rename, and it would count as a renamed file, so that the actual number of renamed files would be too large. Hating on for loops as much as the functional bros. I realised that my get_filenames() fn, which still has no unit tests, could be swapped to an iterator structure. old: pub fn get_filenames ( path : & Path ) -> Vec < String > { let mut names = Vec :: new (); if let Ok ( read_dir ) = fs :: read_dir ( path ) { for file in read_dir .flatten () { names .push ( file .file_name () .into_string () .unwrap_or ( "unknown name" .into ()), ); } } names } pub fn get_filenames ( path : & Path ) -> Vec < String > { fs :: read_dir ( path ) .into_iter () .flatten () .flatten () .map (| f | f .file_name () .into_string () .unwrap_or ( "unknown name" .into ())) .collect () } The two functions behave in exactly the same way, no unnecesary unwrap()s that may cause panics See y’all next devlog!
I’m Smart but I’m Bad at Taking Tests Hello again! You know what they say, new commit, new devlog! “[Test] Torsion” We got MORE UNIT TESTS!!! The get_filenames() fn was formerly the only function in helpers.rs that had no unit tests, so I added 6 unit tests for it. They have about the same general structure as the unit tests for change_leading_zeros(). Beautification I was trying to make my code prettier, and I accidentally screwed up an ownership issue. My unit tests made use of tempdirs with the tempfile crate to test change_leading_zeros() and get_filenames. This is the original pattern for getting the temp dir’s path: let binding = tempdir () .unwrap (); let dir = binding .path (); // stuff can be done with dir now This is what I changed it to: let dir = tempdir () .unwrap () .path () .to_owned (); When the tempdir gets dropped, it also deletes the directory, which makes dir a path to a dir that doesn’t exist. Everything compiles fine, but the code panics because the tempdir doesn’t exist. Override Something I forgot to mention in my last devlog is that if there was the files file1.txt and file01.txt, it (c/w)ould rename over one of the files and silently delete the file written over. I still have to fix this issue. I’ve wanted to learn Zig, so I looked up Zig crash courses on Youtube, and this is from the one I was watching.
Refactor I’m going to keep this one quick because it just got deleted for being too long. The previously mentioned behaviour of overwriting filenames has been fixed and has it’s own unit test now. It was given an exception before the actual rename. All the rename logic was duplicated between dec and !dec, so I flattened that. I pulled out the pre-rename exception logic into a new helper: skip_rename(). It needs unit tests of its own. Byyyeeeeee!!!
Drop it Like it’s Hot THIS IS THE FINAL DEVLOG!!!! We got a working release! After my last devlog, I added some unit tests for skip_rename(), and I added the Github default Rust workflow with some modifications to the repo to automatically test any new commits against the test suit, which is most of my codebase. Also added a test workflow to the homebrew tap so it’s easier to see that all is working.
Ships:
I made a utility to change the number of leading zeros in filenames! I was working on Project Euler and had to add a leading zero to all my filenames, which was tedious, so I made this!
Hello everyone! I was working on some Project Euler problems, and I realised that my solutions weren’t sorting correctly because they didn’t have any leading zeros in the numeric portion of their filenames. The same issue happened for my Advent of Code solutions once I hit day 10. I realised I could automate this, and the leading-zero-util was born. It slowly grew from a little, mediocre script to a decently-ish written CLI tool with proper unit tests, a Homebrew tap, a man page, and completions. If you want a better look at the development process than just the devlogs, please check out my commits on GitHub. If you are going to install the LZU, I also recommend that you use the Homebrew tap rather than the crates.io release, the instructions for which are in the README....
|
1793318120.6725981
|
1793404520.6725981
|