Four days ago our team published a post about a release week that was almost entirely fixes. Money that calculated wrong in currencies we do not use daily. Data visible to people who should not have seen it. Clocks that disagreed with each other. Not a features week, and we said so.

This is the sequel, and it is a happier one.

Between 31 July and 2 August we shipped 23 more releases. This time most of the headline work was new functionality, and the fixes that did go out went out within hours of being understood. Member Blog reached 4.0.0 with 83 changes across the free and Pro pair. Eventonomy 1.4.0 carried 80 changes in free alone. Spaces can now be gated on a membership plan. Chat got an archive.

The point of this post is not the list. It is why the two weeks look so different, and what actually made the cycle speed up, because it was not effort and it was not headcount.

Fixing the foundation is what buys you speed

The uncomfortable truth about the fixing week is that it was not a detour. It was the thing that made this week possible.

When our team went through every currency-touching calculation, every logged-out read path and every timestamp comparison, we were not only closing tickets. We were removing the class of surprise that makes teams slow. A codebase where you are not sure whether the money is right is a codebase where every new feature ships with a knot in your stomach, and that hesitation is expensive in a way that never appears on any board.

Once the foundations are known-good, the cost of adding to them drops. Not because anyone is working faster, but because nobody is bracing.

That is the honest version of “our development cycle got fast.” It got fast four days after a week we spent not shipping features at all.

What actually shipped

The features that landed share a quality worth pointing at: none of them are inventions. Every one traces to somebody saying they needed it.

Member Blog 4.0.0 is the biggest of them, at 43 changes in free and 40 in Pro. Writers now get a real profile at a real URL, with follow support, so a member who writes well can be followed as an author rather than found by luck. On the Pro side, every shortcode now has a matching block, plus series, co-authors and invitations. That is a major version because the shape of the product changed, not because the number was due.

Eventonomy 1.4.0 is the widest, carrying 80 changes in free and 27 in Pro. Members can sign into the mobile app with the WordPress credentials they already have rather than creating a second account. Buyers now get an email when something is refunded or cancelled, which sounds too obvious to be a feature until you count how many ticketing platforms reverse a charge and tell nobody. Organisers can pick which registration questions appear per event instead of setting them globally. The events list got bulk actions. Venues and organisers got their own admin screens instead of being buried in a taxonomy.

Jetonomy 1.9.0 lets a space be gated behind a membership plan, and the Pro version gates a space on a membership tier belonging to a different product in the portfolio. That second one is the interesting half, and there is more on it below.

WPMediaVerse 2.3.0 added an archive tab for finished conversations, because chat threads accumulate and people wanted somewhere for the done ones to go.

Read that list again and notice how ordinary it is. Bulk actions. An email on refund. A place to put old conversations. Sign in with the account you already have. This is what a roadmap looks like when it comes from the support queue rather than a whiteboard, and we think it is the correct kind of boring.

Resolution speed is a separate skill from shipping speed

The Thursday of this stretch is the better story, because it shows the other half of a fast cycle.

One customer reported a white screen on one of our Reign addons. The obvious response is to fix that addon and close the ticket. What actually happened is that somebody asked the follow-up question: these addons share a settings foundation, so how many of the others have this?

The answer was most of them. Eight addons went out the same day, carrying the shared fix plus a settings data-loss bug found during the same investigation, plus bundled translations and raised platform baselines while the code was open anyway.

One report, one afternoon, eight products.

The same day carried three security and privacy releases. One where anonymous forum posts could reveal their real author to a logged-out visitor. One where a story could be read by somebody who should not have seen it. One where a visitor filter was applied in one place but read in several. All three were understood, fixed at the shared layer rather than the reporting screen, and shipped within the day.

Shipping features quickly is a matter of capacity. Resolving problems quickly is a matter of whether your architecture lets one fix reach everywhere it applies. Those are different capabilities and only one of them can be solved by hiring.

The honest answer: AI is doing the loop

Ownership and gates explain why a fix can reach eight products. They do not explain why this year is faster than last year, because we owned the stack last year too.

The thing that changed is that AI now runs most of the loop between “somebody reported something” and “the fix is verified.” Not the deciding, the loop.

Debugging. The slowest part of a bug was never the fix, it was reproducing it and finding out how far it spread. That work is pattern matching across a large codebase, which is exactly what these tools are good at. Reproduce the report, trace the path, then answer the question that actually matters: what else in the portfolio has this same shape. The eight-addon sweep started as one white screen and became eight fixes because searching 108 products for a pattern is now minutes rather than a day nobody would have spent.

Testing and QA cycles. Every customer-visible screen gets walked in a real browser, at desktop and at 390 pixels, in light and dark, across roles. Doing that by hand for one plugin is an afternoon. Doing it for eight in one day was not possible before and is routine now. The important part is that it happens per change rather than being saved up for a release candidate, which is when it would have been skipped under time pressure.

Finding bugs nobody reported. This is the part we did not expect. Contract audits across the portfolio look for meta keys read but never written, hooks consumed but never fired, JavaScript actions with no PHP handler, settings saved but never applied. Those are the defects that generate the worst support tickets, because the customer configured something correctly and it silently did nothing. Most of them are now caught by a sweep before anyone hits them.

Documentation. Every product carries a capability document derived from its own manifest, and it is a release gate rather than a nice-to-have. If the docs are older than the code, the release does not go out. Docs used to rot because writing them competed with shipping. Now they are generated from what the code actually registers, so the failure mode is a blocked release instead of a wrong answer to a customer.

Here is the part worth being careful about. None of that decides anything. AI does not choose what to build, does not judge whether a reported problem is really a bug or a misunderstanding, and is wrong often enough that every finding gets verified before it becomes a fix. A generated finding is a lead, exactly like a customer report is a lead. Roughly a third of what comes back does not survive being checked.

What it removes is the tax. The reproducing, the searching, the walking of every screen at every viewport, the keeping of documents in sync. That tax is what used to make a portfolio this size slow, and it is most of the difference between nine releases in a week and thirty-two in five days.

How a report becomes eight releases

It is worth walking the actual sequence, because “we fixed it fast” hides all the parts that matter.

A customer reports a white screen on one addon in a specific configuration. First move is not to open the file, it is to reproduce it. Install the third-party plugin they named, set the same options, use data shaped like theirs. A report is a lead, not a specification, and the stated cause is frequently not the real one. Roughly a third of the time the reported reason turns out to be wrong even when the symptom is real.

Once reproduced, the question changes from “why does this addon break” to “what is it about the shared foundation that lets this happen.” That reframing is the whole trick. The first question produces one patch. The second produces a list.

Then a search across the portfolio for the same pattern. Not a memory exercise, an actual grep, because memory is optimistic and grep is not. That is where seven more turned up.

Fix at the foundation, then verify against the original reproduction, same configuration, same steps. Code quality checks passing is not verification. The bug was found in a browser and it gets confirmed dead in a browser.

Then the release gate on each of the eight: contract audit, clean-install package test, smoke pass. Eight packages, eight installs, eight verifications. That is the part that takes the afternoon, and it is the part you cannot skip if you want the words “shipped same day” to mean anything good.

Notice what is absent from that sequence. No coordination meeting. No waiting on a vendor. No version matrix to negotiate. The speed comes from the absence of those, not from anybody typing quickly.

Why one report reaches eight products

The mechanism is not clever, it is just consistent.

Everything is built in-house against one set of standards. The theme, the community layer, the LMS, the events plugin, the media stack and the commerce pieces come from one team. A fix to a shared admin component reaches every product using it without a negotiation, a support ticket to another vendor, or a wait.

Every product also carries a machine-readable manifest of what it registers: hooks, REST routes, database tables, settings keys, capabilities. Before anyone adds a function, they check whether the portfolio already has one. That single habit is most of the difference between a portfolio and a pile, and it is also what makes the question “which other products share this foundation” answerable in seconds rather than by memory.

If your stack is assembled from seven vendors, a bug reported on one product is a ticket that gets closed on one product. The other six keep it until somebody else finds it. We made the longer argument for owning the whole stack in twelve products, one vendor; this week is the operational proof of it.

Cross-product features are the payoff

Jetonomy Pro gating a space on a membership tier that belongs to a different product in the portfolio is worth pausing on, because that feature is only cheap if you own both sides.

Building it across two vendors means an integration: an API contract somebody else controls, a version matrix, and a support conversation every time either side ships. Building it across two products you own means reading a value.

This is the part of single-vendor that is hard to explain in a sales page and obvious the moment you need it. The features that connect two products are the ones customers ask for most and the ones a stitched-together stack delivers worst.

The same logic runs through the mobile work. Signing into the app with existing WordPress credentials is not a feature so much as a decision not to build a second identity system. One auth surface across the portfolio, one place for verification rules to live, one set of bugs instead of two.

Speed without gates is just faster breakage

We would be describing something reckless if the pace were not gated, and we have shipped recklessly before and do not recommend it.

Every release runs a contract audit before it goes out. A hook one plugin fires and another consumes has to exist on both sides. A settings key one product writes and another reads has to still match. Free and Pro pairs ship in lockstep or neither ships. The built package gets installed on a clean site and smoke-tested, because a package can break in ways a working development tree never will.

None of that produces a changelog line. Nobody writes “the contract between these two plugins is still intact.” But it is the reason a 23-release stretch does not end with a customer who runs three of our products getting a white screen. The same instinct drives our big-site readiness checklist, which is the version of this applied to list views and data methods.

The gate is what converts speed from a risk into a capability. Without it, a fast cycle just means finding out sooner that you were wrong.

What a fast cycle gets wrong

Speed has failure modes, and ours in this stretch were all in the shipping process rather than the code.

Two products were tagged and finished for two days before anyone noticed the releases were still sitting as drafts. A draft release is invisible to the update API, so every downstream system, including our own site, believed the previous version was still current. The code was done. Customers could not get it. That is a pure process failure and it cost two days of value for zero engineering reason.

Then the changelog links. Several release notes in one batch pointed at a URL pattern that redirects to a generic hub instead of the specific product page. Annoying once. This was the fourth release running that the same wrong format came back.

Four times is not carelessness, it is a signal. When the same mistake returns every cycle, the person is not the problem, the template is. We had been correcting the output every time and never the thing producing it, which is exactly the mistake this whole post argues against making in code. It is fixed in the release template now, three waves later than it should have been.

There is a wider version of the same lesson. An audit comparing every product’s published changelog against its actually shipped release found 29 of 108 lagging, some by several versions. The cause was two hand-maintained copies of one fact: the machine-readable version on the download page and the version a human reads were separate values, and on fourteen pages they disagreed. Both now derive from one index.

The pattern is worth stating plainly, because it is the same defect three times in three different materials. Settings written by eight addons. A privacy rule read on four surfaces. A version number maintained in two places. Duplication of one idea, every time.

Going fast does not create that problem. It just gets you to the consequences sooner.

For developers

This section is the technical half. If you are reading for the product side, the closing thoughts are below and you will not miss anything.

The settings data-loss bug behind the eight-addon sweep is a clean illustration of why the fix belonged at the seam.

The shared foundation stored addon options in one structure. Each addon read the whole structure, modified its own slice, and wrote the whole thing back. Two addons saving during the same request meant the second write clobbered the first, because both had read the original state before either wrote. Classic read-modify-write interleaving, in a place nobody thinks to look for it, because settings feel like a solved problem.

The local fix is to have each addon write only its own key. That works, and it is what a per-product patch would have done eight separate times. The structural fix, which is what shipped, is that addons no longer write the shared structure at all. They hand their slice to the foundation and the foundation performs one merged write. One writer, so no interleaving to get wrong, and the next addon we build inherits the correctness for free.

The privacy fixes followed the same reasoning. The logged-out visitor rule is no longer a conditional inside a template. It is applied at the data layer, so every consumer gets a list that has already had the rule applied, whether that is a server-rendered first paint, a REST response, or a load-more request. A template can no longer forget, because a template is no longer being asked to remember.

The general rule, which we keep relearning in new costumes: if a rule or a value is written down in more than one place, the duplication is the defect and the incident that surfaced it is a symptom. The tell is greppable. A private helper doing something another screen also needs. A hardcoded list. A capability check, a URL, or a colour that appears twice. Most of our worst recurring bugs were two minutes of searching away from never existing.

For the cross-product gating, the seam is a capability check rather than an HTTP call. The membership product exposes tier state through a filter; the community product asks the question and does not care who answers. Either product can be absent without the other breaking, which is the property that makes the feature safe to ship in a portfolio where customers install different subsets.

What we said no to

A post about shipping quickly should be equally clear about what did not ship, because a roadmap is mostly a list of refusals.

Several requests in this stretch were declined or deferred, and the reasons are consistent. Anything that needed a second identity system was refused, which is why app sign-in reuses WordPress credentials rather than introducing app accounts. Anything that would have put the same rule in two places was sent back to be built at the shared layer instead, even when the local version would have shipped days earlier.

And several features that people would genuinely like are still absent, because we would rather say they are absent than ship a control that pretends. If a feature is not built, the honest move is to expose no setting at all, or to return an explicit unsupported response, rather than to accept input that will never be acted on.

There is a temptation in a fast stretch to say yes more, because throughput feels like capability. The opposite is closer to true. The reason eight products could be fixed in an afternoon is that previous versions of us declined to let those eight products each grow their own settings writer.

Every yes to a local shortcut is a withdrawal from the account that pays for weeks like this one.

The numbers, with the caveat attached

Twenty-three releases across four days, on top of nine the week before. We want to be honest about what that number is and is not.

Those releases are not equal. Member Blog 4.0.0 carried 83 changes across the pair and reshaped what the product is. Several of the addon releases were a shared fix, seven bundled translations and a platform baseline bump. Counting them in the same total makes a better headline than it does an argument, and we would rather hand you the caveat than have you find it.

What the number does show is throughput of a specific kind: the ability to touch many products in one motion without any pair of them disagreeing afterwards. That is the capability worth measuring, and the honest metric for it is not releases shipped. It is how many products a single root-cause fix reached, and whether anything broke between them.

This time that was eight, and nothing did.

What we would tell you to copy

Spend the fixing week. The features shipped this week because the foundation stopped being a question mark. A team that never pays that cost does not go faster, it goes more nervously.

Treat one bug report as a question about the whole portfolio. One white screen on one addon became eight fixes on the same afternoon, because somebody asked which other products share that code rather than which product was reported.

Gate the speed. Contract audits between products, clean-install package tests, and lockstep pairs are what stop a fast cycle from becoming a fast incident. Add the gate before you add the pace.

Build the connecting features yourself, or accept they will be bad. The features customers want most are the ones that span two products. Those are cheap when you own both sides and permanently awkward when you do not.

The short version

Two weeks, two very different shapes. One spent almost entirely on correctness, with a changelog nobody would call exciting. The next one delivering a major version, an 80-change release, cross-product gating, and eight same-day fixes from a single report.

Those are not two unrelated weeks. The second one is what the first one bought.

Development speed and resolution speed look like the same virtue from outside, and they come from different places. Shipping quickly comes from owning the stack and not duplicating work. Resolving quickly comes from fixing causes at the seam so one change reaches every surface that needed it. Both of them rest on being willing, occasionally, to spend a whole week shipping nothing anyone can see.

We would rather have that week and then this one, than a steady stream of features on a foundation nobody trusts.