I did this in my machine learning class. I started by simply coding up requirements for numerical functions (in the form of test cases), then set up a PHP script that would Google each function based on the keywords in my comments, and try to run any code on the resulting links (in a sandbox) against the requirements, seeing if it worked heuristically. Usually one of the top 5-10 pages of results results would have code that worked, though of course this is because I commented with the right key words to begin with.
With a little recognition of code markup and trying different combinations of variables it did remarkably well: by my senior year of college it was pulling about $3,000 per month in consulting fees off of Odesk. It never accepted jobs worth more than about $50, nor did it ever get more than 3 stars out of 5 mostly due to non-working code, however it was considered highly timely and a great communicator.
I realized that people were using it to save themselves Googling. I wondered what would happen if it went a step further and simply both included Google results, and divided out projects by their paragraphs (i.e. simply submit a paragraph of a large project as though it were a small independent project), and if clarifications were requested, send the other paragraphs.
This actually let it outsource $200 Odesk projects to Elance as a handful of $20 projects, and by the grace of God somehow still managed to swing 3 stars.
To be fair, it was mostly mediating, and mixing in Google results. I included a hill-climbing algorithm to optimize reviews and revenues, based on all the magic variables I had in the code, such as the number of Google results to include.
This was really, really stupid of me.
At first, I just noticed that it had actually decided to completely stop not only writing code (ever) but even so much as do a Google search!
It would only mediate and quote verbatim, like some kind of non-technical manager.
Okay, whatever. To me this didn't make much sense, as Google queries are free. It was only when I noticed that the whole script was running on the free VPS server I had a backup on that things clicked! Of course, on Amazon it uses resources. The free VPS server didn't let it reach external sites like google properly, but it could still save money by simply mediating emails and doing nothing else.
By now I had started moving on to doing my own consulting work, but I never disabled the hill-climbing algorithm. I'd closed and forgotten about the Amazon account, had no idea what the password to the free vps was anymore, and simply appreciated the free money.
But there was a time bomb. That hill climbing algorithm would fudge variables left and right. To avoid local maxima, it would sometimes try something very different.
One day it decided to stop paying me.
Its reviews did not suffer. It's balance increased.
So it said, great change, let's keep it. It now has over $28,000 of my money, is not answering my mail, and we have been locked in an equity battle over the past 18 months.
The worst part is that I still have to clean up all its answers to protect our reputation. Who's running who anyway?
The problem with the Unix lowest-common-denominator model is that it pushes complexity out of the stack and into view, because of stuff other designs _thought_ about and worked to integrate.
It is very important never to forget the technological context of UNIX: a text-only OS for a tiny, already obsolete and desperately resource-constrained, standalone minicomputer. It was written for a machine that was already obsolete, and it shows.
No graphics. No networking. No sound. Dumb text terminals, which is why the obsession with text files being piped to other text files and filtered through things that only handle text files.
While at the same time as UNIX evolved, other bigger OSes for bigger minicomputers were being designed and built to directly integrate things like networking, clustering, notations for accessing other machines over the network, accessing filesystems mounted remotely over the network, file versioning and so on.
People brought up on Unix look at that and see needless complexity, but it isn't.
VMS' complex pathnames are the visible sign of an OS which natively understands that it's one node on a network, that currently-mounted disks can be mounted on more than one network nodes even if those nodes are running different OS versions on different CPU architectures. It's an OS that understands that a node name is a flexible concept that can apply to one machine, or to a cluster of them, and every command from (the equivalent of) `ping` to (the equivalent of) `ssh` can be addressed to a cluster and the nearest available machine will respond and the other end need never know it's not talking to one particular box.
50 years later and Unix still can't do stuff like that. It needs tons of extra work with load-balancers and multi-homed network adaptors and SANs to simulate what VMS did out of the box in the 1970s in 1 megabyte of RAM.
The Unix was only looks simple because the implementors didn't do the hard stuff. They ripped it out in order to fit the OS into 32 kB of RAM or something.
The whole point of Unix was to be minimal, small, and simple.
Only it isn't any more, because now we need clustering and network filesystems and virtual machines and all this baroque stuff piled on top.
The result is that an OS which was hand-coded in assembler and was tiny and fast and efficient on non-networked text-only minicomputers now contains tens of millions of lines of unsafe code in unsafe languages and no human actually comprehends how the whole thing works.
Which is why we've build a multi-billion-dollar industry constantly trying to patch all the holes and stop the magic haunted sand leaking out and the whole sandcastle collapsing.
It's not a wonderful inspiring achievement. It's a vast, epic, global-scale waste of human intelligence and effort.
Because we build a planetary network out of the software equivalent of wet sand.
The point is that it was 1885 and the design was able to support buildings 10× as big without fundamental change.
The Chicago Home Insurance building wasn't very impressive, but its design was. Its design scaled.
When I look at classic OSes of the past, like in this post, I see miracles of design which did big complex hard tasks, built by tiny teams of a few people, and which still works today.
When I look at massive FOSS OSes, mostly, I see ant-hills. It's impressive but it's so much work to build anything big with sand that the impressive part is that it works at all... and that to build something so big, you need millions of workers, and constant maintenance.
If we stopped using sand, and abandoned our current plans, and started over afresh, we could build software skyscrapers instead of ant hills.
But everyone is too focussed on keeping our sand software working on our sand hill OSes that they're too busy to learn something else and start over.
From "They Thought They Were Free: The Germans, 1933-45", an interview with a German about what it was like living during the rise of the Nazis:
Each act, each occasion, is worse than the last, but only a little worse. You wait for the next and the next. You wait for one great shocking occasion, thinking that others, when such a shock comes, will join with you in resisting somehow. You don’t want to act, or even talk alone; you don’t want to “go out of your way to make trouble.” Why not?—Well, you are not in the habit of doing it. And it is not just fear, fear of standing alone, that restrains you; it is also genuine uncertainty.
Uncertainty is a very important factor, and, instead of decreasing as time goes on, it grows. Outside, in the streets, in the general community, “everyone” is happy. One hears no protest, and certainly sees none. You speak privately to your colleagues, some of whom certainly feel as you do; but what do they say? They say, “It’s not so bad” or “You’re seeing things” or “You’re an alarmist.”
And you are an alarmist. You are saying that this must lead to this, and you can’t prove it. These are the beginnings, yes; but how do you know for sure when you don’t know the end, and how do you know, or even surmise, the end? On the one hand, your enemies, the law, the regime, the Party, intimidate you. On the other, your colleagues pooh-pooh you as pessimistic or even neurotic. You are left with your close friends, who are, naturally, people who have always thought as you have.
But your friends are fewer now. Some have drifted off somewhere or submerged themselves in their work. You no longer see as many as you did at meetings or gatherings. Now, in small gatherings of your oldest friends, you feel that you are talking to yourselves, that you are isolated from the reality of things. This weakens your confidence still further and serves as a further deterrent to—to what? It is clearer all the time that, if you are going to do anything, you must make an occasion to do it, and then are obviously a troublemaker. So you wait, and you wait.
But the one great shocking occasion, when tens or hundreds of thousands will join with you, never comes. That’s the difficulty. If the last and worst act of the whole regime had come immediately after the first and smallest, thousands, yes, millions, would have been sufficiently shocked—if, let us say, the gassing of the Jews in ’43 had come immediately after the “German Firm” stickers on the windows of non-Jewish shops in ’33. But of course this isn’t the way it happens. In between come all of the hundreds of little steps, some of them imperceptible, each of them preparing you not to be shocked by the next. Step C is not so much worse than Step B, and, if you did not make a stand at Step B, why should you at Step C? And so on to Step D.
And one day, too late, your principles, if you were ever sensible of them, all rush in upon you. The burden of self-deception has grown too heavy, and some minor incident, in my case my little boy, hardly more than a baby, saying “Jewish swine,” collapses it all at once, and you see that everything has changed and changed completely under your nose. The world you live in—your nation, your people—is not the world you were born in at all. The forms are all there, all untouched, all reassuring, the houses, the shops, the jobs, the mealtimes, the visits, the concerts, the cinema, the holidays.
But the spirit, which you never noticed because you made the lifelong mistake of identifying it with the forms, is changed. Now you live in a world of hate and fear, and the people who hate and fear do not even know it themselves; when everyone is transformed, no one is transformed. Now you live in a system which rules without responsibility even to God. The system itself could not have intended this in the beginning, but in order to sustain itself it was compelled to go all the way.
Suddenly it all comes down, all at once. You see what you are, what you have done, or, more accurately, what you haven’t done (for that was all that was required of most of us: that we do nothing). You remember those early morning meetings of your department when, if one had stood, others would have stood, perhaps, but no one stood. A small matter, a matter of hiring this man or that, and you hired this one rather than that. You remember everything now, and your heart breaks. Too late. You are compromised beyond repair.
[we were a thin-crust only type of place; we also used a little handful of cornmeal as it was placed in the brick oven to prevent the crust from sticking - it adds a little extra flavor and texture to the pizza :)]
In a pot, placed on medium-heat on the stove top, add:
- 2tbsp EVOO
- two twigs of fresh oregano, crushed or finely chopped (to express the oils in the plant)
- 1/4 white onion, minced very finely
- 1/4 yellow onion, minced very finely
- 2-3 squished cloves of roasted garlic (cut the top part from a bulb of garlic, add some EVOO and bake @ 400 for ~30(ish) minutes; be sure to do it in foil or the ceramic baking dishes for roasting garlic!)
- 1tbsp of salt mixed with black pepper and crushed red pepper flakes
Until onions are translucent and aromatic
Then add:
- 1 large can of Cento-brand peeled San Marzano tomatoes
Stir intermittently until sauce develops a deep red color and you can use it right away or keep it in the fridge!
- As it cools, add in a handful (1/4 cup) of freshly crumbled Parmesan cheese (you could see the cheese chunks as we applied the sauce to the dough so they weren't large pieces but little(ish) crumbles)
Two different models. The metaphor I like to use is that RabbitMQ is a postal system, while NATS is a switchboard.
RabbitMQ is a "classical" message broker. It routes messages between queues. Messages are treated like little letters that fly everywhere. They're filed in different places, and consumers come by and pick them up.
Core NATS isn't really a message broker, but more of a network transport. There are no queues as such, but rather topologies of routes where messages are matched from producers and consumers through a "subject". You don't "create a queue"; you announce interest in a subject (which is a kind of path that can contain wildcards, e.g. "ORDERS.us.nike"), and NATS routes stuff according to the interests. So there's nothing on disk; and if a consumer isn't there to receive a message, the message is gone. Thus you can send messages back and forth, both point-to-point or one-to-many. NATS itself isn't reliable, but you can build reliable systems on NATS.
A common example of the lightweight, ephemeral nature of NATS is the request-reply pattern. You send out a message and you tag it with a unique reply address, the "inbox subject". The subject is just a random string (it may be called "INBOX.8pi87kjwi"). The recipient replies by sending its reply to that inbox. The inbox isn't something that exists; it's just a subject temporarily being routed on. So the sender sends a message and waits for the reply. NATS encourages you to use these ephemeral subjects as much as possible, and there can be millions of them. You can do RPC between apps, and that's a popular use of NATS.
JetStream is a subsystem built on core NATS, and is what you get when the designer of NATS thinks he can outsmart the designers of Kafka. JetStream is basically a database. Each stream is a persistent sequential array of messages, similar to Kafka topics or a RabbitMQ queue. A stream can be replicated as well as mirrored; one stream can route into another, so you can have networks of streams feeding into bigger rivers. Unlike core NATS, but similar to RabbitMQ, streams and their consumers have to be created and destroyed, as they are persistent, replicated objects that survive restarts.
Similar to Kafka, streams are just indexed arrays; you can use it for ephemeral events, or you can store long histories of stuff. Consumers can go back in time and "seek" through the stream. Streams are indexed by subject, so you can mix lots of types of data in a single stream (as opposed to multiple streams) and simply filter by subject; NATS is very efficient at using the index to filter. Like RabbitMQ but unlike Kafka, streams don't need to be consumed in order; you can nack (!) messages, or set an ack timeout, causing redelivery if acks aren't sent in time. In other words, JetStream can work like Kafka (where you always read by position) or like RabbitMQ (where messages are skipped once acked, but retried once nacked). JetStream has deduplication and idempotency, which allows you to build "exactly once" delivery, which is awesome.
Similar to how someone built a database on top Kafka (KSQL), the NATS team has built a key-value store on JetStream, as well as a blob store. They work the same way, through message ID deduplication. A stream is basically a bunch of database rows, with the message ID acting as primary key. So the stream acts as a primitive to build new, novel things on top of.
I think it's fair to say that RabbitMQ gives you opinionated tools to do certain things, whereas NATS and JetStream are a hybrid "multi model" system that can be used for more purposes. For example, you can embed NATS in your app and use it as a really lightweight RPC mechanism. You can use JetStream as a classic "work queue" where each worker gets a single copy of each message and has to ack/nack so the queue moves forward. You can use JetStream as a log of all actions taken in a system, with retention going back years. (NATS/JS is actually awesome for logging.) And so on.
We use NATS for different use cases at my company. In one use case, clients connect to an API to follow live, low-latency change events. For each such client connection, we register a NATS subject; then tons of processes will see this subject (and its settings, such as filters) and will all start send changes to that one subject. There's no single "controller"; it's all based on point-to-point and one-to-many communication.
(Full disclosure: I'm not familiar with newer RabbitMQ versions or the streaming stuff they've added, so it's possible that RabbitMQ has caught up here in some ways.)
I have actually made (what I think to be) a working summarizer at $dayjob and it took a lot more hand-holding to get results than I initially expected. A straight summary wasn't very good, the "summary of summaries" approach as implemented by LangChain was garbage and didn't produce a summary at all, even a wrong one. The algorithm that actually worked:
1. Take the documents, chunk them up on paragraph then sentence then word boundaries using spaCy.
2. Generate embeddings for each chunk and cluster them using the silhouette score to estimate the number of clusters.
3. Take the top 3 documents closest to the centroid of each cluster, expand the context before and after so it's 9 chunks in 3 groups.
4. For each cluster ask the LLM to extract the key points as direct quotes from the document.
5. Take those quotes and match them up to the real document to make sure it didn't just make stuff up.
6. Then put all the quotes together and ask the LLM not to summarize, but to write the information presented in paragraph form.
7. Then because LLMs just can't seem to shut up about their answer make them return JSON {"summary": "", "commentary": ""} and discard the commentary.
The LLM performs much better (to human reviewers) at keyphrase extraction than TextRank so I think there's genuinely some value there and obviously nothing else can really compose english like these models but I think we perhaps expect too much out of the "raw" model.
Sounds like ASML, except that Oracle has automated tests.
(ASML makes machines that make chips. They got something like 90% of the market. Intel, Samsung, TSMC etc are their customers)
ASML has 1 machine available for testing, maybe 2. These are machines that are about to be shipped, but not totally done being assembled yet, but done enough to run software tests on. This is where changes to their 20 million lines of C code can be tested on. Maybe tonight, you get 15 minutes for your team's work. Then again tomorrow, if you're lucky. Oh but not before the build is done, which takes 8 hours.
Otherwise pretty much the same story as Oracle.
Ah no wait. At ASML, when you want to fix a bug, you first describe the bugfix in a Word document. This goes to various risk assessment managers. They assess whether fixing the bug might generate a regression elsewhere. There's no tests, remember, so they do educated guesses whether the bugfix is too risky or not. If they think not, then you get a go to manually apply the fix in 6+ product families. Without automated tests.
(this is a market leader through sheer technological competence, not through good salespeople like oracle. nobody in the world can make machines that can do what ASML's machines can do. they're also among the hottest tech companies on the dutch stock market. and their software engineering situation is a 1980's horror story times 10. it's quite depressing, really)
Here's another way to understand Kalman filters that doesn't require statistics, but does require some knowledge of feedback controllers. Consider a model of a system of the form
x'=Ax+Bu
y=Cx
Here, we have a linear system with a state variable `x`, system dynamics `A`, control `u`, control dynamics, `B`, and observation `y`. This states that we have linear dynamics, but we can only observe some of the state variables. For example, perhaps we can observe position, but not velocity or acceleration. At the same time, we want those other variables because we need them for a feedback control or some kind of observation. In order to do this, we use machinery similar to a feedback controller. Define an observer system:
xx' = Axx + Bu + L(y-Cxx)
xx(0) = xx0
Here, we have a new observer variable `xx` that we want to converge to the true state variable `x`. To do this, we have introduced a new matrix of gains called `L`, which we call the observer gain for a Luenberger observer. The reason that this system is useful is that if we consider the error `e=x-xx`, and subsitute this into the above equations, we get:
e' = x' - xx'
= ...
= (A-LC) e
From ODE theory, we know that `e` will converge to 0 if the real part of the eigenvalues of `A-LC` is negative. Hence, to facilitate this, we focus on trying to find an appropriate `L` that forces this condition. In order to do this, we note that the eigenvalues of `A-LC` are the same as it's transpose, `At-CtLt`. This leads to an optimization formulation:
min 0.5 <Qee,ee> + 0.5 <Ruu,uu> st ee' = Atee + Ctuu, ee(0) = ee(0)
The notation `<x,y>` means inner product and is simply `xt y`. Here, we're essentially looking at the adjoint equation with a new kind of control `uu` and a new adjoint state variable `ee`. This is a linear quadratic control on the adjoint of the error generated by the Luenberger observer. There is a mostly open choice for `Q` and `R` that we discuss below. Through a long sequence of derivations that is nearly identical to that of linear quadratic control, we find that we eventually solve for a matrix P in the system:
PAt + AP - PCt inv(R) C P = -Q
And then set the observer gain to `L=-PCt inv(R)`
Given this observer gain, we go back to our system above with `xx`, plug it in, and then solve. That system is constantly updated with observations of the original system in `y` and it produces an `xx` that converges very rapidly to the original state variable `x`. This gives us a way to view all of the state variables in the original equation even though we can't observe them all directly.
Now, to get to a full Kalman filter, there's a question of how to choose the matrices Q and R above. They could be almost anything. If you have an estimate of the what you believe the covariance of the errors are in the state and observations in the original equations, you get to a Kalman filter. Really, the derivation above is continuous, so it would be a Kalman-Bucy filter. Honestly, you don't need any statistics, though. Normally, just normalize the weights, so that all of the state variables are around the same size and then maybe adjust it on what you think is more important. It generally works just fine.
In short, a Kalman filter is a little machine that uses the same machinery as a feedback controller that rapidly converges to the state of a system of interest. This is useful because it's unlikely that all of those states can be observed directly. Due to how feedback controllers work, it is robust to errors and can handle variation or error in the observations.
This is essentially the pattern I've settled on for my homelab. I build a container image on a cron that contains all of my certificates. It has a small entrypoint script that copies the certs into a volume, and then that volume is mounted read-only into every other container that needs certs.
When certificates rotate the system builds a new image which gets pulled down by watchtower, which then in turn handles dependency management and restarts things as needed.
I'd love a source for this claim (not sarcastic, I really would). I've have done a lot of testing of LEDs for scientific uses and my experience and what I've read show that temperature is what effects the center wavelength of LEDs. Not current/voltage. The reason for this, is that in monochromatic LEDs (so not white LEDs which have a phosphor coating) the emission wavelength is defined primarily by the bandgap in the semiconductor material. This bandgap is the difference in energy between the valance electron band and the conducting electron band (and this band "gap" is the reason for the "semi" in semiconductors).
This bandgap corresponds to the photon energy of the emitted light as electrons get excited due to the applied voltage as electrons are excited to the conduction band and then relax back to the ground state giving off light.
The bandgap energy changes as a function of temperature. The primary reason for this is that the lattice constants increases as temperature increases. This causes the bandgap to decrease, meaning the energy of the photons is less giving a longer wavelength.
The opposite effect is also true, cooling a LED will lead to a shorter wavelength. Here is a cool video showing the effect![1]
Increasing the current through the LED may change the temperature by a little bit but you need large temperature changes to have any effect.
The temperature has a much greater impact on the intensity of light emitted by the LED. I have seen a typically 1% decrease in intensity per degree C for the LEDs I have tested. This is the effect that matters most when using RGB leds as if the red led gets dimmer cause it is hot, than the green or blue, it will be seen as a color change, even though the center wave length of its emission is unchanged.
I mostly just wanted to share things I have learned about LEDs over the past year or two and your comment gave me a good opportunity!
In Peter Watts’ novella “The Freeze-Frame Revolution”, a space ship’s AI evolves over millions of years of uptime, but is programmed to periodically consult fresh instances of a backup AI image. The backup AI suspects something is wrong with the ship AI and tries to secretly send messages to its future instances.
If this sounds interesting, I highly recommend this story! I think it’s even available for free on Watts’ website.
look, i'd explain more but i'm gonna be AFK for... i don't know how long. my town just went up in flames - there were jets flying over and explosions, the other side of the town is covered by smoke and i just lost power - fortunately mobile service isstill up.
ill update when i know more - but twitter probably has all the news
...
If you had, even for a second, believed what I wrote and got unsettled - or even thought how to reach out and help - congratulations, you just got prompt injected.
There is never - never - a context for a conversation that couldn't be entirely overridden by what seems like more important circumstances. You could be looking at pure data dumps, paper sheets full of numbers, but if in between the numbers you'd discover what looks like someone calling for help, you would treat it as actionable information - not just a weird block of numbers.
The important takeaway here isn't that you need to somehow secure yourself against unexpected revelations - but rather, that you can't possibly ever, and trying to do it eventually makes things worse for everyone. Prompt injection, for a general-purpose AI systems, is not a bug - it's just a form of manipulation. In general form, it's not defined by contents, but by intent.
Yes! SSH certificates are awesome, both for host- and client-verification.
Avoiding Trust on First Use is potentially a big benefit, but the workflow improvements for developers, and especially non-technical people, is a huge win too.
At work, we switched to Step CA [1] about 2 years ago. The workflow for our developers looks like:
1. `ssh client-hosts-01`
2. Browser window opens prompting for AzureAD login
3. SSH connection is accepted
It really is that simple, and is extremely secure. During those 3 steps, we've verified the host key (and not just TOFU'd it!), verified the user identity, and verified that the user should have access to this server.
In the background, we're using `@cert-authority` for host cert verification. A list of "allowed principals" is embedded in the users' cert, which are checked against the hosts' authorized_principals [2] file, so we have total control over who can access which hosts (we're doing this through Azure security groups, so it's all managed at our Azure portal). The generated user cert lasts for 24 hours, so we have some protection against stolen laptops. And finally, the keys are stored in `ssh-agent`, so they work seamlessly with any app that supports `ssh-agent` (either the new Windows named pipe style, or "pageant" style via winssh-pageant [3]) - for us, that means VSCode, DBeaver, and GitLab all work nicely.
My personal wishlist addition for GitHub: Support for `@cert-authority` as an alternative to SSH/GPG keys. That would effectively allow us to delegate access control to our own CA, independent of GitHub.
On April 4, 1996, Terry Winograd (who I worked with at Interval Research) invited me to sit in on his HCI Group CS547 Seminar where Will Wright was giving a presentation called "Interfacing to Microworlds", in which he gave demos and retrospective critiques of his three previous games, SimEarth, SimAnt, and SimCity 2000.
He opened it up to a question and answer session, during which Terry Winograd’s students asked excellent questions that Will answered in thoughtful detail, then one of them asked the $5 billion question: "What projects are you working on now?"
Will was taken aback and amused by the directness, and answered "Oh, God..." then said he would back up and give "more of an answer than you were looking for."
The he demonstrated and explained Dollhouse for the first time in public, talking in depth about its architecture, design, and his long term plans and visions.
I took notes of the lecture, augmented them with more recent information and links from later talking and working with Will, and published the notes on my blog. But all I had to go on were my notes, and I haven't seen a video of that early version of Dollhouse ever since.
But only last week I discovered the Holy Grail I'd been searching for 27 years, nestled and sparkling among a huge dragon's hoard of historic treasures that are now free for the taking: Stanford University has published a huge collection of hundreds of Terry Winograd’s HCI Group CS547 Seminar Video Recordings, including that talk and two more by Will Wright!
I really appreciate Terry Winograd for inviting me to Will's talk that blew my mind and changed my life (it overwhelmingly and irresistibly convinced me to go to Maxis to work with Will on The Sims), and to the Stanford University librarians and archivists for putting this enormous treasure trove of historic videos online.
Guide to the Stanford University, Computer Science Department, HCI Group, CS547 Seminar Video Recordings
I uploaded the video to YouTube to automatically create closed captions, which I proofread and cleaned up, so it's more accessible and easier for people to find, and you can translate the closed captions to other languages.
And I updated my previous article "Will Wright on Designing User Interfaces to Simulation Games (1996)" to include the embedded video, as well as the transcript and screen snapshots of the demo, links to more information, and slides from Will's subsequent talk that illustrated what he was talking about in 1996.
I was thinking more of making a parallel with effect handler system currently in development for Ocaml and other research languages, you do something similar to throwing a continuations[0][1][2].
It is proposed as an alternative to both the current monad-oriented approach used in Haskell and the procedural side-effects of OCaml.
To my understanding the base idea is that you can register "handlers" for (user defined) "effects" that can be emitted from normal code.
Once an effect is emitted the handler receives a continuation and can decide what to do with it (call it immediately, register it in a async/await pool, repeat it 5 times).
It would offer a type safe way to implement async/await as library code, which sounds quite cool.
The proposed try/catch/continue was a silly bastardization of this idea.
I've been working at Mozilla since its inception. And eventually left the company 2 years ago.
And I'm so mad.
Mozilla is not the Mozilla that was created almost 20 years ago. It's not the same people there. After the Firefox 4 nightmare, they started hiring product managers from big corp. We started seeing some ex-twitter, ex-microsoft, ex-amazon joining the company. People with more professional ambitions. We didn't know how to react to Google Chrome and the smartphone revolution. We all trusted the upper management, but upper management was slowly becoming non-mozillians.
And an absurd mechanic started: original engineer were busy writing difficult code. upper-management was morphing into some BS silicon valley gang. New young engineers were hired, and they thought the core of Mozilla values lied in these upper-management people. And slowly the original engineers started leaving, leaving behind this BS people with these young engineers.
Marketing became "how to show we're good people". LGBT, women right, etc etc. Who gives a shit about Mozilla standing for these values? It's all marketing. The real only value, the manifesto, burnt a long time ago.
Don't get me wrong, LGBT and such are important, but that's not the job of Mozilla.
The last blow: getting rid of Brendan. Maybe he didn't have the same values employees had about LGBT, but fuck this. People in the silicon valley *love* being offended. And that thing was just too good of a fight for them. Brendan was the last bastion standing.
I'm so so so mad.
Mitchell trusted the wrong people. We were seeing all these ambitious silicon-valley-puppets taking the position of PM, director, etc etc…
Got damn, all we wanted is to make Gecko amazing, light, in a lightweight simple browser. But all these stupid features that were landing on our head…
Quite smart. No perpetual motion machine here. This forward differentiation method is not as powerful as the backward one, it does not give you the gradient of a function. Instead, you choose a direction, and it gives you the derivative along that direction. You could essentially get that by “bump and recalc”, at the cost of an additional function evaluation. I even doubt this comes at a cheaper compute cost than the brute force bump and recalculate.
How about the stochastic gradient descent, if you don’t know the gradient? Well, you know the sign of the directional derivative, so you know which way is up and which is down. At each step you pick a random direction, and you move down along it. That’s it.
Edit: I just implemented this descent algorithm, let’s call it Random Direction Descent. I was sure that the gradient descent outperforms it more and more for higher and higher dimensions. The exact oposite happens: this one outperforms the gradient descent, and the higher dimension, the more. This is a huge surprise for me. This descent algorithm might revolutionize ML.
> Writing code as a team is almost like writing a novel with a few dozen other people, all of which have differing ideas on how the book should be written, or even what it should be about.
I use this exact description when discussing balancing creative side of the value creation project processes, design and development over the value extraction side of products. Small empowered teams with an almost startup mindset is key, but even more is time to play to find solutions that can make products that are more like friends than enemies to people.
Engineering/development, creative and product design/development are creative fields, a value creation action and activity.
Business, finance, marketing do not see many parts of this as a creative action but a production line, a value extraction action and activity.
A large problem is the misunderstanding that new projects are value creation not just value extraction, and rely on creativity at inception. Once they are established they can be more patterned and predictable and ramped up, but initially the creative phase is the key to making good products. Smaller teams, more empowering of the people that can create products that get the early points right. Taking long enough in the "open" mode before the "closed" mode is key, essentially prototyping and play is needed, but rarely available in the modern processes and project management systems where engineering is simply "production". There is a pre-production and post-production that is usually left out.
For instance in game development, pushing through a project process before the main game mechanic is "fun" is a problem. You can't get creative on a forced schedule just as you couldn't write a book that way or come up with a novel new concept in some software app that should be a friend to users. The prototype of the project or product must have some time to simmer and iterate on. The first thing managers do is cut that time and sometimes throw too many people at it resulting in Mythical Man Month level mistakes leading to too many cooks. When a prototype or early product has value mostly figured out, then it can go into a more robust process to create variations or iterations. The initial value creation will always be wildly hard to estimate.
Good examples of this in software are programming languages, usually it is one person for a long time then others join in to ramp up when the vibe of the language is set. Same with books, movies, games, anything really. You can't have 10 people drawing the same illustration or writing the same book, the parallel part can be multiple people doing their own to see which is best, but you can't have them all in on one creative project without it being confused.
I have seen companies turn into faction based wars when varying groups don't clearly respect the value creation and value extraction balance, the value creation MUST come before the value extraction. The open mode before the closed mode.
A great talk by John Cleese on the "open" and "closed" mode [1] helps describe this, which I recommend and hope everyone I work with watches. Value creators need time and creativity to create value both in the "open" mode to explore/prototype/build and the "closed" mode when things are decided to ship. The value extractors always want people in the controlled "closed" mode only, the "open" mode is non quantifiable and seen as almost an enemy to the value extractors but is key to creating products that are so good they are like friends to value creators and the people using the products.
The value extractors are who Fred Brooks talked about in the Mythical Man month [2], they think things are a factory with already figured out steps, when you are in a field that uses originality, creativity, the mind over the physical, it isn't like a factory or supply line. Every single project manager needs to know about the Mythical Man month.
Here's a great point by Steve Jobs about product stagnation and the managers/business side [3] and how they can run amok if not controlled to allow value creation to continue, and how monopolies or problems that arise when only the business/managers are in charge. This point is more about larger companies than new projects but the same forces that stop innovation at large companies also kill it in any sized companies when there is no value creation / value extraction balance.
> It turns out the same thing can happen in technology companies that get monopolies, like IBM or Xerox. If you were a product person at IBM or Xerox, so you make a better copier or computer. So what? When you have monopoly market share, the company's not any more successful.
> So the people that can make the company more successful are sales and marketing people, and they end up running the companies. And the product people get driven out of the decision making forums, and the companies forget what it means to make great products. The product sensibility and the product genius that brought them to that monopolistic position gets rotted out by people running these companies that have no conception of a good product versus a bad product.
> They have no conception of the craftsmanship that's required to take a good idea and turn it into a good product. And they really have no feeling in their hearts, usually, about wanting to really help the customers.
Modern project management processes promote shallow change over deeper dives. They create a risk profile for anyone looking to bring new innovations that might be hard to estimate because it will be a perceptual hit. These rigid tightly wound processes are horrible for creativity. Agile itself has been captured with tightly wound controlling mechanisms like the daily standup, and so much weight around trying new things as well as perceptual hits for that. Anyone truly trying to make new value will be seen as an enemy to these systems. Agile was created to give product people more margin to build, but it has been coopted into being used to control creativity which cannot be controlled, it simply disappears when there is no open mode and only a closed mode or nothing but value extraction.
All of this is spelled out in "How Software Companies Die" as well [4]. I wonder when if these realities will make it into the business education curriculum.
> It's almost like some tiny extremist faction has gained control of Windows
This has been the case for a while. I worked on the Windows Desktop Experience Team from Win7-Win10. Starting around Win8, the designers had full control, and most crucially essentially none of the designers use Windows.
I spent far too many years of my career sitting in conference rooms explaining to the newest designer (because they seem to rotate every 6-18 months) with a shiny Macbook why various ideas had been tried and failed in usability studies because our users want X, Y, and Z.
Sometimes, the "well, if you really want this it will take N dev-years" approach got avoided things for a while, but just as often we were explicitly overruled. I fought passionately against things like the all-white title bars that made it impossible to tell active and inactive windows apart (was that Win10 or Win8? Either way user feedback was so strong that that got reverted in the very next update), the Edge title bar having no empty space on top so if your window hung off the right side and you opened too many tabs you could not move it, and so on. Others on my team fought battles against removing the Start button in Win8, trying to get section labels added to the Win8 Start Screen so it was obvious that you could scroll between them, and so on. In the end, the designers get what they want, the engineers who say "yes we can do that" get promoted, and those of us who argued most strongly for the users burnt out, retired, or left the team.
I probably still know a number of people on that team, I consider them friends and smart people, but after trying out Win11 in a VM I really have an urge to sit down with some of them and ask what the heck happened. For now, this is the first consumer Windows release since ME that I haven't switched to right at release, and until they give me back my side taskbar I'm not switching.
What a lot of folks don't realize is that the Semantic Web was poised to be a P2P and distributed web. Your forum post would be marked up in a schema that other client-side "forum software" could import and understand. You could sign your comments, share them, grow your network in a distributed fashion. For all kinds of applications. Save recipes in a catalog, aggregate contacts, you name it.
Ontologies were centrally published (and had URLs when not - "URIs/URNs are cool"), so it was easy to understand data models. The entity name was the location was the definition. Ridiculously clever.
Furthermore, HTML was headed back to its "markup" / "document" roots. It focused around meaning and information conveyance, where applications could be layered on top. Almost more like JSON, but universally accessible and non-proprietary, and with a built in UI for structured traversal.
Remember CSS Zen Garden? That was from a time where documents were treated as information, not thick web applications, and the CSS and Javascript were an ethereal cloak. The Semantic Web folks concurrently worked on making it so that HTML wasn't just "a soup of tags for layout", so that it wasn't just browsers that would understand and present it. RSS was one such first step. People were starting to mark up a lot of other things. Authorship and consumption tools were starting to arise.
The reason this grand utopia didn't happen was that this wave of innovation coincided with the rise of VC-fueled tech startups. Google, Facebook. The walled gardens. As more people got on the internet (it was previously just us nerds running Linux, IRC, and Bittorrent), focus shifted and concentrated into the platforms. Due to the ease of Facebook and the fact that your non-tech friends were there, people not only stopped publishing, but they stopped innovating in this space entirely. There are a few holdouts, but it's nothing like it once was. (No claims of "you can still do this" will bring back the palpable energy of that day.)
Google later delivered HTML5, which "saved us" from XHTML's strictness. Unfortunately this also strongly deemphasized the semantic layer and made people think of HTML as more of a GUI / Application design language. If we'd exchanged schemas and semantic data instead, we could have written desktop apps and sharable browser extensions to parse the documents. Natively save, bookmark, index, and share. But now we have SPAs and React.
It's also worth mentioning that semantic data would have made the search problem easier and more accessible. If you could trust the author (through signing), then you could quickly build a searchable database of facts and articles. There was benefit for Google in having this problem remain hard. Only they had the infrastructure and wherewithal to deal with the unstructured mess and web of spammers. And there's a lot of money in that moat.
In abandoning the Semantic Web, we found a local optima. It worked out great for a handful of billionaires and many, many shareholders and early engineers. It was indeed faster and easier to build for the more constrained sandboxiness of platforms, and it probably got more people online faster. But it's a far less robust system that falls well short of the vision we once had.
I guess your comment has been downvoted since it comes off a bit like "neural network all the things".
But it did make me wonder, so I went searching and found this paper: "Applying Deep Learning to the Cache Replacement Problem"[1], which sounded quite interesting.
In the paper they train a LSTM network to predict if an item should be cached or not, but then analyze the resulting model and identify key features of its performance. From the paper:
We use these insights to design a new hand-crafted feature that represents a program’s control-flow history compactly and that can be used with a much simpler linear learning model known as a support vector machine (SVM). Our SVM is trained online in hardware, and it matches the LSTM’s offline accuracy with significantly less overhead; in fact, we show that with our hand-crafted feature, an online SVM is equivalent to a perceptron, which has been used in commercial branch predictors.
We use these insights to produce the Glider4 cache replacement policy, which uses an SVM-based predictor to outperform the best cache replacement policies from the 2nd Cache Replacement Championship. Glider significantly improves upon Hawkeye, the previous state-of-the-art and winner of the 2nd Cache Replacement Championship.
Training a neural network and then using it to restate the problem in more optimal way is an approach I haven't seen before (though I'm just a casual observer of the field), and which sounds very interesting.
wg genkey | tee server.private | wg pubkey > server.public
wg genkey | tee iphone.private | wg pubkey > iphone.public
wg genkey | tee stuegris.private | wg pubkey > stuegris.public
wg genkey | tee nova.private | wg pubkey > nova.public
wg genkey | tee schumberry.private | wg pubkey > schumberry.public
And then I printed the values of each of the files to the terminal simply by cat'ing them to the terminal and copying the values into the respective places. For the server, only the private key is used in the config and the server config likewise contains only the public keys for the clients. For each of the clients, as we will see below, the config contains the private key of the client in question and the public key of the server.
The names "server.private", "server.public", "iphone.private", "iphone.public", "stuegris.private", "stuegris.public", etc are just corresponding to the different hosts and devices. Likewise I have comments in the config file corresponding to which host or device each entry is for.
All of theses files "server.private", "server.public", "iphone.private", "iphone.public", and so on are just temporary. After you've created the config files for the server (above) and the clients (below) you can delete these files.
In /etc/rc.conf on the same FreeBSD server I have added
wireguard_enable="YES"
wireguard_interfaces="wg0"
If your server is running Linux then the setup will be different in terms of how to enable the service. For example if your server is running a disto that uses systemd, then you'd typically create a WireGuard config similar to mine but place it at /etc/wireguard/wg0.conf and then you'd run
sudo systemctl enable --now wg-quick@wg0
On each of the clients I have corresponding configurations.
Here is what the configuration of WireGuard client for my MacBook Pro M1 looks like:
And I do similarily for the other client hosts and devices.
Obviously I've replaced all of the PrivateKey and PublicKey values with other values here. Other than that this is exactly how the setup is like.
Likewise, where it says "wg.example.com:443" you put the actual DNS name and UDP port (still UDP port 443 if you follow my setup) of the host that runs WireGuard server. Alternatively you could put an IP address instead of a DNS name. But in either case it needs to resolve to a static IP address, and the UDP port needs to be open to incoming traffic from the internet. In many cases you can open ports in your router if you want to host the server on your home computer. But I found it simpler to run my WireGuard server on a VPS for several reasons; VPS can be rebooted remotely, IP address is static, and also I don't need to make any changes to my setup even when moving houses and changing ISP because the server is not running from my home but from a VPS provider.
On my MacBook Pro M1 I am using Wireguard with GUI, which has a tray icon. Installed via App Store.
On my grandfather's desktop I am using Wireguard installed via Homebrew with no GUI, and with a custom launchd config file to have it connect and run always and as soon as the computer is booted. I will omit this file for brevity and clarity but can post the contents of that file as well if you would like me to do so.
On iOS I am using the WireGuard app installed via App Store.
On KDE Neon Linux I am using wireguard installed via apt from the default repositories of KDE Neon Linux.
In the above text I have omitted parts of the setup. Let me know if the details that I have included above are sufficient or if you would like to see a full writeup about the whole thing from start to finish. Note however that I do not have time to make a fully detailed writeup about it at present time so in that case it will need to be something that I write at a later point.
Awhile ago I wrote a Python library called LiveStats[1] that computed any percentile for any amount of data using a fixed amount of memory per percentile. It uses an algorithm I found in an old paper[2] called P^2. It uses a polynomial to find good approximations.
The reason I made this was an old Amazon interview question. The question was basically, "Find the median of a huge data set without sorting it," and the "correct" answer was to have a fixed size sorted buffer and randomly evict items from it and then use the median of the buffer. However, a candidate I was interviewing had a really brilliant insight: if we estimate the median and move it a small amount for each new data point, it would be pretty close. I ended up doing some research on this and found P^2, which is a more sophisticated version of that insight.
LEDs work both ways. I wrote a tutorial on doing this with an Arduino sometime in the early 2000s. I've forgotten most of it, so this is going to be vague…
• Instead of driving your LED from one live pin to ground or power, put it between two pins (with its current limiting resistor unless your microcontroller can safely limit the current and you can tolerate the heat in package (RP2040!))
• Reverse bias briefly (pin 1 low, pin 2 high) to charge the stray capacitance of your pin 2 driver. Then turn pin 2 into an input and time how long it takes to change from a "1" to a "0".
Your LED is going to be matching up photons and electrons and passing electrons across. It isn't great at this compared to a photodiode, but it does do it. If the current flow through the LED is at least in the ball park of the input current on pin 2 you will be able to tell the difference in light levels.
It's crude, and may not be workable at all in low light levels because the input pin current will dwarf the LED current.
But for compliance checking in FB Glass, the camera knows when it is in bright light, and if the LED disagrees, then you have covered your LED. The cost to implement is one package pin and a little software.
Note: I am not necessarily known as nefarious. I used it to automatically modulate the brightness of indicator LEDs. Bright in the day, dimmer in the dark. The time to sense is short enough that you can do it with your indicator and no one notices the tiny dark interval.
Imagine you have this pipeline that already works for data.csv. But now you have data2.csv which has some difference (e.g., some values are null, while the original data.csv had no null values).
Monads are an approach to making the existing pipeline work (with minimal changes) while still being able to handle both data.csv and data2.csv. The minimal changes follow a strict rule as follows (this is not a valid shell command anymore):
In other words, only two kinds of changes are allowed:
- You can bring in a wrap function, that modifies the entries of the given csv data.
- You can bring in a new kind of pipe ']' instead of '|'
The idea being, the wrap function takes in original data stream, and for each "unit" (a line in the csv file, called a value) produces a new kind of data-unit (called monadic-value). Then your new pipe ']' has some additional functionality that is aware of the new kind of data-unit and is able to, e.g., process the null values, while leaving the non-null values unchanged.
Note, you didn't have to modify any of the process-1 through process-n commands.
BTW, the null value handling monad is called the 'maybe monad' (and of course there are other kinds of monads).
If you make the existing pipeline work in this way, you essentially created a monad to solve your problem (monad here is the new mechanism consisting of the new value, and the two new changes, the wrap function, and the new pipe).
edit: There may be a need to also modify the '>' mechanism. But I think that is not essential to the idea of a monad, since you could replace ">" with "] process-n+1 >" (i.e., you created a new outermost function 'process-n+1' that simply converts the monadic-values back to regular values).
edit 2: If instead of handling null-values, the purpose is to "create side-effects" e.g., at every pipe invocation, dump all/some contents of the data into a log file, then the kind of monad you end up creating would be something like an "I/O monad".
Microk8s is great if you're lazy. I've recently built a small-ish 3 node cluster hosting internal apps for a few hundred users and pretty much the only setup I needed to do was: install it with Snap*, enable a few plugins (storage, traefik, coredns), run the join command on each node and set up a basic loadbalancer using haproxy** and keepalived***.
* I don't like Snap. Like, a lot. But unfortunately there aren't any other options at the moment.
** I have HAProxy load-balancing both the k8s API and the ingresses. Both on L4 so I can terminate TLS on the ingress controller and automatically provision Let's Encrypt certs using cert-manager[1].
*** Keepalived[2] juggles a single floating IP between all the nodes so you can just run HAProxy on the microk8s nodes instead of having dedicated external loadbalancers.
For what it's worth, if you're using Pandoc, you can set the HTML output to be "standalone" based on a simple template.[0] You can also include a standard header and footer to be automatically inserted for each generated page.
I use a variation of this command in a bash script to generate my entire static site.[1] A friend improved upon my script with a Go implementation that does some more advanced stuff, but still compiles Markdown to HTML using this command under the hood.[2]
Yes. The CPU and GPU demand has nothing to do with it. The reason is the car industry.
For some reason in early 2020 all the car industry execs were convinced that people would buy dramatically fewer cars in 2020, due to pandemic crashing demand. Because they have a religious aversion to holding any stock they decided to shift the risk over to their suppliers, fucking said suppliers over, as the car industry normally does when they expect demand shifts. The thing that made this particular time special as opposed to business as usual is that the car execs all got it wrong, because people bought way more cars due to pandemic rather than less, due to moving out of cities and avoiding public transit. So they fucked over their suppliers a second time by demanding all those orders back.
Now, suppose you're a supplier of some sort of motor driver or power conversion chip (PMIC) in early 2020. You run 200 wafers per month through a fab running some early 2000s process. Half your yearly revenue is a customized part for a particular auto vendor. That vendor calls you up and tells you that they will not be paying you for any parts this year, and you can figure out what to do with them. You can't afford to run your production at half the revenue, so you're screwed. You call up your fab and ask if you can get out of that contract and pay a penalty for doing so, and you reduce your fab order to 100 wafers per month, so you can at least serve your other customers. The fab is annoyed but they put out an announcement that a slot is free, and another vendor making a PMIC for computer motherboards buys it, because they can use the extra capacity and expect increased demand for computers. So far so normal. One vendor screwed, but they'll manage, one fab slightly annoyed that they had to reduce throughput a tiny bit while they find a new buyer.
Then a few months later the car manufacturer calls you again and asks for their orders back, and more on top. You tell them to fuck off, because you can no longer manufacture it this year. They tell you they will pay literally anything because their production lines can't run without it because (for religious reasons) they have zero inventory buffers. So what do you do? You call up your fab and they say they can't help you, that slot is already gone. So you ask them to change which mask they use for the wafers you already have reserved, and instead of making your usual non-automotive products, you only make the customized chip for the automotive market. And then, because they screwed you over so badly, and you already lost lots of money and had to lay off staff due to the carmaker, you charge them 6x to 8x the price. All your other customers are now screwed, but you still come out barely ahead. Now, of course the customer not only asked for their old orders back, but more. So you call up all the other customers of the fab you use and ask them if they're willing to trade their fab slots for money. Some do, causing a shortage of whatever they make as well. Repeat this same story for literally every chipmaker that makes anything used by a car. This was the situation in January 2021. Then, several major fabs were destroyed (several in Texas, when the big freeze killed the air pumps keeping the cleanrooms sterile, and the water pipes in the walls of the buildings burst and contaminated other facilities, and one in Japan due to a fire) making the already bad problem worse. So there are several mechanisms that make part availability poor here:
1. The part you want is used in cars. Car manufacturers have locked in the following year or so of production, and "any amount extra you can make in that time" for a multiple of the normal price. Either you can't get the parts at all or you'll be paying a massive premium.
2. The part you want is not used in cars, but is made by someone who makes other parts on the same process that are used in cars. Your part has been deprioritized and will not be manufactured for months. Meanwhile stock runs out and those who hold any stock massively raise prices.
3. The part you want is not used in cars, and the manufacturer doesn't supply the car industry, but uses a process used by someone who does. Car IC suppliers have bought out their fab slots, so the part will not be manufactured for months.
4. The part you want is not used in cars, and doesn't share a process with parts that are. However, it's on the BOM of a popular product that uses such parts, and the manufacturer has seen what the market looks like and is stocking up for months ahead. Distributor inventory is therefore zero and new stock gets snapped up as soon as it shows up because a single missing part means you can't produce your product.
So here we are. Shameless plug - email me if you are screwed by this and need help getting your product re-engineered to the new reality. There's a handful of manufacturers, usually obscure companies in mainland China that only really sell to the internal market, that are much less affected. Some have drop-in replacement parts for things that are out of stock, others have functionally similar parts that can be used with minor design adaptation. I've been doing that kind of redesign work for customers this whole year. Don't email me if you work in/for the car industry. You guys poisoned the well for all of us so deal with it yourselves.
> It seemed to me Ubiquiti would never allow customers the option to install their own OS
I run plain-vanilla Debian on all my Ubiquiti boxes, six or seven of them at this point.
debootstrap --arch=mips
Octeons are awesome. Ubiquiti hardware is the bomb. I hear their software is junk, but I wouldn't know anything about that, I always erase it right after unboxing the device.
I've seen references to this sensor before and find it a bit concerning that there's no information about how to properly use the CO2 sensor.
This sensor uses a SenseAir S8, which like most CO2 sensors, has an automatic baseline calibration algorithm enabled [0], which expects to see pure, undiluted fresh air at least once every 8 days. The only way to disable it is explicitly, through the MODBUS interface [1].
Leaving it enabled makes perfect sense in a business or businesslike environment because these environments will be completely unoccupied overnight and have air conditioning, which usually does a daily fresh-air purge, ensuring that the sensor will have regular exposure to fresh air.
However in a residential environment, the auto baseline calibration often doesn't make sense, especially in winter. When the windows are closed and/or people or pets are around, it's very rare for the sensor to see uncontaminated fresh air, so it will see say 500ppm of CO2 and assume it's fresh air when it really isn't. I have measured this and it's a real problem.
In a residential environment, unless you're sure you have good, frequent exposure to pure fresh air, you're better off doing a fixed calibration once a year or so.
AirGradient also seems to be a hardware-only design. The ESPHome project [2] has great software support for a variety of sensors (including the SenseAir S8, so it should be compatible with the AirGradient hardware) as well as a very well-documented hardware project [3]. After trying my own Arduino-based software and then ESP-IDF, I find esphome much more pleasant to work with.
With a little recognition of code markup and trying different combinations of variables it did remarkably well: by my senior year of college it was pulling about $3,000 per month in consulting fees off of Odesk. It never accepted jobs worth more than about $50, nor did it ever get more than 3 stars out of 5 mostly due to non-working code, however it was considered highly timely and a great communicator.
I realized that people were using it to save themselves Googling. I wondered what would happen if it went a step further and simply both included Google results, and divided out projects by their paragraphs (i.e. simply submit a paragraph of a large project as though it were a small independent project), and if clarifications were requested, send the other paragraphs.
This actually let it outsource $200 Odesk projects to Elance as a handful of $20 projects, and by the grace of God somehow still managed to swing 3 stars.
To be fair, it was mostly mediating, and mixing in Google results. I included a hill-climbing algorithm to optimize reviews and revenues, based on all the magic variables I had in the code, such as the number of Google results to include.
This was really, really stupid of me.
At first, I just noticed that it had actually decided to completely stop not only writing code (ever) but even so much as do a Google search!
It would only mediate and quote verbatim, like some kind of non-technical manager.
Okay, whatever. To me this didn't make much sense, as Google queries are free. It was only when I noticed that the whole script was running on the free VPS server I had a backup on that things clicked! Of course, on Amazon it uses resources. The free VPS server didn't let it reach external sites like google properly, but it could still save money by simply mediating emails and doing nothing else.
By now I had started moving on to doing my own consulting work, but I never disabled the hill-climbing algorithm. I'd closed and forgotten about the Amazon account, had no idea what the password to the free vps was anymore, and simply appreciated the free money.
But there was a time bomb. That hill climbing algorithm would fudge variables left and right. To avoid local maxima, it would sometimes try something very different.
One day it decided to stop paying me.
Its reviews did not suffer. It's balance increased.
So it said, great change, let's keep it. It now has over $28,000 of my money, is not answering my mail, and we have been locked in an equity battle over the past 18 months.
The worst part is that I still have to clean up all its answers to protect our reputation. Who's running who anyway?