Tuesday, March 27, 2007

JBoss Rules 3.0.6 was released

JBoss Rules v3.0.6 was released. As always, you can download it from the project site http://labs.jboss.com/portal/jbossrules/downloads.

This is a maintenance release, with a few bug fixes. We strongly advise all people using JBoss Rules versions 3.0.x to upgrade to version 3.0.6, specially those using dynamic rules.

Our special thanks to Frederic Burlet and Einat Idan for providing patches and all the community users for using, testing and reporting bugs and suggestions.

Follows the list of fixed bugs.

Release Notes for JBoss Rules 3.0.6


[ JBRULES-442 ] Building from source failed: Serialisation / externalisation Error
[ JBRULES-592 ] Problem with WorkingMemory serialization
[ JBRULES-598 ] Core is not indexing beta memory for Strings and Dates
[ JBRULES-603 ] AbstractRuleBase.removeRule(String, String) does not release the lock when failing removing rule from the package
[ JBRULES-612 ] NPE on asserting facts before reading rules with retract
[ JBRULES-615 ] Declared imports should override the default java.lang.* imports
[ JBRULES-641 ] Support for primitive array throws an org.drools.rule.InvalidRulePackage exception


[ JBRULES-607 ] Working memory is not disposed when releasing the RuleSession

Sunday, March 18, 2007

Writing Rules for Monitoring and Time-Sensitive Applications

After talking more abstractly about writing (hopefully better) rules, I would like to go down a bit and talk about real rules engines use cases and some ideas on how to write rules in such cases.

I sent an e-mail to the users list asking for cases that users would like to discuss in more detail and some suggestions started to arrive. In this post I will talk about a subject that was suggested by Neil Goldman that was also kind enough to share his thoughts about how to model rules for Monitoring and Time-Sensitive Applications.

It is not the scope of this post to talk about Event Stream Processing, that besides being related to the subject, have different requirements and are too extensive to be included in this single post.

I will use JBoss Rules (a.k.a. Drools) for the examples, but the ideas should possibly be used with any other engine.

Monitoring Applications

Monitoring Applications are applications that monitor and eventually take actions based on inputs from sensors (temperature, weather, movement, etc) or agents (network elements, managed systems, managed beans, etc). They usually have requirements of working as Near-Real-Time Applications and are designed to react to system state changes.

Question is: how do I architect my application leveraging the advantages of the rules engines to monitoring applications?

Lets discuss the case using a simple practical example: let's say you have a monitoring application for your Air Conditioning System (ACS) that must control it to keep the temperature under a certain range.

One simple way of doing it using a Rules Engine is to work with a statefull working memory that reflects the state of the system and has rules that react to changes in this state. The state of the system, in the above example, is provided by the sensors, so it makes perfect sense to have your sensors modeled as facts. The rules will rely on these "sensor facts" to make decisions. So, your rules could be:

global org.drools.examples.acsmonitoring.AirConditioningSystem acs;

rule "turn ACS on"
TemperatureSensor( celsiusGrade > 25 )

rule "turn ACS off"
TemperatureSensor( celciusGrade < 20 )

The above are very simple rules, but they demonstrate the concept. A more elaborate rule could be able to work with different threasholds according to the weather input given by another sensor:

rule "turn ACS on"
WeatherSensor( $weather : weather )
TemperatureRange( weather == $weather, $max : maxTemperature )
TemperatureSensor( celciusGrade > $max )

Having your constraints also modeled as facts (the TemperatureRange fact in the above example) also helps writing more robust rules, avoids the need for hardcoded values, and allows a single rule to react to several different conditions.

Well, we saw the "rules side" of your problem, but what your application needs to do? The answer is: simply keeps updating the sensors. That may be done in several ways, depending on how your specific system works, but in the end, it will usually be either by poll or by event. If you are polling your ACS, code would be like:

while( /* an exit condition */ ) {

sensorReader.update( sensor );
wm.modify(sensorHandle, sensor );
// wait for the next polling slot


Monitoring applications may also work with stateless working memories, but a statefull working memory usually makes more sense for cases like described above.

Time-Sensitive Applications

Time-Sensitive Applications are applications that reason over or react to time. For example: billing applications, applications that run simulations, task schedulers, etc.

Rules in such applications will be directly or indirectly dependent on time. Here, it is important to not confuse the use of time as "data" to your rule and the use of time as "metadata" to your rule. Rules engines usually offer features to handle time as a metadata, like allowing one to specify a rule effective and expiration time, among other things.

What we are talking here is about reasoning over Time. And if we are reasoning over Time, it is clear that Time must be modeled as a fact. Quoting Neil Goldman:

" You do not want your rule conditions reading the operating system clock
as part of their match criteria, because you have very little control
over just when those criteria are evaluated. That clock is changing at a
fairly high frequency, and the rule engine is unaware of the sensitivity
of such criteria to these changes.
You want your rules to be sensitive to a pseudo-clock that
a) you can update in a controlled manner, and
b) the rule engine can be told about. "

Yes, you want a controlled clock to reason over. A good analogy is to think about the clock as a sensor from the previous examples. In the previous examples, the application controls when and how the sensor is updated as a way to keep the system state consistent. The same way the application can control when and how the rules pseudo-clock gets updated.

There are several advantages of this approach. We can list, among others:

  • system consistency: you can guarantee that no external, unpredicted or predicted event will cause inconsistencies in your facts (all sysadmins know the headaches of going back one hour in time when daylight savings period is over) and having controls inside your application to handle such situations is great.

  • test automation: if your rules are reasoning over a pseudo-clock, you can easily write test that advance the clock as needed to test specific scenarios, while in production, your pseudo clock may be synched with the real clock in predefined intervals.

  • ability to run simulations: so you have your Asset Management Application (considered the best of the breed) that has over 10000 rules to manage every single asset of your customer's portfolio and your multimillionaire customer comes to you and ask "What if...?". Any person used to work with simulation software knows that a basic requirement for one is a pseudo-clock. So, if your 10000 rules are written against a pseudo clock, adding simulation features to your application using the exact same 10000 rules is just a matter of manipulating the clock... on the other side, if your rules use a real clock, you either update your 10000 rules to support simulation or you manipulate the clock of your server... :)

It is important to note that, as mentioned above, there is no restriction to periodically synchronize your pseudo-clock with the system clock, as long as you have the control over when and how this update is done.

So, as promised, just to keep the post a bit more low level, a code example. Imagine you have a task scheduler application and you want to write rules that will run your tasks when the scheduled time arrives or when a previous required task is complete. Your rules could be like:

rule "Fire based on time"
PseudoClock( $currentTime : currentTime )
$t : Task( preReq == Task.PR_TIME, executedAlready == false, scheduledTime <= currentTime )

rule "Fire based on task"
$pr : Task( firedAlready == true )
$t : Task( preReq == Task.PR_TASK, executedAlready == false, preReqTask == $pr )

You probably noticed that the comparison between the scheduled time and the current time in the first rule above is made with a "<=" operator. This is needed because usually, there is no guarantee that your rule will be executed precisely at the given time (except when running in a real time platform), but "as soon as possible" after that time. So, it is a good practice to always constrain time using ranges or thresholds instead of absolute values.

Thank you to Neil for raising the topic. The above is just the tip of the iceberg, but I hope it is a start for deeper research for those interested.



Thursday, March 15, 2007

Writing better rules (Edson Tirelli)

A frequent question we got is "how do I write better rules?" or symptomatic variations of that like:

  • What am I doing wrong? I have so much procedural code in my rules...
  • How do I call a specific rule? (that comes from 2 types of people: those used to backward chaining and those used to procedural code)
  • How do I iterate over a collection?
  • How do I execute an action in the LHS?

All the above questions may expose some level of misunderstanding of declarative programming and/or lack of knowledge in forward chaining engines.
DISCLAIMER: This is not negative criticism. This is only an acknowledgement that we, "rules people", need to do more on the evangelization side. We need to make it easier for people to understand and learn the principles of declarative programming.

Having said that, we all know that writing rules is a creative job and there is no single way of doing it, in the same manner there is no single way of interpreting a song (unless it is a Mozart's composition). There is no right or wrong, but there are better and worst ways (even being a bit subjective).

So, I will try to give some tips on how to identify the symptoms that may indicate that something is not going well with your rules, and how to improve the rules making those symptoms disappear.

The Symptoms

1. Too much procedural code:
If your rules are requiring several functions to be created or your consequences are getting complex, it may be a sign that something is wrong. Rules are supposed to be a declarative description of a pattern you are looking for in your facts and the consequence is supposed to be a sequential list of actions to execute when that pattern is found.

2. Flow control structures in the consequence:
If your rules contains flow control structures in the consequence, like "if" or "switch", there is a high probability your rules are doing something in a really bad way. Loop structures like "for" and "while" may be required in some very rare cases, but they are often enough a sign of problems in the rules too.

3. Extensive use of eval():
Mark my words: "EVAL IS EVIL". Eval is a very flexible CE, but it is also a BIG problem too. To start with, your rules frequently become unreadable if you use it extensively. Also, since you can do almost anything inside an eval, the engine can not make any assumptions about it and so it is really difficult to provide any optimization. In JBoss Rules 3.0.x, there are some situations that require the use of eval(), but we worked a lot on improving expressiveness of the language and, in JBoss Rules 3.1.0-M1 and later, we reduced a lot the situations that require eval(). So, if you are using a lot of evals, you probably can do better.

How to improve the rules

1. Business Domain Model:
Probably the most important single item you need to worry about is how expressive is your Business Domain Model. A simple analogy is to compare it with a data model and an RDMS system: we all know that the performance, simplicity and efficiency of SQL queries are directly related to the quality of the data model. The same way, the performance, simplicity and efficiency of the rules is directly related to the quality of the business model. Different Rule Engines have different ways of representing your Business Model, but fundamentally, your Business Model will be an instantiation of the ontology of your business. In other words, you know what your business is, what the requirements to running it are and what you need from your information systems. So, formally describe that ontology using your rules engine "language".
JBoss Rules/Drools works natively with Java Object Oriented Models, but it also allows you to define higher level models using Decision Tables, Domain Specific Languages, or any other language you provide a driver for (see Mark's post about supporting CLIPS, for instance).

So, tips for you to create good models for applying rules:

  • prefer flat models over deeply nested ones. It is always easier to write rules for flat models.

  • ask yourself the questions your rules will ask and see if you can answer them through the use of your Business Model. If it is confuse, refactor your model and try again. Simple example: your rules will apply over orders, products, and the products in the orders (let's call them items). So, does your model allow you to know about orders? Does your model allow you to easily know about the items that compound your order? Does your model allow you to easily know the details of the products in each of the items of your order? As you can see, this is a very similar exercise we go through when designing data models.

  • write your business rules in your natural language (English, Portuguese or whatever). Identify all objects referenced in your rules. For each object identify all referenced attributes. For each attribute, identify all constraints applied over that attribute. Now check if your business domain model contains those objects (facts) with those attributes and if it is possible to apply the constraints over those attribute types. It may appear like we are doing Object Oriented analysis here, but it is not really the same; we are talking in a higher conceptual level, since, whatever the tool you use, it will need the same information, being it OO based, template based, or even a higher level DSL.
2. Know your tool:
It is obvious, but good to reinforce. Know the tool you are using and how to express knowledge using its "interface", be it a plain textual language, spreadsheets, web interfaces or whatever. Learning a tool takes time and investment, but it is worth it. You will write better and simpler rules using advanced features. A simple example: I often see people using eval() and functions to write constraints in JBoss Rules that would be much simpler, efficient and performant if written as simple pattern constraints. (remember: EVAL IS EVIL!)

3. Assert all your objects as facts:
Rule engines usually know how to handle a fairly heavy load of facts, so let the engine do its magic. If you want to reason over a nested set of objects, assert all of them (not only the top level ones) into the engine and make sure your business model models the relationship between them. After that, writing your rules will be easier and the engine will be able to optimize execution (when compared to using eval and other constructs to access deeply nested structures). Example: if you have an Order fact that contains a list of OrderItems, assert both Order and OrdemItems as facts (if you need to reason over OrderItems too, obviously).

All the above tips have exceptions, but for the general case, following the above tips will help you write better rules.


There are good books reference in the documentation page and I recommend those interested in learning more to read them. Writing good rules is usually very simple for those "initiated", but may not be so simple for those "initiating"... :) I guess it is like using a spreadsheet: once you know your way, it is an incredible powerful and flexible tool, but you may need a hand to start using it.

I will try to follow up this post with concrete examples of writing rules. Maybe it will be helpful for some of you.


Monday, March 12, 2007

RuleFlow (Kris Verlaenen)

A new feature has been added to the JBoss Rules code, allowing users to create a graphical flow chart that defines the order in which rule sets should be evaluated. This blog shows some examples on how to use ruleflow. Ruleflow will be available in the next milestone release, and really anxious users can already try it by building the latest version on svn.
JBoss Rules already provides some functionality to define the order in which rules should be executed, like salience, activation groups, etc. When dealing with (possibly a lot of) large rule sets, managing the order in which rules are evaluated might become complex. Ruleflow allows you to specify the order in which rule sets should be evaluated by using a flow chart. This allows you to define which rule sets should be evaluated in sequence or in parallel, to specify conditions under which rule sets should be evaluated, etc. Here are two examples of a ruleflow:

Figure 1: A ruleflow showing a simple sequence of two ruleflow-groups that makes sure that all rules responsible for validating orders are checked first before trying to process these orders.

Figure 2: A more advanced ruleflow showing parallelism, conditional evaluation of rule sets (e.g. the rule set responsible for processing orders should only be executed if no errors were found when checking the order) and looping.

The JBoss Rules IDE has also been extended to allow the creating of these ruleflows:
* A new editor for creating ruleflow files (*.rf), as shown in the next screenshot. Whenever you try to save such a ruleflow file, a corresponding model file (*.rfm) is created that contains the definition of the ruleflow. The ruleflow file (*.rf) contains the graphical information.
* A wizard for creating a new ruleflow file.

Ruleflow definitions can be added to a RuleBase almost the same way rules are added to one:

// create a package containing all the rules
final PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( new InputStreamReader(
getClass().getResourceAsStream( "rules.drl" ) ) );
final Package pkg = builder.getPackage();

// create a new process containing the ruleflow
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.addProcessFromFile(new InputStreamReader(
getClass().getResourceAsStream( "ruleflow.rfm" ) ) );

// add the package and the processes to the RuleBase
final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
ruleBase.addPackage( pkg );
ruleBase.addProcess( processBuilder.getProcesses()[0]);

// create a new working memory for this RuleBase
final WorkingMemory workingMemory = ruleBase.newWorkingMemory();

Ruleflows can then be started by

// add elements to the working memory here, then start
// the ruleflow to start executing the first ruleset

More details on how to use ruleflow will be added in the near future. We are however already interested in getting some feedback about the usefulness and useability of ruleflows, and possibly some extension you might find interesting.



Sunday, March 11, 2007

A standards based approach to natural language rules - SBVR (S Beaver) (Michael Neale)

SBVR is a OMG standard for natural language rules and vocabularies (nominally using English). We think SBVR (Semantics of Business Vocabulary and Business Rules) is an important and useful standard, which can be used for rules interchange in a "source" and human readable format (which RuleML? and RIF are not aiming to do).

From a users point of view, there are 2 main aspects to using SBVR (I am skipping the grander vision for SBVR, which goes beyond production rules, I believe, but for now, lets keep it simple, and relevant to us):

  • The SBVR vocabulary
  • The rules themselves - which are written according to the SBVR vocab.

SBVR comes under Model Driven Architecture (MDA), and is defined a "Computation Independent Model" (CIM) - what that means to you, is that SVBR is designed primarily for human consumption. However, it is defined in terms of formal logic, and detailed enough to generate models and rules for a specific platform. The next layer "lower down" to CIM in MDA is PIM (Platform Independent Model) - which is where things like RuleML come in. Lower again in MDA terms is the PSM (Platform Specific Model) - this is where rule engine specific languages kick in.

Anyway, enough of my flawed MDA tutorial (if you have followed along this far, well done !).

What brought SBVR to my attention is the work of Maurizio De Tommasi and Pierpaolo Cira, and their practical work on a SBVR plug in for eclipse called "sbeaver" - you can read more about sbeaver here.

We are working with These guys to have tooling and a SBVR framework to author rules, and manage vocabularies for JBoss Rules (narrowing SBVR down to production rules to start with). Although SBVR is a CIM (see above) - we think its possible as a format for capturing business rules, and actually generating executable rules directly (perhaps with some assumptions built in - for instance SBVR vocabularies are not strong on data type information that I am aware of).

The first steps are a proof of concept to generate DRL rules from SBVR.

I am also interestsed in the SBVR vocabulary definition "language" as a generic "business object model" for the rule engine to use (regardless of if SBVR is used) - still under investigation.

So, what can I do with SBVR?
A picture says a thousand words, so take a look at the vocabulary editor:
This is where you define concepts about the business model, and things like synonyms, all of which help SBVR understand sentences.

And the rules?
You can see content assistance is pretty critical - this is a structure language, but much more free form then templates allow, but still - smart content assistance like is being showed here is invaluable.

I look forward to working together on integrating this !



Tuesday, March 06, 2007

update - Drools adds Clips parser

Progress is going well with the Clips parser I now have the full LHS working, exception functions. That includes the 'and', 'or', 'not and exists conditional elements, with full nesting, including 'and' and 'or' inside the 'not' and 'exists'. Patterns work with literals, bound variables, predicates and return values. I'm now working on functions at which point we should be able to execute Clips rules inside the JBoss Rules engine. Probably the hardest part with functions is finding a sane way to deal with primitives in functions, especially built in Math functions. After that we'll look at mapping our 'accumulate', 'collect', 'forall' and 'from' implementations.

Monday, March 05, 2007

Drools adds Clips parser

We have often stated that the Drools rule engine is fully language independant, but to date it's only had two parsers - XML and DRL. For a bit of fun this weekend, hey I'm a willd type of guy, I went ahead and started on an experimental Clips grammar with ANTLR, although its still a long way from being finished. I hope It should eventually provide a migration path for Clips users as well as demonstrate how people can build their own grammars for the Drools rule engine using ANTLR, you don't have to use ANTLR, but its our parser of choice. Clients who use other vendor products and want to migrate, but worried about the investment in the authored rules, can now write parsers for those products targetting JBoss Rules; obviously there are other things to consider like feature parity and execution models. We also support "dumpers", via the visitor design patter, making round tripping possible - i.e. currently you can load an xml and dump drl, and vice versa, we will try and make the same possible with Clips.

So far it's parsing multiple rules with multiple patterns, it supports literal, bound variable, predicate and return value field constraints as well as & and | field constraint connectives. I don't yet have it working with functions, so I've just put text into the predicate and return value for now, for the purposes of testing. The next stage is to get nested Conditional Elements working including 'and', 'or', 'not' and 'exists'. The really adventerous can help make 'accumulate', 'collect' and 'from' available :)

Clips/Lisp is a fairly simple grammar so this is a great learning project for anyone that wants to learn ANTLR and how to write custom parsers for the Drools Rule Engine; so if you want to help out why not pop onto codehause IRC #drools, or subscribe to our developer mailing list, and we'll help you get started.

The Clips ANTLR grammar is here http://anonsvn.labs.jboss.com/labs/jbossrules/trunk/drools-compiler/src/main/resources/org/drools/clp/CLP.g

And for those interested here is the current unit test. This demonstrates the intermediate AST we use to build a language agnostic view of a grammar. This AST is "dumb" and we call it Descr, short for Description, this is because everything at this stage is held in a String format; little or not validation has been done, it's just a pure string based tree representing the rules, this is then pass to the PackageBuider which validates the descr tree and builds the resulting rule AST.
public void testRule() throws Exception {
RuleDescr rule = parse(
"(defrule xxx ?b <- (person (name \"yyy\"&?bf|~\"zzz\"|~=(ppp)&:(ooo)) )
?c <- (hobby (type ?bf2&~iii) (rating fivestar) )").rule();

assertEquals( "xxx", rule.getName() );

AndDescr lhs = rule.getLhs();
List lhsList = lhs.getDescrs();
assertEquals(2, lhsList.size());

// Parse the first column
ColumnDescr col = ( ColumnDescr ) lhsList.get( 0 );
assertEquals("?b", col.getIdentifier() );
assertEquals("person", col.getObjectType() );

List colList = col.getDescrs();
assertEquals(2, colList.size());
FieldConstraintDescr fieldConstraintDescr = ( FieldConstraintDescr ) colList.get( 0 );
List restrictionList = fieldConstraintDescr.getRestrictions();

assertEquals("name", fieldConstraintDescr.getFieldName() );
// @todo the 7th one has no constraint, as its a predicate, have to figure out how to handle this
assertEquals(8, restrictionList.size());

LiteralRestrictionDescr litDescr = ( LiteralRestrictionDescr ) restrictionList.get( 0 );
assertEquals("==", litDescr.getEvaluator() );
assertEquals("yyy", litDescr.getText() );

RestrictionConnectiveDescr connDescr = ( RestrictionConnectiveDescr ) restrictionList.get( 1 );
assertEquals(RestrictionConnectiveDescr.AND, connDescr.getConnective() );

VariableRestrictionDescr varDescr = ( VariableRestrictionDescr ) restrictionList.get( 2 );
assertEquals("==", varDescr.getEvaluator() );
assertEquals("?bf", varDescr.getIdentifier() );

connDescr = ( RestrictionConnectiveDescr ) restrictionList.get( 3 );
assertEquals(RestrictionConnectiveDescr.OR, connDescr.getConnective() );

litDescr = ( LiteralRestrictionDescr ) restrictionList.get( 4 );
assertEquals("!=", litDescr.getEvaluator() );
assertEquals("zzz", litDescr.getText() );

connDescr = ( RestrictionConnectiveDescr ) restrictionList.get( 5 );
assertEquals(RestrictionConnectiveDescr.OR, connDescr.getConnective() );

ReturnValueRestrictionDescr retDescr = ( ReturnValueRestrictionDescr ) restrictionList.get( 6 );
assertEquals("!=", retDescr.getEvaluator() );
assertEquals("ppp", retDescr.getText() );

PredicateDescr predicateDescr = ( PredicateDescr ) colList.get( 1 );
assertEquals( "ooo", predicateDescr.getText() );

// Parse the second column
col = ( ColumnDescr ) lhsList.get( 1 );
assertEquals("?c", col.getIdentifier() );
assertEquals("hobby", col.getObjectType() );

colList = col.getDescrs();
assertEquals(2, colList.size());
fieldConstraintDescr = ( FieldConstraintDescr ) colList.get( 0 );
restrictionList = fieldConstraintDescr.getRestrictions();

assertEquals("type", fieldConstraintDescr.getFieldName() );

varDescr = ( VariableRestrictionDescr ) restrictionList.get( 0 );
assertEquals("==", varDescr.getEvaluator() );
assertEquals("?bf2", varDescr.getIdentifier() );

connDescr = ( RestrictionConnectiveDescr ) restrictionList.get( 1 );
assertEquals(RestrictionConnectiveDescr.AND, connDescr.getConnective() );

litDescr = ( LiteralRestrictionDescr ) restrictionList.get( 2 );
assertEquals("!=", litDescr.getEvaluator() );
assertEquals("iii", litDescr.getText() );

fieldConstraintDescr = ( FieldConstraintDescr ) colList.get( 1 );
restrictionList = fieldConstraintDescr.getRestrictions();

assertEquals("rating", fieldConstraintDescr.getFieldName() );

litDescr = ( LiteralRestrictionDescr ) restrictionList.get( 0 );
assertEquals("==", litDescr.getEvaluator() );
assertEquals("fivestar", litDescr.getText() );


Thursday, March 01, 2007

BRMS Introduction - and progress update (Michael Neale)

Well, its been a while since any updates. In the mean time I have moved house, twice, once to Sydney (temporarily) and then back to my home in Queensland, so its been a disruptive period. I have been working out of the wonderful Red Hat Sydney office (North Sydney, photos later - amazing view !), as well as dropping into the Queensland office (no photos, not so scenic).

So, introducing the BRMS: The BRMS has (roughly) 3 aspects:
  1. BRMS Administrators,
  2. Users of all kinds, and
  3. Developers/architects.
These 3 aspects correspond to the 3 groups that will be using it, in many cases there is overlap (ie users could be developers, or users could be non technical, or a developer could be all three !). Keep this rough division in mind when reading through the rest of this introduction (not all the functionality applies to all the groups).

Of course, the pretty stuff you see is just the icing on the web cake, but there is plenty going on underneath, as has been covered before, so I won't bore you with it. Its important to note that the IDE (as shown previously by mark) forms a part of this (but I won't cover it here). This, coupled with recently described new features makes for a load of goodness.

The BRMS (starting from an empty state following a rough order in which things may happen):

Categories: As mentioned previously, generally you want to start with some categories created to help you find your rules. Categories are completely non technical, in the sense they can be called whatever you want, and do whatever you want, they have no bearing on how the rules work. This would normally be a BRMS Admin type of job.

Status Management: You can use status flags (any item can only have one status at a time, whereas it can have multiple categories) to manage, well, statuses (or statii???). This can effect deployment (if you want it to). The system starts with just a "Draft" status - any new changes are saved as draft status. You can add more to this list. Statuses are applied either on the individual "asset" level, or at a whole "package" level - if you do it at the package level it applies it to all the assets below it. This would normally be an Admin job.

Assets: I have mentioned "assets" - well the short version is that they are really just rules, or a decision table, or a chunk of rules, or a model, or a document - any thing that you want to treat as one controlled, versionable unit (an "atomic" unit if you like). This also includes other config and definition items needed for rules, and in future, things like processes and service definitions. We have a dream. This is a KEY POINT to keep in mind, if your mind is as warped as mine.

Packages: packages, in this sense, are a physical grouping of rules. This grouping is a bit like a folder, and would certainly make sense to developers and technical users. You can view the world through packages if you like, but as your rules and packages get more numerous, categories can be a more flexible and controlled way of finding rules

The package view of the world looks something like the following:
From here you can browse for rules, or you can view and edit the package configuration (all the top level stuff you need to make a ruleset work). This is a fairly technical view of the world.

Nice view: I thought I would share a nice picture of the desk I was at in the Sydney office, just to keep everyone interested:
(if you look carefully you will see the tip of the Sydney Opera House).

Browsing a package: Packages show a breakdown of broad asset types, according to their "format" (which is a Dublin Core attribute, for those who care).

(showing browsing a list of "business rules")

This little bar of "hieroglyphics" allow you to launch various wizards to create new things (packages, models, rules etc) from within the package view of the world. There are tool-tips to tell you what each one does.
There are also some other wizards which can help you out with configuring the package, should you need help !

Uploading stuff: Should you need some jar's for a model, then that respective "asset type" will allow you to upload stuff (uploading automatically creates a new version of something - so you can't accidentally overwrite it):

Browsing rules: When you use the rules "tab" - you can use the previously defined categories to navigate lists of rules.
Authoring rules: This is one of the fun parts. There are many many ways to author rules, some formats are ideal for the IDE, some are good for the web, lets take a look at a few key ones:

(shot of the modeller in action)
The rule modeller uses knowledge of the package to provide a "guided editor" for rules. This can be augmented with DSL configurations if needed. We haven't decided the final name for this. There is also an eclipse version in the works:

Phew, thats a lotta buttons. On the left hand side of the web view is all the boring "meta data" including lists of categories that the rule belongs to. The bottom right is the all important documentation.

Some people have asked how this is stored: well, as mentioned previously, it depends on the "asset" format itself - the repository is content agnostic in that regards (it can and does store anything, in any format). At the moment the modeller uses XML, but this will most likely be enhanced to be DRL itself, and RuleML (in the case of RuleML, many features will have to be disabled to produce RuleML compliant rules). In any case, you probably don't really care about that. So its time for another picture:

(even DSL rules are in on the action, complete with content assist, many people still like the personal tough you only get with plain text).

More wizards than Middle Earth: Creating a new "rule asset" is done through wizards (on the web anyway):

Before I go, I will show briefly the "snapshot" and deployment features. You can, at any time, take a "snapshot" of a package, and all its "assets" - which can be used for deployment. This snapshot is frozen (read only normally), and lives in a separate "area" to allow you to make concurrent changes to the rules themselves. There can be as many snapshots as you like, and they are "labelled" according to some meaning you give them. You can copy snapshots, delete, or simply update them with the latest. Some screen shots may help:

(shows creating a snapshot of a package - either replace existing, or create a new label)

(this shows a list of snapshots, from the "deployment" tab) of course this is an Admin feature !

(this shows a frozen view of a package, exactly as you took it, back in the good olde days).

History/versions: Every change you make to an "asset" is versioned - you can at any time view the history, and with one click restore any item (and you can undo that restore of course) - I tried to make it as intuitive as possible :

And finally, I will leave with a photo of the Really Cool foyer of the Sydney office:

OK, that's it, that should be sufficient for now.

Enjoy !

PS this is of course available in SVN, we always develop out in the open: drools-repository and drools-jbrms are the models for anyone crazy enough.