Counterfirm
The application. Database tables, the extractor, the graph, the agent generator, the simulation engine, the report builder, the REST API and the front end shell behind the [counterfirm] shortcode. This one is required.
Documentation
Two plugins, about fifteen minutes, and a diagnostics screen at the end that runs the simulation engine on a synthetic company on your own server so you know it works before a single real number goes in.
Everything stays on your server. The simulation makes no outbound calls at all.
They are separate because they do genuinely different jobs, and plenty of people will want one without the other.
The application. Database tables, the extractor, the graph, the agent generator, the simulation engine, the report builder, the REST API and the front end shell behind the [counterfirm] shortcode. This one is required.
The marketing site: every page you are reading, the layout, the drawn artwork, the enquiry forms, the signup flow and the plan pages. Skip it if you are bolting the app onto a site you already have.
There is no build step, no node, no external service and no phone home. The engine is PHP, the charts are drawn in the browser from data the engine produced, and the artwork on this site is computed rather than shipped as images.
The order matters in exactly one place: activate the app before the site, so the site plugin can find the app when it creates pages.
Activation creates the database tables, generates a cron token and schedules the background queue on a five minute interval. Nothing else happens until somebody creates a twin.
Second, so it can link to the app correctly.
On the Counterfirm Site settings screen there is a button that creates or repairs every page defined in the plugin. It is safe to run repeatedly: existing pages keep their ids and their permalinks, and only the title and the marker shortcode are refreshed. Run it again after every plugin update.
Create one page whose entire content is the shortcode [counterfirm], published wherever you want it. Then set the app slug setting in the site plugin to that page slug, so every button on the site that says open the app points at it.
If you use Paid Memberships Pro, both plugins carry a level map: a small piece of JSON mapping membership level ids to the plan names explore, operator, boardroom and enterprise. Set it in both. The app uses it to decide what a member may do, the site uses it to decide what to show them. A mismatch between the two is the most common configuration fault, and it shows up as somebody who has paid seeing a gate.
Long jobs run in slices. WP-Cron drives them on a site with steady traffic. On a quiet site, or one where WP-Cron is disabled, point an external cron service at the site url with the cfct-cron parameter set to the cron token from the app settings, every five minutes. The browser also advances work while a member is watching a job, so nothing is stuck behind cron alone.
The last screen under the Counterfirm menu. Run it before you invite anybody. It answers the only question that matters at this point, which is whether the thing actually works on this server.
Seven checks. The last two are the interesting ones, because they exercise the engine itself rather than the plumbing around it.
| Check | What it proves |
|---|---|
| Tables present | Every table the app needs exists. If activation half failed, this is where you find out rather than when a member loses an upload. |
| Uploads directory writable | The private folder outside the media library exists and can be written to. It prints the path so you can go and look at it. |
| ZipArchive for Word and Excel | Whether docx and xlsx can be read at all on this server. If it is missing, the check says so plainly and notes that CSV and text still work. |
| WP-Cron scheduled | The five minute background job is on the schedule, and when it next runs. If it is not, set up an external cron url instead. |
| Paid Memberships Pro | Whether it is installed. If it is not, the check says the manual plan assignment on the Members screen still works, which it does. |
| Engine runs on this server | A real twelve month, forty replication run of a 20 percent price rise against a synthetic company built in memory. It reports the time in milliseconds and what the price rise did to revenue. This is the check that turns a claim about speed into a number from your own hardware. |
| Same seed gives the same run | The same synthetic company is run twice with the same seed and the two final states are compared. If they differ, every result the software produces is an anecdote, and the check says exactly that. |
The engine checks build a synthetic company in memory and never touch member data.
Yes. The app only needs a page with the shortcode on it. It looks for the site plugin pages when it wants to link to pricing or start, and falls back to sensible urls when they are not there.
Only calls to a language model, and only if you configure one. The simulation, the extraction rules, the graph, the agents and the report builder are all local arithmetic and text processing.
With no key configured, the plugin makes no outbound requests at all.
Nothing, unless you turn on the delete on uninstall setting first. That is deliberate: a plugin that silently destroys a company's uploaded accounts because somebody clicked the wrong button would be indefensible.
A standard run is 400 simulations and takes about a tenth of a second for a twelve month horizon with around forty agents on the machine this was built on. Your own number appears on the diagnostics screen. Sweeps are the heavy case and run in slices for that reason.
No. Without it you assign plans by hand on the Members screen, which is fine for a handful of people and tedious for more.
Load the worked example first. It fills every screen with an invented company so you can learn the software before you decide how much of your own record to put in it.