<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Konstantin Kolomeitsev</title>
    <description>The latest articles on DEV Community by Konstantin Kolomeitsev (@kolomeitsev).</description>
    <link>https://dev.to/kolomeitsev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3143050%2Face04c33-eb03-48e1-9142-fbd478e03287.jpg</url>
      <title>DEV Community: Konstantin Kolomeitsev</title>
      <link>https://dev.to/kolomeitsev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kolomeitsev"/>
    <language>en</language>
    <item>
      <title>Cheaper Than Perplexity, but Local — and Works With Any Agent: Agent Browser Workspace</title>
      <dc:creator>Konstantin Kolomeitsev</dc:creator>
      <pubDate>Wed, 04 Mar 2026 12:49:41 +0000</pubDate>
      <link>https://dev.to/kolomeitsev/cheaper-than-perplexity-but-local-and-works-with-any-agent-agent-browser-workspace-17bo</link>
      <guid>https://dev.to/kolomeitsev/cheaper-than-perplexity-but-local-and-works-with-any-agent-agent-browser-workspace-17bo</guid>
      <description>&lt;p&gt;If you've used Perplexity Deep Research, you probably know two feelings at once:&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;"Wow, it really digs deep."&lt;/strong&gt;&lt;br&gt;
2) &lt;strong&gt;"Too bad I can't see what's happening inside, intervene, restart a step, or expand the search — it's a black box."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent Browser Workspace&lt;/strong&gt; is not a "one-button SaaS". It's a &lt;strong&gt;local toolkit&lt;/strong&gt; that gives any AI agent (Cursor, your own agent, an LLM orchestrator) a real browser for research.&lt;/p&gt;

&lt;p&gt;It runs &lt;strong&gt;on your machine, through your Chrome&lt;/strong&gt;, but in a &lt;strong&gt;separate profile&lt;/strong&gt;. No Docker, no exotic environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cheaper than Perplexity&lt;/strong&gt;: on DeepResearch Bench we scored &lt;strong&gt;44.37&lt;/strong&gt; (RACE overall) on &lt;strong&gt;Claude Haiku 4.5&lt;/strong&gt; — a model significantly cheaper than typical "frontier" stacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local and transparent&lt;/strong&gt;: a real Chrome right in front of you — you can stop it, log in, close a banner, restart a step, expand the search, refine the query. As many iterations as you need.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not just deep research&lt;/strong&gt;: also a tool for browser automation + content, form, and HTML data extraction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensible&lt;/strong&gt;: new sites are added as profiles in &lt;code&gt;scripts/sites/*.json&lt;/code&gt; — selectors and controls live separately from code and prompts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Inside?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Agent Browser Workspace&lt;/strong&gt; is a repository with two layers:&lt;/p&gt;

&lt;h3&gt;
  
  
  1) Low Level (&lt;code&gt;utils/&lt;/code&gt;)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;utils/browserUse.js&lt;/code&gt; — control a real Chrome via Playwright: navigation, clicks, input, scrolling (including infinite scroll), screenshots, file and image downloads, JS execution on the page, tabs, CDP.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;utils/getDataFromText.js&lt;/code&gt; — parse raw HTML without a browser: finds navigation, main content, forms, and converts content to Markdown.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2) High Level (&lt;code&gt;scripts/&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Ready-made building blocks for a research pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;getContent&lt;/code&gt; — save a page as Markdown + download images and rewrite links to local files.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getForms&lt;/code&gt; — find forms, classify them (search/auth/filter/contact/subscribe), and build ready-to-use CSS selectors for filling.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getAll&lt;/code&gt; — content + forms in one pass (single HTML snapshot).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;googleSearch&lt;/code&gt; — step-by-step Google search: query → organic links → open → extract → close tab → pagination.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How This Beats a Typical Deep Research SaaS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) You Keep Control
&lt;/h3&gt;

&lt;p&gt;With SaaS deep research, you usually see a progress bar and a final result. Here it's different:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The browser is real&lt;/strong&gt; — not a "virtual screenshot black box".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You can intervene&lt;/strong&gt;: close a cookie banner, log in, confirm age, adjust a filter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You can restart&lt;/strong&gt; a specific step: open the next link, re-extract content, change the wait strategy (SPA/JS rendering), scroll through infinite scroll before extraction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You can expand endlessly&lt;/strong&gt;: "add 10 more sources", "double-check the numbers", "add a comparison table", "collect a list of alternatives", "follow the snowball of links".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Research becomes iterative. One failed step doesn't kill the whole process.&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Artifacts and Reproducibility
&lt;/h3&gt;

&lt;p&gt;Deep research isn't just the final text. It's also the &lt;strong&gt;evidence base&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;links.json&lt;/code&gt; — a &lt;strong&gt;stable snapshot&lt;/strong&gt; of Google results across all queries (you can continue later without re-running searches).&lt;/li&gt;
&lt;li&gt;Downloaded pages in Markdown + &lt;code&gt;images/&lt;/code&gt; — sources stay on disk.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;insights.md&lt;/code&gt; — a cumulative draft (in the &lt;code&gt;RESEARCH.md&lt;/code&gt; methodology, this is part of the process).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3) Local, No Extra Infrastructure
&lt;/h3&gt;

&lt;p&gt;No containers, no remote browsers, no special platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;npm install&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npx playwright install chrome&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm run chrome&lt;/code&gt; (starts Chrome with CDP on port 9222)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three commands — done. Details in &lt;code&gt;INSTALLATION.md&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extensibility: Site Profiles Instead of Hardcoding
&lt;/h2&gt;

&lt;p&gt;A common pain point in browser agents — &lt;strong&gt;selectors break&lt;/strong&gt;. Sites change their markup, and the agent starts guessing.&lt;/p&gt;

&lt;p&gt;Here it's different — through &lt;strong&gt;site profiles&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;scripts/sites/*.json&lt;/code&gt; stores selectors and "controls" (which elements matter, what to do with them).&lt;/li&gt;
&lt;li&gt;Scripts return a &lt;code&gt;site&lt;/code&gt; field, and the agent uses &lt;strong&gt;ready-made selectors&lt;/strong&gt; without guessing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Need to support a new site? Add a JSON profile. Google changed its markup? Edit &lt;code&gt;scripts/sites/google-search.json&lt;/code&gt; instead of rewriting code.&lt;/p&gt;

&lt;h2&gt;
  
  
  DeepResearch Bench: Why Numbers Matter
&lt;/h2&gt;

&lt;p&gt;When everyone claims "we have the best deep research", you need an external benchmark.&lt;br&gt;
That benchmark is &lt;strong&gt;DeepResearch Bench (DRB)&lt;/strong&gt; — 100 "PhD-level" tasks, two metrics (RACE/FACT), and a public evaluation methodology.&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Official DRB site: &lt;a href="https://deepresearch-bench.github.io/" rel="noopener noreferrer"&gt;deepresearch-bench.github.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Repository: &lt;a href="https://github.com/Ayanami0730/deep_research_bench" rel="noopener noreferrer"&gt;Ayanami0730/deep_research_bench&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Numbers You Can Verify
&lt;/h3&gt;

&lt;p&gt;On the official DRB page in the &lt;em&gt;Main Results&lt;/em&gt; section for the "Deep Research Agent" category (RACE overall):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemini-2.5-Pro Deep Research&lt;/strong&gt;: 48.88&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI Deep Research&lt;/strong&gt;: 46.98&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Perplexity Deep Research&lt;/strong&gt;: 42.25&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And here's Agent Browser Workspace's result:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;44.37&lt;/strong&gt; &lt;em&gt;(RACE overall)&lt;/em&gt; — &lt;strong&gt;above Perplexity Deep Research&lt;/strong&gt;, closer to OpenAI/Gemini, and running on &lt;strong&gt;Claude Haiku 4.5&lt;/strong&gt; (a model significantly cheaper than "frontier" stacks).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Results have been submitted to the leaderboard and are under review.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why "44.37 on Haiku" Is More Than Just a Number
&lt;/h3&gt;

&lt;p&gt;Most comparisons forget about cost and controllability.&lt;br&gt;
Here you win on three fronts at once:&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;Quality close to the top&lt;/strong&gt; (DRB overall near OpenAI/Gemini).&lt;br&gt;
2) &lt;strong&gt;Lower cost&lt;/strong&gt; (Haiku-class models).&lt;br&gt;
3) &lt;strong&gt;Control and reproducibility&lt;/strong&gt; — on your machine, with real artifacts (links.json + downloaded sources).&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It in 5 Minutes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) Install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install
&lt;/span&gt;npx playwright &lt;span class="nb"&gt;install &lt;/span&gt;chrome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2) Start a Local Chrome for the Agent
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run chrome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3) Save Any Page as Markdown (with Images)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node scripts/getContent.js &lt;span class="nt"&gt;--url&lt;/span&gt; https://example.com &lt;span class="nt"&gt;--dir&lt;/span&gt; ./output &lt;span class="nt"&gt;--name&lt;/span&gt; page.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4) Deep Research: Google → Open → Save Source
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Stable snapshot of search results (links.json)&lt;/span&gt;
node scripts/googleSearch.js &lt;span class="s2"&gt;"best AI newsletters 2026"&lt;/span&gt; &lt;span class="nt"&gt;--links&lt;/span&gt; &lt;span class="nt"&gt;--dir&lt;/span&gt; ./archive/my-research

&lt;span class="c"&gt;# Open result 0 and save content&lt;/span&gt;
node scripts/googleSearch.js &lt;span class="s2"&gt;"best AI newsletters 2026"&lt;/span&gt; &lt;span class="nt"&gt;--open&lt;/span&gt; 0 &lt;span class="nt"&gt;--dir&lt;/span&gt; ./archive/my-research &lt;span class="nt"&gt;--name&lt;/span&gt; source-0.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PDFs are supported too: if a &lt;code&gt;.pdf&lt;/code&gt; shows up in the results, &lt;code&gt;getContent&lt;/code&gt;/&lt;code&gt;googleSearch&lt;/code&gt; automatically extract the text.&lt;/p&gt;

&lt;h2&gt;
  
  
  When a Site Looks "Empty" (SPA, JS Rendering, Lazy-Load)
&lt;/h2&gt;

&lt;p&gt;The classic failure of "fast" web scrapers: the HTML arrives, but there's no content.&lt;/p&gt;

&lt;p&gt;The project has an escalation path (details in &lt;code&gt;AGENTS.md&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gotoAndWaitForContent()&lt;/code&gt; — wait for the DOM to stabilize after JS rendering&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;evaluate(() =&amp;gt; document.body.innerText)&lt;/code&gt; — pull visible text directly&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scroll({ times: N })&lt;/code&gt; — load lazy content or a feed&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;screenshot({ fullPage: true })&lt;/code&gt; — if text isn't accessible programmatically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The logic is simple: the page matters — don't skip it — escalate the extraction level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not Just Deep Research: Where Else It Helps
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) Product and Marketing Research
&lt;/h3&gt;

&lt;p&gt;You can collect search results, lock down &lt;code&gt;links.json&lt;/code&gt;, save 30–60 sources as Markdown, then ask the agent to "expand / compare / double-check / build a table" using local artifacts.&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Web Routine Automation
&lt;/h3&gt;

&lt;p&gt;Log in, click, download, fill out forms, take screenshots, save evidence — it's all here.&lt;/p&gt;

&lt;h3&gt;
  
  
  3) Form Discovery and Ready-Made Selectors
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;getForms&lt;/code&gt; finds forms and fields, returns &lt;strong&gt;ready-to-use CSS selectors&lt;/strong&gt;.&lt;br&gt;
From there, the agent calls &lt;code&gt;browser.fill()&lt;/code&gt; or &lt;code&gt;browser.fillForm()&lt;/code&gt; without guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "Local + Observable" Is a Big Deal
&lt;/h2&gt;

&lt;p&gt;Closed deep research products work well when you need a quick answer.&lt;br&gt;
But if you're working with research, business decisions, sources, verification, and iterations — you need a different mode:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;observe,&lt;/li&gt;
&lt;li&gt;pause,&lt;/li&gt;
&lt;li&gt;fix obstacles,&lt;/li&gt;
&lt;li&gt;restart steps,&lt;/li&gt;
&lt;li&gt;add depth,&lt;/li&gt;
&lt;li&gt;refine the report,&lt;/li&gt;
&lt;li&gt;keep going until the result is right.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's what Agent Browser Workspace is about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to Read More
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/k-kolomeitsev/agent-browser-workspace" rel="noopener noreferrer"&gt;k-kolomeitsev/agent-browser-workspace&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Tool overview and working rules: &lt;code&gt;AGENTS.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Installation and QOL instructions (profiles/shortcuts/checks): &lt;code&gt;INSTALLATION.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Deep research methodology: &lt;code&gt;RESEARCH.md&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you'd like to contribute to the open source project — here are the most impactful areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;new and improved &lt;strong&gt;site profiles&lt;/strong&gt; in &lt;code&gt;scripts/sites/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;better content extraction on tricky sites (SPA, paywall overlays, lazy rendering)&lt;/li&gt;
&lt;li&gt;smarter form and field detection rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Made it this far? Star the repo — it's the best way to help the project grow.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>DSP (Data Structure Protocol): how to give LLM agents "long-term memory" of a large repository</title>
      <dc:creator>Konstantin Kolomeitsev</dc:creator>
      <pubDate>Fri, 20 Feb 2026 13:42:49 +0000</pubDate>
      <link>https://dev.to/kolomeitsev/dsp-data-structure-protocol-how-to-give-llm-agents-long-term-memory-of-a-large-repository-5daj</link>
      <guid>https://dev.to/kolomeitsev/dsp-data-structure-protocol-how-to-give-llm-agents-long-term-memory-of-a-large-repository-5daj</guid>
      <description>&lt;p&gt;There’s a pattern everyone who works with agents recognizes: &lt;strong&gt;the first 5–15 minutes are spent not on the task, but on “getting oriented.”&lt;/strong&gt; Where is the entry point? Where do the dependencies come from? Why this library and not another one? Who considers this a public API? In a small project it’s annoying. In a large one, it becomes a constant tax on tokens and attention.&lt;/p&gt;

&lt;p&gt;DSP (Data Structure Protocol) “externalizes the project map” — into a simple, versioned, language-agnostic graph that lives alongside the code and is available to the agent as persistent memory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/k-kolomeitsev/data-structure-protocol" rel="noopener noreferrer"&gt;k-kolomeitsev/data-structure-protocol&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The goal is phrased in the architecture like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1) Goal and scope

The goal of DSP is to store minimal, but sufficient context about a repository / artifact system as a graph “entities → dependencies / public API”, so that an LLM can:

- quickly locate the necessary fragments by UID,
- understand why entities exist and how they are connected,
- avoid having to load the entire source tree into the context window.

DSP is long-term memory and an index of the project for an LLM. At any time, the agent can run a project-wide search (grep), find the required entities by descriptions/keywords, and from the found UID expand the entire relationship graph: incoming dependencies, outgoing imports, and consumers via `exports`. This replaces the need to “remember” the project structure or load it in full — the entire project map is always available through `.dsp`.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What DSP is, in essence
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;DSP = an entity graph + the reasons behind connections&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;DSP is stored in the &lt;strong&gt;&lt;code&gt;.dsp/&lt;/code&gt;&lt;/strong&gt; directory. Each “entity” gets a stable &lt;strong&gt;UID&lt;/strong&gt; and a small set of files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;description&lt;/code&gt;&lt;/strong&gt;: &lt;em&gt;where it is&lt;/em&gt; (&lt;code&gt;source&lt;/code&gt;), &lt;em&gt;what it is&lt;/em&gt; (&lt;code&gt;kind&lt;/code&gt;), &lt;em&gt;why it exists&lt;/em&gt; (&lt;code&gt;purpose&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;imports&lt;/code&gt;&lt;/strong&gt;: what this entity uses (UID references).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;shared&lt;/code&gt;&lt;/strong&gt;: what it exposes as a public API (exports).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;exports/&lt;/code&gt;&lt;/strong&gt;: a reverse index — &lt;strong&gt;who imports this entity and why&lt;/strong&gt; (the &lt;code&gt;why&lt;/code&gt; text next to each consumer).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In large systems, one detail matters especially: DSP captures not only “what depends on what,” but also &lt;strong&gt;why&lt;/strong&gt;. This drastically reduces guesswork in refactoring, migrations, and legacy removal.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;There are only two base entity types&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Object&lt;/strong&gt;: module/file/class/config/resource/external dependency — “everything that isn’t a function.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Function&lt;/strong&gt;: function/method/handler/pipeline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another bonus: &lt;strong&gt;DSP is language-agnostic&lt;/strong&gt;. It works the same across TS/JS, Python, Go, infrastructure YAML, SQL, assets, and so on. The architecture also explicitly defines “import completeness”: &lt;strong&gt;if something is imported, it must exist in &lt;code&gt;.dsp&lt;/code&gt;&lt;/strong&gt;, including styles, images, JSON, wasm, and other artifacts. This matters more than it seems: agents more often lose not code, but &lt;em&gt;resource dependencies&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why UID is the central idea
&lt;/h2&gt;

&lt;p&gt;DSP is built on identity by UID, not by path. A path is an attribute. A UID is an entity’s “identity.”&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Renamed a file → run &lt;code&gt;move-entity&lt;/code&gt;, the UID stays the same.&lt;/li&gt;
&lt;li&gt;Moved code around / reformatted → the UID stays the same.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A UID changes only when the purpose (semantic identity) changes&lt;/strong&gt;: the module truly became “about something else.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To attach a UID to entities inside a file (exported functions/classes), DSP uses a simple marker comment &lt;code&gt;@dsp &amp;lt;uid&amp;gt;&lt;/code&gt; right in the source code. It’s a pragmatic choice: it doesn’t depend on line numbers, works in any language, and is easy to find with grep.&lt;/p&gt;




&lt;h2&gt;
  
  
  How an agent “walks” DSP instead of endlessly reading code
&lt;/h2&gt;

&lt;p&gt;A typical agent workflow in a DSP-based project looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Find an entity&lt;/strong&gt;: &lt;code&gt;search&lt;/code&gt; by keywords, or &lt;code&gt;find-by-source&lt;/code&gt; by file path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Understand the boundaries&lt;/strong&gt;: read &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;shared&lt;/code&gt;, &lt;code&gt;imports&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pull context in batches&lt;/strong&gt;: instead of “give me the whole repo,” the agent fetches only the nodes it needs plus 1–2 levels of dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Estimate impact&lt;/strong&gt;: who consumes the entity and why (&lt;code&gt;get-parents&lt;/code&gt; / &lt;code&gt;get-recipients&lt;/code&gt;), whether there are cycles, whether there are “orphans.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example commands (PowerShell style; the CLI is shipped inside the skill):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\.claude\skills\data-structure-protocol\scripts\dsp-cli.py&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"authorization"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\.claude\skills\data-structure-protocol\scripts\dsp-cli.py&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;get-entity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;obj-a1b2c3d4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\.claude\skills\data-structure-protocol\scripts\dsp-cli.py&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;get-children&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;obj-a1b2c3d4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--depth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\.claude\skills\data-structure-protocol\scripts\dsp-cli.py&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;get-recipients&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;obj-a1b2c3d4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\.claude\skills\data-structure-protocol\scripts\dsp-cli.py&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;get-path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;obj-a1b2c3d4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;func-7f3a9c12&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What the &lt;code&gt;data-structure-protocol&lt;/code&gt; skill adds (and why it’s more important than it seems)
&lt;/h2&gt;

&lt;p&gt;DSP architecture is a set of rules. But without discipline an agent can easily violate them: poke the code at random, drag half the repo into the context, forget to update the index, and break graph integrity.&lt;/p&gt;

&lt;p&gt;The skill covers exactly the operational part:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It embeds an Agent Prompt&lt;/strong&gt;: “before changing anything — find the entities; when creating — register; when importing — add &lt;code&gt;why&lt;/code&gt;; when deleting — perform cascade cleanup.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It provides reference materials&lt;/strong&gt; in &lt;code&gt;references/&lt;/code&gt;: the storage format, the bootstrap algorithm (DFS from entry points), the semantics of operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It ships a production-ready CLI&lt;/strong&gt; &lt;code&gt;scripts/dsp-cli.py&lt;/code&gt; that implements the operations from &lt;code&gt;ARCHITECTURE.md&lt;/code&gt; and supports navigation/diagnostics (cycles/orphans/stats).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;DSP becomes not a “document,” but a living contract&lt;/strong&gt; that the agent executes while working — and keeps &lt;code&gt;.dsp&lt;/code&gt; consistent without manual intervention.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cost of adoption: bootstrapping a large project will be expensive
&lt;/h2&gt;

&lt;p&gt;Yes. &lt;strong&gt;The initial bootstrap on a large repository is expensive&lt;/strong&gt; — in time, attention, and tokens.&lt;/p&gt;

&lt;p&gt;Why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to identify the root entry points (and there are many in a monorepo).&lt;/li&gt;
&lt;li&gt;You need to traverse dependencies depth-first (DFS) and record all reachable modules/files/resources.&lt;/li&gt;
&lt;li&gt;For each node, you need to write a &lt;em&gt;minimal, but precise&lt;/em&gt; &lt;code&gt;purpose&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You need to fill in the reasons (&lt;code&gt;why&lt;/code&gt;) for import edges in a disciplined way — otherwise half of DSP’s value disappears.&lt;/li&gt;
&lt;li&gt;Sometimes you need to add &lt;code&gt;@dsp&lt;/code&gt; markers in source files for exported entities (so the UID becomes an “anchor” in code).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On large systems, this can realistically be its own mini-project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why it pays off (and usually pays off faster than it seems)
&lt;/h2&gt;

&lt;p&gt;The value of DSP is not “a pretty structure.” It’s in the economics of agent work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fewer tokens spent on orientation&lt;/strong&gt;: instead of repeatedly “warming up” context, the agent reads short &lt;code&gt;description/imports/shared/exports&lt;/code&gt; and pulls exactly the files that need to be changed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context doesn’t dissolve between tasks&lt;/strong&gt;: &lt;code&gt;.dsp&lt;/code&gt; is external memory that doesn’t depend on the current context window or the model’s “mood.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast semantic lookup&lt;/strong&gt;: &lt;code&gt;search&lt;/code&gt; finds entities by keywords, and &lt;code&gt;exports/&lt;/code&gt; answers the question “why is this even here.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refactoring becomes safer&lt;/strong&gt;: impact analysis gets cheaper — you quickly get all consumers of an entity and update them precisely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;External dependencies become transparent&lt;/strong&gt;: external packages are captured as &lt;code&gt;kind: external&lt;/code&gt;, without bloating the graph, but they remain navigable via the exports index.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And here’s an important point from the architecture — &lt;strong&gt;granularity control&lt;/strong&gt;, so DSP doesn’t turn into a junk drawer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10) Granularity and minimal-context policy

- Completeness at the file level, not at the code-within-file level. “Import completeness” (section 2) means that every file/module that is imported in the project must have an Object in `.dsp`. This is about files and modules — not about every variable inside a file. Within a single file, a separate UID is assigned only to an entity that is shared externally (`shared`) or used from multiple places. Local variables, internal helpers, private fields — remain part of the parent Object, without their own UID. If granularity keeps growing, something is being done wrong.

- Update consumers via `exports`. To update a library/module/symbol, it’s enough to open `exports` of the imported entity and get the list of importers (consumers) by UID, then update them precisely.

- Change tracking. `git diff` shows what changed — a new file was created, a function or object changed. The changed files are passed to the LLM to update DSP. Changes inside functions often don’t require updating DSP, because descriptions capture purpose, not implementation details — unless imports were added/removed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what makes DSP viable over time: &lt;strong&gt;the index stays compact&lt;/strong&gt;, and updates stay rare and meaningful.&lt;/p&gt;




&lt;h2&gt;
  
  
  When DSP really shines
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Large monoliths and monorepos&lt;/strong&gt;, where the context “never fits.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long-lived products&lt;/strong&gt;, where agents will work for months and years, not just one sprint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teams that frequently do refactors/migrations/dependency replacements&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Projects with a complex resource layer&lt;/strong&gt; (assets/configs/generation) that is hard for agents to keep in their heads.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;DSP is an attempt to do for LLM agents what people have long done informally: keep a mental map of a system. Only instead of a head — &lt;strong&gt;a graph on disk&lt;/strong&gt;; instead of “that’s how I remember it” — &lt;strong&gt;minimal descriptions, connections, and reasons&lt;/strong&gt;; instead of “read the whole project” — &lt;strong&gt;targeted navigation from entry points&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Yes, &lt;strong&gt;bootstrapping a large project will be expensive&lt;/strong&gt;. But if you truly plan to use agents systematically, this cost typically comes back through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fewer tokens spent on orientation,&lt;/li&gt;
&lt;li&gt;less context loss between tasks,&lt;/li&gt;
&lt;li&gt;faster discovery of the needed modules/dependencies,&lt;/li&gt;
&lt;li&gt;more predictable task execution (especially refactoring work).&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>promptengineering</category>
      <category>programming</category>
    </item>
    <item>
      <title>Autonomous AI Employee</title>
      <dc:creator>Konstantin Kolomeitsev</dc:creator>
      <pubDate>Tue, 14 Oct 2025 19:17:20 +0000</pubDate>
      <link>https://dev.to/kolomeitsev/autonomous-ai-employee-15pp</link>
      <guid>https://dev.to/kolomeitsev/autonomous-ai-employee-15pp</guid>
      <description>&lt;p&gt;This is a repost of my article on &lt;a href="https://www.linkedin.com/posts/kolomeitsev_autonomous-ai-employee-pt1-the-main-dream-activity-7383874142598635521-kfPM" rel="noopener noreferrer"&gt;LinkedIn.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main dream of modern AI investors is an autonomous AI employee who can fully replace certain specialists and work without any external intervention.&lt;/p&gt;

&lt;p&gt;In my view, this is already quite an achievable goal with the current level of technology.&lt;/p&gt;

&lt;p&gt;Let me give an example from a field close to me — programming (though this approach is applicable to most digital professions). Let’s build an autonomous AI &lt;em&gt;middle-level backend developer&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We’ll set it up on a local server machine, inside the company’s internal network.&lt;/p&gt;

&lt;p&gt;Right away, I’ll say that I will &lt;strong&gt;not&lt;/strong&gt; be sharing my code, configurations, or workflows publicly. My goal is to provide a high-level overview of a solution that works for me, because I see not just a gap, but a complete lack of materials of this kind — even at such a surface level of detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparation
&lt;/h2&gt;

&lt;p&gt;First, we’ll need a complete &lt;strong&gt;Job Description&lt;/strong&gt; for the employee, the data they need to know, the tasks they need to perform, and the communication channels through which they can interact. Fortunately, remote work has done its job — everyone has learned to communicate digitally.&lt;/p&gt;

&lt;p&gt;Next, we formalize access:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;to &lt;strong&gt;Git&lt;/strong&gt; — via SSH keys,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;to &lt;strong&gt;Confluence&lt;/strong&gt; and &lt;strong&gt;Jira&lt;/strong&gt; — via API keys,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tokens for &lt;strong&gt;Telegram&lt;/strong&gt;, &lt;strong&gt;Slack&lt;/strong&gt;, or other tools (email, or any other communication channels).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We record all of this into a simple JSON configuration file located in the working directory where the employee (agent) will operate — the agent’s root directory.&lt;/p&gt;

&lt;p&gt;We install &lt;strong&gt;Docker&lt;/strong&gt; on the server and launch the following services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;n8n&lt;/strong&gt; (for workflow orchestration),&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a &lt;strong&gt;vector database&lt;/strong&gt;, and&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a relational database like &lt;strong&gt;PostgreSQL&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also grant &lt;strong&gt;n8n&lt;/strong&gt; access to the working directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Now we configure communication channels.&lt;br&gt;&lt;br&gt;
In &lt;strong&gt;n8n&lt;/strong&gt;, we add triggers for the required channels so that incoming messages are routed to our agent, who can then return responses.&lt;br&gt;&lt;br&gt;
But instead of calling a regular LLM model, we’ll use a &lt;strong&gt;hook or custom node&lt;/strong&gt; that invokes our &lt;strong&gt;local agent&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Agent
&lt;/h2&gt;

&lt;p&gt;The most complex part is developing the agent itself.&lt;br&gt;&lt;br&gt;
However, a level of “agentness” similar to that of &lt;strong&gt;Cursor&lt;/strong&gt; is already more than sufficient — the key is to craft the prompts methodologically correctly.&lt;/p&gt;

&lt;p&gt;Another important step is setting up &lt;strong&gt;MCP tools&lt;/strong&gt; for the agent — such as modules for searching and scraping information, and for working with &lt;strong&gt;Jira&lt;/strong&gt;, &lt;strong&gt;Confluence&lt;/strong&gt;, &lt;strong&gt;Git&lt;/strong&gt;, and so on. This gives our AI employee “hands” and “eyes.”&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;RAG (Retrieval-Augmented Generation)&lt;/strong&gt; mechanism is also essential — for &lt;em&gt;memorizing&lt;/em&gt; important things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;how to correctly solve a particular type of task,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;or how to properly find a specific kind of information.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent itself can determine what is important using a simple prompt such as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Highlight successful solutions from the current session for future memorization.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This allows our AI employee to &lt;strong&gt;accumulate experience&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
The relational database is needed to store “behavioral rules,” for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;when a supervisor says &lt;em&gt;“don’t do it that way again”&lt;/em&gt;, or&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;conversely, &lt;em&gt;“do it like this instead.”&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Methodology
&lt;/h2&gt;

&lt;p&gt;This is the most important — and probably the most extensive — part of the work: &lt;strong&gt;formalizing the working methodology&lt;/strong&gt; of our employee (ideally, all of this should already be reflected in the Job Description).&lt;/p&gt;

&lt;p&gt;The workflow consists of two main stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Populating the RAG with key knowledge&lt;/strong&gt; — essentially, we “load” the onboarding process into the RAG.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scheduling&lt;/strong&gt; — in &lt;strong&gt;n8n&lt;/strong&gt;, we configure &lt;strong&gt;cron triggers&lt;/strong&gt; so that, for example, at 9 a.m. the agent:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- logs into Jira,

- checks for new tasks assigned to them,

- analyzes them, and

- either starts working on them or leaves a comment.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  How It All Works
&lt;/h2&gt;

&lt;p&gt;Let’s look at an example with our AI middle developer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Logs into &lt;strong&gt;Jira&lt;/strong&gt; according to schedule and pulls assigned tasks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Checks each task for completeness and feasibility — if something is missing, leaves a comment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verifies the required environment — network access, code access, Git permissions, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Executes the task.&lt;br&gt;&lt;br&gt;
With a well-written description, &lt;strong&gt;Cursor&lt;/strong&gt; already handles 100% of middle-level developer tasks for me (if yours doesn’t — either the context completeness or prompt quality is lacking).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tests locally using &lt;strong&gt;Playwright MCP&lt;/strong&gt; or &lt;strong&gt;Postman&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pushes the result to &lt;strong&gt;dev&lt;/strong&gt;, verifies the deployment pipeline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If there are errors — comments in Jira, possibly messages the DevOps engineer, and rolls the task back.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If all goes smoothly — rechecks on dev.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Moves the task forward, comments in Jira, team chat, or other configured channels.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instead of daily stand-ups, can automatically:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- compile info from **Jira** about yesterday’s tasks,

- pull commits from **Git** related to those tasks,

- send a daily report, and

- note failed tasks and explain why.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Can reply to messages in &lt;strong&gt;Telegram&lt;/strong&gt;, &lt;strong&gt;Slack&lt;/strong&gt;, and other communication channels.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can even, based on memorized experience and code analysis, &lt;strong&gt;advise junior developers or testers&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point, what we have is already a fairly reliable and high-quality &lt;strong&gt;middle-level developer&lt;/strong&gt;, better than the average on the market.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Of course, much depends on the &lt;strong&gt;model&lt;/strong&gt; used by the agent — but nothing prevents us from experimenting with different options to find the optimal balance between &lt;strong&gt;quality, cost, and speed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is also very important to carefully design the &lt;strong&gt;methodology of operation&lt;/strong&gt;, to account for various behavioral scenarios of the model.&lt;/p&gt;

&lt;p&gt;We should not forget about &lt;strong&gt;safeguards&lt;/strong&gt; — to prevent the agent from looping or drifting into endless, meaningless reasoning.&lt;br&gt;&lt;br&gt;
However, if the agent is well designed, those safeguards will already be in place.&lt;/p&gt;

&lt;p&gt;Even though this is a &lt;strong&gt;pseudo-architecture&lt;/strong&gt;, I have already managed to &lt;strong&gt;run many of the described components locally&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;That’s all for now — thank you for your attention.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>tutorial</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Hiring Programmers v2. Tips from a Programmer</title>
      <dc:creator>Konstantin Kolomeitsev</dc:creator>
      <pubDate>Fri, 16 May 2025 17:35:36 +0000</pubDate>
      <link>https://dev.to/kolomeitsev/hiring-programmers-v2-tips-from-a-programmer-4hic</link>
      <guid>https://dev.to/kolomeitsev/hiring-programmers-v2-tips-from-a-programmer-4hic</guid>
      <description>&lt;p&gt;&lt;strong&gt;Hi, friends!&lt;/strong&gt; I once shared my thoughts on how to hire developers.&lt;/p&gt;

&lt;p&gt;Since then, a lot has changed: &lt;strong&gt;artificial intelligence&lt;/strong&gt; has confidently entered the life of IT teams, and the task of recruiting employees has become even more complicated.&lt;/p&gt;

&lt;p&gt;Modern “recommendations” from recruiters and managers have begun to descend into an absurdity that is very sad to watch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Important&lt;/em&gt;&lt;/strong&gt;: Below is my personal opinion, proven in practice and shared by my fellow programmers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage One: Interview Without a Technical Specialist
&lt;/h2&gt;

&lt;p&gt;I won’t tire of repeating that the &lt;strong&gt;HR’s task&lt;/strong&gt; at this stage is to weed out the inadequate—people unable to perform assigned tasks and generally not focused on work (there are plenty of them).&lt;/p&gt;

&lt;p&gt;Just talk human-to-human, probe the candidate’s soft skills, assess their behavior, and ask about motivation. Don’t turn the conversation into an exam—simply form an impression that you will later pass on to the candidate’s future manager.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you need to find out:&lt;/strong&gt; whether the person will fit into the team, whether they will be able to work productively, and whether they will obtain the desired return—be it income, recognition, or interesting projects.&lt;/p&gt;

&lt;p&gt;Do not try to dive into technical nuances; it looks out of place and helpless. And no ChatGPT will help you if you don’t understand what you are asking about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What else can you ask?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For &lt;strong&gt;experienced&lt;/strong&gt; specialists: ask them to talk about projects they worked on, what difficulties they encountered, and how they solved them.&lt;/li&gt;
&lt;li&gt;For &lt;strong&gt;juniors&lt;/strong&gt;: offer a couple of simple logic puzzles to see how the person thinks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This information is usually enough to filter out 80–90 % of applicants.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage Two: Conversation with a Techie
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do not ask dry theory unrelated to the candidate’s experience.&lt;/strong&gt; I know people who could recite textbooks by heart yet couldn’t write working code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It’s better to discuss real tasks from their experience,&lt;/strong&gt; especially those similar to the ones you have. From their story you will immediately see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;whether the person understands the topic;&lt;/li&gt;
&lt;li&gt;whether their experience matches your requirements;&lt;/li&gt;
&lt;li&gt;whether they can cope with new tasks;&lt;/li&gt;
&lt;li&gt;whether they can learn quickly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How to Deal with Vibe Coders?
&lt;/h3&gt;

&lt;p&gt;Not all vibe coders are the same. If all someone can do is paste a prompt into Cursor and run whatever the AI spits out, then of course nobody needs such a person.&lt;/p&gt;

&lt;p&gt;But if they can design the structure of a future program themselves, know how to ask the neural network to write the required code, understand what the assistant has generated, and can immediately fix the wrong parts by hand—then such a person is quite valuable. They already possess the basics of application architecture, can read code, and, at the very least, are a good prompt engineer, because getting the desired result from a neural network is not that simple.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attitude Toward AI at Work
&lt;/h3&gt;

&lt;p&gt;I believe developers should be better at using AI than anyone else.&lt;/p&gt;

&lt;p&gt;The question is how they use it. It’s the same story as with vibe coders: if someone pushed changes without even running their own code, let alone linting it, you can hardly call that person a professional.&lt;/p&gt;

&lt;p&gt;But if they leverage AI to handle boring, monotonous tasks, then, in my view, their value only increases, because they can close the same tasks faster thanks to smart assistants.&lt;/p&gt;

&lt;p&gt;Therefore, be sure to clarify whether candidates use AI in their work, how they use it, which tools they use, for what purposes, and why.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Usually this set of questions is enough to make a decision.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You will learn &lt;strong&gt;more&lt;/strong&gt; about a person &lt;strong&gt;only&lt;/strong&gt; during the probation period.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I hope these notes prove useful. Thank you for reading!&lt;/p&gt;

</description>
      <category>hiring</category>
      <category>career</category>
      <category>recruitment</category>
      <category>ai</category>
    </item>
    <item>
      <title>PTTJS — A Text‑Based Format for Complex Tables</title>
      <dc:creator>Konstantin Kolomeitsev</dc:creator>
      <pubDate>Sun, 11 May 2025 17:34:23 +0000</pubDate>
      <link>https://dev.to/kolomeitsev/pttjs-a-text-based-format-for-complex-tables-55m3</link>
      <guid>https://dev.to/kolomeitsev/pttjs-a-text-based-format-for-complex-tables-55m3</guid>
      <description>&lt;p&gt;&lt;strong&gt;PTTJS&lt;/strong&gt; (Plain Text Table JavaScript) is a table format I created to solve my own pain points—and, judging by the feedback I’ve already received, I’m not the only one who has felt the limitations of existing text‑table formats.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://github.com/Sergek-Research/PTTJS" rel="noopener noreferrer"&gt;JavaScript library&lt;/a&gt; with a parser + serializer and an &lt;a href="https://github.com/Sergek-Research/pttjs-viewer" rel="noopener noreferrer"&gt;Obsidian plugin&lt;/a&gt; are already available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;The main goal of PTTJS is to provide a &lt;strong&gt;text&lt;/strong&gt; format that can faithfully store &lt;strong&gt;complex tables&lt;/strong&gt;—far beyond what CSV or Markdown can handle—while still remaining human‑readable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;I tolerated the shortcomings of other formats for a long time, but eventually the trade‑offs became impossible to ignore. Key drivers were:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Feeding richer tables to LLMs.&lt;/strong&gt; Documents often contain intricate, merged‑cell tables that can’t be flattened to CSV/Markdown, forcing us to reach for heavier multimodal models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extracting tables via CV into plain text&lt;/strong&gt;, not into a deeply nested JSON blob that’s unreadable until you re‑render it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Letting an LLM manipulate an entire table natively&lt;/strong&gt;—rows, columns, formulas—without shoe‑horning everything through Google Sheets or Excel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opening tables without special software.&lt;/strong&gt; Most tables end up trapped in XLS(X) or ODT; PTTJS keeps them plain text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Editing complex tables in plain‑text tools&lt;/strong&gt; like Obsidian.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Personal dislike of Google Sheets/Excel&lt;/strong&gt; (surely I’m not the only one!).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6diy0d547ovuy943zmb3.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6diy0d547ovuy943zmb3.jpeg" alt="the problem is indicated in points 1 and 2, the format is recognized normally and inserted into the text" width="620" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;the problem is indicated in points 1 and 2, the format is recognized normally and inserted into the text&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Format Overview
&lt;/h2&gt;

&lt;p&gt;The very first line is always an annotation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|PTTJS 1.0|encoding=UTF‑8|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pages
&lt;/h3&gt;

&lt;p&gt;A table can span multiple &lt;em&gt;pages&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|(@P1|Page Name){
    …table data…
}|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Page markers are optional; omit them and the whole table lives on a single page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cells
&lt;/h3&gt;

&lt;p&gt;Every cell starts with &lt;code&gt;|&lt;/code&gt; and ends with &lt;code&gt;&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|H([1|1]1|1|@C1)&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;H&lt;/code&gt;&lt;/strong&gt; — optional marks a header cell&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;([X|Y])&lt;/code&gt;&lt;/strong&gt; — zero‑based cell index (optional; auto‑filled if absent)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;(X|Y)&lt;/code&gt;&lt;/strong&gt; — cell span (defaults to &lt;code&gt;1|1&lt;/code&gt;; always declared in the &lt;em&gt;top‑left&lt;/em&gt; merged cell)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;(@ID)&lt;/code&gt;&lt;/strong&gt; — cell id for references&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Row ends with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a row is otherwise empty but you still have rows below it, include at least one empty cell: &lt;code&gt;|&amp;gt;&amp;lt;|&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Forbidden characters inside cell content (&lt;code&gt;\n | &amp;gt; &amp;lt; { }&lt;/code&gt;) must be &lt;strong&gt;URL‑encoded&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\n  → %5Cn
|   → %7C
&amp;gt;   → %3E
&amp;lt;   → %3C
{   → %7B
}   → %7D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://www.npmjs.com/package/@sergek-research/pttjs" rel="noopener noreferrer"&gt;library&lt;/a&gt; provides &lt;code&gt;escapeValue&lt;/code&gt; / &lt;code&gt;unescapeValue&lt;/code&gt; helpers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scripts
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt;SCRIPT
…typings, formulas, styling…
&amp;lt;&amp;lt;&amp;lt;SCRIPT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Always placed &lt;em&gt;after&lt;/em&gt; all table data.&lt;/li&gt;
&lt;li&gt;Can work across pages.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;&amp;lt;=&lt;/code&gt; for CSS‑like styles. &lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;=&amp;gt;&lt;/code&gt; for cell typings.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;=&lt;/code&gt; for formulas.&lt;/li&gt;
&lt;li&gt;Target a range with &lt;code&gt;:&lt;/code&gt;—e.g. &lt;code&gt;0:0|0&lt;/code&gt; (whole first row) or &lt;code&gt;0|0:0&lt;/code&gt; (whole first column).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The cells always contain up-to-date information. When we add a script, it recalculates the table data and adds the up-to-date information to the cells.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1 – Basic Table
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|PTTJS 1.0|
|H&amp;gt;Plate Number|H&amp;gt;Year|H&amp;gt;Make &amp;amp; Model&amp;lt;|
|&amp;gt;080XXX02|&amp;gt;2005|&amp;gt;LEXUS RX 350&amp;lt;|
|&amp;gt;787XXX16|&amp;gt;2015|&amp;gt;GEELY GC7&amp;lt;|
|&amp;gt;871XXX05|&amp;gt;1997|&amp;gt;TOYOTA IPSUM&amp;lt;|
|&amp;gt;A602XXX|&amp;gt;1996|&amp;gt;MITSUBISHI PAJERO&amp;lt;|
|&amp;gt;890XXX02|&amp;gt;1997|&amp;gt;TOYOTA LAND CRUISER PRADO&amp;lt;|
|&amp;gt;216XXX13|&amp;gt;2007|&amp;gt;DAEWOO NEXIA&amp;lt;|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2 – With Explicit Indexes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|PTTJS 1.0|encoding=UTF‑8|
|H([0|0])&amp;gt;Plate Number|H([1|0])&amp;gt;Year|H([2|0])&amp;gt;Make &amp;amp; Model&amp;lt;|
|([0|1])&amp;gt;080XXX02|([1|1])&amp;gt;2007|([2|1])&amp;gt;LEXUS RX 350&amp;lt;|
…
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3 – Complex Header (Merged Cells)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|PTTJS 1.0|encoding=UTF‑8|
|H(1|2)&amp;gt;Plate Number|H(2|1)&amp;gt;Vehicle Data|H&amp;gt;&amp;lt;|
|H&amp;gt;|H&amp;gt;Year|H&amp;gt;Make &amp;amp; Model&amp;lt;|
|&amp;gt;080XXX02|&amp;gt;2007|&amp;gt;LEXUS RX 350&amp;lt;|
…
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu86maywlhetzrapnyuly.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu86maywlhetzrapnyuly.png" alt="visualization from Obsidian" width="660" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;visualization from Obsidian&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4 – With Scripts
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|PTTJS 1.0|encoding=UTF‑8|
|H([0|0])&amp;gt;Plate Number|H([1|0])&amp;gt;Year|H([2|0])&amp;gt;Make &amp;amp; Model&amp;lt;|
|([0|1])&amp;gt;080XXX02|([1|1])&amp;gt;2007|([2|1])&amp;gt;LEXUS RX 350&amp;lt;|
…
|([0|7])&amp;gt;&amp;lt;|
|([0|8])&amp;gt;Average Year|([1|8])&amp;gt;2003&amp;lt;|

&amp;gt;&amp;gt;&amp;gt;SCRIPT
(1|1,1|6)=&amp;gt;NUMBER(2,' ')
(1|8)=DIV(SUM(1|1,1|6),COUNT(1|1,1|6))
(0|8:8)&amp;lt;=BORDER(each,2,solid,#000)
&amp;lt;&amp;lt;&amp;lt;SCRIPT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Row 9 calculates the average year; numeric formatting is applied; a black 2 px border is added to the "Average Year" label cell.&lt;/p&gt;

&lt;h2&gt;
  
  
  Roadmap
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Execute script functions directly on the parsed &lt;strong&gt;Store&lt;/strong&gt; object.&lt;/li&gt;
&lt;li&gt;Import/export converters (XLS(X), ODT, CSV, MD ↔ PTTJS).&lt;/li&gt;
&lt;li&gt;Libraries in other languages.&lt;/li&gt;
&lt;li&gt;Lightweight web UI for editing PTTJS.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/Sergek-Research/PTTJS" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; is public—PRs and ideas are very welcome!&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Words
&lt;/h2&gt;

&lt;p&gt;Thanks for reading! I hope PTTJS helps you tackle the same table woes I faced. Feel free to reach out, fork the repo, or open an issue—let’s make complex tables easy together.&lt;/p&gt;

</description>
      <category>llm</category>
      <category>cv</category>
      <category>opensource</category>
      <category>datascience</category>
    </item>
  </channel>
</rss>
