Interesting that concepts as dreaming (= background memory reconciliation) that have been in discussion since at least 2023 now enter the production systems
I think working in a filesystem is a local maximum and making a harness that is agnostic of this might be a good idea.
(True enough: It's a local maximum that is hard to overcome. But we already see glimpses here and there such as anthropics scion: Why would an agent even check out the codebase if it could delegate testing, etc to a bunch of runners?)
I've built similar things ad-hoc when creating my project harnesses.
These decision lists kinda work but also they don't: The real challenge for me is fighting decoherence and keeping the orientation in a generated project.
So:
- I guess this works if you review and reshape the agents outputs manually.
- It does not help you a lot building a software factory.
Also good to know about /doctor prompt-audit in Claude Code 2.1.283+:
It reports if there are any contradictions or outdated information in instruction files and does not change anything.
It seems to be hard because it compares the files with each other, not with decisions that were made in sessions.
In Substrate you can see what is in memory and select what each agent sees.
Does decoherence show first in instructions or in generated code?
Thanks for the poem, the feedback and the interest.
Yes, I think to your point: I do review the decision records, and when I approve them, it's because they've articulated something fully that makes sense. My job as the human is to ensure that the record doesn't contain bullshit. It requires me to be epistemically discerning, it requires me to be able to discern bad/broken/fallacious reasoning from epistemic reasoning. That's what colloquially is called "critical thinking."
The kind of approval I do on records is different from the approval of a lot of permission dialogs in CLI harnesses, where you basically see the command-line is harmless, but you don't necessarily fully understand what is going on.
You're right that this has a cost, and the ORRCF (Options, Recommendation, Rationale, Confidence, Falsifier) question format was surgically, or perhaps more honestly "iteratively", designed to reduce the cognitive load on the human: It essentially asks the model to prefetch all the information I might need to even think about a decision, including what the right call is likely to be and why, to bring it all into view for me, for my human context window limits, so that in a few minutes I can load the context in my working memory and be forever satisfied once I'm done that this decision will never have to be made again. It will transfer to other use cases, and other projects. Sometimes the models get things incredibly right, both from their latent space or the rest of our records, and sometimes there's an opportunity to introduce more of my philosophy that will help ensure this deliberation is made correctly now and in the future.
My understanding of your implication is that this isn't worthwhile: But I guess that's where my experience is different. I know (a) how to program, and I know (b) how to justify decisions and evaluate recommendations and reasonings, and I find that exercizing (b) in the context of software building is a better value-add, because I have found to both compound faster and also to make better use of my cognitive abilities. Instead of implementing my idea, I'm being scaffolded into narrowing it down so it can be understand non-ambiguously by current (and future) models.
And to your question, this has absolutely helped me build a software factory. For instance, when Anthropic deprecated Sonnet 4.5 from their platform, I built a harness in Rust and TypeScript that I can host on free tiers and uses various meshes of APIs. Over the summer, every morning, I would get a demo of the features built overnight, with open question raised; I would answer those, specify new features, and go to other projects until the next morning.
Where you are right is that the ADRs4AI framework itself is not all of the components for this formula, it's just the epistemic continuity — the preservation of the "why?" behind everything. There are other components, like pneumatic, the cross-vendor inter-model communication, and the general philosophy behind how I work with agents (which is as extended minds, moreso than extended hands).
The poem made me laugh and I think it's very creative and thoughtful. Thank you for that again! I hope my comment is more genuinely stimulating.
> Thanks for the poem, the feedback and the interest.
It's a paraphrasing of bowies "Life on Mars"
> pneumatic
Interesting! Will check out.
> ... that in a few minutes I can load the context in my working memory and be forever satisfied once I'm done that this decision will never have to be made again
Okay this is an aspect I've not considered enough maybe. But this then applies mostly to decisions that can be phrased project-agnostic.
> My understanding of your implication is that this isn't worthwhile
No. I actually think it is worthwhile!
But I don't think it differs substantially from just having an ad-hoc project harness that's just a bunch of markdown and is maintained by the agents based on the discussions.
It's all a fugazi, as they don't tell you how many tokens you get, it's dynamic. But yes everyone with a Codex subscription felt the token quotas getting a huge cut about 2 weeks after Astra release.
Interesting. I come from a math background and for me, monads capture a notion of "things that depend on a type". So for every type X you can think about Lists/Records/Trees/... of X. And if you're lucky this gadget let's you do two things: 1. You can turn every instance x of X into a primitive List/Record/Tree/... of Xs. 2. You can flatten Lists of Lists of Xs into plain Lists of Xs, etc.
This is something you see a lot once you know what you're looking for.
And if you're really lucky, these two are nicely compatible:
For example there are two ways to get from L(L(L(X))) to L(X): By either flattening first in the inside or first on the outside.
And for a monad, you get the same result either way.
And the computational part is then really more of a consequence: If you've got some function of type X->L(Y) and another one of type Y->L(Z) then you can compose them to a function of type X->L(Z).
What also makes the monad more interesting than just composition or flattening is that when executing the ordered computation, you can decide next computations based on previous results. This was what really made it click for me.
I find it easier to think of them as transforms which turn "a function which accepts/returns plain values" into a "function which accepts and returns a type which embeds plain values".
map :: (a -> b) -> (t a -> t b) -- Functor
bind :: (a -> t b) -> (t a -> t b) -- Monad
cobind :: (t a -> b) -> (t a -> t b) -- Comonad
ap :: t (a -> b) -> (t a -> t b) -- Applicative
The resulting function type is the same in all these cases - the difference is the type of the input function. There are other similar functions which return a `(t a -> t b)` too.
The "ordered computation" isn't unique to monads, it applies to all of these when you chain them. For monads particularly though, you can't begin the continuation until the previous result has been generated - whereas with a comonad, you can begin the continuation right away and extract the value afterwards (inside the continuation).
Can also think of it like a producer/consumer or push/pull thing. Monads push values into some type `t`, and comonads pull values out of `t`.
The naming of `return` is perhaps unfortunate as it gives the impression you're returning a value (done to make do-notation look like imperative code) - but monads don't return values. `return` produces a computation.
`coreturn` is usually called `extract`, which is better naming - it extracts a value from a computation.
The order of arguments is also unfortunate because it makes the above pattern less obvious - they're usually written as:
fmap :: f a -> (a -> b) -> f b
bind :: m a -> (a -> m b) -> m b
So it's not obvious that `fmap` is transforming a function `(a -> b)` into one `(f a -> f b)`, etc.
reply