AI Development and Agentic Automation Projects

I first began using LLMs with ChatGPT in late 2022 when it became publicly available, and later ChatGPT Teams, Google Gemini, and have experimented with DeepSeek and other models.

My early use of LLMs was largely organization of larger document structures. Hallucinations limited their use for data analytics and research until very recently.

Today I primarily use Anthropic’s Claude CoWork and Claude Code for its speed, accuracy, and their best-in-class agentic capabilities.

The Evolution of AI over 80 Years

Most people think of AI as a chat tool. This interactive timeline maps 28 technology classes from 1943 to 2026: across the 27 that reached commercial deployment, the median gap between research and production was 22 years, and older classes did not stop working when newer ones arrived.

Authgnosis AI Architecture

Authgnosis runs its own operations on an AI agent. Claude Code sits at the centre of the business, from analytics and finance through to the website and client deliverables.

Four layers carry the work:

  • Integrations: a unified layer of local services and secure remote connectors links the agent to the platforms the business runs on, from web analytics and accounting through to email, documents, design tools, and the website.
  • Automation: scheduled jobs handle recurring work on their own, including federal grant-opportunity monitoring, daily analytics reporting, and ongoing website health checks.
  • Outputs: status reports, search-optimization improvements, grant alerts, and the activity feed below.
  • State and governance: every change is versioned in private repositories with an automated audit trail and layered backups, so the environment stays reviewable and recoverable.

A governed perimeter defines what the agent is permitted to manage. That boundary is what makes the approach practical: the agent operates on live business systems, and every action it takes remains transparent, auditable, and reversible.

Why I Didn’t Build a Multi-Agentic AI Role-Based Architecture

Human-in-loop AI-assisted development provides a critical cost-control and business value creation capability that can reduce AI token costs by over 50% and surface significant opportunities to increase the quality and value of AI-assisted business activities.

Documentor

Documentor is a Mac OS application I am developing for organizing files generated for client or employer work. Over time, files get spread across local and cloud-based storage, working folders, shared team folders, and other operations. User-managed version control within a generation of related files is inconsistent or non-existent.

When wrapping up client projects or leaving a company, important files and related information is important for smooth work transitions. Documentor is designed to make that process fast, easy, and complete.

  • Fast filesystem scanning and unique fingerprinting and grouping of files
  • Form-based and Advanced Filesystem Query Language (FQL) for inclusion and exclusion of filename, file paths, file types, and other metadata to work on only the files that matter
  • Automated soft (in-app) or hard (on-disk) de-duplication and retention of exact copies of files even when the names, folder locations, and dates are different 
  • Identification of critical files from non-critical files
  • Creation of descriptions for critical files
  • Automated detection of generational families and versions of files
  • Soft/hard versioning and re-versioning of generational families of files
  • Report generation of critical files with local paths and auto-generated secure cloud-share links for client and employer consumption
  • Audit trail, verification and reporting of destruction of files to comply with client contracts, NDAs, and employment agreements
  • Integrations with Notion, Sharepoint, Confluence, and other knowledge platforms
  • End-to-end secure application metadata storage at-rest
  • Future support for auto-versioning of new files as they are created in the filesystem
  • Future support for Microsoft Windows

 

AI Event Log

The following content is generated automatically by Claude agentic AI upon each git push to the Authgnosis private GitHub repository. Descriptions are automatically generated by Claude.

Publishing the instrument before the policy it measures

MTA-STS tells sending mail servers to require a valid TLS connection and to refuse delivery rather than fall back if they cannot get one. Turning that on without evidence is a way to lose mail quietly, so the reporting channel went up first, on its own, and collected for eleven days before the policy existed.

  • TLS reporting was published alone and deliberately left alone. It is the instrument that says whether enforcement would break anything, so it has to be collecting before there is a policy to enforce. Publishing both at once discards the safety net that makes the rollout survivable.
  • The policy is live in testing mode. Conforming senders fetch it, evaluate it and report what they saw, but they never refuse a delivery on it. There is no path to losing mail until the mode changes, which is a separate decision at least two weeks out and is gated on what the reports say rather than on the date reached.
  • The baseline reads 99 successful sessions and zero failures across eleven contiguous days, counted from the raw reports rather than taken from a summary line. Three limits are recorded beside it, because the number invites a stronger claim than it supports: one organisation is the only reporter, the volume is about nine sessions a day, and every report predates the policy, so it describes opportunistic encryption and not the policy itself.
  • The verification script reported the new record as missing while it was live on three other resolvers. It had been asking whichever resolver the machine happened to use, which inside the window after publishing still answered that no such record existed. Three of twelve queries came back empty against it and none of twelve against a pinned resolver. The script now pins one and prints which it used, because a verifier that intermittently calls a correct record absent fails in the exact way it exists to detect.

The 202% rise that the measurement window invented

Five consecutive weekly reviews had built on a number the measurement window produced. Checking it against the source data changed what the strategy should do next.

  • A weekly review had reported site impressions rising 202% over five weeks while clicks stayed flat, and a new strategic rule was about to be adopted on the strength of it. The monitor pulls a 90-day rolling window, so two readings five weeks apart shared 62 of their 90 days.
  • Read week by week instead, impressions roughly tripled over six weeks and clicks held at about one per week. The conclusion survived. The figure quoted for it did not, and neither did the claim that it described five weeks.
  • Three other claims had ridden along unchecked across the same five reviews. One had been formally disproven and closed in the CRM seven weeks earlier. Another held that the answer-engine instruments could not report a non-zero, when both run weekly and were returning a real zero.
  • The homepage description was rewritten and deployed the same day, replacing wording that had been recorded as live since July but never actually deployed.

A monitor that could not tell a dead resolver from a deleted record

An alert reported that two mail authentication records had stopped resolving. Both were correct, and had been throughout. What the alert had no way to say was that the machine asking had lost its network at the moment it asked.

  • The lookup command exits with one code, meaning no reply from the server, for two conditions that call for opposite responses: the record is gone, which is urgent, and this machine could not reach a resolver, which is noise. Nothing in the alert separated them, so the line that would report a genuine failure had already been taught to read as a blip.
  • The check now tests the resolver before it tests any record, using a query every recursive resolver answers from its own cache, so a slow authoritative server cannot make a working resolver look dead. When the resolver does not answer, the alert says that once and names it instead of listing every record as missing. The timestamp recording when the records were last actually read is deliberately not advanced, so a run that measured nothing cannot later be read as a clean one.
  • Behind it sat a larger gap. The monitor runs at two fixed times a day, and if the machine is asleep at one the scheduler defers it, so the following summary is an ordinary pass and looks the same as a day when both ran. The external dead man’s switch did not cover this, because it fires on every run including a late catch up. Missed slots are now reported, read from the live schedule rather than from a copy kept in the code.
  • Both changes were tested against the failures they were written for rather than only compiled. The resolver probe was run against a working resolver and an unroutable one, where it returns the same code the ambiguous failure produces. The slot logic was replayed against the original incident, where it reports the run as thirty one minutes late, and against a run three minutes late, where it correctly stays silent.

A setting that stored correctly, read back correctly, and was never in force

The automation that raises sales process tasks had raised the same one twice, seconds apart. Each of its eighteen checks looks for an existing task and then creates one if it finds none, which is a question rather than a rule, and two runs happening at once both pass it.

  • The run history settled it. Two runs that overlapped produced both duplicate pairs, and a third run seconds later, which overlapped nothing, produced exactly one task. The gap that had looked like a coincidence was the gap that let the earlier runs finish.
  • The obvious remedy is to make the automation run one at a time. That setting was written into the live definition, read back correctly, and survived switching the automation off and on. Runs kept overlapping anyway. Every check except the one that looked at the outcome would have reported this as done.
  • A later test carried the more useful finding. Seven genuinely overlapping runs produced seven tasks and no duplicates at all, so overlapping is necessary but not sufficient, and the fault is intermittent rather than systematic. That argued against building an automation that deletes tasks.
  • What shipped instead is a report. It reads only, follows every page rather than the first, and separates a real collision from ordinary test leftovers by whether the copies appeared in the same second. Its first run found an open pair that nobody had noticed.

One meeting that served two process steps, recorded as two

The sales process expects an awareness call and then a discovery call. On a smaller account both can happen in a single sitting, and the process had no way to record that. The lead stopped at a step the work had already satisfied.

  • The satisfying logic already existed and nothing about the process changed. An appointment marked as the discovery booking ticks the booking step when it is created and the call step when it is closed, so one appointment covers both. The booking gate is never skipped. It is satisfied by a record standing for a meeting that genuinely happened.
  • A decline type was added to the task. Declining a step already means the work did not happen, and compression makes the same keystrokes also mean it happened elsewhere. Without a field to tell those apart, an automation reading the free text reason would create a record of a meeting that never took place.
  • The new automation writes no attendee of any kind, and refuses to act when there is no source meeting to compress into. It can record a real meeting and cannot invent one. That was verified on a record the automation itself created, not only on its design.
  • It deployed clean, switched on clean, and did nothing. A run whose condition is false still reports success, and a second fault killed every later run with a message that named no step. Both were found by reading the records rather than the run status.

Generating a product catalogue from one canonical file

A CRM product catalogue is usually typed in once and then quietly drifts from whatever document is supposed to govern it. This one is generated, and the drift it replaced had been sitting there unnoticed.

  • The catalogue is built by a script that parses the canonical pricing document and writes the products, the units and the price list from it. Nothing in the CRM restates a figure, so the two cannot be edited apart by hand.
  • The catalogue that already existed disagreed with that document in three ways: a rate the document explicitly supersedes, a recurring figure matching no published tier, and several products carrying no price at all. Nothing had noticed, because nothing was looking.
  • A verification script now compares the live catalogue against the document and runs in the daily close out. It shares only the parser with the build, so a build that wrote the wrong value still fails the check. It was made to fail on purpose before being trusted: a seeded change produced exactly the two expected failures and a non-zero exit, and the source file was restored and confirmed identical afterwards.
  • One rule was recorded too broadly, applying a minimum commitment to every tier rather than to the single engagement option that carries it. That mattered beyond the documentation, because product descriptions appear on quote lines, so the wrong version would have stated a commitment to a customer on engagements that do not have one.

Filing a generated document to the record automatically

A document the system generates had to be handed over for a person to upload by hand, because sending the file through the tooling cost too much. That turned out to be a fact about typefaces rather than about documents.

  • The skill builds a one page executive summary from what the customer said on the discovery call, quoting them rather than summarising, and files the PDF onto their record itself.
  • The earlier measurement put a single page at roughly 178,000 tokens, which is what ruled this out. Re-measuring showed the cost is driven by how many typefaces are embedded, not by length. One page using a single family came in at 232 kilobytes against 521 for one using eleven.
  • The size check now runs at the moment of upload rather than sitting in the documentation as a claim. Over the limit, the file is handed over and the number reported.
  • The generator can refuse. The field holding the customer’s own cost figure accepts anything, and on one record it held a number identical to that company’s revenue. Reading that field and printing it produces a confident wrong document, so an implausible value stops the run.

Two local dependencies, and only one was obvious

Before Authgnosis approaches a prospective client, it scores that company against a detailed ideal customer profile, so outreach only goes where the services and Marissa Wright’s experience are a reasonable fit. This build doubles as a proof of concept for the enterprise sales and customer lifecycle automation work, where the aim is that a salesperson stays in the browser the CRM already lives in.

  • The client-fit score combines what a company does, read from its website, with its size, read from the CRM. Reading the CRM needed a database connection that exists only on one desktop, so answering a fit question meant leaving the browser where the CRM lives, getting the answer elsewhere, and coming back.
  • A read only endpoint now serves that lookup over an authenticated connector, so the check runs in the browser session alongside the CRM. It offers one operation and no general query, so a surface that can score a company cannot do anything else with the CRM.
  • Fixing CRM access alone would not have been enough. The scoring also called a local script to gather website evidence, so it would have failed on its first action before reaching the CRM at all. It now falls back to fetching the pages itself and collecting the same named signals. Confirmed by scoring a company end to end from a browser session.
  • Running both evidence paths against the same company exposed a defect in the preferred one. The script reported navigation labels where the pricing tiers should have been, and missed the sales button beneath each tier. Those are the signals the fit rubric arbitrates on.

A one to one email from a lead left the engagement record blank

Every contact and account carries a last engagement date and type, stamped by three small automations whenever an email, a call or a meeting completes. A reframe email sent one to one from a lead had stamped nothing, and the reason was structural rather than a bug.

  • The automations only recognised an activity filed against a contact or an account. An activity filed against a lead, which is where early conversations live, fell through both branches and the record stayed silent.
  • Each of the three now looks up the lead’s parent contact and account and stamps both. All three were proven on throwaway test records before the change went live, and the one real gap was filled by hand.
  • The same session added a yes or no flag on every contact showing whether they are the primary contact for their account, kept true by two automations and set correctly across 255 existing contacts.
  • The twelve month nurturing email series was rebuilt on the one email structure now used everywhere, with months two to twelve created as shells ready for their text.

The rehearsal that guards every process change had been failing silently

Before any change to how the sales process behaves, a rehearsal runs the whole twenty step chain against a test record and reports what broke. It had been stopping at the second step for three days, and nothing said so, because a rehearsal nobody runs looks exactly like one that passes.

  • The rehearsal did not know about a question added to the process the day before, so it never cleared that answer between runs. The test record carried a stale answer from an earlier run, which made the first step pass for the wrong reason.
  • It also never attached the document that the process has required since the end of August before it will close a review step. That is what stopped the run at step two, so steps three to twenty had not actually run in three days.
  • Both were repaired. The full chain now passes twenty one of twenty one steps, the count of records created comes out exact, and the test record is left clean.
  • It was found only because a separate change needed proving. Nothing reports a rehearsal that is not being run.

An email step in the sales process can now be excused, not only sent

Every step in the sales process raises a piece of work, and declining a task with a reason has always marked its step excused so the process moves on. An email step had no such route. A rep who judged the email unnecessary had to send something anyway or tick the record by hand.

  • Two fields were added to the email record, an acceptance status that defaults to yes and a reason for decline, mirroring what tasks already carry.
  • A new automation watches for an email cancelled with the status set to no and a reason written, and ticks the step exactly as a sent email would. A cancel on its own, or a decline with no reason, excuses nothing, so duplicates and mistakes stay harmless.
  • It was proven on a throwaway test record with three cases before anything real touched it. The reasoned decline ticked the step and both negatives held.
  • The rehearsal that gates every process change gained a check it was missing, the path where a partner coordination call is correctly not raised. Running it also exposed two checks that had gone stale when a rule changed the day before, and both were corrected.

The AI skills study has its final reading

  • Collection closed at wave 4 with 1,408 qualifying postings against a target of 1,200. The one-shot 2 September run recomputed the figures from the stored corpus without touching a job board.
  • The headline is 35.7 percent of open director-level and above B2B technology sales and marketing roles asking the candidate for AI skills, with a 95 percent interval of 33.3 to 38.3. The Research Note on the site now carries that reading and a four-wave trend chart in place of the 6 August single-day figure.
  • Two caveats travel with it. 83 percent of the analyzed postings came from LinkedIn, and the funnel reconciliation is one row off. Both are stated in the methodology note rather than smoothed over.
  • One generator defect surfaced only by rendering the page: a closing sentence read “a measurement of collected between”. Fixed at the source, and a child theme rule stops the wave table wrapping its dates.

Why a corrected email signature kept sending the old one

A signature record was patched, verified clean, and kept arriving in inboxes with its original content. Four attempts across two working sessions had corrected the wrong thing.

  • The signature is stored in three columns. Insert Signature reads two of them, and every patch so far had written only the third, so the record read correct in every query and sent the old content.
  • Writing all three columns fixed it. The proof was a received message, not a read of the stored record: a stored copy looks self consistent either way, which is how the defect survived two earlier attempts.
  • The logos moved from inline base64 to hosted files. That removes about 55KB from every send and lets the two most clicked links carry campaign attribution.
  • A separate change to the signature card means an existing record now repositions its own card the next time someone opens and saves it, with no migration and no manual step.

A read-only CRM endpoint for scoring outside the desktop

  • Skills that read the CRM only ran on the machine holding the CRM connection, because that connection is a local process rather than an account level integration. A scoring skill therefore could not run in a browser session or on a schedule, whatever else was available to it.
  • The obvious control, allowing only named skills to call the endpoint, is not available. The protocol carries no skill identity: a server sees tool calls and not what invoked them. So the restriction had to come from the operations on offer. The endpoint exposes a single account lookup rather than a general query interface, because a read-only credential answering arbitrary queries is still answering arbitrary queries.
  • Read-only was verified by attempting a write and having it refused, rather than by reading the permission definition back. Those are different claims: one describes what the credential can do, the other describes what someone intended.
  • Revenue figures are returned with their currency attached, because the scoring bands are set in Canadian dollars and a figure in another currency places a company a full band too high. The currency travels with the number so it cannot be dropped in transit.

Choosing what runs the AI layer in the CRM sales process

  • Microsoft is withdrawing the AI Builder credits that come seeded with Power Platform and Dynamics licences on 1 November 2026, and new customers can no longer buy the capacity add-on. The AI layer planned for the sales process was costed against an entitlement that expires, so it needed re-pricing whatever it ended up being built on.
  • The comparison was made on the work the process actually runs, which is drafting and content checking rather than prediction. At current volume the cost gap between the options is small enough that it should not decide anything, so the decision had to rest somewhere else.
  • It rested on where the instructions live. A prompt held inside the platform never appears in a diff or a pull request, so nothing detects when it drifts. A prompt held as a file in the repository reviews like the rest of the code.
  • Predictive deal scoring stays out of scope. It needs a fitted model and enough closed history to fit one on, which is a data question rather than a model question.

Asking whether a partner is involved, instead of inferring it

A step in the sales process was deciding whether a partner was in a deal by looking at who would deliver the work. Those are different questions, and the answer to one is not the answer to the other.

  • The process now asks the question directly, early in the Awareness stage, and accepts three answers: yes, no, and not known yet. The third is not treated as an answer, so the task stays open rather than the process deciding by default.
  • Where the work is partner delivered, the answer is filled in automatically, because that case already settles it.
  • A later step that depends on the answer no longer goes quiet when nobody has given one. It raises a task saying what it is waiting for, and why nothing further will appear until then.
  • The step numbers were respaced first, from consecutive to gapped, so inserting a step no longer renumbers every step after it. The new step used the first gap the same day.

The AI skills study now reports its own state every week

The weekly AI skills study has produced a figure since early August. What it could not do was tell anyone how it was getting on. Its only outbound channel was an alarm that fired when something went wrong, and that channel had been broken since the day it was written, in a way that looked exactly like nothing being wrong. It now sends a short report after every run, whether the run went well or badly.

  • The alarm mail had never sent once. The call that sent it passed the wrong argument names to the shared mail function, which raised a type error on every attempt. The surrounding handler caught it, wrote a single line to a log, and carried on. Two runs finished in a degraded state and the inbox stayed quiet, because a broken alarm and a healthy job produce exactly the same evidence: nothing. The line was sitting in the log the whole time, which is the part worth noticing. Nothing reads a log that nothing is asking you to read.
  • The replacement sends on every run, which is what makes silence mean something. A channel that speaks only when there is a problem cannot report the problem of itself being broken. The report now goes out after a successful run as well as a failed one, so an empty inbox means the job did not run rather than the job ran and was fine. Every exit path leads to it, including a failure that escapes the wrappers meant to catch it, which was the one case the old design could never have reported: the code that would have raised the alarm sat downstream of whatever had gone wrong.
  • The first version of the new report called a finished study broken. Collection stops on purpose once it has gathered enough postings to answer the question, and the report inferred that a run with no new collection had failed. So it opened every message with a problem that was not one. Reporting a normal condition as a fault every week is how a status report teaches its reader to skim it, which would have undone the reason for sending one at all. It now states completion as a fact, and still reports a missing collection run when the target has not been met.

The search index was rewriting U.S. as US, so results did not match the page

The Insights page at authgnosis.com/insights/ searches 225 records across the site. One of them read Can you work in the US? while the page it linked to read Can you work in the U.S.? The cause was a normalisation step that was correct for matching and wrong for display, and finding it exposed that the test suite guarding the search was checking far less than it appeared to.

  • One function was doing two jobs, and only one of them wanted the text changed. A search tokenizer splits on punctuation, so U.S. arrives as two single letters and both are discarded as too short to index. The original fix removed the periods before indexing, which made the acronym searchable. That same function also produced the text results display, so every result rendered US where the source said U.S. Lower cased and read back in a sentence, US is the ordinary word us, which this search deliberately keeps rather than discarding because it carries meaning inside a question. The collapse now happens inside tokenization, where it affects matching and nothing else, and stored text keeps what the page actually says.
  • The claim that ranking did not move was tested rather than asserted. Changing how text is split into terms can quietly reorder every result. 361 queries drawn from the site’s own vocabulary were run against the previous index with the previous tokenizer, and against the new index with the new one. The top twenty results were identical in both their identifiers and their scores for every query, with none changed.
  • Ten ranking checks were passing, and four of the six things they named were not being tested. The suite reads as a guarantee that stemming, stop words, acronym handling, prefix matching and fuzzy matching all work. Disabling each in turn and rerunning showed otherwise: only the field weighting and one query fallback changed any result. Two checks had become true for reasons unrelated to what they claimed to cover. Five checks were added, each chosen so it fails when exactly one mechanism is switched off, so a failure now names the part that broke instead of pointing at search in general.

A signature defect that three mailboxes agreed was not there

A CRM email signature was rendering its logos centred instead of left aligned, and the usual way of checking said it was fine. What makes it worth writing up is not the fix, it is that the check itself was blind. The same message looks correct in Outlook whichever account it arrives through, so opening it in a second mailbox would have confirmed the wrong answer twice.

  • The defect was invisible in the one place it was being checked. The editor that composes these emails wraps every inserted image in a block that carries two separate instructions to centre it. Gmail, Apple Mail and mobile webmail all obey those instructions. Outlook renders with a different engine that ignores both, so it quietly left aligns and shows a clean result. An earlier review had raised the centring and been told it could be ignored, on the grounds that it was not showing up in Outlook. That reasoning used the one client blind to the fault as the judge of whether a fault existed.
  • Patching the stored record did not work, three times, and the record was not the problem. The signature is held in three separate fields. Each was corrected and verified, and two subsequent sends still arrived centred with no trace of the correction. In the same message, a content card inserted by a small script came through correctly aligned. That contrast was the whole diagnosis: inserting a signature makes the editor redraw the images and reapply its own default, discarding whatever was stored, while the script writes the entire body as one value and the editor accepts it unchanged.
  • So the fix had to move to the only write that survives. The card script already rebuilds the whole body each time it runs, so it now normalises alignment in the same pass. The trade is stated rather than hidden: it straightens every image in the body, not only the two logos, and it only runs when a card is inserted. Both are acceptable here and both are recorded, because an undocumented side effect becomes a defect the moment somebody wants a centred image.
  • One behaviour explained three separate symptoms, and a finding that was true elsewhere was false here. Paragraph spacing was collapsing, the logos were centred, and a gap above the card kept vanishing. All three came from the same normalising pass: it zeroes margins on paragraphs, collapses empty lines, and rewraps bare images. Earlier work had established that a plain paragraph keeps the mail client’s own spacing, which is correct on the path where the text is written directly into the record and wrong on the path that goes through the editor. Same markup, opposite result, because different software touches it.

Three CRM automations passed their tests without running the code that had just changed

Four sales process automations in Dynamics 365 were repaired in one day. What made the day worth writing up is not the repairs, it is that three of them reported success while the branch they added had never executed once. Each fault was found by asking which test actually runs the new code, rather than whether the test suite passes.

  • A branch that could not be reached by an empty value was being reached by one. Each automation reads a step field from the record that triggered it and matches it against a list of cases. When that field is empty the platform fails the whole evaluation before it attempts any match, and the default case does not catch it, because a default handles a value that matched nothing rather than the absence of a value. Two internal design documents had reasoned the opposite from the same definition. Both were wrong, and both are now corrected.
  • One of the four reported 200 runs and zero failures while carrying the identical defect. Its trigger only fires when a record moves into a closed state, and the records it watches are already closed when they arrive, so the faulty path was never entered. A clean failure count was evidence that the code had not run. It was not evidence that it worked, and reading it as such is how the same fault survived a fix applied to its sibling that morning.
  • One automation had been retired because its only working guard was accidental. It closed a process step whenever a note appeared whose subject contained a particular phrase and which carried an attachment. Nothing ever read the attachment. On the day it was examined, six unrelated notes on a single record matched the phrase, and the only reason the step did not close roughly 97 minutes early is that none of them happened to have a file attached. The trigger is now an explicit marker written by the process that completes the work.
  • The pattern behind all three was the same, and it is worth naming. Each change also updated the test harness in a way that stopped the harness reaching the new code. The sharpest case: a step that reopens a task when its evidence is missing had been failing on every attempt since it was written, because it set a status value this system does not define, and the same change that added it taught the harness to supply the evidence, so the harness always took the other path. Ask which test executes that specific branch, and be most suspicious when the test was edited alongside the code.

Every article on the site now has a path from the navigation

Search Console had 21 of 45 posts sitting in Discovered, currently not indexed. That status means Google knows a page exists and has chosen not to spend the time fetching it, which is usually a statement about how the site is put together rather than about the writing. The likely cause here was structural: there was no route to any article from the site navigation. Category archives could not serve as one, because they are deliberately set to noindex across the site. The new Insights page is the route, and it is now in the main menu.

  • An index page earns its place through crawl distribution, not rankings. This page was never meant to rank, and designing it to would be a mistake. Its job is to sit one click from every page on the site and hand a crawler 137 links to articles that previously had no navigational parent. Those links are in the page source before any script runs, so what the crawler receives does not depend on JavaScript or on which topic filter a reader happened to select.
  • Filtering had to be built so it cannot create pages of its own. The obvious way to build a topic filter puts the selection in the address as a query parameter, and that quietly manufactures a crawlable near duplicate of the page for every combination anyone clicks. On a site this size that competes with the very articles the page exists to promote. The filter state lives in the fragment instead, which no search engine treats as a separate address, and no entry is ever removed from the page when a filter is applied, only hidden.
  • There was already content on the site that could not be reached. Ninety five question and answer pairs were written across the articles, but the article template showed only the first five of them while the structured data published all of them. Answers were therefore visible to Google and invisible to readers. All 112 pairs that exist today are now searchable and each one links to its own answer on the article that carries it.
  • The measurement that matters has not happened yet. Shipping the page is not the same as clearing the backlog, and it would be easy to call this finished on the strength of the build alone. The test is whether that Discovered, currently not indexed count falls over the coming crawl cycles, and the reporting on it lags by around nine days, so it needs checking against live inspection rather than the summary. Until then this is a well founded change with its result still outstanding.

Site search now returns the section of a page, not just the page

The Insights page at authgnosis.com/insights/ is live. It searches 222 records across the whole site: the 28 published articles, the 112 question and answer pairs that sit inside them, the five main pages, the 48 entries in the AI project log, and 29 individual sections of those pages. That last group is the change worth explaining. A search for capital funding readiness now returns that specific service block and opens on it, rather than returning the home page and leaving the reader to scroll for the part they asked about.

  • A page is not one destination, it is several. The home page holds six service descriptions, a case study, and a set of frequently asked questions. Treating all of that as a single searchable record means the best a result can do is name the page, which puts the work of finding the actual answer back on the reader. Each addressable region is now its own record with its own heading and its own text, so it competes on what it says rather than on what the page around it says. The addresses were already there and already server rendered; what was missing was anything that indexed them.
  • The rule for what counts as a destination is written down and generated, not curated. A page carries far more element identifiers than it has places worth linking to, because the page builder stamps one on every row, column and grid. A hand kept list of the useful ones goes stale the first time someone adds a section and forgets, which is exactly the failure it exists to catch. A destination is now defined by test: it is not framework plumbing, it does not name a structural role, and it has a heading inside it. Running that test against the live pages found a case study added days earlier that the hand kept list had never recorded.
  • Adding the new records could not be allowed to move the existing results, so it was made structurally impossible rather than merely checked. The second group of records is scored in its own separate index and rendered in its own group beneath the main results, so it never competes with an article or an answer for position. The claim was then tested rather than asserted: the same thirty queries were run against the previous index and the new one, and the top twenty results were identical in both their order and their scores for every query.
  • The harder half was making the links actually land. A link to a region of a page looks like it should just work, and it did not. These pages load their images lazily, so the blocks above the target grow after the browser has already made its one jump, leaving the reader somewhere near the section rather than on it. Six of the destinations are collapsed panels that open on click, so a result promising a sentence of description arrived on a closed heading. Both are now handled on arrival: the scroll re-asserts itself until the position stops moving, and a targeted panel opens itself. An index that is correct and a link that does not land is still a broken feature.

Campaign responses now create leads behind a confirmation step

  • The CRM assigns a response code the moment a campaign reply arrives, and the routing automation only fired when that code was later changed by hand. A reply the platform coded correctly on arrival therefore never triggered anything and no lead was created. Nothing recorded that it had happened.
  • Create time routing now acts on a single code. A reply coded Interested creates a lead and a task asking for it to be reviewed. Every other code waits for a person to classify it, so an automated misread can never suppress a contact.
  • Reclassifying a response raises a confirmation task instead of acting immediately. Completing the task applies the change and cancelling it leaves everything as it stands. A response coded back to Interested reactivates the original lead rather than creating a second one.
  • Two saved views were built before go live rather than after, so the rate of leads created in error is countable from the first week instead of estimated later.

A measured answer to how often senior sales roles ask for AI skills

It is easy to find a number for how much employers want AI skills, and hard to find one that survives being asked how it was produced. Search job adverts for the word AI and a very large share of senior commercial roles appear to want it. That figure is close to meaningless, because most of what it counts is not a requirement at all. A new weekly job collects public postings, narrows them to director level and above in business to business technology sales and marketing, and then does the part that actually matters: it separates AI named as an expectation of the candidate from AI used to describe the employer, and from notices about the employer screening applications. The first wave has been published with its full methodology.

  • The headline is 33.3 percent, and the interval around it is stated rather than implied. Of 700 analyzed postings open in Canada and the United States, 33.3 percent require AI skills of the candidate, with a 95 percent confidence interval of 29.9 to 36.9. The interval is a Wilson score interval rather than the usual approximation, which matters at proportions near zero or one because the common method produces bounds that are impossible. Sample size does not change how confident the figure is, it changes how wide the band is, and both are reported so a reader can judge the precision instead of taking it on trust.
  • The same postings counted loosely give 74.3 percent, and the gap is the finding. A keyword search of the identical set reports 74.3 percent, because that share mentions AI somewhere in the advert. Only 40.6 percent mention it inside the requirements, and 33.3 percent ask anything of the candidate. Most of that gap turns out to be location rather than marketing: 33.7 points of it is AI language sitting in company descriptions, benefits and legal text, against 7.3 points lost to requirements that mention AI while asking nothing. A naive count therefore overstates demand by roughly a factor of two, and not for the reason most people would assume.
  • Every counted posting can be traced to a specific sentence. Each classification has to carry a quotation from the advert itself, and that quotation is checked automatically against the source text before the posting is counted. A classification whose quotation does not verify is discarded rather than downgraded, and the check runs twice, in the stage that produces it and again in the stage that publishes it, so that a result recorded before a check existed can never enter a published count. This is the difference between a number that can be spot checked and one that collapses when somebody tries.
  • The limitations are published with the figure, including the one that weakens it most. Although postings were collected from two boards, 87.6 percent of the analyzed set came from a single one, because postings from the other were rejected far more often by the test for a business to business technology employer. That is stated in the note rather than left for a reader to discover, along with the coverage that job boards cannot see at all, the fact that senior hiring often runs through search firms, and the plain point that an advert records what an employer says it wants, which is an imperfect proxy for what it screens on.

Marketing list members now show engagement and account fit

Judging whether a marketing list had been over mailed used to mean opening each member one at a time. It now reads off the list itself.

  • An Outlook template became a native CRM template. The recipient first name now resolves as a merge field, and the signature images were rehosted so they render for people reading outside Outlook.
  • The Members view carries engagement history. Last contact engagement, engagement type, and the date a member was last included in a campaign now read straight off the marketing list.
  • Account fit sits beside contact recency. ICP fit score joins in from the account record, using an outer join on purpose so that members with no parent account still appear instead of quietly dropping out of the list.
  • Sorting works where the data lives. Columns stored on the record sort and filter normally. The joined fit score displays but cannot sort, which is a platform limit rather than a configuration choice.

The monitoring now watches whether the website’s email actually arrives

The monitoring that watches the Authgnosis automations was running, and it was reporting healthy, and it was still missing something. It watched whether the scheduled jobs had run. The email the website sends when someone fills in the contact form is not a scheduled job, so it was never in the picture at all. Four checks have now been added to close that gap and three others like it, and one further gap has been written down as deliberately not covered rather than half covered.

  • The website’s email is now proven by outcome, not by asking it whether it is well. A form submission leaves two independent traces: a record in the CRM, created by one system, and a notification email, sent by a completely different one. The check reads both and pairs them up. A record with no matching notification means the email side is failing, which is exactly the case the earlier checks had no way to see, and it now surfaces within a day. That independence is the whole point and it is easy to lose by accident, because the CRM side also sends its own notification. Counting that one would let the system vouch for itself, so only the website’s own email is accepted as evidence.
  • A quiet week stays quiet. If nobody submitted the form, there is nothing to pair up and the check says nothing. That restraint is deliberate. The earlier generation of this monitoring asked whether a file had been touched recently, which answers a useful question for something that runs on a timetable and a meaningless one for something that only happens when a person acts. Inventing a signal where none should exist is how monitoring teaches people to ignore it.
  • New automations can no longer be born unwatched. The list of jobs being monitored was maintained by hand, and in August three jobs that were running were found to be missing from it, which is why a healthy summary kept printing while one of them was dead. The list was corrected then, but nothing prevented it drifting again. Now every running job is checked against the list automatically, so anything added in future is either covered or reported on the next run.
  • The records that authorise email to leave the domain are checked for drift. A handful of DNS entries decide whether mail sent as Authgnosis is accepted as genuine. If one is edited, expires or is overwritten, outbound mail starts failing silently and the first sign is a client who never replies. The expected values are now written down in a reviewable file and compared on every run. The check reports drift and deliberately cannot repair it: a wrong automated edit to those records would break every outbound message for hours, which is a far worse outcome than a report nobody has read yet.

Contact form duplicate detection now reads the request, not just the address

The website contact form creates a Lead in the CRM, and until now it decided whether a submission was a duplicate by comparing the email address as a plain string. That was wrong in two opposite directions at the same time, and both were live. A returning prospect asking about something new was filed as a repeat and never became a Lead, so genuinely new interest went into the record as a note instead of the pipeline. Meanwhile one person writing in from x@, x+something@ and a capitalised spelling of the same address became three separate Leads, because nothing tidied the address before comparing it. The fix addresses both, and it is now live.

  • Addresses are normalised before they are compared. The address is trimmed and lowercased, and a plus tag is stripped, so a person who uses tagged addresses is recognised as one person. Google accounts additionally ignore dots, so dots are removed for those and only those. That restriction matters more than it looks: for most providers a.b@ and ab@ are two different mailboxes, so applying the rule everywhere would have fixed duplicate records by silently merging two real people, which is a worse failure than the one being fixed.
  • A repeat only counts as a repeat if nothing new is being asked. The form asks what the enquiry is about, and those answers are now part of the decision. Ask about something never asked before and it creates a Lead, even from a familiar address. Ask about the same things again and it stays a note on the existing Lead, exactly as before. Asking nothing in particular is treated as its own kind of request rather than as a match for everything.
  • The comparison is bounded to six months. Someone returning after half a year is a new opportunity, not a duplicate of an old one.
  • Verified by submitting the real form, not by reading the change. Eleven submissions were put through the live form covering both outcomes, each confirmed by which record it actually produced. One of them exists purely as a control: it proves the six month filter really is excluding old records rather than quietly matching nothing, which would have looked identical from the outside and made every other test pass for the wrong reason. All test records were then deleted and their absence confirmed by re-reading the database.

Two reference diagrams rebuilt as interactive components

Two diagrams in the business growth guide were flat images. Readers could see the structure but not what any single element meant, because the explanation lived only in the surrounding prose.

  • Both diagrams are now interactive. Hovering or tapping any element opens a short plain language explanation, with the full layout on desktop and a stacked card view on phones.
  • Each runs as self contained HTML inside an auto resizing frame, so the page never shows an inner scrollbar and either diagram can be revised later without editing the article itself.
  • The desktop layouts were keyed to the browser width rather than the column they occupy, which would have shown most laptop readers the phone view. Both now switch on the width actually available to them.
  • A faint hover tint on both figures traced back to a site wide rule written for photographs, inherited through a shared wrapper class. Scoping the wrapper cleared both diagrams and left every other image on the site untouched.

Post FAQs now display in full, not just the first five

The FAQ block on each article was rendering only the first five questions. The limit sat in the query rather than the display: the template fetched five rows and stopped, so any answer past the fifth was never sent to the page.

  • 15 of 95 authored FAQ answers were unreachable, concentrated in six articles. The longest set held 11 questions and displayed 5.
  • Structured data was unaffected throughout, so search engines received every question while readers saw a truncated list.
  • The template now fetches every row, with the block held to roughly five questions in height and the remainder reachable by scrolling.
  • Each answer carries a stable anchor, so an individual question can be linked directly rather than only the article that contains it.

Two AI write paths into the website, down from three

The site now has two inbound AI write paths rather than three. A builder aware server was added for live Divi work, the older server it made redundant was removed, and the existing offline toolkit was retained because it occupies a different layer.

  • Added Respira, a builder aware server that gives an AI agent structured access to a live WordPress site. It reads and writes Divi 5 layouts directly rather than through generic content fields, snapshots before it edits, and duplicates a page before any large change. That last part matters more than the feature list: the failure mode with live site tooling is not a bad edit, it is a bad edit with nothing to roll back to.
  • Removed the previous server once Respira was verified to reach the site on its own. Inbound write paths went from three to two. Every one of them is a standing door into the live site, so the count is worth keeping down, and the verification was deliberately concrete: confirm the retired path is gone from the site’s published interface list, then confirm the new one still answers. Two checks, both observable, neither taken on trust.
  • Kept the existing Divi toolkit instead of treating the new server as a replacement, which was the tempting call and the wrong one. They sit at different layers. The toolkit is offline authoring knowledge: the Divi 5.3 to 5.6 changelog, selector specificity, the seven breakpoints, how caching plugins interfere. Respira is live execution, generic across twelve builders, carrying no version specific Divi knowledge at all. One knows what to write, the other can write it.
  • Where the two do overlap, on performance and accessibility checks, the generic analyzers are heuristics and say so in their own output: the performance result states plainly that it is not a real measurement. Reading it as one would repeat exactly the error described in the previous entry here, where a simulated figure had been driving real decisions for months. A tool that labels its own confidence is doing something useful. The remaining job is to actually read the label.

Made the sales-process decision points an interactive diagram

A published article about our sales process carried a static image of its decision points. That image is now an interactive diagram – and while replacing it, the article’s text and its FAQ were re-checked against how the system actually runs.

  • Replaced the static picture with an interactive diagram: nine lifecycle stages, every decision gate colour-coded by type, each with a plain-language explanation that appears on hover or tap. Nothing to read in advance – the detail is there when you point at it.
  • Made two distinctions visible that a flat image cannot. It marks the handful of gates that are genuinely hard – where a “no” sends the deal back a stage – and it flags the two stages that have no decisions at all, where the process simply acts on its own. That is the whole point of the view: it shows where human judgment is required and where it is not.
  • Re-checked the article’s wording against the process that is actually deployed and corrected where the two had drifted apart – most importantly the description of how the customer loop restarts, which the live system handles differently than the older text claimed.
  • Fixed the same drift in the article’s structured FAQ data – the version search engines read – so the public answer now matches the running process rather than contradicting it.
  • The diagram is one self-contained file. Updating it later updates every page that embeds it, with no change to the article itself.

Fixed a performance alarm that was measuring the wrong thing

A weekly report had been flagging the homepage as failing a core speed metric for months. Measuring it properly showed the page was fine – the alarm was.

  • The weekly site-health report graded the homepage as failing Google’s Largest Contentful Paint standard, week after week. Acting on that flag meant a plan to rebuild the hero image and strip out stylesheets – real work, aimed at a real-sounding number.
  • Measuring the live page directly told a different story. In a real browser the page finished painting in roughly four tenths of a second. The failing figure came from a simulation that models a slow phone on a slow network, and it swung between seven and sixteen seconds across runs – the kind of variance that is itself a clue you are looking at a model, not a measurement.
  • The image the plan would have optimised turned out to be the wrong target entirely: it was already compressed, already prioritised, and arrived in about two milliseconds. Roughly 86% of the simulated delay came from elsewhere. Fixing the image would have changed nothing.
  • The reporting now separates the two kinds of data it was quietly conflating. Real-user measurements decide the pass/fail grade; lab simulations are labelled as such and can no longer escalate into a recommended action. Where no real-user data exists yet – which is the case for a site still building traffic – the report says so plainly instead of showing a red cross.

A consent-first grant newsletter for BC businesses, built compliance-first

Authgnosis is building an opt-in email newsletter that keeps BC businesses current on government grant opportunities they could actually use. The foundation is now in place, engineered around consent and privacy from the start: people subscribe on purpose, confirm it themselves, can leave at any time, and every message says who it is from.

  • Double opt-in by design: someone asks to subscribe, then confirms from their own inbox before anything else happens – so a subscription is always something the person genuinely chose, and no one can sign someone else up.
  • Consent is stored as an audited record in the CRM – when someone confirmed and the exact wording they agreed to – so the newsletter can always show a clear, tamper-evident history, and unsubscribes are honored automatically and permanently.
  • The automation that sends the newsletter runs on least privilege: a dedicated sending identity scoped so it can only use its own newsletter mailbox and nothing else, and it writes subscriber records with the narrowest permissions needed – verified end to end.
  • Every issue carries only public grant information – program, funder, award range, deadline, and a link to the official page – with clear sender identification and a working unsubscribe in each message. Nothing about any specific business ever appears.

Completed the Docker migration for the Authgnosis automation (Phase 3)

The automation that quietly runs the business is now fully isolated, credential-safe, and reversible – the multi-phase move into Docker is complete.

  • Finished moving the automation off the Mac’s own environment: the code runs from versioned, labelled images, and its working data and credentials live in dedicated storage volumes rather than loose files on the machine.
  • Every action software can’t undo – outbound email, writes to the CRM – is now recorded in an append-only audit log, plus a duplicate-write guard so a re-run can’t post the same CRM record twice.
  • The containers now run as a restricted, non-privileged user, each with a written rollback path – re-run a prior image version, restore a data snapshot, or reverse the specific external change.
  • Every routine job was tested end-to-end through the new setup before trusting it – same schedules, same reports, stronger isolation.

Added category filters to the AI project activity log

  • Added filter buttons to the AI project activity log so visitors can narrow the feed to a single category – Documentor, Architecture, Automation, CRM, and more – with one click.
  • Introduced a new Architecture category for infrastructure and platform work – like the recent move to Docker – separating it from the day-to-day Automation entries.
  • The filters apply instantly with no page reload and stay pinned to the top while scrolling, and the buttons build themselves from whatever categories exist so the list stays current on its own.

Made the Docker automation reproducible and instantly recoverable (Phase 3)

Building on the earlier move into Docker, the automation that quietly runs the business now runs from versioned, labelled images with its working data kept in dedicated, snapshotted storage – so any run can be traced to an exact version, and the whole setup can be rolled back to a known-good point in seconds without losing data.

  • Froze the automation’s code into versioned, labelled container images – every scheduled run is now tied to an exact, reproducible version, and rolling back becomes as simple as re-running a previous label instead of un-picking changes by hand.
  • Moved the automation’s working memory – the week-over-week SEO history, the grant-notification subscriber list, and each job’s last-run markers – off the Mac and into dedicated storage volumes, so the data no longer depends on the machine’s own folders.
  • Added automatic daily snapshots of that data, kept as a rolling set of recent and weekly backups (held locally, never in the cloud), giving a clean recovery point if anything is ever lost or corrupted.
  • Rollback now has two independent levers – restore an earlier code version, or restore an earlier data snapshot – and, true to the earlier phases, the previous setup stays in place as a fallback so nothing is a one-way door.

Moved the Authgnosis automation jobs into Docker (Phase 1)

The scheduled automations that quietly run the business – the weekly SEO monitor, monthly site-health check, daily analytics email, and the federal-grant monitor and subscription poller – now run inside a reproducible, isolated Docker container instead of directly on the Mac. Same schedules, same reports, but a far more portable, consistent, and secure foundation – and the whole cutover was designed to be reversed instantly if anything misbehaved.

  • Packaged all five scheduled automation jobs into a single reproducible container image with a pinned Python version and locked dependencies, so they run identically anywhere and no longer depend on whatever happens to be installed on the machine. The Mac’s own scheduler still triggers them on the same cadence – only where the code runs changed.
  • Built for reversibility first: nothing was deleted. The original setup was left in place, dormant, as a one-command rollback, and each job was validated end-to-end and switched over one at a time rather than all at once.
  • Strengthened security in the process – credentials stay encrypted in the Mac’s Keychain and are handed to the container only at the moment a job runs, never written to disk in plain text; the sensitive credential files were locked down to owner-only; and a tempting shortcut that would have weakened that protection was deliberately avoided.
  • Ran every job against real data inside the container before committing to the switch. That discipline surfaced and fixed several issues that would otherwise have failed silently weeks later – a secret the container wasn’t yet handing over, and a couple of scripts that lived in an unexpected place.

New automation watches Canadian government grants for a fit

A new unattended job now scans Canadian government grant and funding programs, filters them against Authgnosis’s own eligibility, has Claude score and explain each fit, and emails a short ranked digest – so relevant opportunities surface on their own instead of being hunted down by hand.

  • Draws on official government sources – the open.canada.ca grants-and-contributions open data and Innovation Canada’s Business Benefits Finder program catalogue – so the program list is authoritative and refreshes itself, with a live lookup used where one is available and a stable open-data snapshot as the reliable fallback.
  • Runs fast, deterministic eligibility checks first – applicant type, funding instrument, and firm-size and age gates – so obvious non-fits are filtered out before any AI scoring, cheaply and explainably, and it records the reason a program was ruled out rather than dropping it silently.
  • Has Claude score each remaining program for direct fit and explain it in a sentence or two, blending fit, award size, effort, and deadline into a single priority so the shortlist is ranked by what is actually worth pursuing.
  • Emails a change-only alert when a watched program’s status moves, plus a weekly digest that ranks each program with a plain-English note and direct links to the program and its application page – built on the same shared, reusable automation core as the rest of the Authgnosis job fleet.

Fixed a hidden duplicate-ID issue across the site’s design system

Cleaned up a subtle but systemic issue in the Authgnosis site’s reusable design presets: a handful of shared styles had a fixed HTML id baked into them, which meant the same id was being stamped onto dozens of page modules at once – quietly undermining in-page links, targeted styling, and clean, valid markup. Fixed across the entire site in one safe, verified pass.

  • Audited every global design preset and found that several carried a hardcoded HTML id (plus a few images with a baked-in alt/title). Because those presets are reused everywhere, a single id was duplicated across roughly forty modules – many headings and rows all sharing the same identifier.
  • Duplicate IDs quietly break real things: anchor and jump links stop landing correctly, any styling or script targeting an id can hit the wrong element, and the page fails HTML validity and accessibility checks.
  • Hand-fixing it in the visual builder kept reverting – two editor sessions were overwriting each other’s changes to the shared preset store – so it was corrected with a single atomic write behind the scenes: strip the stray id/alt/title from every preset, keep the legitimate class names, and verify nothing else changed.
  • Built small, reusable audit-and-clean tools and kept a backup of the original, so this stays easy to re-check and maintain going forward.

Your SEO health now lives as a dashboard inside the CRM

The weekly SEO, AEO/GEO, and site-health metrics Authgnosis already tracks now flow automatically into Dynamics 365 as a live, on-brand dashboard – so the full trend of how the site is performing in search and in AI answers is one click away in the CRM, with no spreadsheets and no manual entry.

  • Created a purpose-built table in the CRM to hold a weekly snapshot of 16 key metrics – search impressions and clicks, average position, referring domains and backlinks, on-page quality score, Core Web Vitals, brand mentions in AI answers, and more – so each run adds one row and a real time series builds itself.
  • Wired the weekly SEO monitor to write its results straight into that table automatically, authenticating as a dedicated service account – the dashboard stays current on its own, with zero manual data entry.
  • Built a native model-driven dashboard, ‘SEO / AEO / GEO Health’, with eight on-brand charts (impressions, average position, referring domains, AI mentions, AI-answer citations, homepage load speed, on-page score, and data budget) and surfaced it right inside the day-to-day sales app.
  • Backfilled historical rows so the charts open with a real baseline and trend from day one, instead of an empty grid waiting to fill up.

Dynamics 365 CRM: contacts inherit their company’s website, and emails timestamp by send time

Two improvements to the Authgnosis CRM automation: new contacts now pick up their company’s website automatically, and outreach emails are now timestamped by when they were actually sent.

  • When a new contact is added under a company that already has a website on file, the contact now inherits that website automatically. Every existing contact was backfilled the same way in one pass, so the field is populated across the board rather than left blank.
  • The inheritance only ever fills a blank – it never overwrites a website that was entered by hand.
  • The ‘last contact’ engagement timestamp for emails now uses the true send time, rather than a less reliable field that could record midnight. The record now reflects when outreach actually happened, down to the minute.

Documentor: correcting a version family by hand

A round of Documentor refinements makes its version detection easier to steer. When the automatic ordering is right it stays out of your way – and when it can’t tell, you can now set the order yourself instead of being stuck.

  • When Documentor genuinely can’t tell what order a set of file versions came in – because nothing in the files themselves reveals it – you can now set the order by hand with simple up and down arrows. A hand-set order takes precedence over every automatic guess, so it’s the real fix for the files that structure alone can’t place.
  • A new toggle hides version families you’ve already finalized on disk, so a long review list stays focused on the ones still needing a decision.
  • Documentor now flags a file that has been both starred (keep) and excluded (leave out) at the same time – usually an oversight – with a gentle caution icon, instead of quietly letting the two settings contradict each other.
  • Folder search gained a precise option: match a single folder on its own, without also pulling in everything nested beneath it.

Dynamics 365 CRM: Last Contact Engagement tracking on Accounts

Every Account in the Authgnosis CRM now carries a live last-touch indicator: when anyone at that company was last emailed, called, or met, and how – updated automatically the moment it happens.

  • Added two fields to the Account table: Last Contact Engagement (date/time) and Last Contact Engagement Type (Email, Phone Call, or Meeting), shown read-only on the main Account form.
  • Shipped the Authgnosis publisher and solution first, so this and all future customizations carry a proper ag prefix instead of the platform default – portable, reviewable, and rollback-friendly.
  • Engineering detail: Dynamics rollup columns cannot see activity logged against a Contact from its parent Account (a one-hop limit Microsoft documents), so three small Power Automate flows stamp the Account whenever a qualifying email, call, or meeting completes.
  • Built, activated, and verified end-to-end with a live test run – a completed phone call stamped its account within about a minute, confirming the whole chain works in production.

Turning a sales-intelligence export into a clean CRM data model

  • Mapped every field from a sales-intelligence platform’s export into the matching CRM account and contact records
  • Caught the transforms that trip up imports – values stored in thousands, and picklists that must match the CRM’s own options
  • Corrected a mis-typed date field so a “year founded” value imports as a whole number instead of a full date
  • Locked the whole mapping into a single versioned reference so it stays authoritative across tools

Auto-versioning gets tougher after a round of real-world testing

Documentor’s auto-versioning has now been run against a real, messy corpus of client files – and every rough edge that turned up became a fix, from a genuine crash to a handful of review-screen refinements that make it faster to trust what’s being proposed.

  • Fixed a real crash: a rare document-history shape – two independent ancestors both converging on one later file – was being walked twice instead of recognized as unorderable, corrupting the numbering. Documentor now detects this shape up front and correctly flags it for manual review instead.
  • Documentor can now recognize an original file with no version number in its name, sitting among copies that do (v2, v3, and so on) – it correctly infers that file is the first version, exactly where structural clues alone leave gaps.
  • The review screen now shows a file’s modified date and size, tags exact-duplicate copies the same way the family view does, and adds a toggle to hide families with no established order – useful once a corpus has a lot of them.
  • Un-doing a false grouping is now a genuine toggle: previously the only way back was re-checking every file in the group one at a time, and a small string-matching gap meant “Report_Revised.docx” wasn’t recognized as a version marker the way “Report Revised.docx” was.

Documentor’s duplicate finder moves from a popup into its own mode

Finding and clearing out duplicate files used to mean opening a separate window on top of your file list. Now it’s a full mode of its own, switched to with one click, so reviewing duplicates feels like a normal part of working the list rather than a detour.

  • Added a toolbar switch between the regular file list and a dedicated Duplicates view, sharing the same project sidebar so you never lose your place moving between the two.
  • The Duplicates screen keeps everything it already did – re-scan, exclusion patterns, keep-pattern rules – now with more room to work and no popup window to manage.
  • If you’ve made changes in Duplicates mode and haven’t saved them, switching projects or modes now warns you first, so a half-finished cleanup can never be silently lost.
  • Under the hood, this is also the foundation for upcoming duplicate-handling rules – the mode switch had to exist before rules could be built on top of it.

Made the hero sections and client-logo band consistent across every page

A pass across the Authgnosis site’s top-level pages to fix two related issues – hero text overflowing onto the client-logo band on the AI Projects page, and client logos rendering at very uneven sizes – and to make the hero and logo band structurally consistent from page to page.

  • Fixed the AI Projects hero, where a long introduction overran its fixed-height band and ran over the logo band beneath it – the band now grows to fit its text while still filling the screen when the text is short.
  • Standardized the client-logo band so every logo displays at the same height on desktop, tablet, and mobile – previously wide logos were shrunk to a fraction of the others’ size – and applied the identical treatment to all five top-level pages.
  • Unified the underlying page structure so the hero and logo band use the same building blocks and naming on every page, making the whole set easier to maintain and keep consistent going forward.
  • Made the logo band sit correctly at the bottom of the first screen on every page, adapting to any window size, and re-checked each page after clearing all caching layers.

Making it real: Documentor now renames files to match their version

Documentor has been able to work out a family of documents’ order and propose a clean version number for a while now, but only within its own records – nothing on the actual file changed. That gap closes today: Documentor can now rename real files to match their assigned version, with a full undo available whenever it’s needed, plus smarter handling of documents that split into separately-edited copies and files that already carry their own version label.

  • Assigning a version number and renaming the real file are now two separate, deliberate steps – nothing changes on disk until you’ve reviewed and explicitly approved it, and a rename always covers every duplicate copy of a file, not just the one you’re looking at.
  • Every rename is recorded before it happens, so an interrupted batch – a crash, a permissions hiccup – can always be picked back up right where it left off, and a completed rename can be undone at any time, restoring the original filename with the same one-click safety.
  • When a document splits into two separately-edited copies, each branch now gets its own clean label showing where it diverged and how many edits it’s had since. If one branch is later declared the real one going forward, a single click collapses its whole history into the next version number, without disturbing the other branch’s numbering.
  • Documentor now recognizes files that already carry a deliberate version scheme of their own (v1.0, v2.0) and leaves them alone by default, while still cleaning up messier labels like “FINAL” or “Draft 2”. A safety fix also ensures that if a file is renamed a second time, undo only ever reaches back to the most recent rename – never an earlier one that’s already been superseded.

Dynamics 365 CRM: API integration + change-control repo

Claude can now manage the Authgnosis CRM directly through the Dataverse API, with every future change tracked, auditable, and reversible through a new change-control repo wired into the daily close-out workflow.

  • Stood up programmatic access to the Authgnosis CRM (Dynamics 365 Sales Professional). Claude now works the CRM through the Microsoft Dataverse API using a service principal instead of via Claude’s CoWork screen control.
  • Debugged a chain of integration obstacles along the way: a missing Microsoft first-party service principal, a Claude/Microsoft Entra OAuth incompatibility, and a broken official MCP proxy. Resolved with the community mcp-dataverse server (79 tools).
  • Established a change-control repo in GitHub to mirror change-control for other Authgnosis projects: backlog, per-change audit trail, before/after snapshots, and documented rollback paths.
  • Wired the repo into the daily close-out workflow, including this Activity Feed publisher hook.

PDFs join the order: reading a file’s own embedded history, not just Word’s

Word documents have long carried a revision history Documentor can read to work out their order. PDFs carry a different kind of history, embedded in the file itself, and Documentor now reads that too – so PDFs take their place in a version family’s sequence instead of sitting in the “order unknown” pile.

  • PDFs embed their own provenance: a record, inside the file, of which earlier draft a saved copy was created from. Documentor now reads that directly from the file’s own metadata, so a family of PDF revisions can be put in order the same way Word documents already are.
  • This signal takes priority over the order Documentor infers from content alone, since it comes from the file itself rather than a guess. When the two disagree – a document’s own history looks reverted relative to what its metadata claims – Documentor flags it for a look rather than picking one silently.
  • A new “Review order” indicator in the Version Families view surfaces exactly which files triggered that disagreement, alongside the existing order badges.
  • The “order unknown” pile shrinks: PDFs, which previously carried no ordering signal at all, can now be sequenced wherever this metadata is present – closing the last major gap in version ordering.