GitHub has made the redesigned GitHub Copilot CLI terminal interface generally available. It adds a tabbed layout for sessions, gists, issues, and pull requests; an in-session, form-driven setup for MCP servers, skills, and plugins that avoids hand-editing config files; and a cleaner, theme-aware, more accessible UI with screen reader support.
A number on the dashboard gets questioned in a meeting. Nobody can prove who is right, and within ten minutes a room full of expensive people is arguing about a spreadsheet instead of making a decision. I have sat in that room. So have you. The coffee goes cold, the meeting runs long, and everyone leaves agreeing on exactly one thing: the dashboard is wrong. What nobody says is which problem they are looking at, because most teams never learned the difference between data quality, data reliability, and data observability.
“The dashboard is wrong” is not a diagnosis. It is a feeling. And you cannot assign a feeling to an engineer and expect a fix by Friday.
Almost every “the number looks off” complaint is one of three very different problems wearing the same coat. Tell them apart and the panic drops, because the work becomes obvious.
One complaint, three different problems. Each has a different owner and a different fix.
One complaint, three different problems
From the outside all three look identical: a number nobody trusts. What separates them is what broke underneath, and that decides who fixes it.
Problem one: data quality
Data quality is about the values themselves. Are they fit for use?
A duplicate order slips into the table and revenue jumps. A region code is blank, so a real sale belongs to no territory and vanishes from the regional report. A date sits in the future because someone typed 2027.
The tell is that you can point at one row and one field and say: this value is wrong.
-- The duplicate that made finance briefly very happy
SELECT order_id, COUNT(*)
FROM sales_orders
GROUP BY order_id
HAVING COUNT(*) > 1;
If that query returns rows, the fix lives close to the data. Reject it, flag it, or backfill it. Straightforward, as these things go.
Problem two: data reliability
Reliability is the sneaky one. It has nothing to do with whether the values are correct. It is about whether the data showed up.
A daily feed loads at 6 am so the numbers are ready for the 9 am review. One morning the load fails. Nobody notices, because yesterday’s data is still sitting there, calm and complete. Every value is correct. Every value is also a day old.
The dashboard is telling a story from yesterday while the room treats it as today. Nothing looks broken. The rows are valid, the totals add up, and the only thing wrong is the clock. Reliability points you at the pipeline and the schedule, never at the value.
Problem three: data observability
Observability is the one that produces the sentence “I have no idea why this happened.”
Something shifts upstream. A column that held five product categories now holds eight. A source system starts sending amounts in cents instead of dollars. No rule caught it, because nobody writes a rule for a change they did not see coming.
Observability is the difference between “revenue doubled overnight and we lost two days working out why” and “revenue doubled overnight and lineage pointed at the currency change in ten minutes.”
The three questions that keep them straight
When someone brings you a wrong number, ask these in order.
Ask this
If yes, it is a
And you fix it by
Is a value wrong or missing?
Quality problem
Fixing, flagging, or backfilling the row
Are the values fine but late?
Reliability problem
Checking the pipeline and schedule
Did something change and no rule saw it?
Observability problem
Tracing lineage back to the source
The same complaint sends you to three different places. Fix the row, check the pipeline, or trace the lineage. Hand a reliability problem to the person who owns data cleaning and they will stare at perfectly valid rows for an hour and find nothing, because the rows were never the problem.
Why the label is the whole game
Naming the problem is not tidiness. The name decides who owns the work and what happens next.
“The dashboard is wrong” bounces from inbox to inbox because nobody can tell whose it is. Rewrite it as “revenue is overstated because duplicate order ids are in the sales extract” and suddenly there is a field, a cause, and an owner. Same problem. Completely different Tuesday.
You did not need a new tool for that. You needed a clearer sentence.
Try this on Monday
Next time someone says the numbers look off, do not open the query editor. Ask the three questions first. Within a minute you will know whether you are chasing a value, a schedule, or a change, and that minute saves the afternoon.
Get the name right and the fix is already half done. The other half is typing.
We bundled an internal Azure Pipelines task extension into a single bundled JavaScript file using esbuild. The task package dropped from tens of megabytes and thousands of files to three files per task ( script.js , task.json , and icon.png ). The change took about 20 lines of build tooling. We measured the payoff across our production pipelines:
Per-task download + extract on the agent: ~4.5 s to ~0.25 s (about 17x faster)
Downloads taking longer than 10 seconds: down ~98%
Spending less time downloading and extracting tasks means we can make more efficient use of our build infrastructure. If you publish a node-based Azure DevOps task extension that ships a large node_modules folder or thousands of small files, you can almost certainly benefit from this same change!
Why task package size matters more than you think
Every time a pipeline job runs your task, the agent does the following during ‘Initialize job’, before your task code ever executes:
Downloads the task’s content zip
Extracts it to disk.
This happens on every job, on every agent, for every task in the job. On ephemeral hosted agents (which start from a clean VM), there is no cache to save you from this startup cost.
Our task had grown the way node-based tasks tend to: the compiled TypeScript plus a full node_modules tree that our build copied into each task folder. The result, quoting our own build script:
// package huge (tens of MB and thousands of files per task).
Thousands of small files is the problem here. Task extensions are packaged in a vsix file which is really just a zip file that follows a specific packaging convention. Zipping and unzipping a package with thousands of files is costly. In this case it’s also completely unnecessary.
Bundling and pruning aren’t just for the browser
Bundlers and tree-shaking carry a reputation as front-end tools. We reach for them to ship less JavaScript to a browser over a slow network, and it’s easy to assume that a server-side or CLI-style program, where “it all runs on one machine anyway,” has nothing to gain.
A pipeline task is a distributable artifact that each build agent downloads and unpacks from scratch on every run, often thousands of times a day across many agents. That is the problem bundling helps to solve. Front-end developers are familiar with optimizing assets to minimize the cost of transferring and processing files. The same cost applies here; the difference is the build agents pay the cost instead of browsers.
The same logic applies to anything you distribute and load repeatedly: pipeline tasks, npm-published CLIs, serverless function packages, even container image layers. If your artifact drags an entire node_modules tree along for the ride, tree-shaking away the code you never call and collapsing what’s left into one file pays off wherever it lands. Treat your task like something you ship, not like a folder you develop in.
The fix: bundle everything into one file
We added a single esbuild build step that bundles each task’s entry point, together with the shared Common code and all of its npm dependencies, into one bundled, tree-shaken script.js per task. The task’s VSIX then only needs to ship, per task:
Tasks/{taskname}/
script.js (the entire bundled task)
task.json (the task manifest)
icon.png
You no longer ship hundreds of transitive dependency files in multiple node_modules folders. You simply point task.json‘s execution target field at script.js, and that’s it.
import * as esbuild from "esbuild";
await esbuild.build({
entryPoints: ["Tasks/MyTask/index.ts"], // one per task
outfile: "Tasks/MyTask/script.js",
bundle: true,
treeShaking: true,
platform: "node",
target: "node20", // Target the lowest Node handler your task.json declares, or emit one bundle per handler
format: "cjs"
});
Two gotchas
We hit two subtle issues that other publishers might hit too:
Deduplicate stateful shared modules. If you install the same package (for example azure-pipelines-task-lib) in both a shared Common/node_modules and each task’s own node_modules, esbuild can bundle two separate copies. For libraries that hold module-level state, that state splits across the copies and silently disappears (for example with azure-pipelines-task-lib, the internal \_vault that holds secrets). We wrote a small esbuild resolver plugin that forces bare-specifier imports to resolve to a single, canonical node_modules.
Fix sibling-asset paths if your extension contains multiple tasks and they share common code. For example:
Common
moduleA.js
moduleB.js
Task1
script.js
task.json
distribution.json (custom file needed by the task)
Task2
script.js
task.json
Task3
Bundling collapses the Tasks/{taskname}/Common/ subfolder, so the emitted script.js now lives one level up from where the source did. Update any runtime reads of sibling files ( task.json , distribution.json ) that use __dirname to drop the now-incorrect ../ prefix.
These changes took a couple iterations to fix, but knowing about them up front might save you a confusing debugging session.
How we measured the impact
Task file transfer time measures how long the Azure DevOps service spends streaming each task’s zip to the agent. Across all downloads, the average dropped from ~1.35 s to ~0.23 s, and downloads taking more than 10 seconds (slow network) fell by ~98%. Here we already saw a big improvement.
Agent-side download and package extraction time. This is the number that matters to customers because it means more efficient use of build agent compute.
Metric (per task, download + extract)
Before
After (bundled)
Change
Task1
~4.5s
~0.25s
−94%
Task2
~4.6s
~0.26s
−94%
Both tasks combined, per job
~9.2s
~0.5s
~17x faster
Because this task runs across a huge number of pipelines every day, the small per-job saving compounds dramatically. Overall, we’re making much more efficient use of our build agent infrastructure which means we can run more builds on the same overall CPU quota.
As a pipeline author, this change delivers real savings to your customers while requiring zero changes on the customer’s side.
Some Caveats
There are some potential drawbacks here that are worth mentioning.
Bundled files might make debugging more challenging since your stack traces won’t point you to the original source locations. (You can output sourcemaps to help with this.)
esbuild and other static bundlers can break dynamic requires. Make sure you thoroughly test your tasks after bundling. (You may need to use the external option for some dependencies
Bundling is a tradeoff that can result in higher memory usage. With a single large, bundled JS file, the V8 engine now needs to load the entire file into memory at startup instead of loading smaller files as they are needed. If this is a concern, you could experiment with https://esbuild.github.io/api/#splitting.
Should you do this? (A checklist for task publishers)
If you publish a Node-based Azure Pipelines task, you can very likely get the same benefit:
Check your package. Does your published task ship a node_modules folder with hundreds or thousands of files? (Look at the .vsix contents by renaming it to .zip and extracting the contents)
Add a bundler (esbuild, ncc, or webpack) that emits a single script.js per task with bundle and treeShaking enabled, targeting the Node version your task declares. (You could enabling minify too but that makes debugging more challenging as your stack traces will be unreadable unless you also output sourcemaps)
Point task.json at the bundled entry file.
Watch for duplicated stateful modules (especially azure-pipelines-task-lib) and deduplicate to a single instance.
Fix any __dirname -relative asset reads if bundling changes your output’s folder depth.
Verify the task still runs, then compare your Initialize job log timestamps before and after.
It’s a small, self-contained change, and as we found, the payoff scales with how often your task runs.
Ask your coding agent to draft a PR and test the results.
The mission of Thinking Machines is to build AI that extends human will and judgment.
Artificial intelligence can do more every day, but deciding what it should do is up to us: individuals, organizations, humanity as a whole. These decisions require knowledge and judgment that people acquire through continuous contact with the work, increasingly done alongside AI. Shaping the goals of advanced intelligence is also a continuous process of feedback, learning, and realignment.
Most AI in use today is trained in a handful of places and then frozen. It isn’t shaped by the people it serves, and doesn’t learn much from the work they do together. Extending human will and judgment calls for AIs as diverse and distributed as people themselves are. This is the path we have chosen.
To progress on that path, we are pursuing these technical directions:
We train strong models, advancing capabilities such as multimodal interaction and customizability. Sharp instruments extend human will, and human judgment needs to shape models that compete on the frontier.
We build tools that enable people to make AI their own, customizing models to serve their unique needs. This includes the ability to train model weights.
We develop interfaces that broaden the communication channel between human and machine, allowing personal judgment to continuously influence the work of AI.
We publish research for the scientific community, because the power to shape AI requires deep understanding of how it’s made.
We believe the future worth building is human — shaped by human knowledge, guided by human will, and decided by human judgment. What follows is the case for that future, and the work we’re doing to bring it about.
Bringing intelligence to knowledge
AI exists to serve the work that we do. This work runs on knowledge of how things are done and what is worth doing, knowledge that is generated continuously by people engaged in the work.
Think of a chef crafting a new recipe or a shopkeeper rearranging the items and prices on display. They are pursuing a complex set of goals and applying know-how that isn’t immediately legible to outsiders. This knowledge is constantly updated through feedback; it’s not a static repository that can be written into a database. It’s local — a different restaurant or shop pursues different outcomes by different means. The collective knowledge of shops and kitchens is scattered across every shopkeeper and chef.Michael Polanyi, The Tacit Dimension (1966)
The dispersion of knowledge is a collective strength; it’s the source of variety, adaptability, and resilience of the overall system. It’s the reason that free markets outperform planned economies. Central planning fails not because of insufficient intelligence, but because of the nature of productive knowledge: tacit, local, fleeting, and held privately by those who acquired it through their work.Friedrich Hayek, The Use of Knowledge in Society (1945) Attempting to aggregate knowledge for the use of a centralized intelligence faces the same challenge.
There are domains where intelligence alone is sufficient, and where autonomous AI doesn’t require human participation to race ahead. Two examples are chess, where the strongest engines are trained purely on self-play, and math, where frontier models are solving long-standing problems on their own. These examples share two traits. First, the goal given to AI is static and expressible: to win a chess match, to prove a theorem. Second, these domains don’t contain hidden knowledge. The rules of chess and math are universal; the board is visible to all. Outside the board, intelligence alone is not enough.
For artificial intelligence to benefit from distributed knowledge, it must itself be distributed. Every organization is powered by the expert knowledge of its people, gained and expressed through their work. We believe in AI that helps the organization cultivate that unique knowledge, not AI that extracts a snapshot of it and replaces it with a standard offering. This cultivation is an ongoing process that requires AI to work with people, not in their stead.
In 2014, Toyota, long a master of the automated plant, brought its expert craftsmen back onto the line with the explicit goal of growing craftsmanship and knowledge. The man who led this, Mitsuru Kawai, put the reason this way: “To be the master of the machine, you have to have the knowledge and the skills to teach the machine.”Craig Trudell, Yuki Hagiwara and Ma Jie, Humans Replacing Robots Herald Toyota’s Vision of Future (2014) The production of knowledge and application of intelligence lift each other; they are not substitutes.
The work people do may change, and turn toward more of what only people bring, but the best organizations will make the fullest use of both. AI should enable each organization to be excellent in its own way, not to erase the differences between them.
We aim to bring intelligence to where knowledge is made and used. We build tools that enable everyone to fine-tune models with their unique knowledge, and to keep adapting the models as their knowledge evolves. We publish research and recipes that put this capability within reach of more people. We envision frontier AI as a collective, as diverse as the people it serves because it was shaped by them in each unique location.
Human participation is a technical challenge
Keeping people engaged in setting goals and sharing knowledge with AI doesn’t mean resisting automation for its own sake. What a machine does reliably on its own, it should do. But it should also know when to act alone and when to invite oversight and feedback, as people themselves do when working in teams. The best collaborators anticipate: they learn what someone is reaching for and bring it before being asked, earning over time the right to act on their behalf. These are technical challenges, requiring a new approach to how AI is designed and evaluated.
A major bottleneck for bringing human knowledge and judgment to work with LLMs is the communication channel between human and AI — a small text box and a long wait. This is too narrow to carry the richness of human wisdom and intent, and too slow for ongoing feedback. People collaborate best when they collaborate live. We interrupt and correct, take second looks and make gestures, change our minds aloud. This is why we’re making a long-term bet on interaction models: models that handle live, multimodal interaction natively, in the model itself rather than in scaffolding bolted around it. Built this way, interactivity scales with intelligence; the same training that makes the model smarter makes it a better collaborator. The right interface doesn’t just allow human participation, it invites and rewards it.
Another challenge is setting the right target for evaluation and optimization. The common measure of AI intelligence today is the time horizon of software tasks models can execute autonomously, tracked on charts like METR’s.Thomas Kwa and Ben West et al., Task-Completion Time Horizons of Frontier AI Models (2025) We expect progress on this benchmark to continue, but it ultimately measures only what AI is capable of on its own, not what people and machines can accomplish together.
Measuring the latter is more complex, and can’t be done by a lab on its own. Every organization evaluates for itself whether AI helps it sharpen its judgment, develop new knowledge, and achieve its objectives.
Building AI that makes its users stronger in the long run also aligns incentives well. An AI lab offering a single model for every customer benefits by absorbing what makes each user distinct and devaluing the cultivation of specialized knowledge. By optimizing AI to be customized and collaborated with, we benefit when our customers leverage their unique advantages. These advantages are maximized not by renting an AI and outsourcing to it, but by organizations owning it and tailoring it to their goals.
Decentralized alignment
Human values, just like human knowledge, reside in the heads of individual people and resist consolidation. But today, the values and voice of AI are decided in a handful of places. A single locus of value alignment, however well run, becomes a locus of power to be captured.
This creates danger, especially if most valuable work is done by AI on its own with little need for human input. The social contract between corporations, governments, and citizens relies on individuals’ productive capabilities on which the government’s sovereignty and corporations’ profits ultimately depend. Power that needs nothing from people loses the incentive to care for their needs and values, caring instead for its own preservation.Luke Drago and Rudolf Laine, The Intelligence Curse (2025)
Even with the best intentions, a model shaped in one place inevitably encodes the values of its owner, not the individual users it serves.“A more moral AI is not enough if that morality is determined by a few.” Leo XIV, Magnifica Humanitas (2026) Today each lab trains its next flagship model by using its previous flagship model to generate training data and a reward signal. Whatever character emerges from that loop, everyone gets the same one, and each generation inherits the traits of the last, raised on its parent’s outputs and judged by its parent’s tastes. A single alignment spec suppresses creativity and diversity and stultifies progress. Free speech and free markets let new ideas, goods, and services emerge and compete, rather than averaging out the preferences that exist at a point in time.
For organizations and individuals to align AI to their own values, these values must be encoded in the model weights. If the user’s values and desires only impact the model through a prompt, the user finds that surface properties change while the deeper habits remain. Allowing core model behavior to change significantly with prompts sacrifices safety, making a malleable centralized model vulnerable to repeated attacks.Gwern Branwen, Guardian Angels: LLM Personalization for Productivity and Security (2026)
The power to shape a model profoundly is also the power to shape it for ill. John von Neumann remarked on this problem in 1955,John von Neumann, Can We Survive Technology? (1955) writing that the useful and the harmful aspects of technology “lie everywhere so close together that it is never possible to separate the lions from the lambs.” Keeping the lambs safe is an ongoing process, the result of judgment exercised and choices made continuously. We aim to give the people making these choices stronger tools, pursuing research that enables safer models without taking away ownership.
Humanity has flourished through individual weirdness and creative tension. We envision alignment as a feature not of a single model but of an ecosystem of AIs raised in different places, disagreeing, competing, and learning from each other. We believe in keeping the weirdness alive.
The future worth building
The technology industry has made incredible progress in teaching machines to think; what they should think about must remain with us. What is worth wanting, what is worth making, what’s the right use of the time we have.“The only way out of the dilemma of meaninglessness in all strictly utilitarian philosophy is to turn away from the objective world of use things and fall back upon the subjectivity of use itself. Only in a strictly anthropocentric world, where the user, that is, man himself, becomes the ultimate end which puts a stop to the unending chain of ends and means, can utility as such acquire the dignity of meaningfulness…The anthropocentric utilitarianism of homo faber has found its greatest expression in the Kantian formula that no man must ever become a means to an end, that every human being is an end in himself.” Hannah Arendt, The Human Condition (1958) We are not looking to hand down a single answer to this, but to give every person the ability to make their own answer part of the development of frontier AI.
The current path of AI development, pushing towards centralization and autonomy, frames human involvement as a trade-off: participation vs. capability, ownership vs. safe alignment. We see these as technical challenges to solve: AI that is more capable because it encourages human participation, organizations that benefit in the long run from tailoring AI to their advantages, alignment that arises from diverse AIs shaped by the people who own them. Solving these challenges is what our mission requires.
The future is not a choice between human dominance and rapid obsolescence in the face of AI. Different roads lead to many different futures, and we get to choose which one to take. We are building technology that lets the born and the made walk the road together.